From 7612f3c5edc127e36392cae99119d776b481efb3 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Fri, 19 Jun 2020 16:52:16 +0200 Subject: [PATCH 1/2] Added test for whitespaces in feed attributes --- .../antennapod/handler/AtomParserTest.java | 43 ++++++++++++ ...ndlerTest.java => FeedParserTestBase.java} | 65 +++++++------------ .../antennapod/handler/RssParserTest.java | 44 +++++++++++++ .../feedgenerator/AtomGenerator.java | 8 ++- .../feedgenerator/RSS2Generator.java | 8 ++- 5 files changed, 124 insertions(+), 44 deletions(-) create mode 100644 app/src/androidTest/java/de/test/antennapod/handler/AtomParserTest.java rename app/src/androidTest/java/de/test/antennapod/handler/{FeedHandlerTest.java => FeedParserTestBase.java} (75%) create mode 100644 app/src/androidTest/java/de/test/antennapod/handler/RssParserTest.java diff --git a/app/src/androidTest/java/de/test/antennapod/handler/AtomParserTest.java b/app/src/androidTest/java/de/test/antennapod/handler/AtomParserTest.java new file mode 100644 index 000000000..5a3be0374 --- /dev/null +++ b/app/src/androidTest/java/de/test/antennapod/handler/AtomParserTest.java @@ -0,0 +1,43 @@ +package de.test.antennapod.handler; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; +import de.danoeh.antennapod.core.feed.Feed; +import de.test.antennapod.util.syndication.feedgenerator.AtomGenerator; +import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +/** + * Tests for Atom feeds in FeedHandler. + */ +@SmallTest +public class AtomParserTest extends FeedParserTestBase { + @Test + public void testAtomBasic() throws Exception { + Feed f1 = createTestFeed(10, true); + Feed f2 = runFeedTest(f1, new AtomGenerator(), "UTF-8", 0); + feedValid(f1, f2, Feed.TYPE_ATOM1); + } + + @Test + public void testLogoWithWhitespace() throws Exception { + String logo = "https://example.com/image.png"; + Feed f1 = createTestFeed(0, false); + f1.setImageUrl(null); + Feed f2 = runFeedTest(f1, new AtomGenerator() { + @Override + protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException { + xml.startTag(null, "logo"); + xml.text(" " + logo + "\n"); + xml.endTag(null, "logo"); + } + }, "UTF-8", 0); + assertEquals(logo, f2.getImageUrl()); + } +} diff --git a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java b/app/src/androidTest/java/de/test/antennapod/handler/FeedParserTestBase.java similarity index 75% rename from app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java rename to app/src/androidTest/java/de/test/antennapod/handler/FeedParserTestBase.java index ba4a944f7..83f334633 100644 --- a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/handler/FeedParserTestBase.java @@ -1,13 +1,19 @@ package de.test.antennapod.handler; import android.content.Context; -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; +import de.danoeh.antennapod.core.feed.Chapter; +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.syndication.handler.FeedHandler; +import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException; +import de.test.antennapod.util.syndication.feedgenerator.FeedGenerator; import org.junit.After; import org.junit.Before; -import org.junit.Test; import org.xml.sax.SAXException; +import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -16,28 +22,15 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import javax.xml.parsers.ParserConfigurationException; - -import de.danoeh.antennapod.core.feed.Chapter; -import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.syndication.handler.FeedHandler; -import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException; -import de.test.antennapod.util.syndication.feedgenerator.AtomGenerator; -import de.test.antennapod.util.syndication.feedgenerator.FeedGenerator; -import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** - * Tests for FeedHandler + * Tests for FeedHandler. */ -@SmallTest -public class FeedHandlerTest { +public abstract class FeedParserTestBase { private static final String FEEDS_DIR = "testfeeds"; private File file = null; @@ -45,7 +38,7 @@ public class FeedHandlerTest { @Before public void setUp() throws Exception { - Context context = InstrumentationRegistry.getTargetContext(); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); File destDir = context.getExternalFilesDir(FEEDS_DIR); assertNotNull(destDir); @@ -68,7 +61,8 @@ public class FeedHandlerTest { outputStream = null; } - private Feed runFeedTest(Feed feed, FeedGenerator g, String encoding, long flags) throws IOException, UnsupportedFeedtypeException, SAXException, ParserConfigurationException { + protected Feed runFeedTest(Feed feed, FeedGenerator g, String encoding, long flags) + throws IOException, UnsupportedFeedtypeException, SAXException, ParserConfigurationException { g.writeFeed(feed, outputStream, encoding, flags); FeedHandler handler = new FeedHandler(); Feed parsedFeed = new Feed(feed.getDownload_url(), feed.getLastUpdate()); @@ -78,7 +72,7 @@ public class FeedHandlerTest { return parsedFeed; } - private void feedValid(Feed feed, Feed parsedFeed, String feedType) { + protected void feedValid(Feed feed, Feed parsedFeed, String feedType) { assertEquals(feed.getTitle(), parsedFeed.getTitle()); if (feedType.equals(Feed.TYPE_ATOM1)) { assertEquals(feed.getFeedIdentifier(), parsedFeed.getFeedIdentifier()); @@ -99,8 +93,9 @@ public class FeedHandlerTest { FeedItem item = feed.getItems().get(i); FeedItem parsedItem = parsedFeed.getItems().get(i); - if (item.getItemIdentifier() != null) + if (item.getItemIdentifier() != null) { assertEquals(item.getItemIdentifier(), parsedItem.getItemIdentifier()); + } assertEquals(item.getTitle(), parsedItem.getTitle()); assertEquals(item.getDescription(), parsedItem.getDescription()); assertEquals(item.getContentEncoded(), parsedItem.getContentEncoded()); @@ -137,33 +132,19 @@ public class FeedHandlerTest { } } - @Test - public void testRSS2Basic() throws IOException, UnsupportedFeedtypeException, SAXException, ParserConfigurationException { - Feed f1 = createTestFeed(10, true); - Feed f2 = runFeedTest(f1, new RSS2Generator(), "UTF-8", RSS2Generator.FEATURE_WRITE_GUID); - feedValid(f1, f2, Feed.TYPE_RSS2); - } - - @Test - public void testAtomBasic() throws IOException, UnsupportedFeedtypeException, SAXException, ParserConfigurationException { - Feed f1 = createTestFeed(10, true); - Feed f2 = runFeedTest(f1, new AtomGenerator(), "UTF-8", 0); - feedValid(f1, f2, Feed.TYPE_ATOM1); - } - - private Feed createTestFeed(int numItems, boolean withFeedMedia) { + protected Feed createTestFeed(int numItems, boolean withFeedMedia) { Feed feed = new Feed(0, null, "title", "http://example.com", "This is the description", - "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", "http://example.com/picture", file.getAbsolutePath(), - "http://example.com/feed", true); + "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", + "http://example.com/picture", file.getAbsolutePath(), "http://example.com/feed", true); feed.setItems(new ArrayList<>()); for (int i = 0; i < numItems; i++) { FeedItem item = new FeedItem(0, "item-" + i, "http://example.com/item-" + i, - "http://example.com/items/" + i, new Date(i*60000), FeedItem.UNPLAYED, feed); + "http://example.com/items/" + i, new Date(i * 60000), FeedItem.UNPLAYED, feed); feed.getItems().add(item); if (withFeedMedia) { - item.setMedia(new FeedMedia(0, item, 4711, 0, 1024*1024, "audio/mp3", null, "http://example.com/media-" + i, - false, null, 0, 0)); + item.setMedia(new FeedMedia(0, item, 4711, 0, 1024 * 1024, "audio/mp3", null, + "http://example.com/media-" + i, false, null, 0, 0)); } } diff --git a/app/src/androidTest/java/de/test/antennapod/handler/RssParserTest.java b/app/src/androidTest/java/de/test/antennapod/handler/RssParserTest.java new file mode 100644 index 000000000..b78d5770c --- /dev/null +++ b/app/src/androidTest/java/de/test/antennapod/handler/RssParserTest.java @@ -0,0 +1,44 @@ +package de.test.antennapod.handler; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; +import de.danoeh.antennapod.core.feed.Feed; +import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +/** + * Tests for RSS feeds in FeedHandler. + */ +@SmallTest +public class RssParserTest extends FeedParserTestBase { + @Test + public void testRss2Basic() throws Exception { + Feed f1 = createTestFeed(10, true); + Feed f2 = runFeedTest(f1, new RSS2Generator(), "UTF-8", RSS2Generator.FEATURE_WRITE_GUID); + feedValid(f1, f2, Feed.TYPE_RSS2); + } + + @Test + public void testImageWithWhitespace() throws Exception { + String image = "https://example.com/image.png"; + Feed f1 = createTestFeed(0, false); + f1.setImageUrl(null); + Feed f2 = runFeedTest(f1, new RSS2Generator() { + @Override + protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException { + xml.startTag(null, "image"); + xml.startTag(null, "url"); + xml.text(" " + image + "\n"); + xml.endTag(null, "url"); + xml.endTag(null, "image"); + } + }, "UTF-8", 0); + assertEquals(image, f2.getImageUrl()); + } +} diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java index 8d2408b45..c80e3bbb1 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java +++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java @@ -15,7 +15,7 @@ import de.danoeh.antennapod.core.util.DateUtils; /** * Creates Atom feeds. See FeedGenerator for more information. */ -public class AtomGenerator implements FeedGenerator{ +public class AtomGenerator implements FeedGenerator { private static final String NS_ATOM = "http://www.w3.org/2005/Atom"; @@ -119,7 +119,13 @@ public class AtomGenerator implements FeedGenerator{ } } + writeAdditionalAttributes(xml); + xml.endTag(null, "feed"); xml.endDocument(); } + + protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException { + + } } diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java index 5f8b4d18c..ee664bfdc 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java +++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java @@ -14,7 +14,7 @@ import de.danoeh.antennapod.core.util.DateUtils; /** * Creates RSS 2.0 feeds. See FeedGenerator for more information. */ -public class RSS2Generator implements FeedGenerator{ +public class RSS2Generator implements FeedGenerator { public static final long FEATURE_WRITE_GUID = 1; @@ -111,9 +111,15 @@ public class RSS2Generator implements FeedGenerator{ } } + writeAdditionalAttributes(xml); + xml.endTag(null, "channel"); xml.endTag(null, "rss"); xml.endDocument(); } + + protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException { + + } } From 64b9fcd18a0146048b92d2c93f4ed6174a96db36 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 24 Jun 2020 22:37:41 +0200 Subject: [PATCH 2/2] Trimming Atom content (except GUID) --- .../de/test/antennapod/handler/AtomParserTest.java | 3 --- .../de/test/antennapod/handler/RssParserTest.java | 8 +++----- .../java/de/test/antennapod/ui/UITestUtils.java | 4 ++-- .../{RSS2Generator.java => Rss2Generator.java} | 12 ++++++++---- .../core/syndication/namespace/atom/NSAtom.java | 12 +++++++----- 5 files changed, 20 insertions(+), 19 deletions(-) rename app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/{RSS2Generator.java => Rss2Generator.java} (91%) diff --git a/app/src/androidTest/java/de/test/antennapod/handler/AtomParserTest.java b/app/src/androidTest/java/de/test/antennapod/handler/AtomParserTest.java index 5a3be0374..de9f53ae2 100644 --- a/app/src/androidTest/java/de/test/antennapod/handler/AtomParserTest.java +++ b/app/src/androidTest/java/de/test/antennapod/handler/AtomParserTest.java @@ -1,12 +1,9 @@ package de.test.antennapod.handler; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import de.danoeh.antennapod.core.feed.Feed; import de.test.antennapod.util.syndication.feedgenerator.AtomGenerator; -import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator; import org.junit.Test; -import org.junit.runner.RunWith; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; diff --git a/app/src/androidTest/java/de/test/antennapod/handler/RssParserTest.java b/app/src/androidTest/java/de/test/antennapod/handler/RssParserTest.java index b78d5770c..d137bb459 100644 --- a/app/src/androidTest/java/de/test/antennapod/handler/RssParserTest.java +++ b/app/src/androidTest/java/de/test/antennapod/handler/RssParserTest.java @@ -1,11 +1,9 @@ package de.test.antennapod.handler; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import de.danoeh.antennapod.core.feed.Feed; -import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator; +import de.test.antennapod.util.syndication.feedgenerator.Rss2Generator; import org.junit.Test; -import org.junit.runner.RunWith; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; @@ -20,7 +18,7 @@ public class RssParserTest extends FeedParserTestBase { @Test public void testRss2Basic() throws Exception { Feed f1 = createTestFeed(10, true); - Feed f2 = runFeedTest(f1, new RSS2Generator(), "UTF-8", RSS2Generator.FEATURE_WRITE_GUID); + Feed f2 = runFeedTest(f1, new Rss2Generator(), "UTF-8", Rss2Generator.FEATURE_WRITE_GUID); feedValid(f1, f2, Feed.TYPE_RSS2); } @@ -29,7 +27,7 @@ public class RssParserTest extends FeedParserTestBase { String image = "https://example.com/image.png"; Feed f1 = createTestFeed(0, false); f1.setImageUrl(null); - Feed f2 = runFeedTest(f1, new RSS2Generator() { + Feed f2 = runFeedTest(f1, new Rss2Generator() { @Override protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException { xml.startTag(null, "image"); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java index 1dddca6b5..b989b519e 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java @@ -9,7 +9,7 @@ import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.test.antennapod.util.service.download.HTTPBin; -import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator; +import de.test.antennapod.util.syndication.feedgenerator.Rss2Generator; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -78,7 +78,7 @@ public class UITestUtils { private String hostFeed(Feed feed) throws IOException { File feedFile = new File(hostedFeedDir, feed.getTitle()); FileOutputStream out = new FileOutputStream(feedFile); - RSS2Generator generator = new RSS2Generator(); + Rss2Generator generator = new Rss2Generator(); generator.writeFeed(feed, out, "UTF-8", 0); out.close(); int id = server.serveFile(feedFile); diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/Rss2Generator.java similarity index 91% rename from app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java rename to app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/Rss2Generator.java index ee664bfdc..a9a6f91e7 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java +++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/Rss2Generator.java @@ -14,15 +14,19 @@ import de.danoeh.antennapod.core.util.DateUtils; /** * Creates RSS 2.0 feeds. See FeedGenerator for more information. */ -public class RSS2Generator implements FeedGenerator { +public class Rss2Generator implements FeedGenerator { public static final long FEATURE_WRITE_GUID = 1; @Override public void writeFeed(Feed feed, OutputStream outputStream, String encoding, long flags) throws IOException { - if (feed == null) throw new IllegalArgumentException("feed = null"); - if (outputStream == null) throw new IllegalArgumentException("outputStream = null"); - if (encoding == null) throw new IllegalArgumentException("encoding = null"); + if (feed == null) { + throw new IllegalArgumentException("feed = null"); + } else if (outputStream == null) { + throw new IllegalArgumentException("outputStream = null"); + } else if (encoding == null) { + throw new IllegalArgumentException("encoding = null"); + } XmlSerializer xml = Xml.newSerializer(); xml.setOutput(outputStream, encoding); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index 7aa5a90e7..7e4350fd4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.syndication.namespace.atom; import android.text.TextUtils; import android.util.Log; +import de.danoeh.antennapod.core.syndication.util.SyndStringUtils; import org.xml.sax.Attributes; import de.danoeh.antennapod.core.feed.FeedItem; @@ -163,12 +164,13 @@ public class NSAtom extends Namespace { if (state.getTagstack().size() >= 2) { AtomText textElement = null; - String content; + String contentRaw; if (state.getContentBuf() != null) { - content = state.getContentBuf().toString(); + contentRaw = state.getContentBuf().toString(); } else { - content = ""; + contentRaw = ""; } + String content = SyndStringUtils.trimAllWhitespace(contentRaw); SyndElement topElement = state.getTagstack().peek(); String top = topElement.getName(); SyndElement secondElement = state.getSecondTag(); @@ -181,9 +183,9 @@ public class NSAtom extends Namespace { if (ID.equals(top)) { if (FEED.equals(second) && state.getFeed() != null) { - state.getFeed().setFeedIdentifier(content); + state.getFeed().setFeedIdentifier(contentRaw); } else if (ENTRY.equals(second) && state.getCurrentItem() != null) { - state.getCurrentItem().setItemIdentifier(content); + state.getCurrentItem().setItemIdentifier(contentRaw); } } else if (TITLE.equals(top) && textElement != null) { if (FEED.equals(second) && state.getFeed() != null) {