|
15 | 15 | */
|
16 | 16 | package org.culturegraph.mf.json;
|
17 | 17 |
|
18 |
| -import com.fasterxml.jackson.core.JsonParseException; |
19 |
| -import com.fasterxml.jackson.core.io.JsonEOFException; |
| 18 | +import static org.mockito.Mockito.inOrder; |
| 19 | +import static org.mockito.Mockito.times; |
| 20 | +import static org.mockito.Mockito.verifyZeroInteractions; |
| 21 | + |
20 | 22 | import org.culturegraph.mf.framework.MetafactureException;
|
21 |
| -import org.culturegraph.mf.framework.ObjectReceiver; |
22 |
| -import org.culturegraph.mf.javaintegration.EventList.Event; |
23 |
| -import org.culturegraph.mf.javaintegration.EventList; |
24 |
| -import org.hamcrest.core.IsInstanceOf; |
25 |
| -import org.junit.After; |
26 |
| -import org.junit.Assert; |
| 23 | +import org.culturegraph.mf.framework.StreamReceiver; |
27 | 24 | import org.junit.Before;
|
28 | 25 | import org.junit.Rule;
|
29 | 26 | import org.junit.Test;
|
30 | 27 | import org.junit.rules.ExpectedException;
|
| 28 | +import org.mockito.InOrder; |
31 | 29 | import org.mockito.Mock;
|
32 |
| -import org.mockito.Mockito; |
33 |
| -import org.mockito.MockitoAnnotations; |
34 |
| - |
35 |
| -import java.util.Iterator; |
| 30 | +import org.mockito.junit.MockitoJUnit; |
| 31 | +import org.mockito.junit.MockitoRule; |
36 | 32 |
|
37 | 33 | /**
|
38 | 34 | * Tests for class {@link JsonDecoder}.
|
|
42 | 38 | */
|
43 | 39 | public final class JsonDecoderTest {
|
44 | 40 |
|
45 |
| - private static final String RECORD = |
46 |
| - "{\"lit1\":\"value 1\",\" ent1\":{\"lit2\":\"value {x}\",\"lit\\\\3\":\"value 2 \"},\"lit4\":\"value '3'\",\"lit5\":null}"; |
47 |
| - |
48 |
| - private static final String ARRAY_RECORD = |
49 |
| - "{\"arr1\":[\"val1\",\"val2\"],\"arr2\":[{\"lit1\":\"val1\",\"lit2\":\"val2\"},{\"lit3\":\"val3\"}],\"arr3\":[[{\"lit4\":\"val4\"}],[{\"lit5\":\"val5\"}]]}"; |
50 |
| - |
51 |
| - private JsonDecoder decoder; |
| 41 | + @Rule |
| 42 | + public MockitoRule mockitoRule = MockitoJUnit.rule(); |
52 | 43 |
|
53 |
| - private EventList eventReceiver; |
| 44 | + @Rule |
| 45 | + public ExpectedException exception = ExpectedException.none(); |
54 | 46 |
|
55 | 47 | @Mock
|
56 |
| - private ObjectReceiver<String> objectReceiver; |
| 48 | + private StreamReceiver receiver; |
57 | 49 |
|
58 |
| - @Rule |
59 |
| - public ExpectedException thrown = ExpectedException.none(); |
| 50 | + private JsonDecoder jsonDecoder; |
60 | 51 |
|
61 | 52 | @Before
|
62 |
| - public void setup() { |
63 |
| - MockitoAnnotations.initMocks(this); |
64 |
| - |
65 |
| - decoder = new JsonDecoder(); |
66 |
| - eventReceiver = new EventList(); |
67 |
| - decoder.setReceiver(eventReceiver); |
68 |
| - } |
69 |
| - |
70 |
| - @After |
71 |
| - public void cleanup() { |
72 |
| - decoder.closeStream(); |
| 53 | + public void init() { |
| 54 | + jsonDecoder = new JsonDecoder(); |
| 55 | + jsonDecoder.setReceiver(receiver); |
73 | 56 | }
|
74 | 57 |
|
75 | 58 | @Test
|
76 | 59 | public void testShouldProcessEmptyStrings() {
|
77 |
| - assertEvents("", new EventList()); |
| 60 | + jsonDecoder.process(""); |
| 61 | + |
| 62 | + verifyZeroInteractions(receiver); |
78 | 63 | }
|
79 | 64 |
|
80 | 65 | @Test
|
81 | 66 | public void testShouldProcessRecords() {
|
82 |
| - final EventList eventList = new EventList(); |
83 |
| - |
84 |
| - expectRecord(eventList); |
85 |
| - assertEvents(RECORD, eventList); |
| 67 | + jsonDecoder.process( |
| 68 | + "{" + |
| 69 | + "\"lit1\":\"value 1\"," + |
| 70 | + "\" ent1\":{" + |
| 71 | + "\"lit2\":\"value {x}\"," + |
| 72 | + "\"lit\\\\3\":\"value 2 \"" + |
| 73 | + "}," + |
| 74 | + "\"lit4\":\"value '3'\"," + |
| 75 | + "\"lit5\":null" + |
| 76 | + "}"); |
| 77 | + |
| 78 | + final InOrder ordered = inOrder(receiver); |
| 79 | + ordered.verify(receiver).startRecord("1"); |
| 80 | + ordered.verify(receiver).literal("lit1", "value 1"); |
| 81 | + ordered.verify(receiver).startEntity(" ent1"); |
| 82 | + ordered.verify(receiver).literal("lit2", "value {x}"); |
| 83 | + ordered.verify(receiver).literal("lit\\3", "value 2 "); |
| 84 | + ordered.verify(receiver).endEntity(); |
| 85 | + ordered.verify(receiver).literal("lit4", "value '3'"); |
| 86 | + ordered.verify(receiver).literal("lit5", null); |
| 87 | + ordered.verify(receiver).endRecord(); |
86 | 88 | }
|
87 | 89 |
|
88 | 90 | @Test
|
89 | 91 | public void testShouldProcessArrays() {
|
90 |
| - final EventList eventList = new EventList(); |
91 |
| - |
92 |
| - expectArray(eventList, "1"); |
93 |
| - assertEvents(ARRAY_RECORD, eventList); |
| 92 | + jsonDecoder.process( |
| 93 | + "{" + |
| 94 | + "\"arr1\":[\"val1\",\"val2\"]," + |
| 95 | + "\"arr2\":[" + |
| 96 | + "{" + |
| 97 | + "\"lit1\":\"val1\"," + |
| 98 | + "\"lit2\":\"val2\"" + |
| 99 | + "},{" + |
| 100 | + "\"lit3\":\"val3\"" + |
| 101 | + "}" + |
| 102 | + "]," + |
| 103 | + "\"arr3\":[" + |
| 104 | + "[" + |
| 105 | + "{\"lit4\":\"val4\"}" + |
| 106 | + "],[" + |
| 107 | + "{\"lit5\":\"val5\"}" + |
| 108 | + "]" + |
| 109 | + "]" + |
| 110 | + "}"); |
| 111 | + |
| 112 | + final InOrder ordered = inOrder(receiver); |
| 113 | + ordered.verify(receiver).startRecord("1"); |
| 114 | + ordered.verify(receiver).startEntity("arr1[]"); |
| 115 | + ordered.verify(receiver).literal("1", "val1"); |
| 116 | + ordered.verify(receiver).literal("2", "val2"); |
| 117 | + ordered.verify(receiver).endEntity(); |
| 118 | + ordered.verify(receiver).startEntity("arr2[]"); |
| 119 | + ordered.verify(receiver).startEntity("1"); |
| 120 | + ordered.verify(receiver).literal("lit1", "val1"); |
| 121 | + ordered.verify(receiver).literal("lit2", "val2"); |
| 122 | + ordered.verify(receiver).endEntity(); |
| 123 | + ordered.verify(receiver).startEntity("2"); |
| 124 | + ordered.verify(receiver).literal("lit3", "val3"); |
| 125 | + ordered.verify(receiver, times(2)).endEntity(); |
| 126 | + ordered.verify(receiver).startEntity("arr3[]"); |
| 127 | + ordered.verify(receiver).startEntity("1[]"); |
| 128 | + ordered.verify(receiver).startEntity("1"); |
| 129 | + ordered.verify(receiver).literal("lit4", "val4"); |
| 130 | + ordered.verify(receiver, times(2)).endEntity(); |
| 131 | + ordered.verify(receiver).startEntity("2[]"); |
| 132 | + ordered.verify(receiver).startEntity("1"); |
| 133 | + ordered.verify(receiver).literal("lit5", "val5"); |
| 134 | + ordered.verify(receiver, times(3)).endEntity(); |
| 135 | + ordered.verify(receiver).endRecord(); |
94 | 136 | }
|
95 | 137 |
|
96 | 138 | @Test
|
97 | 139 | public void testShouldProcessConcatenatedRecords() {
|
98 |
| - final EventList eventList = new EventList(); |
99 |
| - |
100 |
| - expectRecord(eventList); |
101 |
| - expectArray(eventList, "2"); |
| 140 | + jsonDecoder.process( |
| 141 | + "{\"lit\": \"record 1\"}\n" + |
| 142 | + "{\"lit\": \"record 2\"}"); |
102 | 143 |
|
103 |
| - assertEvents(RECORD + "\n" + ARRAY_RECORD, eventList); |
| 144 | + final InOrder ordered = inOrder(receiver); |
| 145 | + ordered.verify(receiver).startRecord("1"); |
| 146 | + ordered.verify(receiver).literal("lit", "record 1"); |
| 147 | + ordered.verify(receiver).endRecord(); |
| 148 | + ordered.verify(receiver).startRecord("2"); |
| 149 | + ordered.verify(receiver).literal("lit", "record 2"); |
| 150 | + ordered.verify(receiver).endRecord(); |
104 | 151 | }
|
105 | 152 |
|
106 | 153 | @Test
|
107 | 154 | public void testShouldProcessMultipleRecords() {
|
108 |
| - final EventList eventList = new EventList(); |
109 |
| - |
110 |
| - expectRecord(eventList); |
111 |
| - assertEvents(RECORD, eventList); |
| 155 | + jsonDecoder.process("{\"lit\": \"record 1\"}"); |
| 156 | + jsonDecoder.process("{\"lit\": \"record 2\"}"); |
112 | 157 |
|
113 |
| - eventList.resetStream(); |
114 |
| - eventReceiver.resetStream(); |
115 |
| - |
116 |
| - expectArray(eventList, "2"); |
117 |
| - assertEvents(ARRAY_RECORD, eventList); |
| 158 | + final InOrder ordered = inOrder(receiver); |
| 159 | + ordered.verify(receiver).startRecord("1"); |
| 160 | + ordered.verify(receiver).literal("lit", "record 1"); |
| 161 | + ordered.verify(receiver).endRecord(); |
| 162 | + ordered.verify(receiver).startRecord("2"); |
| 163 | + ordered.verify(receiver).literal("lit", "record 2"); |
| 164 | + ordered.verify(receiver).endRecord(); |
118 | 165 | }
|
119 | 166 |
|
120 | 167 | @Test
|
121 | 168 | public void testShouldOnlyParseObjects() {
|
122 |
| - expectParseError("null", "Unexpected token 'VALUE_NULL'"); |
123 |
| - } |
| 169 | + exception.expect(MetafactureException.class); |
| 170 | + exception.expectMessage("Unexpected token 'VALUE_NULL'"); |
124 | 171 |
|
125 |
| - @Test |
126 |
| - public void testShouldNotParseIncompleteObjects() { |
127 |
| - expectParseError("{", "Unexpected end-of-input", JsonEOFException.class); |
| 172 | + jsonDecoder.process("null"); |
128 | 173 | }
|
129 | 174 |
|
130 | 175 | @Test
|
131 |
| - public void testShouldNotParseTrailingContent() { |
132 |
| - expectParseError(RECORD + "null", "Unexpected token 'VALUE_NULL'"); |
133 |
| - } |
| 176 | + public void testShouldNotParseIncompleteObjects() { |
| 177 | + exception.expect(MetafactureException.class); |
| 178 | + exception.expectMessage("Unexpected end-of-input"); |
134 | 179 |
|
135 |
| - @Test |
136 |
| - public void testShouldNotParseTrailingGarbage() { |
137 |
| - expectParseError(RECORD + "XXX", "Unrecognized token 'XXX'", JsonParseException.class); |
| 180 | + jsonDecoder.process("{"); |
138 | 181 | }
|
139 | 182 |
|
140 | 183 | @Test
|
141 |
| - public void testShouldRoundtripRecords() { |
142 |
| - verifyRoundtrip(RECORD); |
143 |
| - } |
| 184 | + public void testShouldNotParseTrailingContent() { |
| 185 | + exception.expect(MetafactureException.class); |
| 186 | + exception.expectMessage("Unexpected token 'VALUE_NULL'"); |
144 | 187 |
|
145 |
| - @Test |
146 |
| - public void testShouldRoundtripArrays() { |
147 |
| - verifyRoundtrip(ARRAY_RECORD); |
| 188 | + jsonDecoder.process("{\"lit\":\"value\"}null"); |
148 | 189 | }
|
149 | 190 |
|
150 | 191 | @Test
|
151 |
| - public void testShouldRoundtripMultipleRecords() { |
152 |
| - verifyRoundtrip(RECORD, ARRAY_RECORD); |
153 |
| - } |
154 |
| - |
155 |
| - private void assertEvents(final String string, final EventList eventList) { |
156 |
| - decoder.process(string); |
157 |
| - |
158 |
| - final Iterator<Event> expected = eventList.getEvents().iterator(); |
159 |
| - final Iterator<Event> actual = eventReceiver.getEvents().iterator(); |
160 |
| - |
161 |
| - while (expected.hasNext() && actual.hasNext()) { |
162 |
| - Assert.assertEquals(expected.next().toString(), actual.next().toString()); |
163 |
| - } |
164 |
| - |
165 |
| - Assert.assertFalse("Missing events", expected.hasNext()); |
166 |
| - Assert.assertFalse("Unexpected events", actual.hasNext()); |
167 |
| - } |
168 |
| - |
169 |
| - private void expectParseError(final String string, final String msg, final Class cause) { |
170 |
| - thrown.expectCause(IsInstanceOf.instanceOf(cause)); |
171 |
| - expectParseError(string, msg); |
172 |
| - } |
173 |
| - |
174 |
| - private void expectParseError(final String string, final String msg) { |
175 |
| - thrown.expect(MetafactureException.class); |
176 |
| - thrown.expectMessage(msg); |
177 |
| - |
178 |
| - decoder.process(string); |
179 |
| - } |
180 |
| - |
181 |
| - private void verifyRoundtrip(final String... strings) { |
182 |
| - decoder |
183 |
| - .setReceiver(new JsonEncoder()) |
184 |
| - .setReceiver(objectReceiver); |
185 |
| - |
186 |
| - decoder.process(String.join("\n", strings)); |
187 |
| - |
188 |
| - for (final String string : strings) { |
189 |
| - Mockito.verify(objectReceiver).process(string); |
190 |
| - } |
191 |
| - |
192 |
| - Mockito.verifyNoMoreInteractions(objectReceiver); |
193 |
| - } |
194 |
| - |
195 |
| - private void expectRecord(final EventList eventList) { |
196 |
| - eventList.startRecord("1"); |
197 |
| - eventList.literal("lit1", "value 1"); |
198 |
| - eventList.startEntity(" ent1"); |
199 |
| - eventList.literal("lit2", "value {x}"); |
200 |
| - eventList.literal("lit\\3", "value 2 "); |
201 |
| - eventList.endEntity(); |
202 |
| - eventList.literal("lit4", "value '3'"); |
203 |
| - eventList.literal("lit5", null); |
204 |
| - eventList.endRecord(); |
205 |
| - } |
| 192 | + public void testShouldNotParseTrailingGarbage() { |
| 193 | + exception.expect(MetafactureException.class); |
| 194 | + exception.expectMessage("Unrecognized token 'XXX'"); |
206 | 195 |
|
207 |
| - private void expectArray(final EventList eventList, final String id) { |
208 |
| - eventList.startRecord(id); |
209 |
| - eventList.startEntity("arr1[]"); |
210 |
| - eventList.literal("1", "val1"); |
211 |
| - eventList.literal("2", "val2"); |
212 |
| - eventList.endEntity(); |
213 |
| - eventList.startEntity("arr2[]"); |
214 |
| - eventList.startEntity("1"); |
215 |
| - eventList.literal("lit1", "val1"); |
216 |
| - eventList.literal("lit2", "val2"); |
217 |
| - eventList.endEntity(); |
218 |
| - eventList.startEntity("2"); |
219 |
| - eventList.literal("lit3", "val3"); |
220 |
| - eventList.endEntity(); |
221 |
| - eventList.endEntity(); |
222 |
| - eventList.startEntity("arr3[]"); |
223 |
| - eventList.startEntity("1[]"); |
224 |
| - eventList.startEntity("1"); |
225 |
| - eventList.literal("lit4", "val4"); |
226 |
| - eventList.endEntity(); |
227 |
| - eventList.endEntity(); |
228 |
| - eventList.startEntity("2[]"); |
229 |
| - eventList.startEntity("1"); |
230 |
| - eventList.literal("lit5", "val5"); |
231 |
| - eventList.endEntity(); |
232 |
| - eventList.endEntity(); |
233 |
| - eventList.endEntity(); |
234 |
| - eventList.endRecord(); |
| 196 | + jsonDecoder.process("{\"lit\":\"value\"}XXX"); |
235 | 197 | }
|
236 | 198 |
|
237 | 199 | }
|
0 commit comments