mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Improve SimpleCacheTest
PiperOrigin-RevId: 313630376
This commit is contained in:
parent
1cfb68bf68
commit
cf726f0c60
@ -18,9 +18,10 @@ package com.google.android.exoplayer2.upstream.cache;
|
||||
import static com.google.android.exoplayer2.C.LENGTH_UNSET;
|
||||
import static com.google.android.exoplayer2.util.Util.toByteArray;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||
@ -32,7 +33,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -44,26 +44,29 @@ import org.mockito.MockitoAnnotations;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SimpleCacheTest {
|
||||
|
||||
private static final byte[] ENCRYPTED_INDEX_KEY = Util.getUtf8Bytes("Bar12345Bar12345");
|
||||
private static final String KEY_1 = "key1";
|
||||
private static final String KEY_2 = "key2";
|
||||
|
||||
private File testDir;
|
||||
private File cacheDir;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
cacheDir = Util.createTempFile(ApplicationProvider.getApplicationContext(), "ExoPlayerTest");
|
||||
// Delete the file. SimpleCache initialization should create a directory with the same name.
|
||||
assertThat(cacheDir.delete()).isTrue();
|
||||
testDir = Util.createTempFile(ApplicationProvider.getApplicationContext(), "SimpleCacheTest");
|
||||
assertThat(testDir.delete()).isTrue();
|
||||
assertThat(testDir.mkdirs()).isTrue();
|
||||
cacheDir = new File(testDir, "cache");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
Util.recursiveDelete(cacheDir);
|
||||
Util.recursiveDelete(testDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheInitialization() {
|
||||
public void newInstance_withEmptyDirectory() {
|
||||
SimpleCache cache = getSimpleCache();
|
||||
|
||||
// Cache initialization should have created a non-negative UID.
|
||||
@ -76,10 +79,13 @@ public class SimpleCacheTest {
|
||||
cache.release();
|
||||
cache = getSimpleCache();
|
||||
assertThat(cache.getUid()).isEqualTo(uid);
|
||||
|
||||
// Cache should be empty.
|
||||
assertThat(cache.getKeys()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheInitializationError() throws IOException {
|
||||
public void newInstance_withConflictingFile_fails() throws IOException {
|
||||
// Creating a file where the cache should be will cause an error during initialization.
|
||||
assertThat(cacheDir.createNewFile()).isTrue();
|
||||
|
||||
@ -90,52 +96,172 @@ public class SimpleCacheTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void committingOneFile() throws Exception {
|
||||
public void newInstance_withExistingCacheDirectory_loadsCachedData() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
|
||||
CacheSpan cacheSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertThat(cacheSpan1.isCached).isFalse();
|
||||
assertThat(cacheSpan1.isOpenEnded()).isTrue();
|
||||
// Write some data and metadata to the cache.
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
ContentMetadataMutations mutations = new ContentMetadataMutations();
|
||||
ContentMetadataMutations.setRedirectedUri(mutations, Uri.parse("https://redirect.google.com"));
|
||||
simpleCache.applyContentMetadataMutations(KEY_1, mutations);
|
||||
simpleCache.release();
|
||||
|
||||
assertThat(simpleCache.startReadWriteNonBlocking(KEY_1, 0)).isNull();
|
||||
// Create a new instance pointing to the same directory.
|
||||
simpleCache = getSimpleCache();
|
||||
|
||||
NavigableSet<CacheSpan> cachedSpans = simpleCache.getCachedSpans(KEY_1);
|
||||
assertThat(cachedSpans.isEmpty()).isTrue();
|
||||
assertThat(simpleCache.getCacheSpace()).isEqualTo(0);
|
||||
// Read the cached data and metadata back.
|
||||
CacheSpan fileSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertCachedDataReadCorrect(fileSpan);
|
||||
assertThat(ContentMetadata.getRedirectedUri(simpleCache.getContentMetadata(KEY_1)))
|
||||
.isEqualTo(Uri.parse("https://redirect.google.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newInstance_withExistingCacheInstance_fails() {
|
||||
getSimpleCache();
|
||||
|
||||
// Instantiation should fail because the directory is locked by the first instance.
|
||||
assertThrows(IllegalStateException.class, this::getSimpleCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newInstance_withExistingCacheDirectory_resolvesInconsistentState() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
simpleCache.removeSpan(simpleCache.getCachedSpans(KEY_1).first());
|
||||
|
||||
// Don't release the cache. This means the index file won't have been written to disk after the
|
||||
// span was removed. Move the cache directory instead, so we can reload it without failing the
|
||||
// folder locking check.
|
||||
File cacheDir2 = new File(testDir, "cache2");
|
||||
cacheDir.renameTo(cacheDir2);
|
||||
|
||||
// Create a new instance pointing to the new directory.
|
||||
simpleCache = new SimpleCache(cacheDir2, new NoOpCacheEvictor());
|
||||
|
||||
// The entry for KEY_1 should have been removed when the cache was reloaded.
|
||||
assertThat(simpleCache.getCachedSpans(KEY_1)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newInstance_withEncryptedIndex() throws Exception {
|
||||
SimpleCache simpleCache = getEncryptedSimpleCache(ENCRYPTED_INDEX_KEY);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
simpleCache.release();
|
||||
|
||||
// Create a new instance pointing to the same directory.
|
||||
simpleCache = getEncryptedSimpleCache(ENCRYPTED_INDEX_KEY);
|
||||
|
||||
// Read the cached data back.
|
||||
CacheSpan fileSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertCachedDataReadCorrect(fileSpan);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newInstance_withEncryptedIndexAndWrongKey_clearsCache() throws Exception {
|
||||
SimpleCache simpleCache = getEncryptedSimpleCache(ENCRYPTED_INDEX_KEY);
|
||||
|
||||
// Write data.
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
simpleCache.release();
|
||||
|
||||
// Create a new instance pointing to the same directory, with a different key.
|
||||
simpleCache = getEncryptedSimpleCache(Util.getUtf8Bytes("Foo12345Foo12345"));
|
||||
|
||||
// Cache should be cleared.
|
||||
assertThat(simpleCache.getKeys()).isEmpty();
|
||||
assertNoCacheFiles(cacheDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newInstance_withEncryptedIndexAndNoKey_clearsCache() throws Exception {
|
||||
SimpleCache simpleCache = getEncryptedSimpleCache(ENCRYPTED_INDEX_KEY);
|
||||
|
||||
// Write data.
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
simpleCache.release();
|
||||
|
||||
// Create a new instance pointing to the same directory, with no key.
|
||||
simpleCache = getSimpleCache();
|
||||
|
||||
// Cache should be cleared.
|
||||
assertThat(simpleCache.getKeys()).isEmpty();
|
||||
assertNoCacheFiles(cacheDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void write_oneLock_oneFile_thenRead() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
|
||||
CacheSpan holeSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertThat(holeSpan1.isCached).isFalse();
|
||||
assertThat(holeSpan1.isOpenEnded()).isTrue();
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
|
||||
Set<String> cachedKeys = simpleCache.getKeys();
|
||||
assertThat(cachedKeys).containsExactly(KEY_1);
|
||||
cachedSpans = simpleCache.getCachedSpans(KEY_1);
|
||||
assertThat(cachedSpans).contains(cacheSpan1);
|
||||
CacheSpan readSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertThat(readSpan.position).isEqualTo(0);
|
||||
assertThat(readSpan.length).isEqualTo(15);
|
||||
assertCachedDataReadCorrect(readSpan);
|
||||
assertThat(simpleCache.getCacheSpace()).isEqualTo(15);
|
||||
|
||||
simpleCache.releaseHoleSpan(cacheSpan1);
|
||||
|
||||
CacheSpan cacheSpan2 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertThat(cacheSpan2.isCached).isTrue();
|
||||
assertThat(cacheSpan2.isOpenEnded()).isFalse();
|
||||
assertThat(cacheSpan2.length).isEqualTo(15);
|
||||
assertCachedDataReadCorrect(cacheSpan2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readCacheWithoutReleasingWriteCacheSpan() throws Exception {
|
||||
public void write_oneLock_twoFiles_thenRead() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
|
||||
CacheSpan cacheSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
CacheSpan cacheSpan2 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertCachedDataReadCorrect(cacheSpan2);
|
||||
simpleCache.releaseHoleSpan(cacheSpan1);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 7);
|
||||
addCache(simpleCache, KEY_1, 7, 8);
|
||||
|
||||
CacheSpan readSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertThat(readSpan1.position).isEqualTo(0);
|
||||
assertThat(readSpan1.length).isEqualTo(7);
|
||||
assertCachedDataReadCorrect(readSpan1);
|
||||
CacheSpan readSpan2 = simpleCache.startReadWrite(KEY_1, 7);
|
||||
assertThat(readSpan2.position).isEqualTo(7);
|
||||
assertThat(readSpan2.length).isEqualTo(8);
|
||||
assertCachedDataReadCorrect(readSpan2);
|
||||
assertThat(simpleCache.getCacheSpace()).isEqualTo(15);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGetContentMetadata() throws Exception {
|
||||
public void write_differentKeyLocked_thenRead() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
CacheSpan holeSpan1 = simpleCache.startReadWrite(KEY_1, 50);
|
||||
|
||||
CacheSpan holeSpan2 = simpleCache.startReadWrite(KEY_2, 50);
|
||||
assertThat(holeSpan1.isCached).isFalse();
|
||||
assertThat(holeSpan1.isOpenEnded()).isTrue();
|
||||
addCache(simpleCache, KEY_2, 0, 15);
|
||||
|
||||
CacheSpan readSpan = simpleCache.startReadWrite(KEY_2, 0);
|
||||
assertThat(readSpan.length).isEqualTo(15);
|
||||
assertCachedDataReadCorrect(readSpan);
|
||||
assertThat(simpleCache.getCacheSpace()).isEqualTo(15);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void write_sameKeyLocked_fails() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
CacheSpan cacheSpan1 = simpleCache.startReadWrite(KEY_1, 50);
|
||||
|
||||
assertThat(simpleCache.startReadWriteNonBlocking(KEY_1, 25)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyContentMetadataMutations_setsContentLength() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
assertThat(ContentMetadata.getContentLength(simpleCache.getContentMetadata(KEY_1)))
|
||||
.isEqualTo(LENGTH_UNSET);
|
||||
|
||||
@ -144,85 +270,6 @@ public class SimpleCacheTest {
|
||||
simpleCache.applyContentMetadataMutations(KEY_1, mutations);
|
||||
assertThat(ContentMetadata.getContentLength(simpleCache.getContentMetadata(KEY_1)))
|
||||
.isEqualTo(15);
|
||||
|
||||
simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
|
||||
mutations = new ContentMetadataMutations();
|
||||
ContentMetadataMutations.setContentLength(mutations, 150);
|
||||
simpleCache.applyContentMetadataMutations(KEY_1, mutations);
|
||||
assertThat(ContentMetadata.getContentLength(simpleCache.getContentMetadata(KEY_1)))
|
||||
.isEqualTo(150);
|
||||
|
||||
addCache(simpleCache, KEY_1, 140, 10);
|
||||
|
||||
simpleCache.release();
|
||||
|
||||
// Check if values are kept after cache is reloaded.
|
||||
SimpleCache simpleCache2 = getSimpleCache();
|
||||
assertThat(ContentMetadata.getContentLength(simpleCache2.getContentMetadata(KEY_1)))
|
||||
.isEqualTo(150);
|
||||
|
||||
// Removing the last span shouldn't cause the length be change next time cache loaded
|
||||
CacheSpan lastSpan = simpleCache2.startReadWrite(KEY_1, 145);
|
||||
simpleCache2.removeSpan(lastSpan);
|
||||
simpleCache2.release();
|
||||
simpleCache2 = getSimpleCache();
|
||||
assertThat(ContentMetadata.getContentLength(simpleCache2.getContentMetadata(KEY_1)))
|
||||
.isEqualTo(150);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reloadCache() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
|
||||
// write data
|
||||
CacheSpan cacheSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(cacheSpan1);
|
||||
simpleCache.release();
|
||||
|
||||
// Reload cache
|
||||
simpleCache = getSimpleCache();
|
||||
|
||||
// read data back
|
||||
CacheSpan cacheSpan2 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertCachedDataReadCorrect(cacheSpan2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reloadCacheWithoutRelease() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
|
||||
// Write data for KEY_1.
|
||||
CacheSpan cacheSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(cacheSpan1);
|
||||
// Write and remove data for KEY_2.
|
||||
CacheSpan cacheSpan2 = simpleCache.startReadWrite(KEY_2, 0);
|
||||
addCache(simpleCache, KEY_2, 0, 15);
|
||||
simpleCache.releaseHoleSpan(cacheSpan2);
|
||||
simpleCache.removeSpan(simpleCache.getCachedSpans(KEY_2).first());
|
||||
|
||||
// Don't release the cache. This means the index file won't have been written to disk after the
|
||||
// data for KEY_2 was removed. Move the cache instead, so we can reload it without failing the
|
||||
// folder locking check.
|
||||
File cacheDir2 =
|
||||
Util.createTempFile(ApplicationProvider.getApplicationContext(), "ExoPlayerTest");
|
||||
cacheDir2.delete();
|
||||
cacheDir.renameTo(cacheDir2);
|
||||
|
||||
// Reload the cache from its new location.
|
||||
simpleCache = new SimpleCache(cacheDir2, new NoOpCacheEvictor());
|
||||
|
||||
// Read data back for KEY_1.
|
||||
CacheSpan cacheSpan3 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertCachedDataReadCorrect(cacheSpan3);
|
||||
|
||||
// Check the entry for KEY_2 was removed when the cache was reloaded.
|
||||
assertThat(simpleCache.getCachedSpans(KEY_2)).isEmpty();
|
||||
|
||||
Util.recursiveDelete(cacheDir2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -241,64 +288,6 @@ public class SimpleCacheTest {
|
||||
assertThat(simpleCache.getCachedSpans(KEY_2)).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encryptedIndex() throws Exception {
|
||||
byte[] key = Util.getUtf8Bytes("Bar12345Bar12345"); // 128 bit key
|
||||
SimpleCache simpleCache = getEncryptedSimpleCache(key);
|
||||
|
||||
// write data
|
||||
CacheSpan cacheSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(cacheSpan1);
|
||||
simpleCache.release();
|
||||
|
||||
// Reload cache
|
||||
simpleCache = getEncryptedSimpleCache(key);
|
||||
|
||||
// read data back
|
||||
CacheSpan cacheSpan2 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
assertCachedDataReadCorrect(cacheSpan2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encryptedIndexWrongKey() throws Exception {
|
||||
byte[] key = Util.getUtf8Bytes("Bar12345Bar12345"); // 128 bit key
|
||||
SimpleCache simpleCache = getEncryptedSimpleCache(key);
|
||||
|
||||
// write data
|
||||
CacheSpan cacheSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(cacheSpan1);
|
||||
simpleCache.release();
|
||||
|
||||
// Reload cache
|
||||
byte[] key2 = Util.getUtf8Bytes("Foo12345Foo12345"); // 128 bit key
|
||||
simpleCache = getEncryptedSimpleCache(key2);
|
||||
|
||||
// Cache should be cleared
|
||||
assertThat(simpleCache.getKeys()).isEmpty();
|
||||
assertNoCacheFiles(cacheDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encryptedIndexLostKey() throws Exception {
|
||||
byte[] key = Util.getUtf8Bytes("Bar12345Bar12345"); // 128 bit key
|
||||
SimpleCache simpleCache = getEncryptedSimpleCache(key);
|
||||
|
||||
// write data
|
||||
CacheSpan cacheSpan1 = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
simpleCache.releaseHoleSpan(cacheSpan1);
|
||||
simpleCache.release();
|
||||
|
||||
// Reload cache
|
||||
simpleCache = getSimpleCache();
|
||||
|
||||
// Cache should be cleared
|
||||
assertThat(simpleCache.getKeys()).isEmpty();
|
||||
assertNoCacheFiles(cacheDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCachedLength_noCachedContent_returnsNegativeMaxHoleLength() {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
@ -320,9 +309,9 @@ public class SimpleCacheTest {
|
||||
@Test
|
||||
public void getCachedLength_returnsNegativeHoleLength() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
CacheSpan cacheSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 50, /* length= */ 50);
|
||||
simpleCache.releaseHoleSpan(cacheSpan);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
|
||||
assertThat(simpleCache.getCachedLength(KEY_1, /* position= */ 0, /* length= */ 100))
|
||||
.isEqualTo(-50);
|
||||
@ -341,9 +330,9 @@ public class SimpleCacheTest {
|
||||
@Test
|
||||
public void getCachedLength_returnsCachedLength() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
CacheSpan cacheSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 0, /* length= */ 50);
|
||||
simpleCache.releaseHoleSpan(cacheSpan);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
|
||||
assertThat(simpleCache.getCachedLength(KEY_1, /* position= */ 0, /* length= */ 100))
|
||||
.isEqualTo(50);
|
||||
@ -364,10 +353,10 @@ public class SimpleCacheTest {
|
||||
@Test
|
||||
public void getCachedLength_withMultipleAdjacentSpans_returnsCachedLength() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
CacheSpan cacheSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 0, /* length= */ 25);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 25, /* length= */ 25);
|
||||
simpleCache.releaseHoleSpan(cacheSpan);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
|
||||
assertThat(simpleCache.getCachedLength(KEY_1, /* position= */ 0, /* length= */ 100))
|
||||
.isEqualTo(50);
|
||||
@ -388,10 +377,10 @@ public class SimpleCacheTest {
|
||||
@Test
|
||||
public void getCachedLength_withMultipleNonAdjacentSpans_returnsCachedLength() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
CacheSpan cacheSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 0, /* length= */ 10);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 15, /* length= */ 35);
|
||||
simpleCache.releaseHoleSpan(cacheSpan);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
|
||||
assertThat(simpleCache.getCachedLength(KEY_1, /* position= */ 0, /* length= */ 100))
|
||||
.isEqualTo(10);
|
||||
@ -430,10 +419,10 @@ public class SimpleCacheTest {
|
||||
@Test
|
||||
public void getCachedBytes_withMultipleAdjacentSpans_returnsCachedBytes() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
CacheSpan cacheSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 0, /* length= */ 25);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 25, /* length= */ 25);
|
||||
simpleCache.releaseHoleSpan(cacheSpan);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
|
||||
assertThat(simpleCache.getCachedBytes(KEY_1, /* position= */ 0, /* length= */ 100))
|
||||
.isEqualTo(50);
|
||||
@ -454,10 +443,10 @@ public class SimpleCacheTest {
|
||||
@Test
|
||||
public void getCachedBytes_withMultipleNonAdjacentSpans_returnsCachedBytes() throws Exception {
|
||||
SimpleCache simpleCache = getSimpleCache();
|
||||
CacheSpan cacheSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, /* position= */ 0);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 0, /* length= */ 10);
|
||||
addCache(simpleCache, KEY_1, /* position= */ 15, /* length= */ 35);
|
||||
simpleCache.releaseHoleSpan(cacheSpan);
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
|
||||
assertThat(simpleCache.getCachedBytes(KEY_1, /* position= */ 0, /* length= */ 100))
|
||||
.isEqualTo(45);
|
||||
@ -477,7 +466,7 @@ public class SimpleCacheTest {
|
||||
|
||||
/* Tests https://github.com/google/ExoPlayer/issues/3260 case. */
|
||||
@Test
|
||||
public void exceptionDuringEvictionByLeastRecentlyUsedCacheEvictorNotHang() throws Exception {
|
||||
public void exceptionDuringIndexStore_doesNotPreventEviction() throws Exception {
|
||||
CachedContentIndex contentIndex =
|
||||
Mockito.spy(new CachedContentIndex(TestUtil.getInMemoryDatabaseProvider()));
|
||||
SimpleCache simpleCache =
|
||||
@ -485,7 +474,7 @@ public class SimpleCacheTest {
|
||||
cacheDir, new LeastRecentlyUsedCacheEvictor(20), contentIndex, /* fileIndex= */ null);
|
||||
|
||||
// Add some content.
|
||||
CacheSpan cacheSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
CacheSpan holeSpan = simpleCache.startReadWrite(KEY_1, 0);
|
||||
addCache(simpleCache, KEY_1, 0, 15);
|
||||
|
||||
// Make index.store() throw exception from now on.
|
||||
@ -496,55 +485,24 @@ public class SimpleCacheTest {
|
||||
.when(contentIndex)
|
||||
.store();
|
||||
|
||||
// Adding more content will make LeastRecentlyUsedCacheEvictor evict previous content.
|
||||
try {
|
||||
addCache(simpleCache, KEY_1, 15, 15);
|
||||
assertWithMessage("Exception was expected").fail();
|
||||
} catch (CacheException e) {
|
||||
// do nothing.
|
||||
}
|
||||
// Adding more content should evict previous content.
|
||||
assertThrows(CacheException.class, () -> addCache(simpleCache, KEY_1, 15, 15));
|
||||
simpleCache.releaseHoleSpan(holeSpan);
|
||||
|
||||
simpleCache.releaseHoleSpan(cacheSpan);
|
||||
|
||||
// Although store() has failed, it should remove the first span and add the new one.
|
||||
// Although store() failed, the first span should have been removed and the new one added.
|
||||
NavigableSet<CacheSpan> cachedSpans = simpleCache.getCachedSpans(KEY_1);
|
||||
assertThat(cachedSpans).isNotEmpty();
|
||||
assertThat(cachedSpans).hasSize(1);
|
||||
assertThat(cachedSpans.pollFirst().position).isEqualTo(15);
|
||||
CacheSpan fileSpan = cachedSpans.first();
|
||||
assertThat(fileSpan.position).isEqualTo(15);
|
||||
assertThat(fileSpan.length).isEqualTo(15);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usingReleasedSimpleCacheThrowsException() throws Exception {
|
||||
public void usingReleasedCache_throwsException() {
|
||||
SimpleCache simpleCache = new SimpleCache(cacheDir, new NoOpCacheEvictor());
|
||||
simpleCache.release();
|
||||
|
||||
try {
|
||||
simpleCache.startReadWriteNonBlocking(KEY_1, 0);
|
||||
assertWithMessage("Exception was expected").fail();
|
||||
} catch (RuntimeException e) {
|
||||
// Expected. Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleSimpleCacheWithSameCacheDirThrowsException() throws Exception {
|
||||
new SimpleCache(cacheDir, new NoOpCacheEvictor());
|
||||
|
||||
try {
|
||||
new SimpleCache(cacheDir, new NoOpCacheEvictor());
|
||||
assertWithMessage("Exception was expected").fail();
|
||||
} catch (IllegalStateException e) {
|
||||
// Expected. Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleSimpleCacheWithSameCacheDirDoesNotThrowsExceptionAfterRelease()
|
||||
throws Exception {
|
||||
SimpleCache simpleCache = new SimpleCache(cacheDir, new NoOpCacheEvictor());
|
||||
simpleCache.release();
|
||||
|
||||
new SimpleCache(cacheDir, new NoOpCacheEvictor());
|
||||
assertThrows(
|
||||
IllegalStateException.class, () -> simpleCache.startReadWriteNonBlocking(KEY_1, 0));
|
||||
}
|
||||
|
||||
private SimpleCache getSimpleCache() {
|
||||
@ -588,8 +546,7 @@ public class SimpleCacheTest {
|
||||
|
||||
private static byte[] generateData(String key, int position, int length) {
|
||||
byte[] bytes = new byte[length];
|
||||
new Random((long) (key.hashCode() ^ position)).nextBytes(bytes);
|
||||
new Random(key.hashCode() ^ position).nextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user