From 05fd22383a90c47897b35088a115a8ff593c802b Mon Sep 17 00:00:00 2001 From: Giuseppe Carnevale Date: Fri, 22 Jul 2022 17:03:11 +0200 Subject: [PATCH 1/9] Improvements --- build.gradle | 25 +++++++++++++++++++++++++ src/main/AndroidManifest.xml | 2 ++ 2 files changed, 27 insertions(+) create mode 100644 build.gradle create mode 100644 src/main/AndroidManifest.xml diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..47664aa --- /dev/null +++ b/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'com.android.library' + +group = 'com.mpatrick.mp3agic' +android { + compileSdkVersion rootProject.ext.compileSdkVersion + defaultConfig { + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } +// buildTypes { +// release { +// minifyEnabled true +// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' +// } +// debug { +// minifyEnabled false +// } +// } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c01664a --- /dev/null +++ b/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + From 8d3811c9bff9a0fdeccd38636e24b612ba649aed Mon Sep 17 00:00:00 2001 From: Giuseppe Carnevale Date: Fri, 22 Jul 2022 17:12:30 +0200 Subject: [PATCH 2/9] Improvements --- build.gradle | 9 --------- 1 file changed, 9 deletions(-) diff --git a/build.gradle b/build.gradle index 47664aa..f492f02 100644 --- a/build.gradle +++ b/build.gradle @@ -9,15 +9,6 @@ android { versionCode 1 versionName "1.0" } -// buildTypes { -// release { -// minifyEnabled true -// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' -// } -// debug { -// minifyEnabled false -// } -// } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 From 855c991120d5b1496c63ef73aff4cd919fca31e5 Mon Sep 17 00:00:00 2001 From: Giuseppe Carnevale Date: Fri, 22 Jul 2022 17:19:28 +0200 Subject: [PATCH 3/9] Improvements --- build.gradle | 7 ------- 1 file changed, 7 deletions(-) diff --git a/build.gradle b/build.gradle index f492f02..e3feeb1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,7 @@ apply plugin: 'com.android.library' -group = 'com.mpatrick.mp3agic' android { compileSdkVersion rootProject.ext.compileSdkVersion - defaultConfig { - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 From 1e4f5e1218066138b0bfca7f347a2f5cfa0c577e Mon Sep 17 00:00:00 2001 From: Giuseppe Carnevale Date: Fri, 22 Jul 2022 17:26:27 +0200 Subject: [PATCH 4/9] Improvements --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index e3feeb1..a50342c 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,9 @@ apply plugin: 'com.android.library' android { compileSdkVersion rootProject.ext.compileSdkVersion + defaultConfig { + minSdkVersion 26 + } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 From 025046e5f607df8ae8401bc4f91c97fa5f39e0be Mon Sep 17 00:00:00 2001 From: Giuseppe Carnevale Date: Fri, 16 Sep 2022 01:32:11 +0200 Subject: [PATCH 5/9] Improvements --- build.gradle | 1 + src/main/AndroidManifest.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a50342c..271eb4c 100644 --- a/build.gradle +++ b/build.gradle @@ -9,4 +9,5 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + namespace 'com.mpatrick.mp3agic' } diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index c01664a..bdae66c 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,2 +1,2 @@ - + From 6aeffdb4bdebadeb14ad91ce93a7fea5fad39573 Mon Sep 17 00:00:00 2001 From: Giuseppe Carnevale Date: Sun, 20 Aug 2023 16:08:44 +0200 Subject: [PATCH 6/9] Improvements --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 271eb4c..65c7dd7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' android { - compileSdkVersion rootProject.ext.compileSdkVersion + compileSdk rootProject.ext.compileSdkVersion defaultConfig { minSdkVersion 26 } From 42d68b036eeb7d1890be6afd6075674e6024b27b Mon Sep 17 00:00:00 2001 From: Giuseppe Carnevale Date: Sat, 4 May 2024 02:02:32 +0200 Subject: [PATCH 7/9] Improvements --- .../mpatric/mp3agic/BaseExceptionTest.java | 37 - .../com/mpatric/mp3agic/BufferToolsTest.java | 608 ------- .../com/mpatric/mp3agic/EncodedTextTest.java | 323 ---- .../com/mpatric/mp3agic/FileWrapperTest.java | 74 - .../com/mpatric/mp3agic/ID3WrapperTest.java | 1440 ----------------- .../com/mpatric/mp3agic/ID3v1GenresTest.java | 34 - .../com/mpatric/mp3agic/ID3v1TagTest.java | 164 -- .../com/mpatric/mp3agic/ID3v22TagTest.java | 158 -- .../com/mpatric/mp3agic/ID3v24TagTest.java | 35 - .../mp3agic/ID3v2ChapterFrameDataTest.java | 201 --- .../mp3agic/ID3v2ChapterTOCFrameDataTest.java | 203 --- .../mp3agic/ID3v2CommentFrameDataTest.java | 236 --- .../mpatric/mp3agic/ID3v2FrameSetTest.java | 17 - .../com/mpatric/mp3agic/ID3v2FrameTest.java | 105 -- .../mp3agic/ID3v2ObseleteFrameTest.java | 38 - .../ID3v2ObseletePictureFrameDataTest.java | 41 - .../mp3agic/ID3v2PictureFrameDataTest.java | 194 --- .../mp3agic/ID3v2PopmFrameDataTest.java | 154 -- .../com/mpatric/mp3agic/ID3v2TagTest.java | 609 ------- .../mp3agic/ID3v2TextFrameDataTest.java | 108 -- .../mp3agic/ID3v2UrlFrameDataTest.java | 147 -- .../mp3agic/ID3v2WWWFrameDataTest.java | 14 - .../mp3agic/InvalidDataExceptionTest.java | 30 - .../java/com/mpatric/mp3agic/Mp3FileTest.java | 484 ------ .../com/mpatric/mp3agic/MpegFrameTest.java | 183 --- .../mpatric/mp3agic/MutableIntegerTest.java | 74 - .../mp3agic/NotSupportedExceptionTest.java | 30 - .../java/com/mpatric/mp3agic/TestHelper.java | 72 - .../mp3agic/UnsupportedTagExceptionTest.java | 31 - .../java/com/mpatric/mp3agic/VersionTest.java | 22 - src/test/resources/dummyframes.mp3 | Bin 4096 -> 0 bytes src/test/resources/image.png | Bin 1885 -> 0 bytes src/test/resources/incompletempegframe.mp3 | Bin 4095 -> 0 bytes src/test/resources/notags.mp3 | Bin 2869 -> 0 bytes src/test/resources/notanmp3.mp3 | 1 - src/test/resources/obsolete-noimage.mp3 | Bin 11456 -> 0 bytes src/test/resources/obsolete.mp3 | Bin 249258 -> 0 bytes src/test/resources/v1andv23andcustomtags.mp3 | Bin 4129 -> 0 bytes src/test/resources/v1andv23tags.mp3 | Bin 4096 -> 0 bytes .../v1andv23tagswithalbumimage-utf16le.mp3 | Bin 6144 -> 0 bytes .../resources/v1andv23tagswithalbumimage.mp3 | Bin 6144 -> 0 bytes src/test/resources/v1andv24tags.mp3 | Bin 4096 -> 0 bytes src/test/resources/v1tag.mp3 | Bin 2997 -> 0 bytes src/test/resources/v1tagwithnotrack.mp3 | Bin 2997 -> 0 bytes src/test/resources/v23tag.mp3 | Bin 3968 -> 0 bytes src/test/resources/v23tagwithbpm.mp3 | Bin 3370 -> 0 bytes src/test/resources/v23tagwithbpmfloat.mp3 | Bin 3373 -> 0 bytes .../resources/v23tagwithbpmfloatwithcomma.mp3 | Bin 3373 -> 0 bytes src/test/resources/v23tagwithchapters.mp3 | Bin 91916 -> 0 bytes src/test/resources/v23tagwithwmprating.mp3 | Bin 3398 -> 0 bytes src/test/resources/v23unicodetags.mp3 | Bin 3071 -> 0 bytes src/test/resources/v24tagswithalbumimage.mp3 | Bin 6144 -> 0 bytes src/test/resources/withitunescomment.mp3 | Bin 4096 -> 0 bytes 53 files changed, 5867 deletions(-) delete mode 100644 src/test/java/com/mpatric/mp3agic/BaseExceptionTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/BufferToolsTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/EncodedTextTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/FileWrapperTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3WrapperTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v1GenresTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v1TagTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v22TagTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v24TagTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2ChapterFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2ChapterTOCFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2CommentFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2FrameSetTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2FrameTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2ObseleteFrameTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2ObseletePictureFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2PictureFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2PopmFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2TagTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2TextFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2UrlFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/ID3v2WWWFrameDataTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/InvalidDataExceptionTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/Mp3FileTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/MpegFrameTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/MutableIntegerTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/NotSupportedExceptionTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/TestHelper.java delete mode 100644 src/test/java/com/mpatric/mp3agic/UnsupportedTagExceptionTest.java delete mode 100644 src/test/java/com/mpatric/mp3agic/VersionTest.java delete mode 100644 src/test/resources/dummyframes.mp3 delete mode 100644 src/test/resources/image.png delete mode 100644 src/test/resources/incompletempegframe.mp3 delete mode 100644 src/test/resources/notags.mp3 delete mode 100644 src/test/resources/notanmp3.mp3 delete mode 100755 src/test/resources/obsolete-noimage.mp3 delete mode 100755 src/test/resources/obsolete.mp3 delete mode 100644 src/test/resources/v1andv23andcustomtags.mp3 delete mode 100644 src/test/resources/v1andv23tags.mp3 delete mode 100644 src/test/resources/v1andv23tagswithalbumimage-utf16le.mp3 delete mode 100644 src/test/resources/v1andv23tagswithalbumimage.mp3 delete mode 100644 src/test/resources/v1andv24tags.mp3 delete mode 100644 src/test/resources/v1tag.mp3 delete mode 100644 src/test/resources/v1tagwithnotrack.mp3 delete mode 100644 src/test/resources/v23tag.mp3 delete mode 100644 src/test/resources/v23tagwithbpm.mp3 delete mode 100644 src/test/resources/v23tagwithbpmfloat.mp3 delete mode 100644 src/test/resources/v23tagwithbpmfloatwithcomma.mp3 delete mode 100644 src/test/resources/v23tagwithchapters.mp3 delete mode 100644 src/test/resources/v23tagwithwmprating.mp3 delete mode 100644 src/test/resources/v23unicodetags.mp3 delete mode 100644 src/test/resources/v24tagswithalbumimage.mp3 delete mode 100644 src/test/resources/withitunescomment.mp3 diff --git a/src/test/java/com/mpatric/mp3agic/BaseExceptionTest.java b/src/test/java/com/mpatric/mp3agic/BaseExceptionTest.java deleted file mode 100644 index ec2b271..0000000 --- a/src/test/java/com/mpatric/mp3agic/BaseExceptionTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class BaseExceptionTest { - - @Test - public void generatesCorrectDetailedMessageForSingleException() { - BaseException e = new BaseException("ONE"); - assertEquals("ONE", e.getMessage()); - assertEquals("[com.mpatric.mp3agic.BaseException: ONE]", e.getDetailedMessage()); - } - - @Test - public void generatesCorrectDetailedMessageForChainedBaseExceptions() { - BaseException e1 = new BaseException("ONE"); - BaseException e2 = new UnsupportedTagException("TWO", e1); - BaseException e3 = new NotSupportedException("THREE", e2); - BaseException e4 = new NoSuchTagException("FOUR", e3); - BaseException e5 = new InvalidDataException("FIVE", e4); - assertEquals("FIVE", e5.getMessage()); - assertEquals("[com.mpatric.mp3agic.InvalidDataException: FIVE] caused by [com.mpatric.mp3agic.NoSuchTagException: FOUR] caused by [com.mpatric.mp3agic.NotSupportedException: THREE] caused by [com.mpatric.mp3agic.UnsupportedTagException: TWO] caused by [com.mpatric.mp3agic.BaseException: ONE]", e5.getDetailedMessage()); - } - - @Test - public void generatesCorrectDetailedMessageForChainedExceptionsWithOtherExceptionInMix() { - BaseException e1 = new BaseException("ONE"); - BaseException e2 = new UnsupportedTagException("TWO", e1); - Exception e3 = new Exception("THREE", e2); - BaseException e4 = new NoSuchTagException("FOUR", e3); - BaseException e5 = new InvalidDataException("FIVE", e4); - assertEquals("FIVE", e5.getMessage()); - assertEquals("[com.mpatric.mp3agic.InvalidDataException: FIVE] caused by [com.mpatric.mp3agic.NoSuchTagException: FOUR] caused by [java.lang.Exception: THREE] caused by [com.mpatric.mp3agic.UnsupportedTagException: TWO] caused by [com.mpatric.mp3agic.BaseException: ONE]", e5.getDetailedMessage()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/BufferToolsTest.java b/src/test/java/com/mpatric/mp3agic/BufferToolsTest.java deleted file mode 100644 index bba3b18..0000000 --- a/src/test/java/com/mpatric/mp3agic/BufferToolsTest.java +++ /dev/null @@ -1,608 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import java.io.UnsupportedEncodingException; -import java.util.Arrays; - -import static org.junit.Assert.*; - -public class BufferToolsTest { - - private static final byte BYTE_T = 0x54; - private static final byte BYTE_A = 0x41; - private static final byte BYTE_G = 0x47; - private static final byte BYTE_DASH = 0x2D; - private static final byte BYTE_FF = -0x01; - private static final byte BYTE_FB = -0x05; - private static final byte BYTE_90 = -0x70; - private static final byte BYTE_44 = 0x44; - private static final byte BYTE_E0 = -0x20; - private static final byte BYTE_F0 = -0x10; - private static final byte BYTE_81 = -0x7F; - private static final byte BYTE_ESZETT = -0x21; - - // byte buffer to string - - @Test - public void shouldExtractStringFromStartOfBuffer() throws UnsupportedEncodingException { - byte[] buffer = {BYTE_T, BYTE_A, BYTE_G, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH}; - assertEquals("TAG", BufferTools.byteBufferToString(buffer, 0, 3)); - } - - @Test - public void shouldExtractStringFromEndOfBuffer() throws UnsupportedEncodingException { - byte[] buffer = {BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_T, BYTE_A, BYTE_G}; - assertEquals("TAG", BufferTools.byteBufferToString(buffer, 5, 3)); - } - - @Test - public void shouldExtractStringFromMiddleOfBuffer() throws UnsupportedEncodingException { - byte[] buffer = {BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_T, BYTE_A, BYTE_G}; - assertEquals("TAG", BufferTools.byteBufferToString(buffer, 5, 3)); - } - - @Test - public void shouldExtractUnicodeStringFromMiddleOfBuffer() throws UnsupportedEncodingException { - byte[] buffer = {BYTE_DASH, BYTE_DASH, 0x03, (byte) 0xb3, 0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0x03, (byte) 0xac, BYTE_DASH, BYTE_DASH}; - assertEquals("\u03B3\u03B5\u03B9\u03AC", BufferTools.byteBufferToString(buffer, 2, 8, "UTF-16BE")); - } - - @Test - public void shouldThrowExceptionForOffsetBeforeStartOfArray() throws UnsupportedEncodingException { - byte[] buffer = {BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_T, BYTE_A, BYTE_G}; - try { - BufferTools.byteBufferToString(buffer, -1, 4); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { - // expected - } - } - - @Test - public void shouldThrowExceptionForOffsetAfterEndOfArray() throws UnsupportedEncodingException { - byte[] buffer = {BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_T, BYTE_A, BYTE_G}; - try { - BufferTools.byteBufferToString(buffer, buffer.length, 1); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { - // expected - } - } - - @Test - public void shouldThrowExceptionForLengthExtendingBeyondEndOfArray() throws UnsupportedEncodingException { - byte[] buffer = {BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_DASH, BYTE_T, BYTE_A, BYTE_G}; - try { - BufferTools.byteBufferToString(buffer, buffer.length - 2, 3); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { - // expected - } - } - - // string to byte buffer - - @Test - public void shouldConvertStringToBufferAndBack() throws UnsupportedEncodingException { - String original = "1234567890QWERTYUIOP"; - byte[] buffer = BufferTools.stringToByteBuffer(original, 0, original.length()); - String converted = BufferTools.byteBufferToString(buffer, 0, buffer.length); - assertEquals(original, converted); - } - - @Test - public void shouldConvertSubstringToBufferAndBack() throws UnsupportedEncodingException { - String original = "1234567890QWERTYUIOP"; - byte[] buffer = BufferTools.stringToByteBuffer(original, 2, original.length() - 5); - String converted = BufferTools.byteBufferToString(buffer, 0, buffer.length); - assertEquals("34567890QWERTYU", converted); - } - - @Test - public void shouldConvertUnicodeStringToBufferAndBack() throws UnsupportedEncodingException { - String original = "\u03B3\u03B5\u03B9\u03AC \u03C3\u03BF\u03C5"; - byte[] buffer = BufferTools.stringToByteBuffer(original, 0, original.length(), "UTF-16LE"); - String converted = BufferTools.byteBufferToString(buffer, 0, buffer.length, "UTF-16LE"); - assertEquals(original, converted); - } - - @Test - public void shouldConvertUnicodeSubstringToBufferAndBack() throws UnsupportedEncodingException { - String original = "\u03B3\u03B5\u03B9\u03AC \u03C3\u03BF\u03C5"; - byte[] buffer = BufferTools.stringToByteBuffer(original, 2, original.length() - 5, "UTF-16LE"); - String converted = BufferTools.byteBufferToString(buffer, 0, buffer.length, "UTF-16LE"); - assertEquals("\u03B9\u03AC ", converted); - } - - @Test - public void shouldThrowAnExceptionWhenConvertingStringToBytesWithOffsetOutOfRange() throws UnsupportedEncodingException { - String original = "1234567890QWERTYUIOP"; - try { - BufferTools.stringToByteBuffer(original, -1, 1); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - try { - BufferTools.stringToByteBuffer(original, original.length(), 1); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - } - - @Test - public void shouldThrowAnExceptionWhenConvertingStringToBytesWithLengthOutOfRange() throws UnsupportedEncodingException { - String original = "1234567890QWERTYUIOP"; - try { - BufferTools.stringToByteBuffer(original, 0, -1); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - try { - BufferTools.stringToByteBuffer(original, 0, original.length() + 1); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - try { - BufferTools.stringToByteBuffer(original, 3, original.length() - 2); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - } - - // string into existing byte buffer - - @Test - public void shouldCopyStringToStartOfByteBuffer() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - Arrays.fill(buffer, (byte) 0); - String s = "TAG-"; - BufferTools.stringIntoByteBuffer(s, 0, s.length(), buffer, 0); - byte[] expectedBuffer = {BYTE_T, BYTE_A, BYTE_G, BYTE_DASH, 0, 0, 0, 0, 0, 0}; - assertArrayEquals(expectedBuffer, buffer); - } - - @Test - public void shouldCopyUnicodeStringToStartOfByteBuffer() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - Arrays.fill(buffer, (byte) 0); - String s = "\u03B3\u03B5\u03B9\u03AC"; - BufferTools.stringIntoByteBuffer(s, 0, s.length(), buffer, 0, "UTF-16BE"); - byte[] expectedBuffer = {0x03, (byte) 0xb3, 0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0x03, (byte) 0xac, 0, 0}; - assertArrayEquals(expectedBuffer, buffer); - } - - @Test - public void shouldCopyStringToEndOfByteBuffer() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - Arrays.fill(buffer, (byte) 0); - String s = "TAG-"; - BufferTools.stringIntoByteBuffer(s, 0, s.length(), buffer, 6); - byte[] expectedBuffer = {0, 0, 0, 0, 0, 0, BYTE_T, BYTE_A, BYTE_G, BYTE_DASH}; - assertArrayEquals(expectedBuffer, buffer); - } - - @Test - public void shouldCopyUnicodeStringToEndOfByteBuffer() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - Arrays.fill(buffer, (byte) 0); - String s = "\u03B3\u03B5\u03B9\u03AC"; - BufferTools.stringIntoByteBuffer(s, 0, s.length(), buffer, 2, "UTF-16BE"); - byte[] expectedBuffer = {0, 0, 0x03, (byte) 0xb3, 0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0x03, (byte) 0xac}; - assertArrayEquals(expectedBuffer, buffer); - } - - @Test - public void shouldCopySubstringToStartOfByteBuffer() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - Arrays.fill(buffer, (byte) 0); - String s = "TAG-"; - BufferTools.stringIntoByteBuffer(s, 1, 2, buffer, 0); - byte[] expectedBuffer = {BYTE_A, BYTE_G, 0, 0, 0, 0, 0, 0, 0, 0}; - assertArrayEquals(expectedBuffer, buffer); - } - - @Test - public void shouldCopyUnicodeSubstringToStartOfByteBuffer() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - Arrays.fill(buffer, (byte) 0); - String s = "\u03B3\u03B5\u03B9\u03AC"; - BufferTools.stringIntoByteBuffer(s, 1, 2, buffer, 0, "UTF-16BE"); - byte[] expectedBuffer = {0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0, 0, 0, 0, 0, 0}; - assertArrayEquals(expectedBuffer, buffer); - } - - @Test - public void shouldCopySubstringToMiddleOfByteBuffer() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - Arrays.fill(buffer, (byte) 0); - String s = "TAG-"; - BufferTools.stringIntoByteBuffer(s, 1, 2, buffer, 4); - byte[] expectedBuffer = {0, 0, 0, 0, BYTE_A, BYTE_G, 0, 0, 0, 0}; - assertArrayEquals(expectedBuffer, buffer); - } - - @Test - public void shouldRaiseExceptionWhenCopyingStringIntoByteBufferWithOffsetOutOfRange() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - String s = "TAG-"; - try { - BufferTools.stringIntoByteBuffer(s, -1, 1, buffer, 0); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - try { - BufferTools.stringIntoByteBuffer(s, s.length(), 1, buffer, 0); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - } - - @Test - public void shouldRaiseExceptionWhenCopyingStringIntoByteBufferWithLengthOutOfRange() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - String s = "TAG-"; - try { - BufferTools.stringIntoByteBuffer(s, 0, -1, buffer, 0); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - try { - BufferTools.stringIntoByteBuffer(s, 0, s.length() + 1, buffer, 0); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - try { - BufferTools.stringIntoByteBuffer(s, 3, s.length() - 2, buffer, 0); - fail("StringIndexOutOfBoundsException expected but not thrown"); - } catch (StringIndexOutOfBoundsException e) { /* expected*/ } - } - - @Test - public void shouldRaiseExceptionWhenCopyingStringIntoByteBufferWithDestinationOffsetOutOfRange() throws UnsupportedEncodingException { - byte[] buffer = new byte[10]; - String s = "TAG-"; - try { - BufferTools.stringIntoByteBuffer(s, 0, 1, buffer, 10); - fail("ArrayIndexOutOfBoundsException expected but not thrown"); - } catch (ArrayIndexOutOfBoundsException e) { /* expected*/ } - try { - BufferTools.stringIntoByteBuffer(s, 0, s.length(), buffer, buffer.length - s.length() + 1); - fail("ArrayIndexOutOfBoundsException expected but not thrown"); - } catch (ArrayIndexOutOfBoundsException e) { /* expected*/ } - } - - // trim strings - - @Test - public void shouldRightTrimStringsCorrectly() throws UnsupportedEncodingException { - assertEquals("", BufferTools.trimStringRight("")); - assertEquals("", BufferTools.trimStringRight(" ")); - assertEquals("TEST", BufferTools.trimStringRight("TEST")); - assertEquals("TEST", BufferTools.trimStringRight("TEST ")); - assertEquals(" TEST", BufferTools.trimStringRight(" TEST")); - assertEquals(" TEST", BufferTools.trimStringRight(" TEST ")); - assertEquals("TEST", BufferTools.trimStringRight("TEST\t\r\n")); - assertEquals("TEST", BufferTools.trimStringRight("TEST" + BufferTools.byteBufferToString(new byte[]{0, 0}, 0, 2))); - } - - @Test - public void shouldRightTrimUnicodeStringsCorrectly() throws UnsupportedEncodingException { - assertEquals("\u03B3\u03B5\u03B9\u03AC", BufferTools.trimStringRight("\u03B3\u03B5\u03B9\u03AC")); - assertEquals("\u03B3\u03B5\u03B9\u03AC", BufferTools.trimStringRight("\u03B3\u03B5\u03B9\u03AC ")); - assertEquals(" \u03B3\u03B5\u03B9\u03AC", BufferTools.trimStringRight(" \u03B3\u03B5\u03B9\u03AC")); - assertEquals(" \u03B3\u03B5\u03B9\u03AC", BufferTools.trimStringRight(" \u03B3\u03B5\u03B9\u03AC ")); - assertEquals("\u03B3\u03B5\u03B9\u03AC", BufferTools.trimStringRight("\u03B3\u03B5\u03B9\u03AC\t\r\n")); - assertEquals("\u03B3\u03B5\u03B9\u03AC", BufferTools.trimStringRight("\u03B3\u03B5\u03B9\u03AC" + BufferTools.byteBufferToString(new byte[]{0, 0}, 0, 2))); - } - - @Test - public void shouldRightPadStringsCorrectly() { - assertEquals("1234", BufferTools.padStringRight("1234", 3, ' ')); - assertEquals("123", BufferTools.padStringRight("123", 3, ' ')); - assertEquals("12 ", BufferTools.padStringRight("12", 3, ' ')); - assertEquals("1 ", BufferTools.padStringRight("1", 3, ' ')); - assertEquals(" ", BufferTools.padStringRight("", 3, ' ')); - } - - @Test - public void shouldRightPadUnicodeStringsCorrectly() { - assertEquals("\u03B3\u03B5\u03B9\u03AC", BufferTools.padStringRight("\u03B3\u03B5\u03B9\u03AC", 3, ' ')); - assertEquals("\u03B3\u03B5\u03B9", BufferTools.padStringRight("\u03B3\u03B5\u03B9", 3, ' ')); - assertEquals("\u03B3\u03B5 ", BufferTools.padStringRight("\u03B3\u03B5", 3, ' ')); - assertEquals("\u03B3 ", BufferTools.padStringRight("\u03B3", 3, ' ')); - } - - @Test - public void shouldPadRightWithNullCharacters() { - assertEquals("123", BufferTools.padStringRight("123", 3, '\00')); - assertEquals("12\00", BufferTools.padStringRight("12", 3, '\00')); - assertEquals("1\00\00", BufferTools.padStringRight("1", 3, '\00')); - assertEquals("\00\00\00", BufferTools.padStringRight("", 3, '\00')); - } - - @Test - public void shouldExtractBitsCorrectly() { - byte b = -0x36; // 11001010 - assertFalse(BufferTools.checkBit(b, 0)); - assertTrue(BufferTools.checkBit(b, 1)); - assertFalse(BufferTools.checkBit(b, 2)); - assertTrue(BufferTools.checkBit(b, 3)); - assertFalse(BufferTools.checkBit(b, 4)); - assertFalse(BufferTools.checkBit(b, 5)); - assertTrue(BufferTools.checkBit(b, 6)); - assertTrue(BufferTools.checkBit(b, 7)); - } - - @Test - public void shouldSetBitsInBytesCorrectly() { - byte b = -0x36; // 11001010 - assertEquals(-0x36, BufferTools.setBit(b, 7, true)); // 11010010 - assertEquals(-0x35, BufferTools.setBit(b, 0, true)); // 11001011 - assertEquals(-0x26, BufferTools.setBit(b, 4, true)); // 11011010 - assertEquals(-0x36, BufferTools.setBit(b, 0, false)); // 11010010 - assertEquals(0x4A, BufferTools.setBit(b, 7, false)); // 01001010 - assertEquals(-0x3E, BufferTools.setBit(b, 3, false)); // 11000010 - } - - @Test - public void shouldUnpackIntegerCorrectly() { - assertEquals(0xFFFB9044, BufferTools.unpackInteger(BYTE_FF, BYTE_FB, BYTE_90, BYTE_44)); - assertEquals(0x00000081, BufferTools.unpackInteger((byte) 0, (byte) 0, (byte) 0, BYTE_81)); - assertEquals(0x00000101, BufferTools.unpackInteger((byte) 0, (byte) 0, (byte) 1, (byte) 1)); - } - - @Test - public void shouldUnpackSynchsafeIntegersCorrectly() { - assertEquals(1217, BufferTools.unpackSynchsafeInteger((byte) 0, (byte) 0, (byte) 0x09, (byte) 0x41)); - assertEquals(1227, BufferTools.unpackSynchsafeInteger((byte) 0, (byte) 0, (byte) 0x09, (byte) 0x4B)); - assertEquals(1002, BufferTools.unpackSynchsafeInteger((byte) 0, (byte) 0, (byte) 0x07, (byte) 0x6A)); - assertEquals(0x0101, BufferTools.unpackSynchsafeInteger((byte) 0, (byte) 0, (byte) 2, (byte) 1)); - assertEquals(0x01010101, BufferTools.unpackSynchsafeInteger((byte) 8, (byte) 4, (byte) 2, (byte) 1)); - } - - @Test - public void shouldPackIntegerCorrectly() { - assertArrayEquals(new byte[]{BYTE_FF, BYTE_FB, BYTE_90, BYTE_44}, BufferTools.packInteger(0xFFFB9044)); - } - - @Test - public void shouldPackSynchsafeIntegersCorrectly() { - assertArrayEquals(new byte[]{(byte) 0, (byte) 0, (byte) 0x09, (byte) 0x41}, BufferTools.packSynchsafeInteger(1217)); - assertArrayEquals(new byte[]{(byte) 0, (byte) 0, (byte) 0x09, (byte) 0x4B}, BufferTools.packSynchsafeInteger(1227)); - assertArrayEquals(new byte[]{(byte) 0, (byte) 0, (byte) 0x07, (byte) 0x6A}, BufferTools.packSynchsafeInteger(1002)); - assertArrayEquals(new byte[]{(byte) 0, (byte) 0, (byte) 2, (byte) 1}, BufferTools.packSynchsafeInteger(0x0101)); - assertArrayEquals(new byte[]{(byte) 8, (byte) 4, (byte) 2, (byte) 1}, BufferTools.packSynchsafeInteger(0x01010101)); - } - - @Test - public void shouldPackAndUnpackIntegerBackToOriginalValue() { - int original = 12345; - byte[] bytes = BufferTools.packInteger(original); - int unpacked = BufferTools.unpackInteger(bytes[0], bytes[1], bytes[2], bytes[3]); - assertEquals(original, unpacked); - } - - @Test - public void shouldPackAndUnpackSynchsafeIntegerBackToOriginalValue() { - int original = 12345; - byte[] bytes = BufferTools.packSynchsafeInteger(original); - int unpacked = BufferTools.unpackSynchsafeInteger(bytes[0], bytes[1], bytes[2], bytes[3]); - assertEquals(original, unpacked); - } - - @Test - public void shouldCopyBuffersWithValidOffsetsAndLengths() { - byte[] buffer = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - assertArrayEquals(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, BufferTools.copyBuffer(buffer, 0, buffer.length)); - assertArrayEquals(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9}, BufferTools.copyBuffer(buffer, 1, buffer.length - 1)); - assertArrayEquals(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8}, BufferTools.copyBuffer(buffer, 0, buffer.length - 1)); - assertArrayEquals(new byte[]{1, 2, 3, 4, 5, 6, 7, 8}, BufferTools.copyBuffer(buffer, 1, buffer.length - 2)); - assertArrayEquals(new byte[]{4}, BufferTools.copyBuffer(buffer, 4, 1)); - } - - @Test - public void throwsExceptionWhenCopyingBufferWithInvalidOffsetAndOrLength() { - byte[] buffer = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - - try { - BufferTools.copyBuffer(buffer, -1, buffer.length); - fail("ArrayIndexOutOfBoundsException expected but not thrown"); - } catch (ArrayIndexOutOfBoundsException e) { /* expected*/ } - - try { - BufferTools.copyBuffer(buffer, buffer.length, 1); - fail("ArrayIndexOutOfBoundsException expected but not thrown"); - } catch (ArrayIndexOutOfBoundsException e) { /* expected*/ } - - try { - BufferTools.copyBuffer(buffer, 1, buffer.length); - fail("ArrayIndexOutOfBoundsException expected but not thrown"); - } catch (ArrayIndexOutOfBoundsException e) { /* expected*/ } - } - - @Test - public void shouldDetermineUnsynchronisationSizesCorrectly() { - assertEquals(0, BufferTools.sizeUnsynchronisationWouldAdd(new byte[]{})); - assertEquals(0, BufferTools.sizeUnsynchronisationWouldAdd(new byte[]{BYTE_FF, 1, BYTE_FB})); - assertEquals(1, BufferTools.sizeUnsynchronisationWouldAdd(new byte[]{BYTE_FF, BYTE_FB})); - assertEquals(1, BufferTools.sizeUnsynchronisationWouldAdd(new byte[]{0, BYTE_FF, BYTE_FB, 0})); - assertEquals(1, BufferTools.sizeUnsynchronisationWouldAdd(new byte[]{0, BYTE_FF})); - assertEquals(2, BufferTools.sizeUnsynchronisationWouldAdd(new byte[]{BYTE_FF, BYTE_FB, 0, BYTE_FF, BYTE_FB})); - assertEquals(3, BufferTools.sizeUnsynchronisationWouldAdd(new byte[]{BYTE_FF, BYTE_FF, BYTE_FF})); - } - - @Test - public void shouldDetermineSynchronisationSizesCorrectly() { - assertEquals(0, BufferTools.sizeSynchronisationWouldSubtract(new byte[]{})); - assertEquals(0, BufferTools.sizeSynchronisationWouldSubtract(new byte[]{BYTE_FF, 1, BYTE_FB})); - assertEquals(1, BufferTools.sizeSynchronisationWouldSubtract(new byte[]{BYTE_FF, 0, BYTE_FB})); - assertEquals(1, BufferTools.sizeSynchronisationWouldSubtract(new byte[]{0, BYTE_FF, 0, BYTE_FB, 0})); - assertEquals(1, BufferTools.sizeSynchronisationWouldSubtract(new byte[]{0, BYTE_FF, 0})); - assertEquals(2, BufferTools.sizeSynchronisationWouldSubtract(new byte[]{BYTE_FF, 0, BYTE_FB, 0, BYTE_FF, 0, BYTE_FB})); - assertEquals(3, BufferTools.sizeSynchronisationWouldSubtract(new byte[]{BYTE_FF, 0, BYTE_FF, 0, BYTE_FF, 0})); - } - - @Test - public void shouldUnsynchroniseThenSynchroniseFFExBytesCorrectly() { - byte[] buffer = {BYTE_FF, BYTE_FB, 2, 3, 4, BYTE_FF, BYTE_E0, 7, 8, 9, 10, 11, 12, 13, BYTE_FF, BYTE_F0}; - byte[] expectedBuffer = {BYTE_FF, 0, BYTE_FB, 2, 3, 4, BYTE_FF, 0, BYTE_E0, 7, 8, 9, 10, 11, 12, 13, BYTE_FF, 0, BYTE_F0}; - byte[] unsynchronised = BufferTools.unsynchroniseBuffer(buffer); - byte[] synchronised = BufferTools.synchroniseBuffer(unsynchronised); - assertArrayEquals(expectedBuffer, unsynchronised); - assertArrayEquals(buffer, synchronised); - } - - @Test - public void shouldUnsynchroniseThenSynchroniseFF00BytesCorrectly() { - byte[] buffer = {BYTE_FF, 0, 2, 3, 4, BYTE_FF, 0, 7, 8, 9, 10, 11, 12, 13, BYTE_FF, 0}; - byte[] expectedBuffer = {BYTE_FF, 0, 0, 2, 3, 4, BYTE_FF, 0, 0, 7, 8, 9, 10, 11, 12, 13, BYTE_FF, 0, 0}; - byte[] unsynchronised = BufferTools.unsynchroniseBuffer(buffer); - byte[] synchronised = BufferTools.synchroniseBuffer(unsynchronised); - assertArrayEquals(expectedBuffer, unsynchronised); - assertArrayEquals(buffer, synchronised); - } - - @Test - public void shouldUnsynchroniseThenSynchroniseBufferFullOfFFsCorrectly() { - byte[] buffer = {BYTE_FF, BYTE_FF, BYTE_FF, BYTE_FF}; - byte[] expectedBuffer = {BYTE_FF, 0, BYTE_FF, 0, BYTE_FF, 0, BYTE_FF, 0}; - byte[] unsynchronised = BufferTools.unsynchroniseBuffer(buffer); - byte[] synchronised = BufferTools.synchroniseBuffer(unsynchronised); - assertArrayEquals(expectedBuffer, unsynchronised); - assertArrayEquals(buffer, synchronised); - } - - @Test - public void shouldUnsynchroniseThenSynchroniseBufferMinimalBufferCorrectly() { - byte[] buffer = {BYTE_FF}; - byte[] expectedBuffer = {BYTE_FF, 0}; - byte[] unsynchronised = BufferTools.unsynchroniseBuffer(buffer); - byte[] synchronised = BufferTools.synchroniseBuffer(unsynchronised); - assertArrayEquals(expectedBuffer, unsynchronised); - assertArrayEquals(buffer, synchronised); - } - - @Test - public void shouldReturnOriginalBufferIfNoUnynchronisationOrSynchronisationIsRequired() { - byte[] buffer = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - byte[] unsynchronised = BufferTools.unsynchroniseBuffer(buffer); - byte[] synchronised = BufferTools.synchroniseBuffer(buffer); - assertEquals(buffer, unsynchronised); - assertEquals(buffer, synchronised); - } - - @Test - public void shouldReplaceTokensWithSpecifiedStrings() { - String source = "%1-%2 something %1-%3"; - assertEquals("ONE-%2 something ONE-%3", BufferTools.substitute(source, "%1", "ONE")); - assertEquals("%1-TWO something %1-%3", BufferTools.substitute(source, "%2", "TWO")); - assertEquals("%1-%2 something %1-THREE", BufferTools.substitute(source, "%3", "THREE")); - } - - @Test - public void shouldReturnOriginalStringIfTokenToSubstituteDoesNotExistInString() { - String source = "%1-%2 something %1-%3"; - assertEquals("%1-%2 something %1-%3", BufferTools.substitute(source, "%X", "XXXXX")); - } - - @Test - public void shouldReturnOriginalStringForSubstitutionWithEmptyString() { - String source = "%1-%2 something %1-%3"; - assertEquals("%1-%2 something %1-%3", BufferTools.substitute(source, "", "WHATEVER")); - } - - @Test - public void shouldSubstituteEmptyStringWhenDestinationStringIsNull() { - String source = "%1-%2 something %1-%3"; - assertEquals("-%2 something -%3", BufferTools.substitute(source, "%1", null)); - } - - @Test - public void shouldConvertNonAsciiCharactersToQuestionMarksInString() { - assertEquals("?12?34?567???89?", BufferTools.asciiOnly("ü12¬34ü567¬¬¬89ü")); - } - - @Test - public void convertsBufferContainingHighAscii() throws UnsupportedEncodingException { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G}; - assertEquals("T" + (char) (223) + "G", BufferTools.byteBufferToString(buffer, 0, 3)); - } - - // finding terminators - - @Test - public void findsSingleTerminator() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T, 0, BYTE_G, BYTE_A}; - assertEquals(4, BufferTools.indexOfTerminator(buffer, 0, 1)); - } - - @Test - public void findsFirstSingleTerminator() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T, 0, BYTE_G, BYTE_A, 0, BYTE_G, BYTE_A}; - assertEquals(4, BufferTools.indexOfTerminator(buffer, 0, 1)); - } - - @Test - public void findsFirstSingleTerminatorAfterFromIndex() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T, 0, BYTE_G, BYTE_A, 0, BYTE_G, BYTE_A}; - assertEquals(7, BufferTools.indexOfTerminator(buffer, 5, 1)); - } - - @Test - public void findsSingleTerminatorWhenFirstElement() { - byte[] buffer = {0, BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T}; - assertEquals(0, BufferTools.indexOfTerminator(buffer, 0, 1)); - } - - @Test - public void findsSingleTerminatorWhenLastElement() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T, 0}; - assertEquals(4, BufferTools.indexOfTerminator(buffer, 0, 1)); - } - - @Test - public void ReturnsMinusOneWhenNoSingleTerminator() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T}; - assertEquals(-1, BufferTools.indexOfTerminator(buffer, 0, 1)); - } - - @Test - public void findsDoubleTerminator() { - byte[] buffer = {BYTE_T, 0, BYTE_G, BYTE_T, 0, 0, BYTE_G, BYTE_A}; - assertEquals(4, BufferTools.indexOfTerminator(buffer, 0, 2)); - } - - @Test - public void findsNotFindDoubleTerminatorIfNotOnEvenByte() { - byte[] buffer = {BYTE_T, 0, BYTE_G, BYTE_T, BYTE_T, 0, 0, BYTE_G, BYTE_A}; - assertEquals(-1, BufferTools.indexOfTerminator(buffer, 0, 2)); - } - - @Test - public void findsFirstDoubleTerminator() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T, 0, 0, BYTE_G, BYTE_A, 0, 0, BYTE_G, BYTE_A}; - assertEquals(4, BufferTools.indexOfTerminator(buffer, 0, 2)); - } - - @Test - public void findsFirstDoubleTerminatorOnAnEvenByte() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, 0, 0, BYTE_T, BYTE_G, BYTE_A, 0, 0, BYTE_G, BYTE_A}; - assertEquals(8, BufferTools.indexOfTerminator(buffer, 0, 2)); - } - - @Test - public void findsFirstDoubleTerminatorAfterFromIndex() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T, 0, 0, BYTE_G, BYTE_A, 0, 0, BYTE_G, BYTE_A}; - assertEquals(8, BufferTools.indexOfTerminator(buffer, 6, 2)); - } - - @Test - public void findsDoubleTerminatorWhenFirstElement() { - byte[] buffer = {0, 0, BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T}; - assertEquals(0, BufferTools.indexOfTerminator(buffer, 0, 2)); - } - - @Test - public void findsDoubleTerminatorWhenLastElement() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T, 0, 0}; - assertEquals(4, BufferTools.indexOfTerminator(buffer, 0, 2)); - } - - @Test - public void returnsMinusOneWhenNoDoubleTerminator() { - byte[] buffer = {BYTE_T, BYTE_ESZETT, BYTE_G, BYTE_T}; - assertEquals(-1, BufferTools.indexOfTerminator(buffer, 0, 2)); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/EncodedTextTest.java b/src/test/java/com/mpatric/mp3agic/EncodedTextTest.java deleted file mode 100644 index f917de6..0000000 --- a/src/test/java/com/mpatric/mp3agic/EncodedTextTest.java +++ /dev/null @@ -1,323 +0,0 @@ -package com.mpatric.mp3agic; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.CharacterCodingException; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class EncodedTextTest { - - private static final String TEST_STRING = "This is a string!"; - // "This is a String!" - private static final String TEST_STRING_HEX_ISO8859_1 = "54 68 69 73 20 69 73 20 61 20 73 74 72 69 6e 67 21"; - // γειά σου - private static final String UNICODE_TEST_STRING = "\u03B3\u03B5\u03B9\u03AC \u03C3\u03BF\u03C5"; - // "γειά σου" (This can't be encoded in ISO-8859-1) - private static final String UNICODE_TEST_STRING_HEX_UTF8 = "ce b3 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85"; - // "γειά σου" (This can't be encoded in ISO-8859-1) - private static final String UNICODE_TEST_STRING_HEX_UTF16LE = "b3 03 b5 03 b9 03 ac 03 20 00 c3 03 bf 03 c5 03"; - // "γειά σου" (This can't be encoded in ISO-8859-1) - private static final String UNICODE_TEST_STRING_HEX_UTF16BE = "03 b3 03 b5 03 b9 03 ac 00 20 03 c3 03 bf 03 c5"; - - private static final byte[] BUFFER_WITH_A_BACK_TICK = {(byte) 0x49, (byte) 0x60, (byte) 0x6D}; - - @Test - public void shouldConstructFromStringOrBytes() { - EncodedText encodedText, encodedText2; - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_STRING); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TestHelper.hexStringToBytes(TEST_STRING_HEX_ISO8859_1)); - assertEquals(encodedText, encodedText2); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, UNICODE_TEST_STRING); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, TestHelper.hexStringToBytes(UNICODE_TEST_STRING_HEX_UTF8)); - assertEquals(encodedText, encodedText2); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, UNICODE_TEST_STRING); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TestHelper.hexStringToBytes(UNICODE_TEST_STRING_HEX_UTF16LE)); - assertEquals(encodedText, encodedText2); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16BE, UNICODE_TEST_STRING); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16BE, TestHelper.hexStringToBytes(UNICODE_TEST_STRING_HEX_UTF16BE)); - assertEquals(encodedText, encodedText2); - } - - @Test - public void shouldUseAppropriateEncodingWhenConstructingFromStringOnly() { - EncodedText encodedText; - String s; - encodedText = new EncodedText(TEST_STRING); - s = encodedText.toString(); - assertNotNull(s); - encodedText = new EncodedText(UNICODE_TEST_STRING); - s = encodedText.toString(); - assertNotNull(s); - } - - @Test - public void shouldEncodeAndDecodeISO8859_1Text() { - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_STRING); - assertEquals(EncodedText.CHARSET_ISO_8859_1, encodedText.getCharacterSet()); - assertEquals(TEST_STRING, encodedText.toString()); - EncodedText encodedText2; - byte[] bytes; - // no bom & no terminator - bytes = encodedText.toBytes(); - assertEquals(TEST_STRING_HEX_ISO8859_1, TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, bytes); - assertEquals(encodedText, encodedText2); - // bom & no terminator - bytes = encodedText.toBytes(true); - assertEquals(TEST_STRING_HEX_ISO8859_1, TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, bytes); - assertEquals(encodedText, encodedText2); - // no bom & terminator - bytes = encodedText.toBytes(false, true); - assertEquals(TEST_STRING_HEX_ISO8859_1 + " 00", TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, bytes); - assertEquals(encodedText, encodedText2); - // bom & terminator - bytes = encodedText.toBytes(true, true); - assertEquals(TEST_STRING_HEX_ISO8859_1 + " 00", TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, bytes); - assertEquals(encodedText, encodedText2); - } - - @Test - public void shouldEncodeAndDecodeUTF8Text() { - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, UNICODE_TEST_STRING); - assertEquals(EncodedText.CHARSET_UTF_8, encodedText.getCharacterSet()); - assertEquals(UNICODE_TEST_STRING, encodedText.toString()); - EncodedText encodedText2; - byte[] bytes; - // no bom & no terminator - bytes = encodedText.toBytes(); - String c = TestHelper.bytesToHexString(bytes); - assertEquals(UNICODE_TEST_STRING_HEX_UTF8, c); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, bytes); - assertEquals(encodedText, encodedText2); - // bom & no terminator - bytes = encodedText.toBytes(true); - assertEquals(UNICODE_TEST_STRING_HEX_UTF8, TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, bytes); - assertEquals(encodedText, encodedText2); - // no bom & terminator - bytes = encodedText.toBytes(false, true); - assertEquals(UNICODE_TEST_STRING_HEX_UTF8 + " 00", TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, bytes); - assertEquals(encodedText, encodedText2); - // bom & terminator - bytes = encodedText.toBytes(true, true); - assertEquals(UNICODE_TEST_STRING_HEX_UTF8 + " 00", TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, bytes); - assertEquals(encodedText, encodedText2); - } - - @Test - public void shouldEncodeAndDecodeUTF16Text() { - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, UNICODE_TEST_STRING); - assertEquals(EncodedText.CHARSET_UTF_16, encodedText.getCharacterSet()); - assertEquals(UNICODE_TEST_STRING, encodedText.toString()); - byte[] bytes; - EncodedText encodedText2; - // no bom & no terminator - bytes = encodedText.toBytes(); - assertEquals(UNICODE_TEST_STRING_HEX_UTF16LE, TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, bytes); - assertEquals(encodedText, encodedText2); - // bom & no terminator - bytes = encodedText.toBytes(true); - assertEquals("ff fe " + UNICODE_TEST_STRING_HEX_UTF16LE, TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, bytes); - assertEquals(encodedText, encodedText2); - // no bom & terminator - bytes = encodedText.toBytes(false, true); - assertEquals(UNICODE_TEST_STRING_HEX_UTF16LE + " 00 00", TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, bytes); - assertEquals(encodedText, encodedText2); - // bom & terminator - bytes = encodedText.toBytes(true, true); - assertEquals("ff fe " + UNICODE_TEST_STRING_HEX_UTF16LE + " 00 00", TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, bytes); - assertEquals(encodedText, encodedText2); - } - - @Test - public void shouldEncodeAndDecodeUTF16BEText() { - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16BE, UNICODE_TEST_STRING); - assertEquals(EncodedText.CHARSET_UTF_16BE, encodedText.getCharacterSet()); - assertEquals(UNICODE_TEST_STRING, encodedText.toString()); - byte[] bytes; - EncodedText encodedText2; - // no bom & no terminator - bytes = encodedText.toBytes(); - assertEquals(UNICODE_TEST_STRING_HEX_UTF16BE, TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16BE, bytes); - assertEquals(encodedText, encodedText2); - // bom & no terminator - bytes = encodedText.toBytes(true); - assertEquals("fe ff " + UNICODE_TEST_STRING_HEX_UTF16BE, TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16BE, bytes); - assertEquals(encodedText, encodedText2); - // no bom & terminator - bytes = encodedText.toBytes(false, true); - assertEquals(UNICODE_TEST_STRING_HEX_UTF16BE + " 00 00", TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16BE, bytes); - assertEquals(encodedText, encodedText2); - // bom & terminator - bytes = encodedText.toBytes(true, true); - assertEquals("fe ff " + UNICODE_TEST_STRING_HEX_UTF16BE + " 00 00", TestHelper.bytesToHexString(bytes)); - encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16BE, bytes); - assertEquals(encodedText, encodedText2); - } - - @Test - public void UTF16ShouldDecodeBEWhenSpecifiedInBOM() { - // id3 v2.2 and 2.3: encoding set to UTF_16 (type 1), but BOM set to big endian, so interpret as UTF_16BE - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16BE, UNICODE_TEST_STRING); - byte[] bytes = encodedText.toBytes(true, true); - EncodedText encodedText2 = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, bytes); - assertEquals(encodedText, encodedText2); - } - - @Test - public void shouldThrowExceptionWhenEncodingWithInvalidCharacterSet() { - try { - new EncodedText((byte) 4, TEST_STRING); - fail("IllegalArgumentException expected but not thrown"); - } catch (IllegalArgumentException e) { - assertEquals("Invalid text encoding 4", e.getMessage()); - } - } - - @Test - public void shouldInferISO8859_1EncodingFromBytesWithNoBOM() { - EncodedText encodedText = new EncodedText(TestHelper.hexStringToBytes(TEST_STRING_HEX_ISO8859_1)); - assertEquals(EncodedText.TEXT_ENCODING_ISO_8859_1, encodedText.getTextEncoding()); - } - - @Test - public void shouldDetectUTF8EncodingFromBytesWithBOM() { - EncodedText encodedText = new EncodedText(TestHelper.hexStringToBytes("ef bb bf " + UNICODE_TEST_STRING_HEX_UTF8)); - assertEquals(EncodedText.TEXT_ENCODING_UTF_8, encodedText.getTextEncoding()); - } - - @Test - public void shouldDetectUTF16EncodingFromBytesWithBOM() { - EncodedText encodedText = new EncodedText(TestHelper.hexStringToBytes("ff fe " + UNICODE_TEST_STRING_HEX_UTF16LE)); - assertEquals(EncodedText.TEXT_ENCODING_UTF_16, encodedText.getTextEncoding()); - } - - @Test - public void shouldDetectUTF16BEEncodingFromBytesWithBOM() { - EncodedText encodedText = new EncodedText(TestHelper.hexStringToBytes("fe ff " + UNICODE_TEST_STRING_HEX_UTF16BE)); - assertEquals(EncodedText.TEXT_ENCODING_UTF_16BE, encodedText.getTextEncoding()); - } - - @Test - public void shouldTranscodeFromOneEncodingToAnother() throws CharacterCodingException { - EncodedText encodedText; - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, TestHelper.hexStringToBytes("43 61 66 c3 a9 20 50 61 72 61 64 69 73 6f")); - encodedText.setTextEncoding(EncodedText.TEXT_ENCODING_ISO_8859_1, true); - assertEquals("43 61 66 e9 20 50 61 72 61 64 69 73 6f", TestHelper.bytesToHexString(encodedText.toBytes())); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, TestHelper.hexStringToBytes("43 61 66 c3 a9 20 50 61 72 61 64 69 73 6f")); - encodedText.setTextEncoding(EncodedText.TEXT_ENCODING_UTF_8, true); - assertEquals("43 61 66 c3 a9 20 50 61 72 61 64 69 73 6f", TestHelper.bytesToHexString(encodedText.toBytes())); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, TestHelper.hexStringToBytes("43 61 66 c3 a9 20 50 61 72 61 64 69 73 6f")); - encodedText.setTextEncoding(EncodedText.TEXT_ENCODING_UTF_16, true); - assertEquals("43 00 61 00 66 00 e9 00 20 00 50 00 61 00 72 00 61 00 64 00 69 00 73 00 6f 00", TestHelper.bytesToHexString(encodedText.toBytes())); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, TestHelper.hexStringToBytes("43 61 66 c3 a9 20 50 61 72 61 64 69 73 6f")); - encodedText.setTextEncoding(EncodedText.TEXT_ENCODING_UTF_16BE, true); - assertEquals("00 43 00 61 00 66 00 e9 00 20 00 50 00 61 00 72 00 61 00 64 00 69 00 73 00 6f", TestHelper.bytesToHexString(encodedText.toBytes())); - } - - @Test(expected = CharacterCodingException.class) - public void shouldThrowAnExceptionWhenAttemptingToTranscodeToACharacterSetWithUnmappableCharacters() throws CharacterCodingException { - // given - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, UNICODE_TEST_STRING); - - // expect exception - encodedText.setTextEncoding(EncodedText.TEXT_ENCODING_ISO_8859_1, true); - } - - @Test - public void shouldThrowExceptionWhenTranscodingWithInvalidCharacterSet() throws CharacterCodingException { - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, TestHelper.hexStringToBytes("43 61 66 c3 a9 20 50 61 72 61 64 69 73 6f")); - try { - encodedText.setTextEncoding((byte) 4, true); - fail("IllegalArgumentException expected but not thrown"); - } catch (IllegalArgumentException e) { - assertEquals("Invalid text encoding 4", e.getMessage()); - } - } - - @Test - public void shouldReturnNullWhenDecodingInvalidString() throws UnsupportedEncodingException { - String s = "Not unicode"; - byte[] notUnicode = BufferTools.stringToByteBuffer(s, 0, s.length()); - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, notUnicode); - assertNull(encodedText.toString()); - } - - @Test - public void shouldHandleBacktickCharacterInString() { - EncodedText encodedText = new EncodedText((byte) 0, BUFFER_WITH_A_BACK_TICK); - assertEquals("I" + (char) (96) + "m", encodedText.toString()); - } - - @Test - public void shouldStillReturnBytesWhenStringIsEmpty() { - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, ""); - assertArrayEquals(new byte[]{}, encodedText.toBytes(false, false)); - assertArrayEquals(new byte[]{}, encodedText.toBytes(true, false)); - assertArrayEquals(new byte[]{0}, encodedText.toBytes(false, true)); - assertArrayEquals(new byte[]{0}, encodedText.toBytes(true, true)); - } - - @Test - public void shouldStillReturnBytesWhenUnicodeStringIsEmpty() { - EncodedText encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, ""); - assertArrayEquals(new byte[]{}, encodedText.toBytes(false, false)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe}, encodedText.toBytes(true, false)); - assertArrayEquals(new byte[]{0, 0}, encodedText.toBytes(false, true)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe, 0, 0}, encodedText.toBytes(true, true)); - } - - @Test - public void shouldStillReturnBytesWhenDataIsEmpty() { - EncodedText encodedText; - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, new byte[]{}); - assertArrayEquals(new byte[]{}, encodedText.toBytes(false, false)); - assertArrayEquals(new byte[]{}, encodedText.toBytes(true, false)); - assertArrayEquals(new byte[]{0}, encodedText.toBytes(false, true)); - assertArrayEquals(new byte[]{0}, encodedText.toBytes(true, true)); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, new byte[]{0}); - assertArrayEquals(new byte[]{}, encodedText.toBytes(false, false)); - assertArrayEquals(new byte[]{}, encodedText.toBytes(true, false)); - assertArrayEquals(new byte[]{0}, encodedText.toBytes(false, true)); - assertArrayEquals(new byte[]{0}, encodedText.toBytes(true, true)); - } - - @Test - public void shouldStillReturnBytesWhenUnicodeDataIsEmpty() { - EncodedText encodedText; - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, new byte[]{}); - assertArrayEquals(new byte[]{}, encodedText.toBytes(false, false)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe}, encodedText.toBytes(true, false)); - assertArrayEquals(new byte[]{0, 0}, encodedText.toBytes(false, true)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe, 0, 0}, encodedText.toBytes(true, true)); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, new byte[]{0, 0}); - assertArrayEquals(new byte[]{}, encodedText.toBytes(false, false)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe}, encodedText.toBytes(true, false)); - assertArrayEquals(new byte[]{0, 0}, encodedText.toBytes(false, true)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe, 0, 0}, encodedText.toBytes(true, true)); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, new byte[]{(byte) 0xff, (byte) 0xfe}); - assertArrayEquals(new byte[]{}, encodedText.toBytes(false, false)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe}, encodedText.toBytes(true, false)); - assertArrayEquals(new byte[]{0, 0}, encodedText.toBytes(false, true)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe, 0, 0}, encodedText.toBytes(true, true)); - encodedText = new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, new byte[]{(byte) 0xff, (byte) 0xfe, 0, 0}); - assertArrayEquals(new byte[]{}, encodedText.toBytes(false, false)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe}, encodedText.toBytes(true, false)); - assertArrayEquals(new byte[]{0, 0}, encodedText.toBytes(false, true)); - assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe, 0, 0}, encodedText.toBytes(true, true)); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/FileWrapperTest.java b/src/test/java/com/mpatric/mp3agic/FileWrapperTest.java deleted file mode 100644 index 15f6699..0000000 --- a/src/test/java/com/mpatric/mp3agic/FileWrapperTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.InvalidPathException; -import java.nio.file.Paths; - -import static org.junit.Assert.*; - -public class FileWrapperTest { - private static final String fs = File.separator; - private static final String VALID_FILENAME = "src" + fs + "test" + fs + "resources" + fs + "notags.mp3"; - private static final long VALID_FILE_LENGTH = 2869; - private static final String NON_EXISTENT_FILENAME = "just-not.there"; - private static final String MALFORMED_FILENAME = "malformed.\0"; - - @Test - public void shouldReadValidFilename() throws IOException { - FileWrapper fileWrapper = new FileWrapper(VALID_FILENAME); - System.out.println(fileWrapper.getFilename()); - System.out.println(VALID_FILENAME); - assertEquals(fileWrapper.getFilename(), VALID_FILENAME); - assertTrue(fileWrapper.getLastModified() > 0); - assertEquals(fileWrapper.getLength(), VALID_FILE_LENGTH); - } - - @Test - public void shouldReadValidFile() throws IOException { - FileWrapper fileWrapper = new FileWrapper(new File(VALID_FILENAME)); - System.out.println(fileWrapper.getFilename()); - System.out.println(VALID_FILENAME); - assertEquals(fileWrapper.getFilename(), VALID_FILENAME); - assertTrue(fileWrapper.getLastModified() > 0); - assertEquals(fileWrapper.getLength(), VALID_FILE_LENGTH); - } - - @Test - public void shouldReadValidPath() throws IOException { - FileWrapper fileWrapper = new FileWrapper(Paths.get(VALID_FILENAME)); - System.out.println(fileWrapper.getFilename()); - System.out.println(VALID_FILENAME); - assertEquals(fileWrapper.getFilename(), VALID_FILENAME); - assertTrue(fileWrapper.getLastModified() > 0); - assertEquals(fileWrapper.getLength(), VALID_FILE_LENGTH); - } - - @Test(expected = FileNotFoundException.class) - public void shouldFailForNonExistentFile() throws IOException { - new FileWrapper(NON_EXISTENT_FILENAME); - } - - @Test(expected = InvalidPathException.class) - public void shouldFailForMalformedFilename() throws IOException { - new FileWrapper(MALFORMED_FILENAME); - } - - @Test(expected = NullPointerException.class) - public void shouldFailForNullFilename() throws IOException { - new FileWrapper((String) null); - } - - @Test(expected = NullPointerException.class) - public void shouldFailForNullFilenameFile() throws IOException { - new FileWrapper((java.io.File) null); - } - - @Test(expected = NullPointerException.class) - public void shouldFailForNullPath() throws IOException { - new FileWrapper((java.nio.file.Path) null); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3WrapperTest.java b/src/test/java/com/mpatric/mp3agic/ID3WrapperTest.java deleted file mode 100644 index 2533a75..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3WrapperTest.java +++ /dev/null @@ -1,1440 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -public class ID3WrapperTest { - //region getId3v1Tag - @Test - public void returnsV1Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals(id3v1Tag, wrapper.getId3v1Tag()); - } - - @Test - public void returnsNullV1Tag() { - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - assertEquals(null, wrapper.getId3v1Tag()); - } - //endregion - - //region getId3v2Tag - @Test - public void returnsV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals(id3v2Tag, wrapper.getId3v2Tag()); - } - - @Test - public void returnsNullV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals(null, wrapper.getId3v2Tag()); - } - //endregion - - //region getTrack - @Test - public void getTrackReturnsV2TagsTrackBeforeV1TagsTrack() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setTrack("V1 Track"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setTrack("V2 Track"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Track", wrapper.getTrack()); - } - - @Test - public void getTrackReturnsV1TagsTrackIfV2TagsTrackIsEmpty() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setTrack("V1 Track"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setTrack(""); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Track", wrapper.getTrack()); - } - - @Test - public void getTrackReturnsV1TagsTrackIfV2TagsTrackDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setTrack("V1 Track"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setTrack(null); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Track", wrapper.getTrack()); - } - - @Test - public void getTrackReturnsV1TagsTrackIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setTrack("V1 Track"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals("V1 Track", wrapper.getTrack()); - } - - @Test - public void getTrackReturnsNullIfBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - assertNull(wrapper.getTrack()); - } - //endregion - - //region setTrack - @Test - public void setsTrackOnBothV1AndV2Tags() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setTrack("a track"); - assertEquals("a track", id3v1Tag.getTrack()); - assertEquals("a track", id3v2Tag.getTrack()); - } - - @Test - public void setsTrackOnV1TagOnly() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setTrack("a track"); - assertEquals("a track", id3v1Tag.getTrack()); - } - - @Test - public void setsTrackOnV2TagOnly() { - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.setTrack("a track"); - assertEquals("a track", id3v2Tag.getTrack()); - } - - @Test - public void setTrackDoesNotThrowExceptionWhenBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.setTrack("a track"); - } - //endregion - - //region getArtist - @Test - public void getArtistReturnsV2TagsArtistBeforeV1TagsArtist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setArtist("V1 Artist"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setArtist("V2 Artist"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Artist", wrapper.getArtist()); - } - - @Test - public void getArtistReturnsV1TagsArtistIfV2TagsArtistIsEmpty() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setArtist("V1 Artist"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setArtist(""); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Artist", wrapper.getArtist()); - } - - @Test - public void getArtistReturnsV1TagsArtistIfV2TagsArtistDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setArtist("V1 Artist"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setArtist(null); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Artist", wrapper.getArtist()); - } - - @Test - public void getArtistReturnsV1TagsArtistIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setArtist("V1 Artist"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals("V1 Artist", wrapper.getArtist()); - } - - @Test - public void getArtistReturnsNullIfBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - assertNull(wrapper.getArtist()); - } - //endregion - - //region setArtist - @Test - public void setsArtistOnBothV1AndV2Tags() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setArtist("an artist"); - assertEquals("an artist", id3v1Tag.getArtist()); - assertEquals("an artist", id3v2Tag.getArtist()); - } - - @Test - public void setsArtistOnV1TagOnly() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setArtist("an artist"); - assertEquals("an artist", id3v1Tag.getArtist()); - } - - @Test - public void setsArtistOnV2TagOnly() { - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.setArtist("an artist"); - assertEquals("an artist", id3v2Tag.getArtist()); - } - - @Test - public void setArtistDoesNotThrowExceptionWhenBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.setArtist("an artist"); - } - //endregion - - //region getTitle - @Test - public void getTitleReturnsV2TagsTitleBeforeV1TagsTitle() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setTitle("V1 Title"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setTitle("V2 Title"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Title", wrapper.getTitle()); - } - - @Test - public void getTitleReturnsV1TagsTitleIfV2TagsTitleIsEmpty() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setTitle("V1 Title"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setTitle(""); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Title", wrapper.getTitle()); - } - - @Test - public void getTitleReturnsV1TagsTitleIfV2TagsTitleDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setTitle("V1 Title"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setTitle(null); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Title", wrapper.getTitle()); - } - - @Test - public void getTitleReturnsV1TagsTitleIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setTitle("V1 Title"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals("V1 Title", wrapper.getTitle()); - } - - @Test - public void getTitleReturnsNullIfBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - assertNull(wrapper.getTitle()); - } - //endregion - - //region setTitle - @Test - public void setsTitleOnBothV1AndV2Tags() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setTitle("a title"); - assertEquals("a title", id3v1Tag.getTitle()); - assertEquals("a title", id3v2Tag.getTitle()); - } - - @Test - public void setsTitleOnV1TagOnly() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setTitle("a title"); - assertEquals("a title", id3v1Tag.getTitle()); - } - - @Test - public void setsTitleOnV2TagOnly() { - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.setTitle("a title"); - assertEquals("a title", id3v2Tag.getTitle()); - } - - @Test - public void setTitleDoesNotThrowExceptionWhenBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.setTitle("a title"); - } - //endregion - - //region getAlbum - @Test - public void getAlbumReturnsV2TagsAlbumBeforeV1TagsAlbum() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setAlbum("V1 Album"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setAlbum("V2 Album"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Album", wrapper.getAlbum()); - } - - @Test - public void getAlbumReturnsV1TagsAlbumIfV2TagsAlbumIsEmpty() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setAlbum("V1 Album"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setAlbum(""); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Album", wrapper.getAlbum()); - } - - @Test - public void getAlbumReturnsV1TagsAlbumIfV2TagsAlbumDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setAlbum("V1 Album"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setAlbum(null); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Album", wrapper.getAlbum()); - } - - @Test - public void getAlbumReturnsV1TagsAlbumIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setAlbum("V1 Album"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals("V1 Album", wrapper.getAlbum()); - } - - @Test - public void getAlbumReturnsNullIfBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - assertNull(wrapper.getAlbum()); - } - //endregion - - //region setAlbum - @Test - public void setsAlbumOnBothV1AndV2Tags() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setAlbum("an album"); - assertEquals("an album", id3v1Tag.getAlbum()); - assertEquals("an album", id3v2Tag.getAlbum()); - } - - @Test - public void setsAlbumOnV1TagOnly() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setAlbum("an album"); - assertEquals("an album", id3v1Tag.getAlbum()); - } - - @Test - public void setsAlbumOnV2TagOnly() { - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.setAlbum("an album"); - assertEquals("an album", id3v2Tag.getAlbum()); - } - - @Test - public void setAlbumDoesNotThrowExceptionWhenBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.setAlbum("an album"); - } - //endregion - - //region getYear - @Test - public void getYearReturnsV2TagsYearBeforeV1TagsYear() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setYear("V1 Year"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setYear("V2 Year"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Year", wrapper.getYear()); - } - - @Test - public void getYearReturnsV1TagsYearIfV2TagsYearIsEmpty() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setYear("V1 Year"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setYear(""); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Year", wrapper.getYear()); - } - - @Test - public void getYearReturnsV1TagsYearIfV2TagsYearDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setYear("V1 Year"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setYear(null); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Year", wrapper.getYear()); - } - - @Test - public void getYearReturnsV1TagsYearIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setYear("V1 Year"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals("V1 Year", wrapper.getYear()); - } - - @Test - public void getYearReturnsNullIfBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - assertNull(wrapper.getYear()); - } - //endregion - - //region setYear - @Test - public void setsYearOnBothV1AndV2Tags() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setYear("a year"); - assertEquals("a year", id3v1Tag.getYear()); - assertEquals("a year", id3v2Tag.getYear()); - } - - @Test - public void setsYearOnV1TagOnly() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setYear("a year"); - assertEquals("a year", id3v1Tag.getYear()); - } - - @Test - public void setsYearOnV2TagOnly() { - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.setYear("a year"); - assertEquals("a year", id3v2Tag.getYear()); - } - - @Test - public void setYearDoesNotThrowExceptionWhenBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.setYear("a year"); - } - //endregion - - //region getGenre - @Test - public void getGenreReturnsV2TagsGenreBeforeV1TagsGenre() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setGenre(10); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setGenre(20); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals(20, wrapper.getGenre()); - } - - @Test - public void getGenreReturnsV1TagsGenreIfV2TagsGenreIsNegativeOne() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setGenre(10); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setGenre(-1); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals(10, wrapper.getGenre()); - } - - @Test - public void getGenreReturnsV1TagsGenreIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setGenre(10); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals(10, wrapper.getGenre()); - } - - @Test - public void getGenreReturnsNegativeOneIfBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - assertEquals(-1, wrapper.getGenre()); - } - //endregion - - //region setGenre - @Test - public void setsGenreOnBothV1AndV2Tags() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setGenre(22); - assertEquals(22, id3v1Tag.getGenre()); - assertEquals(22, id3v2Tag.getGenre()); - } - - @Test - public void setsGenreOnV1TagOnly() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setGenre(22); - assertEquals(22, id3v1Tag.getGenre()); - } - - @Test - public void setsGenreOnV2TagOnly() { - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.setGenre(22); - assertEquals(22, id3v2Tag.getGenre()); - } - - @Test - public void setGenreDoesNotThrowExceptionWhenBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.setGenre(22); - } - //endregion - - //region getGenreDescription - @Test - public void getGenreDescriptionReturnsV2TagsGenreDescriptionBeforeV1TagsGenreDescription() { - ID3v1TagForTesting id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setGenreDescription("V1 GenreDescription"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setGenreDescription("V2 GenreDescription"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 GenreDescription", wrapper.getGenreDescription()); - } - - @Test - public void getGenreDescriptionReturnsV1TagsGenreDescriptionIfV2TagDoesNotExist() { - ID3v1TagForTesting id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setGenreDescription("V1 GenreDescription"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals("V1 GenreDescription", wrapper.getGenreDescription()); - } - - @Test - public void getGenreDescriptionReturnsNullIfBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - assertNull(wrapper.getGenreDescription()); - } - //endregion - - //region getComment - @Test - public void getCommentReturnsV2TagsCommentBeforeV1TagsComment() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setComment("V1 Comment"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setComment("V2 Comment"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Comment", wrapper.getComment()); - } - - @Test - public void getCommentReturnsV1TagsCommentIfV2TagsCommentIsEmpty() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setComment("V1 Comment"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setComment(""); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Comment", wrapper.getComment()); - } - - @Test - public void getCommentReturnsV1TagsCommentIfV2TagsCommentDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setComment("V1 Comment"); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setComment(null); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V1 Comment", wrapper.getComment()); - } - - @Test - public void getCommentReturnsV1TagsCommentIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setComment("V1 Comment"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertEquals("V1 Comment", wrapper.getComment()); - } - - @Test - public void getCommentReturnsNullIfBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - assertNull(wrapper.getComment()); - } - //endregion - - //region setComment - @Test - public void setsCommentOnBothV1AndV2Tags() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setComment("a comment"); - assertEquals("a comment", id3v1Tag.getComment()); - assertEquals("a comment", id3v2Tag.getComment()); - } - - @Test - public void setsCommentOnV1TagOnly() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setComment("a comment"); - assertEquals("a comment", id3v1Tag.getComment()); - } - - @Test - public void setsCommentOnV2TagOnly() { - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.setComment("a comment"); - assertEquals("a comment", id3v2Tag.getComment()); - } - - @Test - public void setCommentDoesNotThrowExceptionWhenBothTagsDoNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.setComment("a comment"); - } - //endregion - - //region getComposer - @Test - public void getComposerReturnsV2TagsComposer() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setComposer("V2 Composer"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Composer", wrapper.getComposer()); - } - - @Test - public void getComposerReturnsNullIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertNull(wrapper.getComposer()); - } - //endregion - - //region setComposer - @Test - public void setsComposerOnV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setComposer("a composer"); - assertEquals("a composer", id3v2Tag.getComposer()); - } - - @Test - public void setComposerDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setComposer("a composer"); - } - //endregion - - //region getOriginalArtist - @Test - public void getOriginalArtistReturnsV2TagsOriginalArtist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setOriginalArtist("V2 OriginalArtist"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 OriginalArtist", wrapper.getOriginalArtist()); - } - - @Test - public void getOriginalArtistReturnsNullIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertNull(wrapper.getOriginalArtist()); - } - //endregion - - //region setOriginalArtist - @Test - public void setsOriginalArtistOnV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setOriginalArtist("an original artist"); - assertEquals("an original artist", id3v2Tag.getOriginalArtist()); - } - - @Test - public void setOriginalArtistDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setOriginalArtist("an original artist"); - } - //endregion - - //region getAlbumArtist - @Test - public void getAlbumArtistReturnsV2TagsAlbumArtist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setAlbumArtist("V2 AlbumArtist"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 AlbumArtist", wrapper.getAlbumArtist()); - } - - @Test - public void getAlbumArtistReturnsNullIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertNull(wrapper.getAlbumArtist()); - } - //endregion - - //region setAlbumArtist - @Test - public void setsAlbumArtistOnV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setAlbumArtist("an album artist"); - assertEquals("an album artist", id3v2Tag.getAlbumArtist()); - } - - @Test - public void setAlbumArtistDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setAlbumArtist("an album artist"); - } - //endregion - - //region getCopyright - @Test - public void getCopyrightReturnsV2TagsCopyright() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setCopyright("V2 Copyright"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Copyright", wrapper.getCopyright()); - } - - @Test - public void getCopyrightReturnsNullIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertNull(wrapper.getCopyright()); - } - //endregion - - //region setCopyright - @Test - public void setsCopyrightOnV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setCopyright("a copyright"); - assertEquals("a copyright", id3v2Tag.getCopyright()); - } - - @Test - public void setCopyrightDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setCopyright("a copyright"); - } - //endregion - - //region getUrl - @Test - public void getUrlReturnsV2TagsUrl() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setUrl("V2 Url"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Url", wrapper.getUrl()); - } - - @Test - public void getUrlReturnsNullIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertNull(wrapper.getUrl()); - } - //endregion - - //region setUrl - @Test - public void setsUrlOnV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setUrl("a url"); - assertEquals("a url", id3v2Tag.getUrl()); - } - - @Test - public void setUrlDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setUrl("a url"); - } - //endregion - - //region getEncoder - @Test - public void getEncoderReturnsV2TagsEncoder() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setEncoder("V2 Encoder"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Encoder", wrapper.getEncoder()); - } - - @Test - public void getEncoderReturnsNullIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertNull(wrapper.getEncoder()); - } - //endregion - - //region setEncoder - @Test - public void setsEncoderOnV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setEncoder("an encoder"); - assertEquals("an encoder", id3v2Tag.getEncoder()); - } - - @Test - public void setEncoderDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setEncoder("an encoder"); - } - //endregion - - //region getAlbumImage and getAlbumImageMimeType - @Test - public void getAlbumImageReturnsV2TagsAlbumImage() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setAlbumImage(new byte[]{12, 4, 7}, "mime type"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertArrayEquals(new byte[]{12, 4, 7}, wrapper.getAlbumImage()); - assertEquals("mime type", wrapper.getAlbumImageMimeType()); - } - - @Test - public void getAlbumImageReturnsNullIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertNull(wrapper.getAlbumImage()); - assertNull(wrapper.getAlbumImageMimeType()); - } - //endregion - - //region setAlbumImage - @Test - public void setsAlbumImageOnV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setAlbumImage(new byte[]{12, 4, 7}, "mime type"); - assertArrayEquals(new byte[]{12, 4, 7}, id3v2Tag.getAlbumImage()); - assertEquals("mime type", id3v2Tag.getAlbumImageMimeType()); - } - - @Test - public void setAlbumImageDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setAlbumImage(new byte[]{12, 4, 7}, "mime type"); - } - //endregion - - //region getLyrics - @Test - public void getLyricsReturnsV2TagsLyrics() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.setLyrics("V2 Lyrics"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - assertEquals("V2 Lyrics", wrapper.getLyrics()); - } - - @Test - public void getLyricsReturnsNullIfV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - assertNull(wrapper.getLyrics()); - } - //endregion - - //region setLyrics - @Test - public void setsLyricsOnV2Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3v2 id3v2Tag = new ID3v2TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, id3v2Tag); - wrapper.setLyrics("lyrics"); - assertEquals("lyrics", id3v2Tag.getLyrics()); - } - - @Test - public void setLyricsDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.setLyrics("lyrics"); - } - //endregion - - //region clearComment - @Test - public void clearsCommentOnV1Tag() { - ID3v1 id3v1Tag = new ID3v1TagForTesting(); - id3v1Tag.setComment("a comment"); - ID3Wrapper wrapper = new ID3Wrapper(id3v1Tag, null); - wrapper.clearComment(); - assertNull(id3v1Tag.getComment()); - } - - @Test - public void clearsCommentFrameOnV2Tag() { - ID3v2TagForTesting id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.addFrameSet(AbstractID3v2Tag.ID_COMMENT, new ID3v2FrameSet(AbstractID3v2Tag.ID_COMMENT)); - assertTrue(id3v2Tag.getFrameSets().containsKey(AbstractID3v2Tag.ID_COMMENT)); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.clearComment(); - assertFalse(id3v2Tag.getFrameSets().containsKey(AbstractID3v2Tag.ID_COMMENT)); - } - //endregion - - //region clearCopyright - @Test - public void clearsCopyrightFrameOnV2Tag() { - ID3v2TagForTesting id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.addFrameSet(AbstractID3v2Tag.ID_COPYRIGHT, new ID3v2FrameSet(AbstractID3v2Tag.ID_COPYRIGHT)); - assertTrue(id3v2Tag.getFrameSets().containsKey(AbstractID3v2Tag.ID_COPYRIGHT)); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.clearCopyright(); - assertFalse(id3v2Tag.getFrameSets().containsKey(AbstractID3v2Tag.ID_COPYRIGHT)); - } - - @Test - public void clearCopyrightDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.clearCopyright(); - } - //endregion - - //region clearCopyright - @Test - public void clearsEncoderFrameOnV2Tag() { - ID3v2TagForTesting id3v2Tag = new ID3v2TagForTesting(); - id3v2Tag.addFrameSet(AbstractID3v2Tag.ID_ENCODER, new ID3v2FrameSet(AbstractID3v2Tag.ID_ENCODER)); - assertTrue(id3v2Tag.getFrameSets().containsKey(AbstractID3v2Tag.ID_ENCODER)); - ID3Wrapper wrapper = new ID3Wrapper(null, id3v2Tag); - wrapper.clearEncoder(); - assertFalse(id3v2Tag.getFrameSets().containsKey(AbstractID3v2Tag.ID_ENCODER)); - } - - @Test - public void clearEncoderDoesNotThrowExceptionWhenV2TagDoesNotExist() { - ID3Wrapper wrapper = new ID3Wrapper(null, null); - wrapper.clearEncoder(); - } - //endregion - - //region ID3v1TagForTesting class - private static class ID3v1TagForTesting implements ID3v1 { - private String track; - private String artist; - private String title; - private String album; - private String year; - private int genre; - protected String genreDescription; - private String comment; - - @Override - public String getVersion() { - return null; - } - - @Override - public String getTrack() { - return track; - } - - @Override - public void setTrack(String track) { - this.track = track; - } - - @Override - public String getArtist() { - return artist; - } - - @Override - public void setArtist(String artist) { - this.artist = artist; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public void setTitle(String title) { - this.title = title; - } - - @Override - public String getAlbum() { - return album; - } - - @Override - public void setAlbum(String album) { - this.album = album; - } - - @Override - public String getYear() { - return year; - } - - @Override - public void setYear(String year) { - this.year = year; - } - - @Override - public int getGenre() { - return genre; - } - - @Override - public void setGenre(int genre) { - this.genre = genre; - } - - @Override - public String getGenreDescription() { - return genreDescription; - } - - public void setGenreDescription(String genreDescription) { - this.genreDescription = genreDescription; - } - - @Override - public String getComment() { - return comment; - } - - @Override - public void setComment(String comment) { - this.comment = comment; - } - - @Override - public byte[] toBytes() { - return new byte[0]; - } - } - //endregion - - //region ID3v2TagForTesting class - private static class ID3v2TagForTesting extends ID3v1TagForTesting implements ID3v2 { - private String composer; - private String originalArtist; - private String albumArtist; - private String copyright; - private String url; - private String encoder; - private byte[] albumImage; - private String albumImageMimeType; - private String lyrics; - private final Map frameSets = new HashMap<>(); - - @Override - public boolean getPadding() { - return false; - } - - @Override - public void setPadding(boolean padding) { - - } - - @Override - public boolean hasFooter() { - return false; - } - - @Override - public void setFooter(boolean footer) { - - } - - @Override - public boolean hasUnsynchronisation() { - return false; - } - - @Override - public void setUnsynchronisation(boolean unsynchronisation) { - - } - - @Override - public int getBPM() { - return 0; - } - - @Override - public void setBPM(int bpm) { - - } - - @Override - public String getGrouping() { - return null; - } - - @Override - public void setGrouping(String grouping) { - - } - - @Override - public String getKey() { - return null; - } - - @Override - public void setKey(String key) { - - } - - @Override - public String getDate() { - return null; - } - - @Override - public void setDate(String date) { - - } - - @Override - public String getComposer() { - return composer; - } - - @Override - public void setComposer(String composer) { - this.composer = composer; - } - - @Override - public String getPublisher() { - return null; - } - - @Override - public void setPublisher(String publisher) { - - } - - @Override - public String getOriginalArtist() { - return originalArtist; - } - - @Override - public void setOriginalArtist(String originalArtist) { - this.originalArtist = originalArtist; - } - - @Override - public String getAlbumArtist() { - return albumArtist; - } - - @Override - public void setAlbumArtist(String albumArtist) { - this.albumArtist = albumArtist; - } - - @Override - public String getCopyright() { - return copyright; - } - - @Override - public void setCopyright(String copyright) { - this.copyright = copyright; - } - - @Override - public String getArtistUrl() { - return null; - } - - @Override - public void setArtistUrl(String url) { - - } - - @Override - public String getCommercialUrl() { - return null; - } - - @Override - public void setCommercialUrl(String url) { - - } - - @Override - public String getCopyrightUrl() { - return null; - } - - @Override - public void setCopyrightUrl(String url) { - - } - - @Override - public String getAudiofileUrl() { - return null; - } - - @Override - public void setAudiofileUrl(String url) { - - } - - @Override - public String getAudioSourceUrl() { - return null; - } - - @Override - public void setAudioSourceUrl(String url) { - - } - - @Override - public String getRadiostationUrl() { - return null; - } - - @Override - public void setRadiostationUrl(String url) { - - } - - @Override - public String getPaymentUrl() { - return null; - } - - @Override - public void setPaymentUrl(String url) { - - } - - @Override - public String getPublisherUrl() { - return null; - } - - @Override - public void setPublisherUrl(String url) { - - } - - @Override - public String getUrl() { - return url; - } - - @Override - public void setUrl(String url) { - this.url = url; - } - - @Override - public String getPartOfSet() { - return null; - } - - @Override - public void setPartOfSet(String partOfSet) { - - } - - @Override - public boolean isCompilation() { - return false; - } - - @Override - public void setCompilation(boolean compilation) { - - } - - @Override - public ArrayList getChapters() { - return null; - } - - @Override - public void setChapters(ArrayList chapters) { - - } - - @Override - public ArrayList getChapterTOC() { - return null; - } - - @Override - public void setChapterTOC(ArrayList ctoc) { - - } - - @Override - public String getEncoder() { - return encoder; - } - - @Override - public void setEncoder(String encoder) { - this.encoder = encoder; - } - - @Override - public byte[] getAlbumImage() { - return albumImage; - } - - @Override - public void setAlbumImage(byte[] albumImage, String mimeType) { - this.albumImage = albumImage; - this.albumImageMimeType = mimeType; - } - - @Override - public void setAlbumImage(byte[] albumImage, String mimeType, byte imageType, String imageDescription) { - - } - - @Override - public void clearAlbumImage() { - - } - - @Override - public String getAlbumImageMimeType() { - return albumImageMimeType; - } - - @Override - public int getWmpRating() { - return 0; - } - - @Override - public void setWmpRating(int rating) { - - } - - @Override - public String getItunesComment() { - return null; - } - - @Override - public void setItunesComment(String itunesComment) { - - } - - @Override - public String getLyrics() { - return lyrics; - } - - @Override - public void setLyrics(String lyrics) { - this.lyrics = lyrics; - } - - @Override - public void setGenreDescription(String text) { - this.genreDescription = text; - } - - @Override - public int getDataLength() { - return 0; - } - - @Override - public int getLength() { - return 0; - } - - @Override - public boolean getObseleteFormat() { - return false; - } - - @Override - public Map getFrameSets() { - return frameSets; - } - - public void addFrameSet(String id, ID3v2FrameSet frameSet) { - frameSets.put(id, frameSet); - } - - @Override - public void clearFrameSet(String id) { - frameSets.remove(id); - } - } - //endregion -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v1GenresTest.java b/src/test/java/com/mpatric/mp3agic/ID3v1GenresTest.java deleted file mode 100644 index 3b092c7..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v1GenresTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class ID3v1GenresTest { - - @Test - public void returnsMinusOneForNonExistentGenre() { - assertEquals(-1, ID3v1Genres.matchGenreDescription("non existent")); - } - - @Test - public void returnsCorrectGenreIdForFirstExistentGenre() { - assertEquals(0, ID3v1Genres.matchGenreDescription("Blues")); - } - - @Test - public void returnsCorrectGenreIdForPolka() { - assertEquals(75, ID3v1Genres.matchGenreDescription("Polka")); - } - - @Test - public void returnsCorrectGenreIdForLastExistentGenre() { - assertEquals(147, ID3v1Genres.matchGenreDescription("Synthpop")); - } - - @Test - public void ignoresCase() { - assertEquals(137, ID3v1Genres.matchGenreDescription("heavy METAL")); - } - -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v1TagTest.java b/src/test/java/com/mpatric/mp3agic/ID3v1TagTest.java deleted file mode 100644 index 6ee7263..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v1TagTest.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class ID3v1TagTest { - - private static final String VALID_TAG = "TAGTITLE1234567890123456789012345ARTIST123456789012345678901234ALBUM12345678901234567890123452001COMMENT123456789012345678901234"; - private static final String VALID_TAG_WITH_WHITESPACE = "TAGTITLE ARTIST ALBUM 2001COMMENT "; - - @Test(expected = NoSuchTagException.class) - public void shouldThrowExceptionForTagBufferTooShort() throws NoSuchTagException { - byte[] buffer = new byte[ID3v1Tag.TAG_LENGTH - 1]; - new ID3v1Tag(buffer); - } - - @Test(expected = NoSuchTagException.class) - public void shouldThrowExceptionForTagBufferTooLong() throws NoSuchTagException { - byte[] buffer = new byte[ID3v1Tag.TAG_LENGTH + 1]; - new ID3v1Tag(buffer); - } - - @Test - public void shouldExtractMaximumLengthFieldsFromValid10Tag() throws Exception { - byte[] buffer = BufferTools.stringToByteBuffer(VALID_TAG, 0, VALID_TAG.length()); - buffer[buffer.length - 1] = -0x6D; // 0x93 as a signed byte - ID3v1Tag id3v1tag = new ID3v1Tag(buffer); - assertEquals("TITLE1234567890123456789012345", id3v1tag.getTitle()); - assertEquals("ARTIST123456789012345678901234", id3v1tag.getArtist()); - assertEquals("ALBUM1234567890123456789012345", id3v1tag.getAlbum()); - assertEquals("2001", id3v1tag.getYear()); - assertEquals("COMMENT12345678901234567890123", id3v1tag.getComment()); - assertEquals(null, id3v1tag.getTrack()); - assertEquals(0x93, id3v1tag.getGenre()); - assertEquals("Synthpop", id3v1tag.getGenreDescription()); - } - - @Test - public void shouldExtractMaximumLengthFieldsFromValid11Tag() throws Exception { - byte[] buffer = BufferTools.stringToByteBuffer(VALID_TAG, 0, VALID_TAG.length()); - buffer[buffer.length - 3] = 0x00; - buffer[buffer.length - 2] = 0x01; - buffer[buffer.length - 1] = 0x0D; - ID3v1Tag id3v1tag = new ID3v1Tag(buffer); - assertEquals("TITLE1234567890123456789012345", id3v1tag.getTitle()); - assertEquals("ARTIST123456789012345678901234", id3v1tag.getArtist()); - assertEquals("ALBUM1234567890123456789012345", id3v1tag.getAlbum()); - assertEquals("2001", id3v1tag.getYear()); - assertEquals("COMMENT123456789012345678901", id3v1tag.getComment()); - assertEquals("1", id3v1tag.getTrack()); - assertEquals(0x0d, id3v1tag.getGenre()); - assertEquals("Pop", id3v1tag.getGenreDescription()); - } - - @Test - public void shouldExtractTrimmedFieldsFromValid11TagWithWhitespace() throws Exception { - byte[] buffer = BufferTools.stringToByteBuffer(VALID_TAG_WITH_WHITESPACE, 0, VALID_TAG_WITH_WHITESPACE.length()); - buffer[buffer.length - 3] = 0x00; - buffer[buffer.length - 2] = 0x01; - buffer[buffer.length - 1] = 0x0D; - ID3v1Tag id3v1tag = new ID3v1Tag(buffer); - assertEquals("TITLE", id3v1tag.getTitle()); - assertEquals("ARTIST", id3v1tag.getArtist()); - assertEquals("ALBUM", id3v1tag.getAlbum()); - assertEquals("2001", id3v1tag.getYear()); - assertEquals("COMMENT", id3v1tag.getComment()); - assertEquals("1", id3v1tag.getTrack()); - assertEquals(0x0d, id3v1tag.getGenre()); - assertEquals("Pop", id3v1tag.getGenreDescription()); - } - - @Test - public void shouldExtractTrimmedFieldsFromValid11TagWithNullspace() throws Exception { - byte[] buffer = BufferTools.stringToByteBuffer(VALID_TAG_WITH_WHITESPACE, 0, VALID_TAG_WITH_WHITESPACE.length()); - TestHelper.replaceSpacesWithNulls(buffer); - buffer[buffer.length - 3] = 0x00; - buffer[buffer.length - 2] = 0x01; - buffer[buffer.length - 1] = 0x0D; - ID3v1Tag id3v1tag = new ID3v1Tag(buffer); - assertEquals("TITLE", id3v1tag.getTitle()); - assertEquals("ARTIST", id3v1tag.getArtist()); - assertEquals("ALBUM", id3v1tag.getAlbum()); - assertEquals("2001", id3v1tag.getYear()); - assertEquals("COMMENT", id3v1tag.getComment()); - assertEquals("1", id3v1tag.getTrack()); - assertEquals(0x0d, id3v1tag.getGenre()); - assertEquals("Pop", id3v1tag.getGenreDescription()); - } - - @Test - public void shouldGenerateValidTagBuffer() throws Exception { - ID3v1Tag id3v1tag = new ID3v1Tag(); - id3v1tag.setTitle("TITLE"); - id3v1tag.setArtist("ARTIST"); - id3v1tag.setAlbum("ALBUM"); - id3v1tag.setYear("2001"); - id3v1tag.setComment("COMMENT"); - id3v1tag.setTrack("1"); - id3v1tag.setGenre(0x0d); - byte[] expectedBuffer = BufferTools.stringToByteBuffer(VALID_TAG_WITH_WHITESPACE, 0, VALID_TAG_WITH_WHITESPACE.length()); - TestHelper.replaceSpacesWithNulls(expectedBuffer); - expectedBuffer[expectedBuffer.length - 3] = 0x00; - expectedBuffer[expectedBuffer.length - 2] = 0x01; - expectedBuffer[expectedBuffer.length - 1] = 0x0D; - assertArrayEquals(expectedBuffer, id3v1tag.toBytes()); - } - - @Test - public void shouldGenerateValidTagBufferWithHighGenreAndTrackNumber() throws Exception { - ID3v1Tag id3v1tag = new ID3v1Tag(); - id3v1tag.setTitle("TITLE"); - id3v1tag.setArtist("ARTIST"); - id3v1tag.setAlbum("ALBUM"); - id3v1tag.setYear("2001"); - id3v1tag.setComment("COMMENT"); - id3v1tag.setTrack("254"); - id3v1tag.setGenre(0x8d); - byte[] expectedBuffer = BufferTools.stringToByteBuffer(VALID_TAG_WITH_WHITESPACE, 0, VALID_TAG_WITH_WHITESPACE.length()); - TestHelper.replaceSpacesWithNulls(expectedBuffer); - expectedBuffer[expectedBuffer.length - 3] = 0x00; - expectedBuffer[expectedBuffer.length - 2] = -0x02; // 254 as a signed byte - expectedBuffer[expectedBuffer.length - 1] = -0x73; // 0x8D as a signed byte - assertArrayEquals(expectedBuffer, id3v1tag.toBytes()); - } - - @Test - public void shouldReadTagFieldsFromMp3() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v1andv23tags.mp3"); - byte[] tagBuffer = BufferTools.copyBuffer(buffer, buffer.length - ID3v1Tag.TAG_LENGTH, ID3v1Tag.TAG_LENGTH); - ID3v1 id3tag = new ID3v1Tag(tagBuffer); - assertEquals("1", id3tag.getTrack()); - assertEquals("ARTIST123456789012345678901234", id3tag.getArtist()); - assertEquals("TITLE1234567890123456789012345", id3tag.getTitle()); - assertEquals("ALBUM1234567890123456789012345", id3tag.getAlbum()); - assertEquals("2001", id3tag.getYear()); - assertEquals(0x0d, id3tag.getGenre()); - assertEquals("Pop", id3tag.getGenreDescription()); - assertEquals("COMMENT123456789012345678901", id3tag.getComment()); - } - - @Test - public void shouldConvertTagToBytesAndBackToEquivalentTag() throws Exception { - ID3v1 id3tag = new ID3v1Tag(); - id3tag.setTrack("5"); - id3tag.setArtist("ARTIST"); - id3tag.setTitle("TITLE"); - id3tag.setAlbum("ALBUM"); - id3tag.setYear("1997"); - id3tag.setGenre(13); - id3tag.setComment("COMMENT"); - byte[] data = id3tag.toBytes(); - ID3v1 id3tagCopy = new ID3v1Tag(data); - assertEquals(id3tag, id3tagCopy); - } - - @Test - public void shouldReturnEmptyTrackIfNotSetOn11Tag() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v1tagwithnotrack.mp3"); - byte[] tagBuffer = BufferTools.copyBuffer(buffer, buffer.length - ID3v1Tag.TAG_LENGTH, ID3v1Tag.TAG_LENGTH); - ID3v1 id3tag = new ID3v1Tag(tagBuffer); - assertEquals("", id3tag.getTrack()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v22TagTest.java b/src/test/java/com/mpatric/mp3agic/ID3v22TagTest.java deleted file mode 100644 index 2078ada..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v22TagTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class ID3v22TagTest { - - private static final byte ZERO = 0; - private static final byte[] inputBytes = new byte[ID3v22Tag.FLAGS_OFFSET + 1]; - private static final byte[] outputBytes = new byte[ID3v22Tag.FLAGS_OFFSET + 1]; - - @Before - public void setUp() { - inputBytes[ID3v22Tag.FLAGS_OFFSET] = 0; - outputBytes[ID3v22Tag.FLAGS_OFFSET] = 0; - } - - @Test - public void shouldUnpackAndPackOffUnsynchronizationBit() { - final ID3v22Tag id3tag = new ID3v22Tag(); - inputBytes[ID3v22Tag.FLAGS_OFFSET] = BufferTools.setBit(ZERO, ID3v22Tag.UNSYNCHRONISATION_BIT, false); - id3tag.unpackFlags(inputBytes); - id3tag.packFlags(outputBytes, 0); - assertFalse(BufferTools.checkBit(outputBytes[ID3v22Tag.FLAGS_OFFSET], ID3v22Tag.UNSYNCHRONISATION_BIT)); - } - - @Test - public void shouldUnpackAndPackOnUnsynchronizationBit() { - final ID3v22Tag id3tag = new ID3v22Tag(); - inputBytes[ID3v22Tag.FLAGS_OFFSET] = BufferTools.setBit(ZERO, ID3v22Tag.UNSYNCHRONISATION_BIT, true); - id3tag.unpackFlags(inputBytes); - id3tag.packFlags(outputBytes, 0); - assertTrue(BufferTools.checkBit(outputBytes[ID3v22Tag.FLAGS_OFFSET], ID3v22Tag.UNSYNCHRONISATION_BIT)); - } - - @Test - public void shouldUnpackAndPackOffCompressionBit() { - final ID3v22Tag id3tag = new ID3v22Tag(); - inputBytes[ID3v22Tag.FLAGS_OFFSET] = BufferTools.setBit(ZERO, ID3v22Tag.COMPRESSION_BIT, false); - id3tag.unpackFlags(inputBytes); - id3tag.packFlags(outputBytes, 0); - assertFalse(BufferTools.checkBit(outputBytes[ID3v22Tag.FLAGS_OFFSET], ID3v22Tag.COMPRESSION_BIT)); - } - - @Test - public void shouldUnpackAndPackOnCompressionBit() { - final ID3v22Tag id3tag = new ID3v22Tag(); - inputBytes[ID3v22Tag.FLAGS_OFFSET] = BufferTools.setBit(ZERO, ID3v22Tag.COMPRESSION_BIT, true); - id3tag.unpackFlags(inputBytes); - id3tag.packFlags(outputBytes, 0); - assertTrue(BufferTools.checkBit(outputBytes[ID3v22Tag.FLAGS_OFFSET], ID3v22Tag.COMPRESSION_BIT)); - } - - @Test - public void shouldStoreAndRetrieveItunesComment() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final String comment = "COMMENT"; - id3tag.setItunesComment(comment); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(comment, newId3tag.getItunesComment()); - } - - @Test - public void shouldStoreAndRetrieveLyrics() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final String lyrics = "La-la-la"; - id3tag.setLyrics(lyrics); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(lyrics, newId3tag.getLyrics()); - } - - @Test - public void shouldStoreAndRetrievePublisher() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final String publisher = "PUBLISHER"; - id3tag.setPublisher(publisher); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(publisher, newId3tag.getPublisher()); - } - - @Test - public void shouldStoreAndRetrieveKey() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final String key = "KEY"; - id3tag.setKey(key); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(key, newId3tag.getKey()); - } - - @Test - public void shouldStoreAndRetrieveBPM() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final int bpm = 8 * 44100; - id3tag.setBPM(bpm); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(bpm, newId3tag.getBPM()); - } - - @Test - public void shouldStoreAndRetrieveDate() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final String date = "DATE"; - id3tag.setDate(date); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(date, newId3tag.getDate()); - } - - @Test - public void shouldStoreAndRetrieveAlbumArtist() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final String albumArtist = "ALBUMARTIST"; - id3tag.setAlbumArtist(albumArtist); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(albumArtist, newId3tag.getAlbumArtist()); - } - - @Test - public void shouldStoreAndRetrieveGrouping() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final String grouping = "GROUPING"; - id3tag.setGrouping(grouping); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(grouping, newId3tag.getGrouping()); - } - - @Test - public void shouldStoreAndRetrieveCompilation() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final boolean compilation = true; - id3tag.setCompilation(compilation); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(compilation, newId3tag.isCompilation()); - } - - @Test - public void shouldStoreAndRetrievePartOfSet() throws Exception { - final ID3v22Tag id3tag = new ID3v22Tag(); - final String partOfSet = "PARTOFSET"; - id3tag.setPartOfSet(partOfSet); - final byte[] bytes = id3tag.toBytes(); - final ID3v22Tag newId3tag = new ID3v22Tag(bytes); - assertEquals(partOfSet, newId3tag.getPartOfSet()); - } - -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v24TagTest.java b/src/test/java/com/mpatric/mp3agic/ID3v24TagTest.java deleted file mode 100644 index 71792c9..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v24TagTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class ID3v24TagTest { - - @Test - public void shouldStoreAndRetrieveRecordingTime() throws Exception { - final ID3v24Tag id3tag = new ID3v24Tag(); - final String recordingTime = "01/01/2011 00:00:00"; - id3tag.setRecordingTime(recordingTime); - final byte[] bytes = id3tag.toBytes(); - final ID3v24Tag newId3tag = new ID3v24Tag(bytes); - assertEquals(recordingTime, newId3tag.getRecordingTime()); - } - - @Test - public void shouldSetGenreDescription() throws Exception { - final ID3v24Tag id3tag = new ID3v24Tag(); - final String genreDescription = "?????"; - id3tag.setGenreDescription(genreDescription); - final byte[] bytes = id3tag.toBytes(); - final ID3v24Tag newId3tag = new ID3v24Tag(bytes); - assertTrue(genreDescription, newId3tag.getFrameSets().containsKey(ID3v24Tag.ID_GENRE)); - final List frames = newId3tag.getFrameSets().get(ID3v24Tag.ID_GENRE).getFrames(); - assertEquals(1, frames.size()); - final ID3v2TextFrameData frameData = new ID3v2TextFrameData(id3tag.hasUnsynchronisation(), frames.get(0).getData()); - assertEquals(genreDescription, frameData.getText().toString()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2ChapterFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2ChapterFrameDataTest.java deleted file mode 100644 index 262c387..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2ChapterFrameDataTest.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.mpatric.mp3agic; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import java.util.ArrayList; - -public class ID3v2ChapterFrameDataTest { - - @Test - public void equalsItself() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - assertEquals(frameData, frameData); - } - - @Test - public void notEqualToNull() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - assertFalse(frameData.equals(null)); - } - - @Test - public void notEqualToDifferentClass() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - assertFalse(frameData.equals("8")); - } - - @Test - public void shouldConsiderTwoEquivalentObjectsEqual() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2TextFrameData subFrameData1 = new ID3v2TextFrameData(false, new EncodedText("Hello there")); - frameData1.addSubframe("TIT2", subFrameData1); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2TextFrameData subFrameData2 = new ID3v2TextFrameData(false, new EncodedText("Hello there")); - frameData2.addSubframe("TIT2", subFrameData2); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfUnsynchronizationNotEqual() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(true, "ch1", 1, 380, 3, 400); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfIdNotEqual() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, "ch2", 1, 380, 3, 400); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfIdIsNullOnOne() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, null, 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, "ch2", 1, 380, 3, 400); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfIdIsNullOnBoth() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, null, 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, null, 1, 380, 3, 400); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfStartTimeNotEqual() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, "ch1", 2, 380, 3, 400); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfEndTimeNotEqual() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, "ch1", 1, 280, 3, 400); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfStartOffsetNotEqual() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 2, 400); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfEndOffsetNotEqual() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 200); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfOneHasSubframes() { - ID3v2ChapterFrameData frameData1 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2ChapterFrameData frameData2 = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2TextFrameData subFrameData2 = new ID3v2TextFrameData(false, new EncodedText("Hello there")); - frameData2.addSubframe("TIT2", subFrameData2); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void hashCodeIsConsistent() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - assertEquals(frameData.hashCode(), frameData.hashCode()); - } - - @Test - public void equalObjectsHaveSameHashCode() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2ChapterFrameData frameDataAgain = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - assertEquals(frameData.hashCode(), frameDataAgain.hashCode()); - } - - @Test - public void shouldConvertFrameDataToBytesAndBackToEquivalentObject() throws Exception { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - ID3v2TextFrameData subFrameData = new ID3v2TextFrameData(false, new EncodedText("Hello there")); - frameData.addSubframe("TIT2", subFrameData); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = { - 'c', 'h', '1', 0, - 0, 0, 0, 1, - 0, 0, 1, (byte) 0x7c, - 0, 0, 0, 3, - 0, 0, 1, (byte) 0x90, - 'T', 'I', 'T', '2', - 0, 0, 0, (byte) 0xc, - 0, 0, - 0, - 'H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'e', 'r', 'e' - }; - assertArrayEquals(expectedBytes, bytes); - ID3v2ChapterFrameData frameDataCopy = new ID3v2ChapterFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void toStringOnMostlyEmptyFrameData() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false); - assertEquals( - "ID3v2ChapterFrameData [id=null, startTime=0, endTime=0, startOffset=0, endOffset=0, subframes=[]]", - frameData.toString()); - } - - @Test - public void toStringOnFullFrameData() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false, "ch1", 1, 380, 3, 400); - assertEquals( - "ID3v2ChapterFrameData [id=ch1, startTime=1, endTime=380, startOffset=3, endOffset=400, subframes=[]]", - frameData.toString()); - } - - @Test - public void getsAndSetsId() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false); - frameData.setId("My ID"); - assertEquals("My ID", frameData.getId()); - } - - @Test - public void getsAndSetsStartTime() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false); - frameData.setStartTime(9); - assertEquals(9, frameData.getStartTime()); - } - - @Test - public void getsAndSetsEndTime() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false); - frameData.setEndTime(9); - assertEquals(9, frameData.getEndTime()); - } - - @Test - public void getsAndSetsStartOffset() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false); - frameData.setStartOffset(9); - assertEquals(9, frameData.getStartOffset()); - } - - @Test - public void getsAndSetsEndOffset() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false); - frameData.setEndOffset(9); - assertEquals(9, frameData.getEndOffset()); - } - - @Test - public void getsAndSetsSubframes() { - ID3v2ChapterFrameData frameData = new ID3v2ChapterFrameData(false); - ArrayList subframes = new ArrayList<>(2); - subframes.add(new ID3v2Frame("", new byte[]{'c', 'h', '1', 0})); - subframes.add(new ID3v2Frame("", new byte[]{1, 0, 1, 0})); - frameData.setSubframes(subframes); - assertEquals(subframes, frameData.getSubframes()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2ChapterTOCFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2ChapterTOCFrameDataTest.java deleted file mode 100644 index e2e5c56..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2ChapterTOCFrameDataTest.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.mpatric.mp3agic; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import java.util.ArrayList; - -public class ID3v2ChapterTOCFrameDataTest { - - @Test - public void equalsItself() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - assertEquals(frameData, frameData); - } - - @Test - public void notEqualToNull() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - assertFalse(frameData.equals(null)); - } - - @Test - public void notEqualToDifferentClass() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - assertFalse(frameData.equals("8")); - } - - @Test - public void shouldConsiderTwoEquivalentObjectsEqual() { - String[] children = {"ch1", "ch2"}; - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", children); - ID3v2TextFrameData subFrameData1 = new ID3v2TextFrameData(false, new EncodedText("Hello there")); - frameData1.addSubframe("TIT2", subFrameData1); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", children); - - ID3v2TextFrameData subFrameData2 = new ID3v2TextFrameData(false, new EncodedText("Hello there")); - frameData2.addSubframe("TIT2", subFrameData2); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfUnsynchronizationNotEqual() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(true, true, false, "toc1", new String[]{"ch1", "ch2"}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfIsRootNotEqual() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, false, false, "toc1", new String[]{"ch1", "ch2"}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfIsOrderedNotEqual() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, true, "toc1", new String[]{"ch1", "ch2"}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfIdNotEqual() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, false, "toc2", new String[]{"ch1", "ch2"}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfIdIsNullOnOne() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, null, new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfIdIsNullOnBoth() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, null, new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, false, null, new String[]{"ch1", "ch2"}); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfChildrenNotEqual() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, false, "toc`", new String[]{"ch3", "ch2"}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfOneDoeNotHaveChildren() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, false, "toc`", new String[]{}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfChildrenNullOnOne() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", null); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, false, "toc`", new String[]{"ch3", "ch2"}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfOneHasSubframes() { - ID3v2ChapterTOCFrameData frameData1 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameData2 = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2TextFrameData subFrameData2 = new ID3v2TextFrameData(false, new EncodedText("Hello there")); - frameData2.addSubframe("TIT2", subFrameData2); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void hashCodeIsConsistent() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - assertEquals(frameData.hashCode(), frameData.hashCode()); - } - - @Test - public void equalObjectsHaveSameHashCode() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - ID3v2ChapterTOCFrameData frameDataAgain = new ID3v2ChapterTOCFrameData(false, true, false, "toc1", new String[]{"ch1", "ch2"}); - assertEquals(frameData.hashCode(), frameDataAgain.hashCode()); - } - - @Test - public void shouldConvertFrameDataToBytesAndBackToEquivalentObject() throws Exception { - String[] children = {"ch1", "ch2"}; - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false, true, true, "toc1", children); - ID3v2TextFrameData subFrameData = new ID3v2TextFrameData(false, new EncodedText("Hello there")); - frameData.addSubframe("TIT2", subFrameData); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = { - 't', 'o', 'c', '1', 0, - 3, 2, - 'c', 'h', '1', 0, - 'c', 'h', '2', 0, - 'T', 'I', 'T', '2', - 0, 0, 0, (byte) 0xc, - 0, 0, - 0, - 'H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'e', 'r', 'e' - }; - assertArrayEquals(expectedBytes, bytes); - ID3v2ChapterTOCFrameData frameDataCopy = new ID3v2ChapterTOCFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void toStringOnMostlyEmptyFrameData() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false); - assertEquals( - "ID3v2ChapterTOCFrameData [isRoot=false, isOrdered=false, id=null, children=null, subframes=[]]", - frameData.toString()); - } - - @Test - public void toStringOnFullFrameData() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false, true, true, "toc1", new String[]{"ch1", "ch2"}); - assertEquals( - "ID3v2ChapterTOCFrameData [isRoot=true, isOrdered=true, id=toc1, children=[ch1, ch2], subframes=[]]", - frameData.toString()); - } - - @Test - public void getsAndSetsIsRoot() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false); - frameData.setRoot(true); - assertTrue(frameData.isRoot()); - } - - @Test - public void getsAndSetsIsOrdered() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false); - frameData.setOrdered(true); - assertTrue(frameData.isOrdered()); - } - - @Test - public void getsAndSetsId() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false); - frameData.setId("My ID"); - assertEquals("My ID", frameData.getId()); - } - - @Test - public void getsAndSetsChildren() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false); - frameData.setChildren(new String[]{"ch1", "ch2"}); - assertArrayEquals(new String[]{"ch1", "ch2"}, frameData.getChildren()); - } - - @Test - public void getsAndSetsSubframes() { - ID3v2ChapterTOCFrameData frameData = new ID3v2ChapterTOCFrameData(false); - ArrayList subframes = new ArrayList<>(2); - subframes.add(new ID3v2Frame("", new byte[]{'c', 'h', '1', 0})); - subframes.add(new ID3v2Frame("", new byte[]{1, 0, 1, 0})); - frameData.setSubframes(subframes); - assertEquals(subframes, frameData.getSubframes()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2CommentFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2CommentFrameDataTest.java deleted file mode 100644 index 6b825f7..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2CommentFrameDataTest.java +++ /dev/null @@ -1,236 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; - -public class ID3v2CommentFrameDataTest { - - private static final String TEST_LANGUAGE = "eng"; - private static final String TEST_DESCRIPTION = "DESCRIPTION"; - private static final String TEST_VALUE = "ABCDEFGHIJKLMNOPQ"; - private static final String TEST_DESCRIPTION_UNICODE = "\u03B3\u03B5\u03B9\u03AC"; - private static final String TEST_VALUE_UNICODE = "\u03C3\u03BF\u03C5"; - - @Test - public void equalsItself() { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertEquals(frameData, frameData); - } - - @Test - public void notEqualToNull() { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertFalse(frameData.equals(null)); - } - - @Test - public void notEqualToDifferentClass() { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertFalse(frameData.equals("8")); - } - - @Test - public void shouldConsiderTwoEquivalentObjectsEqual() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfUnsynchronizationNotEqual() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(true, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfLanguageNotEqual() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, "jap", new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfLanguageIsNullOnOne() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, null, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfLanguageIsNullOnBoth() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, null, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, null, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfDescriptionNotEqual() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, "other description"), new EncodedText((byte) 0, TEST_VALUE)); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfDescriptionIsNullOnOne() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, null, new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfDescriptionIsNullOnBoth() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, null, new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, null, new EncodedText((byte) 0, TEST_VALUE)); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfCommentNotEqual() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, "other comment")); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfCommentIsNullOnOne() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfCommentIsNullOnBoth() { - ID3v2CommentFrameData frameData1 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - ID3v2CommentFrameData frameData2 = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - assertEquals(frameData1, frameData2); - } - - @Test - public void hashCodeIsConsistent() { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - assertEquals(frameData.hashCode(), frameData.hashCode()); - } - - @Test - public void equalObjectsHaveSameHashCode() { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - ID3v2CommentFrameData frameDataAgain = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - assertEquals(frameData.hashCode(), frameDataAgain.hashCode()); - } - - @Test - public void shouldConvertFrameDataToBytesAndBackToEquivalentObject() throws Exception { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText((byte) 0, TEST_DESCRIPTION), new EncodedText((byte) 0, TEST_VALUE)); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {0, 'e', 'n', 'g', 'D', 'E', 'S', 'C', 'R', 'I', 'P', 'T', 'I', 'O', 'N', 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'}; - assertArrayEquals(expectedBytes, bytes); - ID3v2CommentFrameData frameDataCopy = new ID3v2CommentFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test(expected = IllegalArgumentException.class) - public void constructorThrowsErrorWhenEncodingsDoNotMatch() { - new ID3v2CommentFrameData(false, TEST_LANGUAGE, - new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, "description"), - new EncodedText(EncodedText.TEXT_ENCODING_UTF_8, "comment")); - } - - @Test - public void shouldConvertFrameDataWithBlankDescriptionAndLanguageToBytesAndBackToEquivalentObject() throws Exception { - byte[] bytes = {0, 0, 0, 0, 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'}; - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, bytes); - assertEquals("\00\00\00", frameData.getLanguage()); - assertEquals(new EncodedText(""), frameData.getDescription()); - assertEquals(new EncodedText(TEST_VALUE), frameData.getComment()); - assertArrayEquals(bytes, frameData.toBytes()); - } - - @Test - public void shouldConvertFrameDataWithUnicodeToBytesAndBackToEquivalentObject() throws Exception { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TEST_DESCRIPTION_UNICODE), new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TEST_VALUE_UNICODE)); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {1, 'e', 'n', 'g', (byte) 0xff, (byte) 0xfe, (byte) 0xb3, 0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0x03, (byte) 0xac, 0x03, 0, 0, (byte) 0xff, (byte) 0xfe, (byte) 0xc3, 0x03, (byte) 0xbf, 0x03, (byte) 0xc5, 0x03}; - assertArrayEquals(expectedBytes, bytes); - ID3v2CommentFrameData frameDataCopy = new ID3v2CommentFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void convertsEmptyFrameDataToBytesAndBack() throws Exception { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, null, null, null); - byte[] bytes = frameData.toBytes(); - ID3v2CommentFrameData frameDataCopy = new ID3v2CommentFrameData(false, bytes); - assertEquals("eng", frameDataCopy.getLanguage()); - assertEquals(new EncodedText(""), frameDataCopy.getDescription()); - assertEquals(new EncodedText(""), frameDataCopy.getComment()); - } - - @Test - public void convertsFrameDataWithNoLanguageToBytesAndBack() throws Exception { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, null, new EncodedText(TEST_DESCRIPTION), new EncodedText(TEST_VALUE)); - byte[] bytes = frameData.toBytes(); - ID3v2CommentFrameData frameDataCopy = new ID3v2CommentFrameData(false, bytes); - assertEquals("eng", frameDataCopy.getLanguage()); - assertEquals(new EncodedText(TEST_DESCRIPTION), frameDataCopy.getDescription()); - assertEquals(new EncodedText(TEST_VALUE), frameDataCopy.getComment()); - } - - @Test - public void convertsFrameDataWithNoDescriptionToBytesAndBack() throws Exception { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, null, new EncodedText(TEST_VALUE)); - byte[] bytes = frameData.toBytes(); - ID3v2CommentFrameData frameDataCopy = new ID3v2CommentFrameData(false, bytes); - assertEquals("eng", frameDataCopy.getLanguage()); - assertEquals(new EncodedText(""), frameDataCopy.getDescription()); - assertEquals(new EncodedText(TEST_VALUE), frameDataCopy.getComment()); - } - - @Test - public void convertsFrameDataWithNoDescriptionAndCommentIsUnicodeToBytesAndBack() throws Exception { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, null, - new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TEST_VALUE_UNICODE)); - byte[] bytes = frameData.toBytes(); - ID3v2CommentFrameData frameDataCopy = new ID3v2CommentFrameData(false, bytes); - assertEquals("eng", frameDataCopy.getLanguage()); - assertEquals(new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, ""), frameDataCopy.getDescription()); - assertEquals(new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TEST_VALUE_UNICODE), frameDataCopy.getComment()); - } - - @Test - public void convertsFrameDataWithNoCommentToBytesAndBack() throws Exception { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false, TEST_LANGUAGE, new EncodedText(TEST_DESCRIPTION), null); - byte[] bytes = frameData.toBytes(); - ID3v2CommentFrameData frameDataCopy = new ID3v2CommentFrameData(false, bytes); - assertEquals("eng", frameDataCopy.getLanguage()); - assertEquals(new EncodedText(TEST_DESCRIPTION), frameDataCopy.getDescription()); - assertEquals(new EncodedText(""), frameDataCopy.getComment()); - } - - @Test - public void getsAndSetsLanguage() { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false); - frameData.setLanguage("my language"); - assertEquals("my language", frameData.getLanguage()); - } - - @Test - public void getsAndSetsComment() { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false); - EncodedText comment = new EncodedText("my comment"); - frameData.setComment(comment); - assertEquals(comment, frameData.getComment()); - } - - @Test - public void getsAndSetsDescription() { - ID3v2CommentFrameData frameData = new ID3v2CommentFrameData(false); - EncodedText description = new EncodedText("my description"); - frameData.setDescription(description); - assertEquals(description, frameData.getDescription()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2FrameSetTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2FrameSetTest.java deleted file mode 100644 index a7dedbd..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2FrameSetTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.mpatric.mp3agic; - -import nl.jqno.equalsverifier.EqualsVerifier; -import nl.jqno.equalsverifier.Warning; -import org.junit.Test; - -public class ID3v2FrameSetTest { - - @Test - public void shouldCorrectlyImplementHashCodeAndEquals() { - EqualsVerifier.forClass(ID3v2FrameSet.class) - .usingGetClass() - .suppress(Warning.NONFINAL_FIELDS) - .verify(); - } - -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2FrameTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2FrameTest.java deleted file mode 100644 index 7352281..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2FrameTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.mpatric.mp3agic; - -import nl.jqno.equalsverifier.EqualsVerifier; -import nl.jqno.equalsverifier.Warning; -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -public class ID3v2FrameTest { - - private static final String T_FRAME = "TPE1000 000ABCDEFGHIJKLMNOPQRSTUVWXYZABCDE"; - private static final String W_FRAME = "WXXX000!0000ABCDEFGHIJKLMNOPQRSTUVWXYZABCDE"; - private static final String C_FRAME = "COMM000$0000000ABCDEFGHIJKLMNOPQRSTUVWXYZABCDE"; - - @Test - public void shouldReadValid32TFrame() throws Exception { - byte[] bytes = BufferTools.stringToByteBuffer("xxxxx" + T_FRAME, 0, 5 + T_FRAME.length()); - TestHelper.replaceNumbersWithBytes(bytes, 9); - ID3v2Frame frame = new ID3v2Frame(bytes, 5); - assertEquals(42, frame.getLength()); - assertEquals("TPE1", frame.getId()); - String s = "0ABCDEFGHIJKLMNOPQRSTUVWXYZABCDE"; - byte[] expectedBytes = BufferTools.stringToByteBuffer(s, 0, s.length()); - TestHelper.replaceNumbersWithBytes(expectedBytes, 0); - assertArrayEquals(expectedBytes, frame.getData()); - } - - @Test - public void shouldReadValid32WFrame() throws Exception { - byte[] bytes = BufferTools.stringToByteBuffer(W_FRAME + "xxxxx", 0, W_FRAME.length()); - TestHelper.replaceNumbersWithBytes(bytes, 0); - ID3v2Frame frame = new ID3v2Frame(bytes, 0); - assertEquals(43, frame.getLength()); - assertEquals("WXXX", frame.getId()); - String s = "00ABCDEFGHIJKLMNOPQRSTUVWXYZABCDE"; - byte[] expectedBytes = BufferTools.stringToByteBuffer(s, 0, s.length()); - TestHelper.replaceNumbersWithBytes(expectedBytes, 0); - assertArrayEquals(expectedBytes, frame.getData()); - } - - @Test - public void shouldReadValid32CFrame() throws Exception { - byte[] bytes = BufferTools.stringToByteBuffer(C_FRAME, 0, C_FRAME.length()); - TestHelper.replaceNumbersWithBytes(bytes, 0); - ID3v2Frame frame = new ID3v2Frame(bytes, 0); - assertEquals(46, frame.getLength()); - assertEquals("COMM", frame.getId()); - String s = "00000ABCDEFGHIJKLMNOPQRSTUVWXYZABCDE"; - byte[] expectedBytes = BufferTools.stringToByteBuffer(s, 0, s.length()); - TestHelper.replaceNumbersWithBytes(expectedBytes, 0); - assertArrayEquals(expectedBytes, frame.getData()); - } - - @Test - public void shouldPackAndUnpackHeaderToGiveEquivalentObject() throws Exception { - byte[] bytes = new byte[26]; - for (int i = 0; i < bytes.length; i++) { - bytes[i] = (byte) ('A' + i); - } - ID3v2Frame frame = new ID3v2Frame("TEST", bytes); - byte[] newBytes = frame.toBytes(); - ID3v2Frame frameCopy = new ID3v2Frame(newBytes, 0); - assertEquals("TEST", frameCopy.getId()); - assertEquals(frame, frameCopy); - } - - @Test - public void shouldCorrectlyUnpackHeader() throws Exception { - byte[] bytes = BufferTools.stringToByteBuffer(W_FRAME + "?????", 0, W_FRAME.length()); - TestHelper.replaceNumbersWithBytes(bytes, 0); - final ID3v2Frame frame = new ID3v2Frame(bytes, 0); - assertFalse(frame.hasDataLengthIndicator()); - assertFalse(frame.hasCompression()); - assertFalse(frame.hasEncryption()); - assertFalse(frame.hasGroup()); - assertFalse(frame.hasPreserveFile()); - assertFalse(frame.hasPreserveTag()); - assertFalse(frame.isReadOnly()); - assertFalse(frame.hasUnsynchronisation()); - } - - @Test - public void shouldStoreAndRetrieveData() throws Exception { - final byte[] oldBytes = BufferTools.stringToByteBuffer(C_FRAME, 0, C_FRAME.length()); - TestHelper.replaceNumbersWithBytes(oldBytes, 0); - final ID3v2Frame frame = new ID3v2Frame(oldBytes, 0); - final byte[] newBytes = BufferTools.stringToByteBuffer(W_FRAME + "?????", 0, W_FRAME.length()); - TestHelper.replaceNumbersWithBytes(newBytes, 0); - frame.setData(newBytes); - final byte[] expectedBytes = BufferTools.stringToByteBuffer(W_FRAME, 0, W_FRAME.length()); - TestHelper.replaceNumbersWithBytes(expectedBytes, 0); - assertArrayEquals(expectedBytes, frame.getData()); - } - - @Test - public void shouldCorrectlyImplementHashCodeAndEquals() { - EqualsVerifier.forClass(ID3v2Frame.class) - .usingGetClass() - .suppress(Warning.NONFINAL_FIELDS) - .verify(); - } - -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2ObseleteFrameTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2ObseleteFrameTest.java deleted file mode 100644 index c15487a..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2ObseleteFrameTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -public class ID3v2ObseleteFrameTest { - - private static final String T_FRAME = "TP100\"0ARTISTABCDEFGHIJKLMNOPQRSTUVWXYZ0"; - private static final String LONG_T_FRAME = "TP10110Metamorphosis A a very long album B a very long album C a very long album D a very long album E a very long album F a very long album G a very long album H a very long album I a very long album J a very long album K a very long album L a very long album M0"; - - @Test - public void shouldReadValidLong32ObseleteTFrame() throws Exception { - byte[] bytes = BufferTools.stringToByteBuffer(LONG_T_FRAME, 0, LONG_T_FRAME.length()); - TestHelper.replaceNumbersWithBytes(bytes, 3); - ID3v2ObseleteFrame frame = new ID3v2ObseleteFrame(bytes, 0); - assertEquals(263, frame.getLength()); - assertEquals("TP1", frame.getId()); - String s = "0Metamorphosis A a very long album B a very long album C a very long album D a very long album E a very long album F a very long album G a very long album H a very long album I a very long album J a very long album K a very long album L a very long album M0"; - byte[] expectedBytes = BufferTools.stringToByteBuffer(s, 0, s.length()); - TestHelper.replaceNumbersWithBytes(expectedBytes, 0); - assertArrayEquals(expectedBytes, frame.getData()); - } - - @Test - public void shouldReadValid32ObseleteTFrame() throws Exception { - byte[] bytes = BufferTools.stringToByteBuffer("xxxxx" + T_FRAME, 0, 5 + T_FRAME.length()); - TestHelper.replaceNumbersWithBytes(bytes, 8); - ID3v2ObseleteFrame frame = new ID3v2ObseleteFrame(bytes, 5); - assertEquals(40, frame.getLength()); - assertEquals("TP1", frame.getId()); - String s = "0ARTISTABCDEFGHIJKLMNOPQRSTUVWXYZ0"; - byte[] expectedBytes = BufferTools.stringToByteBuffer(s, 0, s.length()); - TestHelper.replaceNumbersWithBytes(expectedBytes, 0); - assertArrayEquals(expectedBytes, frame.getData()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2ObseletePictureFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2ObseletePictureFrameDataTest.java deleted file mode 100644 index a799f06..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2ObseletePictureFrameDataTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -public class ID3v2ObseletePictureFrameDataTest { - - private static final String TEST_MIME_TYPE = "image/png"; - private static final String TEST_DESCRIPTION = "DESCRIPTION"; - private static final String TEST_DESCRIPTION_UNICODE = "\u03B3\u03B5\u03B9\u03AC"; - private static final byte[] DUMMY_IMAGE_DATA = {1, 2, 3, 4, 5}; - - @Test - public void shouldConsiderTwoEquivalentObjectsEqual() { - ID3v2ObseletePictureFrameData frameData1 = new ID3v2ObseletePictureFrameData(false, TEST_MIME_TYPE, (byte) 0, new EncodedText((byte) 1, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2ObseletePictureFrameData frameData2 = new ID3v2ObseletePictureFrameData(false, TEST_MIME_TYPE, (byte) 0, new EncodedText((byte) 1, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertEquals(frameData1, frameData2); - } - - @Test - public void shouldReadFrameData() throws Exception { - byte[] bytes = {0x00, 'P', 'N', 'G', 0x01, 'D', 'E', 'S', 'C', 'R', 'I', 'P', 'T', 'I', 'O', 'N', 0x00, 1, 2, 3, 4, 5}; - ID3v2ObseletePictureFrameData frameData = new ID3v2ObseletePictureFrameData(false, bytes); - assertEquals(TEST_MIME_TYPE, frameData.getMimeType()); - assertEquals((byte) 1, frameData.getPictureType()); - assertEquals(new EncodedText((byte) 0, TEST_DESCRIPTION), frameData.getDescription()); - assertArrayEquals(DUMMY_IMAGE_DATA, frameData.getImageData()); - } - - @Test - public void shouldReadFrameDataWithUnicodeDescription() throws Exception { - byte[] bytes = {0x01, 'P', 'N', 'G', 0x01, (byte) 0xff, (byte) 0xfe, (byte) 0xb3, 0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0x03, (byte) 0xac, 0x03, 0, 0, 1, 2, 3, 4, 5}; - ID3v2ObseletePictureFrameData frameData = new ID3v2ObseletePictureFrameData(false, bytes); - assertEquals(TEST_MIME_TYPE, frameData.getMimeType()); - assertEquals((byte) 1, frameData.getPictureType()); - assertEquals(new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TEST_DESCRIPTION_UNICODE), frameData.getDescription()); - assertArrayEquals(DUMMY_IMAGE_DATA, frameData.getImageData()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2PictureFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2PictureFrameDataTest.java deleted file mode 100644 index 406a6a3..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2PictureFrameDataTest.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; - -public class ID3v2PictureFrameDataTest { - - private static final byte BYTE_FF = -0x01; - private static final byte BYTE_FB = -0x05; - - private static final String TEST_MIME_TYPE = "mime/type"; - private static final String TEST_DESCRIPTION = "DESCRIPTION"; - private static final String TEST_DESCRIPTION_UNICODE = "\u03B3\u03B5\u03B9\u03AC"; - private static final byte[] DUMMY_IMAGE_DATA = {1, 2, 3, 4, 5}; - - @Test - public void equalsItself() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertEquals(frameData, frameData); - } - - @Test - public void notEqualToNull() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertFalse(frameData.equals(null)); - } - - @Test - public void notEqualToDifferentClass() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertFalse(frameData.equals("8")); - } - - @Test - public void shouldConsiderTwoEquivalentObjectsEqual() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfUnsynchronizationNotEqual() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(true, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfMimeTypeNotEqual() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, "other mime type", (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfMimeTypeIsNullOnOne() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, null, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - new ID3v2ChapterFrameData(false, "ch2", 1, 380, 3, 400); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfMimeTypeIsNullOnBoth() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, null, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, null, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfPictureTypeNotEqual() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 4, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfDescriptionNotEqual() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, "other description"), DUMMY_IMAGE_DATA); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfDescriptionIsNullOnOne() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, null, DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfDescriptionIsNullOnBoth() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, null, DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, null, DUMMY_IMAGE_DATA); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfImageDataNotEqual() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), new byte[]{}); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfImageDataNullOnOne() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfImageDataIsNullOnBoth() { - ID3v2PictureFrameData frameData1 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - ID3v2PictureFrameData frameData2 = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - assertEquals(frameData1, frameData2); - } - - @Test - public void hashCodeIsConsistent() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertEquals(frameData.hashCode(), frameData.hashCode()); - } - - @Test - public void equalObjectsHaveSameHashCode() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - ID3v2PictureFrameData frameDataAgain = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - assertEquals(frameData.hashCode(), frameDataAgain.hashCode()); - } - - @Test - public void shouldConvertFrameDataToBytesAndBackToEquivalentObject() throws Exception { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText((byte) 0, TEST_DESCRIPTION), DUMMY_IMAGE_DATA); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {0x00, 'm', 'i', 'm', 'e', '/', 't', 'y', 'p', 'e', 0, 0x03, 'D', 'E', 'S', 'C', 'R', 'I', 'P', 'T', 'I', 'O', 'N', 0, 1, 2, 3, 4, 5}; - assertArrayEquals(expectedBytes, bytes); - ID3v2PictureFrameData frameDataCopy = new ID3v2PictureFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void shouldConvertFrameDataWithUnicodeDescriptionToBytesAndBackToEquivalentObject() throws Exception { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false, TEST_MIME_TYPE, (byte) 3, new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TEST_DESCRIPTION_UNICODE), DUMMY_IMAGE_DATA); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {0x01, 'm', 'i', 'm', 'e', '/', 't', 'y', 'p', 'e', 0, 0x03, (byte) 0xff, (byte) 0xfe, (byte) 0xb3, 0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0x03, (byte) 0xac, 0x03, 0, 0, 1, 2, 3, 4, 5}; - assertArrayEquals(expectedBytes, bytes); - ID3v2PictureFrameData frameDataCopy = new ID3v2PictureFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void shouldUnsynchroniseAndSynchroniseDataWhenPackingAndUnpacking() throws Exception { - byte[] data = {0x00, 'm', 'i', 'm', 'e', '/', 't', 'y', 'p', 'e', 0, 0x03, 'D', 'E', 'S', 'C', 'R', 'I', 'P', 'T', 'I', 'O', 'N', 0, 1, 2, 3, BYTE_FF, 0x00, BYTE_FB, BYTE_FF, 0x00, BYTE_FB, BYTE_FF, 0, 0, 4, 5}; - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(true, data); - byte[] expectedImageData = {1, 2, 3, BYTE_FF, BYTE_FB, BYTE_FF, BYTE_FB, BYTE_FF, 0, 4, 5}; - assertArrayEquals(expectedImageData, frameData.getImageData()); - byte[] bytes = frameData.toBytes(); - assertArrayEquals(data, bytes); - } - - @Test - public void getsAndSetsMimeType() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false); - frameData.setMimeType("Mime Type 1"); - assertEquals("Mime Type 1", frameData.getMimeType()); - } - - @Test - public void getsAndSetsPictureType() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false); - frameData.setPictureType((byte) 4); - assertEquals((byte) 4, frameData.getPictureType()); - } - - @Test - public void getsAndSetsDescription() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false); - EncodedText description = new EncodedText("my description"); - frameData.setDescription(description); - assertEquals(description, frameData.getDescription()); - } - - @Test - public void getsAndSetsImageData() { - ID3v2PictureFrameData frameData = new ID3v2PictureFrameData(false); - frameData.setImageData(new byte[]{1, 2}); - assertArrayEquals(new byte[]{1, 2}, frameData.getImageData()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2PopmFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2PopmFrameDataTest.java deleted file mode 100644 index b5d071a..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2PopmFrameDataTest.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.mpatric.mp3agic; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import org.junit.Test; - -public class ID3v2PopmFrameDataTest { - - @Test - public void shouldReturnAddress() throws Exception { - byte[] bytes = {'A', 'd', 'd', 'r', 'e', 's', 's', 0, (byte) 0x00}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - assertEquals("Address", iD3v2PopmFrameData.getAddress()); - } - - @Test - public void shouldReturn1StarRating() throws Exception { - byte[] bytes = {'A', 'd', 'd', 'r', 'e', 's', 's', 0, (byte) 0x01}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - assertEquals(1, iD3v2PopmFrameData.getRating()); - } - - @Test - public void shouldReturn2StarRating() throws Exception { - byte[] bytes = {'A', 'd', 'd', 'r', 'e', 's', 's', 0, (byte) 0x40}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - assertEquals(2, iD3v2PopmFrameData.getRating()); - } - - @Test - public void shouldReturn3StarRating() throws Exception { - byte[] bytes = {'A', 'd', 'd', 'r', 'e', 's', 's', 0, (byte) 0x80}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - assertEquals(3, iD3v2PopmFrameData.getRating()); - } - - @Test - public void shouldReturn4StarRating() throws Exception { - byte[] bytes = {'A', 'd', 'd', 'r', 'e', 's', 's', 0, (byte) 0xC4}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - assertEquals(4, iD3v2PopmFrameData.getRating()); - } - - @Test - public void shouldReturn5StarRating() throws Exception { - byte[] bytes = {'A', 'd', 'd', 'r', 'e', 's', 's', 0, (byte) 0xFF}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - assertEquals(5, iD3v2PopmFrameData.getRating()); - } - - @Test - public void shouldReturnMinus1ForInvalidRating() throws Exception { - byte[] bytes = {'A', 'd', 'd', 'r', 'e', 's', 's', 0, (byte) 0x33}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - assertEquals(-1, iD3v2PopmFrameData.getRating()); - } - - @Test - public void canSetAndGetRating() throws Exception { - byte[] bytes = {0}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - iD3v2PopmFrameData.setRating(1); - assertEquals(1, iD3v2PopmFrameData.getRating()); - } - - @Test - public void canSetAndGetAddress() throws Exception { - byte[] bytes = {0}; - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, bytes); - iD3v2PopmFrameData.setAddress("New Address"); - assertEquals("New Address", iD3v2PopmFrameData.getAddress()); - } - - @Test - public void canGetLength() { - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, 0); - iD3v2PopmFrameData.setAddress("Address"); - final int expectedLength = "Address".length() + 2; // Length of address , plus 1 separator byte + 1 bye for rating - assertEquals(expectedLength, iD3v2PopmFrameData.getLength()); - } - - @Test - public void canPackFrameData() { - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, 5); - byte[] expectedBytes = {'W', 'i', 'n', 'd', 'o', 'w', 's', ' ', 'M', 'e', 'd', 'i', 'a', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '9', ' ', 'S', 'e', 'r', 'i', 'e', 's', 0, (byte) 0xFF}; - final byte[] result = iD3v2PopmFrameData.packFrameData(); - assertEquals(expectedBytes.length, result.length); - int i = 0; - for (byte expectedByte : expectedBytes) { - assertEquals(expectedByte, result[i++]); - } - } - - @Test - public void hashCodeOfTwoDifferentObjectsAreDifferent() { - ID3v2PopmFrameData iD3v2PopmFrameData1 = new ID3v2PopmFrameData(false, 0); - ID3v2PopmFrameData iD3v2PopmFrameData2 = new ID3v2PopmFrameData(false, 1); - assertFalse(iD3v2PopmFrameData1.hashCode() == iD3v2PopmFrameData2.hashCode()); - } - - - @Test - public void twoEquivalentObjectsAreEquals() { - ID3v2PopmFrameData iD3v2PopmFrameData1 = new ID3v2PopmFrameData(false, 0); - ID3v2PopmFrameData iD3v2PopmFrameData2 = new ID3v2PopmFrameData(false, 0); - assertEquals(iD3v2PopmFrameData1, iD3v2PopmFrameData2); - } - - @Test - public void sameObjectsAreEquals() { - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, 0); - assertEquals(iD3v2PopmFrameData, iD3v2PopmFrameData); - } - - @Test - public void ID3v2PopmFrameDataIsNotEqualOtherType() { - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, 0); - assertFalse(iD3v2PopmFrameData.equals("a String")); - } - - @Test - public void ID3v2PopmFrameDataIsNotEqualNull() { - ID3v2PopmFrameData iD3v2PopmFrameData = new ID3v2PopmFrameData(false, 0); - assertFalse(iD3v2PopmFrameData.equals(null)); - } - - @Test - public void ID3v2PopmFrameDataIsNotEqualOtherWithDifferentRating() { - ID3v2PopmFrameData iD3v2PopmFrameData1 = new ID3v2PopmFrameData(false, 1); - ID3v2PopmFrameData iD3v2PopmFrameData2 = new ID3v2PopmFrameData(false, 2); - assertFalse(iD3v2PopmFrameData1.equals(iD3v2PopmFrameData2)); - } - - @Test - public void ID3v2PopmFrameDataIsNotEqualOtherWithDifferentAddress() { - ID3v2PopmFrameData iD3v2PopmFrameData1 = new ID3v2PopmFrameData(false, 1); - iD3v2PopmFrameData1.setAddress("Address1"); - ID3v2PopmFrameData iD3v2PopmFrameData2 = new ID3v2PopmFrameData(false, 1); - iD3v2PopmFrameData1.setAddress("Address2"); - assertFalse(iD3v2PopmFrameData1.equals(iD3v2PopmFrameData2)); - } - - @Test - public void ID3v2PopmFrameDataIsNotEqualOtherWithNullAddress() { - ID3v2PopmFrameData iD3v2PopmFrameData1 = new ID3v2PopmFrameData(false, 1); - iD3v2PopmFrameData1.setAddress("Address1"); - ID3v2PopmFrameData iD3v2PopmFrameData2 = new ID3v2PopmFrameData(false, 1); - iD3v2PopmFrameData1.setAddress(null); - assertFalse(iD3v2PopmFrameData1.equals(iD3v2PopmFrameData2)); - } - - -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2TagTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2TagTest.java deleted file mode 100644 index 44c79db..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2TagTest.java +++ /dev/null @@ -1,609 +0,0 @@ -package com.mpatric.mp3agic; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class ID3v2TagTest { - - private static final byte BYTE_I = 0x49; - private static final byte BYTE_D = 0x44; - private static final byte BYTE_3 = 0x33; - private static final byte[] ID3V2_HEADER = {BYTE_I, BYTE_D, BYTE_3, 4, 0, 0, 0, 0, 2, 1}; - - @Test - public void shouldInitialiseFromHeaderBlockWithValidHeaders() throws NoSuchTagException, UnsupportedTagException, InvalidDataException { - byte[] header = BufferTools.copyBuffer(ID3V2_HEADER, 0, ID3V2_HEADER.length); - header[3] = 2; - header[4] = 0; - ID3v2 id3v2tag; - id3v2tag = createTag(header); - assertEquals("2.0", id3v2tag.getVersion()); - header[3] = 3; - id3v2tag = createTag(header); - assertEquals("3.0", id3v2tag.getVersion()); - header[3] = 4; - id3v2tag = createTag(header); - assertEquals("4.0", id3v2tag.getVersion()); - } - - @Test - public void shouldCalculateCorrectDataLengthsFromHeaderBlock() throws NoSuchTagException, UnsupportedTagException, InvalidDataException { - byte[] header = BufferTools.copyBuffer(ID3V2_HEADER, 0, ID3V2_HEADER.length); - ID3v2 id3v2tag = createTag(header); - assertEquals(257, id3v2tag.getDataLength()); - header[8] = 0x09; - header[9] = 0x41; - id3v2tag = createTag(header); - assertEquals(1217, id3v2tag.getDataLength()); - } - - @Test - public void shouldThrowExceptionForNonSupportedVersionInId3v2HeaderBlock() throws NoSuchTagException, InvalidDataException { - byte[] header = BufferTools.copyBuffer(ID3V2_HEADER, 0, ID3V2_HEADER.length); - header[3] = 5; - header[4] = 0; - try { - ID3v2TagFactory.createTag(header); - fail("UnsupportedTagException expected but not thrown"); - } catch (UnsupportedTagException e) { - // expected - } - } - - @Test - public void shouldSortId3TagsAlphabetically() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v1andv23tags.mp3"); - ID3v2 id3v2tag = ID3v2TagFactory.createTag(buffer); - Map frameSets = id3v2tag.getFrameSets(); - Iterator frameSetIterator = frameSets.values().iterator(); - String lastKey = ""; - while (frameSetIterator.hasNext()) { - ID3v2FrameSet frameSet = frameSetIterator.next(); - assertTrue(frameSet.getId().compareTo(lastKey) > 0); - lastKey = frameSet.getId(); - } - } - - @Test - public void shouldReadFramesFromMp3With32Tag() throws IOException, NoSuchTagException, UnsupportedTagException, InvalidDataException { - byte[] buffer = TestHelper.loadFile("src/test/resources/v1andv23tags.mp3"); - ID3v2 id3v2tag = ID3v2TagFactory.createTag(buffer); - assertEquals("3.0", id3v2tag.getVersion()); - assertEquals(0x44B, id3v2tag.getLength()); - assertEquals(12, id3v2tag.getFrameSets().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TENC")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("WXXX")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TCOP")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TOPE")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TCOM")).getFrames().size()); - assertEquals(2, (id3v2tag.getFrameSets().get("COMM")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TPE1")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TALB")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TRCK")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TYER")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TCON")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TIT2")).getFrames().size()); - } - - @Test - public void shouldReadId3v2WithFooter() throws IOException, NoSuchTagException, UnsupportedTagException, InvalidDataException { - byte[] buffer = TestHelper.loadFile("src/test/resources/v1andv24tags.mp3"); - ID3v2 id3v2tag = ID3v2TagFactory.createTag(buffer); - assertEquals("4.0", id3v2tag.getVersion()); - assertEquals(0x44B, id3v2tag.getLength()); - } - - @Test - public void shouldReadTagFieldsFromMp3With24tag() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v24tagswithalbumimage.mp3"); - ID3v2 id3v24tag = ID3v2TagFactory.createTag(buffer); - assertEquals("4.0", id3v24tag.getVersion()); - assertEquals("1", id3v24tag.getTrack()); - assertEquals("ARTIST123456789012345678901234", id3v24tag.getArtist()); - assertEquals("TITLE1234567890123456789012345", id3v24tag.getTitle()); - assertEquals("ALBUM1234567890123456789012345", id3v24tag.getAlbum()); - assertEquals(0x0d, id3v24tag.getGenre()); - assertEquals("Pop", id3v24tag.getGenreDescription()); - assertEquals("COMMENT123456789012345678901", id3v24tag.getComment()); - assertEquals("LYRICS1234567890123456789012345", id3v24tag.getLyrics()); - assertEquals("COMPOSER23456789012345678901234", id3v24tag.getComposer()); - assertEquals("ORIGARTIST234567890123456789012", id3v24tag.getOriginalArtist()); - assertEquals("COPYRIGHT2345678901234567890123", id3v24tag.getCopyright()); - assertEquals("URL2345678901234567890123456789", id3v24tag.getUrl()); - assertEquals("COMMERCIALURL234567890123456789", id3v24tag.getCommercialUrl()); - assertEquals("COPYRIGHTURL2345678901234567890", id3v24tag.getCopyrightUrl()); - assertEquals("OFFICIALARTISTURL23456789012345", id3v24tag.getArtistUrl()); - assertEquals("OFFICIALAUDIOFILE23456789012345", id3v24tag.getAudiofileUrl()); - assertEquals("OFFICIALAUDIOSOURCE234567890123", id3v24tag.getAudioSourceUrl()); - assertEquals("INTERNETRADIOSTATIONURL23456783", id3v24tag.getRadiostationUrl()); - assertEquals("PAYMENTURL234567890123456789012", id3v24tag.getPaymentUrl()); - assertEquals("PUBLISHERURL2345678901234567890", id3v24tag.getPublisherUrl()); - assertEquals("ENCODER234567890123456789012345", id3v24tag.getEncoder()); - assertEquals(1885, id3v24tag.getAlbumImage().length); - assertEquals("image/png", id3v24tag.getAlbumImageMimeType()); - } - - @Test - public void shouldReadTagFieldsFromMp3With32tag() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v1andv23tagswithalbumimage.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals("1", id3tag.getTrack()); - assertEquals("ARTIST123456789012345678901234", id3tag.getArtist()); - assertEquals("TITLE1234567890123456789012345", id3tag.getTitle()); - assertEquals("ALBUM1234567890123456789012345", id3tag.getAlbum()); - assertEquals("2001", id3tag.getYear()); - assertEquals(0x0d, id3tag.getGenre()); - assertEquals("Pop", id3tag.getGenreDescription()); - assertEquals("COMMENT123456789012345678901", id3tag.getComment()); - assertEquals("LYRICS1234567890123456789012345", id3tag.getLyrics()); - assertEquals("COMPOSER23456789012345678901234", id3tag.getComposer()); - assertEquals("ORIGARTIST234567890123456789012", id3tag.getOriginalArtist()); - assertEquals("COPYRIGHT2345678901234567890123", id3tag.getCopyright()); - assertEquals("URL2345678901234567890123456789", id3tag.getUrl()); - assertEquals("ENCODER234567890123456789012345", id3tag.getEncoder()); - assertEquals(1885, id3tag.getAlbumImage().length); - assertEquals("image/png", id3tag.getAlbumImageMimeType()); - } - - @Test - public void shouldConvert23TagToBytesAndBackToEquivalentTag() throws Exception { - ID3v2 id3tag = new ID3v23Tag(); - setTagFields(id3tag); - byte[] data = id3tag.toBytes(); - ID3v2 id3tagCopy = new ID3v23Tag(data); - assertEquals(2340, data.length); - assertEquals(id3tag, id3tagCopy); - } - - @Test - public void shouldConvert24TagWithFooterToBytesAndBackToEquivalentTag() throws Exception { - ID3v2 id3tag = new ID3v24Tag(); - setTagFields(id3tag); - id3tag.setFooter(true); - byte[] data = id3tag.toBytes(); - ID3v2 id3tagCopy = new ID3v24Tag(data); - assertEquals(2350, data.length); - assertEquals(id3tag, id3tagCopy); - } - - @Test - public void shouldConvert24TagWithPaddingToBytesAndBackToEquivalentTag() throws Exception { - ID3v2 id3tag = new ID3v24Tag(); - setTagFields(id3tag); - id3tag.setPadding(true); - byte[] data = id3tag.toBytes(); - ID3v2 id3tagCopy = new ID3v24Tag(data); - assertEquals(2340 + AbstractID3v2Tag.PADDING_LENGTH, data.length); - assertEquals(id3tag, id3tagCopy); - } - - @Test - public void shouldNotUsePaddingOnA24TagIfItHasAFooter() throws Exception { - ID3v2 id3tag = new ID3v24Tag(); - setTagFields(id3tag); - id3tag.setFooter(true); - id3tag.setPadding(true); - byte[] data = id3tag.toBytes(); - assertEquals(2350, data.length); - } - - @Test - public void shouldExtractGenreNumberFromCombinedGenreStringsCorrectly() { - ID3v23TagForTesting id3tag = new ID3v23TagForTesting(); - try { - id3tag.extractGenreNumber(""); - fail("NumberFormatException expected but not thrown"); - } catch (NumberFormatException e) { - // expected - } - assertEquals(13, id3tag.extractGenreNumber("13")); - assertEquals(13, id3tag.extractGenreNumber("(13)")); - assertEquals(13, id3tag.extractGenreNumber("(13)Pop")); - } - - @Test - public void shouldExtractGenreDescriptionFromCombinedGenreStringsCorrectly() { - ID3v23TagForTesting id3tag = new ID3v23TagForTesting(); - assertNull(id3tag.extractGenreDescription("")); - assertEquals("", id3tag.extractGenreDescription("(13)")); - assertEquals("Pop", id3tag.extractGenreDescription("(13)Pop")); - } - - @Test - public void shouldSetCombinedGenreOnTag() throws Exception { - ID3v2 id3tag = new ID3v23Tag(); - setTagFields(id3tag); - Map frameSets = id3tag.getFrameSets(); - ID3v2FrameSet frameSet = frameSets.get("TCON"); - List frames = frameSet.getFrames(); - ID3v2Frame frame = frames.get(0); - byte[] bytes = frame.getData(); - String genre = BufferTools.byteBufferToString(bytes, 1, bytes.length - 1); - assertEquals("(13)Pop", genre); - } - - @Test - public void testSetGenreDescriptionOn23Tag() throws Exception { - ID3v2 id3tag = new ID3v23Tag(); - setTagFields(id3tag); - id3tag.setGenreDescription("Jazz"); - assertEquals("Jazz", id3tag.getGenreDescription()); - assertEquals(8, id3tag.getGenre()); - - Map frameSets = id3tag.getFrameSets(); - ID3v2FrameSet frameSet = frameSets.get("TCON"); - List frames = frameSet.getFrames(); - ID3v2Frame frame = frames.get(0); - byte[] bytes = frame.getData(); - String genre = BufferTools.byteBufferToString(bytes, 1, bytes.length - 1); - assertEquals("(8)Jazz", genre); - } - - @Test - public void testSetGenreDescriptionOn23TagWithUnknownGenre() throws Exception { - ID3v2 id3tag = new ID3v23Tag(); - setTagFields(id3tag); - try { - id3tag.setGenreDescription("Bebop"); - fail("expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // fine - } - } - - @Test - public void testSetGenreDescriptionOn24Tag() throws Exception { - ID3v2 id3tag = new ID3v24Tag(); - setTagFields(id3tag); - id3tag.setGenreDescription("Jazz"); - assertEquals("Jazz", id3tag.getGenreDescription()); - assertEquals(8, id3tag.getGenre()); - - Map frameSets = id3tag.getFrameSets(); - ID3v2FrameSet frameSet = frameSets.get("TCON"); - List frames = frameSet.getFrames(); - ID3v2Frame frame = frames.get(0); - byte[] bytes = frame.getData(); - String genre = BufferTools.byteBufferToString(bytes, 1, bytes.length - 1); - assertEquals("Jazz", genre); - } - - @Test - public void testSetGenreDescriptionOn24TagWithUnknownGenre() throws Exception { - ID3v2 id3tag = new ID3v24Tag(); - setTagFields(id3tag); - id3tag.setGenreDescription("Bebop"); - assertEquals("Bebop", id3tag.getGenreDescription()); - assertEquals(-1, id3tag.getGenre()); - - Map frameSets = id3tag.getFrameSets(); - ID3v2FrameSet frameSet = frameSets.get("TCON"); - List frames = frameSet.getFrames(); - ID3v2Frame frame = frames.get(0); - byte[] bytes = frame.getData(); - String genre = BufferTools.byteBufferToString(bytes, 1, bytes.length - 1); - assertEquals("Bebop", genre); - } - - @Test - public void shouldReadCombinedGenreInTag() throws Exception { - ID3v2 id3tag = new ID3v23Tag(); - setTagFields(id3tag); - byte[] bytes = id3tag.toBytes(); - ID3v2 id3tagFromData = new ID3v23Tag(bytes); - assertEquals(13, id3tagFromData.getGenre()); - assertEquals("Pop", id3tagFromData.getGenreDescription()); - } - - @Test - public void shouldGetCommentAndItunesComment() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/withitunescomment.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals("COMMENT123456789012345678901", id3tag.getComment()); - assertEquals(" 00000A78 00000A74 00000C7C 00000C6C 00000000 00000000 000051F7 00005634 00000000 00000000", id3tag.getItunesComment()); - } - - @Test - public void shouldReadFramesFromMp3WithObselete32Tag() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/obsolete.mp3"); - ID3v2 id3v2tag = ID3v2TagFactory.createTag(buffer); - assertEquals("2.0", id3v2tag.getVersion()); - assertEquals(0x3c5a2, id3v2tag.getLength()); - assertEquals(10, id3v2tag.getFrameSets().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TCM")).getFrames().size()); - assertEquals(2, (id3v2tag.getFrameSets().get("COM")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TP1")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TAL")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TRK")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TPA")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TYE")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("PIC")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TCO")).getFrames().size()); - assertEquals(1, (id3v2tag.getFrameSets().get("TT2")).getFrames().size()); - } - - @Test - public void shouldReadTagFieldsFromMp3WithObselete32tag() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/obsolete.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals("2009", id3tag.getYear()); - assertEquals("4/15", id3tag.getTrack()); - assertEquals("image/png", id3tag.getAlbumImageMimeType()); - assertEquals(40, id3tag.getGenre()); - assertEquals("Alt Rock", id3tag.getGenreDescription()); - assertEquals("NAME1234567890123456789012345678901234567890", id3tag.getTitle()); - assertEquals("ARTIST1234567890123456789012345678901234567890", id3tag.getArtist()); - assertEquals("COMPOSER1234567890123456789012345678901234567890", id3tag.getComposer()); - assertEquals("ALBUM1234567890123456789012345678901234567890", id3tag.getAlbum()); - assertEquals("COMMENTS1234567890123456789012345678901234567890", id3tag.getComment()); - } - - @Test - public void shouldReadTagFieldsWithUnicodeDataFromMp3() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v23unicodetags.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals("\u03B3\u03B5\u03B9\u03AC \u03C3\u03BF\u03C5", id3tag.getArtist()); // greek - assertEquals("\u4E2D\u6587", id3tag.getTitle()); // chinese - assertEquals("\u3053\u3093\u306B\u3061\u306F", id3tag.getAlbum()); // japanese - assertEquals("\u0AB9\u0AC7\u0AB2\u0ACD\u0AB2\u0ACB", id3tag.getComposer()); // gujarati - } - - @Test - public void shouldSetTagFieldsWithUnicodeDataAndSpecifiedEncodingCorrectly() throws Exception { - ID3v2 id3tag = new ID3v23Tag(); - id3tag.setArtist("\u03B3\u03B5\u03B9\u03AC \u03C3\u03BF\u03C5"); - id3tag.setTitle("\u4E2D\u6587"); - id3tag.setAlbum("\u3053\u3093\u306B\u3061\u306F"); - id3tag.setComment("\u03C3\u03BF\u03C5"); - id3tag.setComposer("\u0AB9\u0AC7\u0AB2\u0ACD\u0AB2\u0ACB"); - id3tag.setOriginalArtist("\u03B3\u03B5\u03B9\u03AC"); - id3tag.setCopyright("\u03B3\u03B5"); - id3tag.setUrl("URL"); - id3tag.setEncoder("\u03B9\u03AC"); - byte[] albumImage = TestHelper.loadFile("src/test/resources/image.png"); - id3tag.setAlbumImage(albumImage, "image/png", ID3v23Tag.PICTURETYPE_OTHER, "\u03B3\u03B5\u03B9\u03AC"); - } - - @Test - public void shouldExtractChapterTOCFramesFromMp3() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v23tagwithchapters.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - - ArrayList chapterTOCs = id3tag.getChapterTOC(); - assertEquals(1, chapterTOCs.size()); - - ID3v2ChapterTOCFrameData tocFrameData = chapterTOCs.get(0); - assertEquals("toc1", tocFrameData.getId()); - String[] expectedChildren = {"ch1", "ch2", "ch3"}; - assertArrayEquals(expectedChildren, tocFrameData.getChildren()); - - ArrayList subFrames = tocFrameData.getSubframes(); - assertEquals(0, subFrames.size()); - } - - @Test - public void shouldExtractChapterTOCAndChapterFramesFromMp3() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v23tagwithchapters.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - - ArrayList chapters = id3tag.getChapters(); - assertEquals(3, chapters.size()); - - ID3v2ChapterFrameData chapter1 = chapters.get(0); - assertEquals("ch1", chapter1.getId()); - assertEquals(0, chapter1.getStartTime()); - assertEquals(5000, chapter1.getEndTime()); - assertEquals(-1, chapter1.getStartOffset()); - assertEquals(-1, chapter1.getEndOffset()); - - ArrayList subFrames1 = chapter1.getSubframes(); - assertEquals(1, subFrames1.size()); - ID3v2Frame subFrame1 = subFrames1.get(0); - assertEquals("TIT2", subFrame1.getId()); - ID3v2TextFrameData frameData1 = new ID3v2TextFrameData(false, subFrame1.getData()); - assertEquals("start", frameData1.getText().toString()); - - ID3v2ChapterFrameData chapter2 = chapters.get(1); - assertEquals("ch2", chapter2.getId()); - assertEquals(5000, chapter2.getStartTime()); - assertEquals(10000, chapter2.getEndTime()); - assertEquals(-1, chapter2.getStartOffset()); - assertEquals(-1, chapter2.getEndOffset()); - - ArrayList subFrames2 = chapter2.getSubframes(); - assertEquals(1, subFrames2.size()); - ID3v2Frame subFrame2 = subFrames2.get(0); - assertEquals("TIT2", subFrame2.getId()); - ID3v2TextFrameData frameData2 = new ID3v2TextFrameData(false, subFrame2.getData()); - assertEquals("5 seconds", frameData2.getText().toString()); - - ID3v2ChapterFrameData chapter3 = chapters.get(2); - assertEquals("ch3", chapter3.getId()); - assertEquals(10000, chapter3.getStartTime()); - assertEquals(15000, chapter3.getEndTime()); - assertEquals(-1, chapter3.getStartOffset()); - assertEquals(-1, chapter3.getEndOffset()); - - ArrayList subFrames3 = chapter3.getSubframes(); - assertEquals(1, subFrames3.size()); - ID3v2Frame subFrame3 = subFrames3.get(0); - assertEquals("TIT2", subFrame3.getId()); - ID3v2TextFrameData frameData3 = new ID3v2TextFrameData(false, subFrame3.getData()); - assertEquals("10 seconds", frameData3.getText().toString()); - } - - @Test - public void shouldReadTagFieldsFromMp3With32tagResavedByMp3tagWithUTF16Encoding() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v1andv23tagswithalbumimage-utf16le.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals("1", id3tag.getTrack()); - assertEquals("ARTIST123456789012345678901234", id3tag.getArtist()); - assertEquals("TITLE1234567890123456789012345", id3tag.getTitle()); - assertEquals("ALBUM1234567890123456789012345", id3tag.getAlbum()); - assertEquals("2001", id3tag.getYear()); - assertEquals(0x01, id3tag.getGenre()); - assertEquals("Classic Rock", id3tag.getGenreDescription()); - assertEquals("COMMENT123456789012345678901", id3tag.getComment()); - assertEquals("COMPOSER23456789012345678901234", id3tag.getComposer()); - assertEquals("ORIGARTIST234567890123456789012", id3tag.getOriginalArtist()); - assertEquals("COPYRIGHT2345678901234567890123", id3tag.getCopyright()); - assertEquals("URL2345678901234567890123456789", id3tag.getUrl()); - assertEquals("ENCODER234567890123456789012345", id3tag.getEncoder()); - assertEquals(1885, id3tag.getAlbumImage().length); - assertEquals("image/png", id3tag.getAlbumImageMimeType()); - } - - @Test - public void shouldRemoveAlbumImageFrame() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v1andv23tagswithalbumimage.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals(1885, id3tag.getAlbumImage().length); - id3tag.clearAlbumImage(); - assertNull(id3tag.getAlbumImage()); - } - - @Test - public void shouldReadBPM() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v23tagwithbpm.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals(84, id3tag.getBPM()); - } - - @Test - public void shouldReadFloatingPointBPM() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v23tagwithbpmfloat.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals(84, id3tag.getBPM()); - } - - @Test - public void shouldReadFloatingPointBPMWithCommaDelimiter() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v23tagwithbpmfloatwithcomma.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals(84, id3tag.getBPM()); - } - - @Test - public void shouldReadWmpRating() throws Exception { - byte[] buffer = TestHelper.loadFile("src/test/resources/v23tagwithwmprating.mp3"); - ID3v2 id3tag = ID3v2TagFactory.createTag(buffer); - assertEquals(3, id3tag.getWmpRating()); - } - - @Test - public void shouldWriteWmpRating() throws Exception { - ID3v2 id3tag = new ID3v23Tag(); - setTagFields(id3tag); - final int expectedUnsetValue = -1; - assertEquals(expectedUnsetValue, id3tag.getWmpRating()); - final int newValue = 4; - id3tag.setWmpRating(newValue); - assertEquals(newValue, id3tag.getWmpRating()); - } - - @Test - public void shouldIgnoreInvalidWmpRatingOnWrite() throws Exception { - ID3v2 id3tag = new ID3v23Tag(); - setTagFields(id3tag); - final int originalValue = id3tag.getWmpRating(); - final int invalidValue = 6; - id3tag.setWmpRating(invalidValue); - assertEquals(originalValue, id3tag.getWmpRating()); - } - - - private void setTagFields(ID3v2 id3tag) throws IOException { - id3tag.setTrack("1"); - id3tag.setArtist("ARTIST"); - id3tag.setTitle("TITLE"); - id3tag.setAlbum("ALBUM"); - id3tag.setYear("1954"); - id3tag.setGenre(0x0d); - id3tag.setComment("COMMENT"); - id3tag.setComposer("COMPOSER"); - id3tag.setOriginalArtist("ORIGINALARTIST"); - id3tag.setCopyright("COPYRIGHT"); - id3tag.setUrl("URL"); - id3tag.setCommercialUrl("COMMERCIALURL"); - id3tag.setCopyrightUrl("COPYRIGHTURL"); - id3tag.setArtistUrl("OFFICIALARTISTURL"); - id3tag.setAudiofileUrl("OFFICIALAUDIOFILEURL"); - id3tag.setAudioSourceUrl("OFFICIALAUDIOSOURCEURL"); - id3tag.setRadiostationUrl("INTERNETRADIOSTATIONURL"); - id3tag.setPaymentUrl("PAYMENTURL"); - id3tag.setPublisherUrl("PUBLISHERURL"); - id3tag.setEncoder("ENCODER"); - byte[] albumImage = TestHelper.loadFile("src/test/resources/image.png"); - id3tag.setAlbumImage(albumImage, "image/png"); - } - - private ID3v2 createTag(byte[] buffer) throws NoSuchTagException, UnsupportedTagException, InvalidDataException { - ID3v2TagFactoryForTesting factory = new ID3v2TagFactoryForTesting(); - return factory.createTag(buffer); - } - - static class ID3v22TagForTesting extends ID3v22Tag { - - ID3v22TagForTesting(byte[] buffer) throws NoSuchTagException, UnsupportedTagException, InvalidDataException { - super(buffer); - } - - @Override - protected int unpackFrames(byte[] buffer, int offset, int framesLength) { - return offset; - } - } - - static class ID3v23TagForTesting extends ID3v23Tag { - - ID3v23TagForTesting() { - super(); - } - - ID3v23TagForTesting(byte[] buffer) throws NoSuchTagException, UnsupportedTagException, InvalidDataException { - super(buffer); - } - - @Override - protected int unpackFrames(byte[] buffer, int offset, int framesLength) { - return offset; - } - } - - static class ID3v24TagForTesting extends ID3v24Tag { - - ID3v24TagForTesting(byte[] buffer) throws NoSuchTagException, UnsupportedTagException, InvalidDataException { - super(buffer); - } - - @Override - protected int unpackFrames(byte[] buffer, int offset, int framesLength) { - return offset; - } - } - - static class ID3v2TagFactoryForTesting { - - static final int MAJOR_VERSION_OFFSET = 3; - - ID3v2 createTag(byte[] buffer) throws NoSuchTagException, UnsupportedTagException, InvalidDataException { - int majorVersion = buffer[MAJOR_VERSION_OFFSET]; - switch (majorVersion) { - case 2: - return new ID3v22TagForTesting(buffer); - case 3: - return new ID3v23TagForTesting(buffer); - case 4: - return new ID3v24TagForTesting(buffer); - } - throw new UnsupportedTagException("Tag version not supported"); - } - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2TextFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2TextFrameDataTest.java deleted file mode 100644 index 22d16d6..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2TextFrameDataTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; - -public class ID3v2TextFrameDataTest { - - private static final String TEST_TEXT = "ABCDEFGHIJKLMNOPQ"; - private static final String TEST_TEXT_UNICODE = "\u03B3\u03B5\u03B9\u03AC"; - - @Test - public void equalsItself() { - ID3v2TextFrameData frameData = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - assertEquals(frameData, frameData); - } - - @Test - public void notEqualToNull() { - ID3v2TextFrameData frameData = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - assertFalse(frameData.equals(null)); - } - - @Test - public void notEqualToDifferentClass() { - ID3v2TextFrameData frameData = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - assertFalse(frameData.equals("8")); - } - - @Test - public void notEqualIfUnsynchronizationNotEqual() { - ID3v2TextFrameData frameData1 = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - ID3v2TextFrameData frameData2 = new ID3v2TextFrameData(true, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfTextNotEqual() { - ID3v2TextFrameData frameData1 = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - ID3v2TextFrameData frameData2 = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, "other text")); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfTextIsNullOnOne() { - ID3v2TextFrameData frameData1 = new ID3v2TextFrameData(false, (EncodedText) null); - ID3v2TextFrameData frameData2 = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfTextIsNullOnBoth() { - ID3v2TextFrameData frameData1 = new ID3v2TextFrameData(false, (EncodedText) null); - ID3v2TextFrameData frameData2 = new ID3v2TextFrameData(false, (EncodedText) null); - assertEquals(frameData1, frameData2); - } - - @Test - public void hashCodeIsConsistent() { - ID3v2TextFrameData frameData = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - assertEquals(frameData.hashCode(), frameData.hashCode()); - } - - @Test - public void equalObjectsHaveSameHashCode() { - ID3v2TextFrameData frameData = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - ID3v2TextFrameData frameDataAgain = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - assertEquals(frameData.hashCode(), frameDataAgain.hashCode()); - } - - @Test - public void shouldConsiderTwoEquivalentObjectsEqual() { - ID3v2TextFrameData frameData1 = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - ID3v2TextFrameData frameData2 = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - assertEquals(frameData1, frameData2); - } - - @Test - public void shouldConvertFrameDataToBytesAndBackToEquivalentObject() throws Exception { - ID3v2TextFrameData frameData = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_ISO_8859_1, TEST_TEXT)); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'}; - assertArrayEquals(expectedBytes, bytes); - ID3v2TextFrameData frameDataCopy = new ID3v2TextFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void shouldConvertFrameDataWithUnicodeToBytesAndBackToEquivalentObject() throws Exception { - ID3v2TextFrameData frameData = new ID3v2TextFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TEST_TEXT_UNICODE)); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {1, (byte) 0xff, (byte) 0xfe, (byte) 0xb3, 0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0x03, (byte) 0xac, 0x03}; - assertArrayEquals(expectedBytes, bytes); - ID3v2TextFrameData frameDataCopy = new ID3v2TextFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void getsAndSetsDescription() { - ID3v2TextFrameData frameData = new ID3v2TextFrameData(false); - EncodedText text = new EncodedText("my text"); - frameData.setText(text); - assertEquals(text, frameData.getText()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2UrlFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2UrlFrameDataTest.java deleted file mode 100644 index 3d0c479..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2UrlFrameDataTest.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; - -public class ID3v2UrlFrameDataTest { - - private static final String TEST_DESCRIPTION = "DESCRIPTION"; - private static final String TEST_DESCRIPTION_UNICODE = "\u03B3\u03B5\u03B9\u03AC"; - private static final String TEST_URL = "http://ABCDEFGHIJKLMNOPQ"; - - @Test - public void equalsItself() { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertEquals(frameData, frameData); - } - - @Test - public void notEqualToNull() { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertFalse(frameData.equals(null)); - } - - @Test - public void notEqualToDifferentClass() { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertFalse(frameData.equals("8")); - } - - @Test - public void shouldConsiderTwoEquivalentObjectsEqual() { - ID3v2UrlFrameData frameData1 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - ID3v2UrlFrameData frameData2 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfUnsynchronizationNotEqual() { - ID3v2UrlFrameData frameData1 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - ID3v2UrlFrameData frameData2 = new ID3v2UrlFrameData(true, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfDescriptionNotEqual() { - ID3v2UrlFrameData frameData1 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - ID3v2UrlFrameData frameData2 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, "other description"), TEST_URL); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfDescriptionIsNullOnOne() { - ID3v2UrlFrameData frameData1 = new ID3v2UrlFrameData(false, null, TEST_URL); - ID3v2UrlFrameData frameData2 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfDescriptionIsNullOnBoth() { - ID3v2UrlFrameData frameData1 = new ID3v2UrlFrameData(false, null, TEST_URL); - ID3v2UrlFrameData frameData2 = new ID3v2UrlFrameData(false, null, TEST_URL); - assertEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfUrlNotEqual() { - ID3v2UrlFrameData frameData1 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - ID3v2UrlFrameData frameData2 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), "other url"); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void notEqualIfIdUrlNullOnOne() { - ID3v2UrlFrameData frameData1 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - ID3v2UrlFrameData frameData2 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertNotEquals(frameData1, frameData2); - } - - @Test - public void equalIfUrlIsNullOnBoth() { - ID3v2UrlFrameData frameData1 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - ID3v2UrlFrameData frameData2 = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), null); - assertEquals(frameData1, frameData2); - } - - @Test - public void hashCodeIsConsistent() { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertEquals(frameData.hashCode(), frameData.hashCode()); - } - - @Test - public void equalObjectsHaveSameHashCode() { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - ID3v2UrlFrameData frameDataAgain = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - assertEquals(frameData.hashCode(), frameDataAgain.hashCode()); - } - - @Test - public void shouldConvertFrameDataToBytesAndBackToEquivalentObject() throws Exception { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false, new EncodedText((byte) 0, TEST_DESCRIPTION), TEST_URL); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {0, 'D', 'E', 'S', 'C', 'R', 'I', 'P', 'T', 'I', 'O', 'N', 0, 'h', 't', 't', 'p', ':', '/', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'}; - assertArrayEquals(expectedBytes, bytes); - ID3v2UrlFrameData frameDataCopy = new ID3v2UrlFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void shouldConvertFrameDataWithNoDescriptionToBytesAndBackToEquivalentObject() throws Exception { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false, new EncodedText(""), TEST_URL); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {0, 0, 'h', 't', 't', 'p', ':', '/', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'}; - assertArrayEquals(expectedBytes, bytes); - ID3v2UrlFrameData frameDataCopy = new ID3v2UrlFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void shouldConvertFrameDataWithUnicodeDescriptionToBytesAndBackToEquivalentObject() throws Exception { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false, new EncodedText(EncodedText.TEXT_ENCODING_UTF_16, TEST_DESCRIPTION_UNICODE), TEST_URL); - byte[] bytes = frameData.toBytes(); - byte[] expectedBytes = {1, (byte) 0xff, (byte) 0xfe, (byte) 0xb3, 0x03, (byte) 0xb5, 0x03, (byte) 0xb9, 0x03, (byte) 0xac, 0x03, 0, 0, 'h', 't', 't', 'p', ':', '/', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'}; - assertArrayEquals(expectedBytes, bytes); - ID3v2UrlFrameData frameDataCopy = new ID3v2UrlFrameData(false, bytes); - assertEquals(frameData, frameDataCopy); - } - - @Test - public void getsAndSetsDescription() { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false); - EncodedText description = new EncodedText("my description"); - frameData.setDescription(description); - assertEquals(description, frameData.getDescription()); - } - - @Test - public void getsAndSetsUrl() { - ID3v2UrlFrameData frameData = new ID3v2UrlFrameData(false); - frameData.setUrl("My URL"); - assertEquals("My URL", frameData.getUrl()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/ID3v2WWWFrameDataTest.java b/src/test/java/com/mpatric/mp3agic/ID3v2WWWFrameDataTest.java deleted file mode 100644 index 80d41cd..0000000 --- a/src/test/java/com/mpatric/mp3agic/ID3v2WWWFrameDataTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class ID3v2WWWFrameDataTest { - @Test - public void getsAndSetsId() { - ID3v2WWWFrameData frameData = new ID3v2WWWFrameData(false); - frameData.setUrl("My URL"); - assertEquals("My URL", frameData.getUrl()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/InvalidDataExceptionTest.java b/src/test/java/com/mpatric/mp3agic/InvalidDataExceptionTest.java deleted file mode 100644 index a907ce1..0000000 --- a/src/test/java/com/mpatric/mp3agic/InvalidDataExceptionTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -public class InvalidDataExceptionTest { - @Test - public void defaultConstructor() { - InvalidDataException exception = new InvalidDataException(); - assertNull(exception.getMessage()); - assertNull(exception.getCause()); - } - - @Test - public void constructorWithMessage() { - InvalidDataException exception = new InvalidDataException("A message"); - assertEquals("A message", exception.getMessage()); - assertNull(exception.getCause()); - } - - @Test - public void constructorWithMessageAndCause() { - Throwable exceptionCause = new IllegalArgumentException("Bad argument"); - InvalidDataException exception = new InvalidDataException("A message", exceptionCause); - assertEquals("A message", exception.getMessage()); - assertEquals(exceptionCause, exception.getCause()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/Mp3FileTest.java b/src/test/java/com/mpatric/mp3agic/Mp3FileTest.java deleted file mode 100644 index 56777a9..0000000 --- a/src/test/java/com/mpatric/mp3agic/Mp3FileTest.java +++ /dev/null @@ -1,484 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.nio.channels.SeekableByteChannel; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; - -import static junit.framework.TestCase.assertFalse; -import static org.junit.Assert.*; - -public class Mp3FileTest { - - private static final String fs = File.separator; - private static final String MP3_WITH_NO_TAGS = "src" + fs + "test" + fs + "resources" + fs + "notags.mp3"; - private static final String MP3_WITH_ID3V1_AND_ID3V23_TAGS = "src" + fs + "test" + fs + "resources" + fs + "v1andv23tags.mp3"; - private static final String MP3_WITH_DUMMY_START_AND_END_FRAMES = "src" + fs + "test" + fs + "resources" + fs + "dummyframes.mp3"; - private static final String MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS = "src" + fs + "test" + fs + "resources" + fs + "v1andv23andcustomtags.mp3"; - private static final String MP3_WITH_ID3V23_UNICODE_TAGS = "src" + fs + "test" + fs + "resources" + fs + "v23unicodetags.mp3"; - private static final String NOT_AN_MP3 = "src" + fs + "test" + fs + "resources" + fs + "notanmp3.mp3"; - private static final String MP3_WITH_INCOMPLETE_MPEG_FRAME = "src" + fs + "test" + fs + "resources" + fs + "incompletempegframe.mp3"; - - @Test - public void shouldLoadMp3WithNoTags() throws IOException, UnsupportedTagException, InvalidDataException { - loadAndCheckTestMp3WithNoTags(MP3_WITH_NO_TAGS, 41); - loadAndCheckTestMp3WithNoTags(MP3_WITH_NO_TAGS, 256); - loadAndCheckTestMp3WithNoTags(MP3_WITH_NO_TAGS, 1024); - loadAndCheckTestMp3WithNoTags(MP3_WITH_NO_TAGS, 5000); - loadAndCheckTestMp3WithNoTags(new File(MP3_WITH_NO_TAGS), 41); - loadAndCheckTestMp3WithNoTags(new File(MP3_WITH_NO_TAGS), 256); - loadAndCheckTestMp3WithNoTags(new File(MP3_WITH_NO_TAGS), 1024); - loadAndCheckTestMp3WithNoTags(new File(MP3_WITH_NO_TAGS), 5000); - } - - @Test - public void shouldLoadMp3WithId3Tags() throws IOException, UnsupportedTagException, InvalidDataException { - loadAndCheckTestMp3WithTags(MP3_WITH_ID3V1_AND_ID3V23_TAGS, 41); - loadAndCheckTestMp3WithTags(MP3_WITH_ID3V1_AND_ID3V23_TAGS, 256); - loadAndCheckTestMp3WithTags(MP3_WITH_ID3V1_AND_ID3V23_TAGS, 1024); - loadAndCheckTestMp3WithTags(MP3_WITH_ID3V1_AND_ID3V23_TAGS, 5000); - loadAndCheckTestMp3WithTags(new File(MP3_WITH_ID3V1_AND_ID3V23_TAGS), 41); - loadAndCheckTestMp3WithTags(new File(MP3_WITH_ID3V1_AND_ID3V23_TAGS), 256); - loadAndCheckTestMp3WithTags(new File(MP3_WITH_ID3V1_AND_ID3V23_TAGS), 1024); - loadAndCheckTestMp3WithTags(new File(MP3_WITH_ID3V1_AND_ID3V23_TAGS), 5000); - } - - @Test - public void shouldLoadMp3WithFakeStartAndEndFrames() throws IOException, UnsupportedTagException, InvalidDataException { - loadAndCheckTestMp3WithTags(MP3_WITH_DUMMY_START_AND_END_FRAMES, 41); - loadAndCheckTestMp3WithTags(MP3_WITH_DUMMY_START_AND_END_FRAMES, 256); - loadAndCheckTestMp3WithTags(MP3_WITH_DUMMY_START_AND_END_FRAMES, 1024); - loadAndCheckTestMp3WithTags(MP3_WITH_DUMMY_START_AND_END_FRAMES, 5000); - loadAndCheckTestMp3WithTags(new File(MP3_WITH_DUMMY_START_AND_END_FRAMES), 41); - loadAndCheckTestMp3WithTags(new File(MP3_WITH_DUMMY_START_AND_END_FRAMES), 256); - loadAndCheckTestMp3WithTags(new File(MP3_WITH_DUMMY_START_AND_END_FRAMES), 1024); - loadAndCheckTestMp3WithTags(new File(MP3_WITH_DUMMY_START_AND_END_FRAMES), 5000); - } - - @Test - public void shouldLoadMp3WithCustomTag() throws IOException, UnsupportedTagException, InvalidDataException { - loadAndCheckTestMp3WithCustomTag(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS, 41); - loadAndCheckTestMp3WithCustomTag(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS, 256); - loadAndCheckTestMp3WithCustomTag(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS, 1024); - loadAndCheckTestMp3WithCustomTag(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS, 5000); - loadAndCheckTestMp3WithCustomTag(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS), 41); - loadAndCheckTestMp3WithCustomTag(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS), 256); - loadAndCheckTestMp3WithCustomTag(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS), 1024); - loadAndCheckTestMp3WithCustomTag(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS), 5000); - } - - @Test - public void shouldThrowExceptionForFileThatIsNotAnMp3() throws Exception { - try { - new Mp3File(NOT_AN_MP3); - fail("InvalidDataException expected but not thrown"); - } catch (InvalidDataException e) { - assertEquals("No mpegs frames found", e.getMessage()); - } - } - - @Test - public void shouldThrowExceptionForFileThatIsNotAnMp3ForFileConstructor() throws Exception { - try { - new Mp3File(new File(NOT_AN_MP3)); - fail("InvalidDataException expected but not thrown"); - } catch (InvalidDataException e) { - assertEquals("No mpegs frames found", e.getMessage()); - } - } - - @Test - public void shouldFindProbableStartOfMpegFramesWithPrescan() throws IOException { - Mp3FileForTesting mp3File = new Mp3FileForTesting(MP3_WITH_ID3V1_AND_ID3V23_TAGS); - testShouldFindProbableStartOfMpegFramesWithPrescan(mp3File); - } - - @Test - public void shouldFindProbableStartOfMpegFramesWithPrescanForFileConstructor() throws IOException { - Mp3FileForTesting mp3File = new Mp3FileForTesting(new File(MP3_WITH_ID3V1_AND_ID3V23_TAGS)); - testShouldFindProbableStartOfMpegFramesWithPrescan(mp3File); - } - - private void testShouldFindProbableStartOfMpegFramesWithPrescan(Mp3FileForTesting mp3File) { - assertEquals(0x44B, mp3File.preScanResult); - } - - @Test - public void shouldThrowExceptionIfSavingMp3WithSameNameAsSourceFile() throws Exception { - Mp3File mp3File = new Mp3File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS); - testShouldThrowExceptionIfSavingMp3WithSameNameAsSourceFile(mp3File); - } - - @Test - public void shouldThrowExceptionIfSavingMp3WithSameNameAsSourceFileForFileConstructor() throws Exception { - Mp3File mp3File = new Mp3File(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS)); - testShouldThrowExceptionIfSavingMp3WithSameNameAsSourceFile(mp3File); - } - - private void testShouldThrowExceptionIfSavingMp3WithSameNameAsSourceFile(Mp3File mp3File) throws NotSupportedException, IOException { - System.out.println(mp3File.getFilename()); - System.out.println(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS); - try { - mp3File.save(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS); - fail("IllegalArgumentException expected but not thrown"); - } catch (IllegalArgumentException e) { - assertEquals("Save filename same as source filename", e.getMessage()); - } - } - - @Test - public void shouldSaveLoadedMp3WhichIsEquivalentToOriginal() throws Exception { - copyAndCheckTestMp3WithCustomTag(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS, 41); - copyAndCheckTestMp3WithCustomTag(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS, 256); - copyAndCheckTestMp3WithCustomTag(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS, 1024); - copyAndCheckTestMp3WithCustomTag(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS, 5000); - copyAndCheckTestMp3WithCustomTag(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS), 41); - copyAndCheckTestMp3WithCustomTag(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS), 256); - copyAndCheckTestMp3WithCustomTag(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS), 1024); - copyAndCheckTestMp3WithCustomTag(new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS), 5000); - } - - @Test - public void shouldLoadAndCheckMp3ContainingUnicodeFields() throws Exception { - loadAndCheckTestMp3WithUnicodeFields(MP3_WITH_ID3V23_UNICODE_TAGS, 41); - loadAndCheckTestMp3WithUnicodeFields(MP3_WITH_ID3V23_UNICODE_TAGS, 256); - loadAndCheckTestMp3WithUnicodeFields(MP3_WITH_ID3V23_UNICODE_TAGS, 1024); - loadAndCheckTestMp3WithUnicodeFields(MP3_WITH_ID3V23_UNICODE_TAGS, 5000); - loadAndCheckTestMp3WithUnicodeFields(new File(MP3_WITH_ID3V23_UNICODE_TAGS), 41); - loadAndCheckTestMp3WithUnicodeFields(new File(MP3_WITH_ID3V23_UNICODE_TAGS), 256); - loadAndCheckTestMp3WithUnicodeFields(new File(MP3_WITH_ID3V23_UNICODE_TAGS), 1024); - loadAndCheckTestMp3WithUnicodeFields(new File(MP3_WITH_ID3V23_UNICODE_TAGS), 5000); - } - - @Test - public void shouldSaveLoadedMp3WithUnicodeFieldsWhichIsEquivalentToOriginal() throws Exception { - copyAndCheckTestMp3WithUnicodeFields(MP3_WITH_ID3V23_UNICODE_TAGS, 41); - copyAndCheckTestMp3WithUnicodeFields(MP3_WITH_ID3V23_UNICODE_TAGS, 256); - copyAndCheckTestMp3WithUnicodeFields(MP3_WITH_ID3V23_UNICODE_TAGS, 1024); - copyAndCheckTestMp3WithUnicodeFields(MP3_WITH_ID3V23_UNICODE_TAGS, 5000); - copyAndCheckTestMp3WithUnicodeFields(new File(MP3_WITH_ID3V23_UNICODE_TAGS), 41); - copyAndCheckTestMp3WithUnicodeFields(new File(MP3_WITH_ID3V23_UNICODE_TAGS), 256); - copyAndCheckTestMp3WithUnicodeFields(new File(MP3_WITH_ID3V23_UNICODE_TAGS), 1024); - copyAndCheckTestMp3WithUnicodeFields(new File(MP3_WITH_ID3V23_UNICODE_TAGS), 5000); - } - - @Test - public void shouldIgnoreIncompleteMpegFrame() throws Exception { - Mp3File mp3File = new Mp3File(MP3_WITH_INCOMPLETE_MPEG_FRAME, 256); - testShouldIgnoreIncompleteMpegFrame(mp3File); - } - - @Test - public void shouldIgnoreIncompleteMpegFrameForFileConstructor() throws Exception { - Mp3File mp3File = new Mp3File(new File(MP3_WITH_INCOMPLETE_MPEG_FRAME), 256); - testShouldIgnoreIncompleteMpegFrame(mp3File); - } - - private void testShouldIgnoreIncompleteMpegFrame(Mp3File mp3File) { - assertEquals(0x44B, mp3File.getXingOffset()); - assertEquals(0x5EC, mp3File.getStartOffset()); - assertEquals(0xF17, mp3File.getEndOffset()); - assertTrue(mp3File.hasId3v1Tag()); - assertTrue(mp3File.hasId3v2Tag()); - assertEquals(5, mp3File.getFrameCount()); - } - - @Test - public void shouldInitialiseProperlyWhenNotScanningFile() throws Exception { - Mp3File mp3File = new Mp3File(MP3_WITH_INCOMPLETE_MPEG_FRAME, 256, false); - testShouldInitialiseProperlyWhenNotScanningFile(mp3File); - } - - @Test - public void shouldInitialiseProperlyWhenNotScanningFileForFileConstructor() throws Exception { - Mp3File mp3File = new Mp3File(new File(MP3_WITH_INCOMPLETE_MPEG_FRAME), 256, false); - testShouldInitialiseProperlyWhenNotScanningFile(mp3File); - } - - private void testShouldInitialiseProperlyWhenNotScanningFile(Mp3File mp3File) { - assertTrue(mp3File.hasId3v1Tag()); - assertTrue(mp3File.hasId3v2Tag()); - } - - @Test - public void shouldRemoveId3v1Tag() throws Exception { - String filename = MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS; - testShouldRemoveId3v1Tag(new Mp3File(filename)); - } - - @Test - public void shouldRemoveId3v1TagForFileConstructor() throws Exception { - File filename = new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS); - testShouldRemoveId3v1Tag(new Mp3File(filename)); - } - - private void testShouldRemoveId3v1Tag(Mp3File mp3File) throws Exception { - String saveFilename = mp3File.getFilename() + ".copy"; - try { - mp3File.removeId3v1Tag(); - mp3File.save(saveFilename); - Mp3File newMp3File = new Mp3File(saveFilename); - assertFalse(newMp3File.hasId3v1Tag()); - assertTrue(newMp3File.hasId3v2Tag()); - assertTrue(newMp3File.hasCustomTag()); - } finally { - TestHelper.deleteFile(saveFilename); - } - } - - @Test - public void shouldRemoveId3v2Tag() throws Exception { - String filename = MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS; - testShouldRemoveId3v2Tag(new Mp3File(filename)); - } - - @Test - public void shouldRemoveId3v2TagForFileConstructor() throws Exception { - File filename = new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS); - testShouldRemoveId3v2Tag(new Mp3File(filename)); - } - - private void testShouldRemoveId3v2Tag(Mp3File mp3File) throws Exception { - String saveFilename = mp3File.getFilename() + ".copy"; - try { - mp3File.removeId3v2Tag(); - mp3File.save(saveFilename); - Mp3File newMp3File = new Mp3File(saveFilename); - assertTrue(newMp3File.hasId3v1Tag()); - assertFalse(newMp3File.hasId3v2Tag()); - assertTrue(newMp3File.hasCustomTag()); - } finally { - TestHelper.deleteFile(saveFilename); - } - } - - @Test - public void shouldRemoveCustomTag() throws Exception { - String filename = MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS; - testShouldRemoveCustomTag(new Mp3File(filename)); - } - - @Test - public void shouldRemoveCustomTagForFileConstructor() throws Exception { - File filename = new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS); - testShouldRemoveCustomTag(new Mp3File(filename)); - } - - private void testShouldRemoveCustomTag(Mp3File mp3File) throws Exception { - String saveFilename = mp3File.getFilename() + ".copy"; - try { - mp3File.removeCustomTag(); - mp3File.save(saveFilename); - Mp3File newMp3File = new Mp3File(saveFilename); - assertTrue(newMp3File.hasId3v1Tag()); - assertTrue(newMp3File.hasId3v2Tag()); - assertFalse(newMp3File.hasCustomTag()); - } finally { - TestHelper.deleteFile(saveFilename); - } - } - - @Test - public void shouldRemoveId3v1AndId3v2AndCustomTags() throws Exception { - String filename = MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS; - testShouldRemoveId3v1AndId3v2AndCustomTags(new Mp3File(filename)); - } - - @Test - public void shouldRemoveId3v1AndId3v2AndCustomTagsForFileConstructor() throws Exception { - File filename = new File(MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS); - testShouldRemoveId3v1AndId3v2AndCustomTags(new Mp3File(filename)); - } - - private void testShouldRemoveId3v1AndId3v2AndCustomTags(Mp3File mp3File) throws Exception { - String saveFilename = mp3File.getFilename() + ".copy"; - try { - mp3File.removeId3v1Tag(); - mp3File.removeId3v2Tag(); - mp3File.removeCustomTag(); - mp3File.save(saveFilename); - Mp3File newMp3File = new Mp3File(saveFilename); - assertFalse(newMp3File.hasId3v1Tag()); - assertFalse(newMp3File.hasId3v2Tag()); - assertFalse(newMp3File.hasCustomTag()); - } finally { - TestHelper.deleteFile(saveFilename); - } - } - - private Mp3File copyAndCheckTestMp3WithCustomTag(String filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException, NotSupportedException { - Mp3File mp3File = loadAndCheckTestMp3WithCustomTag(filename, bufferLength); - return copyAndCheckTestMp3WithCustomTag(mp3File); - } - - private Mp3File copyAndCheckTestMp3WithCustomTag(File filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException, NotSupportedException { - Mp3File mp3File = loadAndCheckTestMp3WithCustomTag(filename, bufferLength); - return copyAndCheckTestMp3WithCustomTag(mp3File); - } - - private Mp3File copyAndCheckTestMp3WithCustomTag(Mp3File mp3File) throws NotSupportedException, IOException, UnsupportedTagException, InvalidDataException { - String saveFilename = mp3File.getFilename() + ".copy"; - try { - mp3File.save(saveFilename); - Mp3File copyMp3file = loadAndCheckTestMp3WithCustomTag(saveFilename, 5000); - assertEquals(mp3File.getId3v1Tag(), copyMp3file.getId3v1Tag()); - assertEquals(mp3File.getId3v2Tag(), copyMp3file.getId3v2Tag()); - assertArrayEquals(mp3File.getCustomTag(), copyMp3file.getCustomTag()); - return copyMp3file; - } finally { - TestHelper.deleteFile(saveFilename); - } - } - - private Mp3File copyAndCheckTestMp3WithUnicodeFields(String filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException, NotSupportedException { - Mp3File mp3File = loadAndCheckTestMp3WithUnicodeFields(filename, bufferLength); - return copyAndCheckTestMp3WithUnicodeFields(mp3File); - } - - private Mp3File copyAndCheckTestMp3WithUnicodeFields(File filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException, NotSupportedException { - Mp3File mp3File = loadAndCheckTestMp3WithUnicodeFields(filename, bufferLength); - return copyAndCheckTestMp3WithUnicodeFields(mp3File); - } - - private Mp3File copyAndCheckTestMp3WithUnicodeFields(Mp3File mp3File) throws NotSupportedException, IOException, UnsupportedTagException, InvalidDataException { - String saveFilename = mp3File.getFilename() + ".copy"; - try { - mp3File.save(saveFilename); - Mp3File copyMp3file = loadAndCheckTestMp3WithUnicodeFields(saveFilename, 5000); - assertEquals(mp3File.getId3v2Tag(), copyMp3file.getId3v2Tag()); - return copyMp3file; - } finally { - TestHelper.deleteFile(saveFilename); - } - } - - private Mp3File loadAndCheckTestMp3WithNoTags(String filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = loadAndCheckTestMp3(filename, bufferLength); - return loadAndCheckTestMp3WithNoTags(mp3File); - } - - private Mp3File loadAndCheckTestMp3WithNoTags(File filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = loadAndCheckTestMp3(filename, bufferLength); - return loadAndCheckTestMp3WithNoTags(mp3File); - } - - private Mp3File loadAndCheckTestMp3WithNoTags(Mp3File mp3File) { - assertEquals(0x000, mp3File.getXingOffset()); - assertEquals(0x1A1, mp3File.getStartOffset()); - assertEquals(0xB34, mp3File.getEndOffset()); - assertFalse(mp3File.hasId3v1Tag()); - assertFalse(mp3File.hasId3v2Tag()); - assertFalse(mp3File.hasCustomTag()); - return mp3File; - } - - private Mp3File loadAndCheckTestMp3WithTags(String filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = loadAndCheckTestMp3(filename, bufferLength); - return loadAndCheckTestMp3WithTags(mp3File); - } - - private Mp3File loadAndCheckTestMp3WithTags(File filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = loadAndCheckTestMp3(filename, bufferLength); - return loadAndCheckTestMp3WithTags(mp3File); - } - - private Mp3File loadAndCheckTestMp3WithTags(Mp3File mp3File) { - assertEquals(0x44B, mp3File.getXingOffset()); - assertEquals(0x5EC, mp3File.getStartOffset()); - assertEquals(0xF7F, mp3File.getEndOffset()); - assertTrue(mp3File.hasId3v1Tag()); - assertTrue(mp3File.hasId3v2Tag()); - assertFalse(mp3File.hasCustomTag()); - return mp3File; - } - - private Mp3File loadAndCheckTestMp3WithUnicodeFields(String filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = loadAndCheckTestMp3(filename, bufferLength); - return loadAndCheckTestMp3WithUnicodeFields(mp3File); - } - - private Mp3File loadAndCheckTestMp3WithUnicodeFields(File filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = loadAndCheckTestMp3(filename, bufferLength); - return loadAndCheckTestMp3WithUnicodeFields(mp3File); - } - - private Mp3File loadAndCheckTestMp3WithUnicodeFields(Mp3File mp3File) { - assertEquals(0x0CA, mp3File.getXingOffset()); - assertEquals(0x26B, mp3File.getStartOffset()); - assertEquals(0xBFE, mp3File.getEndOffset()); - assertFalse(mp3File.hasId3v1Tag()); - assertTrue(mp3File.hasId3v2Tag()); - assertFalse(mp3File.hasCustomTag()); - return mp3File; - } - - private Mp3File loadAndCheckTestMp3WithCustomTag(String filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = loadAndCheckTestMp3(filename, bufferLength); - return loadAndCheckTestMp3WithCustomTag(mp3File); - } - - private Mp3File loadAndCheckTestMp3WithCustomTag(File filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = loadAndCheckTestMp3(filename, bufferLength); - return loadAndCheckTestMp3WithCustomTag(mp3File); - } - - private Mp3File loadAndCheckTestMp3WithCustomTag(Mp3File mp3File) { - assertEquals(0x44B, mp3File.getXingOffset()); - assertEquals(0x5EC, mp3File.getStartOffset()); - assertEquals(0xF7F, mp3File.getEndOffset()); - assertTrue(mp3File.hasId3v1Tag()); - assertTrue(mp3File.hasId3v2Tag()); - assertTrue(mp3File.hasCustomTag()); - return mp3File; - } - - private Mp3File loadAndCheckTestMp3(String filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = new Mp3File(filename, bufferLength); - return loadAndCheckTestMp3(mp3File); - } - - private Mp3File loadAndCheckTestMp3(File filename, int bufferLength) throws IOException, UnsupportedTagException, InvalidDataException { - Mp3File mp3File = new Mp3File(filename, bufferLength); - return loadAndCheckTestMp3(mp3File); - } - - private Mp3File loadAndCheckTestMp3(Mp3File mp3File) { - assertTrue(mp3File.hasXingFrame()); - assertEquals(6, mp3File.getFrameCount()); - assertEquals(MpegFrame.MPEG_VERSION_1_0, mp3File.getVersion()); - assertEquals(MpegFrame.MPEG_LAYER_3, mp3File.getLayer()); - assertEquals(44100, mp3File.getSampleRate()); - assertEquals(MpegFrame.CHANNEL_MODE_JOINT_STEREO, mp3File.getChannelMode()); - assertEquals(MpegFrame.EMPHASIS_NONE, mp3File.getEmphasis()); - assertTrue(mp3File.isOriginal()); - assertFalse(mp3File.isCopyright()); - assertEquals(128, mp3File.getXingBitrate()); - assertEquals(125, mp3File.getBitrate()); - assertEquals(1, (mp3File.getBitrates().get(224)).getValue()); - assertEquals(1, (mp3File.getBitrates().get(112)).getValue()); - assertEquals(2, (mp3File.getBitrates().get(96)).getValue()); - assertEquals(1, (mp3File.getBitrates().get(192)).getValue()); - assertEquals(1, (mp3File.getBitrates().get(32)).getValue()); - assertEquals(156, mp3File.getLengthInMilliseconds()); - return mp3File; - } - - private static class Mp3FileForTesting extends Mp3File { - - int preScanResult; - - public Mp3FileForTesting(String filename) throws IOException { - SeekableByteChannel file = Files.newByteChannel(Paths.get(filename), StandardOpenOption.READ); - preScanResult = preScanFile(file); - } - - public Mp3FileForTesting(File filename) throws IOException { - SeekableByteChannel file = Files.newByteChannel(filename.toPath(), StandardOpenOption.READ); - preScanResult = preScanFile(file); - } - } -} diff --git a/src/test/java/com/mpatric/mp3agic/MpegFrameTest.java b/src/test/java/com/mpatric/mp3agic/MpegFrameTest.java deleted file mode 100644 index 5f24d6f..0000000 --- a/src/test/java/com/mpatric/mp3agic/MpegFrameTest.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -public class MpegFrameTest { - - private static final byte BYTE_FF = -0x01; - private static final byte BYTE_FB = -0x05; - private static final byte BYTE_F9 = -0x07; - private static final byte BYTE_F3 = -0x0D; - private static final byte BYTE_F2 = -0x0E; - private static final byte BYTE_A2 = -0x5E; - private static final byte BYTE_AE = -0x52; - private static final byte BYTE_DB = -0x25; - private static final byte BYTE_EB = -0x15; - private static final byte BYTE_40 = 0x40; - private static final byte BYTE_02 = 0x02; - - @Test - public void testBitwiseLeftShiftOperationsOnLong() { - long original = 0xFFFFFFFE; // 1111 1111 1111 1111 1111 1111 1111 1110 - long expectedShl1 = 0xFFFFFFFC; // 1111 1111 1111 1111 1111 1111 1111 1100 - long expectedShl28 = 0xE0000000; // 1110 0000 0000 0000 0000 0000 0000 0000 - long expectedShl30 = 0x80000000; // 1000 0000 0000 0000 0000 0000 0000 0000 - assertEquals(expectedShl1, original << 1); - assertEquals(expectedShl28, original << 28); - assertEquals(expectedShl30, original << 30); - } - - @Test - public void testBitwiseRightShiftOperationsOnLong() { - long original = 0x80000000; // 1000 0000 0000 0000 0000 0000 0000 0000 - long expectedShr1 = 0xC0000000; // 1100 0000 0000 0000 0000 0000 0000 0000 - long expectedShr28 = 0xFFFFFFF8; // 1111 1111 1111 1111 1111 1111 1111 1000 - long expectedShr30 = 0xFFFFFFFE; // 1111 1111 1111 1111 1111 1111 1111 1110 - assertEquals(expectedShr1, original >> 1); - assertEquals(expectedShr28, original >> 28); - assertEquals(expectedShr30, original >> 30); - } - - @Test - public void testShiftingByteIntoBiggerNumber() { - byte original = -0x02; // 1111 1110 - long originalAsLong = (original & 0xFF); - byte expectedShl1 = -0x04; // 1111 1100 - long expectedShl8 = 0x0000FE00; // 0000 0000 0000 0000 1111 1110 0000 0000 - long expectedShl16 = 0x00FE0000; // 0000 0000 1111 1110 0000 0000 0000 0000 - long expectedShl23 = 0x7F000000; // 0111 1111 00000 0000 0000 0000 0000 0000 - assertEquals(expectedShl1, original << 1); - assertEquals(254, originalAsLong); - assertEquals(expectedShl8, originalAsLong << 8); - assertEquals(expectedShl16, originalAsLong << 16); - assertEquals(expectedShl23, originalAsLong << 23); - } - - @Test - public void shouldExtractValidFields() { - MpegFrameForTesting mpegFrame = new MpegFrameForTesting(); - assertEquals(0x000007FF, mpegFrame.extractField(0xFFE00000, 0xFFE00000L)); - assertEquals(0x000007FF, mpegFrame.extractField(0xFFEFFFFF, 0xFFE00000L)); - assertEquals(0x00000055, mpegFrame.extractField(0x11111155, 0x000000FFL)); - assertEquals(0x00000055, mpegFrame.extractField(0xFFEFFF55, 0x000000FFL)); - } - - @Test - public void shouldExtractValidMpegVersion1Header() throws InvalidDataException { - byte[] frameData = {BYTE_FF, BYTE_FB, BYTE_A2, BYTE_40}; - MpegFrameForTesting mpegFrame = new MpegFrameForTesting(frameData); - assertEquals(MpegFrame.MPEG_VERSION_1_0, mpegFrame.getVersion()); - assertEquals(MpegFrame.MPEG_LAYER_3, mpegFrame.getLayer()); - assertEquals(160, mpegFrame.getBitrate()); - assertEquals(44100, mpegFrame.getSampleRate()); - assertEquals(MpegFrame.CHANNEL_MODE_JOINT_STEREO, mpegFrame.getChannelMode()); - assertEquals("None", mpegFrame.getModeExtension()); - assertEquals("None", mpegFrame.getEmphasis()); - assertEquals(true, mpegFrame.isProtection()); - assertEquals(true, mpegFrame.hasPadding()); - assertEquals(false, mpegFrame.isPrivate()); - assertEquals(false, mpegFrame.isCopyright()); - assertEquals(false, mpegFrame.isOriginal()); - assertEquals(523, mpegFrame.getLengthInBytes()); - } - - @Test - public void shouldProcessValidMpegVersion2Header() throws InvalidDataException { - byte[] frameData = {BYTE_FF, BYTE_F3, BYTE_A2, BYTE_40}; - MpegFrameForTesting mpegFrame = new MpegFrameForTesting(frameData); - assertEquals(MpegFrame.MPEG_VERSION_2_0, mpegFrame.getVersion()); - assertEquals(MpegFrame.MPEG_LAYER_3, mpegFrame.getLayer()); - assertEquals(96, mpegFrame.getBitrate()); - assertEquals(22050, mpegFrame.getSampleRate()); - assertEquals(MpegFrame.CHANNEL_MODE_JOINT_STEREO, mpegFrame.getChannelMode()); - assertEquals("None", mpegFrame.getModeExtension()); - assertEquals("None", mpegFrame.getEmphasis()); - assertEquals(true, mpegFrame.isProtection()); - assertEquals(true, mpegFrame.hasPadding()); - assertEquals(false, mpegFrame.isPrivate()); - assertEquals(false, mpegFrame.isCopyright()); - assertEquals(false, mpegFrame.isOriginal()); - assertEquals(627, mpegFrame.getLengthInBytes()); - } - - @Test - public void shouldThrowExceptionForInvalidFrameSync() { - byte[] frameData = {BYTE_FF, BYTE_DB, BYTE_A2, BYTE_40}; - try { - new MpegFrameForTesting(frameData); - fail("InvalidDataException expected but not thrown"); - } catch (InvalidDataException e) { - assertEquals("Frame sync missing", e.getMessage()); - } - } - - @Test - public void shouldThrowExceptionForInvalidMpegVersion() { - byte[] frameData = {BYTE_FF, BYTE_EB, BYTE_A2, BYTE_40}; - try { - new MpegFrameForTesting(frameData); - fail("InvalidDataException expected but not thrown"); - } catch (InvalidDataException e) { - assertEquals("Invalid mpeg audio version in frame header", e.getMessage()); - } - } - - @Test - public void shouldThrowExceptionForInvalidMpegLayer() { - byte[] frameData = {BYTE_FF, BYTE_F9, BYTE_A2, BYTE_40}; - try { - new MpegFrameForTesting(frameData); - fail("InvalidDataException expected but not thrown"); - } catch (InvalidDataException e) { - assertEquals("Invalid mpeg layer description in frame header", e.getMessage()); - } - } - - @Test - public void shouldThrowExceptionForFreeBitrate() { - byte[] frameData = {BYTE_FF, BYTE_FB, BYTE_02, BYTE_40}; - try { - new MpegFrameForTesting(frameData); - fail("InvalidDataException expected but not thrown"); - } catch (InvalidDataException e) { - assertEquals("Invalid bitrate in frame header", e.getMessage()); - } - } - - @Test - public void shouldThrowExceptionForInvalidBitrate() { - byte[] frameData = {BYTE_FF, BYTE_FB, BYTE_F2, BYTE_40}; - try { - new MpegFrameForTesting(frameData); - fail("InvalidDataException expected but not thrown"); - } catch (InvalidDataException e) { - assertEquals("Invalid bitrate in frame header", e.getMessage()); - } - } - - @Test - public void shouldThrowExceptionForInvalidSampleRate() { - byte[] frameData = {BYTE_FF, BYTE_FB, BYTE_AE, BYTE_40}; - try { - new MpegFrameForTesting(frameData); - fail("InvalidDataException expected but not thrown"); - } catch (InvalidDataException e) { - assertEquals("Invalid sample rate in frame header", e.getMessage()); - } - } - - static class MpegFrameForTesting extends MpegFrame { - - public MpegFrameForTesting() { - super(); - } - - public MpegFrameForTesting(byte[] frameData) throws InvalidDataException { - super(frameData); - } - - } -} diff --git a/src/test/java/com/mpatric/mp3agic/MutableIntegerTest.java b/src/test/java/com/mpatric/mp3agic/MutableIntegerTest.java deleted file mode 100644 index 46679d3..0000000 --- a/src/test/java/com/mpatric/mp3agic/MutableIntegerTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; - -public class MutableIntegerTest { - @Test - public void initializesValue() { - MutableInteger integer = new MutableInteger(8); - assertEquals(8, integer.getValue()); - } - - @Test - public void incrementsValue() { - MutableInteger integer = new MutableInteger(8); - integer.increment(); - assertEquals(9, integer.getValue()); - } - - @Test - public void setsValue() { - MutableInteger integer = new MutableInteger(8); - integer.setValue(5); - assertEquals(5, integer.getValue()); - } - - @Test - public void equalsItself() { - MutableInteger integer = new MutableInteger(8); - assertEquals(integer, integer); - } - - @Test - public void equalIfValueEqual() { - MutableInteger eight = new MutableInteger(8); - MutableInteger eightAgain = new MutableInteger(8); - assertEquals(eight, eightAgain); - } - - @Test - public void notEqualToNull() { - MutableInteger integer = new MutableInteger(8); - assertFalse(integer.equals(null)); - } - - @Test - public void notEqualToDifferentClass() { - MutableInteger integer = new MutableInteger(8); - assertFalse(integer.equals("8")); - } - - @Test - public void notEqualIfValueNotEqual() { - MutableInteger eight = new MutableInteger(8); - MutableInteger nine = new MutableInteger(9); - assertNotEquals(eight, nine); - } - - @Test - public void hashCodeIsConsistent() { - MutableInteger integer = new MutableInteger(8); - assertEquals(integer.hashCode(), integer.hashCode()); - } - - @Test - public void equalObjectsHaveSameHashCode() { - MutableInteger eight = new MutableInteger(8); - MutableInteger eightAgain = new MutableInteger(8); - assertEquals(eight.hashCode(), eightAgain.hashCode()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/NotSupportedExceptionTest.java b/src/test/java/com/mpatric/mp3agic/NotSupportedExceptionTest.java deleted file mode 100644 index ab067ed..0000000 --- a/src/test/java/com/mpatric/mp3agic/NotSupportedExceptionTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -public class NotSupportedExceptionTest { - @Test - public void defaultConstructor() { - NotSupportedException exception = new NotSupportedException(); - assertNull(exception.getMessage()); - assertNull(exception.getCause()); - } - - @Test - public void constructorWithMessage() { - NotSupportedException exception = new NotSupportedException("A message"); - assertEquals("A message", exception.getMessage()); - assertNull(exception.getCause()); - } - - @Test - public void constructorWithMessageAndCause() { - Throwable exceptionCause = new IllegalArgumentException("Bad argument"); - NotSupportedException exception = new NotSupportedException("A message", exceptionCause); - assertEquals("A message", exception.getMessage()); - assertEquals(exceptionCause, exception.getCause()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/TestHelper.java b/src/test/java/com/mpatric/mp3agic/TestHelper.java deleted file mode 100644 index c6ca0d7..0000000 --- a/src/test/java/com/mpatric/mp3agic/TestHelper.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.mpatric.mp3agic; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.Test; - -public class TestHelper { - public static String bytesToHexString(byte[] bytes) { - StringBuilder hexString = new StringBuilder(); - for (int i = 0; i < bytes.length; i++) { - if (i > 0) hexString.append(' '); - String hex = Integer.toHexString(0xff & bytes[i]); - if (hex.length() == 1) hexString.append('0'); - hexString.append(hex); - } - return hexString.toString(); - } - - public static byte[] hexStringToBytes(String hex) { - int len = hex.length(); - byte[] bytes = new byte[(len + 1) / 3]; - for (int i = 0; i < len; i += 3) { - bytes[i / 3] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16)); - } - return bytes; - } - - public static byte[] loadFile(String filename) throws IOException { - try (RandomAccessFile file = new RandomAccessFile(filename, "r")) { - byte[] buffer = new byte[(int) file.length()]; - file.read(buffer); - return buffer; - } - } - - public static void deleteFile(String filename) throws IOException { - Path file = Paths.get(filename); - Files.delete(file); - } - - public static void replaceSpacesWithNulls(byte[] buffer) { - for (int i = 0; i < buffer.length; i++) { - if (buffer[i] == 0x20) { - buffer[i] = 0x00; - } - } - } - - public static void replaceNumbersWithBytes(byte[] bytes, int offset) { - for (int i = offset; i < bytes.length; i++) { - if (bytes[i] >= '0' && bytes[i] <= '9') { - bytes[i] -= (byte) 48; - } - } - } - - // self tests - @Test - public void shouldConvertBytesToHexAndBack() { - byte[] bytes = {(byte) 0x48, (byte) 0x45, (byte) 0x4C, (byte) 0x4C, (byte) 0x4F, (byte) 0x20, (byte) 0x74, (byte) 0x68, (byte) 0x65, (byte) 0x72, (byte) 0x65, (byte) 0x21}; - String hexString = TestHelper.bytesToHexString(bytes); - assertEquals("48 45 4c 4c 4f 20 74 68 65 72 65 21", hexString); - assertArrayEquals(bytes, TestHelper.hexStringToBytes(hexString)); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/UnsupportedTagExceptionTest.java b/src/test/java/com/mpatric/mp3agic/UnsupportedTagExceptionTest.java deleted file mode 100644 index 2306ef1..0000000 --- a/src/test/java/com/mpatric/mp3agic/UnsupportedTagExceptionTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -public class UnsupportedTagExceptionTest { - - @Test - public void defaultConstructor() { - UnsupportedTagException exception = new UnsupportedTagException(); - assertNull(exception.getMessage()); - assertNull(exception.getCause()); - } - - @Test - public void constructorWithMessage() { - UnsupportedTagException exception = new UnsupportedTagException("A message"); - assertEquals("A message", exception.getMessage()); - assertNull(exception.getCause()); - } - - @Test - public void constructorWithMessageAndCause() { - Throwable exceptionCause = new IllegalArgumentException("Bad argument"); - UnsupportedTagException exception = new UnsupportedTagException("A message", exceptionCause); - assertEquals("A message", exception.getMessage()); - assertEquals(exceptionCause, exception.getCause()); - } -} diff --git a/src/test/java/com/mpatric/mp3agic/VersionTest.java b/src/test/java/com/mpatric/mp3agic/VersionTest.java deleted file mode 100644 index ec5cb10..0000000 --- a/src/test/java/com/mpatric/mp3agic/VersionTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.mpatric.mp3agic; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class VersionTest { - @Test - public void returnsVersion() { - assertEquals("UNKNOWN-SNAPSHOT", Version.getVersion()); - } - - @Test - public void returnsUrl() { - assertEquals("http://github.com/mpatric/mp3agic", Version.getUrl()); - } - - @Test - public void returnsVersionAndUrlAsString() { - assertEquals("UNKNOWN-SNAPSHOT - http://github.com/mpatric/mp3agic", Version.asString()); - } -} diff --git a/src/test/resources/dummyframes.mp3 b/src/test/resources/dummyframes.mp3 deleted file mode 100644 index 53c803bffe21526fcbcc8f3e0f02d2c0ede6c483..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 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 diff --git a/src/test/resources/incompletempegframe.mp3 b/src/test/resources/incompletempegframe.mp3 deleted file mode 100644 index 1fb47e013e3e8016b5ef725441c3257b9206348b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4095 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 diff --git a/src/test/resources/notags.mp3 b/src/test/resources/notags.mp3 deleted file mode 100644 index 45a28d939f62d9e914e85f5167a5eab9da77d6f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2869 zcmds3Yfw{18{TsgVgiQ{!Y$D#Nk9x3FyW4%CS0u22%*x7N;PPLfQ$sGMbXO11sX0& z0$KvJB_Op(r+$dk0;Lifs?q|YSj9@q&1&gTi$H6I!1;om{_#)yyU*k|}iTkDm* zLGstxQKKZ7Vd>hj%}gPZSqKuV+tQMCknHp^2fCsMd#6dBd?RFI zh+6zUc6FHfF!7?0SX1M|eq`BO7tTqE`u5R7aZ5^U`I45PH8%Nq)6ZMwEh&4~Rh8RR zFAZYYqrb)!C$3h=TP*E|rliKf^gtRyfKe3Cydqd<8%q>Pn!b7ld=9`&0k1(%vHcSd zdOQ^S=yngjLD4zw7GOVz3k z)sO7dsF73uJ&5PcC)NtG{}DYUi1E~b?wL&xnx9ILhEF$tB0FXS@5ed-#B7 ztaB-*bV^cOi>-y&JSwH08sILEcFi%uQBZ5dlSyEm63WTQHVH=ZWw!rI2l7rc3z-$@ zO~JG-l%-LjW@8u8O29xM72xNn(dqj_oWmFgaaBrqF?hU47-tpL6YH9Gd-&jF!}Ixy z-bDb2g6(AGOu(@$IpH#*%Cb>7M_gun55)dYu)M9(Si1Wt@jl-id)wMv7ygZ*RG)SB=MY!Mh72C;1 zN3qW_h0#+3rbF~r;A!4YYL!(Xq`E=X+W_dT?@W8M-5ejUIQ+{-lXmK0u2Ie6I>7ih zd3npkjfacA&<-^nIZKZkkGcGYGuQE+xU2IwyA4QN%w*b`KQas(M?**3HKc1=Yy^N_ z&i*$NM80>tda8{@qMPo>7P82}UWqasE7*$8dreRC!QsaT1cp1zUwP?xo=C)dwFsM+ zOBuGeQSvt{s(%LSp$icQ+5xFQ)GOneN$?Xvdg{YTz!whk#6oMujck zmnG+2RH;y--6)fV z-mswwY(3BMc(edOlRLP*8mPW`Zy+^o;F$S97Hh!_#v^w5|J=1H5ng_Zvs`fSH3hqb z-x=yi5)MqB(b(UO8QB(c_p;jwC`ioki+E1~q)BXV@JYkctpVaS3OiZ0(DAW!{KuS< z{L^VtRlb)sfg;eMNzj=lD37^Me+f0x@GI+$#ddsqkI>e2Jj2q(tvq#mKRLSU!Ow<} zqzbDkvgY4^E|tpkA{5E-`{BSyLWSTW;t- zQd2z0pwbGsbi~eN=MSj}xQ$Uq{Hx#f>%&YxvMTl+zxw(Fucj8KyC#di?p)-tQb!2a zkVeMz=P7zAnT#9b+3y;OkIzKxaK(0b2%B$|I-$f@3SJ|;ErE+{zL)hffgShD)$P{+ zSg_fjt=B>q@#ze?3}sOGR*VE3l&4dmHS>gBQxlz6ASra4z-F#FZC=stJNS_)9_fsf zMZxRU&SoV!fG^52jnQsdMT|0PWV!5p&5mG%syAGx`?EbB78}4C&cMjDIXwz*2-FD{aS1hJ#ja2BQbQkhM5vg<=RNEyMM7@5An{p zd94y?=2ntosA>bFz097o!eKipJnn2aQ)3_hI-!>H%P5D6yP=f8!1P&Pq;B<7JW=y; zYpU$Rwgk>x$+nxIJ!&mh0`uh{u@GpSPQ>4yzQvjq|Ub_Xh%ohaJy&&L^TKHcq^N%k7 E2YXg~DgXcg diff --git a/src/test/resources/notanmp3.mp3 b/src/test/resources/notanmp3.mp3 deleted file mode 100644 index 456ede9..0000000 --- a/src/test/resources/notanmp3.mp3 +++ /dev/null @@ -1 +0,0 @@ -THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3THISISNOTANMP3 \ No newline at end of file diff --git a/src/test/resources/obsolete-noimage.mp3 b/src/test/resources/obsolete-noimage.mp3 deleted file mode 100755 index b04f073565f436523a947172141250fde55a9676..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11456 zcmeI&UrbY17y$6ESg@|G?FJJPy>W@HJ!@Ff@4sHW+=uU+ zd(QdJ_j^7{Sz-VXktM?oa)3Y(2?Qy)E(2g4hya&r$T^-!z?W(;fD(9jZ?O@t*qf=* zVZaeQiM119@{=|HB?7^7b^(ry0635-!Q_&3sZ74(O@&gGp~f;b+AN(O&(3)(*RT_C ztq>p@BsyHF$Dg-OO5B|XLjAI;!dpT4VKW3!gJ^Un>&1{wVd0x2qhep> z$0rEINhzsm>2ie%)9P~!dHK8EDco%=-DBFf|NTSe>Y6%BV^ed>>9+QBofj_ke0KGV zYu5(`zy5akyOA5C;}bu+ZvQ+r{oCw4&x56h%YSPD%089=5h4?NKLn0Md15kBD&a!tv&CL2L zf6ZKkDRO*uGX37INY?yZM1T^0sVdu3r#W9b-|~uW_H>%!=rBD;OmE0~9T&YP%pGNf zvlsYeo#k;-8K}NC~ZAk+1#k`@eJz54c3H{)7zBG zOJCNz86SLnxafuA6LW9(7i@~J2R74o%T76Qb!BCgtRn-MfwB7>vLCV}h3?ezFV+^` zU0}?K+02RWoyTf;ssbjpUKn7#u$Aq}9Z0THx=YrZdTEdQW7-HEl~XS>SE zXHxsm-Pu>BO&iiiaGBKVfit$L?8?aQy5I*xeMC)nB6TmJ4?*J#yraN@V&MxqjnDu{svv;mM#DQ diff --git a/src/test/resources/obsolete.mp3 b/src/test/resources/obsolete.mp3 deleted file mode 100755 index ff88206ee62cc8f19cf7db4a4b253dda342e6e70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249258 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 mV>;^-^@-8i`{x7w{bLLUIZ%RX7hn5-2HJsO~ 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 diff --git a/src/test/resources/v1andv23tags.mp3 b/src/test/resources/v1andv23tags.mp3 deleted file mode 100644 index ec8205f603f50d006f99432d6ed8434d5605b3ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 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 diff --git a/src/test/resources/v1andv23tagswithalbumimage-utf16le.mp3 b/src/test/resources/v1andv23tagswithalbumimage-utf16le.mp3 deleted file mode 100644 index 3c910455ef3785b82eb0e767bbe36b17932c984c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6144 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 C5m^Wq1ksV9r^ zCy5^V=ZUuDpT|V`U6k78fmntqndbyJxpcidv!#5mwQ{}ncDW%>->m2H^-cC%iG$C6 zk%&7Pa5J38%nr)Cdh2>>+V!=ADOvnCgW#TQLEyuN>5Iso+k~Ey<#7hVc5z*}i=Fg( z-wu=0&6vBtpE z88o(}M4v?3ah#OTTWUF`w{oc?tF2od#ZKeG&rA|k62gt#)}G9owdb3Mm7z%}lJX6( zzmY0j^GZ)57id^t93{E=FJ!)d&*^N&<+0<^&VmW=uI~fDgSH3ft`?M(C4_q<=7e}u zPq}qGo78#F%6V0?<7M`4u|D*}wzi}8KTSNDow=Ldeb4x)rhf%)&|Am`Dk%A7%ZLi$og%LR)(XiO%p+Dv}*Z6ZleSCUUxlkQTZDAY{w zW4a0n@gqyBt~-#qIo${E$QPemBm9cFA~ZOG$s?=kPtV!vTqUvg(Y6AKzAnVkAW7V1 zw}i8791E1&0QU>A&$0_{=h7(CH70?ABn2=QA#dpXEnNQ88@PRKwua9b6_4JvAakTdn$y@Bd*0%6~qu&=} zYcB!t#y&aQVkRA-rh8>*^Y&uzheAMHER( zuL$<_I8#FQ>hTQN_g8+s--MMzN;Wwot8q%<7IPL|-%_$lW88YE-Q`KC9ISG%|h6XwsupS!zHQK>E_?ZNTE zMK8p@_jV@ecEWwPtFJ+toyGCEfUks{9^oHyKD^z)Fz(}3Pr!%t8*VO|Mh_pT;w_uS z@w3-7dY^maL=x>7<2y=XdNtB6hLcz6Ra@pH9N`>q7cpmNGtcCto=e*&eB3SMP@0U1 zWKjRt*2t2vPpNd%CudT%tM1=faFS0+?qKHa|1p#;tvRqSs&sv01bbVH|DqRPrQOk{ zU9Y^}5c^Wq)t2Tk<s&e8ZQpx}J7>y#e28hBG;7JHYe^2Xf$>xCGFVD_vcxnCW- znxirK`Hn;B>VN@u^~V+7(Hd8L<&d$~wXGmxMB9SjJ_6xU#2*^|nyqnjd;$;o;M)$( zfj3-`4h$C{P!G#L1o;;RsHHRE8K+YI4^A52o<2(B)QWiZKkJ5P_H(2ES?6TpbdxyV MmdE^K06-%B2Zw<|FaQ7m diff --git a/src/test/resources/v1andv23tagswithalbumimage.mp3 b/src/test/resources/v1andv23tagswithalbumimage.mp3 deleted file mode 100644 index 0018760537f7dead9e0dc4534f2368f18c24d505..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6144 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 diff --git a/src/test/resources/v1tag.mp3 b/src/test/resources/v1tag.mp3 deleted file mode 100644 index 1fb50d39a9db7cf269efa2216e7f87fdcc9f31e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2997 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 diff --git a/src/test/resources/v23tagwithbpm.mp3 b/src/test/resources/v23tagwithbpm.mp3 deleted file mode 100644 index d533e49ae5514a9794f148653b680e3bda8c789e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3370 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 diff --git a/src/test/resources/v23tagwithbpmfloatwithcomma.mp3 b/src/test/resources/v23tagwithbpmfloatwithcomma.mp3 deleted file mode 100644 index e8f31ea3d6cc030b5961d5c3cdb789aa8f53a153..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3373 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 diff --git a/src/test/resources/v23tagwithchapters.mp3 b/src/test/resources/v23tagwithchapters.mp3 deleted file mode 100644 index fea837692e3c2441b62d8745ef36037f69046783..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91916 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

>jw@Da-O5b!lWuXU+BkQeq|ys{n^?m(@J+6 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

  • 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 X{{cq^v&Yq<@U-0Q|LraPC#(M-8w@9P diff --git a/src/test/resources/v23tagwithwmprating.mp3 b/src/test/resources/v23tagwithwmprating.mp3 deleted file mode 100644 index 87ad80f671ea7a53a76acd7515637dda2038e863..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3398 zcmds3Yg7~07CtixF~AT)cm<6z35Wp^6T(wa6Cf%WLV#FNsRm6HkU{`0zN!-fGy)0% ztpVHe&|0*sUQ}w)QV9)JX+cq}Vx>jEYU!dD!PW|qxf8v;t97-#{e8ccJ^R~dzBzlJ zvy(H4juMan0rIrSxY$^Nuq_b*ODLAg`Tl}{z@XreP~Pv@f24kdEGa1|I!f?5AC1g< z?KM^AmcM;Y7ALc$a0g&zTBb59FBgqfDbrF=Sw_lsRSp`8CaQAMRJj0?izE>*gn(cx zVt<$WkM+ojQV1bR7{O$5iQJ}j3y+hDEmIN}M`RWy$fFbgJiA;b<`XK* zlrL0&HK#lwaycP_3FFIGi4zEKMVLR2$6rabiJ;GWyCOmI=c|0tXMD0eije*-lF~9a z5dwR{C;-?70?A9rc^Q>2vdnW@k>x93spELq z=#k%U{NH+f(nvIjoTQazW@2!|shD|PGT?mgcJ#T27<_)NPu@bsi?w4$MF@+a_LJtY z_{b~0_?6qOG`H=0rWyqdo~Gp*FT5IzFMERZfQ;Ut{>RL?!6p|Gd*YiLiJS-5{dRYL zyp@0NM%Gm4$8QLt=<|=&;8V#Wcp~i(Jrc*qEM9n_TGhUo=+kpT4~`{t!ErD8_DmoI zkMl{_sZ$^|J`Kd895=Xr>K7dQS);8uEb-;&lr zS$V+h1v?-8YTmureg8C)#%SarsPm{1<#v)>n@zn8>&Rsxo(LU7BfN)ciYDuTdcZ{J z9#*xl(q^y~WlOkRWX&NV-)v|6ygHbK7>^=0fL?1)A{pCBLNutC@9!%&dO}ni-|~wm z63wc;1Hlf7>&zRXkG{!0Uxx3m7>f!yzt;{ox9Dkp^^uYac0c~K*t4S|>YC-c4#$r+ z#V171b9DAp+TeKlhb!JYh<5|fc0htu$J2Y4ZY<(Y(ci&S?1$^hy%GaGpL=({B*a}HArps-0oqK`+^Zn#+~#NB39YJ4w=tFf9N6tw&6;2G z;k?5ae*Be!pjb+?-LVqxFS~S(_bas*gTTh=MI2GB!Ufkv2)?dLq#2!Le%m!hZygv5 zHCTa1g{v5ct%@P-Wro2PKwG{tt;_RpdN3pBhef9H(an2|1#DkOnEWcQaGIMZ~Mu9A#z?il78TqtlC8bVFN8X>x!ec8(vA0_}}p9 ztTC2Iu6iQNXc9+s_!p05zMqM#3qYKWZUgE77+NakigZ=KZLHmC?5oxkU>z9B#xC13g?8RY zcsynxV5%KGmIoDFz15SJ-m~4jDVP1s42B|C2YlbYI2oS4k2_tsIYGlIh$5NmJr=dc0z2OvQWRhn#7)$N>4qjpB=JRST8#i;`^$oO`!*{-~4Na*MY`Oz% zZ=`XzPGAsRq@;b?2)X#JL0%tnIIsR@C{uG_0kOI;d6@*oZ8FMxoDT6fH=0qaX;Sp&TCmRsmsD3EbQO-6bz0k+Z>188ShL zFD$I%Y8fe>p8vDXL{Z&|NnqeEt4i^N+4YTguF!A;+?tJd$luws~3S5MMkRK;9!De;=Ar$p$i?+zM{ z(G5x(jWoz}SbbM6&qnM?rS@b9pKMe*W7MU46DY4M;1b)fRb42s_x*Hs%S8a5*>1=) zltU-U87#F5W6}9mtRxatsMlb1la$q?!)<3FC3Ky_LFeo@&uH=Qea|FE+M-lqctL@S zIiD8Dm*koTnb)i$2UvBgJ)HGTPT(%XPGJ(eSDXf z?i9@TtMm>4kY|Os*mMJKB%eITm0ro;v1Ij}rSp$#LpRN#S(_TSx$gGR3RB_sV!QxM zgVg4g)p(mCfVX%Xca?b0vmdrNIdhX%t;8R@x`xYSpQRkeadYw$zR%FXq>TrObN8E( zc2Qm~!>tw1B5E4O-(kGd*KU(vk2cK3r?6c&lNV9L#_G`27>2K{@{;E#&m17$0S}*9 zLfynnYbm3kmeo?}z@6ckXdMxMumjaO$X8J6xjzhW8Klek3K*C^x)PLxa6LoZTr#ZVYtV4%TF**Zfk)p*t8eR C0p)i9 diff --git a/src/test/resources/v23unicodetags.mp3 b/src/test/resources/v23unicodetags.mp3 deleted file mode 100644 index 858cc2ab67152ac8eb3eac18804bc85992b47651..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3071 zcmds3TT~O*8s0M#ViJZB!Yyc&5D)_bCV*T7HQ{1~MhJygRH{J}1Y`+FEs7qU5TN0r zB%mcgTLMyx^wfih7ATd_P?ZXZVihYbH>;(KS_E1v1m+BM^~IO=<-DA4&Fud=dw=u) zYyLH1Azla|010ElVmt|jO6d54d&GNk0AeJe0>WjzX5(NJT~dzej z75KlE_?(_-5Ghs}aqu7p*If#C?~wrO#}C6=o?&q7TGz~t(m&rF(@Xu>glax#42TNu z9l(1Zw$ts7o?K|~V)7Mjcld!7V0!BdtRJKd_zcakB1fBSL=Lmx-;3rxz3XwJ`}4zs z$M;efx`6_%NP6W>;l`(>Gd}>h&uT{u9HxqqYQW(D5h&(U(*aAnL=K#zR^6Rw>vp-0n+gY*Kjs$n)vsf%26PE%l zSVpm6nDUWb+m$I)OV=aQR=ErTD`YLJ$wzBr$%a;zuy99}nK+iVzMQiHepIiU=U6XY^Zmo`zoYXA#nIGX6* zrmt|27H{G4&|PIhfzeF=b%ig2>T6LNVCc*dMBj-BIX(jdPq!Go6GWl8sjt^Z8|C>U zz82AYjQhfB-{Z9wIbT+7>Z7q>1)LG!Z_B$(X15 z-Ij;jXX)Wks3rK>1fV4b@KQ4k!r?r**?&?%T8GgAoe^pceymQ+L8Ziu`c8_8kc~o0 zAjrzWrXGqA%TXR`pDpD_kVs-tlu2lJqyKunkuRgl z3{!cPgtXYE4A zA}+sW<7V|h(%JE=`9`!gVj}s>@2R>?BLO3AD(ZDLJ`6w)Z{J(7V$XZ7-BtQR@ogt` zD_v}9k&Usf%DIY;2aV73z@ex6g}Qs3U-&5`zF5qEy%3*Eld;Y2V)SoTRQ&`tKo^4d zw*hKjfNSatgYZYP?9@jSKp-06OGGrq&2PGO<)MYo(hCN^lP6>)^$Mb2}kUQOEgEJq-RO1gGGDM@NNjZaGLuo>wx z_;<&xZeNM0IUtgz+Q+c~OeF=gMSChf(Cd!r2P+ggSQo}|z;2qdgk~=1_5I$-7R~`J>-f6G!mT`YcON~x^3hK^|M+sR{f~g@y(He@Sqy^n zWb`i^ARCWe=(}SUt!dw^c1~^uYu`RL0e~I35@)@`)s)5t*h!E0+0_L;Xv~Bjj_H}R znlmpm%LJJJhkbnwroXv2Wu})=M#i$o>z^IO6_^%QWH+x8sRP+}&be~)^G;ZeE9poV z#e@v&(Jjy<^tFVn1aWp`6eZWG;qf1&5JnNh&2`W)X)8iX2fwCBy!_l?VRgS5%sMi1 zekgSJ7l(P@q6htbV^Iz)F*HXNSyl`66XYTw#5(-U6+-Fz)IH2ZXF8}b0k-Xt)0ugL zN;0x3^ssl;dtSY`;RlEEy~nP-InJ-HK{VIp;WumwomXneK`QF-sP;TVE2GnqQNG2_ z;h30o)Ep@?CqejJgUlMEyq5n4`CTboX!@PJhXc&rzFggQ9e{b$eVJM{bdi+8PLpG7 zhQNd!i$J*=1y(&r-Z?qmaTSt5cgbANn$yM=ZJq-k8)DFo5P2xPA;-p;OEok78RG>2r_MHe)evShmj+;+Tcijt_9CQ%zbwzE6B*N{_`YNq-rddbuO zoa;7=y>5F8)(VIjJ#{?WGB0QLVE*wzEjL$moBNm;@nY2_8=fYr$60j=7I>7pcmv3( zB(%VA4{jh`Y~e-pW@l~Lx#qQX7nJ_{*U+hkh9kBo9F@XExU&Gy0n4B?TDNBWfAixxrX=i2#<-}%$CByaHTgyv-&xSqWYvINq*?Zp`A?*$i4wI z=iIOU3{ib;&DN4*H-Z?adOYG@e49KZPwv7?FI;KqJ=IUHdiSe9b)O}p#v`uD>r!Hi-S@-1y rt?1kN*H2*mKL9?*klC0|0+2*}?F7s?O9HB062KcHRjg9_J2Do+L~$xv{JWvhX3T%sj8VqM|0z=l#F0Zp zhZw}fNENELqIpeNrIZRF#0QSouHT7*)KwyRQ0|8r{ zv2>|s*$SA8zhDw4o&om|;Si`Kad=H^;0WRif??zesNw}vW@M^lsvxN0l%Xn@{wWiY zQUqmix%MFLKbil(OMA1 zf&dsjBn7b+ptS(R0$_MBACM;84buVRha_NxkTo<0Nkf(p3VA@s&^9y;Z2>%U_%fVB zL9|+cClba7-NG4yXb}MO3d4mg;Gz~FS^)D1GYt~}c|kZ#G>jIe66OQagu7unASW0w zj1aPh#vp096Vie_pkrtong)1@a5P+ob0`2-3?>rB2i?LM0>3ds-v&I~p#sB-;`JOV z5>9F;?|6BKQi*dM$_`%bp@4D9LowjRAEJdvFyslEhPGgpVDey0{Qz_Ua0-B00E__S zz()}P5&*aWI71r$gXRAI{;saBQ>RYV*47%0#+;m-goFf%M8f5Aot<&pFQ^7c0@!6n z&&meCfr$@7d)L}Q_#tP7G-*YAhIU0x%5n{uxiWR(5>@I_4Lc-I5QwmOiK)wwAU|Mv zHu)C_wp}5Mk=kB!Z~(#n&5t{G!yniYnM9<@-T6~jXVz^YjjX(L_?c~0@J_}t`I4`g zVWb{PkqApW-=8?ecaHDF+zQ*)g_x|;>B{CPer{?XJ0O4ZIVv~KJUf7GU+}Tiapu^K z0pZ5dvuAhd%|S<9!y0#1?~djK(j29ftcA^fOygMb^ltGD&memb=2?@{Y~tI_Icp#X zb-2=fJL=2ZINh`n1vFU}-&Yk~mKRtpYG-sNA;X!|9nO+k>D<=zol&ZtXx12WsJ&Gh$>m@8OcH#OJ)Du z^^1I#V6p2&ax+70D>9sZ;3d@A3p5Pgy&s!Kl4}^*O&0P;qXG&;`K`Q3)Hb$)t|FS% zP6V&Ui+UL-Z)TU!C1>@(uIGVy1}LAzXd?HZ=6F#4kV7ab%BK^EzKw!yeLwDFi%P2V zX`McG;bd16zbQJhz`J!gM_;1vO;Xz1t@IuxX@1l(g4q`uO>vZ(GMnZ_=Ft>gfJlrs zEF8lTMXhIdJ@WJX;B$M=PxNb=)~n~1*~+r(X1r(ExY_FFolz#c;Ktckf|X@A_cq3` zg@wKmYe)Sk)Y{(SmaHpFz4SG^(>Ttz`N^a2gvox<6T7!=Wj|iu9bOV+2wob!#%qAo zasb^OvpUyWz;83v$0NkdV`@ zzF7DvxAW>-6e0d1GHmII z_IX_n(bVDBzn%R4qG7qC3pzH_TFR6^Ugm@`mq$>1^=I#$Ge~BHev@lb+JC|FV2(-o zb%EHx>wAwF4Ww-{a@Jm>mmR0XHN{8JSj1hnTNkQyeP6{`SX^7gT(Ic!wKj1;0A;wG z9lQ1Gy*jsEzoX`lJ`gwOlre4|DoD2rNzc;NF-PUz8Q&rMAyRXH*eCE84P;V<j-MDS!e7x47#kHO!|lCpRQ?MZ0;Apn zCP-wlQ8Kyo&DIM7{k4=aZzX45*jr$!aQ>dhI3aKhi1TDs^L@HUV;@@qo#@vQPmcA^ znVkGO13GJRs5exdUJORe6t{L@t(|A+o*%Azbr50l^>vr|lPbXD=%>0XAiZPa%_pqb zo}=y}&hxIT@!TKU1J|Not`ziM&3J`=`4J*vjNe;{y_zc`K2P1w5M$T?eixpu&@@hk zH5yVFAu$ja68pMlFA*VlVj#6ssYD{sS#c_KNafYT5jT3?!!9A2?3T?~18IbB=!grX zP@N;E^?nV-2>6*t*QwomoE&yKnbcD%EY**TX<5Z!Zso}|Z7D%h@}Y~T9>qR7oT+UN zn-Z3<+=-pO$?lzdKt!#s_Tb)yzDpx{i=`Lt_9~Arj@^!P2^r&1STOMHMCS3u^T+Sl z?of$;h+%hMf2Ln^+LC!3UO#C_IoOdtkwv2rbvnTE7jw2A+^kPAw$^wPcLO3@$geds z9DgGNbhLhfCz)7Z#A2}~+V~Zlfi2aU;lL-&Nz6;PbMeo8>{`GOuq0zyM<<%yU04c+ z$Bq$`EAKkx>#PCRD)={b+&T=~ZYC30M8fD|0-Rvj1%tKRlT$JMCwziossrWWDVO$_ zU0XLa#qPvDeu;Q)ytXOoOpnqOJSu$kqu&PCPW36VCF!kJK8@}6(8}haB#+|_9ZWlM zbf_D7*$Rr zlC_Z}WKZl61O=$9z67d$fazRq{Gg_&JH$DD{@_B{p7p$wo3WCz0ZHh|B1denu9P0Q zODr$r+{B(0`?i!xF5}nv7`Er=%sAON7dKzEJ%*+IBjMAnSQ`NKTjaEgnT(EU+Rdx& zpR}~)paQ_R?(x{js83$(v(a9Jz0j$do2~?SP4`)4B}xe=#QlB1esKgZBd0-lt5Dr#$8?%lxqb&b*GZh79hi9qXB z$Q4y3yJPxDdgM0j}4TjrBh}O{Sex^rdb2 zHKS@ucSLuc(e9iHy9K~S-op2ic(MszE`6XXkG+plEY|weTTDbc9>xUl|g5^If z5>{Ph|HMxx^W}2>j1Aa}OtrUTyN-T-SmiwsPS_`2R0r(ZBK$L+HVE%f)SEu(0|HS8 zUn#QJH=jqVEYc1AS;aTL)o53xVGjXe4y{vuxKW{D$|nKgs$&tEjakPn$2W8LT^ za2_3TVm!YJPu%cL?F;GCcYJrRDlEla5?R+xx z{HW1sC&AeFSN8$nN!fw1R&YzplOjBmb3;9ACS5&!&G;rIxVX_EKl-TvI7!nLmV^XQ}&sttu`r9}}Q624Ya z^1xhA3XMjoF%j>7pG?qE<;3GPgj?ij5;+U}oUTMd1Bk-vD~?1~Zuj1s(s`#=^1h)h z3kyl2v5Crt<1;t9R12+rl#M{Bs}FV33zN6m&1WtiO$QY=z~fBpB`{B z^++q$@IA+}VD;&Q`~2!%q|$Sm=}qn%Mh`EgL>ldG^_cfE%xXHF)Wdh4eM_avqB)T^ zI*|$3i-T%69d%k!9OZ*#;s%FrH5b{yDd4M7b>{$h>98=zY$6;Wr+a5=blwbsjdv1> zP*AGZRllIjet5tB7(q>Fr*PS0N(P731$BJdprX}FG*V)CzWbnoK0zSQZs=iMwh?!G zS8LXB7aVm3x0vRtCRTwl)s5}P-8?v*#FtRgD?|J}Pm~h9d%S{n{gcxWFgD|roI%XY zZkklI!IVwaT`XO$Hf-EidT5n;o`8D>YZ;&});}iO9S%(Nu1CjE((_DA(+{*mL1DZ7 zW1JTREGQl;fY0cGH3pZ${O8Mx*4!|23q+T=z3>q)Hy(25mCn34+IWa42rTyt1_a+S zX>r3<;z9C(6Ffz$VO7-ZG1JEH%L`jHhHlqzFxO-4$UNaJ>$!2<E8+Ng4#$vB@Yp%_mLX8-xW-p%33~*34`JQ^|OyF-B=|4hfd_LSx!OXAn zt}A!u4ReXNi=4T&g>7_JB~W(p9(41Vq-H}h5j6a>RZ=?Y5t(ZI>_n<&`JJ1yk8(&0 zJ81d4e-2}aYWM7lE?eCc$=Gx;aPHG@(r#+fu2fxVjD4o;YD;sRwC}QCrw{fV$e7=4 zJEj9}diEs6Jl}F<{>U5uJfo0tXG|}a2GlcZm}+By|7Z(U6*R!8`LxnEM(u`WyfW0e zwG~DVYn%N?69~_B{#LLT47Iz{LwI5ef9+5l*+VzNo}n8E*1`MV8u@PkRHA8rb9g&+ Z5dLTX@xa6Azc_-%&y4@-s2LC({{_@+bkYC- diff --git a/src/test/resources/withitunescomment.mp3 b/src/test/resources/withitunescomment.mp3 deleted file mode 100644 index b549ea258b1870363c8c86633042876379b475b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 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 y0Z7Gv?YP-7p9ZM Date: Sat, 19 Oct 2024 02:11:32 +0200 Subject: [PATCH 8/9] Improvements --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 65c7dd7..eeefeca 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,8 @@ android { minSdkVersion 26 } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } namespace 'com.mpatrick.mp3agic' } From bebbe1637c3d12a104a19878a5bbfaff26e515c2 Mon Sep 17 00:00:00 2001 From: Giuseppe Carnevale Date: Sun, 27 Oct 2024 02:11:45 +0200 Subject: [PATCH 9/9] Improvements --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index eeefeca..7d7acff 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,8 @@ android { minSdkVersion 26 } compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } namespace 'com.mpatrick.mp3agic' }