X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Ftest%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Ftext%2FSoneTextParserTest.java;h=62f8b481cacebc88aad998d61a8c6be73fbee3cc;hb=852bb107b491884ed09a1a223c67ea05a5de73b9;hp=d81cdc6efa881d6fc6ce49d236f9f5b304190324;hpb=008f8fadc29475e47ebad45d86c9412ceb5c7cf9;p=Sone.git
diff --git a/src/test/java/net/pterodactylus/sone/text/SoneTextParserTest.java b/src/test/java/net/pterodactylus/sone/text/SoneTextParserTest.java
index d81cdc6..62f8b48 100644
--- a/src/test/java/net/pterodactylus/sone/text/SoneTextParserTest.java
+++ b/src/test/java/net/pterodactylus/sone/text/SoneTextParserTest.java
@@ -1,5 +1,5 @@
/*
- * Sone - SoneTextParserTest.java - Copyright © 2011â2012 David Roden
+ * Sone - SoneTextParserTest.java - Copyright © 2011â2013 David Roden
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,164 +17,314 @@
package net.pterodactylus.sone.text;
+import static com.google.common.collect.ImmutableList.builder;
+import static java.util.Arrays.asList;
+import static java.util.UUID.randomUUID;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
import java.io.IOException;
import java.io.StringReader;
+import java.util.Collection;
-import junit.framework.TestCase;
-import net.pterodactylus.sone.core.SoneProvider;
+import net.pterodactylus.sone.data.Mocks;
+import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.data.impl.DefaultSone;
+
+import com.google.common.collect.ImmutableList;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.hamcrest.collection.IsIterableContainingInOrder;
+import org.junit.Test;
/**
* JUnit test case for {@link SoneTextParser}.
*
* @author David âBombeâ Roden
*/
-public class SoneTextParserTest extends TestCase {
-
- //
- // ACTIONS
- //
-
- /**
- * Tests basic plain-text operation of the parser.
- *
- * @throws IOException
- * if an I/O error occurs
- */
- @SuppressWarnings("static-method")
- public void testPlainText() throws IOException {
- SoneTextParser soneTextParser = new SoneTextParser(null, null);
- Iterable parts;
-
- /* check basic operation. */
- parts = soneTextParser.parse(null, new StringReader("Test."));
- assertNotNull("Parts", parts);
- assertEquals("Part Text", "Test.", convertText(parts, PlainTextPart.class));
-
- /* check empty lines at start and end. */
- parts = soneTextParser.parse(null, new StringReader("\nTest.\n\n"));
- assertNotNull("Parts", parts);
- assertEquals("Part Text", "Test.", convertText(parts, PlainTextPart.class));
-
- /* check duplicate empty lines in the text. */
- parts = soneTextParser.parse(null, new StringReader("\nTest.\n\n\nTest."));
- assertNotNull("Parts", parts);
- assertEquals("Part Text", "Test.\n\nTest.", convertText(parts, PlainTextPart.class));
- }
-
- /**
- * Tests parsing of KSK links.
- *
- * @throws IOException
- * if an I/O error occurs
- */
- @SuppressWarnings("static-method")
- public void testKSKLinks() throws IOException {
- SoneTextParser soneTextParser = new SoneTextParser(null, null);
- Iterable parts;
-
- /* check basic links. */
- parts = soneTextParser.parse(null, new StringReader("KSK@gpl.txt"));
- assertNotNull("Parts", parts);
- assertEquals("Part Text", "[KSK@gpl.txt|gpl.txt|gpl.txt]", convertText(parts, FreenetLinkPart.class));
-
- /* check embedded links. */
- parts = soneTextParser.parse(null, new StringReader("Link is KSK@gpl.txt\u200b."));
- assertNotNull("Parts", parts);
- assertEquals("Part Text", "Link is [KSK@gpl.txt|gpl.txt|gpl.txt]\u200b.", convertText(parts, PlainTextPart.class, FreenetLinkPart.class));
-
- /* check embedded links and line breaks. */
- parts = soneTextParser.parse(null, new StringReader("Link is KSK@gpl.txt\nKSK@test.dat\n"));
- assertNotNull("Parts", parts);
- assertEquals("Part Text", "Link is [KSK@gpl.txt|gpl.txt|gpl.txt]\n[KSK@test.dat|test.dat|test.dat]", convertText(parts, PlainTextPart.class, FreenetLinkPart.class));
- }
-
- /**
- * Test case for a bug that was discovered in 0.6.7.
- *
- * @throws IOException
- * if an I/O error occurs
- */
- @SuppressWarnings({ "synthetic-access", "static-method" })
- public void testEmptyLinesAndSoneLinks() throws IOException {
- SoneTextParser soneTextParser = new SoneTextParser(new TestSoneProvider(), null);
- Iterable parts;
-
- /* check basic links. */
- parts = soneTextParser.parse(null, new StringReader("Some text.\n\nLink to sone://DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU and stuff."));
- assertNotNull("Parts", parts);
- assertEquals("Part Text", "Some text.\n\nLink to [Sone|DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU] and stuff.", convertText(parts, PlainTextPart.class, SonePart.class));
- }
-
- //
- // PRIVATE METHODS
- //
-
- /**
- * Converts all given {@link Part}s into a string, validating that the
- * partâs classes match only the expected classes.
- *
- * @param parts
- * The parts to convert to text
- * @param validClasses
- * The valid classes; if no classes are given, all classes are
- * valid
- * @return The converted text
- */
- private String convertText(Iterable parts, Class>... validClasses) {
- StringBuilder text = new StringBuilder();
- for (Part part : parts) {
- assertNotNull("Part", part);
- boolean classValid = validClasses.length == 0;
- for (Class> validClass : validClasses) {
- if (validClass.isAssignableFrom(part.getClass())) {
- classValid = true;
- break;
+public class SoneTextParserTest {
+
+ private final Mocks mocks = new Mocks();
+ private final SoneTextParser soneTextParser = new SoneTextParser(mocks.database);
+
+ private Matcher> matches(final Matcher extends Part>... partsToMatch) {
+ return new TypeSafeMatcher>() {
+
+ private Matcher> iterableMatcher;
+
+ @Override
+ protected boolean matchesSafely(Iterable parts) {
+ iterableMatcher = new IsIterableContainingInOrder(asList(partsToMatch));
+ return iterableMatcher.matches(collapseParts(expandParts(parts)));
+ }
+
+ private Iterable expandParts(Iterable extends Part> parts) {
+ PartContainer partContainer = new PartContainer();
+ for (Part part : parts) {
+ partContainer.add(part);
}
+ return partContainer;
}
- if (!classValid) {
- assertEquals("Partâs Class", null, part.getClass());
+
+ private Collection collapseParts(Iterable extends Part> parts) {
+ ImmutableList.Builder collapsedPartsBuilder = builder();
+ PlainTextPart lastPlainTextPart = null;
+ for (Part part : parts) {
+ if (part instanceof PlainTextPart) {
+ if (lastPlainTextPart != null) {
+ lastPlainTextPart = new PlainTextPart(lastPlainTextPart.getText() + ((PlainTextPart) part).getText());
+ } else {
+ lastPlainTextPart = (PlainTextPart) part;
+ }
+ } else {
+ if (lastPlainTextPart != null) {
+ collapsedPartsBuilder.add(lastPlainTextPart);
+ lastPlainTextPart = null;
+ }
+ collapsedPartsBuilder.add(part);
+ }
+ }
+ if (lastPlainTextPart != null) {
+ collapsedPartsBuilder.add(lastPlainTextPart);
+ }
+ return collapsedPartsBuilder.build();
}
- if (part instanceof PlainTextPart) {
- text.append(((PlainTextPart) part).getText());
- } else if (part instanceof FreenetLinkPart) {
- FreenetLinkPart freenetLinkPart = (FreenetLinkPart) part;
- text.append('[').append(freenetLinkPart.getLink()).append('|').append(freenetLinkPart.isTrusted() ? "trusted|" : "").append(freenetLinkPart.getTitle()).append('|').append(freenetLinkPart.getText()).append(']');
- } else if (part instanceof LinkPart) {
- LinkPart linkPart = (LinkPart) part;
- text.append('[').append(linkPart.getLink()).append('|').append(linkPart.getTitle()).append('|').append(linkPart.getText()).append(']');
- } else if (part instanceof SonePart) {
- SonePart sonePart = (SonePart) part;
- text.append("[Sone|").append(sonePart.getSone().getId()).append(']');
+
+ @Override
+ protected void describeMismatchSafely(Iterable parts, Description mismatchDescription) {
+ iterableMatcher.describeMismatch(collapseParts(parts), mismatchDescription);
}
- }
- return text.toString();
- }
-
- /**
- * Mock Sone provider.
- *
- * @author David âBombeâ Roden
- */
- private static class TestSoneProvider implements SoneProvider {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Sone getSone(final String soneId, boolean create) {
- return new Sone(soneId) {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getName() {
- return soneId;
- }
- };
- }
+ @Override
+ public void describeTo(Description description) {
+ iterableMatcher.describeTo(description);
+ }
+ };
+ }
+
+ private Iterable parse(String text) throws IOException {
+ return soneTextParser.parse(null, new StringReader(text));
+ }
+
+ private Iterable parse(SoneTextParserContext context, String text) throws IOException {
+ return soneTextParser.parse(context, new StringReader(text));
+ }
+
+ @Test
+ public void parsePlainText() throws IOException {
+ assertThat(parse("Test."), matches(is(new PlainTextPart("Test."))));
+ }
+
+ @Test
+ public void parsePlainTextWithEmptyLinesAtTheBeginningAndEnd() throws IOException {
+ assertThat(parse("\nTest.\n\n"), matches(is(new PlainTextPart("Test."))));
+ }
+
+ @Test
+ public void parsePlainTextAndCollapseMultipleEmptyLines() throws IOException {
+ assertThat(parse("\nTest.\n\n\nTest."), matches(is(new PlainTextPart("Test.\n\nTest."))));
+ }
+
+ @Test
+ public void parseSimpleKskLinks() throws IOException {
+ assertThat(parse("KSK@gpl.txt"), matches(is(new FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false))));
+ }
+
+ @Test
+ public void parseEmbeddedLinks() throws IOException {
+ assertThat(parse("Link is KSK@gpl.txt\u200b."), matches(
+ is(new PlainTextPart("Link is ")),
+ is(new FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false)),
+ is(new PlainTextPart("\u200b."))
+ ));
+ }
+
+ @Test
+ public void parseEmbeddedLinksAndLineBreaks() throws IOException {
+ assertThat(parse("Link is KSK@gpl.txt\nKSK@test.dat\n"), matches(
+ is(new PlainTextPart("Link is ")),
+ is(new FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false)),
+ is(new PlainTextPart("\n")),
+ is(new FreenetLinkPart("KSK@test.dat", "test.dat", false))
+ ));
+ }
+
+ @Test
+ public void parseEmptyLinesAndSoneLinks() throws IOException {
+ Sone sone = mocks.mockSone("DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU").create();
+ assertThat(parse("Some text.\n\nLink to sone://DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU and stuff."), matches(
+ is(new PlainTextPart("Some text.\n\nLink to ")),
+ is(new SonePart(sone)),
+ is(new PlainTextPart(" and stuff."))
+ ));
+ }
+
+ @Test
+ public void parseEmptyHttpLinks() throws IOException {
+ assertThat(parse("Some text. Empty link: http:// â nice!"), matches(
+ is(new PlainTextPart("Some text. Empty link: http:// â nice!"))
+ ));
+ }
+
+ @Test
+ public void parseTrustedSoneSSKLinks() throws IOException {
+ Sone trustedSone = mocks.mockSone("DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU").create();
+ assertThat(parse(new SoneTextParserContext(trustedSone), "Get SSK@DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU/file.txt\u200b!"), matches(
+ is(new PlainTextPart("Get ")),
+ is(new FreenetLinkPart("SSK@DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU/file.txt", "file.txt", true)),
+ is(new PlainTextPart("\u200b!"))
+ ));
+ }
+
+ @Test
+ public void parseTrustedSoneUSKLinks() throws IOException {
+ Sone trustedSone = mocks.mockSone("DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU").create();
+ assertThat(parse(new SoneTextParserContext(trustedSone), "Get USK@DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU,DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU/site/0/file.txt\u200b!"), matches(
+ is(new PlainTextPart("Get ")),
+ is(new FreenetLinkPart("USK@DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU,DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU/site/0/file.txt", "file.txt", true)),
+ is(new PlainTextPart("\u200b!"))
+ ));
+ }
+
+ @Test
+ public void parseHttpLink() throws IOException {
+ assertThat(parse("http://w3.org/foo.html"), matches(
+ is(new LinkPart("http://w3.org/foo.html", "w3.org/foo.html", "w3.org/foo.html"))
+ ));
+ }
+
+ @Test
+ public void twoNonEmptyLinesAreParsedCorrectly() throws IOException {
+ assertThat(parse("First line.\nSecond line."), matches(
+ is(new PlainTextPart("First line.\nSecond line."))
+ ));
+ }
+
+ @Test
+ public void malformedChkLinkIsParsedAsText() throws IOException {
+ assertThat(parse("CHK@key/gpl.txt"), matches(
+ is(new PlainTextPart("CHK@key/gpl.txt"))
+ ));
+ }
+
+ @Test
+ public void malformedUskLinkIsParsedAsText() throws IOException {
+ assertThat(parse("USK@key/site/"), matches(
+ is(new PlainTextPart("USK@key/site/"))
+ ));
+ }
+
+ @Test
+ public void httpsLinksAreParsedCorrectly() throws IOException {
+ assertThat(parse("https://site/file.txt"), matches(
+ is(new LinkPart("https://site/file.txt", "site/file.txt"))
+ ));
+ }
+
+ @Test
+ public void postLinksAreParsedCorrectly() throws IOException {
+ Sone sone = mocks.mockSone("Sone").create();
+ Post post = mocks.mockPost(sone, randomUUID().toString()).create();
+ assertThat(parse("post://" + post.getId()), matches(
+ is(new PostPart(post))
+ ));
+ }
+
+ @Test
+ public void linkToNonExistingPostIsParsedAsPlainText() throws IOException {
+ String postId = randomUUID().toString();
+ assertThat(parse("post://" + postId), matches(
+ is(new PlainTextPart("post://" + postId))
+ ));
+ }
+
+ @Test
+ public void tooShortPostLinkIsParsedAsPlainText() throws IOException {
+ assertThat(parse("post://post"), matches(
+ is(new PlainTextPart("post://post"))
+ ));
+ }
+
+ @Test
+ public void freenetPrefixBeforeKeysIsCutOff() throws IOException {
+ assertThat(parse("freenet:KSK@gpl.txt"), matches(
+ is(new FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false))
+ ));
+ }
+
+ @Test
+ public void freenetPrefixBeforeKeysInMiddleOfTextIsCutOff() throws IOException {
+ assertThat(parse("Link is freenet:KSK@gpl.txt"), matches(
+ is(new PlainTextPart("Link is ")),
+ is(new FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false))
+ ));
+ }
+
+ @Test
+ public void linkToNonExistingSoneCreatesPlainTextLink() throws IOException {
+ assertThat(parse("sone://1234567890123456789012345678901234567890123"), matches(
+ is(new PlainTextPart("sone://1234567890123456789012345678901234567890123"))
+ ));
+ }
+
+ @Test
+ public void linkToTooShortSoneIdIsParsedAsPlainText() throws IOException {
+ assertThat(parse("sone://Sone"), matches(
+ is(new PlainTextPart("sone://Sone"))
+ ));
+ }
+
+ @Test
+ public void cutOffQueryFromTextOfFreenetLink() throws IOException {
+ assertThat(parse("KSK@gpl.txt?max-size=17"), matches(
+ is(new FreenetLinkPart("KSK@gpl.txt?max-size=17", "gpl.txt", false))
+ ));
+ }
+
+ @Test
+ public void linkWithoutMetaInformationShowsShortenedRoutingKey() throws IOException {
+ assertThat(parse("CHK@DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU"), matches(
+ is(new FreenetLinkPart("CHK@DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU", "CHK@DAxKQ", false))
+ ));
+ }
+
+ @Test
+ public void httpLinkGetsPartOfPathRemoved() throws IOException {
+ assertThat(parse("http://server.com/path/foo/test.html"), matches(
+ is(new LinkPart("http://server.com/path/foo/test.html", "server.com/â¦/test.html"))
+ ));
+ }
+
+ @Test
+ public void httpLinkThatEndsInASlashGetsSlashRemoved() throws IOException {
+ assertThat(parse("http://server.com/path/foo/"), matches(
+ is(new LinkPart("http://server.com/path/foo/", "server.com/â¦"))
+ ));
+ }
+
+ @Test
+ public void httpLinkGetsWwwRemoved() throws IOException {
+ assertThat(parse("http://www.server.com/foo.html"), matches(
+ is(new LinkPart("http://www.server.com/foo.html", "server.com/foo.html"))
+ ));
+ }
+
+ @Test
+ public void httpLinkGetsQueryRemoved() throws IOException {
+ assertThat(parse("http://server.com/foo.html?id=4"), matches(
+ is(new LinkPart("http://server.com/foo.html?id=4", "server.com/foo.html"))
+ ));
+ }
+
+ @Test
+ public void multipleLinksInOneLine() throws IOException {
+ assertThat(parse("KSK@gpl.txt and http://server.com/"), matches(
+ is(new FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false)),
+ is(new PlainTextPart(" and ")),
+ is(new FreenetLinkPart("http://server.com/", "server.com", false))
+ ));
}
}