diff --git a/constants.gradle b/constants.gradle index 4107faab4c..dcec53efba 100644 --- a/constants.gradle +++ b/constants.gradle @@ -25,6 +25,9 @@ project.ext { playServicesLibraryVersion = '11.0.2' dexmakerVersion = '1.2' mockitoVersion = '1.9.5' + junitVersion = '4.12' + truthVersion = '0.35' + robolectricVersion = '3.4.2' releaseVersion = 'r2.5.1' modulePrefix = ':' if (gradle.ext.has('exoplayerModulePrefix')) { diff --git a/library/core/build.gradle b/library/core/build.gradle index ecad1e58b5..d50834efd5 100644 --- a/library/core/build.gradle +++ b/library/core/build.gradle @@ -28,6 +28,9 @@ android { androidTest { java.srcDirs += "../../testutils/src/main/java/" } + test { + java.srcDirs += "../../testutils/src/main/java/" + } } buildTypes { @@ -44,6 +47,10 @@ dependencies { androidTestCompile 'com.google.dexmaker:dexmaker:' + dexmakerVersion androidTestCompile 'com.google.dexmaker:dexmaker-mockito:' + dexmakerVersion androidTestCompile 'org.mockito:mockito-core:' + mockitoVersion + testCompile 'com.google.truth:truth:' + truthVersion + testCompile 'junit:junit:' + junitVersion + testCompile 'org.mockito:mockito-core:' + mockitoVersion + testCompile 'org.robolectric:robolectric:' + robolectricVersion } ext { diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/CTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/CTest.java deleted file mode 100644 index ddcdc4ac8a..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/CTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2; - -import android.annotation.SuppressLint; -import android.media.MediaCodec; -import junit.framework.TestCase; - -/** - * Unit test for {@link C}. - */ -public class CTest extends TestCase { - - @SuppressLint("InlinedApi") - public static void testConstants() { - // Sanity check that constant values match those defined by the platform. - assertEquals(MediaCodec.BUFFER_FLAG_KEY_FRAME, C.BUFFER_FLAG_KEY_FRAME); - assertEquals(MediaCodec.BUFFER_FLAG_END_OF_STREAM, C.BUFFER_FLAG_END_OF_STREAM); - assertEquals(MediaCodec.CRYPTO_MODE_AES_CTR, C.CRYPTO_MODE_AES_CTR); - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/FormatTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/FormatTest.java deleted file mode 100644 index bdea08638b..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/FormatTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2; - -import static com.google.android.exoplayer2.C.WIDEVINE_UUID; -import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_MP4; -import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_WEBM; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.media.MediaFormat; -import android.os.Parcel; -import com.google.android.exoplayer2.drm.DrmInitData; -import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; -import com.google.android.exoplayer2.testutil.TestUtil; -import com.google.android.exoplayer2.util.MimeTypes; -import com.google.android.exoplayer2.util.Util; -import com.google.android.exoplayer2.video.ColorInfo; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import junit.framework.TestCase; - -/** - * Unit test for {@link Format}. - */ -public final class FormatTest extends TestCase { - - private static final List INIT_DATA; - static { - byte[] initData1 = new byte[] {1, 2, 3}; - byte[] initData2 = new byte[] {4, 5, 6}; - List initData = new ArrayList<>(); - initData.add(initData1); - initData.add(initData2); - INIT_DATA = Collections.unmodifiableList(initData); - } - - public void testParcelable() { - DrmInitData.SchemeData DRM_DATA_1 = new DrmInitData.SchemeData(WIDEVINE_UUID, "cenc", VIDEO_MP4, - TestUtil.buildTestData(128, 1 /* data seed */)); - DrmInitData.SchemeData DRM_DATA_2 = new DrmInitData.SchemeData(C.UUID_NIL, null, VIDEO_WEBM, - TestUtil.buildTestData(128, 1 /* data seed */)); - DrmInitData drmInitData = new DrmInitData(DRM_DATA_1, DRM_DATA_2); - byte[] projectionData = new byte[] {1, 2, 3}; - Metadata metadata = new Metadata( - new TextInformationFrame("id1", "description1", "value1"), - new TextInformationFrame("id2", "description2", "value2")); - ColorInfo colorInfo = new ColorInfo(C.COLOR_SPACE_BT709, - C.COLOR_RANGE_LIMITED, C.COLOR_TRANSFER_SDR, new byte[] {1, 2, 3, 4, 5, 6, 7}); - - Format formatToParcel = new Format("id", MimeTypes.VIDEO_MP4, MimeTypes.VIDEO_H264, null, - 1024, 2048, 1920, 1080, 24, 90, 2, projectionData, C.STEREO_MODE_TOP_BOTTOM, colorInfo, 6, - 44100, C.ENCODING_PCM_24BIT, 1001, 1002, 0, "und", Format.NO_VALUE, - Format.OFFSET_SAMPLE_RELATIVE, INIT_DATA, drmInitData, metadata); - - Parcel parcel = Parcel.obtain(); - formatToParcel.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - - Format formatFromParcel = Format.CREATOR.createFromParcel(parcel); - assertEquals(formatToParcel, formatFromParcel); - - parcel.recycle(); - } - - public void testConversionToFrameworkMediaFormat() { - if (Util.SDK_INT < 16) { - // Test doesn't apply. - return; - } - - testConversionToFrameworkMediaFormatV16(Format.createVideoSampleFormat(null, "video/xyz", null, - 5000, 102400, 1280, 720, 30, INIT_DATA, null)); - testConversionToFrameworkMediaFormatV16(Format.createVideoSampleFormat(null, "video/xyz", null, - 5000, Format.NO_VALUE, 1280, 720, 30, null, null)); - testConversionToFrameworkMediaFormatV16(Format.createAudioSampleFormat(null, "audio/xyz", null, - 500, 128, 5, 44100, INIT_DATA, null, 0, null)); - testConversionToFrameworkMediaFormatV16(Format.createAudioSampleFormat(null, "audio/xyz", null, - 500, Format.NO_VALUE, 5, 44100, null, null, 0, null)); - testConversionToFrameworkMediaFormatV16(Format.createTextSampleFormat(null, "text/xyz", 0, - "eng")); - testConversionToFrameworkMediaFormatV16(Format.createTextSampleFormat(null, "text/xyz", 0, - null)); - } - - @SuppressLint("InlinedApi") - @TargetApi(16) - private static void testConversionToFrameworkMediaFormatV16(Format in) { - MediaFormat out = in.getFrameworkMediaFormatV16(); - assertEquals(in.sampleMimeType, out.getString(MediaFormat.KEY_MIME)); - assertOptionalV16(out, MediaFormat.KEY_LANGUAGE, in.language); - assertOptionalV16(out, MediaFormat.KEY_MAX_INPUT_SIZE, in.maxInputSize); - assertOptionalV16(out, MediaFormat.KEY_WIDTH, in.width); - assertOptionalV16(out, MediaFormat.KEY_HEIGHT, in.height); - assertOptionalV16(out, MediaFormat.KEY_CHANNEL_COUNT, in.channelCount); - assertOptionalV16(out, MediaFormat.KEY_SAMPLE_RATE, in.sampleRate); - assertOptionalV16(out, MediaFormat.KEY_FRAME_RATE, in.frameRate); - - for (int i = 0; i < in.initializationData.size(); i++) { - byte[] originalData = in.initializationData.get(i); - ByteBuffer frameworkBuffer = out.getByteBuffer("csd-" + i); - byte[] frameworkData = Arrays.copyOf(frameworkBuffer.array(), frameworkBuffer.limit()); - assertTrue(Arrays.equals(originalData, frameworkData)); - } - } - - @TargetApi(16) - private static void assertOptionalV16(MediaFormat format, String key, String value) { - if (value == null) { - assertFalse(format.containsKey(key)); - } else { - assertEquals(value, format.getString(key)); - } - } - - @TargetApi(16) - private static void assertOptionalV16(MediaFormat format, String key, int value) { - if (value == Format.NO_VALUE) { - assertFalse(format.containsKey(key)); - } else { - assertEquals(value, format.getInteger(key)); - } - } - - @TargetApi(16) - private static void assertOptionalV16(MediaFormat format, String key, float value) { - if (value == Format.NO_VALUE) { - assertFalse(format.containsKey(key)); - } else { - assertEquals(value, format.getFloat(key)); - } - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/AtomicFileTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/AtomicFileTest.java deleted file mode 100644 index b4f1d50293..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/AtomicFileTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import android.test.InstrumentationTestCase; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Tests {@link AtomicFile}. - */ -public class AtomicFileTest extends InstrumentationTestCase { - - private File tempFolder; - private File file; - private AtomicFile atomicFile; - - @Override - public void setUp() throws Exception { - tempFolder = Util.createTempDirectory(getInstrumentation().getContext(), "ExoPlayerTest"); - file = new File(tempFolder, "atomicFile"); - atomicFile = new AtomicFile(file); - } - - @Override - protected void tearDown() throws Exception { - Util.recursiveDelete(tempFolder); - } - - public void testDelete() throws Exception { - assertTrue(file.createNewFile()); - atomicFile.delete(); - assertFalse(file.exists()); - } - - public void testWriteRead() throws Exception { - OutputStream output = atomicFile.startWrite(); - output.write(5); - atomicFile.endWrite(output); - output.close(); - - assertRead(); - - output = atomicFile.startWrite(); - output.write(5); - output.write(6); - output.close(); - - assertRead(); - - output = atomicFile.startWrite(); - output.write(6); - - assertRead(); - output.close(); - - output = atomicFile.startWrite(); - - assertRead(); - output.close(); - } - - private void assertRead() throws IOException { - InputStream input = atomicFile.openRead(); - assertEquals(5, input.read()); - assertEquals(-1, input.read()); - input.close(); - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ColorParserTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ColorParserTest.java deleted file mode 100644 index 641b58b0ce..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ColorParserTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import android.graphics.Color; -import android.test.InstrumentationTestCase; - -/** - * Unit test for ColorParser. - */ -public class ColorParserTest extends InstrumentationTestCase { - - // Negative tests. - - public void testParseUnknownColor() { - try { - ColorParser.parseTtmlColor("colorOfAnElectron"); - fail(); - } catch (IllegalArgumentException e) { - // expected - } - } - - public void testParseNull() { - try { - ColorParser.parseTtmlColor(null); - fail(); - } catch (IllegalArgumentException e) { - // expected - } - } - - public void testParseEmpty() { - try { - ColorParser.parseTtmlColor(""); - fail(); - } catch (IllegalArgumentException e) { - // expected - } - } - - public void testRgbColorParsingRgbValuesNegative() { - try { - ColorParser.parseTtmlColor("rgb(-4, 55, 209)"); - fail(); - } catch (IllegalArgumentException e) { - // expected - } - } - - // Positive tests. - - public void testHexCodeParsing() { - assertEquals(Color.WHITE, ColorParser.parseTtmlColor("#FFFFFF")); - assertEquals(Color.WHITE, ColorParser.parseTtmlColor("#FFFFFFFF")); - assertEquals(Color.parseColor("#FF123456"), ColorParser.parseTtmlColor("#123456")); - // Hex colors in ColorParser are RGBA, where-as {@link Color#parseColor} takes ARGB. - assertEquals(Color.parseColor("#00FFFFFF"), ColorParser.parseTtmlColor("#FFFFFF00")); - assertEquals(Color.parseColor("#78123456"), ColorParser.parseTtmlColor("#12345678")); - } - - public void testRgbColorParsing() { - assertEquals(Color.WHITE, ColorParser.parseTtmlColor("rgb(255,255,255)")); - // Spaces are ignored. - assertEquals(Color.WHITE, ColorParser.parseTtmlColor(" rgb ( 255, 255, 255)")); - } - - public void testRgbColorParsingRgbValuesOutOfBounds() { - int outOfBounds = ColorParser.parseTtmlColor("rgb(999, 999, 999)"); - int color = Color.rgb(999, 999, 999); - // Behave like the framework does. - assertEquals(color, outOfBounds); - } - - public void testRgbaColorParsing() { - assertEquals(Color.WHITE, ColorParser.parseTtmlColor("rgba(255,255,255,255)")); - assertEquals(Color.argb(255, 255, 255, 255), - ColorParser.parseTtmlColor("rgba(255,255,255,255)")); - assertEquals(Color.BLACK, ColorParser.parseTtmlColor("rgba(0, 0, 0, 255)")); - assertEquals(Color.argb(0, 0, 0, 255), ColorParser.parseTtmlColor("rgba(0, 0, 255, 0)")); - assertEquals(Color.RED, ColorParser.parseTtmlColor("rgba(255, 0, 0, 255)")); - assertEquals(Color.argb(0, 255, 0, 255), ColorParser.parseTtmlColor("rgba(255, 0, 255, 0)")); - assertEquals(Color.argb(205, 255, 0, 0), ColorParser.parseTtmlColor("rgba(255, 0, 0, 205)")); - } -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/NalUnitUtilTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/NalUnitUtilTest.java deleted file mode 100644 index 286013e83a..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/NalUnitUtilTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import junit.framework.TestCase; - -/** - * Tests for {@link NalUnitUtil}. - */ -public class NalUnitUtilTest extends TestCase { - - private static final int TEST_PARTIAL_NAL_POSITION = 4; - private static final int TEST_NAL_POSITION = 10; - private static final byte[] SPS_TEST_DATA = createByteArray(0x00, 0x00, 0x01, 0x67, 0x4D, 0x40, - 0x16, 0xEC, 0xA0, 0x50, 0x17, 0xFC, 0xB8, 0x08, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, - 0x00, 0x0F, 0x47, 0x8B, 0x16, 0xCB); - private static final int SPS_TEST_DATA_OFFSET = 3; - - public void testFindNalUnit() { - byte[] data = buildTestData(); - - // Should find NAL unit. - int result = NalUnitUtil.findNalUnit(data, 0, data.length, null); - assertEquals(TEST_NAL_POSITION, result); - // Should find NAL unit whose prefix ends one byte before the limit. - result = NalUnitUtil.findNalUnit(data, 0, TEST_NAL_POSITION + 4, null); - assertEquals(TEST_NAL_POSITION, result); - // Shouldn't find NAL unit whose prefix ends at the limit (since the limit is exclusive). - result = NalUnitUtil.findNalUnit(data, 0, TEST_NAL_POSITION + 3, null); - assertEquals(TEST_NAL_POSITION + 3, result); - // Should find NAL unit whose prefix starts at the offset. - result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION, data.length, null); - assertEquals(TEST_NAL_POSITION, result); - // Shouldn't find NAL unit whose prefix starts one byte past the offset. - result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION + 1, data.length, null); - assertEquals(data.length, result); - } - - public void testFindNalUnitWithPrefix() { - byte[] data = buildTestData(); - - // First byte of NAL unit in data1, rest in data2. - boolean[] prefixFlags = new boolean[3]; - byte[] data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1); - byte[] data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, data.length); - int result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); - assertEquals(data1.length, result); - result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); - assertEquals(-1, result); - assertPrefixFlagsCleared(prefixFlags); - - // First three bytes of NAL unit in data1, rest in data2. - prefixFlags = new boolean[3]; - data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 3); - data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 3, data.length); - result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); - assertEquals(data1.length, result); - result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); - assertEquals(-3, result); - assertPrefixFlagsCleared(prefixFlags); - - // First byte of NAL unit in data1, second byte in data2, rest in data3. - prefixFlags = new boolean[3]; - data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1); - data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, TEST_NAL_POSITION + 2); - byte[] data3 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, data.length); - result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); - assertEquals(data1.length, result); - result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); - assertEquals(data2.length, result); - result = NalUnitUtil.findNalUnit(data3, 0, data3.length, prefixFlags); - assertEquals(-2, result); - assertPrefixFlagsCleared(prefixFlags); - - // NAL unit split with one byte in four arrays. - prefixFlags = new boolean[3]; - data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1); - data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, TEST_NAL_POSITION + 2); - data3 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, TEST_NAL_POSITION + 3); - byte[] data4 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, data.length); - result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); - assertEquals(data1.length, result); - result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); - assertEquals(data2.length, result); - result = NalUnitUtil.findNalUnit(data3, 0, data3.length, prefixFlags); - assertEquals(data3.length, result); - result = NalUnitUtil.findNalUnit(data4, 0, data4.length, prefixFlags); - assertEquals(-3, result); - assertPrefixFlagsCleared(prefixFlags); - - // NAL unit entirely in data2. data1 ends with partial prefix. - prefixFlags = new boolean[3]; - data1 = Arrays.copyOfRange(data, 0, TEST_PARTIAL_NAL_POSITION + 2); - data2 = Arrays.copyOfRange(data, TEST_PARTIAL_NAL_POSITION + 2, data.length); - result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); - assertEquals(data1.length, result); - result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); - assertEquals(4, result); - assertPrefixFlagsCleared(prefixFlags); - } - - public void testParseSpsNalUnit() { - NalUnitUtil.SpsData data = NalUnitUtil.parseSpsNalUnit(SPS_TEST_DATA, SPS_TEST_DATA_OFFSET, - SPS_TEST_DATA.length); - assertEquals(640, data.width); - assertEquals(360, data.height); - assertFalse(data.deltaPicOrderAlwaysZeroFlag); - assertTrue(data.frameMbsOnlyFlag); - assertEquals(4, data.frameNumLength); - assertEquals(6, data.picOrderCntLsbLength); - assertEquals(0, data.seqParameterSetId); - assertEquals(1.0f, data.pixelWidthAspectRatio); - assertEquals(0, data.picOrderCountType); - assertFalse(data.separateColorPlaneFlag); - } - - public void testUnescapeDoesNotModifyBuffersWithoutStartCodes() { - assertUnescapeDoesNotModify(""); - assertUnescapeDoesNotModify("0000"); - assertUnescapeDoesNotModify("172BF38A3C"); - assertUnescapeDoesNotModify("000004"); - } - - public void testUnescapeModifiesBuffersWithStartCodes() { - assertUnescapeMatchesExpected("00000301", "000001"); - assertUnescapeMatchesExpected("0000030200000300", "000002000000"); - } - - public void testDiscardToSps() { - assertDiscardToSpsMatchesExpected("", ""); - assertDiscardToSpsMatchesExpected("00", ""); - assertDiscardToSpsMatchesExpected("FFFF000001", ""); - assertDiscardToSpsMatchesExpected("00000001", ""); - assertDiscardToSpsMatchesExpected("00000001FF67", ""); - assertDiscardToSpsMatchesExpected("00000001000167", ""); - assertDiscardToSpsMatchesExpected("0000000167", "0000000167"); - assertDiscardToSpsMatchesExpected("0000000167FF", "0000000167FF"); - assertDiscardToSpsMatchesExpected("0000000167FF", "0000000167FF"); - assertDiscardToSpsMatchesExpected("0000000167FF000000016700", "0000000167FF000000016700"); - assertDiscardToSpsMatchesExpected("000000000167FF", "0000000167FF"); - assertDiscardToSpsMatchesExpected("0001670000000167FF", "0000000167FF"); - assertDiscardToSpsMatchesExpected("FF00000001660000000167FF", "0000000167FF"); - } - - private static byte[] buildTestData() { - byte[] data = new byte[20]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) 0xFF; - } - // Insert an incomplete NAL unit start code. - data[TEST_PARTIAL_NAL_POSITION] = 0; - data[TEST_PARTIAL_NAL_POSITION + 1] = 0; - // Insert a complete NAL unit start code. - data[TEST_NAL_POSITION] = 0; - data[TEST_NAL_POSITION + 1] = 0; - data[TEST_NAL_POSITION + 2] = 1; - data[TEST_NAL_POSITION + 3] = 5; - return data; - } - - private static void assertPrefixFlagsCleared(boolean[] flags) { - assertEquals(false, flags[0] || flags[1] || flags[2]); - } - - private static void assertUnescapeDoesNotModify(String input) { - assertUnescapeMatchesExpected(input, input); - } - - private static void assertUnescapeMatchesExpected(String input, String expectedOutput) { - byte[] bitstream = Util.getBytesFromHexString(input); - byte[] expectedOutputBitstream = Util.getBytesFromHexString(expectedOutput); - int count = NalUnitUtil.unescapeStream(bitstream, bitstream.length); - assertEquals(expectedOutputBitstream.length, count); - byte[] outputBitstream = new byte[count]; - System.arraycopy(bitstream, 0, outputBitstream, 0, count); - assertTrue(Arrays.equals(expectedOutputBitstream, outputBitstream)); - } - - private static void assertDiscardToSpsMatchesExpected(String input, String expectedOutput) { - byte[] bitstream = Util.getBytesFromHexString(input); - byte[] expectedOutputBitstream = Util.getBytesFromHexString(expectedOutput); - ByteBuffer buffer = ByteBuffer.wrap(bitstream); - buffer.position(buffer.limit()); - NalUnitUtil.discardToSps(buffer); - assertTrue(Arrays.equals(expectedOutputBitstream, - Arrays.copyOf(buffer.array(), buffer.position()))); - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableBitArrayTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableBitArrayTest.java deleted file mode 100644 index d7b2b36740..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableBitArrayTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import android.test.MoreAsserts; -import junit.framework.TestCase; - -/** - * Tests for {@link ParsableBitArray}. - */ -public final class ParsableBitArrayTest extends TestCase { - - private static final byte[] TEST_DATA = new byte[] {0x3C, (byte) 0xD2, (byte) 0x5F, (byte) 0x01, - (byte) 0xFF, (byte) 0x14, (byte) 0x60, (byte) 0x99}; - - private ParsableBitArray testArray; - - @Override - public void setUp() { - testArray = new ParsableBitArray(TEST_DATA); - } - - public void testReadAllBytes() { - byte[] bytesRead = new byte[TEST_DATA.length]; - testArray.readBytes(bytesRead, 0, TEST_DATA.length); - MoreAsserts.assertEquals(TEST_DATA, bytesRead); - assertEquals(TEST_DATA.length * 8, testArray.getPosition()); - assertEquals(TEST_DATA.length, testArray.getBytePosition()); - } - - public void testReadBit() { - assertReadBitsToEnd(0); - } - - public void testReadBits() { - assertEquals(getTestDataBits(0, 5), testArray.readBits(5)); - assertEquals(getTestDataBits(5, 0), testArray.readBits(0)); - assertEquals(getTestDataBits(5, 3), testArray.readBits(3)); - assertEquals(getTestDataBits(8, 16), testArray.readBits(16)); - assertEquals(getTestDataBits(24, 3), testArray.readBits(3)); - assertEquals(getTestDataBits(27, 18), testArray.readBits(18)); - assertEquals(getTestDataBits(45, 5), testArray.readBits(5)); - assertEquals(getTestDataBits(50, 14), testArray.readBits(14)); - } - - public void testReadBitsToByteArray() { - byte[] result = new byte[TEST_DATA.length]; - // Test read within byte boundaries. - testArray.readBits(result, 0, 6); - assertEquals(TEST_DATA[0] & 0xFC, result[0]); - // Test read across byte boundaries. - testArray.readBits(result, 0, 8); - assertEquals(((TEST_DATA[0] & 0x03) << 6) | ((TEST_DATA[1] & 0xFC) >> 2), result[0]); - // Test reading across multiple bytes. - testArray.readBits(result, 1, 50); - for (int i = 1; i < 7; i++) { - assertEquals((byte) (((TEST_DATA[i] & 0x03) << 6) | ((TEST_DATA[i + 1] & 0xFC) >> 2)), - result[i]); - } - assertEquals((byte) (TEST_DATA[7] & 0x03) << 6, result[7]); - assertEquals(0, testArray.bitsLeft()); - // Test read last buffer byte across input data bytes. - testArray.setPosition(31); - result[3] = 0; - testArray.readBits(result, 3, 3); - assertEquals((byte) 0xE0, result[3]); - // Test read bits in the middle of a input data byte. - result[0] = 0; - assertEquals(34, testArray.getPosition()); - testArray.readBits(result, 0, 3); - assertEquals((byte) 0xE0, result[0]); - // Test read 0 bits. - testArray.setPosition(32); - result[1] = 0; - testArray.readBits(result, 1, 0); - assertEquals(0, result[1]); - // Test reading a number of bits divisible by 8. - testArray.setPosition(0); - testArray.readBits(result, 0, 16); - assertEquals(TEST_DATA[0], result[0]); - assertEquals(TEST_DATA[1], result[1]); - // Test least significant bits are unmodified. - result[1] = (byte) 0xFF; - testArray.readBits(result, 0, 9); - assertEquals(0x5F, result[0]); - assertEquals(0x7F, result[1]); - } - - public void testRead32BitsByteAligned() { - assertEquals(getTestDataBits(0, 32), testArray.readBits(32)); - assertEquals(getTestDataBits(32, 32), testArray.readBits(32)); - } - - public void testRead32BitsNonByteAligned() { - assertEquals(getTestDataBits(0, 5), testArray.readBits(5)); - assertEquals(getTestDataBits(5, 32), testArray.readBits(32)); - } - - public void testSkipBytes() { - testArray.skipBytes(2); - assertReadBitsToEnd(16); - } - - public void testSkipBitsByteAligned() { - testArray.skipBits(16); - assertReadBitsToEnd(16); - } - - public void testSkipBitsNonByteAligned() { - testArray.skipBits(5); - assertReadBitsToEnd(5); - } - - public void testSetPositionByteAligned() { - testArray.setPosition(16); - assertReadBitsToEnd(16); - } - - public void testSetPositionNonByteAligned() { - testArray.setPosition(5); - assertReadBitsToEnd(5); - } - - public void testByteAlignFromNonByteAligned() { - testArray.setPosition(11); - testArray.byteAlign(); - assertEquals(2, testArray.getBytePosition()); - assertEquals(16, testArray.getPosition()); - assertReadBitsToEnd(16); - } - - public void testByteAlignFromByteAligned() { - testArray.setPosition(16); - testArray.byteAlign(); // Should be a no-op. - assertEquals(2, testArray.getBytePosition()); - assertEquals(16, testArray.getPosition()); - assertReadBitsToEnd(16); - } - - private void assertReadBitsToEnd(int expectedStartPosition) { - int position = testArray.getPosition(); - assertEquals(expectedStartPosition, position); - for (int i = position; i < TEST_DATA.length * 8; i++) { - assertEquals(getTestDataBit(i), testArray.readBit()); - assertEquals(i + 1, testArray.getPosition()); - } - } - - private static int getTestDataBits(int bitPosition, int length) { - int result = 0; - for (int i = 0; i < length; i++) { - result = result << 1; - if (getTestDataBit(bitPosition++)) { - result |= 0x1; - } - } - return result; - } - - private static boolean getTestDataBit(int bitPosition) { - return (TEST_DATA[bitPosition / 8] & (0x80 >>> (bitPosition % 8))) != 0; - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableByteArrayTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableByteArrayTest.java deleted file mode 100644 index 324d668c7a..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableByteArrayTest.java +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.Arrays; -import junit.framework.TestCase; - -/** - * Tests for {@link ParsableByteArray}. - */ -public class ParsableByteArrayTest extends TestCase { - - private static final byte[] TEST_DATA = - new byte[] {0x0F, (byte) 0xFF, (byte) 0x42, (byte) 0x0F, 0x00, 0x00, 0x00, 0x00}; - - private static ParsableByteArray getTestDataArray() { - ParsableByteArray testArray = new ParsableByteArray(TEST_DATA.length); - System.arraycopy(TEST_DATA, 0, testArray.data, 0, TEST_DATA.length); - return testArray; - } - - public void testReadShort() { - testReadShort((short) -1); - testReadShort((short) 0); - testReadShort((short) 1); - testReadShort(Short.MIN_VALUE); - testReadShort(Short.MAX_VALUE); - } - - private static void testReadShort(short testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(4).putShort(testValue).array()); - int readValue = testArray.readShort(); - - // Assert that the value we read was the value we wrote. - assertEquals(testValue, readValue); - // And that the position advanced as expected. - assertEquals(2, testArray.getPosition()); - - // And that skipping back and reading gives the same results. - testArray.skipBytes(-2); - readValue = testArray.readShort(); - assertEquals(testValue, readValue); - assertEquals(2, testArray.getPosition()); - } - - public void testReadInt() { - testReadInt(0); - testReadInt(1); - testReadInt(-1); - testReadInt(Integer.MIN_VALUE); - testReadInt(Integer.MAX_VALUE); - } - - private static void testReadInt(int testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(4).putInt(testValue).array()); - int readValue = testArray.readInt(); - - // Assert that the value we read was the value we wrote. - assertEquals(testValue, readValue); - // And that the position advanced as expected. - assertEquals(4, testArray.getPosition()); - - // And that skipping back and reading gives the same results. - testArray.skipBytes(-4); - readValue = testArray.readInt(); - assertEquals(testValue, readValue); - assertEquals(4, testArray.getPosition()); - } - - public void testReadUnsignedInt() { - testReadUnsignedInt(0); - testReadUnsignedInt(1); - testReadUnsignedInt(Integer.MAX_VALUE); - testReadUnsignedInt(Integer.MAX_VALUE + 1L); - testReadUnsignedInt(0xFFFFFFFFL); - } - - private static void testReadUnsignedInt(long testValue) { - ParsableByteArray testArray = new ParsableByteArray( - Arrays.copyOfRange(ByteBuffer.allocate(8).putLong(testValue).array(), 4, 8)); - long readValue = testArray.readUnsignedInt(); - - // Assert that the value we read was the value we wrote. - assertEquals(testValue, readValue); - // And that the position advanced as expected. - assertEquals(4, testArray.getPosition()); - - // And that skipping back and reading gives the same results. - testArray.skipBytes(-4); - readValue = testArray.readUnsignedInt(); - assertEquals(testValue, readValue); - assertEquals(4, testArray.getPosition()); - } - - public void testReadUnsignedIntToInt() { - testReadUnsignedIntToInt(0); - testReadUnsignedIntToInt(1); - testReadUnsignedIntToInt(Integer.MAX_VALUE); - try { - testReadUnsignedIntToInt(-1); - fail(); - } catch (IllegalStateException e) { - // Expected. - } - try { - testReadUnsignedIntToInt(Integer.MIN_VALUE); - fail(); - } catch (IllegalStateException e) { - // Expected. - } - } - - private static void testReadUnsignedIntToInt(int testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(4).putInt(testValue).array()); - int readValue = testArray.readUnsignedIntToInt(); - - // Assert that the value we read was the value we wrote. - assertEquals(testValue, readValue); - // And that the position advanced as expected. - assertEquals(4, testArray.getPosition()); - - // And that skipping back and reading gives the same results. - testArray.skipBytes(-4); - readValue = testArray.readUnsignedIntToInt(); - assertEquals(testValue, readValue); - assertEquals(4, testArray.getPosition()); - } - - public void testReadUnsignedLongToLong() { - testReadUnsignedLongToLong(0); - testReadUnsignedLongToLong(1); - testReadUnsignedLongToLong(Long.MAX_VALUE); - try { - testReadUnsignedLongToLong(-1); - fail(); - } catch (IllegalStateException e) { - // Expected. - } - try { - testReadUnsignedLongToLong(Long.MIN_VALUE); - fail(); - } catch (IllegalStateException e) { - // Expected. - } - } - - private static void testReadUnsignedLongToLong(long testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(8).putLong(testValue).array()); - long readValue = testArray.readUnsignedLongToLong(); - - // Assert that the value we read was the value we wrote. - assertEquals(testValue, readValue); - // And that the position advanced as expected. - assertEquals(8, testArray.getPosition()); - - // And that skipping back and reading gives the same results. - testArray.skipBytes(-8); - readValue = testArray.readUnsignedLongToLong(); - assertEquals(testValue, readValue); - assertEquals(8, testArray.getPosition()); - } - - public void testReadLong() { - testReadLong(0); - testReadLong(1); - testReadLong(-1); - testReadLong(Long.MIN_VALUE); - testReadLong(Long.MAX_VALUE); - } - - private static void testReadLong(long testValue) { - ParsableByteArray testArray = new ParsableByteArray( - ByteBuffer.allocate(8).putLong(testValue).array()); - long readValue = testArray.readLong(); - - // Assert that the value we read was the value we wrote. - assertEquals(testValue, readValue); - // And that the position advanced as expected. - assertEquals(8, testArray.getPosition()); - - // And that skipping back and reading gives the same results. - testArray.skipBytes(-8); - readValue = testArray.readLong(); - assertEquals(testValue, readValue); - assertEquals(8, testArray.getPosition()); - } - - public void testReadingMovesPosition() { - ParsableByteArray parsableByteArray = getTestDataArray(); - - // Given an array at the start - assertEquals(0, parsableByteArray.getPosition()); - // When reading an integer, the position advances - parsableByteArray.readUnsignedInt(); - assertEquals(4, parsableByteArray.getPosition()); - } - - public void testOutOfBoundsThrows() { - ParsableByteArray parsableByteArray = getTestDataArray(); - - // Given an array at the end - parsableByteArray.readUnsignedLongToLong(); - assertEquals(TEST_DATA.length, parsableByteArray.getPosition()); - // Then reading more data throws. - try { - parsableByteArray.readUnsignedInt(); - fail(); - } catch (Exception e) { - // Expected. - } - } - - public void testModificationsAffectParsableArray() { - ParsableByteArray parsableByteArray = getTestDataArray(); - - // When modifying the wrapped byte array - byte[] data = parsableByteArray.data; - long readValue = parsableByteArray.readUnsignedInt(); - data[0] = (byte) (TEST_DATA[0] + 1); - parsableByteArray.setPosition(0); - // Then the parsed value changes. - assertFalse(parsableByteArray.readUnsignedInt() == readValue); - } - - public void testReadingUnsignedLongWithMsbSetThrows() { - ParsableByteArray parsableByteArray = getTestDataArray(); - - // Given an array with the most-significant bit set on the top byte - byte[] data = parsableByteArray.data; - data[0] = (byte) 0x80; - // Then reading an unsigned long throws. - try { - parsableByteArray.readUnsignedLongToLong(); - fail(); - } catch (Exception e) { - // Expected. - } - } - - public void testReadUnsignedFixedPoint1616() { - ParsableByteArray parsableByteArray = getTestDataArray(); - - // When reading the integer part of a 16.16 fixed point value - int value = parsableByteArray.readUnsignedFixedPoint1616(); - // Then the read value is equal to the array elements interpreted as a short. - assertEquals((0xFF & TEST_DATA[0]) << 8 | (TEST_DATA[1] & 0xFF), value); - assertEquals(4, parsableByteArray.getPosition()); - } - - public void testReadingBytesReturnsCopy() { - ParsableByteArray parsableByteArray = getTestDataArray(); - - // When reading all the bytes back - int length = parsableByteArray.limit(); - assertEquals(TEST_DATA.length, length); - byte[] copy = new byte[length]; - parsableByteArray.readBytes(copy, 0, length); - // Then the array elements are the same. - assertTrue(Arrays.equals(parsableByteArray.data, copy)); - } - - public void testReadLittleEndianLong() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, (byte) 0xFF - }); - assertEquals(0xFF00000000000001L, byteArray.readLittleEndianLong()); - assertEquals(8, byteArray.getPosition()); - } - - public void testReadLittleEndianUnsignedInt() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x10, 0x00, 0x00, (byte) 0xFF - }); - assertEquals(0xFF000010L, byteArray.readLittleEndianUnsignedInt()); - assertEquals(4, byteArray.getPosition()); - } - - public void testReadLittleEndianInt() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x01, 0x00, 0x00, (byte) 0xFF - }); - assertEquals(0xFF000001, byteArray.readLittleEndianInt()); - assertEquals(4, byteArray.getPosition()); - } - - public void testReadLittleEndianUnsignedInt24() { - byte[] data = { 0x01, 0x02, (byte) 0xFF }; - ParsableByteArray byteArray = new ParsableByteArray(data); - assertEquals(0xFF0201, byteArray.readLittleEndianUnsignedInt24()); - assertEquals(3, byteArray.getPosition()); - } - - public void testReadLittleEndianUnsignedShort() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x01, (byte) 0xFF, 0x02, (byte) 0xFF - }); - assertEquals(0xFF01, byteArray.readLittleEndianUnsignedShort()); - assertEquals(2, byteArray.getPosition()); - assertEquals(0xFF02, byteArray.readLittleEndianUnsignedShort()); - assertEquals(4, byteArray.getPosition()); - } - - public void testReadLittleEndianShort() { - ParsableByteArray byteArray = new ParsableByteArray(new byte[] { - 0x01, (byte) 0xFF, 0x02, (byte) 0xFF - }); - assertEquals((short) 0xFF01, byteArray.readLittleEndianShort()); - assertEquals(2, byteArray.getPosition()); - assertEquals((short) 0xFF02, byteArray.readLittleEndianShort()); - assertEquals(4, byteArray.getPosition()); - } - - public void testReadString() { - byte[] data = { - (byte) 0xC3, (byte) 0xA4, (byte) 0x20, - (byte) 0xC3, (byte) 0xB6, (byte) 0x20, - (byte) 0xC2, (byte) 0xAE, (byte) 0x20, - (byte) 0xCF, (byte) 0x80, (byte) 0x20, - (byte) 0xE2, (byte) 0x88, (byte) 0x9A, (byte) 0x20, - (byte) 0xC2, (byte) 0xB1, (byte) 0x20, - (byte) 0xE8, (byte) 0xB0, (byte) 0xA2, (byte) 0x20, - }; - ParsableByteArray byteArray = new ParsableByteArray(data); - assertEquals("ä ö ® π √ ± 谢 ", byteArray.readString(data.length)); - assertEquals(data.length, byteArray.getPosition()); - } - - public void testReadAsciiString() { - byte[] data = new byte[] {'t', 'e', 's', 't'}; - ParsableByteArray testArray = new ParsableByteArray(data); - assertEquals("test", testArray.readString(data.length, Charset.forName("US-ASCII"))); - assertEquals(data.length, testArray.getPosition()); - } - - public void testReadStringOutOfBoundsDoesNotMovePosition() { - byte[] data = { - (byte) 0xC3, (byte) 0xA4, (byte) 0x20 - }; - ParsableByteArray byteArray = new ParsableByteArray(data); - try { - byteArray.readString(data.length + 1); - fail(); - } catch (StringIndexOutOfBoundsException e) { - assertEquals(0, byteArray.getPosition()); - } - } - - public void testReadEmptyString() { - byte[] bytes = new byte[0]; - ParsableByteArray parser = new ParsableByteArray(bytes); - assertNull(parser.readLine()); - } - - public void testReadNullTerminatedStringWithLengths() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', 0, 'b', 'a', 'r', 0 - }; - // Test with lengths that match NUL byte positions. - ParsableByteArray parser = new ParsableByteArray(bytes); - assertEquals("foo", parser.readNullTerminatedString(4)); - assertEquals(4, parser.getPosition()); - assertEquals("bar", parser.readNullTerminatedString(4)); - assertEquals(8, parser.getPosition()); - assertNull(parser.readNullTerminatedString()); - // Test with lengths that do not match NUL byte positions. - parser = new ParsableByteArray(bytes); - assertEquals("fo", parser.readNullTerminatedString(2)); - assertEquals(2, parser.getPosition()); - assertEquals("o", parser.readNullTerminatedString(2)); - assertEquals(4, parser.getPosition()); - assertEquals("bar", parser.readNullTerminatedString(3)); - assertEquals(7, parser.getPosition()); - assertEquals("", parser.readNullTerminatedString(1)); - assertEquals(8, parser.getPosition()); - assertNull(parser.readNullTerminatedString()); - // Test with limit at NUL - parser = new ParsableByteArray(bytes, 4); - assertEquals("foo", parser.readNullTerminatedString(4)); - assertEquals(4, parser.getPosition()); - assertNull(parser.readNullTerminatedString()); - // Test with limit before NUL - parser = new ParsableByteArray(bytes, 3); - assertEquals("foo", parser.readNullTerminatedString(3)); - assertEquals(3, parser.getPosition()); - assertNull(parser.readNullTerminatedString()); - } - - public void testReadNullTerminatedString() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', 0, 'b', 'a', 'r', 0 - }; - // Test normal case. - ParsableByteArray parser = new ParsableByteArray(bytes); - assertEquals("foo", parser.readNullTerminatedString()); - assertEquals(4, parser.getPosition()); - assertEquals("bar", parser.readNullTerminatedString()); - assertEquals(8, parser.getPosition()); - assertNull(parser.readNullTerminatedString()); - // Test with limit at NUL. - parser = new ParsableByteArray(bytes, 4); - assertEquals("foo", parser.readNullTerminatedString()); - assertEquals(4, parser.getPosition()); - assertNull(parser.readNullTerminatedString()); - // Test with limit before NUL. - parser = new ParsableByteArray(bytes, 3); - assertEquals("foo", parser.readNullTerminatedString()); - assertEquals(3, parser.getPosition()); - assertNull(parser.readNullTerminatedString()); - } - - public void testReadNullTerminatedStringWithoutEndingNull() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', 0, 'b', 'a', 'r' - }; - ParsableByteArray parser = new ParsableByteArray(bytes); - assertEquals("foo", parser.readNullTerminatedString()); - assertEquals("bar", parser.readNullTerminatedString()); - assertNull(parser.readNullTerminatedString()); - } - - public void testReadSingleLineWithoutEndingTrail() { - byte[] bytes = new byte[] { - 'f', 'o', 'o' - }; - ParsableByteArray parser = new ParsableByteArray(bytes); - assertEquals("foo", parser.readLine()); - assertNull(parser.readLine()); - } - - public void testReadSingleLineWithEndingLf() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', '\n' - }; - ParsableByteArray parser = new ParsableByteArray(bytes); - assertEquals("foo", parser.readLine()); - assertNull(parser.readLine()); - } - - public void testReadTwoLinesWithCrFollowedByLf() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', '\r', '\n', 'b', 'a', 'r' - }; - ParsableByteArray parser = new ParsableByteArray(bytes); - assertEquals("foo", parser.readLine()); - assertEquals("bar", parser.readLine()); - assertNull(parser.readLine()); - } - - public void testReadThreeLinesWithEmptyLine() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', '\r', '\n', '\r', 'b', 'a', 'r' - }; - ParsableByteArray parser = new ParsableByteArray(bytes); - assertEquals("foo", parser.readLine()); - assertEquals("", parser.readLine()); - assertEquals("bar", parser.readLine()); - assertNull(parser.readLine()); - } - - public void testReadFourLinesWithLfFollowedByCr() { - byte[] bytes = new byte[] { - 'f', 'o', 'o', '\n', '\r', '\r', 'b', 'a', 'r', '\r', '\n' - }; - ParsableByteArray parser = new ParsableByteArray(bytes); - assertEquals("foo", parser.readLine()); - assertEquals("", parser.readLine()); - assertEquals("", parser.readLine()); - assertEquals("bar", parser.readLine()); - assertNull(parser.readLine()); - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArrayTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArrayTest.java deleted file mode 100644 index 294d3d352a..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ParsableNalUnitBitArrayTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray; - -import junit.framework.TestCase; - -/** - * Tests for {@link ParsableNalUnitBitArray}. - */ -public final class ParsableNalUnitBitArrayTest extends TestCase { - - private static final byte[] NO_ESCAPING_TEST_DATA = createByteArray(0, 3, 0, 1, 3, 0, 0); - private static final byte[] ALL_ESCAPING_TEST_DATA = createByteArray(0, 0, 3, 0, 0, 3, 0, 0, 3); - private static final byte[] MIX_TEST_DATA = createByteArray(255, 0, 0, 3, 255, 0, 0, 127); - - public void testReadNoEscaping() { - ParsableNalUnitBitArray array = - new ParsableNalUnitBitArray(NO_ESCAPING_TEST_DATA, 0, NO_ESCAPING_TEST_DATA.length); - assertEquals(0x000300, array.readBits(24)); - assertEquals(0, array.readBits(7)); - assertTrue(array.readBit()); - assertEquals(0x030000, array.readBits(24)); - assertFalse(array.canReadBits(1)); - assertFalse(array.canReadBits(8)); - } - - public void testReadNoEscapingTruncated() { - ParsableNalUnitBitArray array = new ParsableNalUnitBitArray(NO_ESCAPING_TEST_DATA, 0, 4); - assertTrue(array.canReadBits(32)); - array.skipBits(32); - assertFalse(array.canReadBits(1)); - try { - array.readBit(); - fail(); - } catch (Exception e) { - // Expected. - } - } - - public void testReadAllEscaping() { - ParsableNalUnitBitArray array = - new ParsableNalUnitBitArray(ALL_ESCAPING_TEST_DATA, 0, ALL_ESCAPING_TEST_DATA.length); - assertTrue(array.canReadBits(48)); - assertFalse(array.canReadBits(49)); - assertEquals(0, array.readBits(15)); - assertFalse(array.readBit()); - assertEquals(0, array.readBits(17)); - assertEquals(0, array.readBits(15)); - } - - public void testReadMix() { - ParsableNalUnitBitArray array = - new ParsableNalUnitBitArray(MIX_TEST_DATA, 0, MIX_TEST_DATA.length); - assertTrue(array.canReadBits(56)); - assertFalse(array.canReadBits(57)); - assertEquals(127, array.readBits(7)); - assertEquals(2, array.readBits(2)); - assertEquals(3, array.readBits(17)); - assertEquals(126, array.readBits(7)); - assertEquals(127, array.readBits(23)); - assertFalse(array.canReadBits(1)); - } - - public void testReadExpGolomb() { - ParsableNalUnitBitArray array = new ParsableNalUnitBitArray(createByteArray(0x9E), 0, 1); - assertTrue(array.canReadExpGolombCodedNum()); - assertEquals(0, array.readUnsignedExpGolombCodedInt()); - assertEquals(6, array.readUnsignedExpGolombCodedInt()); - assertEquals(0, array.readUnsignedExpGolombCodedInt()); - assertFalse(array.canReadExpGolombCodedNum()); - try { - array.readUnsignedExpGolombCodedInt(); - fail(); - } catch (Exception e) { - // Expected. - } - } - - public void testReadExpGolombWithEscaping() { - ParsableNalUnitBitArray array = - new ParsableNalUnitBitArray(createByteArray(0, 0, 3, 128, 0), 0, 5); - assertFalse(array.canReadExpGolombCodedNum()); - array.skipBit(); - assertTrue(array.canReadExpGolombCodedNum()); - assertEquals(32767, array.readUnsignedExpGolombCodedInt()); - assertFalse(array.canReadBits(1)); - } - - public void testReset() { - ParsableNalUnitBitArray array = new ParsableNalUnitBitArray(createByteArray(0, 0), 0, 2); - assertFalse(array.canReadExpGolombCodedNum()); - assertTrue(array.canReadBits(16)); - assertFalse(array.canReadBits(17)); - array.reset(createByteArray(0, 0, 3, 0), 0, 4); - assertTrue(array.canReadBits(24)); - assertFalse(array.canReadBits(25)); - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ReusableBufferedOutputStreamTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ReusableBufferedOutputStreamTest.java deleted file mode 100644 index beb9e44853..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/ReusableBufferedOutputStreamTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import android.test.MoreAsserts; -import java.io.ByteArrayOutputStream; -import junit.framework.TestCase; - -/** - * Tests {@link ReusableBufferedOutputStream}. - */ -public class ReusableBufferedOutputStreamTest extends TestCase { - - private static final byte[] TEST_DATA_1 = "test data 1".getBytes(); - private static final byte[] TEST_DATA_2 = "2 test data".getBytes(); - - public void testReset() throws Exception { - ByteArrayOutputStream byteArrayOutputStream1 = new ByteArrayOutputStream(1000); - ReusableBufferedOutputStream outputStream = new ReusableBufferedOutputStream( - byteArrayOutputStream1, 1000); - outputStream.write(TEST_DATA_1); - outputStream.close(); - - ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream(1000); - outputStream.reset(byteArrayOutputStream2); - outputStream.write(TEST_DATA_2); - outputStream.close(); - - MoreAsserts.assertEquals(TEST_DATA_1, byteArrayOutputStream1.toByteArray()); - MoreAsserts.assertEquals(TEST_DATA_2, byteArrayOutputStream2.toByteArray()); - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/UriUtilTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/UriUtilTest.java deleted file mode 100644 index 1755c6f70d..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/UriUtilTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import junit.framework.TestCase; - -/** - * Unit tests for {@link UriUtil}. - */ -public class UriUtilTest extends TestCase { - - /** - * Tests normal usage of {@link UriUtil#resolve(String, String)}. - *

- * The test cases are taken from RFC-3986 5.4.1. - */ - public void testResolveNormal() { - String base = "http://a/b/c/d;p?q"; - - assertEquals("g:h", UriUtil.resolve(base, "g:h")); - assertEquals("http://a/b/c/g", UriUtil.resolve(base, "g")); - assertEquals("http://a/b/c/g/", UriUtil.resolve(base, "g/")); - assertEquals("http://a/g", UriUtil.resolve(base, "/g")); - assertEquals("http://g", UriUtil.resolve(base, "//g")); - assertEquals("http://a/b/c/d;p?y", UriUtil.resolve(base, "?y")); - assertEquals("http://a/b/c/g?y", UriUtil.resolve(base, "g?y")); - assertEquals("http://a/b/c/d;p?q#s", UriUtil.resolve(base, "#s")); - assertEquals("http://a/b/c/g#s", UriUtil.resolve(base, "g#s")); - assertEquals("http://a/b/c/g?y#s", UriUtil.resolve(base, "g?y#s")); - assertEquals("http://a/b/c/;x", UriUtil.resolve(base, ";x")); - assertEquals("http://a/b/c/g;x", UriUtil.resolve(base, "g;x")); - assertEquals("http://a/b/c/g;x?y#s", UriUtil.resolve(base, "g;x?y#s")); - assertEquals("http://a/b/c/d;p?q", UriUtil.resolve(base, "")); - assertEquals("http://a/b/c/", UriUtil.resolve(base, ".")); - assertEquals("http://a/b/c/", UriUtil.resolve(base, "./")); - assertEquals("http://a/b/", UriUtil.resolve(base, "..")); - assertEquals("http://a/b/", UriUtil.resolve(base, "../")); - assertEquals("http://a/b/g", UriUtil.resolve(base, "../g")); - assertEquals("http://a/", UriUtil.resolve(base, "../..")); - assertEquals("http://a/", UriUtil.resolve(base, "../../")); - assertEquals("http://a/g", UriUtil.resolve(base, "../../g")); - } - - /** - * Tests abnormal usage of {@link UriUtil#resolve(String, String)}. - *

- * The test cases are taken from RFC-3986 5.4.2. - */ - public void testResolveAbnormal() { - String base = "http://a/b/c/d;p?q"; - - assertEquals("http://a/g", UriUtil.resolve(base, "../../../g")); - assertEquals("http://a/g", UriUtil.resolve(base, "../../../../g")); - - assertEquals("http://a/g", UriUtil.resolve(base, "/./g")); - assertEquals("http://a/g", UriUtil.resolve(base, "/../g")); - assertEquals("http://a/b/c/g.", UriUtil.resolve(base, "g.")); - assertEquals("http://a/b/c/.g", UriUtil.resolve(base, ".g")); - assertEquals("http://a/b/c/g..", UriUtil.resolve(base, "g..")); - assertEquals("http://a/b/c/..g", UriUtil.resolve(base, "..g")); - - assertEquals("http://a/b/g", UriUtil.resolve(base, "./../g")); - assertEquals("http://a/b/c/g/", UriUtil.resolve(base, "./g/.")); - assertEquals("http://a/b/c/g/h", UriUtil.resolve(base, "g/./h")); - assertEquals("http://a/b/c/h", UriUtil.resolve(base, "g/../h")); - assertEquals("http://a/b/c/g;x=1/y", UriUtil.resolve(base, "g;x=1/./y")); - assertEquals("http://a/b/c/y", UriUtil.resolve(base, "g;x=1/../y")); - - assertEquals("http://a/b/c/g?y/./x", UriUtil.resolve(base, "g?y/./x")); - assertEquals("http://a/b/c/g?y/../x", UriUtil.resolve(base, "g?y/../x")); - assertEquals("http://a/b/c/g#s/./x", UriUtil.resolve(base, "g#s/./x")); - assertEquals("http://a/b/c/g#s/../x", UriUtil.resolve(base, "g#s/../x")); - - assertEquals("http:g", UriUtil.resolve(base, "http:g")); - } - - /** - * Tests additional abnormal usage of {@link UriUtil#resolve(String, String)}. - */ - public void testResolveAbnormalAdditional() { - assertEquals("c:e", UriUtil.resolve("http://a/b", "c:d/../e")); - assertEquals("a:c", UriUtil.resolve("a:b", "../c")); - } - -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/UtilTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/util/UtilTest.java deleted file mode 100644 index 1d9aff0723..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/util/UtilTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import com.google.android.exoplayer2.testutil.TestUtil; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import junit.framework.TestCase; - -/** - * Unit tests for {@link Util}. - */ -public class UtilTest extends TestCase { - - public void testArrayBinarySearchFloor() { - long[] values = new long[0]; - assertEquals(-1, Util.binarySearchFloor(values, 0, false, false)); - assertEquals(0, Util.binarySearchFloor(values, 0, false, true)); - - values = new long[] {1, 3, 5}; - assertEquals(-1, Util.binarySearchFloor(values, 0, false, false)); - assertEquals(-1, Util.binarySearchFloor(values, 0, true, false)); - assertEquals(0, Util.binarySearchFloor(values, 0, false, true)); - assertEquals(0, Util.binarySearchFloor(values, 0, true, true)); - - assertEquals(-1, Util.binarySearchFloor(values, 1, false, false)); - assertEquals(0, Util.binarySearchFloor(values, 1, true, false)); - assertEquals(0, Util.binarySearchFloor(values, 1, false, true)); - assertEquals(0, Util.binarySearchFloor(values, 1, true, true)); - - assertEquals(1, Util.binarySearchFloor(values, 4, false, false)); - assertEquals(1, Util.binarySearchFloor(values, 4, true, false)); - - assertEquals(1, Util.binarySearchFloor(values, 5, false, false)); - assertEquals(2, Util.binarySearchFloor(values, 5, true, false)); - - assertEquals(2, Util.binarySearchFloor(values, 6, false, false)); - assertEquals(2, Util.binarySearchFloor(values, 6, true, false)); - } - - public void testListBinarySearchFloor() { - List values = new ArrayList<>(); - assertEquals(-1, Util.binarySearchFloor(values, 0, false, false)); - assertEquals(0, Util.binarySearchFloor(values, 0, false, true)); - - values.add(1); - values.add(3); - values.add(5); - assertEquals(-1, Util.binarySearchFloor(values, 0, false, false)); - assertEquals(-1, Util.binarySearchFloor(values, 0, true, false)); - assertEquals(0, Util.binarySearchFloor(values, 0, false, true)); - assertEquals(0, Util.binarySearchFloor(values, 0, true, true)); - - assertEquals(-1, Util.binarySearchFloor(values, 1, false, false)); - assertEquals(0, Util.binarySearchFloor(values, 1, true, false)); - assertEquals(0, Util.binarySearchFloor(values, 1, false, true)); - assertEquals(0, Util.binarySearchFloor(values, 1, true, true)); - - assertEquals(1, Util.binarySearchFloor(values, 4, false, false)); - assertEquals(1, Util.binarySearchFloor(values, 4, true, false)); - - assertEquals(1, Util.binarySearchFloor(values, 5, false, false)); - assertEquals(2, Util.binarySearchFloor(values, 5, true, false)); - - assertEquals(2, Util.binarySearchFloor(values, 6, false, false)); - assertEquals(2, Util.binarySearchFloor(values, 6, true, false)); - } - - public void testArrayBinarySearchCeil() { - long[] values = new long[0]; - assertEquals(0, Util.binarySearchCeil(values, 0, false, false)); - assertEquals(-1, Util.binarySearchCeil(values, 0, false, true)); - - values = new long[] {1, 3, 5}; - assertEquals(0, Util.binarySearchCeil(values, 0, false, false)); - assertEquals(0, Util.binarySearchCeil(values, 0, true, false)); - - assertEquals(1, Util.binarySearchCeil(values, 1, false, false)); - assertEquals(0, Util.binarySearchCeil(values, 1, true, false)); - - assertEquals(1, Util.binarySearchCeil(values, 2, false, false)); - assertEquals(1, Util.binarySearchCeil(values, 2, true, false)); - - assertEquals(3, Util.binarySearchCeil(values, 5, false, false)); - assertEquals(2, Util.binarySearchCeil(values, 5, true, false)); - assertEquals(2, Util.binarySearchCeil(values, 5, false, true)); - assertEquals(2, Util.binarySearchCeil(values, 5, true, true)); - - assertEquals(3, Util.binarySearchCeil(values, 6, false, false)); - assertEquals(3, Util.binarySearchCeil(values, 6, true, false)); - assertEquals(2, Util.binarySearchCeil(values, 6, false, true)); - assertEquals(2, Util.binarySearchCeil(values, 6, true, true)); - } - - public void testListBinarySearchCeil() { - List values = new ArrayList<>(); - assertEquals(0, Util.binarySearchCeil(values, 0, false, false)); - assertEquals(-1, Util.binarySearchCeil(values, 0, false, true)); - - values.add(1); - values.add(3); - values.add(5); - assertEquals(0, Util.binarySearchCeil(values, 0, false, false)); - assertEquals(0, Util.binarySearchCeil(values, 0, true, false)); - - assertEquals(1, Util.binarySearchCeil(values, 1, false, false)); - assertEquals(0, Util.binarySearchCeil(values, 1, true, false)); - - assertEquals(1, Util.binarySearchCeil(values, 2, false, false)); - assertEquals(1, Util.binarySearchCeil(values, 2, true, false)); - - assertEquals(3, Util.binarySearchCeil(values, 5, false, false)); - assertEquals(2, Util.binarySearchCeil(values, 5, true, false)); - assertEquals(2, Util.binarySearchCeil(values, 5, false, true)); - assertEquals(2, Util.binarySearchCeil(values, 5, true, true)); - - assertEquals(3, Util.binarySearchCeil(values, 6, false, false)); - assertEquals(3, Util.binarySearchCeil(values, 6, true, false)); - assertEquals(2, Util.binarySearchCeil(values, 6, false, true)); - assertEquals(2, Util.binarySearchCeil(values, 6, true, true)); - } - - public void testParseXsDuration() { - assertEquals(150279L, Util.parseXsDuration("PT150.279S")); - assertEquals(1500L, Util.parseXsDuration("PT1.500S")); - } - - public void testParseXsDateTime() throws Exception { - assertEquals(1403219262000L, Util.parseXsDateTime("2014-06-19T23:07:42")); - assertEquals(1407322800000L, Util.parseXsDateTime("2014-08-06T11:00:00Z")); - assertEquals(1407322800000L, Util.parseXsDateTime("2014-08-06T11:00:00,000Z")); - assertEquals(1411161535000L, Util.parseXsDateTime("2014-09-19T13:18:55-08:00")); - assertEquals(1411161535000L, Util.parseXsDateTime("2014-09-19T13:18:55-0800")); - assertEquals(1411161535000L, Util.parseXsDateTime("2014-09-19T13:18:55.000-0800")); - assertEquals(1411161535000L, Util.parseXsDateTime("2014-09-19T13:18:55.000-800")); - } - - public void testUnescapeInvalidFileName() { - assertNull(Util.unescapeFileName("%a")); - assertNull(Util.unescapeFileName("%xyz")); - } - - public void testEscapeUnescapeFileName() { - assertEscapeUnescapeFileName("just+a regular+fileName", "just+a regular+fileName"); - assertEscapeUnescapeFileName("key:value", "key%3avalue"); - assertEscapeUnescapeFileName("<>:\"/\\|?*%", "%3c%3e%3a%22%2f%5c%7c%3f%2a%25"); - - Random random = new Random(0); - for (int i = 0; i < 1000; i++) { - String string = TestUtil.buildTestString(1000, random); - assertEscapeUnescapeFileName(string); - } - } - - private static void assertEscapeUnescapeFileName(String fileName, String escapedFileName) { - assertEquals(escapedFileName, Util.escapeFileName(fileName)); - assertEquals(fileName, Util.unescapeFileName(escapedFileName)); - } - - private static void assertEscapeUnescapeFileName(String fileName) { - String escapedFileName = Util.escapeFileName(fileName); - assertEquals(fileName, Util.unescapeFileName(escapedFileName)); - } - -}