# DataSourceContractTest

Artifact: [androidx.media3:media3-test-utils](https://developer.android.com/jetpack/androidx/releases/media3) [View Source](https://cs.android.com/search?q=file:androidx/media3/test/utils/DataSourceContractTest.java+class:androidx.media3.test.utils.DataSourceContractTest)

*** ** * ** ***


```
@UnstableApi
public abstract class DataSourceContractTest
```

<br />

*** ** * ** ***

A collection of contract tests for `https://developer.android.com/reference/androidx/media3/datasource/DataSource` implementations.

Subclasses should only include the logic necessary to construct the DataSource (overriding either `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSource()` or `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSources()`) and allow it to successfully read data (overriding `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getTestResources()`. They shouldn't include any new `https://junit.org/junit4/javadoc/latest/org/junit/Test.html` methods - implementation-specific tests should be in a separate class.

Most implementations should pass all these tests. If necessary, subclasses can disable tests by overriding the `https://junit.org/junit4/javadoc/latest/org/junit/Test.html` method with a no-op implementation. It's recommended (but not required) to also annotate this `https://junit.org/junit4/javadoc/latest/org/junit/Ignore.html` so that JUnit correctly reports the test as skipped/ignored instead of passing.

## Summary

| ### Nested types |
|---|
| `public class https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.FakeTransferListener implements https://developer.android.com/reference/androidx/media3/datasource/TransferListener` A `https://developer.android.com/reference/androidx/media3/datasource/TransferListener` that only keeps track of the transferred bytes. |
| `public final class https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource` Information about a resource that can be used to test the `https://developer.android.com/reference/androidx/media3/datasource/DataSource` instance. |
| `public final class https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource.Builder` Builder for `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource` instances. |

| ### Public fields |
|---|---|
| `final https://developer.android.com/reference/androidx/media3/test/utils/AdditionalFailureInfo` | `@https://junit.org/junit4/javadoc/latest/org/junit/Rule.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#additionalFailureInfo()` |

| ### Public constructors |
|---|
| `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#DataSourceContractTest()()` |

| ### Public methods |
|---|---|
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#dataSpecWithEndPositionOutOfRange_readsToEnd()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#dataSpecWithLength_readExpectedRange()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#dataSpecWithLength_readUntilEndInTwoParts()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#dataSpecWithPositionAndLength_readExpectedRange()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#dataSpecWithPositionAtEndAndLength_readsZeroBytes()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#dataSpecWithPositionAtEnd_readsZeroBytes()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#dataSpecWithPositionOutOfRange_throwsPositionOutOfRangeException()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#dataSpecWithPosition_readUntilEnd()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getResponseHeaders_caseInsensitive()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getResponseHeaders_isEmptyWhileNotOpen()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getResponseHeaders_noNullKeysOrValues()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getResponseHeaders_resourceNotFound_isEmptyWhileNotOpen()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getResponseHeaders_returnsExpectedValues()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getUri_resourceNotFound_returnsNullIfNotOpened()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getUri_returnsExpectedValueOnlyWhileOpen()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#resourceNotFound()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#resourceNotFound_transferListenerCallbacks()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#transferListenerCallbacks()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#unboundedDataSpecWithGzipFlag_readUntilEnd()()` `https://developer.android.com/reference/androidx/media3/datasource/DataSpec#FLAG_ALLOW_GZIP()` should either be ignored by `https://developer.android.com/reference/androidx/media3/datasource/DataSource` implementations, or correctly handled (i.e. the data is decompressed before being returned from `https://developer.android.com/reference/androidx/media3/common/DataReader#read(byte[],int,int)`). |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#unboundedDataSpec_readExpectedBytesWithOffset()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#unboundedDataSpec_readUntilEnd()()` |
| `void` | `@https://junit.org/junit4/javadoc/latest/org/junit/Test.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#uriSchemeIsCaseInsensitive()()` |

| ### Protected methods |
|---|---|
| `https://developer.android.com/reference/androidx/media3/datasource/DataSource` | `@https://checkerframework.org/api/com/google/errorprone/annotations/ForOverride.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSource()()` Creates and returns an instance of the `https://developer.android.com/reference/androidx/media3/datasource/DataSource`. |
| `https://developer.android.com/reference/java/util/List.html<https://developer.android.com/reference/androidx/media3/datasource/DataSource>` | `@https://checkerframework.org/api/com/google/errorprone/annotations/ForOverride.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSources()()` Creates and returns a list of instances of the `https://developer.android.com/reference/androidx/media3/datasource/DataSource`. |
| `https://developer.android.com/reference/java/util/List.html<https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource>` | `@https://checkerframework.org/api/com/google/errorprone/annotations/ForOverride.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getNotFoundResources()()` Returns a non-empty list of `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource` that don't resolve. |
| `https://developer.android.com/reference/android/net/Uri.html` | `@https://checkerframework.org/api/com/google/errorprone/annotations/ForOverride.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getNotFoundUri()()` Returns a `https://developer.android.com/reference/android/net/Uri.html` that doesn't resolve. |
| `abstract https://guava.dev/releases/snapshot-android/api/docs/com/google/common/collect/ImmutableList.html<https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource>` | `@https://checkerframework.org/api/com/google/errorprone/annotations/ForOverride.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getTestResources()()` Returns `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource` instances. |
| `@https://developer.android.com/reference/androidx/annotation/Nullable https://developer.android.com/reference/androidx/media3/datasource/DataSource` | `@https://checkerframework.org/api/com/google/errorprone/annotations/ForOverride.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getTransferListenerDataSource()()` Returns the `https://developer.android.com/reference/androidx/media3/datasource/DataSource` that will be included in the `https://developer.android.com/reference/androidx/media3/datasource/TransferListener` callbacks for the `https://developer.android.com/reference/androidx/media3/datasource/DataSource` most recently created by `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSource()`. |
| `boolean` | `@https://checkerframework.org/api/com/google/errorprone/annotations/ForOverride.html https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#unboundedReadsAreIndefinite()()` Returns whether the `https://developer.android.com/reference/androidx/media3/datasource/DataSource` will continue reading indefinitely for unbounded `https://developer.android.com/reference/androidx/media3/datasource/DataSpec`. |

## Public fields

### additionalFailureInfo

```
@Rule
public final AdditionalFailureInfo additionalFailureInfo
```

## Public constructors

### DataSourceContractTest

```
public DataSourceContractTest()
```

## Public methods

### dataSpecWithEndPositionOutOfRange_readsToEnd

```
@Test
public void dataSpecWithEndPositionOutOfRange_readsToEnd()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### dataSpecWithLength_readExpectedRange

```
@Test
public void dataSpecWithLength_readExpectedRange()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### dataSpecWithLength_readUntilEndInTwoParts

```
@Test
public void dataSpecWithLength_readUntilEndInTwoParts()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### dataSpecWithPositionAndLength_readExpectedRange

```
@Test
public void dataSpecWithPositionAndLength_readExpectedRange()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### dataSpecWithPositionAtEndAndLength_readsZeroBytes

```
@Test
public void dataSpecWithPositionAtEndAndLength_readsZeroBytes()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### dataSpecWithPositionAtEnd_readsZeroBytes

```
@Test
public void dataSpecWithPositionAtEnd_readsZeroBytes()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### dataSpecWithPositionOutOfRange_throwsPositionOutOfRangeException

```
@Test
public void dataSpecWithPositionOutOfRange_throwsPositionOutOfRangeException()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### dataSpecWithPosition_readUntilEnd

```
@Test
public void dataSpecWithPosition_readUntilEnd()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getResponseHeaders_caseInsensitive

```
@Test
public void getResponseHeaders_caseInsensitive()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getResponseHeaders_isEmptyWhileNotOpen

```
@Test
public void getResponseHeaders_isEmptyWhileNotOpen()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getResponseHeaders_noNullKeysOrValues

```
@Test
public void getResponseHeaders_noNullKeysOrValues()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getResponseHeaders_resourceNotFound_isEmptyWhileNotOpen

```
@Test
public void getResponseHeaders_resourceNotFound_isEmptyWhileNotOpen()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getResponseHeaders_returnsExpectedValues

```
@Test
public void getResponseHeaders_returnsExpectedValues()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getUri_resourceNotFound_returnsNullIfNotOpened

```
@Test
public void getUri_resourceNotFound_returnsNullIfNotOpened()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getUri_returnsExpectedValueOnlyWhileOpen

```
@Test
public void getUri_returnsExpectedValueOnlyWhileOpen()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### resourceNotFound

```
@Test
public void resourceNotFound()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### resourceNotFound_transferListenerCallbacks

```
@Test
public void resourceNotFound_transferListenerCallbacks()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### transferListenerCallbacks

```
@Test
public void transferListenerCallbacks()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### unboundedDataSpecWithGzipFlag_readUntilEnd

```
@Test
public void unboundedDataSpecWithGzipFlag_readUntilEnd()
```

`https://developer.android.com/reference/androidx/media3/datasource/DataSpec#FLAG_ALLOW_GZIP()` should either be ignored by `https://developer.android.com/reference/androidx/media3/datasource/DataSource` implementations, or correctly handled (i.e. the data is decompressed before being returned from `https://developer.android.com/reference/androidx/media3/common/DataReader#read(byte[],int,int)`).

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### unboundedDataSpec_readExpectedBytesWithOffset

```
@Test
public void unboundedDataSpec_readExpectedBytesWithOffset()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### unboundedDataSpec_readUntilEnd

```
@Test
public void unboundedDataSpec_readUntilEnd()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### uriSchemeIsCaseInsensitive

```
@Test
public void uriSchemeIsCaseInsensitive()
```

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

## Protected methods

### createDataSource

```
@ForOverride
protected DataSource createDataSource()
```

Creates and returns an instance of the `https://developer.android.com/reference/androidx/media3/datasource/DataSource`.

Only one of `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSource()` and `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSources()` should be implemented.

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### createDataSources

```
@ForOverride
protected List<DataSource> createDataSources()
```

Creates and returns a list of instances of the `https://developer.android.com/reference/androidx/media3/datasource/DataSource`.

Only one of `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSource()` and `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSources()` should be implemented.

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getNotFoundResources

```
@ForOverride
protected List<DataSourceContractTest.TestResource> getNotFoundResources()
```

Returns a non-empty list of `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource` that don't resolve.

This is used to test how a `https://developer.android.com/reference/androidx/media3/datasource/DataSource` handles nonexistent data. Multiple entries and the rest of the `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource` fields can be helpful for situations where the data can be "not found" for different reasons. For example in HTTP, 'server not found' generally results in a failed HTTP connection while 'file not found' generally results in a successful connection with a 404 HTTP error code and some response headers, and the handling code for these two cases may be different (and therefore worth testing separately).

Only one of `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getNotFoundUri()` and `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getNotFoundResources()` should be implemented.

### getNotFoundUri

```
@ForOverride
protected Uri getNotFoundUri()
```

Returns a `https://developer.android.com/reference/android/net/Uri.html` that doesn't resolve.

This is used to test how a `https://developer.android.com/reference/androidx/media3/datasource/DataSource` handles nonexistent data.

Only one of `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getNotFoundUri()` and `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#getNotFoundResources()` should be implemented.

### getTestResources

```
@ForOverride
protected abstract ImmutableList<DataSourceContractTest.TestResource> getTestResources()
```

Returns `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource` instances.

Each resource will be used to exercise the `https://developer.android.com/reference/androidx/media3/datasource/DataSource` instance, allowing different behaviours to be tested. Every `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource#getExpectedBytes()` must be at least 5 bytes.

If multiple resources are returned, it's recommended to disambiguate them using `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest.TestResource.Builder#setName(java.lang.String)`.

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/Exception.html` |   |

### getTransferListenerDataSource

```
@ForOverride
protected @Nullable DataSource getTransferListenerDataSource()
```

Returns the `https://developer.android.com/reference/androidx/media3/datasource/DataSource` that will be included in the `https://developer.android.com/reference/androidx/media3/datasource/TransferListener` callbacks for the `https://developer.android.com/reference/androidx/media3/datasource/DataSource` most recently created by `https://developer.android.com/reference/androidx/media3/test/utils/DataSourceContractTest#createDataSource()`. If it's the same `https://developer.android.com/reference/androidx/media3/datasource/DataSource` then `null` can be returned.

### unboundedReadsAreIndefinite

```
@ForOverride
protected boolean unboundedReadsAreIndefinite()
```

Returns whether the `https://developer.android.com/reference/androidx/media3/datasource/DataSource` will continue reading indefinitely for unbounded `https://developer.android.com/reference/androidx/media3/datasource/DataSpec`.