Merge branch 'partial-rewrite' into less-critical
[Sone.git] / src / test / java / net / pterodactylus / sone / text / SoneTextParserTest.java
1 /*
2  * Sone - SoneTextParserTest.java - Copyright © 2011–2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.text;
19
20 import java.io.IOException;
21 import java.io.StringReader;
22 import java.util.Arrays;
23
24 import junit.framework.TestCase;
25 import net.pterodactylus.sone.data.Sone;
26 import net.pterodactylus.sone.database.SoneProvider;
27
28 /**
29  * JUnit test case for {@link SoneTextParser}.
30  *
31  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
32  */
33 public class SoneTextParserTest extends TestCase {
34
35         //
36         // ACTIONS
37         //
38
39         /**
40          * Tests basic plain-text operation of the parser.
41          *
42          * @throws IOException
43          *             if an I/O error occurs
44          */
45         @SuppressWarnings("static-method")
46         public void testPlainText() throws IOException {
47                 SoneTextParser soneTextParser = new SoneTextParser(null, null);
48                 Iterable<Part> parts;
49
50                 /* check basic operation. */
51                 parts = soneTextParser.parse(null, new StringReader("Test."));
52                 assertNotNull("Parts", parts);
53                 assertEquals("Part Text", "Test.", convertText(parts, PlainTextPart.class));
54
55                 /* check empty lines at start and end. */
56                 parts = soneTextParser.parse(null, new StringReader("\nTest.\n\n"));
57                 assertNotNull("Parts", parts);
58                 assertEquals("Part Text", "Test.", convertText(parts, PlainTextPart.class));
59
60                 /* check duplicate empty lines in the text. */
61                 parts = soneTextParser.parse(null, new StringReader("\nTest.\n\n\nTest."));
62                 assertNotNull("Parts", parts);
63                 assertEquals("Part Text", "Test.\n\nTest.", convertText(parts, PlainTextPart.class));
64         }
65
66         /**
67          * Tests parsing of KSK links.
68          *
69          * @throws IOException
70          *             if an I/O error occurs
71          */
72         @SuppressWarnings("static-method")
73         public void testKSKLinks() throws IOException {
74                 SoneTextParser soneTextParser = new SoneTextParser(null, null);
75                 Iterable<Part> parts;
76
77                 /* check basic links. */
78                 parts = soneTextParser.parse(null, new StringReader("KSK@gpl.txt"));
79                 assertNotNull("Parts", parts);
80                 assertEquals("Part Text", "[KSK@gpl.txt|gpl.txt|gpl.txt]", convertText(parts, FreenetLinkPart.class));
81
82                 /* check embedded links. */
83                 parts = soneTextParser.parse(null, new StringReader("Link is KSK@gpl.txt\u200b."));
84                 assertNotNull("Parts", parts);
85                 assertEquals("Part Text", "Link is [KSK@gpl.txt|gpl.txt|gpl.txt]\u200b.", convertText(parts, PlainTextPart.class, FreenetLinkPart.class));
86
87                 /* check embedded links and line breaks. */
88                 parts = soneTextParser.parse(null, new StringReader("Link is KSK@gpl.txt\nKSK@test.dat\n"));
89                 assertNotNull("Parts", parts);
90                 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));
91         }
92
93         /**
94          * Test case for a bug that was discovered in 0.6.7.
95          *
96          * @throws IOException
97          *             if an I/O error occurs
98          */
99         @SuppressWarnings({ "synthetic-access", "static-method" })
100         public void testEmptyLinesAndSoneLinks() throws IOException {
101                 SoneTextParser soneTextParser = new SoneTextParser(new TestSoneProvider(), null);
102                 Iterable<Part> parts;
103
104                 /* check basic links. */
105                 parts = soneTextParser.parse(null, new StringReader("Some text.\n\nLink to sone://DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU and stuff."));
106                 assertNotNull("Parts", parts);
107                 assertEquals("Part Text", "Some text.\n\nLink to [Sone|DAxKQzS48mtaQc7sUVHIgx3fnWZPQBz0EueBreUVWrU] and stuff.", convertText(parts, PlainTextPart.class, SonePart.class));
108         }
109
110         /**
111          * Test for a bug discovered in Sone 0.8.4 where a plain “http://” would be
112          * parsed into a link.
113          *
114          * @throws IOException
115          *             if an I/O error occurs
116          */
117         @SuppressWarnings({ "synthetic-access", "static-method" })
118         public void testEmpyHttpLinks() throws IOException {
119                 SoneTextParser soneTextParser = new SoneTextParser(new TestSoneProvider(), null);
120                 Iterable<Part> parts;
121
122                 /* check empty http links. */
123                 parts = soneTextParser.parse(null, new StringReader("Some text. Empty link: http:// – nice!"));
124                 assertNotNull("Parts", parts);
125                 assertEquals("Part Text", "Some text. Empty link: http:// – nice!", convertText(parts, PlainTextPart.class));
126         }
127
128         //
129         // PRIVATE METHODS
130         //
131
132         /**
133          * Converts all given {@link Part}s into a string, validating that the
134          * part’s classes match only the expected classes.
135          *
136          * @param parts
137          *            The parts to convert to text
138          * @param validClasses
139          *            The valid classes; if no classes are given, all classes are
140          *            valid
141          * @return The converted text
142          */
143         private static String convertText(Iterable<Part> parts, Class<?>... validClasses) {
144                 StringBuilder text = new StringBuilder();
145                 for (Part part : parts) {
146                         assertNotNull("Part", part);
147                         boolean classValid = validClasses.length == 0;
148                         for (Class<?> validClass : validClasses) {
149                                 if (validClass.isAssignableFrom(part.getClass())) {
150                                         classValid = true;
151                                         break;
152                                 }
153                         }
154                         if (!classValid) {
155                                 fail("Part’s Class (" + part.getClass() + ") is not one of " + Arrays.toString(validClasses));
156                         }
157                         if (part instanceof PlainTextPart) {
158                                 text.append(((PlainTextPart) part).getText());
159                         } else if (part instanceof FreenetLinkPart) {
160                                 FreenetLinkPart freenetLinkPart = (FreenetLinkPart) part;
161                                 text.append('[').append(freenetLinkPart.getLink()).append('|').append(freenetLinkPart.isTrusted() ? "trusted|" : "").append(freenetLinkPart.getTitle()).append('|').append(freenetLinkPart.getText()).append(']');
162                         } else if (part instanceof LinkPart) {
163                                 LinkPart linkPart = (LinkPart) part;
164                                 text.append('[').append(linkPart.getLink()).append('|').append(linkPart.getTitle()).append('|').append(linkPart.getText()).append(']');
165                         } else if (part instanceof SonePart) {
166                                 SonePart sonePart = (SonePart) part;
167                                 text.append("[Sone|").append(sonePart.getSone().getId()).append(']');
168                         }
169                 }
170                 return text.toString();
171         }
172
173         /**
174          * Mock Sone provider.
175          *
176          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
177          */
178         private static class TestSoneProvider implements SoneProvider {
179
180                 /**
181                  * {@inheritDoc}
182                  */
183                 @Override
184                 public Sone getSone(final String soneId) {
185                         return new Sone(soneId, false) {
186
187                                 /**
188                                  * {@inheritDoc}
189                                  */
190                                 @Override
191                                 public String getName() {
192                                         return soneId;
193                                 }
194                         };
195                 }
196
197         }
198
199 }