Start fixing nullness in testutil

PiperOrigin-RevId: 292340530
This commit is contained in:
olly 2020-01-30 15:05:32 +00:00 committed by Oliver Woodman
parent ff822ff9fd
commit 7c8a54c6d0
23 changed files with 175 additions and 112 deletions

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.chunk;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
@ -54,7 +55,7 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
DataSpec dataSpec,
Format trackFormat,
int trackSelectionReason,
Object trackSelectionData,
@Nullable Object trackSelectionData,
long startTimeUs,
long endTimeUs,
long chunkIndex,

View File

@ -821,7 +821,8 @@ public final class ExoPlayerTest {
new FakeMediaSource(timeline, Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT);
FakeRenderer videoRenderer = new FakeRenderer(Builder.VIDEO_FORMAT);
FakeRenderer audioRenderer = new FakeRenderer(Builder.AUDIO_FORMAT);
final FakeTrackSelector trackSelector = new FakeTrackSelector(/* reuse track selection */ true);
final FakeTrackSelector trackSelector =
new FakeTrackSelector(/* mayReuseTrackSelection= */ true);
ActionSchedule disableTrackAction =
new ActionSchedule.Builder("testReuseTrackSelection")
.pause()

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil;
import com.google.android.exoplayer2.util.HandlerWrapper;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* {@link FakeClock} extension which automatically advances time whenever an empty message is
@ -25,7 +26,7 @@ import com.google.android.exoplayer2.util.HandlerWrapper;
*/
public final class AutoAdvancingFakeClock extends FakeClock {
private HandlerWrapper autoAdvancingHandler;
private @MonotonicNonNull HandlerWrapper autoAdvancingHandler;
public AutoAdvancingFakeClock() {
super(/* initialTimeMs= */ 0);

View File

@ -21,6 +21,7 @@ import android.content.Context;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.audio.AudioSink;
import com.google.android.exoplayer2.audio.ForwardingAudioSink;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.File;
import java.io.IOException;
@ -122,7 +123,7 @@ public final class CapturingAudioSink extends ForwardingAudioSink implements Dum
if (WRITE_DUMP) {
File directory = context.getExternalFilesDir(null);
File file = new File(directory, dumpFile);
file.getParentFile().mkdirs();
Assertions.checkStateNotNull(file.getParentFile()).mkdirs();
PrintWriter out = new PrintWriter(file);
out.print(actual);
out.close();

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.testutil;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import java.util.Arrays;
import java.util.Locale;
@ -44,7 +45,7 @@ public final class Dumper {
sb = new StringBuilder();
}
public Dumper add(String field, Object value) {
public Dumper add(String field, @Nullable Object value) {
return addString(field + " = " + value + '\n');
}
@ -53,8 +54,13 @@ public final class Dumper {
return this;
}
public Dumper add(String field, byte[] value) {
String string = String.format(Locale.US, "%s = length %d, hash %X\n", field, value.length,
public Dumper add(String field, @Nullable byte[] value) {
String string =
String.format(
Locale.US,
"%s = length %d, hash %X\n",
field,
value == null ? 0 : value.length,
Arrays.hashCode(value));
return addString(string);
}

View File

@ -209,7 +209,7 @@ public final class ExtractorAsserts {
}
// If the SeekMap is seekable, test seeking in the stream.
SeekMap seekMap = extractorOutput.seekMap;
SeekMap seekMap = Assertions.checkNotNull(extractorOutput.seekMap);
if (seekMap.isSeekable()) {
long durationUs = seekMap.getDurationUs();
for (int j = 0; j < 4; j++) {
@ -361,7 +361,7 @@ public final class ExtractorAsserts {
int i = fileName.lastIndexOf('/');
String path = i >= 0 ? fileName.substring(0, i) : "";
String file = i >= 0 ? fileName.substring(i + 1) : fileName;
return Arrays.asList(context.getResources().getAssets().list(path)).contains(file);
String[] assets = context.getResources().getAssets().list(path);
return assets != null && Arrays.asList(assets).contains(file);
}
}

View File

@ -23,6 +23,7 @@ import com.google.android.exoplayer2.source.chunk.BaseMediaChunkIterator;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Util;
import java.util.Random;
/**
@ -92,7 +93,7 @@ public final class FakeAdaptiveDataSet extends FakeDataSet {
checkInBounds();
String uri = dataSet.getUri(trackGroupIndex);
int chunkIndex = (int) getCurrentIndex();
Segment fakeDataChunk = dataSet.getData(uri).getSegments().get(chunkIndex);
Segment fakeDataChunk = Util.castNonNull(dataSet.getData(uri)).getSegments().get(chunkIndex);
return new DataSpec(
Uri.parse(uri), fakeDataChunk.byteOffset, fakeDataChunk.length, /* key= */ null);
}

View File

@ -28,9 +28,12 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Fake {@link MediaPeriod} that provides tracks from the given {@link TrackGroupArray}. Selecting a
@ -44,7 +47,7 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
@Nullable private final TransferListener transferListener;
private final long durationUs;
private Callback callback;
@MonotonicNonNull private Callback callback;
private ChunkSampleStream<FakeChunkSource>[] sampleStreams;
private SequenceableLoader sequenceableLoader;
@ -81,9 +84,9 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
@Override
@SuppressWarnings("unchecked")
public long selectTracks(
TrackSelection[] selections,
@NullableType TrackSelection[] selections,
boolean[] mayRetainStreamFlags,
SampleStream[] streams,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
long positionUs) {
long returnPositionUs = super.selectTracks(selections, mayRetainStreamFlags, streams,
@ -94,7 +97,8 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
validStreams.add((ChunkSampleStream<FakeChunkSource>) stream);
}
}
this.sampleStreams = validStreams.toArray(newSampleStreamArray(validStreams.size()));
sampleStreams = newSampleStreamArray(validStreams.size());
validStreams.toArray(sampleStreams);
this.sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
return returnPositionUs;
}
@ -162,7 +166,7 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
@Override
public void onContinueLoadingRequested(ChunkSampleStream<FakeChunkSource> source) {
callback.onContinueLoadingRequested(this);
Assertions.checkStateNotNull(callback).onContinueLoadingRequested(this);
}
// We won't assign the array to a variable that erases the generic type, and then write into it.

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil;
import android.os.Handler.Callback;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.HandlerWrapper;
import java.util.ArrayList;
@ -90,7 +91,7 @@ public class FakeClock implements Clock {
}
@Override
public HandlerWrapper createHandler(Looper looper, Callback callback) {
public HandlerWrapper createHandler(Looper looper, @Nullable Callback callback) {
return new ClockHandler(looper, callback);
}
@ -119,7 +120,7 @@ public class FakeClock implements Clock {
private final long postTime;
private final HandlerWrapper handler;
private final Runnable runnable;
@Nullable private final Runnable runnable;
private final int message;
public HandlerMessageData(long postTime, HandlerWrapper handler, Runnable runnable) {
@ -155,7 +156,7 @@ public class FakeClock implements Clock {
private final android.os.Handler handler;
public ClockHandler(Looper looper, Callback callback) {
public ClockHandler(Looper looper, @Nullable Callback callback) {
handler = new android.os.Handler(looper, callback);
}
@ -170,7 +171,7 @@ public class FakeClock implements Clock {
}
@Override
public Message obtainMessage(int what, Object obj) {
public Message obtainMessage(int what, @Nullable Object obj) {
return handler.obtainMessage(what, obj);
}
@ -180,7 +181,7 @@ public class FakeClock implements Clock {
}
@Override
public Message obtainMessage(int what, int arg1, int arg2, Object obj) {
public Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
return handler.obtainMessage(what, arg1, arg2, obj);
}
@ -200,7 +201,7 @@ public class FakeClock implements Clock {
}
@Override
public void removeCallbacksAndMessages(Object token) {
public void removeCallbacksAndMessages(@Nullable Object token) {
handler.removeCallbacksAndMessages(token);
}

View File

@ -89,24 +89,28 @@ public class FakeDataSet {
public boolean exceptionCleared;
public int bytesRead;
private Segment(byte[] data, Segment previousSegment) {
private Segment(byte[] data, @Nullable Segment previousSegment) {
this(data, data.length, null, null, previousSegment);
}
private Segment(int length, Segment previousSegment) {
private Segment(int length, @Nullable Segment previousSegment) {
this(null, length, null, null, previousSegment);
}
private Segment(IOException exception, Segment previousSegment) {
private Segment(IOException exception, @Nullable Segment previousSegment) {
this(null, 0, exception, null, previousSegment);
}
private Segment(Runnable action, Segment previousSegment) {
private Segment(Runnable action, @Nullable Segment previousSegment) {
this(null, 0, null, action, previousSegment);
}
private Segment(@Nullable byte[] data, int length, @Nullable IOException exception,
@Nullable Runnable action, Segment previousSegment) {
private Segment(
@Nullable byte[] data,
int length,
@Nullable IOException exception,
@Nullable Runnable action,
@Nullable Segment previousSegment) {
this.exception = exception;
this.action = action;
this.data = data;
@ -125,16 +129,17 @@ public class FakeDataSet {
}
/** Uri of the data or null if this is the default FakeData. */
public final Uri uri;
private final ArrayList<Segment> segments;
private final FakeDataSet dataSet;
/** Uri of the data or null if this is the default FakeData. */
@Nullable public final Uri uri;
private final ArrayList<Segment> segments;
private boolean simulateUnknownLength;
private FakeData(FakeDataSet dataSet, Uri uri) {
private FakeData(FakeDataSet dataSet, @Nullable Uri uri) {
this.dataSet = dataSet;
this.uri = uri;
this.segments = new ArrayList<>();
this.dataSet = dataSet;
}
/** Returns the {@link FakeDataSet} this FakeData belongs to. */
@ -157,7 +162,7 @@ public class FakeDataSet {
* Appends to the underlying data.
*/
public FakeData appendReadData(byte[] data) {
Assertions.checkState(data != null && data.length > 0);
Assertions.checkState(data.length > 0);
segments.add(new Segment(data, getLastSegment()));
return this;
}
@ -213,6 +218,7 @@ public class FakeDataSet {
return simulateUnknownLength;
}
@Nullable
private Segment getLastSegment() {
int count = segments.size();
return count > 0 ? segments.get(count - 1) : null;
@ -221,7 +227,7 @@ public class FakeDataSet {
}
private final HashMap<Uri, FakeData> dataMap;
private FakeData defaultData;
@Nullable private FakeData defaultData;
public FakeDataSet() {
dataMap = new HashMap<>();
@ -266,13 +272,15 @@ public class FakeDataSet {
}
/** Returns the data for the given {@code uri}, or {@code defaultData} if no data is set. */
@Nullable
public FakeData getData(String uri) {
return getData(Uri.parse(uri));
}
/** Returns the data for the given {@code uri}, or {@code defaultData} if no data is set. */
@Nullable
public FakeData getData(Uri uri) {
FakeData data = dataMap.get(uri);
@Nullable FakeData data = dataMap.get(uri);
return data != null ? data : defaultData;
}

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil;
import android.net.Uri;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment;
@ -24,8 +25,10 @@ import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSourceException;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.util.ArrayList;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A fake {@link DataSource} capable of simulating various scenarios. It uses a {@link FakeDataSet}
@ -38,7 +41,7 @@ public class FakeDataSource extends BaseDataSource {
*/
public static class Factory implements DataSource.Factory {
protected FakeDataSet fakeDataSet;
protected @MonotonicNonNull FakeDataSet fakeDataSet;
protected boolean isNetwork;
public final Factory setFakeDataSet(FakeDataSet fakeDataSet) {
@ -53,17 +56,17 @@ public class FakeDataSource extends BaseDataSource {
@Override
public FakeDataSource createDataSource() {
return new FakeDataSource(fakeDataSet, isNetwork);
return new FakeDataSource(Assertions.checkStateNotNull(fakeDataSet), isNetwork);
}
}
private final FakeDataSet fakeDataSet;
private final ArrayList<DataSpec> openedDataSpecs;
private Uri uri;
@Nullable private Uri uri;
private boolean openCalled;
private boolean sourceOpened;
private FakeData fakeData;
@Nullable private FakeData fakeData;
private int currentSegmentIndex;
private long bytesRemaining;
@ -96,10 +99,11 @@ public class FakeDataSource extends BaseDataSource {
openedDataSpecs.add(dataSpec);
transferInitializing(dataSpec);
fakeData = fakeDataSet.getData(uri.toString());
FakeData fakeData = fakeDataSet.getData(dataSpec.uri.toString());
if (fakeData == null) {
throw new IOException("Data not found: " + dataSpec.uri);
}
this.fakeData = fakeData;
long totalLength = 0;
for (Segment segment : fakeData.getSegments()) {
@ -145,6 +149,7 @@ public class FakeDataSource extends BaseDataSource {
public final int read(byte[] buffer, int offset, int readLength) throws IOException {
Assertions.checkState(sourceOpened);
while (true) {
FakeData fakeData = Util.castNonNull(this.fakeData);
if (currentSegmentIndex == fakeData.getSegments().size() || bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT;
}
@ -152,13 +157,13 @@ public class FakeDataSource extends BaseDataSource {
if (current.isErrorSegment()) {
if (!current.exceptionCleared) {
current.exceptionThrown = true;
throw (IOException) current.exception.fillInStackTrace();
throw (IOException) Util.castNonNull(current.exception).fillInStackTrace();
} else {
currentSegmentIndex++;
}
} else if (current.isActionSegment()) {
currentSegmentIndex++;
current.action.run();
Util.castNonNull(current.action).run();
} else {
// Read at most bytesRemaining.
readLength = (int) Math.min(readLength, bytesRemaining);
@ -181,13 +186,14 @@ public class FakeDataSource extends BaseDataSource {
}
}
@Nullable
@Override
public final Uri getUri() {
return uri;
}
@Override
public final void close() throws IOException {
public final void close() {
Assertions.checkState(openCalled);
openCalled = false;
uri = null;

View File

@ -20,12 +20,15 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.content.Context;
import android.util.SparseArray;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.util.Assertions;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A fake {@link ExtractorOutput}.
@ -45,7 +48,7 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
public int numberOfTracks;
public boolean tracksEnded;
public SeekMap seekMap;
public @MonotonicNonNull SeekMap seekMap;
public FakeExtractorOutput() {
trackOutputs = new SparseArray<>();
@ -53,7 +56,7 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
@Override
public FakeTrackOutput track(int id, int type) {
FakeTrackOutput output = trackOutputs.get(id);
@Nullable FakeTrackOutput output = trackOutputs.get(id);
if (output == null) {
assertThat(tracksEnded).isFalse();
numberOfTracks++;
@ -99,10 +102,11 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
assertThat(seekMap).isNull();
} else {
// TODO: Bulk up this check if possible.
assertThat(seekMap).isNotNull();
assertThat(seekMap.getClass()).isEqualTo(expected.seekMap.getClass());
assertThat(seekMap.isSeekable()).isEqualTo(expected.seekMap.isSeekable());
assertThat(seekMap.getSeekPoints(0)).isEqualTo(expected.seekMap.getSeekPoints(0));
SeekMap expectedSeekMap = Assertions.checkNotNull(expected.seekMap);
SeekMap seekMap = Assertions.checkNotNull(this.seekMap);
assertThat(seekMap.getClass()).isEqualTo(expectedSeekMap.getClass());
assertThat(seekMap.isSeekable()).isEqualTo(expectedSeekMap.isSeekable());
assertThat(seekMap.getSeekPoints(0)).isEqualTo(expectedSeekMap.getSeekPoints(0));
}
for (int i = 0; i < numberOfTracks; i++) {
assertThat(trackOutputs.keyAt(i)).isEqualTo(expected.trackOutputs.keyAt(i));
@ -125,7 +129,7 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
if (WRITE_DUMP) {
File file = new File(System.getProperty("user.dir"), "src/test/assets");
file = new File(file, dumpFile);
file.getParentFile().mkdirs();
Assertions.checkStateNotNull(file.getParentFile()).mkdirs();
PrintWriter out = new PrintWriter(file);
out.print(actual);
out.close();

View File

@ -22,7 +22,6 @@ import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import java.io.IOException;
/** Fake {@link MediaChunk}. */
public final class FakeMediaChunk extends MediaChunk {
@ -51,7 +50,7 @@ public final class FakeMediaChunk extends MediaChunk {
}
@Override
public void load() throws IOException, InterruptedException {
public void load() {
// Do nothing.
}

View File

@ -35,6 +35,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* Fake {@link MediaPeriod} that provides tracks from the given {@link TrackGroupArray}. Selecting
@ -149,8 +150,12 @@ public class FakeMediaPeriod implements MediaPeriod {
}
@Override
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
public long selectTracks(
@NullableType TrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
long positionUs) {
assertThat(prepared).isTrue();
sampleStreams.clear();
int rendererCount = selections.length;

View File

@ -84,7 +84,7 @@ public class FakeRenderer extends BaseRenderer {
if (result == C.RESULT_FORMAT_READ) {
formatReadCount++;
assertThat(expectedFormats).contains(formatHolder.format);
onFormatChanged(formatHolder.format);
onFormatChanged(Assertions.checkNotNull(formatHolder.format));
} else if (result == C.RESULT_BUFFER_READ) {
if (buffer.isEndOfStream()) {
isEnded = true;

View File

@ -24,9 +24,7 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
/**
* Fake {@link Timeline} which can be setup to return custom {@link TimelineWindowDefinition}s.
*/
/** Fake {@link Timeline} which can be setup to return custom {@link TimelineWindowDefinition}s. */
public final class FakeTimeline extends Timeline {
/**

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertThat;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.ExtractorInput;
@ -29,6 +30,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A fake {@link TrackOutput}.
@ -39,10 +42,10 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
private final ArrayList<Integer> sampleFlags;
private final ArrayList<Integer> sampleStartOffsets;
private final ArrayList<Integer> sampleEndOffsets;
private final ArrayList<CryptoData> cryptoDatas;
private final ArrayList<@NullableType CryptoData> cryptoDatas;
private byte[] sampleData;
public Format format;
public @MonotonicNonNull Format format;
public FakeTrackOutput() {
sampleData = Util.EMPTY_BYTE_ARRAY;
@ -64,6 +67,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
@Override
public void format(Format format) {
// TODO: Capture and assert all formats (interleaved with the samples).
this.format = format;
}
@ -91,8 +95,12 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
}
@Override
public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset,
CryptoData cryptoData) {
public void sampleMetadata(
long timeUs,
@C.BufferFlags int flags,
int size,
int offset,
@Nullable CryptoData cryptoData) {
if (format == null) {
throw new IllegalStateException("TrackOutput must receive format before sampleMetadata");
}
@ -110,7 +118,8 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
assertThat(sampleTimesUs).hasSize(count);
}
public void assertSample(int index, byte[] data, long timeUs, int flags, CryptoData cryptoData) {
public void assertSample(
int index, byte[] data, long timeUs, int flags, @Nullable CryptoData cryptoData) {
byte[] actualData = getSampleData(index);
assertThat(actualData).isEqualTo(data);
assertThat(sampleTimesUs.get(index)).isEqualTo(timeUs);
@ -131,6 +140,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
return sampleFlags.get(index);
}
@Nullable
public CryptoData getSampleCryptoData(int index) {
return cryptoDatas.get(index);
}
@ -162,6 +172,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
@Override
public void dump(Dumper dumper) {
if (format != null) {
dumper
.startBlock("format")
.add("bitrate", format.bitrate)
@ -190,6 +201,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
dumper.add("data", format.initializationData.get(i));
}
dumper.endBlock().endBlock();
}
dumper.add("total output bytes", sampleData.length);
dumper.add("sample count", sampleTimesUs.size());

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertThat;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.TrackGroup;
@ -109,6 +110,7 @@ public final class FakeTrackSelection implements TrackSelection {
}
@Override
@Nullable
public Object getSelectionData() {
return null;
}

View File

@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer2.testutil;
import com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport;
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
@ -23,6 +25,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** A fake {@link MappingTrackSelector} that returns {@link FakeTrackSelection}s. */
public class FakeTrackSelector extends DefaultTrackSelector {
@ -30,7 +33,7 @@ public class FakeTrackSelector extends DefaultTrackSelector {
private final FakeTrackSelectionFactory fakeTrackSelectionFactory;
public FakeTrackSelector() {
this(false);
this(/* mayReuseTrackSelection= */ false);
}
/**
@ -48,13 +51,14 @@ public class FakeTrackSelector extends DefaultTrackSelector {
}
@Override
protected TrackSelection.Definition[] selectAllTracks(
protected TrackSelection.@NullableType Definition[] selectAllTracks(
MappedTrackInfo mappedTrackInfo,
int[][][] rendererFormatSupports,
int[] rendererMixedMimeTypeAdaptationSupports,
@Capabilities int[][][] rendererFormatSupports,
@AdaptiveSupport int[] rendererMixedMimeTypeAdaptationSupports,
Parameters params) {
int rendererCount = mappedTrackInfo.getRendererCount();
TrackSelection.Definition[] definitions = new TrackSelection.Definition[rendererCount];
TrackSelection.@NullableType Definition[] definitions =
new TrackSelection.Definition[rendererCount];
for (int i = 0; i < rendererCount; i++) {
TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(i);
boolean hasTracks = trackGroupArray.length > 0;
@ -80,7 +84,7 @@ public class FakeTrackSelector extends DefaultTrackSelector {
@Override
public TrackSelection[] createTrackSelections(
TrackSelection.Definition[] definitions, BandwidthMeter bandwidthMeter) {
@NullableType TrackSelection.Definition[] definitions, BandwidthMeter bandwidthMeter) {
TrackSelection[] selections = new TrackSelection[definitions.length];
for (int i = 0; i < definitions.length; i++) {
TrackSelection.Definition definition = definitions[i];

View File

@ -33,9 +33,7 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
/**
* A host activity for performing playback tests.
*/
/** A host activity for performing playback tests. */
public final class HostActivity extends Activity implements SurfaceHolder.Callback {
/**

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil;
import android.os.Looper;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.BasePlayer;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
@ -250,7 +251,7 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
}
@Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) {
public void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters) {
throw new UnsupportedOperationException();
}
@ -260,7 +261,7 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
}
@Override
public void setSeekParameters(SeekParameters seekParameters) {
public void setSeekParameters(@Nullable SeekParameters seekParameters) {
throw new UnsupportedOperationException();
}

View File

@ -18,13 +18,16 @@ package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.offline.Download.State;
import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.util.Util;
import java.util.HashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** A {@link DownloadManager.Listener} for testing. */
public final class TestDownloadManagerListener implements DownloadManager.Listener {
@ -39,7 +42,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
private final CountDownLatch initializedCondition;
private final int timeoutMs;
private CountDownLatch downloadFinishedCondition;
private @MonotonicNonNull CountDownLatch downloadFinishedCondition;
@Download.FailureReason private int failureReason;
public TestDownloadManagerListener(
@ -57,6 +60,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
downloadManager.addListener(this);
}
@Nullable
public Integer pollStateChange(String taskId, long timeoutMs) throws InterruptedException {
return getStateQueue(taskId).poll(timeoutMs, TimeUnit.MILLISECONDS);
}
@ -112,7 +116,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
dummyMainThread.runOnMainThread(
() -> {
if (downloadManager.isIdle()) {
downloadFinishedCondition.countDown();
Util.castNonNull(downloadFinishedCondition).countDown();
}
});
assertThat(downloadFinishedCondition.await(timeoutMs, TimeUnit.MILLISECONDS)).isTrue();
@ -120,10 +124,12 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
private ArrayBlockingQueue<Integer> getStateQueue(String taskId) {
synchronized (downloadStates) {
if (!downloadStates.containsKey(taskId)) {
downloadStates.put(taskId, new ArrayBlockingQueue<>(10));
@Nullable ArrayBlockingQueue<Integer> stateQueue = downloadStates.get(taskId);
if (stateQueue == null) {
stateQueue = new ArrayBlockingQueue<>(10);
downloadStates.put(taskId, stateQueue);
}
return downloadStates.get(taskId);
return stateQueue;
}
}
@ -137,11 +143,11 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
private void assertStateInternal(String taskId, int expectedState, int timeoutMs) {
while (true) {
Integer state = null;
@Nullable Integer state = null;
try {
state = pollStateChange(taskId, timeoutMs);
} catch (InterruptedException e) {
fail(e.getMessage());
fail("Interrupted: " + e.getMessage());
}
if (state != null) {
if (expectedState == state) {

View File

@ -22,6 +22,8 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.util.Assertions;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Unit test for {@link Timeline}. */
public final class TimelineAsserts {
@ -48,7 +50,8 @@ public final class TimelineAsserts {
* @param expectedWindowTags A list of expected window tags. If a tag is unknown or not important
* {@code null} can be passed to skip this window.
*/
public static void assertWindowTags(Timeline timeline, Object... expectedWindowTags) {
public static void assertWindowTags(
Timeline timeline, @NullableType Object... expectedWindowTags) {
Window window = new Window();
assertThat(timeline.getWindowCount()).isEqualTo(expectedWindowTags.length);
for (int i = 0; i < timeline.getWindowCount(); i++) {
@ -140,8 +143,9 @@ public final class TimelineAsserts {
expectedWindowIndex++;
}
assertThat(period.windowIndex).isEqualTo(expectedWindowIndex);
assertThat(timeline.getIndexOfPeriod(period.uid)).isEqualTo(i);
assertThat(timeline.getUidOfPeriod(i)).isEqualTo(period.uid);
Object periodUid = Assertions.checkNotNull(period.uid);
assertThat(timeline.getIndexOfPeriod(periodUid)).isEqualTo(i);
assertThat(timeline.getUidOfPeriod(i)).isEqualTo(periodUid);
for (int repeatMode : REPEAT_MODES) {
if (i < accumulatedPeriodCounts[expectedWindowIndex + 1] - 1) {
assertThat(timeline.getNextPeriodIndex(i, period, window, repeatMode, false))