| /* |
| * Copyright (C) 2017 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.source; |
| |
| import static com.google.android.exoplayer2.C.INDEX_UNSET; |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import androidx.test.ext.junit.runners.AndroidJUnit4; |
| import com.google.android.exoplayer2.C; |
| import com.google.android.exoplayer2.source.ShuffleOrder.DefaultShuffleOrder; |
| import com.google.android.exoplayer2.source.ShuffleOrder.UnshuffledShuffleOrder; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| /** Unit test for {@link ShuffleOrder}. */ |
| @RunWith(AndroidJUnit4.class) |
| public final class ShuffleOrderTest { |
| |
| public static final long RANDOM_SEED = 1234567890L; |
| |
| @Test |
| public void defaultShuffleOrder() { |
| assertShuffleOrderCorrectness(new DefaultShuffleOrder(0, RANDOM_SEED), 0); |
| assertShuffleOrderCorrectness(new DefaultShuffleOrder(1, RANDOM_SEED), 1); |
| assertShuffleOrderCorrectness(new DefaultShuffleOrder(5, RANDOM_SEED), 5); |
| for (int initialLength = 0; initialLength < 4; initialLength++) { |
| for (int insertionPoint = 0; insertionPoint <= initialLength; insertionPoint += 2) { |
| testCloneAndInsert(new DefaultShuffleOrder(initialLength, RANDOM_SEED), insertionPoint, 0); |
| testCloneAndInsert(new DefaultShuffleOrder(initialLength, RANDOM_SEED), insertionPoint, 1); |
| testCloneAndInsert(new DefaultShuffleOrder(initialLength, RANDOM_SEED), insertionPoint, 5); |
| } |
| } |
| testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 0, 1); |
| testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 2, 3); |
| testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 4, 5); |
| testCloneAndRemove(new DefaultShuffleOrder(1, RANDOM_SEED), 0, 1); |
| testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 1000); |
| testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 999); |
| testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 500); |
| testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 100, 600); |
| testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 500, 1000); |
| } |
| |
| @Test |
| public void defaultShuffleOrderSideloaded() { |
| int[] shuffledIndices = new int[] {2, 1, 0, 4, 3}; |
| ShuffleOrder shuffleOrder = new DefaultShuffleOrder(shuffledIndices, RANDOM_SEED); |
| assertThat(shuffleOrder.getFirstIndex()).isEqualTo(2); |
| assertThat(shuffleOrder.getLastIndex()).isEqualTo(3); |
| for (int i = 0; i < 4; i++) { |
| assertThat(shuffleOrder.getNextIndex(shuffledIndices[i])).isEqualTo(shuffledIndices[i + 1]); |
| } |
| assertThat(shuffleOrder.getNextIndex(3)).isEqualTo(C.INDEX_UNSET); |
| for (int i = 4; i > 0; i--) { |
| assertThat(shuffleOrder.getPreviousIndex(shuffledIndices[i])) |
| .isEqualTo(shuffledIndices[i - 1]); |
| } |
| assertThat(shuffleOrder.getPreviousIndex(2)).isEqualTo(C.INDEX_UNSET); |
| } |
| |
| @Test |
| public void unshuffledShuffleOrder() { |
| assertShuffleOrderCorrectness(new UnshuffledShuffleOrder(0), 0); |
| assertShuffleOrderCorrectness(new UnshuffledShuffleOrder(1), 1); |
| assertShuffleOrderCorrectness(new UnshuffledShuffleOrder(5), 5); |
| for (int initialLength = 0; initialLength < 4; initialLength++) { |
| for (int insertionPoint = 0; insertionPoint <= initialLength; insertionPoint += 2) { |
| testCloneAndInsert(new UnshuffledShuffleOrder(initialLength), insertionPoint, 0); |
| testCloneAndInsert(new UnshuffledShuffleOrder(initialLength), insertionPoint, 1); |
| testCloneAndInsert(new UnshuffledShuffleOrder(initialLength), insertionPoint, 5); |
| } |
| } |
| testCloneAndRemove(new UnshuffledShuffleOrder(5), 0, 1); |
| testCloneAndRemove(new UnshuffledShuffleOrder(5), 2, 3); |
| testCloneAndRemove(new UnshuffledShuffleOrder(5), 4, 5); |
| testCloneAndRemove(new UnshuffledShuffleOrder(1), 0, 1); |
| testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 1000); |
| testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 999); |
| testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 500); |
| testCloneAndRemove(new UnshuffledShuffleOrder(1000), 100, 600); |
| testCloneAndRemove(new UnshuffledShuffleOrder(1000), 500, 1000); |
| } |
| |
| @Test |
| public void unshuffledShuffleOrderIsUnshuffled() { |
| ShuffleOrder shuffleOrder = new UnshuffledShuffleOrder(5); |
| assertThat(shuffleOrder.getFirstIndex()).isEqualTo(0); |
| assertThat(shuffleOrder.getLastIndex()).isEqualTo(4); |
| for (int i = 0; i < 4; i++) { |
| assertThat(shuffleOrder.getNextIndex(i)).isEqualTo(i + 1); |
| } |
| } |
| |
| private static void assertShuffleOrderCorrectness(ShuffleOrder shuffleOrder, int length) { |
| assertThat(shuffleOrder.getLength()).isEqualTo(length); |
| if (length == 0) { |
| assertThat(shuffleOrder.getFirstIndex()).isEqualTo(INDEX_UNSET); |
| assertThat(shuffleOrder.getLastIndex()).isEqualTo(INDEX_UNSET); |
| } else { |
| int[] indices = new int[length]; |
| indices[0] = shuffleOrder.getFirstIndex(); |
| assertThat(shuffleOrder.getPreviousIndex(indices[0])).isEqualTo(INDEX_UNSET); |
| for (int i = 1; i < length; i++) { |
| indices[i] = shuffleOrder.getNextIndex(indices[i - 1]); |
| assertThat(shuffleOrder.getPreviousIndex(indices[i])).isEqualTo(indices[i - 1]); |
| for (int j = 0; j < i; j++) { |
| assertThat(indices[i] != indices[j]).isTrue(); |
| } |
| } |
| assertThat(shuffleOrder.getLastIndex()).isEqualTo(indices[length - 1]); |
| assertThat(shuffleOrder.getNextIndex(indices[length - 1])).isEqualTo(INDEX_UNSET); |
| for (int i = 0; i < length; i++) { |
| assertThat(indices[i] >= 0).isTrue(); |
| assertThat(indices[i] < length).isTrue(); |
| } |
| } |
| } |
| |
| private static void testCloneAndInsert(ShuffleOrder shuffleOrder, int position, int count) { |
| ShuffleOrder newOrder = shuffleOrder.cloneAndInsert(position, count); |
| assertShuffleOrderCorrectness(newOrder, shuffleOrder.getLength() + count); |
| // Assert all elements still have the relative same order |
| for (int i = 0; i < shuffleOrder.getLength(); i++) { |
| int expectedNextIndex = shuffleOrder.getNextIndex(i); |
| if (expectedNextIndex != C.INDEX_UNSET && expectedNextIndex >= position) { |
| expectedNextIndex += count; |
| } |
| int newNextIndex = newOrder.getNextIndex(i < position ? i : i + count); |
| while (newNextIndex >= position && newNextIndex < position + count) { |
| newNextIndex = newOrder.getNextIndex(newNextIndex); |
| } |
| assertThat(newNextIndex).isEqualTo(expectedNextIndex); |
| } |
| } |
| |
| private static void testCloneAndRemove( |
| ShuffleOrder shuffleOrder, int indexFrom, int indexToExclusive) { |
| int numberOfElementsToRemove = indexToExclusive - indexFrom; |
| ShuffleOrder newOrder = shuffleOrder.cloneAndRemove(indexFrom, indexToExclusive); |
| assertShuffleOrderCorrectness(newOrder, shuffleOrder.getLength() - numberOfElementsToRemove); |
| // Assert all elements still have the relative same order |
| for (int i = 0; i < shuffleOrder.getLength(); i++) { |
| if (i >= indexFrom && i < indexToExclusive) { |
| continue; |
| } |
| int expectedNextIndex = shuffleOrder.getNextIndex(i); |
| while (expectedNextIndex >= indexFrom && expectedNextIndex < indexToExclusive) { |
| expectedNextIndex = shuffleOrder.getNextIndex(expectedNextIndex); |
| } |
| if (expectedNextIndex != C.INDEX_UNSET && expectedNextIndex >= indexFrom) { |
| expectedNextIndex -= numberOfElementsToRemove; |
| } |
| int newNextIndex = newOrder.getNextIndex(i < indexFrom ? i : i - numberOfElementsToRemove); |
| assertThat(newNextIndex).isEqualTo(expectedNextIndex); |
| } |
| } |
| |
| } |