Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
cf726f0c
authored
May 28, 2020
by
olly
Committed by
Oliver Woodman
May 29, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Improve SimpleCacheTest
PiperOrigin-RevId: 313630376
parent
1cfb68bf
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
169 additions
and
212 deletions
library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheTest.java
library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheTest.java
View file @
cf726f0c
...
...
@@ -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
(
cache
Dir
);
Util
.
recursiveDelete
(
test
Dir
);
}
@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,139 +96,180 @@ 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
();
assertThat
(
simpleCache
.
startReadWriteNonBlocking
(
KEY_1
,
0
)).
isNull
();
NavigableSet
<
CacheSpan
>
cachedSpans
=
simpleCache
.
getCachedSpans
(
KEY_1
);
assertThat
(
cachedSpans
.
isEmpty
()).
isTrue
();
assertThat
(
simpleCache
.
getCacheSpace
()).
isEqualTo
(
0
);
assertNoCacheFiles
(
cacheDir
);
// 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
();
Set
<
String
>
cachedKeys
=
simpleCache
.
getKeys
();
assertThat
(
cachedKeys
).
containsExactly
(
KEY_1
);
cachedSpans
=
simpleCache
.
getCachedSpans
(
KEY_1
);
assertThat
(
cachedSpans
).
contains
(
cacheSpan1
);
assertThat
(
simpleCache
.
getCacheSpace
()).
isEqualTo
(
15
);
simpleCache
.
releaseHoleSpan
(
cacheSpan1
);
// Create a new instance pointing to the same directory.
simpleCache
=
getSimpleCache
();
CacheSpan
cacheSpan2
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
assertThat
(
cacheSpan2
.
isCached
).
isTrue
(
);
assert
That
(
cacheSpan2
.
isOpenEnded
()).
isFalse
(
);
assertThat
(
cacheSpan2
.
length
).
isEqualTo
(
15
);
assertCachedDataReadCorrect
(
cacheSpan2
);
// Read the cached data and metadata back.
CacheSpan
fileSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
assert
CachedDataReadCorrect
(
fileSpan
);
assertThat
(
ContentMetadata
.
getRedirectedUri
(
simpleCache
.
getContentMetadata
(
KEY_1
)))
.
isEqualTo
(
Uri
.
parse
(
"https://redirect.google.com"
)
);
}
@Test
public
void
readCacheWithoutReleasingWriteCacheSpan
()
throws
Exception
{
SimpleCache
simpleCache
=
getSimpleCache
();
public
void
newInstance_withExistingCacheInstance_fails
()
{
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
);
// Instantiation should fail because the directory is locked by the first instance.
assertThrows
(
IllegalStateException
.
class
,
this
::
getSimpleCache
);
}
@Test
public
void
setGetContentMetadata
()
throws
Exception
{
public
void
newInstance_withExistingCacheDirectory_resolvesInconsistentState
()
throws
Exception
{
SimpleCache
simpleCache
=
getSimpleCache
();
assertThat
(
ContentMetadata
.
getContentLength
(
simpleCache
.
getContentMetadata
(
KEY_1
)))
.
isEqualTo
(
LENGTH_UNSET
);
CacheSpan
holeSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
addCache
(
simpleCache
,
KEY_1
,
0
,
15
);
simpleCache
.
releaseHoleSpan
(
holeSpan
);
simpleCache
.
removeSpan
(
simpleCache
.
getCachedSpans
(
KEY_1
).
first
());
ContentMetadataMutations
mutations
=
new
ContentMetadataMutations
();
ContentMetadataMutations
.
setContentLength
(
mutations
,
15
);
simpleCache
.
applyContentMetadataMutations
(
KEY_1
,
mutations
);
assertThat
(
ContentMetadata
.
getContentLength
(
simpleCache
.
getContentMetadata
(
KEY_1
)))
.
isEqualTo
(
15
);
// 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
());
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
// 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
();
mutations
=
new
ContentMetadataMutations
();
ContentMetadataMutations
.
setContentLength
(
mutations
,
150
);
simpleCache
.
applyContentMetadataMutations
(
KEY_1
,
mutations
);
assertThat
(
ContentMetadata
.
getContentLength
(
simpleCache
.
getContentMetadata
(
KEY_1
)))
.
isEqualTo
(
150
);
// Create a new instance pointing to the same directory.
simpleCache
=
getEncryptedSimpleCache
(
ENCRYPTED_INDEX_KEY
);
addCache
(
simpleCache
,
KEY_1
,
140
,
10
);
// 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
();
// Check if values are kept after cache is reloaded.
SimpleCache
simpleCache2
=
getSimpleCache
();
assertThat
(
ContentMetadata
.
getContentLength
(
simpleCache2
.
getContentMetadata
(
KEY_1
)))
.
isEqualTo
(
150
);
// Create a new instance pointing to the same directory, with a different key.
simpleCache
=
getEncryptedSimpleCache
(
Util
.
getUtf8Bytes
(
"Foo12345Foo12345"
));
// 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
);
// Cache should be cleared.
assertThat
(
simpleCache
.
getKeys
()).
isEmpty
();
assertNoCacheFiles
(
cacheDir
);
}
@Test
public
void
reload
Cache
()
throws
Exception
{
SimpleCache
simpleCache
=
get
SimpleCache
(
);
public
void
newInstance_withEncryptedIndexAndNoKey_clears
Cache
()
throws
Exception
{
SimpleCache
simpleCache
=
get
EncryptedSimpleCache
(
ENCRYPTED_INDEX_KEY
);
//
write data
CacheSpan
cacheSpan1
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
//
Write data.
CacheSpan
holeSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
addCache
(
simpleCache
,
KEY_1
,
0
,
15
);
simpleCache
.
releaseHoleSpan
(
cacheSpan1
);
simpleCache
.
releaseHoleSpan
(
holeSpan
);
simpleCache
.
release
();
//
Reload cache
//
Create a new instance pointing to the same directory, with no key.
simpleCache
=
getSimpleCache
();
//
read data back
CacheSpan
cacheSpan2
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
assert
CachedDataReadCorrect
(
cacheSpan2
);
//
Cache should be cleared.
assertThat
(
simpleCache
.
getKeys
()).
isEmpty
(
);
assert
NoCacheFiles
(
cacheDir
);
}
@Test
public
void
reloadCacheWithoutRelease
()
throws
Exception
{
public
void
write_oneLock_oneFile_thenRead
()
throws
Exception
{
SimpleCache
simpleCache
=
getSimpleCache
();
// Write data for KEY_1.
CacheSpan
cacheSpan1
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
CacheSpan
holeSpan1
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
assertThat
(
holeSpan1
.
isCached
).
isFalse
();
assertThat
(
holeSpan1
.
isOpenEnded
()).
isTrue
();
addCache
(
simpleCache
,
KEY_1
,
0
,
15
);
simpleCache
.
releaseHoleSpan
(
cacheSpan1
);
// Write and remove data for KEY_2.
CacheSpan
cacheSpan2
=
simpleCache
.
startReadWrite
(
KEY_2
,
0
);
CacheSpan
readSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
assertThat
(
readSpan
.
position
).
isEqualTo
(
0
);
assertThat
(
readSpan
.
length
).
isEqualTo
(
15
);
assertCachedDataReadCorrect
(
readSpan
);
assertThat
(
simpleCache
.
getCacheSpace
()).
isEqualTo
(
15
);
}
@Test
public
void
write_oneLock_twoFiles_thenRead
()
throws
Exception
{
SimpleCache
simpleCache
=
getSimpleCache
();
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
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
);
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
);
CacheSpan
readSpan
=
simpleCache
.
startReadWrite
(
KEY_2
,
0
);
assertThat
(
readSpan
.
length
).
isEqualTo
(
15
);
assertCachedDataReadCorrect
(
readSpan
);
assertThat
(
simpleCache
.
getCacheSpace
()).
isEqualTo
(
15
);
}
// Reload the cache from its new location.
simpleCache
=
new
SimpleCache
(
cacheDir2
,
new
NoOpCacheEvictor
());
@Test
public
void
write_sameKeyLocked_fails
()
throws
Exception
{
SimpleCache
simpleCache
=
getSimpleCache
();
CacheSpan
cacheSpan1
=
simpleCache
.
startReadWrite
(
KEY_1
,
50
);
// Read data back for KEY_1.
CacheSpan
cacheSpan3
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
assertCachedDataReadCorrect
(
cacheSpan3
);
assertThat
(
simpleCache
.
startReadWriteNonBlocking
(
KEY_1
,
25
)).
isNull
();
}
// Check the entry for KEY_2 was removed when the cache was reloaded.
assertThat
(
simpleCache
.
getCachedSpans
(
KEY_2
)).
isEmpty
();
@Test
public
void
applyContentMetadataMutations_setsContentLength
()
throws
Exception
{
SimpleCache
simpleCache
=
getSimpleCache
();
assertThat
(
ContentMetadata
.
getContentLength
(
simpleCache
.
getContentMetadata
(
KEY_1
)))
.
isEqualTo
(
LENGTH_UNSET
);
Util
.
recursiveDelete
(
cacheDir2
);
ContentMetadataMutations
mutations
=
new
ContentMetadataMutations
();
ContentMetadataMutations
.
setContentLength
(
mutations
,
15
);
simpleCache
.
applyContentMetadataMutations
(
KEY_1
,
mutations
);
assertThat
(
ContentMetadata
.
getContentLength
(
simpleCache
.
getContentMetadata
(
KEY_1
)))
.
isEqualTo
(
15
);
}
@Test
...
...
@@ -242,64 +289,6 @@ public class SimpleCacheTest {
}
@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
cach
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
CacheSpan
hol
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
50
,
/* length= */
50
);
simpleCache
.
releaseHoleSpan
(
cach
eSpan
);
simpleCache
.
releaseHoleSpan
(
hol
eSpan
);
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
cach
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
CacheSpan
hol
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
0
,
/* length= */
50
);
simpleCache
.
releaseHoleSpan
(
cach
eSpan
);
simpleCache
.
releaseHoleSpan
(
hol
eSpan
);
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
cach
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
CacheSpan
hol
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
0
,
/* length= */
25
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
25
,
/* length= */
25
);
simpleCache
.
releaseHoleSpan
(
cach
eSpan
);
simpleCache
.
releaseHoleSpan
(
hol
eSpan
);
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
cach
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
CacheSpan
hol
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
0
,
/* length= */
10
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
15
,
/* length= */
35
);
simpleCache
.
releaseHoleSpan
(
cach
eSpan
);
simpleCache
.
releaseHoleSpan
(
hol
eSpan
);
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
cach
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
CacheSpan
hol
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
0
,
/* length= */
25
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
25
,
/* length= */
25
);
simpleCache
.
releaseHoleSpan
(
cach
eSpan
);
simpleCache
.
releaseHoleSpan
(
hol
eSpan
);
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
cach
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
CacheSpan
hol
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
/* position= */
0
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
0
,
/* length= */
10
);
addCache
(
simpleCache
,
KEY_1
,
/* position= */
15
,
/* length= */
35
);
simpleCache
.
releaseHoleSpan
(
cach
eSpan
);
simpleCache
.
releaseHoleSpan
(
hol
eSpan
);
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
exceptionDuring
EvictionByLeastRecentlyUsedCacheEvictorNotHang
()
throws
Exception
{
public
void
exceptionDuring
IndexStore_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
cach
eSpan
=
simpleCache
.
startReadWrite
(
KEY_1
,
0
);
CacheSpan
hol
eSpan
=
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.
}
simpleCache
.
releaseHoleSpan
(
cacheSpan
);
// Adding more content should evict previous content.
assertThrows
(
CacheException
.
class
,
()
->
addCache
(
simpleCache
,
KEY_1
,
15
,
15
));
simpleCache
.
releaseHoleSpan
(
holeSpan
);
// 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
usingReleased
SimpleCacheThrowsException
()
throws
Exception
{
public
void
usingReleased
Cache_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
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment