From 3e8dacc2844f9d8dd86eefb2604a25166568d58a Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Thu, 1 Oct 2020 11:18:18 +0100 Subject: [PATCH] Move DataSource reading methods into Util This will be used to read ads responses out of data: URLs in a subsequent change. PiperOrigin-RevId: 334778780 --- .../google/android/exoplayer2/util/Util.java | 48 ++++++++++++++++++ .../upstream/DataSchemeDataSourceTest.java | 3 +- .../upstream/cache/CacheDataSourceTest.java | 16 +++--- .../exoplayer2/testutil/CacheAsserts.java | 2 +- .../android/exoplayer2/testutil/TestUtil.java | 50 +------------------ 5 files changed, 59 insertions(+), 60 deletions(-) diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java index 0c13900330..3409263367 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -534,6 +534,54 @@ public final class Util { return Executors.newSingleThreadExecutor(runnable -> new Thread(runnable, threadName)); } + /** + * Reads data from the specified opened {@link DataSource} until it ends, and returns a byte array + * containing the read data. + * + * @param dataSource The source from which to read. + * @return The concatenation of all read data. + * @throws IOException If an error occurs reading from the source. + */ + public static byte[] readToEnd(DataSource dataSource) throws IOException { + byte[] data = new byte[1024]; + int position = 0; + int bytesRead = 0; + while (bytesRead != C.RESULT_END_OF_INPUT) { + if (position == data.length) { + data = Arrays.copyOf(data, data.length * 2); + } + bytesRead = dataSource.read(data, position, data.length - position); + if (bytesRead != C.RESULT_END_OF_INPUT) { + position += bytesRead; + } + } + return Arrays.copyOf(data, position); + } + + /** + * Reads {@code length} bytes from the specified opened {@link DataSource}, and returns a byte + * array containing the read data. + * + * @param dataSource The source from which to read. + * @return The read data. + * @throws IOException If an error occurs reading from the source. + * @throws IllegalStateException If the end of the source was reached before {@code length} bytes + * could be read. + */ + public static byte[] readExactly(DataSource dataSource, int length) throws IOException { + byte[] data = new byte[length]; + int position = 0; + while (position < length) { + int bytesRead = dataSource.read(data, position, data.length - position); + if (bytesRead == C.RESULT_END_OF_INPUT) { + throw new IllegalStateException( + "Not enough data could be read: " + position + " < " + length); + } + position += bytesRead; + } + return data; + } + /** * Closes a {@link DataSource}, suppressing any {@link IOException} that may occur. * diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSchemeDataSourceTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSchemeDataSourceTest.java index 0acbd74891..ab0bf95404 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSchemeDataSourceTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/DataSchemeDataSourceTest.java @@ -22,7 +22,6 @@ import static org.junit.Assert.fail; import android.net.Uri; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.util.Util; import java.io.IOException; import org.junit.Before; @@ -167,7 +166,7 @@ public final class DataSchemeDataSourceTest { try { long length = dataSource.open(dataSpec); assertThat(length).isEqualTo(expectedData.length); - byte[] readData = TestUtil.readToEnd(dataSource); + byte[] readData = Util.readToEnd(dataSource); assertThat(readData).isEqualTo(expectedData); } finally { dataSource.close(); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest.java index cadd9e43ab..5ee8e423b7 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest.java @@ -302,7 +302,7 @@ public final class CacheDataSourceTest { CacheDataSource cacheDataSource = new CacheDataSource(cache, upstream, 0); cacheDataSource.open(unboundedDataSpec); - TestUtil.readToEnd(cacheDataSource); + Util.readToEnd(cacheDataSource); cacheDataSource.close(); assertThat(upstream.getAndClearOpenedDataSpecs()).hasLength(1); @@ -319,7 +319,7 @@ public final class CacheDataSourceTest { cache, upstream, CacheDataSource.FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS); cacheDataSource.open(unboundedDataSpec); - TestUtil.readToEnd(cacheDataSource); + Util.readToEnd(cacheDataSource); cacheDataSource.close(); assertThat(cache.getKeys()).isEmpty(); @@ -369,7 +369,7 @@ public final class CacheDataSourceTest { cacheWriter.cache(); // Read the rest of the data. - TestUtil.readToEnd(cacheDataSource); + Util.readToEnd(cacheDataSource); cacheDataSource.close(); } @@ -419,7 +419,7 @@ public final class CacheDataSourceTest { cacheWriter.cache(); // Read the rest of the data. - TestUtil.readToEnd(cacheDataSource); + Util.readToEnd(cacheDataSource); cacheDataSource.close(); } @@ -449,14 +449,14 @@ public final class CacheDataSourceTest { // Open source and read some data from upstream as the data hasn't cached yet. cacheDataSource.open(unboundedDataSpec); - TestUtil.readExactly(cacheDataSource, 100); + Util.readExactly(cacheDataSource, 100); // Delete cached data. cache.removeResource(cacheDataSource.getCacheKeyFactory().buildCacheKey(unboundedDataSpec)); assertCacheEmpty(cache); // Read the rest of the data. - TestUtil.readToEnd(cacheDataSource); + Util.readToEnd(cacheDataSource); cacheDataSource.close(); } @@ -487,7 +487,7 @@ public final class CacheDataSourceTest { cacheDataSource.open(unboundedDataSpec); // Read the first half from upstream as it hasn't cached yet. - TestUtil.readExactly(cacheDataSource, halfDataLength); + Util.readExactly(cacheDataSource, halfDataLength); // Delete the cached latter half. NavigableSet cachedSpans = cache.getCachedSpans(defaultCacheKey); @@ -498,7 +498,7 @@ public final class CacheDataSourceTest { } // Read the rest of the data. - TestUtil.readToEnd(cacheDataSource); + Util.readToEnd(cacheDataSource); cacheDataSource.close(); } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java index 118f571e01..65cc7dc8e7 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java @@ -130,7 +130,7 @@ public final class CacheAsserts { byte[] bytes; try { dataSource.open(dataSpec); - bytes = TestUtil.readToEnd(dataSource); + bytes = Util.readToEnd(dataSource); } catch (IOException e) { throw new IOException("Opening/reading cache failed: " + dataSpec, e); } finally { diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java index ea423660f4..f2ead0485f 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer2.testutil; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; import android.content.Context; import android.database.sqlite.SQLiteDatabase; @@ -53,7 +52,6 @@ import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.ByteBuffer; -import java.util.Arrays; import java.util.Random; import java.util.concurrent.TimeoutException; import org.checkerframework.checker.nullness.qual.EnsuresNonNull; @@ -77,52 +75,6 @@ public class TestUtil { private TestUtil() {} - /** - * Given an open {@link DataSource}, repeatedly calls {@link DataSource#read(byte[], int, int)} - * until {@link C#RESULT_END_OF_INPUT} is returned. - * - * @param dataSource The source from which to read. - * @return The concatenation of all read data. - * @throws IOException If an error occurs reading from the source. - */ - public static byte[] readToEnd(DataSource dataSource) throws IOException { - byte[] data = new byte[1024]; - int position = 0; - int bytesRead = 0; - while (bytesRead != C.RESULT_END_OF_INPUT) { - if (position == data.length) { - data = Arrays.copyOf(data, data.length * 2); - } - bytesRead = dataSource.read(data, position, data.length - position); - if (bytesRead != C.RESULT_END_OF_INPUT) { - position += bytesRead; - } - } - return Arrays.copyOf(data, position); - } - - /** - * Given an open {@link DataSource}, repeatedly calls {@link DataSource#read(byte[], int, int)} - * until exactly {@code length} bytes have been read. - * - * @param dataSource The source from which to read. - * @return The read data. - * @throws IOException If an error occurs reading from the source. - */ - public static byte[] readExactly(DataSource dataSource, int length) throws IOException { - byte[] data = new byte[length]; - int position = 0; - while (position < length) { - int bytesRead = dataSource.read(data, position, data.length - position); - if (bytesRead == C.RESULT_END_OF_INPUT) { - fail("Not enough data could be read: " + position + " < " + length); - } else { - position += bytesRead; - } - } - return data; - } - /** * Equivalent to {@code buildTestData(length, length)}. * @@ -271,7 +223,7 @@ public class TestUtil { try { long length = dataSource.open(dataSpec); assertThat(length).isEqualTo(expectKnownLength ? expectedData.length : C.LENGTH_UNSET); - byte[] readData = readToEnd(dataSource); + byte[] readData = Util.readToEnd(dataSource); assertThat(readData).isEqualTo(expectedData); } finally { dataSource.close();