From 38096fb73472718a87a78a8cd905bebd40403c9d Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Thu, 21 Jun 2018 01:02:20 -0700 Subject: [PATCH] Add some Robolectric tests for ImaAdsLoader ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=201484853 --- extensions/ima/build.gradle | 3 + .../exoplayer2/ext/ima/ImaAdsLoader.java | 93 +++++++++++++++---- .../source/ads/AdPlaybackState.java | 49 ++++++++++ 3 files changed, 127 insertions(+), 18 deletions(-) diff --git a/extensions/ima/build.gradle b/extensions/ima/build.gradle index 96d0439aa3..c7481bf829 100644 --- a/extensions/ima/build.gradle +++ b/extensions/ima/build.gradle @@ -41,6 +41,9 @@ dependencies { // |-- com.android.support:customtabs:26.1.0 implementation 'com.android.support:support-v4:' + supportLibraryVersion implementation 'com.android.support:customtabs:' + supportLibraryVersion + testImplementation 'junit:junit:' + junitVersion + testImplementation 'org.mockito:mockito-core:' + mockitoVersion + testImplementation 'org.robolectric:robolectric:' + robolectricVersion } ext { diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java index 3256da21dd..b02869fbe4 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java @@ -85,6 +85,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A private @Nullable AdEventListener adEventListener; private int vastLoadTimeoutMs; private int mediaLoadTimeoutMs; + private ImaFactory imaFactory; /** * Creates a new builder for {@link ImaAdsLoader}. @@ -95,6 +96,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A this.context = Assertions.checkNotNull(context); vastLoadTimeoutMs = TIMEOUT_UNSET; mediaLoadTimeoutMs = TIMEOUT_UNSET; + imaFactory = new DefaultImaFactory(); } /** @@ -149,6 +151,12 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A return this; } + // @VisibleForTesting + /* package */ Builder setImaFactory(ImaFactory imaFactory) { + this.imaFactory = Assertions.checkNotNull(imaFactory); + return this; + } + /** * Returns a new {@link ImaAdsLoader} for the specified ad tag. * @@ -165,7 +173,8 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A null, vastLoadTimeoutMs, mediaLoadTimeoutMs, - adEventListener); + adEventListener, + imaFactory); } /** @@ -183,7 +192,8 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A adsResponse, vastLoadTimeoutMs, mediaLoadTimeoutMs, - adEventListener); + adEventListener, + imaFactory); } } @@ -242,9 +252,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A private final int vastLoadTimeoutMs; private final int mediaLoadTimeoutMs; private final @Nullable AdEventListener adEventListener; + private final ImaFactory imaFactory; private final Timeline.Period period; private final List adCallbacks; - private final ImaSdkFactory imaSdkFactory; private final AdDisplayContainer adDisplayContainer; private final com.google.ads.interactivemedia.v3.api.AdsLoader adsLoader; @@ -337,7 +347,8 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A /* adsResponse= */ null, /* vastLoadTimeoutMs= */ TIMEOUT_UNSET, /* mediaLoadTimeoutMs= */ TIMEOUT_UNSET, - /* adEventListener= */ null); + /* adEventListener= */ null, + /* imaFactory= */ new DefaultImaFactory()); } /** @@ -360,7 +371,8 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A /* adsResponse= */ null, /* vastLoadTimeoutMs= */ TIMEOUT_UNSET, /* mediaLoadTimeoutMs= */ TIMEOUT_UNSET, - /* adEventListener= */ null); + /* adEventListener= */ null, + /* imaFactory= */ new DefaultImaFactory()); } private ImaAdsLoader( @@ -370,26 +382,27 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A @Nullable String adsResponse, int vastLoadTimeoutMs, int mediaLoadTimeoutMs, - @Nullable AdEventListener adEventListener) { + @Nullable AdEventListener adEventListener, + ImaFactory imaFactory) { Assertions.checkArgument(adTagUri != null || adsResponse != null); this.adTagUri = adTagUri; this.adsResponse = adsResponse; this.vastLoadTimeoutMs = vastLoadTimeoutMs; this.mediaLoadTimeoutMs = mediaLoadTimeoutMs; this.adEventListener = adEventListener; - period = new Timeline.Period(); - adCallbacks = new ArrayList<>(1); - imaSdkFactory = ImaSdkFactory.getInstance(); - adDisplayContainer = imaSdkFactory.createAdDisplayContainer(); - adDisplayContainer.setPlayer(this); + this.imaFactory = imaFactory; if (imaSdkSettings == null) { - imaSdkSettings = imaSdkFactory.createImaSdkSettings(); + imaSdkSettings = imaFactory.createImaSdkSettings(); } imaSdkSettings.setPlayerType(IMA_SDK_SETTINGS_PLAYER_TYPE); imaSdkSettings.setPlayerVersion(IMA_SDK_SETTINGS_PLAYER_VERSION); - adsLoader = imaSdkFactory.createAdsLoader(context, imaSdkSettings); - adsLoader.addAdErrorListener(this); - adsLoader.addAdsLoadedListener(this); + adsLoader = imaFactory.createAdsLoader(context, imaSdkSettings); + period = new Timeline.Period(); + adCallbacks = new ArrayList<>(/* initialCapacity= */ 1); + adDisplayContainer = imaFactory.createAdDisplayContainer(); + adDisplayContainer.setPlayer(/* videoAdPlayer= */ this); + adsLoader.addAdErrorListener(/* adErrorListener= */ this); + adsLoader.addAdsLoadedListener(/* adsLoadedListener= */ this); fakeContentProgressElapsedRealtimeMs = C.TIME_UNSET; fakeContentProgressOffsetMs = C.TIME_UNSET; pendingContentPositionMs = C.TIME_UNSET; @@ -421,7 +434,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A } adDisplayContainer.setAdContainer(adUiViewGroup); pendingAdRequestContext = new Object(); - AdsRequest request = imaSdkFactory.createAdsRequest(); + AdsRequest request = imaFactory.createAdsRequest(); if (adTagUri != null) { request.setAdTagUrl(adTagUri.toString()); } else /* adsResponse != null */ { @@ -865,8 +878,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A // Internal methods. private void startAdPlayback() { - ImaSdkFactory imaSdkFactory = ImaSdkFactory.getInstance(); - AdsRenderingSettings adsRenderingSettings = imaSdkFactory.createAdsRenderingSettings(); + AdsRenderingSettings adsRenderingSettings = imaFactory.createAdsRenderingSettings(); adsRenderingSettings.setEnablePreloading(ENABLE_PRELOADING); adsRenderingSettings.setMimeTypes(supportedMimeTypes); if (mediaLoadTimeoutMs != TIMEOUT_UNSET) { @@ -1218,4 +1230,49 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A return true; } } + + /** Factory for objects provided by the IMA SDK. */ + // @VisibleForTesting + /* package */ interface ImaFactory { + /** @see ImaSdkSettings */ + ImaSdkSettings createImaSdkSettings(); + /** @see com.google.ads.interactivemedia.v3.api.ImaSdkFactory#createAdsRenderingSettings() */ + AdsRenderingSettings createAdsRenderingSettings(); + /** @see com.google.ads.interactivemedia.v3.api.ImaSdkFactory#createAdDisplayContainer() */ + AdDisplayContainer createAdDisplayContainer(); + /** @see com.google.ads.interactivemedia.v3.api.ImaSdkFactory#createAdsRequest() */ + AdsRequest createAdsRequest(); + /** @see ImaSdkFactory#createAdsLoader(Context, ImaSdkSettings) */ + com.google.ads.interactivemedia.v3.api.AdsLoader createAdsLoader( + Context context, ImaSdkSettings imaSdkSettings); + } + + /** Default {@link ImaFactory} for non-test usage, which delegates to {@link ImaSdkFactory}. */ + private static final class DefaultImaFactory implements ImaFactory { + @Override + public ImaSdkSettings createImaSdkSettings() { + return ImaSdkFactory.getInstance().createImaSdkSettings(); + } + + @Override + public AdsRenderingSettings createAdsRenderingSettings() { + return ImaSdkFactory.getInstance().createAdsRenderingSettings(); + } + + @Override + public AdDisplayContainer createAdDisplayContainer() { + return ImaSdkFactory.getInstance().createAdDisplayContainer(); + } + + @Override + public AdsRequest createAdsRequest() { + return ImaSdkFactory.getInstance().createAdsRequest(); + } + + @Override + public com.google.ads.interactivemedia.v3.api.AdsLoader createAdsLoader( + Context context, ImaSdkSettings imaSdkSettings) { + return ImaSdkFactory.getInstance().createAdsLoader(context, imaSdkSettings); + } + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java index 8654e94bdb..c91c934279 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java @@ -96,6 +96,30 @@ public final class AdPlaybackState { return count == C.LENGTH_UNSET || getFirstAdIndexToPlay() < count; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdGroup adGroup = (AdGroup) o; + return count == adGroup.count + && Arrays.equals(uris, adGroup.uris) + && Arrays.equals(states, adGroup.states) + && Arrays.equals(durationsUs, adGroup.durationsUs); + } + + @Override + public int hashCode() { + int result = count; + result = 31 * result + Arrays.hashCode(uris); + result = 31 * result + Arrays.hashCode(states); + result = 31 * result + Arrays.hashCode(durationsUs); + return result; + } + /** * Returns a new instance with the ad count set to {@code count}. This method may only be called * if this instance's ad count has not yet been specified. @@ -393,4 +417,29 @@ public final class AdPlaybackState { } } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdPlaybackState that = (AdPlaybackState) o; + return adGroupCount == that.adGroupCount + && adResumePositionUs == that.adResumePositionUs + && contentDurationUs == that.contentDurationUs + && Arrays.equals(adGroupTimesUs, that.adGroupTimesUs) + && Arrays.equals(adGroups, that.adGroups); + } + + @Override + public int hashCode() { + int result = adGroupCount; + result = 31 * result + (int) adResumePositionUs; + result = 31 * result + (int) contentDurationUs; + result = 31 * result + Arrays.hashCode(adGroupTimesUs); + result = 31 * result + Arrays.hashCode(adGroups); + return result; + } }