Enable use of database storage in CachedContentIndex
It's not yet enabled in the SimpleCache layer, however, so this is a no-op change. PiperOrigin-RevId: 233064490
This commit is contained in:
parent
9c3ac92ae8
commit
434b5a3029
@ -102,41 +102,60 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a CachedContentIndex which works on the index file in the given cacheDir.
|
* Creates an instance supporting database storage only.
|
||||||
*
|
*
|
||||||
* @param cacheDir Directory where the index file is kept.
|
* @param databaseProvider Provides the database in which the index is stored.
|
||||||
*/
|
*/
|
||||||
public CachedContentIndex(File cacheDir) {
|
public CachedContentIndex(DatabaseProvider databaseProvider) {
|
||||||
this(cacheDir, null);
|
this(
|
||||||
|
databaseProvider,
|
||||||
|
/* legacyStorageDir= */ null,
|
||||||
|
/* legacyStorageSecretKey= */ null,
|
||||||
|
/* legacyStorageEncrypt= */ false,
|
||||||
|
/* preferLegacyStorage= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a CachedContentIndex which works on the index file in the given cacheDir.
|
* Creates an instance supporting either or both of database and legacy storage.
|
||||||
*
|
*
|
||||||
* @param cacheDir Directory where the index file is kept.
|
* @param databaseProvider Provides the database in which the index is stored, or {@code null} to
|
||||||
* @param secretKey 16 byte AES key for reading and writing the cache index.
|
* use only legacy storage.
|
||||||
|
* @param legacyStorageDir The directory in which any legacy storage is stored, or {@code null} to
|
||||||
|
* use only database storage.
|
||||||
|
* @param legacyStorageSecretKey A 16 byte AES key for reading, and optionally writing, legacy
|
||||||
|
* storage.
|
||||||
|
* @param legacyStorageEncrypt Whether to encrypt when writing to legacy storage. Must be false if
|
||||||
|
* {@code secretKey} is null.
|
||||||
|
* @param preferLegacyStorage Whether to use prefer legacy storage if both storage types are
|
||||||
|
* enabled. This option is only useful for downgrading from database storage back to legacy
|
||||||
|
* storage.
|
||||||
*/
|
*/
|
||||||
public CachedContentIndex(File cacheDir, @Nullable byte[] secretKey) {
|
public CachedContentIndex(
|
||||||
this(cacheDir, secretKey, secretKey != null);
|
@Nullable DatabaseProvider databaseProvider,
|
||||||
}
|
@Nullable File legacyStorageDir,
|
||||||
|
@Nullable byte[] legacyStorageSecretKey,
|
||||||
/**
|
boolean legacyStorageEncrypt,
|
||||||
* Creates a CachedContentIndex which works on the index file in the given cacheDir.
|
boolean preferLegacyStorage) {
|
||||||
*
|
Assertions.checkState(databaseProvider != null || legacyStorageDir != null);
|
||||||
* @param cacheDir Directory where the index file is kept.
|
|
||||||
* @param secretKey 16 byte AES key for reading, and optionally writing, the cache index.
|
|
||||||
* @param encrypt Whether the index will be encrypted when written. Must be false if {@code
|
|
||||||
* secretKey} is null.
|
|
||||||
*/
|
|
||||||
public CachedContentIndex(File cacheDir, @Nullable byte[] secretKey, boolean encrypt) {
|
|
||||||
keyToContent = new HashMap<>();
|
keyToContent = new HashMap<>();
|
||||||
idToKey = new SparseArray<>();
|
idToKey = new SparseArray<>();
|
||||||
removedIds = new SparseBooleanArray();
|
removedIds = new SparseBooleanArray();
|
||||||
Storage atomicFileStorage =
|
Storage databaseStorage =
|
||||||
new AtomicFileStorage(new File(cacheDir, FILE_NAME_ATOMIC), secretKey, encrypt);
|
databaseProvider != null ? new DatabaseStorage(databaseProvider) : null;
|
||||||
// Storage sqliteStorage = new SQLiteStorage(databaseProvider);
|
Storage legacyStorage =
|
||||||
storage = atomicFileStorage;
|
legacyStorageDir != null
|
||||||
previousStorage = null;
|
? new LegacyStorage(
|
||||||
|
new File(legacyStorageDir, FILE_NAME_ATOMIC),
|
||||||
|
legacyStorageSecretKey,
|
||||||
|
legacyStorageEncrypt)
|
||||||
|
: null;
|
||||||
|
if (databaseStorage == null || (legacyStorage != null && preferLegacyStorage)) {
|
||||||
|
storage = legacyStorage;
|
||||||
|
previousStorage = databaseStorage;
|
||||||
|
} else {
|
||||||
|
storage = databaseStorage;
|
||||||
|
previousStorage = legacyStorage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Loads the index file. */
|
/** Loads the index file. */
|
||||||
@ -413,7 +432,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** {@link Storage} implementation that uses an {@link AtomicFile}. */
|
/** {@link Storage} implementation that uses an {@link AtomicFile}. */
|
||||||
private static class AtomicFileStorage implements Storage {
|
private static class LegacyStorage implements Storage {
|
||||||
|
|
||||||
private final boolean encrypt;
|
private final boolean encrypt;
|
||||||
@Nullable private final Cipher cipher;
|
@Nullable private final Cipher cipher;
|
||||||
@ -424,7 +443,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
private boolean changed;
|
private boolean changed;
|
||||||
@Nullable private ReusableBufferedOutputStream bufferedOutputStream;
|
@Nullable private ReusableBufferedOutputStream bufferedOutputStream;
|
||||||
|
|
||||||
public AtomicFileStorage(File file, @Nullable byte[] secretKey, boolean encrypt) {
|
public LegacyStorage(File file, @Nullable byte[] secretKey, boolean encrypt) {
|
||||||
Cipher cipher = null;
|
Cipher cipher = null;
|
||||||
SecretKeySpec secretKeySpec = null;
|
SecretKeySpec secretKeySpec = null;
|
||||||
if (secretKey != null) {
|
if (secretKey != null) {
|
||||||
@ -436,7 +455,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
throw new IllegalStateException(e); // Should never happen.
|
throw new IllegalStateException(e); // Should never happen.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Assertions.checkArgument(!encrypt);
|
Assertions.checkState(!encrypt);
|
||||||
}
|
}
|
||||||
this.encrypt = encrypt;
|
this.encrypt = encrypt;
|
||||||
this.cipher = cipher;
|
this.cipher = cipher;
|
||||||
@ -642,7 +661,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** {@link Storage} implementation that uses an SQL database. */
|
/** {@link Storage} implementation that uses an SQL database. */
|
||||||
private static final class SQLiteStorage implements Storage {
|
private static final class DatabaseStorage implements Storage {
|
||||||
|
|
||||||
private static final String TABLE_NAME = DatabaseProvider.TABLE_PREFIX + "CacheContentMetadata";
|
private static final String TABLE_NAME = DatabaseProvider.TABLE_PREFIX + "CacheContentMetadata";
|
||||||
private static final int TABLE_VERSION = 1;
|
private static final int TABLE_VERSION = 1;
|
||||||
@ -674,7 +693,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
private final DatabaseProvider databaseProvider;
|
private final DatabaseProvider databaseProvider;
|
||||||
private final SparseArray<CachedContent> pendingUpdates;
|
private final SparseArray<CachedContent> pendingUpdates;
|
||||||
|
|
||||||
public SQLiteStorage(DatabaseProvider databaseProvider) {
|
public DatabaseStorage(DatabaseProvider databaseProvider) {
|
||||||
this.databaseProvider = databaseProvider;
|
this.databaseProvider = databaseProvider;
|
||||||
pendingUpdates = new SparseArray<>();
|
pendingUpdates = new SparseArray<>();
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,15 @@ public final class SimpleCache implements Cache {
|
|||||||
* secretKey} is null.
|
* secretKey} is null.
|
||||||
*/
|
*/
|
||||||
public SimpleCache(File cacheDir, CacheEvictor evictor, byte[] secretKey, boolean encrypt) {
|
public SimpleCache(File cacheDir, CacheEvictor evictor, byte[] secretKey, boolean encrypt) {
|
||||||
this(cacheDir, evictor, new CachedContentIndex(cacheDir, secretKey, encrypt));
|
this(
|
||||||
|
cacheDir,
|
||||||
|
evictor,
|
||||||
|
new CachedContentIndex(
|
||||||
|
/* databaseProvider= */ null,
|
||||||
|
cacheDir,
|
||||||
|
secretKey,
|
||||||
|
encrypt,
|
||||||
|
/* preferLegacyStorage= */ true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +19,10 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -73,14 +75,12 @@ public class CachedContentIndexTest {
|
|||||||
0, 0, 0, 0, 0, 0, 10, 0, // original_content_length
|
0, 0, 0, 0, 0, 0, 10, 0, // original_content_length
|
||||||
0x12, 0x15, 0x66, (byte) 0x8A // hashcode_of_CachedContent_array
|
0x12, 0x15, 0x66, (byte) 0x8A // hashcode_of_CachedContent_array
|
||||||
};
|
};
|
||||||
private CachedContentIndex index;
|
|
||||||
private File cacheDir;
|
private File cacheDir;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
cacheDir =
|
cacheDir =
|
||||||
Util.createTempDirectory(RuntimeEnvironment.application, "ExoPlayerTest");
|
Util.createTempDirectory(RuntimeEnvironment.application, "ExoPlayerTest");
|
||||||
index = new CachedContentIndex(cacheDir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -94,6 +94,8 @@ public class CachedContentIndexTest {
|
|||||||
final String key2 = "key2";
|
final String key2 = "key2";
|
||||||
final String key3 = "key3";
|
final String key3 = "key3";
|
||||||
|
|
||||||
|
CachedContentIndex index = newInstance();
|
||||||
|
|
||||||
// Add two CachedContents with add methods
|
// Add two CachedContents with add methods
|
||||||
CachedContent cachedContent1 = index.getOrAdd(key1);
|
CachedContent cachedContent1 = index.getOrAdd(key1);
|
||||||
CachedContent cachedContent2 = index.getOrAdd(key2);
|
CachedContent cachedContent2 = index.getOrAdd(key2);
|
||||||
@ -145,12 +147,14 @@ public class CachedContentIndexTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStoreAndLoad() throws Exception {
|
public void testLegacyStoreAndLoad() throws Exception {
|
||||||
assertStoredAndLoadedEqual(index, new CachedContentIndex(cacheDir));
|
assertStoredAndLoadedEqual(newLegacyInstance(), newLegacyInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadV1() throws Exception {
|
public void testLegacyLoadV1() throws Exception {
|
||||||
|
CachedContentIndex index = newLegacyInstance();
|
||||||
|
|
||||||
FileOutputStream fos =
|
FileOutputStream fos =
|
||||||
new FileOutputStream(new File(cacheDir, CachedContentIndex.FILE_NAME_ATOMIC));
|
new FileOutputStream(new File(cacheDir, CachedContentIndex.FILE_NAME_ATOMIC));
|
||||||
fos.write(testIndexV1File);
|
fos.write(testIndexV1File);
|
||||||
@ -169,7 +173,9 @@ public class CachedContentIndexTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadV2() throws Exception {
|
public void testLegacyLoadV2() throws Exception {
|
||||||
|
CachedContentIndex index = newLegacyInstance();
|
||||||
|
|
||||||
FileOutputStream fos =
|
FileOutputStream fos =
|
||||||
new FileOutputStream(new File(cacheDir, CachedContentIndex.FILE_NAME_ATOMIC));
|
new FileOutputStream(new File(cacheDir, CachedContentIndex.FILE_NAME_ATOMIC));
|
||||||
fos.write(testIndexV2File);
|
fos.write(testIndexV2File);
|
||||||
@ -190,6 +196,7 @@ public class CachedContentIndexTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAssignIdForKeyAndGetKeyForId() {
|
public void testAssignIdForKeyAndGetKeyForId() {
|
||||||
|
CachedContentIndex index = newInstance();
|
||||||
final String key1 = "key1";
|
final String key1 = "key1";
|
||||||
final String key2 = "key2";
|
final String key2 = "key2";
|
||||||
int id1 = index.assignIdForKey(key1);
|
int id1 = index.assignIdForKey(key1);
|
||||||
@ -214,12 +221,11 @@ public class CachedContentIndexTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncryption() throws Exception {
|
public void testLegacyEncryption() throws Exception {
|
||||||
byte[] key = "Bar12345Bar12345".getBytes(C.UTF8_NAME); // 128 bit key
|
byte[] key = "Bar12345Bar12345".getBytes(C.UTF8_NAME); // 128 bit key
|
||||||
byte[] key2 = "Foo12345Foo12345".getBytes(C.UTF8_NAME); // 128 bit key
|
byte[] key2 = "Foo12345Foo12345".getBytes(C.UTF8_NAME); // 128 bit key
|
||||||
|
|
||||||
assertStoredAndLoadedEqual(
|
assertStoredAndLoadedEqual(newLegacyInstance(key), newLegacyInstance(key));
|
||||||
new CachedContentIndex(cacheDir, key), new CachedContentIndex(cacheDir, key));
|
|
||||||
|
|
||||||
// Rename the index file from the test above
|
// Rename the index file from the test above
|
||||||
File file1 = new File(cacheDir, CachedContentIndex.FILE_NAME_ATOMIC);
|
File file1 = new File(cacheDir, CachedContentIndex.FILE_NAME_ATOMIC);
|
||||||
@ -227,8 +233,7 @@ public class CachedContentIndexTest {
|
|||||||
assertThat(file1.renameTo(file2)).isTrue();
|
assertThat(file1.renameTo(file2)).isTrue();
|
||||||
|
|
||||||
// Write a new index file
|
// Write a new index file
|
||||||
assertStoredAndLoadedEqual(
|
assertStoredAndLoadedEqual(newLegacyInstance(key), newLegacyInstance(key));
|
||||||
new CachedContentIndex(cacheDir, key), new CachedContentIndex(cacheDir, key));
|
|
||||||
|
|
||||||
assertThat(file1.length()).isEqualTo(file2.length());
|
assertThat(file1.length()).isEqualTo(file2.length());
|
||||||
// Assert file content is different
|
// Assert file content is different
|
||||||
@ -240,8 +245,7 @@ public class CachedContentIndexTest {
|
|||||||
|
|
||||||
boolean threw = false;
|
boolean threw = false;
|
||||||
try {
|
try {
|
||||||
assertStoredAndLoadedEqual(
|
assertStoredAndLoadedEqual(newLegacyInstance(key), newLegacyInstance(key2));
|
||||||
new CachedContentIndex(cacheDir, key), new CachedContentIndex(cacheDir, key2));
|
|
||||||
} catch (AssertionError e) {
|
} catch (AssertionError e) {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
@ -250,8 +254,7 @@ public class CachedContentIndexTest {
|
|||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
assertStoredAndLoadedEqual(
|
assertStoredAndLoadedEqual(newLegacyInstance(key), newLegacyInstance());
|
||||||
new CachedContentIndex(cacheDir, key), new CachedContentIndex(cacheDir));
|
|
||||||
} catch (AssertionError e) {
|
} catch (AssertionError e) {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
@ -260,18 +263,18 @@ public class CachedContentIndexTest {
|
|||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
// Non encrypted index file can be read even when encryption key provided.
|
// Non encrypted index file can be read even when encryption key provided.
|
||||||
assertStoredAndLoadedEqual(
|
assertStoredAndLoadedEqual(newLegacyInstance(), newLegacyInstance(key));
|
||||||
new CachedContentIndex(cacheDir), new CachedContentIndex(cacheDir, key));
|
|
||||||
|
|
||||||
// Test multiple store() calls
|
// Test multiple store() calls
|
||||||
CachedContentIndex index = new CachedContentIndex(cacheDir, key);
|
CachedContentIndex index = newLegacyInstance(key);
|
||||||
index.getOrAdd("key3");
|
index.getOrAdd("key3");
|
||||||
index.store();
|
index.store();
|
||||||
assertStoredAndLoadedEqual(index, new CachedContentIndex(cacheDir, key));
|
assertStoredAndLoadedEqual(index, newLegacyInstance(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveEmptyNotLockedCachedContent() {
|
public void testRemoveEmptyNotLockedCachedContent() {
|
||||||
|
CachedContentIndex index = newInstance();
|
||||||
CachedContent cachedContent = index.getOrAdd("key1");
|
CachedContent cachedContent = index.getOrAdd("key1");
|
||||||
|
|
||||||
index.maybeRemove(cachedContent.key);
|
index.maybeRemove(cachedContent.key);
|
||||||
@ -281,6 +284,8 @@ public class CachedContentIndexTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCantRemoveNotEmptyCachedContent() throws Exception {
|
public void testCantRemoveNotEmptyCachedContent() throws Exception {
|
||||||
|
CachedContentIndex index = newInstance();
|
||||||
|
|
||||||
CachedContent cachedContent = index.getOrAdd("key1");
|
CachedContent cachedContent = index.getOrAdd("key1");
|
||||||
long cacheFileLength = 20;
|
long cacheFileLength = 20;
|
||||||
File cacheFile =
|
File cacheFile =
|
||||||
@ -300,6 +305,7 @@ public class CachedContentIndexTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCantRemoveLockedCachedContent() {
|
public void testCantRemoveLockedCachedContent() {
|
||||||
|
CachedContentIndex index = newInstance();
|
||||||
CachedContent cachedContent = index.getOrAdd("key1");
|
CachedContent cachedContent = index.getOrAdd("key1");
|
||||||
cachedContent.setLocked(true);
|
cachedContent.setLocked(true);
|
||||||
|
|
||||||
@ -327,4 +333,21 @@ public class CachedContentIndexTest {
|
|||||||
assertThat(index2.get(key)).isEqualTo(index.get(key));
|
assertThat(index2.get(key)).isEqualTo(index.get(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CachedContentIndex newInstance() {
|
||||||
|
return new CachedContentIndex(TestUtil.getTestDatabaseProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CachedContentIndex newLegacyInstance() {
|
||||||
|
return newLegacyInstance(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CachedContentIndex newLegacyInstance(@Nullable byte[] key) {
|
||||||
|
return new CachedContentIndex(
|
||||||
|
/* databaseProvider= */ null,
|
||||||
|
cacheDir,
|
||||||
|
/* legacyStorageSecretKey= */ key,
|
||||||
|
/* legacyStorageEncrypt= */ key != null,
|
||||||
|
/* preferLegacyStorage= */ true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import static org.mockito.Mockito.anyString;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.extractor.ChunkIndex;
|
import com.google.android.exoplayer2.extractor.ChunkIndex;
|
||||||
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -64,7 +65,7 @@ public final class CachedRegionTrackerTest {
|
|||||||
when(cache.addListener(anyString(), any(Cache.Listener.class))).thenReturn(new TreeSet<>());
|
when(cache.addListener(anyString(), any(Cache.Listener.class))).thenReturn(new TreeSet<>());
|
||||||
tracker = new CachedRegionTracker(cache, CACHE_KEY, CHUNK_INDEX);
|
tracker = new CachedRegionTracker(cache, CACHE_KEY, CHUNK_INDEX);
|
||||||
cacheDir = Util.createTempDirectory(RuntimeEnvironment.application, "ExoPlayerTest");
|
cacheDir = Util.createTempDirectory(RuntimeEnvironment.application, "ExoPlayerTest");
|
||||||
index = new CachedContentIndex(cacheDir);
|
index = new CachedContentIndex(TestUtil.getTestDatabaseProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer2.upstream.cache;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -51,7 +52,7 @@ public class SimpleCacheSpanTest {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
cacheDir =
|
cacheDir =
|
||||||
Util.createTempDirectory(RuntimeEnvironment.application, "ExoPlayerTest");
|
Util.createTempDirectory(RuntimeEnvironment.application, "ExoPlayerTest");
|
||||||
index = new CachedContentIndex(cacheDir);
|
index = new CachedContentIndex(TestUtil.getTestDatabaseProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
|
|||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer2.upstream.cache.Cache.CacheException;
|
import com.google.android.exoplayer2.upstream.cache.Cache.CacheException;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -293,7 +294,8 @@ public class SimpleCacheTest {
|
|||||||
/* Tests https://github.com/google/ExoPlayer/issues/3260 case. */
|
/* Tests https://github.com/google/ExoPlayer/issues/3260 case. */
|
||||||
@Test
|
@Test
|
||||||
public void testExceptionDuringEvictionByLeastRecentlyUsedCacheEvictorNotHang() throws Exception {
|
public void testExceptionDuringEvictionByLeastRecentlyUsedCacheEvictorNotHang() throws Exception {
|
||||||
CachedContentIndex index = Mockito.spy(new CachedContentIndex(cacheDir));
|
CachedContentIndex index =
|
||||||
|
Mockito.spy(new CachedContentIndex(TestUtil.getTestDatabaseProvider()));
|
||||||
SimpleCache simpleCache =
|
SimpleCache simpleCache =
|
||||||
new SimpleCache(cacheDir, new LeastRecentlyUsedCacheEvictor(20), index);
|
new SimpleCache(cacheDir, new LeastRecentlyUsedCacheEvictor(20), index);
|
||||||
|
|
||||||
|
@ -19,11 +19,15 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.database.DatabaseProvider;
|
||||||
|
import com.google.android.exoplayer2.database.DefaultDatabaseProvider;
|
||||||
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
|
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
|
||||||
import com.google.android.exoplayer2.extractor.Extractor;
|
import com.google.android.exoplayer2.extractor.Extractor;
|
||||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||||
@ -155,6 +159,23 @@ public class TestUtil {
|
|||||||
return BitmapFactory.decodeStream(getInputStream(context, fileName));
|
return BitmapFactory.decodeStream(getInputStream(context, fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DatabaseProvider getTestDatabaseProvider() {
|
||||||
|
// Provides an in-memory database.
|
||||||
|
return new DefaultDatabaseProvider(
|
||||||
|
new SQLiteOpenHelper(
|
||||||
|
/* context= */ null, /* name= */ null, /* factory= */ null, /* version= */ 1) {
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that data read from a {@link DataSource} matches {@code expected}.
|
* Asserts that data read from a {@link DataSource} matches {@code expected}.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user