summaryrefslogtreecommitdiff
path: root/parser/media/src/test
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2021-08-28 09:52:45 +0200
committerByteHamster <info@bytehamster.com>2021-08-28 10:59:26 +0200
commitca64739f363e585758b6ada6cc4e6c9d43191724 (patch)
tree3b5b6634792a3997d9302053e628ec8cda205ff5 /parser/media/src/test
parentddae5e2278fe6b6e950576cdc460ec7ffe761d5d (diff)
downloadAntennaPod-ca64739f363e585758b6ada6cc4e6c9d43191724.zip
Moved media file parser to its own module
Diffstat (limited to 'parser/media/src/test')
-rw-r--r--parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/ChapterReaderTest.java205
-rw-r--r--parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/Id3ReaderTest.java151
-rw-r--r--parser/media/src/test/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentChapterReaderTest.java44
3 files changed, 400 insertions, 0 deletions
diff --git a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/ChapterReaderTest.java b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/ChapterReaderTest.java
new file mode 100644
index 000000000..af535b12a
--- /dev/null
+++ b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/ChapterReaderTest.java
@@ -0,0 +1,205 @@
+package de.danoeh.antennapod.parser.media.id3;
+
+import de.danoeh.antennapod.model.feed.Chapter;
+import de.danoeh.antennapod.model.feed.EmbeddedChapterImage;
+import de.danoeh.antennapod.parser.media.id3.model.FrameHeader;
+import org.apache.commons.io.input.CountingInputStream;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class ChapterReaderTest {
+ private static final byte CHAPTER_WITHOUT_SUBFRAME_START_TIME = 23;
+ private static final byte[] CHAPTER_WITHOUT_SUBFRAME = {
+ 'C', 'H', '1', 0, // String ID for mapping to CTOC
+ 0, 0, 0, CHAPTER_WITHOUT_SUBFRAME_START_TIME, // Start time
+ 0, 0, 0, 0, // End time
+ 0, 0, 0, 0, // Start offset
+ 0, 0, 0, 0 // End offset
+ };
+
+ @Test
+ public void testReadFullTagWithChapter() throws IOException, ID3ReaderException {
+ byte[] chapter = Id3ReaderTest.concat(
+ Id3ReaderTest.generateFrameHeader(ChapterReader.FRAME_ID_CHAPTER, CHAPTER_WITHOUT_SUBFRAME.length),
+ CHAPTER_WITHOUT_SUBFRAME);
+ byte[] data = Id3ReaderTest.concat(
+ Id3ReaderTest.generateId3Header(chapter.length),
+ chapter);
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ ChapterReader reader = new ChapterReader(inputStream);
+ reader.readInputStream();
+ assertEquals(1, reader.getChapters().size());
+ assertEquals(CHAPTER_WITHOUT_SUBFRAME_START_TIME, reader.getChapters().get(0).getStart());
+ }
+
+ @Test
+ public void testReadFullTagWithMultipleChapters() throws IOException, ID3ReaderException {
+ byte[] chapter = Id3ReaderTest.concat(
+ Id3ReaderTest.generateFrameHeader(ChapterReader.FRAME_ID_CHAPTER, CHAPTER_WITHOUT_SUBFRAME.length),
+ CHAPTER_WITHOUT_SUBFRAME);
+ byte[] data = Id3ReaderTest.concat(
+ Id3ReaderTest.generateId3Header(2 * chapter.length),
+ chapter,
+ chapter);
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ ChapterReader reader = new ChapterReader(inputStream);
+ reader.readInputStream();
+ assertEquals(2, reader.getChapters().size());
+ assertEquals(CHAPTER_WITHOUT_SUBFRAME_START_TIME, reader.getChapters().get(0).getStart());
+ assertEquals(CHAPTER_WITHOUT_SUBFRAME_START_TIME, reader.getChapters().get(1).getStart());
+ }
+
+ @Test
+ public void testReadChapterWithoutSubframes() throws IOException, ID3ReaderException {
+ FrameHeader header = new FrameHeader(ChapterReader.FRAME_ID_CHAPTER,
+ CHAPTER_WITHOUT_SUBFRAME.length, (short) 0);
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(CHAPTER_WITHOUT_SUBFRAME));
+ Chapter chapter = new ChapterReader(inputStream).readChapter(header);
+ assertEquals(CHAPTER_WITHOUT_SUBFRAME_START_TIME, chapter.getStart());
+ }
+
+ @Test
+ public void testReadChapterWithTitle() throws IOException, ID3ReaderException {
+ byte[] title = {
+ ID3Reader.ENCODING_ISO,
+ 'H', 'e', 'l', 'l', 'o', // Title
+ 0 // Null-terminated
+ };
+ byte[] chapterData = Id3ReaderTest.concat(
+ CHAPTER_WITHOUT_SUBFRAME,
+ Id3ReaderTest.generateFrameHeader(ChapterReader.FRAME_ID_TITLE, title.length),
+ title);
+ FrameHeader header = new FrameHeader(ChapterReader.FRAME_ID_CHAPTER, chapterData.length, (short) 0);
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(chapterData));
+ ChapterReader reader = new ChapterReader(inputStream);
+ Chapter chapter = reader.readChapter(header);
+ assertEquals(CHAPTER_WITHOUT_SUBFRAME_START_TIME, chapter.getStart());
+ assertEquals("Hello", chapter.getTitle());
+ }
+
+ @Test
+ public void testReadTitleWithGarbage() throws IOException, ID3ReaderException {
+ byte[] titleSubframeContent = {
+ ID3Reader.ENCODING_ISO,
+ 'A', // Title
+ 0, // Null-terminated
+ 42, 42, 42, 42 // Garbage, should be ignored
+ };
+ FrameHeader header = new FrameHeader(ChapterReader.FRAME_ID_TITLE, titleSubframeContent.length, (short) 0);
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(titleSubframeContent));
+ ChapterReader reader = new ChapterReader(inputStream);
+ Chapter chapter = new ID3Chapter("", 0);
+ reader.readChapterSubFrame(header, chapter);
+ assertEquals("A", chapter.getTitle());
+
+ // Should skip the garbage and point to the next frame
+ assertEquals(titleSubframeContent.length, reader.getPosition());
+ }
+
+ @Test
+ public void testRealFileUltraschall() throws IOException, ID3ReaderException {
+ CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
+ .getResource("ultraschall5.mp3").openStream());
+ ChapterReader reader = new ChapterReader(inputStream);
+ reader.readInputStream();
+ List<Chapter> chapters = reader.getChapters();
+
+ assertEquals(3, chapters.size());
+
+ assertEquals(0, chapters.get(0).getStart());
+ assertEquals(4004, chapters.get(1).getStart());
+ assertEquals(7999, chapters.get(2).getStart());
+
+ assertEquals("Marke 1", chapters.get(0).getTitle());
+ assertEquals("Marke 2", chapters.get(1).getTitle());
+ assertEquals("Marke 3", chapters.get(2).getTitle());
+
+ assertEquals("https://example.com", chapters.get(0).getLink());
+ assertEquals("https://example.com", chapters.get(1).getLink());
+ assertEquals("https://example.com", chapters.get(2).getLink());
+
+ assertEquals(EmbeddedChapterImage.makeUrl(16073, 2750569), chapters.get(0).getImageUrl());
+ assertEquals(EmbeddedChapterImage.makeUrl(2766765, 15740), chapters.get(1).getImageUrl());
+ assertEquals(EmbeddedChapterImage.makeUrl(2782628, 2750569), chapters.get(2).getImageUrl());
+ }
+
+ @Test
+ public void testRealFileAuphonic() throws IOException, ID3ReaderException {
+ CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
+ .getResource("auphonic.mp3").openStream());
+ ChapterReader reader = new ChapterReader(inputStream);
+ reader.readInputStream();
+ List<Chapter> chapters = reader.getChapters();
+
+ assertEquals(4, chapters.size());
+
+ assertEquals(0, chapters.get(0).getStart());
+ assertEquals(3000, chapters.get(1).getStart());
+ assertEquals(6000, chapters.get(2).getStart());
+ assertEquals(9000, chapters.get(3).getStart());
+
+ assertEquals("Chapter 1 - ❤️😊", chapters.get(0).getTitle());
+ assertEquals("Chapter 2 - ßöÄ", chapters.get(1).getTitle());
+ assertEquals("Chapter 3 - 爱", chapters.get(2).getTitle());
+ assertEquals("Chapter 4", chapters.get(3).getTitle());
+
+ assertEquals("https://example.com", chapters.get(0).getLink());
+ assertEquals("https://example.com", chapters.get(1).getLink());
+ assertEquals("https://example.com", chapters.get(2).getLink());
+ assertEquals("https://example.com", chapters.get(3).getLink());
+
+ assertEquals(EmbeddedChapterImage.makeUrl(765, 308), chapters.get(0).getImageUrl());
+ assertEquals(EmbeddedChapterImage.makeUrl(1271, 308), chapters.get(1).getImageUrl());
+ assertEquals(EmbeddedChapterImage.makeUrl(1771, 308), chapters.get(2).getImageUrl());
+ assertEquals(EmbeddedChapterImage.makeUrl(2259, 308), chapters.get(3).getImageUrl());
+ }
+
+ @Test
+ public void testRealFileHindenburgJournalistPro() throws IOException, ID3ReaderException {
+ CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
+ .getResource("hindenburg-journalist-pro.mp3").openStream());
+ ChapterReader reader = new ChapterReader(inputStream);
+ reader.readInputStream();
+ List<Chapter> chapters = reader.getChapters();
+
+ assertEquals(2, chapters.size());
+
+ assertEquals(0, chapters.get(0).getStart());
+ assertEquals(5006, chapters.get(1).getStart());
+
+ assertEquals("Chapter Marker 1", chapters.get(0).getTitle());
+ assertEquals("Chapter Marker 2", chapters.get(1).getTitle());
+
+ assertEquals("https://example.com/chapter1url", chapters.get(0).getLink());
+ assertEquals("https://example.com/chapter2url", chapters.get(1).getLink());
+
+ assertEquals(EmbeddedChapterImage.makeUrl(5330, 4015), chapters.get(0).getImageUrl());
+ assertEquals(EmbeddedChapterImage.makeUrl(9498, 4364), chapters.get(1).getImageUrl());
+ }
+
+ @Test
+ public void testRealFileMp3chapsPy() throws IOException, ID3ReaderException {
+ CountingInputStream inputStream = new CountingInputStream(getClass().getClassLoader()
+ .getResource("mp3chaps-py.mp3").openStream());
+ ChapterReader reader = new ChapterReader(inputStream);
+ reader.readInputStream();
+ List<Chapter> chapters = reader.getChapters();
+
+ assertEquals(4, chapters.size());
+
+ assertEquals(0, chapters.get(0).getStart());
+ assertEquals(7000, chapters.get(1).getStart());
+ assertEquals(9000, chapters.get(2).getStart());
+ assertEquals(11000, chapters.get(3).getStart());
+
+ assertEquals("Start", chapters.get(0).getTitle());
+ assertEquals("Chapter 1", chapters.get(1).getTitle());
+ assertEquals("Chapter 2", chapters.get(2).getTitle());
+ assertEquals("Chapter 3", chapters.get(3).getTitle());
+ }
+}
diff --git a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/Id3ReaderTest.java b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/Id3ReaderTest.java
new file mode 100644
index 000000000..4b0bb2113
--- /dev/null
+++ b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/Id3ReaderTest.java
@@ -0,0 +1,151 @@
+package de.danoeh.antennapod.parser.media.id3;
+
+import de.danoeh.antennapod.parser.media.id3.model.FrameHeader;
+import de.danoeh.antennapod.parser.media.id3.model.TagHeader;
+import org.apache.commons.io.input.CountingInputStream;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class Id3ReaderTest {
+ @Test
+ public void testReadString() throws IOException {
+ byte[] data = {
+ ID3Reader.ENCODING_ISO,
+ 'T', 'e', 's', 't',
+ 0 // Null-terminated
+ };
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ String string = new ID3Reader(inputStream).readEncodingAndString(1000);
+ assertEquals("Test", string);
+ }
+
+ @Test
+ public void testReadMultipleStrings() throws IOException {
+ byte[] data = {
+ ID3Reader.ENCODING_ISO,
+ 'F', 'o', 'o',
+ 0, // Null-terminated
+ ID3Reader.ENCODING_ISO,
+ 'B', 'a', 'r',
+ 0 // Null-terminated
+ };
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ ID3Reader reader = new ID3Reader(inputStream);
+ assertEquals("Foo", reader.readEncodingAndString(1000));
+ assertEquals("Bar", reader.readEncodingAndString(1000));
+ }
+
+ @Test
+ public void testReadingLimit() throws IOException {
+ byte[] data = {
+ ID3Reader.ENCODING_ISO,
+ 'A', 'B', 'C', 'D'
+ };
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ ID3Reader reader = new ID3Reader(inputStream);
+ assertEquals("ABC", reader.readEncodingAndString(4)); // Includes encoding
+ assertEquals('D', reader.readByte());
+ }
+
+ @Test
+ public void testReadUtf16RespectsBom() throws IOException {
+ byte[] data = {
+ ID3Reader.ENCODING_UTF16_WITH_BOM,
+ (byte) 0xff, (byte) 0xfe, // BOM: Little-endian
+ 'A', 0, 'B', 0, 'C', 0,
+ 0, 0, // Null-terminated
+ ID3Reader.ENCODING_UTF16_WITH_BOM,
+ (byte) 0xfe, (byte) 0xff, // BOM: Big-endian
+ 0, 'D', 0, 'E', 0, 'F',
+ 0, 0, // Null-terminated
+ };
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ ID3Reader reader = new ID3Reader(inputStream);
+ assertEquals("ABC", reader.readEncodingAndString(1000));
+ assertEquals("DEF", reader.readEncodingAndString(1000));
+ }
+
+ @Test
+ public void testReadUtf16NullPrefix() throws IOException {
+ byte[] data = {
+ ID3Reader.ENCODING_UTF16_WITH_BOM,
+ (byte) 0xff, (byte) 0xfe, // BOM
+ 0x00, 0x01, // Latin Capital Letter A with macron (Ā)
+ 0, 0, // Null-terminated
+ };
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ String string = new ID3Reader(inputStream).readEncodingAndString(1000);
+ assertEquals("Ā", string);
+ }
+
+ @Test
+ public void testReadingLimitUtf16() throws IOException {
+ byte[] data = {
+ ID3Reader.ENCODING_UTF16_WITHOUT_BOM,
+ 'A', 0, 'B', 0, 'C', 0, 'D', 0
+ };
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ ID3Reader reader = new ID3Reader(inputStream);
+ reader.readEncodingAndString(6); // Includes encoding, produces broken string
+ assertTrue("Should respect limit even if it breaks a symbol", reader.getPosition() <= 6);
+ }
+
+ @Test
+ public void testReadTagHeader() throws IOException, ID3ReaderException {
+ byte[] data = generateId3Header(23);
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ TagHeader header = new ID3Reader(inputStream).readTagHeader();
+ assertEquals("ID3", header.getId());
+ assertEquals(42, header.getVersion());
+ assertEquals(23, header.getSize());
+ }
+
+ @Test
+ public void testReadFrameHeader() throws IOException {
+ byte[] data = generateFrameHeader("CHAP", 42);
+ CountingInputStream inputStream = new CountingInputStream(new ByteArrayInputStream(data));
+ FrameHeader header = new ID3Reader(inputStream).readFrameHeader();
+ assertEquals("CHAP", header.getId());
+ assertEquals(42, header.getSize());
+ }
+
+ public static byte[] generateFrameHeader(String id, int size) {
+ return concat(
+ id.getBytes(StandardCharsets.ISO_8859_1), // Frame ID
+ new byte[] {
+ (byte) (size >> 24), (byte) (size >> 16),
+ (byte) (size >> 8), (byte) (size), // Size
+ 0, 0 // Flags
+ });
+ }
+
+ static byte[] generateId3Header(int size) {
+ return new byte[] {
+ 'I', 'D', '3', // Identifier
+ 0, 42, // Version
+ 0, // Flags
+ (byte) (size >> 24), (byte) (size >> 16),
+ (byte) (size >> 8), (byte) (size), // Size
+ };
+ }
+
+ static byte[] concat(byte[]... arrays) {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ try {
+ for (byte[] array : arrays) {
+ outputStream.write(array);
+ }
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ return outputStream.toByteArray();
+ }
+}
diff --git a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentChapterReaderTest.java b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentChapterReaderTest.java
new file mode 100644
index 000000000..b81ce4651
--- /dev/null
+++ b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentChapterReaderTest.java
@@ -0,0 +1,44 @@
+package de.danoeh.antennapod.parser.media.vorbis;
+
+import de.danoeh.antennapod.model.feed.Chapter;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class VorbisCommentChapterReaderTest {
+
+ @Test
+ public void testRealFilesAuphonic() throws IOException, VorbisCommentReaderException {
+ testRealFileAuphonic("auphonic.ogg");
+ testRealFileAuphonic("auphonic.opus");
+ }
+
+ public void testRealFileAuphonic(String filename) throws IOException, VorbisCommentReaderException {
+ InputStream inputStream = getClass().getClassLoader()
+ .getResource(filename).openStream();
+ VorbisCommentChapterReader reader = new VorbisCommentChapterReader();
+ reader.readInputStream(inputStream);
+ List<Chapter> chapters = reader.getChapters();
+
+ assertEquals(4, chapters.size());
+
+ assertEquals(0, chapters.get(0).getStart());
+ assertEquals(3000, chapters.get(1).getStart());
+ assertEquals(6000, chapters.get(2).getStart());
+ assertEquals(9000, chapters.get(3).getStart());
+
+ assertEquals("Chapter 1 - ❤️😊", chapters.get(0).getTitle());
+ assertEquals("Chapter 2 - ßöÄ", chapters.get(1).getTitle());
+ assertEquals("Chapter 3 - 爱", chapters.get(2).getTitle());
+ assertEquals("Chapter 4", chapters.get(3).getTitle());
+
+ assertEquals("https://example.com", chapters.get(0).getLink());
+ assertEquals("https://example.com", chapters.get(1).getLink());
+ assertEquals("https://example.com", chapters.get(2).getLink());
+ assertEquals("https://example.com", chapters.get(3).getLink());
+ }
+}