mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add test to ensure AdsLoader is initialized.
This tests explicitly that initialization happens even if the Timeline is a placeholder. No other change is needed. While the Timeline is still a placeholder ImaAdsLoader.getCurrentPeriodPosition will return 0 and trigger pre-rolls (intended behaviour) and it doesn't matter whether the actual initial period position may be somewhere else. PiperOrigin-RevId: 298833867
This commit is contained in:
parent
03be1551a7
commit
d1b900604a
3 changed files with 36 additions and 93 deletions
|
|
@ -16,6 +16,7 @@
|
||||||
package com.google.android.exoplayer2.ext.ima;
|
package com.google.android.exoplayer2.ext.ima;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.inOrder;
|
import static org.mockito.Mockito.inOrder;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
@ -39,11 +40,14 @@ import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
import com.google.android.exoplayer2.Timeline.Period;
|
||||||
|
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader.ImaFactory;
|
||||||
|
import com.google.android.exoplayer2.source.MaskingMediaSource;
|
||||||
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
|
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
|
||||||
import com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline;
|
import com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline;
|
||||||
|
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -63,8 +67,11 @@ public class ImaAdsLoaderTest {
|
||||||
|
|
||||||
private static final long CONTENT_DURATION_US = 10 * C.MICROS_PER_SECOND;
|
private static final long CONTENT_DURATION_US = 10 * C.MICROS_PER_SECOND;
|
||||||
private static final Timeline CONTENT_TIMELINE =
|
private static final Timeline CONTENT_TIMELINE =
|
||||||
new SinglePeriodTimeline(
|
new FakeTimeline(
|
||||||
CONTENT_DURATION_US, /* isSeekable= */ true, /* isDynamic= */ false, /* isLive= */ false);
|
new FakeTimeline.TimelineWindowDefinition(
|
||||||
|
/* isSeekable= */ true, /* isDynamic= */ false, CONTENT_DURATION_US));
|
||||||
|
private static final long CONTENT_PERIOD_DURATION_US =
|
||||||
|
CONTENT_TIMELINE.getPeriod(/* periodIndex= */ 0, new Period()).durationUs;
|
||||||
private static final Uri TEST_URI = Uri.EMPTY;
|
private static final Uri TEST_URI = Uri.EMPTY;
|
||||||
private static final long TEST_AD_DURATION_US = 5 * C.MICROS_PER_SECOND;
|
private static final long TEST_AD_DURATION_US = 5 * C.MICROS_PER_SECOND;
|
||||||
private static final long[][] PREROLL_ADS_DURATIONS_US = new long[][] {{TEST_AD_DURATION_US}};
|
private static final long[][] PREROLL_ADS_DURATIONS_US = new long[][] {{TEST_AD_DURATION_US}};
|
||||||
|
|
@ -72,11 +79,11 @@ public class ImaAdsLoaderTest {
|
||||||
private static final FakeAd UNSKIPPABLE_AD =
|
private static final FakeAd UNSKIPPABLE_AD =
|
||||||
new FakeAd(/* skippable= */ false, /* podIndex= */ 0, /* totalAds= */ 1, /* adPosition= */ 1);
|
new FakeAd(/* skippable= */ false, /* podIndex= */ 0, /* totalAds= */ 1, /* adPosition= */ 1);
|
||||||
|
|
||||||
private @Mock ImaSdkSettings imaSdkSettings;
|
@Mock private ImaSdkSettings imaSdkSettings;
|
||||||
private @Mock AdsRenderingSettings adsRenderingSettings;
|
@Mock private AdsRenderingSettings adsRenderingSettings;
|
||||||
private @Mock AdDisplayContainer adDisplayContainer;
|
@Mock private AdDisplayContainer adDisplayContainer;
|
||||||
private @Mock AdsManager adsManager;
|
@Mock private AdsManager adsManager;
|
||||||
private SingletonImaFactory testImaFactory;
|
@Mock private ImaFactory mockImaFactory;
|
||||||
private ViewGroup adViewGroup;
|
private ViewGroup adViewGroup;
|
||||||
private View adOverlayView;
|
private View adOverlayView;
|
||||||
private AdsLoader.AdViewProvider adViewProvider;
|
private AdsLoader.AdViewProvider adViewProvider;
|
||||||
|
|
@ -89,13 +96,11 @@ public class ImaAdsLoaderTest {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
FakeAdsRequest fakeAdsRequest = new FakeAdsRequest();
|
FakeAdsRequest fakeAdsRequest = new FakeAdsRequest();
|
||||||
FakeAdsLoader fakeAdsLoader = new FakeAdsLoader(imaSdkSettings, adsManager);
|
FakeAdsLoader fakeAdsLoader = new FakeAdsLoader(imaSdkSettings, adsManager);
|
||||||
testImaFactory =
|
when(mockImaFactory.createAdDisplayContainer()).thenReturn(adDisplayContainer);
|
||||||
new SingletonImaFactory(
|
when(mockImaFactory.createAdsRenderingSettings()).thenReturn(adsRenderingSettings);
|
||||||
imaSdkSettings,
|
when(mockImaFactory.createAdsRequest()).thenReturn(fakeAdsRequest);
|
||||||
adsRenderingSettings,
|
when(mockImaFactory.createImaSdkSettings()).thenReturn(imaSdkSettings);
|
||||||
adDisplayContainer,
|
when(mockImaFactory.createAdsLoader(any(), any(), any())).thenReturn(fakeAdsLoader);
|
||||||
fakeAdsRequest,
|
|
||||||
fakeAdsLoader);
|
|
||||||
adViewGroup = new FrameLayout(ApplicationProvider.getApplicationContext());
|
adViewGroup = new FrameLayout(ApplicationProvider.getApplicationContext());
|
||||||
adOverlayView = new View(ApplicationProvider.getApplicationContext());
|
adOverlayView = new View(ApplicationProvider.getApplicationContext());
|
||||||
adViewProvider =
|
adViewProvider =
|
||||||
|
|
@ -136,6 +141,16 @@ public class ImaAdsLoaderTest {
|
||||||
verify(adDisplayContainer, atLeastOnce()).registerVideoControlsOverlay(adOverlayView);
|
verify(adDisplayContainer, atLeastOnce()).registerVideoControlsOverlay(adOverlayView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStart_withPlaceholderContent_initializedAdsLoader() {
|
||||||
|
Timeline placeholderTimeline = new MaskingMediaSource.DummyTimeline(/* tag= */ null);
|
||||||
|
setupPlayback(placeholderTimeline, PREROLL_ADS_DURATIONS_US, PREROLL_CUE_POINTS_SECONDS);
|
||||||
|
imaAdsLoader.start(adsLoaderListener, adViewProvider);
|
||||||
|
|
||||||
|
// We'll only create the rendering settings when initializing the ads loader.
|
||||||
|
verify(mockImaFactory).createAdsRenderingSettings();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStart_updatesAdPlaybackState() {
|
public void testStart_updatesAdPlaybackState() {
|
||||||
setupPlayback(CONTENT_TIMELINE, PREROLL_ADS_DURATIONS_US, PREROLL_CUE_POINTS_SECONDS);
|
setupPlayback(CONTENT_TIMELINE, PREROLL_ADS_DURATIONS_US, PREROLL_CUE_POINTS_SECONDS);
|
||||||
|
|
@ -143,9 +158,9 @@ public class ImaAdsLoaderTest {
|
||||||
|
|
||||||
assertThat(adsLoaderListener.adPlaybackState)
|
assertThat(adsLoaderListener.adPlaybackState)
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
new AdPlaybackState(/* adGroupTimesUs= */ 0)
|
new AdPlaybackState(/* adGroupTimesUs...= */ 0)
|
||||||
.withAdDurationsUs(PREROLL_ADS_DURATIONS_US)
|
.withAdDurationsUs(PREROLL_ADS_DURATIONS_US)
|
||||||
.withContentDurationUs(CONTENT_DURATION_US));
|
.withContentDurationUs(CONTENT_PERIOD_DURATION_US));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -213,8 +228,8 @@ public class ImaAdsLoaderTest {
|
||||||
// Verify that the preroll ad has been marked as played.
|
// Verify that the preroll ad has been marked as played.
|
||||||
assertThat(adsLoaderListener.adPlaybackState)
|
assertThat(adsLoaderListener.adPlaybackState)
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
new AdPlaybackState(/* adGroupTimesUs= */ 0)
|
new AdPlaybackState(/* adGroupTimesUs...= */ 0)
|
||||||
.withContentDurationUs(CONTENT_DURATION_US)
|
.withContentDurationUs(CONTENT_PERIOD_DURATION_US)
|
||||||
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)
|
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)
|
||||||
.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, /* uri= */ TEST_URI)
|
.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, /* uri= */ TEST_URI)
|
||||||
.withAdDurationsUs(PREROLL_ADS_DURATIONS_US)
|
.withAdDurationsUs(PREROLL_ADS_DURATIONS_US)
|
||||||
|
|
@ -240,7 +255,7 @@ public class ImaAdsLoaderTest {
|
||||||
when(adsManager.getAdCuePoints()).thenReturn(Arrays.asList(cuePoints));
|
when(adsManager.getAdCuePoints()).thenReturn(Arrays.asList(cuePoints));
|
||||||
imaAdsLoader =
|
imaAdsLoader =
|
||||||
new ImaAdsLoader.Builder(ApplicationProvider.getApplicationContext())
|
new ImaAdsLoader.Builder(ApplicationProvider.getApplicationContext())
|
||||||
.setImaFactory(testImaFactory)
|
.setImaFactory(mockImaFactory)
|
||||||
.setImaSdkSettings(imaSdkSettings)
|
.setImaSdkSettings(imaSdkSettings)
|
||||||
.buildForAdTag(TEST_URI);
|
.buildForAdTag(TEST_URI);
|
||||||
imaAdsLoader.setPlayer(fakeExoPlayer);
|
imaAdsLoader.setPlayer(fakeExoPlayer);
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2018 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.exoplayer2.ext.ima;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import com.google.ads.interactivemedia.v3.api.AdDisplayContainer;
|
|
||||||
import com.google.ads.interactivemedia.v3.api.AdsLoader;
|
|
||||||
import com.google.ads.interactivemedia.v3.api.AdsRenderingSettings;
|
|
||||||
import com.google.ads.interactivemedia.v3.api.AdsRequest;
|
|
||||||
import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
|
|
||||||
|
|
||||||
/** {@link ImaAdsLoader.ImaFactory} that returns provided instances from each getter, for tests. */
|
|
||||||
final class SingletonImaFactory implements ImaAdsLoader.ImaFactory {
|
|
||||||
|
|
||||||
private final ImaSdkSettings imaSdkSettings;
|
|
||||||
private final AdsRenderingSettings adsRenderingSettings;
|
|
||||||
private final AdDisplayContainer adDisplayContainer;
|
|
||||||
private final AdsRequest adsRequest;
|
|
||||||
private final com.google.ads.interactivemedia.v3.api.AdsLoader adsLoader;
|
|
||||||
|
|
||||||
public SingletonImaFactory(
|
|
||||||
ImaSdkSettings imaSdkSettings,
|
|
||||||
AdsRenderingSettings adsRenderingSettings,
|
|
||||||
AdDisplayContainer adDisplayContainer,
|
|
||||||
AdsRequest adsRequest,
|
|
||||||
com.google.ads.interactivemedia.v3.api.AdsLoader adsLoader) {
|
|
||||||
this.imaSdkSettings = imaSdkSettings;
|
|
||||||
this.adsRenderingSettings = adsRenderingSettings;
|
|
||||||
this.adDisplayContainer = adDisplayContainer;
|
|
||||||
this.adsRequest = adsRequest;
|
|
||||||
this.adsLoader = adsLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImaSdkSettings createImaSdkSettings() {
|
|
||||||
return imaSdkSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AdsRenderingSettings createAdsRenderingSettings() {
|
|
||||||
return adsRenderingSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AdDisplayContainer createAdDisplayContainer() {
|
|
||||||
return adDisplayContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AdsRequest createAdsRequest() {
|
|
||||||
return adsRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AdsLoader createAdsLoader(
|
|
||||||
Context context, ImaSdkSettings imaSdkSettings, AdDisplayContainer adDisplayContainer) {
|
|
||||||
return adsLoader;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -293,7 +293,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Dummy placeholder timeline with one dynamic window with a period of indeterminate duration. */
|
/** Dummy placeholder timeline with one dynamic window with a period of indeterminate duration. */
|
||||||
private static final class DummyTimeline extends Timeline {
|
public static final class DummyTimeline extends Timeline {
|
||||||
|
|
||||||
@Nullable private final Object tag;
|
@Nullable private final Object tag;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue