1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.exoplayer2.testutil; 17 18 import static com.google.common.truth.Truth.assertThat; 19 20 import com.google.android.exoplayer2.C; 21 import com.google.android.exoplayer2.Player; 22 import com.google.android.exoplayer2.Timeline; 23 import com.google.android.exoplayer2.Timeline.Period; 24 import com.google.android.exoplayer2.Timeline.Window; 25 import com.google.android.exoplayer2.util.Assertions; 26 import org.checkerframework.checker.nullness.compatqual.NullableType; 27 28 /** Unit test for {@link Timeline}. */ 29 public final class TimelineAsserts { 30 31 private static final int[] REPEAT_MODES = { 32 Player.REPEAT_MODE_OFF, Player.REPEAT_MODE_ONE, Player.REPEAT_MODE_ALL 33 }; 34 TimelineAsserts()35 private TimelineAsserts() {} 36 37 /** Assert that timeline is empty (i.e. has no windows or periods). */ assertEmpty(Timeline timeline)38 public static void assertEmpty(Timeline timeline) { 39 assertWindowTags(timeline); 40 assertPeriodCounts(timeline); 41 for (boolean shuffled : new boolean[] {false, true}) { 42 assertThat(timeline.getFirstWindowIndex(shuffled)).isEqualTo(C.INDEX_UNSET); 43 assertThat(timeline.getLastWindowIndex(shuffled)).isEqualTo(C.INDEX_UNSET); 44 } 45 } 46 47 /** 48 * Asserts that window tags are set correctly. 49 * 50 * @param expectedWindowTags A list of expected window tags. If a tag is unknown or not important 51 * {@code null} can be passed to skip this window. 52 */ assertWindowTags( Timeline timeline, @NullableType Object... expectedWindowTags)53 public static void assertWindowTags( 54 Timeline timeline, @NullableType Object... expectedWindowTags) { 55 Window window = new Window(); 56 assertThat(timeline.getWindowCount()).isEqualTo(expectedWindowTags.length); 57 for (int i = 0; i < timeline.getWindowCount(); i++) { 58 timeline.getWindow(i, window); 59 if (expectedWindowTags[i] != null) { 60 assertThat(window.tag).isEqualTo(expectedWindowTags[i]); 61 } 62 } 63 } 64 65 /** Asserts that window properties {@link Window}.isDynamic are set correctly. */ assertWindowIsDynamic(Timeline timeline, boolean... windowIsDynamic)66 public static void assertWindowIsDynamic(Timeline timeline, boolean... windowIsDynamic) { 67 Window window = new Window(); 68 for (int i = 0; i < timeline.getWindowCount(); i++) { 69 timeline.getWindow(i, window); 70 assertThat(window.isDynamic).isEqualTo(windowIsDynamic[i]); 71 } 72 } 73 74 /** 75 * Asserts that previous window indices for each window depending on the repeat mode and the 76 * shuffle mode are equal to the given sequence. 77 */ assertPreviousWindowIndices( Timeline timeline, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled, int... expectedPreviousWindowIndices)78 public static void assertPreviousWindowIndices( 79 Timeline timeline, 80 @Player.RepeatMode int repeatMode, 81 boolean shuffleModeEnabled, 82 int... expectedPreviousWindowIndices) { 83 for (int i = 0; i < timeline.getWindowCount(); i++) { 84 assertThat(timeline.getPreviousWindowIndex(i, repeatMode, shuffleModeEnabled)) 85 .isEqualTo(expectedPreviousWindowIndices[i]); 86 } 87 } 88 89 /** 90 * Asserts that next window indices for each window depending on the repeat mode and the shuffle 91 * mode are equal to the given sequence. 92 */ assertNextWindowIndices( Timeline timeline, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled, int... expectedNextWindowIndices)93 public static void assertNextWindowIndices( 94 Timeline timeline, 95 @Player.RepeatMode int repeatMode, 96 boolean shuffleModeEnabled, 97 int... expectedNextWindowIndices) { 98 for (int i = 0; i < timeline.getWindowCount(); i++) { 99 assertThat(timeline.getNextWindowIndex(i, repeatMode, shuffleModeEnabled)) 100 .isEqualTo(expectedNextWindowIndices[i]); 101 } 102 } 103 104 /** 105 * Asserts that the durations of the periods in the {@link Timeline} and the durations in the 106 * given sequence are equal. 107 */ assertPeriodDurations(Timeline timeline, long... durationsUs)108 public static void assertPeriodDurations(Timeline timeline, long... durationsUs) { 109 int periodCount = timeline.getPeriodCount(); 110 assertThat(periodCount).isEqualTo(durationsUs.length); 111 Period period = new Period(); 112 for (int i = 0; i < periodCount; i++) { 113 assertThat(timeline.getPeriod(i, period).durationUs).isEqualTo(durationsUs[i]); 114 } 115 } 116 117 /** 118 * Asserts that period counts for each window are set correctly. Also asserts that {@link 119 * Window#firstPeriodIndex} and {@link Window#lastPeriodIndex} are set correctly, and it asserts 120 * the correct behavior of {@link Timeline#getNextWindowIndex(int, int, boolean)}. 121 */ assertPeriodCounts(Timeline timeline, int... expectedPeriodCounts)122 public static void assertPeriodCounts(Timeline timeline, int... expectedPeriodCounts) { 123 int windowCount = timeline.getWindowCount(); 124 assertThat(windowCount).isEqualTo(expectedPeriodCounts.length); 125 int[] accumulatedPeriodCounts = new int[windowCount + 1]; 126 accumulatedPeriodCounts[0] = 0; 127 for (int i = 0; i < windowCount; i++) { 128 accumulatedPeriodCounts[i + 1] = accumulatedPeriodCounts[i] + expectedPeriodCounts[i]; 129 } 130 assertThat(timeline.getPeriodCount()) 131 .isEqualTo(accumulatedPeriodCounts[accumulatedPeriodCounts.length - 1]); 132 Window window = new Window(); 133 Period period = new Period(); 134 for (int i = 0; i < windowCount; i++) { 135 timeline.getWindow(i, window); 136 assertThat(window.firstPeriodIndex).isEqualTo(accumulatedPeriodCounts[i]); 137 assertThat(window.lastPeriodIndex).isEqualTo(accumulatedPeriodCounts[i + 1] - 1); 138 } 139 int expectedWindowIndex = 0; 140 for (int i = 0; i < timeline.getPeriodCount(); i++) { 141 timeline.getPeriod(i, period, true); 142 while (i >= accumulatedPeriodCounts[expectedWindowIndex + 1]) { 143 expectedWindowIndex++; 144 } 145 assertThat(period.windowIndex).isEqualTo(expectedWindowIndex); 146 Object periodUid = Assertions.checkNotNull(period.uid); 147 assertThat(timeline.getIndexOfPeriod(periodUid)).isEqualTo(i); 148 assertThat(timeline.getUidOfPeriod(i)).isEqualTo(periodUid); 149 for (int repeatMode : REPEAT_MODES) { 150 if (i < accumulatedPeriodCounts[expectedWindowIndex + 1] - 1) { 151 assertThat(timeline.getNextPeriodIndex(i, period, window, repeatMode, false)) 152 .isEqualTo(i + 1); 153 } else { 154 int nextWindow = timeline.getNextWindowIndex(expectedWindowIndex, repeatMode, false); 155 int nextPeriod = 156 nextWindow == C.INDEX_UNSET ? C.INDEX_UNSET : accumulatedPeriodCounts[nextWindow]; 157 assertThat(timeline.getNextPeriodIndex(i, period, window, repeatMode, false)) 158 .isEqualTo(nextPeriod); 159 } 160 } 161 } 162 } 163 164 /** Asserts that periods' {@link Period#getAdGroupCount()} are set correctly. */ assertAdGroupCounts(Timeline timeline, int... expectedAdGroupCounts)165 public static void assertAdGroupCounts(Timeline timeline, int... expectedAdGroupCounts) { 166 Period period = new Period(); 167 for (int i = 0; i < timeline.getPeriodCount(); i++) { 168 timeline.getPeriod(i, period); 169 assertThat(period.getAdGroupCount()).isEqualTo(expectedAdGroupCounts[i]); 170 } 171 } 172 } 173