diff --git a/README.md b/README.md index c09416d..f0e28b2 100755 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In future releases, the plugin will be named "Video Streaming Plugin" instead of - The encoder creates a Master Playlist File with the URLs of each Media Playlist. To play, the client first downloads the Master Playlist, and then the Media Playlists. Then, they play each Media Segment declared within the chosen Media Playlist. The client can reload the Playlist to discover any added segments. This is needed in cases of live events, for example. -Notice that the recognition of the HLS protocol is based on the requirement of the URL extension of the Master playlist link, which must have ".m3u8" on it, as specified on the [ISO regulation](https://tools.ietf.org/html/rfc8216#section-4). +Notice that the automatic recognition of the HLS protocol is based on the requirement of the URL extension of the Master playlist link, which must have ".m3u8" on it, as specified on the [ISO regulation](https://tools.ietf.org/html/rfc8216#section-4). #### In a Dynamic Adaptive Streaming over HTTP Live Streaming process: @@ -61,6 +61,12 @@ Set the link to the master playlist file ![](docs/video-url.png) +#### Protocol + +Set the protocol you want to test or let the plugin to automatically detect it. + +![](docs/protocol.png) + #### Duration Set the playback time to either the whole video, or a certain amount of seconds. diff --git a/docs/audio-and-subtitles.png b/docs/audio-and-subtitles.png index ff56965..062759e 100644 Binary files a/docs/audio-and-subtitles.png and b/docs/audio-and-subtitles.png differ diff --git a/docs/bandwidth.png b/docs/bandwidth.png index 1131bfe..50ee337 100644 Binary files a/docs/bandwidth.png and b/docs/bandwidth.png differ diff --git a/docs/duration.png b/docs/duration.png index 4d0310a..1d0e1d7 100644 Binary files a/docs/duration.png and b/docs/duration.png differ diff --git a/docs/protocol.png b/docs/protocol.png new file mode 100644 index 0000000..409e7d8 Binary files /dev/null and b/docs/protocol.png differ diff --git a/docs/resolution.png b/docs/resolution.png index ed08fe1..7aa0d58 100644 Binary files a/docs/resolution.png and b/docs/resolution.png differ diff --git a/docs/resume-video.png b/docs/resume-video.png index 3b14ef9..c868ba9 100644 Binary files a/docs/resume-video.png and b/docs/resume-video.png differ diff --git a/docs/sampler.png b/docs/sampler.png index 1288c0a..809d4b5 100644 Binary files a/docs/sampler.png and b/docs/sampler.png differ diff --git a/docs/video-url.png b/docs/video-url.png index f0a2bf5..8c13992 100644 Binary files a/docs/video-url.png and b/docs/video-url.png differ diff --git a/pom.xml b/pom.xml index 7f3c3a0..12d20bc 100755 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.blazemeter.jmeter jmeter-bzm-hls - 3.0.3 + 3.1 Video Streaming Sampler as JMeter plugin diff --git a/src/main/java/com/blazemeter/jmeter/hls/gui/HlsSamplerGui.java b/src/main/java/com/blazemeter/jmeter/hls/gui/HlsSamplerGui.java index 5cb6509..9baaea3 100755 --- a/src/main/java/com/blazemeter/jmeter/hls/gui/HlsSamplerGui.java +++ b/src/main/java/com/blazemeter/jmeter/hls/gui/HlsSamplerGui.java @@ -3,6 +3,7 @@ import com.blazemeter.jmeter.hls.logic.BandwidthSelector; import com.blazemeter.jmeter.hls.logic.HlsSampler; import com.blazemeter.jmeter.hls.logic.ResolutionSelector; +import com.blazemeter.jmeter.videostreaming.core.Protocol; import com.google.common.annotations.VisibleForTesting; import java.awt.BorderLayout; import org.apache.jmeter.samplers.gui.AbstractSamplerGui; @@ -54,6 +55,7 @@ public void configure(TestElement el) { hlsSamplerPanel.setBandwidthSelector(sampler.getBandwidthSelector()); hlsSamplerPanel.setResolutionSelector(sampler.getResolutionSelector()); hlsSamplerPanel.setResumeStatus(sampler.getResumeVideoStatus()); + hlsSamplerPanel.setProtocolSelector(sampler.getProtocolSelector()); } @Override @@ -69,6 +71,7 @@ public void modifyTestElement(TestElement s) { sampler.setBandwidthSelector(hlsSamplerPanel.getBandwidthSelector()); sampler.setResolutionSelector(hlsSamplerPanel.getResolutionSelector()); sampler.setResumeVideoStatus(hlsSamplerPanel.getResumeVideoStatus()); + sampler.setProtocolSelector(hlsSamplerPanel.getProtocolSelector()); } } @@ -83,6 +86,7 @@ public void clearGui() { hlsSamplerPanel.setBandwidthSelector(BandwidthSelector.MIN); hlsSamplerPanel.setResolutionSelector(ResolutionSelector.MIN); hlsSamplerPanel.setResumeStatus(false); + hlsSamplerPanel.setProtocolSelector(Protocol.AUTOMATIC); } } diff --git a/src/main/java/com/blazemeter/jmeter/hls/gui/HlsSamplerPanel.java b/src/main/java/com/blazemeter/jmeter/hls/gui/HlsSamplerPanel.java index 8fcba44..dc200ea 100755 --- a/src/main/java/com/blazemeter/jmeter/hls/gui/HlsSamplerPanel.java +++ b/src/main/java/com/blazemeter/jmeter/hls/gui/HlsSamplerPanel.java @@ -2,6 +2,7 @@ import com.blazemeter.jmeter.hls.logic.BandwidthSelector; import com.blazemeter.jmeter.hls.logic.ResolutionSelector; +import com.blazemeter.jmeter.videostreaming.core.Protocol; import java.awt.event.ItemEvent; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; @@ -31,8 +32,12 @@ public class HlsSamplerPanel extends JPanel { private JRadioButton customResolutionOption; private JTextField customResolutionField; - private JRadioButton maxResolutionOption; private JRadioButton minResolutionOption; + private JRadioButton maxResolutionOption; + + private JRadioButton hlsProtocolOption; + private JRadioButton mpegDashProtocolOption; + private JRadioButton automaticProtocolOption; private JCheckBox resumeDownloadOption; @@ -47,6 +52,7 @@ private void initComponents() { JPanel bandwidthPanel = buildBandwidthPanel(); JPanel resolutionPanel = buildResolutionPanel(); JPanel resumeDownloadPanel = buildResumeDownloadPanel(); + JPanel protocolSelectionPanel = buildProtocolSelectionPanel(); BlazeMeterLabsLogo blazeMeterLabsLogo = new BlazeMeterLabsLogo(); GroupLayout layout = new GroupLayout(this); @@ -54,7 +60,10 @@ private void initComponents() { layout.setAutoCreateGaps(true); setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup() - .addComponent(urlPanel) + .addComponent(urlPanel, GroupLayout.PREFERRED_SIZE, + GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + .addComponent(protocolSelectionPanel, GroupLayout.PREFERRED_SIZE, + GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(durationPanel) .addComponent(trackPanel)) @@ -68,6 +77,8 @@ private void initComponents() { layout.setVerticalGroup(layout.createSequentialGroup() .addComponent(urlPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(protocolSelectionPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, + GroupLayout.PREFERRED_SIZE) .addGroup(layout.createParallelGroup() .addComponent(durationPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) @@ -88,7 +99,7 @@ private JPanel buildUrlPanel() { panel.setBorder(BorderFactory.createTitledBorder("Video")); JLabel urlLabel = new JLabel("URL"); - masterUrlField = namedComponent("masterUrlField", new JTextField()); + masterUrlField = namedComponent("masterUrlField", new JTextField(80)); GroupLayout layout = new GroupLayout(panel); layout.setAutoCreateContainerGaps(true); @@ -295,6 +306,36 @@ private JPanel buildResumeDownloadPanel() { return panel; } + private JPanel buildProtocolSelectionPanel() { + JPanel panel = new JPanel(); + panel.setBorder(BorderFactory.createTitledBorder("Protocol")); + + automaticProtocolOption = namedComponent("automaticProtocolOption", + new JRadioButton(Protocol.AUTOMATIC.toString())); + hlsProtocolOption = namedComponent("hlsProtocolOption", + new JRadioButton(Protocol.HLS.toString())); + mpegDashProtocolOption = namedComponent("mpegDashProtocolOption", + new JRadioButton(Protocol.MPEG_DASH.toString())); + + ButtonGroup protocolRadiosGroup = new ButtonGroup(); + protocolRadiosGroup.add(automaticProtocolOption); + protocolRadiosGroup.add(hlsProtocolOption); + protocolRadiosGroup.add(mpegDashProtocolOption); + + GroupLayout layout = new GroupLayout(panel); + layout.setAutoCreateContainerGaps(true); + panel.setLayout(layout); + layout.setHorizontalGroup(layout.createSequentialGroup() + .addComponent(automaticProtocolOption) + .addComponent(hlsProtocolOption) + .addComponent(mpegDashProtocolOption)); + layout.setVerticalGroup(layout.createParallelGroup() + .addComponent(automaticProtocolOption) + .addComponent(hlsProtocolOption) + .addComponent(mpegDashProtocolOption)); + return panel; + } + public void setMasterUrl(String masterUrl) { masterUrlField.setText(masterUrl); } @@ -377,6 +418,26 @@ public void setResolutionSelector(ResolutionSelector option) { } } + public Protocol getProtocolSelector() { + if (mpegDashProtocolOption.isSelected()) { + return Protocol.MPEG_DASH; + } else if (hlsProtocolOption.isSelected()) { + return Protocol.HLS; + } else { + return Protocol.AUTOMATIC; + } + } + + public void setProtocolSelector(Protocol option) { + if (option == Protocol.AUTOMATIC) { + automaticProtocolOption.setSelected(true); + } else if (option == Protocol.HLS) { + hlsProtocolOption.setSelected(true); + } else { + mpegDashProtocolOption.setSelected(true); + } + } + public boolean getResumeVideoStatus() { return resumeDownloadOption.isSelected(); } diff --git a/src/main/java/com/blazemeter/jmeter/hls/logic/HlsSampler.java b/src/main/java/com/blazemeter/jmeter/hls/logic/HlsSampler.java index 2fd7f43..a189ae0 100755 --- a/src/main/java/com/blazemeter/jmeter/hls/logic/HlsSampler.java +++ b/src/main/java/com/blazemeter/jmeter/hls/logic/HlsSampler.java @@ -1,5 +1,6 @@ package com.blazemeter.jmeter.hls.logic; +import com.blazemeter.jmeter.videostreaming.core.Protocol; import com.blazemeter.jmeter.videostreaming.core.SampleResultProcessor; import com.blazemeter.jmeter.videostreaming.core.TimeMachine; import com.blazemeter.jmeter.videostreaming.core.VideoStreamingHttpClient; @@ -40,6 +41,7 @@ public class HlsSampler extends HTTPSamplerBase implements Interruptible { private static final String BANDWIDTH_TYPE_PROPERTY_NAME = "HLS.BANDWIDTH_TYPE"; private static final String RESOLUTION_TYPE_PROPERTY_NAME = "HLS.RESOLUTION_TYPE"; private static final String RESUME_DOWNLOAD_PROPERTY_NAME = "HLS.RESUME_DOWNLOAD"; + private static final String PROTOCOL_PROPERTY_NAME = "VIDEO_STREAMING.PROTOCOL"; private static final String HEADER_MANAGER = "HLSRequest.header_manager"; private static final String COOKIE_MANAGER = "HLSRequest.cookie_manager"; @@ -151,6 +153,14 @@ public void setResolutionSelector(ResolutionSelector selector) { setProperty(CUSTOM_RESOLUTION_PROPERTY_NAME, selector.getCustomResolution()); } + public Protocol getProtocolSelector() { + return Protocol.valueOf(getPropertyAsString(PROTOCOL_PROPERTY_NAME, Protocol.AUTOMATIC.name())); + } + + public void setProtocolSelector(Protocol selector) { + setProperty(PROTOCOL_PROPERTY_NAME, selector.name()); + } + public boolean getResumeVideoStatus() { return this.getPropertyAsBoolean(RESUME_DOWNLOAD_PROPERTY_NAME); } @@ -189,8 +199,12 @@ public SampleResult sample() { String url = getMasterUrl(); if (!url.equals(lastMasterUrl)) { - sampler = factory - .getVideoStreamingSampler(url, this, httpClient, timeMachine, sampleResultProcessor); + try { + sampler = factory + .getVideoStreamingSampler(url, this, httpClient, timeMachine, sampleResultProcessor); + } catch (IllegalArgumentException e) { + LOG.error("Error initializing the sampler", e); + } } else if (!this.getResumeVideoStatus()) { sampler.resetVideoStatus(); } diff --git a/src/main/java/com/blazemeter/jmeter/hls/logic/VideoStreamingSamplerFactory.java b/src/main/java/com/blazemeter/jmeter/hls/logic/VideoStreamingSamplerFactory.java index 846f136..217bce3 100644 --- a/src/main/java/com/blazemeter/jmeter/hls/logic/VideoStreamingSamplerFactory.java +++ b/src/main/java/com/blazemeter/jmeter/hls/logic/VideoStreamingSamplerFactory.java @@ -9,13 +9,20 @@ public class VideoStreamingSamplerFactory { public VideoStreamingSampler getVideoStreamingSampler(String url, HlsSampler baseSampler, - VideoStreamingHttpClient httpClient, - TimeMachine timeMachine, SampleResultProcessor sampleResultProcessor) { - //HLS Master Playlist must contain this .m3u8 extension in their URLs - if (url.contains(".m3u8")) { - return createHlsSampler(baseSampler, httpClient, timeMachine, sampleResultProcessor); - } else { - return createDashSampler(baseSampler, httpClient, timeMachine, sampleResultProcessor); + VideoStreamingHttpClient httpClient, TimeMachine timeMachine, + SampleResultProcessor sampleResultProcessor) throws IllegalArgumentException { + switch (baseSampler.getProtocolSelector()) { + case HLS: + return createHlsSampler(baseSampler, httpClient, timeMachine, sampleResultProcessor); + case MPEG_DASH: + return createDashSampler(baseSampler, httpClient, timeMachine, sampleResultProcessor); + default: + //HLS Master Playlist must contain this .m3u8 extension in their URLs + if (url.contains(".m3u8")) { + return createHlsSampler(baseSampler, httpClient, timeMachine, sampleResultProcessor); + } else { + return createDashSampler(baseSampler, httpClient, timeMachine, sampleResultProcessor); + } } } diff --git a/src/main/java/com/blazemeter/jmeter/videostreaming/core/Protocol.java b/src/main/java/com/blazemeter/jmeter/videostreaming/core/Protocol.java new file mode 100644 index 0000000..16b2ea1 --- /dev/null +++ b/src/main/java/com/blazemeter/jmeter/videostreaming/core/Protocol.java @@ -0,0 +1,19 @@ +package com.blazemeter.jmeter.videostreaming.core; + +public enum Protocol { + AUTOMATIC("Automatic"), + HLS("HLS"), + MPEG_DASH("MPEG-DASH"); + + private final String name; + + Protocol(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + +} diff --git a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/DashMediaSegment.java b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/DashMediaSegment.java index aae13c3..9d18c4b 100644 --- a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/DashMediaSegment.java +++ b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/DashMediaSegment.java @@ -9,12 +9,14 @@ public class DashMediaSegment extends MediaSegment { private final Duration startTime; private final MediaPeriod period; + private final Duration presentationTimeOffset; public DashMediaSegment(MediaPeriod period, long sequenceNumber, URI uri, Duration duration, - Duration startTime) { + Duration startTime, Duration presentationTimeOffset) { super(sequenceNumber, uri, duration); this.startTime = startTime; this.period = period; + this.presentationTimeOffset = presentationTimeOffset; } public MediaPeriod getPeriod() { @@ -26,7 +28,10 @@ public Duration getEndTime() { } public Instant getStartAvailabilityTime() { - return period.getAvailabilityStartTime().plus(getEndTime()); + return period.getAvailabilityStartTime().plus(getEndTime()).minus(presentationTimeOffset); } + public Duration getDuration() { + return duration; + } } diff --git a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/DashSampler.java b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/DashSampler.java index ef45f44..5fdc13b 100644 --- a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/DashSampler.java +++ b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/DashSampler.java @@ -184,10 +184,12 @@ private void downloadNextSegment() throws InterruptedException { } private void awaitSegmentAvailable(DashMediaSegment segment) throws InterruptedException { - Instant availabilityTime = segment.getStartAvailabilityTime(); - Instant now = timeMachine.now(); - if (availabilityTime.isAfter(now)) { - timeMachine.awaitMillis(Duration.between(availabilityTime, now).toMillis()); + Instant availabilityTime = + segment.getStartAvailabilityTime().plus(segment.getDuration()); + //The clocks have to be synchronized to avoid error on segments availability + Instant nowSynchronized = timeMachine.now().plus(manifest.getClocksDiff()); + if (availabilityTime.isAfter(nowSynchronized)) { + timeMachine.awaitMillis(Duration.between(nowSynchronized, availabilityTime).toMillis()); } } diff --git a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/Manifest.java b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/Manifest.java index 7c8cd6d..ad7f981 100644 --- a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/Manifest.java +++ b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/Manifest.java @@ -95,6 +95,11 @@ public Duration getBufferStartTime() { .minus(bufferTime); } + public Duration getClocksDiff() { + OffsetDateTime publishTime = mpd.getPublishTime(); + return publishTime != null ? Duration.between(downloadTime, publishTime) : Duration.ZERO; + } + public Instant getAvailabilityStartTime() { OffsetDateTime time = mpd.getAvailabilityStartTime(); return time != null ? time.toInstant() : Instant.MIN; diff --git a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/segmentbuilders/MultiSegmentBuilder.java b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/segmentbuilders/MultiSegmentBuilder.java index 6bf3ecf..e609ef8 100644 --- a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/segmentbuilders/MultiSegmentBuilder.java +++ b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/segmentbuilders/MultiSegmentBuilder.java @@ -3,6 +3,8 @@ import com.blazemeter.jmeter.videostreaming.dash.DashMediaSegment; import com.blazemeter.jmeter.videostreaming.dash.MediaRepresentation; import io.lindstrom.mpd.data.Segment; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.net.URI; import java.time.Duration; import java.util.Iterator; @@ -49,12 +51,11 @@ public void advanceUntil(DashMediaSegment lastSegment) { if (lastSegment == null) { if (manifest.isDynamic()) { Duration reproductionStart = manifest.getBufferStartTime() - .minus(period.getStartTime()) - .plus(scaledTimeToDuration(startTime)); + .minus(period.getStartTime()); advanceUntilTime(reproductionStart, true); } } else if (lastSegment.getPeriod().equals(period)) { - advanceUntilTime(lastSegment.getEndTime(), false); + advanceUntilTime(lastSegment.getEndTime().minus(scaledTimeToDuration(startTime)), false); } } @@ -70,8 +71,11 @@ private long getStartNumber() { protected abstract Supplier getSegmentDurationSupplier(); private Duration scaledTimeToDuration(long scaledTime) { - double seconds = (double) scaledTime / getTimescale(); - return Duration.ofMillis((long) (seconds * 1000)); + //BigDecimal is used to avoid losing precision which is necessary to avoid miscalculating + //segment numbers or time stamps + return Duration.ofMillis(BigDecimal.valueOf(scaledTime) + .divide(BigDecimal.valueOf(getTimescale()), 10, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(1000)).longValue()); } private long getTimescale() { @@ -88,22 +92,21 @@ protected int getSegmentIndex(long segmentNumber) { private void advanceUntilTime(Duration time, boolean init) { Long segmentDuration = getSegmentDurationSupplier().get(); if (segmentDuration != null) { - double incrDec = (double) time.toMillis() / scaledTimeToDuration(segmentDuration).toMillis(); - // we round times due to double precision issues - long incr = init ? (long) incrDec : Math.round(incrDec); + //BigDecimal is used to avoid losing precision which is necessary to avoid miscalculating + //segment numbers or time stamps + long incr = BigDecimal.valueOf(time.toMillis()) + .divide(BigDecimal.valueOf(segmentDuration).multiply(BigDecimal.valueOf(1000)), 10, + RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(getTimescale())).longValue(); segmentNumber += incr; startTime += incr * segmentDuration; } else { while (hasNext() && scaledTimeToDuration(startTime + timelineSegment.duration).compareTo(time) <= 0) { - /* - instead converting scaling time to seconds (dividing by 1000), we scale it to millis - to and work with millis which requires smaller doubles to operate and less precision - issues - */ - long repetitionsUntilTime = - Math.round((double) (time.toMillis() * getTimescale() - startTime * 1000) / ( - timelineSegment.duration * 1000)); + long repetitionsUntilTime = BigDecimal + .valueOf(time.toMillis() * getTimescale() - startTime) + .divide(BigDecimal.valueOf(timelineSegment.duration), 10, RoundingMode.HALF_UP) + .longValue(); long pendingRepetitions = timelineSegment.repetitions - timelineSegmentRepetitions + 1; long repetitions = Math.min(pendingRepetitions, repetitionsUntilTime); segmentNumber += repetitions; @@ -163,7 +166,7 @@ private boolean hasNextSegmentInTimeline() { public DashMediaSegment next() { DashMediaSegment ret = new DashMediaSegment(period, segmentNumber, getUrlSolver(segmentNumber).apply(startTime), scaledTimeToDuration(getDuration()), - scaledTimeToDuration(startTime)); + scaledTimeToDuration(startTime), scaledTimeToDuration(getPresentationTimeOffset())); moveToNextSegment(); return ret; } diff --git a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/segmentbuilders/SegmentBaseBuilder.java b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/segmentbuilders/SegmentBaseBuilder.java index d7bbffa..12fc009 100644 --- a/src/main/java/com/blazemeter/jmeter/videostreaming/dash/segmentbuilders/SegmentBaseBuilder.java +++ b/src/main/java/com/blazemeter/jmeter/videostreaming/dash/segmentbuilders/SegmentBaseBuilder.java @@ -74,7 +74,8 @@ public void advanceUntil(DashMediaSegment lastSegment) { @Override public DashMediaSegment next() { generated = true; - return new DashMediaSegment(period, 1, segmentUrl, period.getDuration(), Duration.ZERO); + return new DashMediaSegment(period, 1, segmentUrl, period.getDuration(), Duration.ZERO, + Duration.ZERO); } } diff --git a/src/test/java/com/blazemeter/jmeter/hls/logic/VideoStreamingSamplerFactoryTest.java b/src/test/java/com/blazemeter/jmeter/hls/logic/VideoStreamingSamplerFactoryTest.java index 2c78f6c..fa7f5f6 100644 --- a/src/test/java/com/blazemeter/jmeter/hls/logic/VideoStreamingSamplerFactoryTest.java +++ b/src/test/java/com/blazemeter/jmeter/hls/logic/VideoStreamingSamplerFactoryTest.java @@ -1,14 +1,19 @@ package com.blazemeter.jmeter.hls.logic; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doReturn; +import com.blazemeter.jmeter.videostreaming.core.Protocol; import com.blazemeter.jmeter.videostreaming.core.SampleResultProcessor; import com.blazemeter.jmeter.videostreaming.core.TimeMachine; import com.blazemeter.jmeter.videostreaming.core.VideoStreamingHttpClient; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +@RunWith(MockitoJUnitRunner.class) public class VideoStreamingSamplerFactoryTest { @Mock @@ -25,6 +30,7 @@ public class VideoStreamingSamplerFactoryTest { @Before public void setUp() { factory = new VideoStreamingSamplerFactory(); + doReturn(Protocol.AUTOMATIC).when(proxy).getProtocolSelector(); } @Test @@ -40,4 +46,20 @@ public void shouldNotCreateHlsSamplerWhenUrlNotContainsExtension() { .getVideoStreamingSampler("test.com/master.mpd", proxy, client, timeMachine, processor)) .isNotInstanceOf(com.blazemeter.jmeter.videostreaming.hls.HlsSampler.class); } -} \ No newline at end of file + + @Test + public void shouldCreateHlsSamplerWhenHlsProtocolIsSelected() { + doReturn(Protocol.HLS).when(proxy).getProtocolSelector(); + assertThat(factory + .getVideoStreamingSampler("test.com/master", proxy, client, timeMachine, processor)) + .isInstanceOf(com.blazemeter.jmeter.videostreaming.hls.HlsSampler.class); + } + + @Test + public void shouldCreateDashSamplerWhenDashProtocolIsSelected() { + doReturn(Protocol.MPEG_DASH).when(proxy).getProtocolSelector(); + assertThat(factory + .getVideoStreamingSampler("test.com/master", proxy, client, timeMachine, processor)) + .isInstanceOf(com.blazemeter.jmeter.videostreaming.dash.DashSampler.class); + } +}