1 package emissary.core;
2
3 import emissary.core.channels.FillChannelFactory;
4 import emissary.core.channels.InMemoryChannelFactory;
5 import emissary.core.channels.SeekableByteChannelFactory;
6 import emissary.core.channels.SeekableByteChannelHelper;
7 import emissary.directory.DirectoryEntry;
8 import emissary.pickup.Priority;
9 import emissary.test.core.junit5.LogbackTester;
10 import emissary.test.core.junit5.UnitTest;
11
12 import ch.qos.logback.classic.Level;
13 import com.google.common.collect.ArrayListMultimap;
14 import com.google.common.collect.ListMultimap;
15 import jakarta.annotation.Nullable;
16 import org.apache.commons.io.IOUtils;
17 import org.junit.jupiter.api.AfterEach;
18 import org.junit.jupiter.api.BeforeEach;
19 import org.junit.jupiter.api.Test;
20 import org.junit.jupiter.params.ParameterizedTest;
21 import org.junit.jupiter.params.provider.Arguments;
22 import org.junit.jupiter.params.provider.MethodSource;
23 import org.mockito.Mockito;
24
25 import java.io.ByteArrayOutputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.lang.reflect.Field;
29 import java.nio.ByteBuffer;
30 import java.nio.channels.SeekableByteChannel;
31 import java.nio.charset.StandardCharsets;
32 import java.time.Instant;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Set;
41 import java.util.TreeSet;
42 import java.util.concurrent.ThreadLocalRandom;
43 import java.util.stream.Stream;
44
45 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
46 import static org.junit.jupiter.api.Assertions.assertEquals;
47 import static org.junit.jupiter.api.Assertions.assertFalse;
48 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
49 import static org.junit.jupiter.api.Assertions.assertNotEquals;
50 import static org.junit.jupiter.api.Assertions.assertNotNull;
51 import static org.junit.jupiter.api.Assertions.assertNull;
52 import static org.junit.jupiter.api.Assertions.assertThrows;
53 import static org.junit.jupiter.api.Assertions.assertTrue;
54 import static org.junit.jupiter.api.Assertions.fail;
55
56 class BaseDataObjectTest extends UnitTest {
57
58 @Nullable
59 private BaseDataObject b = null;
60
61 @Override
62 @BeforeEach
63 public void setUp() throws Exception {
64 this.b = new BaseDataObject("This is a test".getBytes(), "filename.txt");
65 this.b.pushCurrentForm("ONE");
66 this.b.pushCurrentForm("TWO");
67 this.b.pushCurrentForm("THREE");
68 }
69
70 @Override
71 @AfterEach
72 public void tearDown() throws Exception {
73 super.tearDown();
74 this.b = null;
75 }
76
77 @Test
78 void testInterface() {
79
80
81 assertInstanceOf(IBaseDataObject.class, this.b, "Implements the interface");
82 }
83
84 @Test
85 void testConstructors() {
86 final BaseDataObject b2 = new BaseDataObject("This is a test".getBytes(), "filename.txt", "ONE");
87 assertEquals("ONE", b2.currentForm(), "Current form in ctor");
88 assertNotNull(b2.getCreationTimestamp());
89
90 final BaseDataObject b3 = new BaseDataObject("test".getBytes(), "filename.txt", null);
91 assertEquals("", b3.currentForm(), "Current form with null in ctor");
92 assertNotNull(b3.getCreationTimestamp());
93
94 final BaseDataObject tld = new BaseDataObject();
95 final byte[] data = "content".getBytes(StandardCharsets.UTF_8);
96 final String fileName = "aChild";
97 final String form = "UNKNOWN";
98 final BaseDataObject b4 = new BaseDataObject(data, fileName, form, tld);
99 assertEquals(fileName, b4.getFilename());
100 assertEquals(form, b4.currentForm());
101 assertNotNull(b4.getCreationTimestamp());
102 assertEquals(tld, b4.getTld());
103
104 final String fileType = "TEXT";
105 BaseDataObject b5 = new BaseDataObject(data, fileName, form, fileType, tld);
106 assertEquals(fileName, b5.getFilename());
107 assertEquals(form, b5.currentForm());
108 assertEquals(fileType, b5.getFileType());
109 assertNotNull(b5.getCreationTimestamp());
110 assertEquals(tld, b5.getTld());
111
112 }
113
114 @Test
115 void testDataLength() {
116 assertEquals("This is a test".length(), this.b.dataLength(), "Data length");
117 }
118
119 @Test
120 void testNullDataLength() {
121 this.b.setData(null);
122 assertEquals(0, this.b.dataLength(), "Null data length");
123 }
124
125 @Test
126 void testDataLengthWithChannel() {
127 this.b.setData(null);
128 assertEquals(0, this.b.dataLength());
129 this.b.setChannelFactory(InMemoryChannelFactory.create(new byte[10]));
130 assertEquals(10, this.b.dataLength());
131 this.b.setData(new byte[10]);
132 assertEquals(10, this.b.dataLength());
133 }
134
135
136 @Test
137 void testLargestFile() throws IOException {
138 final BaseDataObject bdo = new BaseDataObject();
139 final long fileSize = Long.MAX_VALUE;
140 final SeekableByteChannelFactory sbcf = FillChannelFactory.create(fileSize, (byte) 0);
141 bdo.setChannelFactory(sbcf);
142 assertEquals(fileSize, bdo.getChannelSize());
143 assertEquals(BaseDataObject.MAX_BYTE_ARRAY_SIZE, bdo.dataLength());
144
145 final SeekableByteChannel sbc = sbcf.create();
146 final long newPosition = ThreadLocalRandom.current().nextLong(Integer.MAX_VALUE, Long.MAX_VALUE);
147 sbc.position(newPosition);
148 assertEquals(newPosition, sbc.position());
149 final ByteBuffer buff = ByteBuffer.allocate(16);
150 final int bytesRead = sbc.read(buff);
151 assertEquals(16, bytesRead);
152 final byte[] zeroByteArray = new byte[16];
153 Arrays.fill(zeroByteArray, (byte) 0);
154 assertArrayEquals(zeroByteArray, buff.array());
155 }
156
157 @Test
158 void testDataLengthWhenLargerThanMaxInt() throws IOException {
159 final Long higherLength = Integer.MAX_VALUE + 100L;
160 final String testString = "test data";
161 BaseDataObject bdo = Mockito.spy(this.b);
162 Mockito.when(bdo.getChannelSize()).thenReturn(higherLength);
163 bdo.setChannelFactory(SeekableByteChannelHelper.memory(testString.getBytes()));
164 assertEquals(higherLength.longValue(), bdo.getChannelSize());
165 assertEquals(BaseDataObject.MAX_BYTE_ARRAY_SIZE, bdo.dataLength());
166 }
167
168 @Test
169 void testExceptionWhenGettingDataLengthWithChannel() throws IOException {
170 BaseDataObject bdo = Mockito.spy(this.b);
171 final String testString = "test data";
172 bdo.setChannelFactory(SeekableByteChannelHelper.memory(testString.getBytes()));
173 Mockito.when(bdo.getChannelSize()).thenThrow(IOException.class);
174 assertEquals(0, bdo.dataLength());
175 }
176
177 @Test
178 void testGetDataWhenSmallerThanMaxInt() throws IOException {
179 final String testString = "test data";
180 this.b.setChannelFactory(SeekableByteChannelHelper.memory(testString.getBytes()));
181 assertEquals(testString.getBytes().length, this.b.dataLength());
182 }
183
184 @Test
185 void testExceptionWhenGettingChannelFactory() throws IOException {
186
187
188 final SeekableByteChannelFactory sbcf = Mockito.spy(SeekableByteChannelHelper.memory("Test data".getBytes()));
189
190 this.b.setChannelFactory(sbcf);
191
192 try (SeekableByteChannel sbc = Mockito.spy(this.b.getChannelFactory().create())) {
193
194 Mockito.when(sbcf.create()).thenReturn(sbc);
195
196 Mockito.when(sbc.size()).thenThrow(IOException.class);
197
198 assertArrayEquals(new byte[0], this.b.data());
199 }
200 }
201
202 @Test
203 void testExceptionWhenGettingChannelSize() throws IOException {
204
205 final SeekableByteChannelFactory sbcf = Mockito.spy(SeekableByteChannelHelper.memory("Test data".getBytes()));
206 this.b.setChannelFactory(sbcf);
207
208 try (SeekableByteChannel sbc = Mockito.spy(this.b.getChannelFactory().create())) {
209
210 Mockito.when(sbcf.create()).thenReturn(sbc);
211
212 Mockito.when(sbc.size()).thenThrow(IOException.class);
213
214 assertThrows(IOException.class, () -> this.b.getChannelSize(), "Should throw the IOException up to the caller");
215 }
216 }
217
218 @Test
219 void testIsDataEmpty() throws IOException {
220 final IBaseDataObject nullDataIbdo = new BaseDataObject();
221 final IBaseDataObject zeroLengthDataIbdo = new BaseDataObject(new byte[0], "zeroLengthDataIbdo");
222 final IBaseDataObject nonZeroLengthDataIbdo = new BaseDataObject(new byte[1], "nonZeroLengthDataIbdo");
223
224 assertFalse(nullDataIbdo.hasContent());
225 assertFalse(zeroLengthDataIbdo.hasContent());
226 assertTrue(nonZeroLengthDataIbdo.hasContent());
227 }
228
229 @Test
230 void testDataLengthBothNull() {
231 BaseDataObject bdo = new BaseDataObject();
232 assertEquals(0, bdo.dataLength());
233 }
234
235 @Test
236 void testZeroLengthDataSlice() {
237 final byte[] ary = new byte[0];
238 this.b.setData(ary, 0, 0);
239 assertEquals(0, this.b.dataLength(), "Null data length is zero");
240 }
241
242 @Test
243 void testDataSliceLength() {
244 final byte[] ary = "abcdefghijk".getBytes();
245 this.b.setData(ary, 3, 4);
246 assertEquals(4, this.b.dataLength(), "Array slice must use length");
247 }
248
249 @Test
250 void testDataSliceData() {
251 final byte[] ary = "abcdefghijk".getBytes();
252 this.b.setData(ary, 3, 4);
253 assertEquals("defg", new String(this.b.data()), "Array slice must use proper data");
254 }
255
256 @Test
257 void testNullData() {
258 this.b.setData(null);
259 assertNotNull(this.b.data(), "Data array can never be null");
260 }
261
262 @Test
263 void testNullDataSlice() {
264 this.b.setData(null, 3, 4);
265 assertNotNull(this.b.data(), "Data slice can never be null");
266 }
267
268
269 @Test
270 void testShortName() {
271 assertEquals("filename.txt", this.b.shortName(), "Short name");
272 }
273
274 @Test
275 @SuppressWarnings("ByteBufferBackingArray")
276 void testByteArrays() {
277 this.b.setHeader("A fine header".getBytes());
278 this.b.setFooter("A good footer".getBytes());
279 this.b.addAlternateView("TESTVIEW", "alternate view".getBytes());
280 assertEquals("This is a test", new String(this.b.data()), "Data bytes retrieved");
281 assertEquals("A fine header", new String(this.b.header()), "Header bytes");
282 assertEquals("A good footer", new String(this.b.footer()), "Footer bytes");
283 assertEquals("alternate view", new String(this.b.getAlternateView("TESTVIEW")), "Alt view bytes");
284
285
286 final ByteBuffer hb = this.b.headerBuffer();
287 final ByteBuffer fb = this.b.footerBuffer();
288 final ByteBuffer db = this.b.dataBuffer();
289 final ByteBuffer vb = this.b.getAlternateViewBuffer("TESTVIEW");
290 assertEquals("A fine header".length(), hb.array().length, "Byte buffer on header");
291 assertEquals("A good footer".length(), fb.array().length, "Byte buffer on footer");
292 assertEquals("This is a test".length(), db.array().length, "Byte buffer on data");
293 assertNotNull(vb, "Byte buffer on view");
294 assertEquals("alternate view".length(), vb.array().length, "Byte buffer on view");
295
296 this.b.addAlternateView("TESTVIEW", null);
297 assertNull(this.b.getAlternateView("TESTVIEW"), "Byte buffer on removed view");
298 }
299
300 @Test
301 void testNonExistentAltViews() {
302 assertNull(this.b.getAlternateView("NOSUCHVIEW"), "No such view");
303 }
304
305 @Test
306 void testNonExistentAltViewBuffer() {
307 assertNull(this.b.getAlternateViewBuffer("NOSUCHVIEW"), "Byte buffer on no such view");
308 }
309
310 @Test
311 void testAltViews() {
312 this.b.addAlternateView("TESTVIEW1", "alternate view".getBytes());
313 this.b.addAlternateView("TESTVIEW2", "alternate view".getBytes());
314 this.b.addAlternateView("TESTVIEW3", "alternate view".getBytes());
315
316 this.b.addAlternateView("TESTVIEW2", null);
317 assertNull(this.b.getAlternateView("TESTVIEW2"), "Null view after removal");
318 assertNull(this.b.getAlternateViewBuffer("TESTVIEW2"), "Empty byte buffer after removal");
319 }
320
321 @Test
322 void testAltViewSlice() {
323 this.b.addAlternateView("TESTVIEW1", "abcdefghij".getBytes(), 3, 4);
324 assertEquals("defg", new String(this.b.getAlternateView("TESTVIEW1")), "Alt view slice must use proper data");
325 }
326
327 @Test
328 void testSetOfAltViewNames() {
329 this.b.addAlternateView("TESTVIEW1", "alternate view".getBytes());
330 this.b.addAlternateView("TESTVIEW2", "alternate view".getBytes());
331 this.b.addAlternateView("TESTVIEW3", "alternate view".getBytes());
332 final Set<String> vnames = this.b.getAlternateViewNames();
333 assertEquals(3, vnames.size(), "Count of view names");
334
335 List<String> source = new ArrayList<>(vnames);
336 List<String> sorted = new ArrayList<>(vnames);
337 Collections.sort(sorted);
338 assertEquals(sorted, source, "Views are sorted");
339 }
340
341 @Test
342 void testMapOfAltViews() {
343 this.b.addAlternateView("TESTVIEW1", "alternate view".getBytes());
344 this.b.addAlternateView("TESTVIEW2", "alternate view".getBytes());
345 this.b.addAlternateView("TESTVIEW3", "alternate view".getBytes());
346 final Map<String, byte[]> v = this.b.getAlternateViews();
347 assertEquals(3, v.size(), "Count of views");
348
349 List<String> source = new ArrayList<>(v.keySet());
350 List<String> sorted = new ArrayList<>(v.keySet());
351 Collections.sort(sorted);
352 assertEquals(sorted, source, "Views are sorted");
353 }
354
355 @Test
356 void testAppendAltView() {
357 this.b.addAlternateView("T1", "alternate view".getBytes());
358 this.b.appendAlternateView("T1", " more stuff".getBytes());
359 assertEquals("alternate view more stuff", new String(this.b.getAlternateView("T1")), "Appended alternate view contents");
360 }
361
362 @Test
363 void testAppendAltViewOnEmpty() {
364 this.b.appendAlternateView("T1", "more stuff".getBytes());
365 assertEquals("more stuff", new String(this.b.getAlternateView("T1")), "Appended alternate view contents");
366 }
367
368 @Test
369 void testAppendAltViewSlice() {
370 this.b.addAlternateView("T1", "alternate view".getBytes());
371 this.b.appendAlternateView("T1", "xx more stuff xx".getBytes(), 2, 11);
372 assertEquals("alternate view more stuff", new String(this.b.getAlternateView("T1")), "Appended alternate view contents");
373 }
374
375 @Test
376 void testAppendAltViewSliceOnEmpty() {
377 this.b.appendAlternateView("T1", "xx more stuff xx".getBytes(), 3, 10);
378 assertEquals("more stuff", new String(this.b.getAlternateView("T1")), "Appended alternate view contents");
379 }
380
381 @Test
382 void testWindowsShortName() {
383 this.b.setFilename("c:\\Program Files\\Windows\\filename.txt");
384 assertEquals("filename.txt", this.b.shortName(), "Short windows name");
385 }
386
387 @Test
388 void testUnixShortName() {
389 this.b.setFilename("/usr/local/share/filename.txt");
390 assertEquals("filename.txt", this.b.shortName(), "Short unix name");
391 }
392
393 @Test
394 void testFilename() {
395 assertEquals("filename.txt", this.b.getFilename(), "Short name");
396 }
397
398 @Test
399 void testCurrentFormTop() {
400 assertEquals("THREE", this.b.currentForm(), "Current form push");
401 }
402
403 @Test
404 void testCurrentFormEnqueue() {
405 final int i = this.b.enqueueCurrentForm("FOUR");
406 assertEquals(4, i, "Enqueue return value");
407 assertEquals("THREE", this.b.currentForm(), "Current form push");
408 assertEquals("ONE", this.b.currentFormAt(2), "Prev bottom form");
409 assertEquals("FOUR", this.b.currentFormAt(3), "Bottom form");
410 }
411
412 @Test
413 void testPopCurrentForm() {
414 final String s = this.b.popCurrentForm();
415 assertEquals("THREE", s, "Pop return value");
416 assertEquals("TWO", this.b.currentForm(), "Current form after pop");
417 this.b.popCurrentForm();
418 assertEquals("ONE", this.b.currentForm(), "Current form after pop pop");
419 this.b.popCurrentForm();
420 assertEquals("", this.b.currentForm(), "No forms left");
421 }
422
423 @Test
424 void testCurrentFormAt() {
425 assertEquals("TWO", this.b.currentFormAt(1), "Current form at");
426 }
427
428 @Test
429 void testSearchCurrentForm() {
430 assertEquals(1, this.b.searchCurrentForm("TWO"), "Successful search");
431
432 final List<String> l = new ArrayList<>();
433 l.add("CHOP");
434 l.add("TWO");
435 l.add("CHIP");
436 assertEquals("TWO", this.b.searchCurrentForm(l), "Successful list search");
437
438 }
439
440 @Test
441 void testReplaceCurrentForm() {
442 this.b.replaceCurrentForm("NEWONE");
443 assertEquals(-1, this.b.searchCurrentForm("ONE"), "Not found search");
444 assertEquals(-1, this.b.searchCurrentForm("TWO"), "Not found search");
445 assertEquals(-1, this.b.searchCurrentForm("THREE"), "Not found search");
446 assertEquals(0, this.b.searchCurrentForm("NEWONE"), "Successful search");
447 assertEquals(1, this.b.currentFormSize(), "One form left");
448
449 this.b.replaceCurrentForm(null);
450 assertEquals(-1, this.b.searchCurrentForm("NEWONE"), "Not found search");
451 assertEquals(0, this.b.currentFormSize(), "No forms left");
452 }
453
454
455 @Test
456 void testBadSearchCurrentForm() {
457 assertEquals(-1, this.b.searchCurrentForm("SEVENTEEN"), "Not found search");
458
459 final List<String> l2 = new ArrayList<>();
460 l2.add("SHIP");
461 l2.add("SHAPE");
462 assertNull(this.b.searchCurrentForm(l2), "Search but no match");
463 }
464
465 @Test
466 void testFormSize() {
467 assertEquals(3, this.b.currentFormSize(), "Form stack size");
468 }
469
470 @Test
471 void testDeleteFormFromBottom() {
472 this.b.deleteCurrentFormAt(0);
473 assertEquals("TWO", this.b.currentForm(), "Form remaining on bottom");
474 assertEquals(2, this.b.currentFormSize(), "Stack size after delete");
475 }
476
477 @Test
478 void testDeleteFormFromTop() {
479 this.b.deleteCurrentFormAt(2);
480 assertEquals("THREE", this.b.currentForm(), "Form remaining on top");
481 assertEquals(2, this.b.currentFormSize(), "Stack size after delete");
482 }
483
484 @Test
485 void testDeleteFormFromMiddle() {
486 final int i = this.b.deleteCurrentFormAt(1);
487 assertEquals(2, i, "Delete return value");
488 assertEquals("THREE", this.b.currentForm(), "Form remaining on top");
489 assertEquals("ONE", this.b.currentFormAt(1), "Form remaining on bottom");
490 assertEquals(2, this.b.currentFormSize(), "Stack size after delete");
491 }
492
493 @Test
494 void testDeleteFormFromIllegalPosition() {
495 this.b.deleteCurrentFormAt(7);
496 assertEquals(3, this.b.currentFormSize(), "Stack size after delete");
497 this.b.deleteCurrentFormAt(-1);
498 assertEquals(3, this.b.currentFormSize(), "Stack size after delete");
499 }
500
501 @Test
502 void testDeleteCurrentFormFromNull() {
503 while (this.b.currentFormSize() > 0) {
504 this.b.popCurrentForm();
505 }
506 assertEquals(0, this.b.deleteCurrentFormAt(0), "Delete from empty current forms failed");
507 }
508
509 @Test
510 void testPrintMeta() {
511 this.b.putParameter("FOO", "QUUZ");
512 assertTrue(this.b.printMeta().contains("QUUZ"), "PrintMeta returnss valid params");
513 }
514
515 @Test
516 void testSetParameters() {
517 final Map<String, Object> m = new HashMap<>();
518 m.put("A", "B");
519 this.b.putParameter("FOO", "BAR");
520 this.b.setParameters(m);
521 assertNull(this.b.getParameter("FOO"), "Set parameters must clear old data");
522 }
523
524 @Test
525 void testStringParameterOnNonStringValue() {
526 this.b.putParameter("A", 1L);
527 assertEquals("1", this.b.getStringParameter("A"), "Non-string parameters must call toString method");
528 assertEquals("1", this.b.getParameterAsConcatString("A"), "Non-string parameters must call toString method");
529 assertEquals("1", this.b.getParameterAsString("A"), "Non-string parameters must call toString method");
530 }
531
532 @Test
533 void testStringParameterOnNullValue() {
534 this.b.putParameter("A", null);
535 assertNull(this.b.getStringParameter("A"), "Null parameter must be returned as null");
536 assertNull(this.b.getParameterAsConcatString("A"), "Null parameter must be returned as null");
537 assertNull(this.b.getParameterAsString("A"), "Null parameter must be returned as null");
538 }
539
540 @Test
541 void testStringParameterOnEmptyValue() {
542 this.b.putParameter("A", "");
543 assertEquals("", this.b.getStringParameter("A"), "Empty parameter must be returned as empty string");
544 assertEquals("", this.b.getParameterAsConcatString("A"), "Empty parameter must be returned as empty string");
545 assertEquals("", this.b.getParameterAsString("A"), "Empty parameter must be returned as empty string");
546 }
547
548 @Test
549 void testNumSiblings() {
550 this.b.setNumSiblings(10);
551 assertEquals(10, this.b.getNumSiblings(), "NumSiblings simple set/get failed");
552 }
553
554 @Test
555 void testBirthOrder() {
556 this.b.setBirthOrder(10);
557 assertEquals(10, this.b.getBirthOrder(), "BirthOrder simple set/get failed");
558 }
559
560 @Test
561 void testFontEncoding() {
562 this.b.setFontEncoding("zhosa");
563 assertEquals("zhosa", this.b.getFontEncoding(), "FontEncoding simple set/get failed");
564 }
565
566 @Test
567 void testFileTypeIsEmpty() {
568 this.b.setFileType(Form.UNKNOWN);
569 assertTrue(this.b.isFileTypeEmpty(), "Unknown form must count as empty");
570 this.b.setFileType("BAR");
571 final String[] fakeEmpties = {Form.UNKNOWN, "FOO", "BAR"};
572 assertTrue(this.b.setFileTypeIfEmpty("BAZ", fakeEmpties), "Unknown form must count as empty when passing in list");
573 assertEquals("BAZ", this.b.getFileType(), "Failed to use supplied list of empty forms " + Arrays.asList(fakeEmpties));
574
575 this.b.setFileType("TEST-UNWRAPPED");
576 assertTrue(this.b.setFileTypeIfEmpty("ZAZ"), "Unknown form must count as empty when passing in list");
577 assertEquals("ZAZ", this.b.getFileType());
578 }
579
580 @Test
581 void testAlternateViewCount() {
582 this.b.addAlternateView("FOO", "abcd".getBytes());
583 assertEquals(1, this.b.getNumAlternateViews(), "Number of alternate views failed");
584 this.b.addAlternateView("BAR", "abcd".getBytes());
585 assertEquals(2, this.b.getNumAlternateViews(), "Number of alternate views failed to increment");
586 }
587
588 @Test
589 void testSetBroken() {
590 this.b.setBroken("This is broken");
591 assertTrue(this.b.isBroken(), "Broken indicator failed");
592 this.b.setBroken("This is still broken");
593 assertTrue(this.b.isBroken(), "Broken indicator failed after append");
594 assertTrue(this.b.getBroken().contains("still"), "Broken indicator string failed");
595 }
596
597 @Test
598 void testDeleteFormByName() {
599 this.b.deleteCurrentForm("TWO");
600 assertEquals(2, this.b.currentFormSize(), "Remaining form count");
601 this.b.deleteCurrentForm("ONE");
602 assertEquals(1, this.b.currentFormSize(), "Remaining form count");
603 this.b.deleteCurrentForm("THREE");
604 assertEquals(0, this.b.currentFormSize(), "Remaining form count");
605
606 this.b.pushCurrentForm("ONE");
607 this.b.deleteCurrentForm("BOGUS");
608 assertEquals(1, this.b.currentFormSize(), "Remaining form count");
609 this.b.deleteCurrentForm(null);
610 assertEquals(1, this.b.currentFormSize(), "Remaining form count");
611
612 this.b.deleteCurrentForm("ONE");
613 assertEquals(0, this.b.currentFormSize(), "Remaining form count");
614 this.b.deleteCurrentForm("BOGUS");
615 assertEquals(0, this.b.currentFormSize(), "Remaining form count");
616 this.b.deleteCurrentForm(null);
617 assertEquals(0, this.b.currentFormSize(), "Remaining form count");
618 }
619
620 @Test
621 void testAddCurrentFormAtBottom() {
622 this.b.addCurrentFormAt(0, "FOUR");
623 assertEquals("FOUR", this.b.currentForm(), "Form on top");
624 assertEquals("ONE", this.b.currentFormAt(3), "Form on bottom");
625 assertEquals(4, this.b.currentFormSize(), "Stack size after add");
626 }
627
628 @Test
629 void testAddCurrentFormInMiddle() {
630 this.b.addCurrentFormAt(1, "FOUR");
631 assertEquals("THREE", this.b.currentForm(), "Form remaining on top");
632 assertEquals("ONE", this.b.currentFormAt(3), "Form on bottom");
633 assertEquals(4, this.b.currentFormSize(), "Stack size after add");
634 }
635
636 @Test
637 void testAddCurrentFormAtTop() {
638 this.b.addCurrentFormAt(3, "FOUR");
639 assertEquals("THREE", this.b.currentForm(), "Form on top");
640 assertEquals("FOUR", this.b.currentFormAt(3), "Form on bottom");
641 assertEquals(4, this.b.currentFormSize(), "Stack size after add");
642 }
643
644 @Test
645 void testSetCurrentForm() {
646 this.b.setCurrentForm("FOUR");
647 assertEquals("FOUR", this.b.currentForm(), "Form on top");
648 assertEquals("ONE", this.b.currentFormAt(2), "Form on bottom");
649 assertEquals(3, this.b.currentFormSize(), "Stack size after set");
650 assertTrue(this.b.toString().contains("FOUR"), "To string with current form");
651 }
652
653 @Test
654 void testHistoryInToString() {
655 this.b.setCurrentForm("UNKNOWN");
656 this.b.appendTransformHistory("*.FOOPLACE.*.http://host:1234/fooPlace");
657 this.b.appendTransformHistory("*.BARPLACE.*.http://host:1234/barPlace");
658 final String s = this.b.toString();
659 assertTrue(s.contains("FOOPLACE"), "history elements in toString");
660 assertTrue(s.contains("BARPLACE"), "history elements in toString");
661 }
662
663 @Test
664 void testSetCurrentFormEmpty() {
665 this.b.popCurrentForm();
666 this.b.popCurrentForm();
667 this.b.popCurrentForm();
668 this.b.setCurrentForm("FOUR");
669 assertEquals("FOUR", this.b.currentForm(), "Form on top");
670 assertEquals("FOUR", this.b.currentFormAt(0), "Form on bottom");
671 assertEquals(1, this.b.currentFormSize(), "Stack size after set");
672 }
673
674 @Test
675 void testCurrentFormNullHandling() {
676 assertThrows(IllegalArgumentException.class, () -> this.b.pushCurrentForm(null));
677 assertThrows(IllegalArgumentException.class, () -> this.b.enqueueCurrentForm(null));
678 assertThrows(IllegalArgumentException.class, () -> this.b.setCurrentForm(null));
679 assertThrows(IllegalArgumentException.class, () -> this.b.addCurrentFormAt(0, null));
680 }
681
682 static Stream<Arguments> arguments() {
683 return Stream.of(
684 Arguments.of("TWO", "TWO", "ONE", "pull to top from middle"),
685 Arguments.of("ONE", "ONE", "TWO", "pull to top from bottom"),
686 Arguments.of("THREE", "THREE", "ONE", "pull to top from top"),
687 Arguments.of("SEVENTEEN", "THREE", "ONE", "pull non existent to top"));
688 }
689
690 @ParameterizedTest
691 @MethodSource("arguments")
692 void testPullToTop(String pullToTop, String expected, String expectedAt, String msg) {
693 this.b.pullFormToTop(pullToTop);
694 assertEquals(expected, this.b.currentForm(), msg);
695 assertEquals(expectedAt, this.b.currentFormAt(2), "Form on bottom");
696 assertEquals(3, this.b.currentFormSize(), "Stack size after set");
697 }
698
699 @Test
700 void testGetAllForms() {
701 final List<String> al = this.b.getAllCurrentForms();
702 assertEquals(3, al.size(), "Forms returned");
703 assertEquals("THREE", al.get(0), "Form order");
704 }
705
706 @Test
707 void testProcessingError() {
708 assertNull(this.b.getProcessingError(), "Empty processing error");
709 this.b.addProcessingError("ONE");
710 this.b.addProcessingError("TWO");
711 assertEquals("ONE\nTWO\n", this.b.getProcessingError(), "Catted proc error");
712 }
713
714 @Test
715 void testBeforeStart() {
716 assertTrue(this.b.beforeStart(), "Before start on empty history");
717 this.b.appendTransformHistory("*.FOOPLACE.*.http://host:1234/fooPlace");
718 assertFalse(this.b.beforeStart(), "Before start with history");
719 this.b.clearTransformHistory();
720 assertEquals(0, this.b.transformHistory().size(), "Empty history");
721 assertTrue(this.b.beforeStart(), "Re-emptied history before start");
722
723 this.b.appendTransformHistory("*.FOOPLACE.*.http://host:1234/fooPlace");
724 this.b.appendTransformHistory("*.<SPROUT>.*.http://host:1234/barPlace");
725 assertTrue(this.b.beforeStart(), "Before start with sprout key on end");
726 this.b.appendTransformHistory("UNKNOWN.FOOPLACE.ID.http://host:1234/bazPlace");
727 assertFalse(this.b.beforeStart(), "Not before start with sprout key on list");
728 }
729
730 @Test
731 void testParametersMapSignature() {
732 final Map<String, Object> map = new HashMap<>();
733 map.put("ONE", "uno");
734 map.put("TWO", "dos");
735 map.put("THREE", "tres");
736
737 this.b.putParameters(map);
738
739 final Map<String, String> smap = new HashMap<>();
740 smap.put("FOUR", "cuatro");
741 smap.put("FIVE", "cinco");
742 smap.put("SIX", "seis");
743
744 this.b.putParameters(smap);
745
746 Map<String, Collection<Object>> result = this.b.getParameters();
747 assertEquals(6, result.size(), "Added all types of parameters");
748
749
750 this.b.setParameter("SEVEN", map);
751 this.b.putParameter("EIGHT", smap);
752
753
754 final Map<String, Map<String, String>> combo = new HashMap<>();
755 combo.put("NINE", smap);
756 this.b.putParameters(combo);
757
758 result = this.b.getParameters();
759 assertEquals(9, result.size(), "Added all types of parameters");
760
761 }
762
763 @Test
764 void testParametersMapInterfaceSignature() {
765
766 final IBaseDataObject i = this.b;
767
768 final Map<String, Object> map = new HashMap<>();
769 map.put("ONE", "uno");
770 map.put("TWO", "dos");
771 map.put("THREE", "tres");
772
773 i.putParameters(map);
774
775 final Map<String, String> smap = new HashMap<>();
776 smap.put("FOUR", "cuatro");
777 smap.put("FIVE", "cinco");
778 smap.put("SIX", "seis");
779
780 i.putParameters(smap);
781
782 Map<String, Collection<Object>> result = this.b.getParameters();
783 assertEquals(6, result.size(), "Added all types of parameters");
784
785
786 i.setParameter("SEVEN", map);
787 i.putParameter("EIGHT", smap);
788
789
790 final Map<String, Map<String, String>> combo = new HashMap<>();
791 combo.put("NINE", smap);
792 i.putParameters(combo);
793
794 result = i.getParameters();
795 assertEquals(9, result.size(), "Added all types of parameters");
796 }
797
798 @Test
799 void testPutUniqueParameters() {
800
801 this.b.putParameter("ONE", "uno");
802 this.b.putParameter("TWO", "deux");
803
804 final Map<String, Object> map = new HashMap<>();
805 map.put("ONE", "uno");
806 map.put("TWO", "dos");
807 map.put("THREE", "tres");
808
809 this.b.putUniqueParameters(map);
810
811 assertEquals(1, this.b.getParameter("ONE").size(), "When putting unique parameters values must collapse");
812 assertEquals(2, this.b.getParameter("TWO").size(), "When putting unique parameters distinct values must be stored");
813 assertEquals(1, this.b.getParameter("THREE").size(), "When putting unique parameters new keys must be stored");
814 }
815
816 @Test
817 void testMergeParameters() {
818
819 this.b.putParameter("ONE", "uno");
820 this.b.putParameter("TWO", "deux");
821
822 final Map<String, Object> map = new HashMap<>();
823 map.put("ONE", "uno");
824 map.put("TWO", "dos");
825 map.put("THREE", "tres");
826
827 this.b.mergeParameters(map);
828
829 assertEquals("uno", this.b.getStringParameter("ONE"), "When merging parameters previous values must override");
830 assertEquals("uno", this.b.getParameterAsConcatString("ONE"), "When merging parameters previous values must override");
831 assertEquals("uno", this.b.getParameterAsString("ONE"), "When merging parameters previous values must override");
832 assertEquals("deux", this.b.getStringParameter("TWO"), "When merging parameters previous values must override");
833 assertEquals("deux", this.b.getParameterAsConcatString("TWO"), "When merging parameters previous values must override");
834 assertEquals("deux", this.b.getParameterAsString("TWO"), "When merging parameters previous values must override");
835 assertEquals("tres", this.b.getStringParameter("THREE"), "When merging parameters new keys must be stored");
836 assertEquals("tres", this.b.getParameterAsConcatString("THREE"), "When merging parameters new keys must be stored");
837 assertEquals("tres", this.b.getParameterAsString("THREE"), "When merging parameters new keys must be stored");
838 }
839
840 @Test
841 void testPutParametersWithPolicy() {
842
843 this.b.putParameter("ONE", "uno");
844 this.b.putParameter("TWO", "deux");
845
846 final Map<String, Object> map = new HashMap<>();
847 map.put("ONE", "uno");
848 map.put("TWO", "dos");
849 map.put("THREE", "tres");
850
851 this.b.putParameters(map, IBaseDataObject.MergePolicy.KEEP_ALL);
852
853 assertEquals("uno;uno", this.b.getStringParameter("ONE"), "When specifying KEEP_ALL values must all stay");
854 assertEquals("uno;uno", this.b.getParameterAsConcatString("ONE"), "When specifying KEEP_ALL values must all stay");
855 assertEquals("uno;uno", this.b.getParameterAsString("ONE"), "When specifying KEEP_ALL first value should be retained");
856 assertEquals("deux;dos", this.b.getStringParameter("TWO"), "When specifying KEEP_ALL values must all stay");
857 assertEquals("deux;dos", this.b.getParameterAsConcatString("TWO"), "When specifying KEEP_ALL values must all stay");
858 assertEquals("deux;dos", this.b.getParameterAsString("TWO"), "When specifying KEEP_ALL first value should be retained");
859 assertEquals("tres", this.b.getStringParameter("THREE"), "When specifying KEEP_ALL new keys must be stored");
860 assertEquals("tres", this.b.getParameterAsConcatString("THREE"), "When specifying KEEP_ALL new keys must be stored");
861 assertEquals("tres", this.b.getParameterAsString("THREE"), "When specifying KEEP_ALL first value should be retained");
862 }
863
864 @Test
865 void testPutParametersWithMultimapAsMap() {
866 final ListMultimap<String, String> map = ArrayListMultimap.create();
867 map.put("ONE", "uno");
868 map.put("ONE", "ein");
869 map.put("ONE", "neo");
870 map.put("TWO", "deux");
871 this.b.putParameter("TWO", "dos");
872 this.b.putParameters(map.asMap());
873 assertEquals(3, this.b.getParameter("ONE").size(), "Multimap parameters should merge");
874 assertEquals(2, this.b.getParameter("TWO").size(), "Multimap parameters should merge");
875 map.clear();
876 assertEquals(3, this.b.getParameter("ONE").size(), "Multimap parameters should be detached from callers map");
877 assertEquals(2, this.b.getParameter("TWO").size(), "Multimap parameters should be detached from callers map");
878 map.put("THREE", "tres");
879 this.b.mergeParameters(map.asMap());
880 assertEquals(1, this.b.getParameter("THREE").size(), "Multimap parameters should merge");
881 map.put("FOUR", "cuatro");
882 this.b.putUniqueParameters(map.asMap());
883 assertEquals(1, this.b.getParameter("THREE").size(), "Multimap parameters should remain unique");
884 assertEquals(1, this.b.getParameter("FOUR").size(), "Multimap params should add on unique");
885 }
886
887 @Test
888 void testParameters() {
889 this.b.putParameter("ME", "YOU");
890 assertEquals("YOU", this.b.getStringParameter("ME"), "Gotten parameter");
891 assertEquals("YOU", this.b.getParameterAsConcatString("ME"), "Gotten parameter");
892 assertEquals("YOU", this.b.getParameterAsString("ME"), "Gotten parameter");
893 final Map<String, Object> map = new HashMap<>();
894 map.put("ONE", "uno");
895 map.put("TWO", "dos");
896 map.put("THREE", "tres");
897 this.b.putParameters(map);
898 assertEquals("uno", this.b.getStringParameter("ONE"), "Map put parameter gotten");
899 assertEquals("uno", this.b.getParameterAsConcatString("ONE"), "Map put parameter gotten");
900 assertEquals("uno", this.b.getParameterAsString("ONE"), "Map put parameter gotten");
901 assertEquals("dos", this.b.getStringParameter("TWO"), "Map put parameter gotten");
902 assertEquals("dos", this.b.getParameterAsConcatString("TWO"), "Map put parameter gotten");
903 assertEquals("dos", this.b.getParameterAsString("TWO"), "Map put parameter gotten");
904 assertEquals("tres", this.b.getStringParameter("THREE"), "Map put parameter gotten");
905 assertEquals("tres", this.b.getParameterAsConcatString("THREE"), "Map put parameter gotten");
906 assertEquals("tres", this.b.getParameterAsString("THREE"), "Map put parameter gotten");
907 assertEquals("YOU", this.b.getStringParameter("ME"), "Gotten parameter");
908 assertEquals("YOU", this.b.getParameterAsConcatString("ME"), "Gotten parameter");
909 assertEquals("YOU", this.b.getParameterAsString("ME"), "Gotten parameter");
910
911
912 this.b.deleteParameter("THREE");
913 assertNull(this.b.getParameter("THREE"), "Deleted param is gone");
914
915
916 this.b.putParameter("ME", "THEM");
917 assertEquals("THEM", this.b.getStringParameter("ME"), "Gotten parameter");
918 assertEquals("THEM", this.b.getParameterAsConcatString("ME"), "Gotten parameter");
919 assertEquals("THEM", this.b.getParameterAsString("ME"), "Gotten parameter");
920
921
922 this.b.clearParameters();
923 assertNull(this.b.getParameter("THREE"), "Deleted param is gone");
924 assertNull(this.b.getParameter("ME"), "Deleted param is gone");
925 final Map<?, ?> m = this.b.getParameters();
926 assertNotNull(m, "Clear paramters leave empty map");
927 assertEquals(0, m.size(), "Clear parameters leaves empty map");
928
929 }
930
931 @Test
932 void testHasParameter() {
933 this.b.setParameter("FOO", "BAR");
934 assertTrue(this.b.hasParameter("FOO"), "Has parameter must be true when present");
935 }
936
937 @Test
938 void testHasParameterMiss() {
939 assertFalse(this.b.hasParameter("FOO"), "Has parameter must be false when not present");
940 }
941
942 @Test
943 void testHasParameterAfterDelete() {
944 this.b.putParameter("FOO", "BARZILLAI");
945 this.b.deleteParameter("FOO");
946 assertFalse(this.b.hasParameter("FOO"), "Has parameter must be false after parameter has been removed");
947 }
948
949 @Test
950 void testAppendDuplicateParameters() {
951 this.b.appendParameter("YO", "GABBA");
952 this.b.appendParameter("YO", "GABBA");
953 assertEquals("GABBA;GABBA", this.b.getStringParameter("YO"), "Appended duplicate parameters should be preserved");
954 assertEquals("GABBA;GABBA", this.b.getParameterAsConcatString("YO"), "Appended duplicate parameters should be preserved");
955 assertEquals("GABBA;GABBA", this.b.getParameterAsString("YO"), "Appended duplicate parameters first value should be preserved");
956 assertTrue(this.b.hasParameter("YO"), "HasParameter should be true");
957 }
958
959 @Test
960 void testAppendUniqueParameters() {
961 this.b.appendUniqueParameter("YO", "GABBA");
962 this.b.appendUniqueParameter("YO", "GABBA");
963 assertEquals("GABBA", this.b.getStringParameter("YO"), "Appended unique parameters should be collapsed");
964 assertEquals("GABBA", this.b.getParameterAsConcatString("YO"), "Appended unique parameters should be collapsed");
965 assertEquals("GABBA", this.b.getParameterAsString("YO"), "Appended unique parameters should be collapsed");
966 assertTrue(this.b.hasParameter("YO"), "HasParameter should be true");
967 }
968
969 @Test
970 void testParametersWithMixtureOfSingleValuesAndLists() {
971 final Map<String, Object> p = new HashMap<>();
972 final List<String> foolist = new ArrayList<>();
973 foolist.add("FOO1");
974 foolist.add("FOO2");
975 foolist.add("FOO3");
976 p.put("FOO", foolist);
977 this.b.putParameters(p);
978 assertEquals(3, this.b.getParameter("FOO").size(), "Returned list size should match what was put in");
979 this.b.appendParameter("FOO", "FOO4");
980 assertEquals("FOO1;FOO2;FOO3;FOO4",
981 this.b.getStringParameter("FOO"),
982 "Returned string should be combination of initial list and added value");
983 assertEquals("FOO1;FOO2;FOO3;FOO4",
984 this.b.getParameterAsConcatString("FOO"),
985 "Returned string should be combination of initial list and added value");
986 assertEquals("FOO1;FOO2;FOO3;FOO4",
987 this.b.getParameterAsString("FOO"),
988 "Returned string should be first value from combination of initial list and added value");
989 }
990
991 @Test
992 void testParametersWithMixtureOfSingleValuesAndSets() {
993 final Map<String, Object> p = new HashMap<>();
994 final Set<String> fooset = new TreeSet<>();
995 fooset.add("FOO1");
996 fooset.add("FOO2");
997 fooset.add("FOO3");
998 p.put("FOO", fooset);
999 this.b.putParameters(p);
1000 assertEquals(3, this.b.getParameter("FOO").size(), "Returned list size should match what was put in");
1001 this.b.appendParameter("FOO", "FOO4");
1002 assertEquals("FOO1;FOO2;FOO3;FOO4", this.b.getStringParameter("FOO"), "Returned string should be combination of initial set and added value");
1003 assertEquals("FOO1;FOO2;FOO3;FOO4", this.b.getParameterAsConcatString("FOO"),
1004 "Returned string should be combination of initial set and added value");
1005 assertEquals("FOO1;FOO2;FOO3;FOO4", this.b.getParameterAsString("FOO"),
1006 "Returned string should be first value from combination of initial set and added value");
1007 }
1008
1009 @Test
1010 void testCookedParameters() {
1011 this.b.appendParameter("YO", "GABBA");
1012 this.b.appendParameter("YO", "GABBA");
1013 this.b.appendUniqueParameter("WHALE", "BLUBBER");
1014 this.b.appendUniqueParameter("WHALE", "BLUBBER");
1015 final Map<String, String> m = this.b.getCookedParameters();
1016 assertNotNull(m, "Cooked parameters cannot be null");
1017 assertEquals("GABBA;GABBA", m.get("YO"), "Cooked parameters should contains inserted value");
1018 assertEquals("BLUBBER", m.get("WHALE"), "Cooked parameters should contains inserted unique value");
1019 }
1020
1021 @Test
1022 void testParameterKeys() {
1023 this.b.appendParameter("YO", "GABBA");
1024 this.b.appendParameter("YO", "GABBA");
1025 this.b.appendUniqueParameter("WHALE", "BLUBBER");
1026 this.b.appendUniqueParameter("WHALE", "BLUBBER");
1027 final Set<String> keys = this.b.getParameterKeys();
1028 assertNotNull(keys, "Parameter keys cannot be null");
1029 assertTrue(keys.contains("YO"), "Parameter keys should contains inserted key");
1030 assertTrue(keys.contains("WHALE"), "Parameter keys should contains inserted unique key");
1031 }
1032
1033 @Test
1034 void testAppendParameter() {
1035 this.b.putParameter("ME", "YOU");
1036 this.b.appendParameter("ME", "FOO");
1037 assertEquals("YOU;FOO", this.b.getStringParameter("ME"), "Appended parameter value");
1038 assertEquals("YOU;FOO", this.b.getParameterAsConcatString("ME"), "Appended parameter value");
1039 assertEquals("YOU;FOO", this.b.getParameterAsString("ME"), "Appended parameter value");
1040 }
1041
1042 @Test
1043 void testAppendParameterIterables() {
1044 this.b.putParameter("ME", "YOU");
1045 this.b.appendParameter("ME", Arrays.asList("FOO", "BAR", "BAZ"));
1046 assertEquals("YOU;FOO;BAR;BAZ", this.b.getStringParameter("ME"), "Appended parameter value");
1047 assertEquals("YOU;FOO;BAR;BAZ", this.b.getParameterAsConcatString("ME"), "Appended parameter value");
1048 assertEquals("YOU;FOO;BAR;BAZ", this.b.getParameterAsString("ME"), "First value from appended parameter value");
1049
1050 final Set<String> s = new TreeSet<>();
1051 s.add("ZAB");
1052 s.add("RAB");
1053 s.add("OOF");
1054 this.b.appendParameter("ME", s);
1055
1056 assertEquals("YOU;FOO;BAR;BAZ;OOF;RAB;ZAB", this.b.getStringParameter("ME"), "Appended set parameter value");
1057 assertEquals("YOU;FOO;BAR;BAZ;OOF;RAB;ZAB", this.b.getParameterAsConcatString("ME"), "Appended set parameter value");
1058 assertEquals("YOU;FOO;BAR;BAZ;OOF;RAB;ZAB", this.b.getParameterAsString("ME"), "First value from appended set parameter value");
1059 }
1060
1061 @Test
1062 void testAppendParameterOntoEmpty() {
1063 this.b.appendParameter("ME", "FOO");
1064 assertEquals("FOO", this.b.getStringParameter("ME"), "Appended parameter value");
1065 assertEquals("FOO", this.b.getParameterAsConcatString("ME"), "Appended parameter value");
1066 assertEquals("FOO", this.b.getParameterAsString("ME"), "First value from appended parameter value");
1067 }
1068
1069
1070 @Test
1071 void testWhereAmI() {
1072 assertNotNull(this.b.whereAmI(), "WhereamI gets host name");
1073 assertNotEquals("FAILED", this.b.whereAmI(), "WhereamI gets host name");
1074 }
1075
1076 @Test
1077 void testVisitHistory() {
1078 assertNull(this.b.getLastPlaceVisited(), "No last place");
1079 assertNull(this.b.getPenultimatePlaceVisited(), "No penultimate place");
1080
1081 this.b.appendTransformHistory("UNKNOWN.FOO.ID.http://host:1234/FooPlace$1010");
1082
1083 assertNull(this.b.getPenultimatePlaceVisited(), "Still no penultimate place");
1084
1085 this.b.appendTransformHistory("UNKNOWN.BAR.ID.http://host:1234/BarPlace$2020");
1086 this.b.appendTransformHistory("UNKNOWN.BAZ.ID.http://host:1234/BazPlace$3030");
1087 this.b.appendTransformHistory("UNKNOWN.BAM.ID.http://host:1234/BamPlace$4040");
1088
1089 final DirectoryEntry sde = this.b.getLastPlaceVisited();
1090 assertNotNull(sde, "Last place directory entry");
1091 assertEquals("UNKNOWN.BAM.ID.http://host:1234/BamPlace$4040", sde.getFullKey(), "Last place key");
1092 final DirectoryEntry pen = this.b.getPenultimatePlaceVisited();
1093 assertNotNull(pen, "Penultimate place");
1094 assertEquals("UNKNOWN.BAZ.ID.http://host:1234/BazPlace$3030", pen.getFullKey(), "Pen place key");
1095
1096 assertTrue(this.b.hasVisited("*.BAM.*.*"), "Has visited last");
1097 assertTrue(this.b.hasVisited("*.BAR.*.*"), "Has visited first");
1098 assertFalse(this.b.hasVisited("*.SHAZAM.*.*"), "No such visit");
1099
1100 this.b.clearTransformHistory();
1101 assertFalse(this.b.hasVisited("*.BAM.*.*"), "Has no visited after clear");
1102 }
1103
1104 @Test
1105 void testVisitHistoryCoordinated() {
1106 assertNull(this.b.getLastPlaceVisited(), "Transform history should be empty");
1107 assertNull(this.b.getPenultimatePlaceVisited(), "Transform history should be empty");
1108
1109 this.b.appendTransformHistory("UNKNOWN.FOO.ID.http://host:1234/FooPlace$1010");
1110 this.b.appendTransformHistory("UNKNOWN.BAR_COORDINATION.ID.http://host:1234/BarPlace$2020");
1111 this.b.appendTransformHistory("UNKNOWN.BAZ.ID.http://host:1234/BazPlace$3030", true);
1112 this.b.appendTransformHistory("UNKNOWN.BAM.ID.http://host:1234/BamPlace$4040", true);
1113
1114 final DirectoryEntry sde = this.b.getLastPlaceVisited();
1115 assertNotNull(sde, "Last place directory entry should exist");
1116 assertEquals("UNKNOWN.BAR_COORDINATION.ID.http://host:1234/BarPlace$2020", sde.getFullKey(), "Last place returned the wrong key");
1117
1118 final DirectoryEntry pen = this.b.getPenultimatePlaceVisited();
1119 assertNotNull(pen, "Penultimate place directory entry should exist");
1120 assertEquals("UNKNOWN.FOO.ID.http://host:1234/FooPlace$1010", pen.getFullKey(), "Penultimate place returned the wrong key");
1121
1122 assertTrue(this.b.hasVisited("*.FOO.*.*"), "Has visited should have matched for pattern");
1123 assertTrue(this.b.hasVisited("*.BAR_COORDINATION.*.*"), "Has visited should have matched for pattern");
1124 assertFalse(this.b.hasVisited("*.BAZ.*.*"), "Has visited should not have matched for pattern");
1125 assertFalse(this.b.hasVisited("*.BAM.*.*"), "Has visited should not have matched for pattern");
1126
1127 this.b.clearTransformHistory();
1128 assertFalse(this.b.hasVisited("*.FOO.*.*"), "Has visited should not have matched for pattern");
1129 assertFalse(this.b.hasVisited("*.BAR_COORDINATION.*.*"), "Has visited should not have matched for pattern");
1130 }
1131
1132 @Test
1133 void testFiletype() {
1134 this.b.setFileType(Form.UNKNOWN);
1135 assertEquals(Form.UNKNOWN, this.b.getFileType(), "Filetype saved");
1136
1137 this.b.setFileTypeIfEmpty("FOO");
1138 assertEquals("FOO", this.b.getFileType(), "Filetype saved on empty");
1139
1140 this.b.setFileTypeIfEmpty("BAR");
1141 assertEquals("FOO", this.b.getFileType(), "Filetype ignored on non-empty");
1142
1143 this.b.setFileType(null);
1144 assertNull(this.b.getFileType(), "Null filetype set");
1145 this.b.setFileTypeIfEmpty("BAZ");
1146 assertEquals("BAZ", this.b.getFileType(), "Filetype set on null as empty");
1147 }
1148
1149 @Test
1150 void testClone() throws IOException {
1151 try {
1152 this.b.setParameter("FOOBAR", "JOEBLOGGS");
1153 final IBaseDataObject clone = this.b.clone();
1154 assertEquals(this.b.getFilename(), clone.getFilename(), "Names must match");
1155 final String savedName = this.b.getFilename();
1156 this.b.setFilename("foo.bar");
1157 assertEquals(savedName, clone.getFilename(), "Names must be detached after clone");
1158
1159 assertEquals(this.b.currentFormSize(), clone.currentFormSize(), "Current form size must match");
1160 this.b.popCurrentForm();
1161 assertEquals(this.b.currentFormSize(), clone.currentFormSize() - 1, "Current form stack must be detached after clone");
1162 final String newData = "some new data";
1163 final SeekableByteChannelFactory sbcf = InMemoryChannelFactory.create(newData.getBytes());
1164 this.b.setChannelFactory(sbcf);
1165 final IBaseDataObject cloneSbc = this.b.clone();
1166 assertEquals(13, cloneSbc.getChannelFactory().create().read(ByteBuffer.allocate(newData.length())));
1167
1168 assertEquals(newData, new String(cloneSbc.data()));
1169
1170 } catch (CloneNotSupportedException ex) {
1171 fail("Clone must be supported on BaseDataObject", ex);
1172 }
1173 }
1174
1175 @Test
1176 void testHeaderEncoding() {
1177 this.b.setHeaderEncoding("foo");
1178 assertEquals("foo", this.b.getHeaderEncoding(), "Header encoding simple string set/get failed");
1179 }
1180
1181 @Test
1182 void testDefaultPriority() {
1183 assertEquals(Priority.DEFAULT, this.b.getPriority(), "Default priority failed");
1184 }
1185
1186 @Test
1187 void testUpdatedPriority() {
1188 this.b.setPriority(1);
1189 assertEquals(1, this.b.getPriority(), "Updated priority failed");
1190 }
1191
1192 @Test
1193 void testDefaultConstructor_setDateTime() {
1194
1195 final BaseDataObject ibdo = new BaseDataObject();
1196
1197
1198 assertNotNull(ibdo.getCreationTimestamp());
1199 }
1200
1201 @Test
1202 void testDefaultConstructor_getSetDateTime() {
1203
1204 final Instant date = Instant.now();
1205
1206
1207 this.b.setCreationTimestamp(date);
1208
1209
1210 assertEquals(date, this.b.getCreationTimestamp());
1211 }
1212
1213 @Test
1214 void testNullTimestampSettingThrowsException() {
1215 assertThrows(IllegalArgumentException.class, () -> this.b.setCreationTimestamp(null));
1216 }
1217
1218 @Test
1219 void testNullDataAndChannel() {
1220 final BaseDataObject bdo = new BaseDataObject();
1221 assertNull(bdo.getChannelFactory());
1222 }
1223
1224 @Test
1225 void testSettingChannelFactoryWhenCurrentlyNull() throws IOException {
1226 final String testData = "This is a test";
1227 final SeekableByteChannelFactory sbcf = SeekableByteChannelHelper.memory(testData.getBytes());
1228 final BaseDataObject bdo = new BaseDataObject();
1229 bdo.setChannelFactory(sbcf);
1230 assertEquals(sbcf, bdo.getChannelFactory());
1231 }
1232
1233 @Test
1234 void testCanRetrieveChannelFactoryFromByteArray() throws IOException {
1235 final String testData = "This is a test";
1236 this.b.setData(testData.getBytes());
1237 final ByteBuffer buff = ByteBuffer.allocate(testData.length());
1238 final SeekableByteChannelFactory sbcf = this.b.getChannelFactory();
1239 sbcf.create().read(buff);
1240 assertArrayEquals(testData.getBytes(), buff.array());
1241 }
1242
1243 @Test
1244 void testBothDataFieldsHaveValue()
1245 throws IOException, NoSuchFieldException, IllegalAccessException {
1246 final BaseDataObject bdo = new BaseDataObject();
1247 final String testData = "This is a test";
1248 bdo.setChannelFactory(SeekableByteChannelHelper.memory(testData.getBytes()));
1249 Field theData = bdo.getClass().getDeclaredField("theData");
1250 theData.set(bdo, testData.getBytes());
1251
1252 final String msg = "Should throw an error when trying to access data on a BDO where we have a byte array and a channel";
1253
1254 assertThrows(IllegalStateException.class, () -> bdo.data(), msg);
1255 assertThrows(IllegalStateException.class, () -> bdo.getChannelFactory(), msg);
1256 assertThrows(IllegalStateException.class, () -> bdo.getChannelSize(), msg);
1257 assertThrows(IllegalStateException.class, () -> bdo.dataLength(), msg);
1258 }
1259
1260 @Test
1261 void testBasicDataMethods() throws IOException {
1262 final String testData = "This is a test";
1263 final byte[] testArray = testData.getBytes();
1264 final int testLength = testArray.length;
1265
1266
1267 byte[] existingData = this.b.data();
1268 assertEquals(testData, new String(existingData));
1269
1270
1271 ByteBuffer buff = ByteBuffer.allocate(testLength);
1272 this.b.getChannelFactory().create().read(buff);
1273 assertEquals(testData, new String(buff.array()));
1274
1275 final SeekableByteChannelFactory sbcf = InMemoryChannelFactory.create(testArray);
1276 this.b.setChannelFactory(sbcf);
1277
1278
1279 existingData = this.b.data();
1280 assertEquals(testData, new String(existingData));
1281
1282
1283 buff = ByteBuffer.allocate(testLength);
1284 this.b.getChannelFactory().create().read(buff);
1285 assertEquals(testData, new String(buff.array()));
1286 }
1287
1288 @Test
1289 void testSeekableByteChannelFactoryWithInvalidData() {
1290 assertThrows(NullPointerException.class, () -> this.b.setChannelFactory(null));
1291 }
1292
1293 @Test
1294 void testExtractedRecords() {
1295 final BaseDataObject other = new BaseDataObject();
1296 assertFalse(this.b.hasExtractedRecords(), "Expected no extracted records");
1297 assertNull(this.b.getExtractedRecords());
1298
1299 this.b.setExtractedRecords(new ArrayList<>());
1300 assertFalse(this.b.hasExtractedRecords(), "Expected no extracted records");
1301 assertNotNull(this.b.getExtractedRecords(), "Expected non-null extracted records");
1302 assertEquals(0, this.b.getExtractedRecords().size(), "Expected empty extracted records");
1303
1304 this.b.setExtractedRecords(Collections.<IBaseDataObject>singletonList(other));
1305 assertTrue(this.b.hasExtractedRecords(), "Expected extracted records");
1306 assertEquals(1, this.b.getExtractedRecords().size(), "Expected a single extracted record");
1307 assertEquals(1, this.b.getExtractedRecordCount(), "Expected a single extracted record");
1308
1309 assertThrows(IllegalArgumentException.class, () -> this.b.setExtractedRecords(null));
1310
1311 assertThrows(IllegalArgumentException.class, () -> this.b.addExtractedRecord(null));
1312
1313 this.b.addExtractedRecord(other);
1314 assertTrue(this.b.hasExtractedRecords(), "Expected extracted records");
1315 assertEquals(2, this.b.getExtractedRecords().size(), "Expected a two extracted record");
1316 assertEquals(2, this.b.getExtractedRecordCount(), "Expected a two extracted record");
1317
1318 this.b.addExtractedRecord(other);
1319 assertTrue(this.b.hasExtractedRecords(), "Expected extracted records");
1320 assertEquals(3, this.b.getExtractedRecords().size(), "Expected three extracted record");
1321 assertEquals(3, this.b.getExtractedRecordCount(), "Expected three extracted record");
1322
1323 this.b.clearExtractedRecords();
1324 assertFalse(this.b.hasExtractedRecords(), "Expected no extracted records");
1325 assertNull(this.b.getExtractedRecords());
1326
1327 final List<IBaseDataObject> list = new ArrayList<>();
1328 list.add(new BaseDataObject());
1329 list.add(null);
1330
1331 assertThrows(IllegalArgumentException.class, () -> this.b.setExtractedRecords(list));
1332
1333 assertThrows(IllegalArgumentException.class, () -> this.b.addExtractedRecords(list));
1334
1335 list.remove(1);
1336
1337 assertThrows(IllegalArgumentException.class, () -> this.b.addExtractedRecords(null));
1338
1339 this.b.addExtractedRecords(list);
1340 assertEquals(1, this.b.getExtractedRecordCount(), "Expect one extracted record");
1341
1342 this.b.addExtractedRecords(list);
1343 assertEquals(2, this.b.getExtractedRecordCount(), "Expect two extracted record");
1344
1345 final List<ExtendedDataObject> elist = new ArrayList<>();
1346 elist.add(new ExtendedDataObject());
1347 elist.add(new ExtendedDataObject());
1348
1349 this.b.addExtractedRecords(elist);
1350 assertEquals(4, this.b.getExtractedRecordCount(), "Expected extended records to be added");
1351
1352 }
1353
1354 @Test
1355 void testSetCurrentFormWithBoolean() {
1356 IBaseDataObject testIbdo = DataObjectFactory.getInstance(null, "dummy", "FORM-1");
1357 testIbdo.enqueueCurrentForm("FORM-2");
1358 testIbdo.enqueueCurrentForm("FORM-3");
1359
1360 assertEquals(3, testIbdo.currentFormSize(), "Form stack should have 3 forms before test");
1361 testIbdo.setCurrentForm("FINAL-FORM", true);
1362 assertEquals(1, testIbdo.currentFormSize(), "Form stack should have been cleared except for final set form");
1363 assertEquals("FINAL-FORM", testIbdo.currentForm(), "Form should be set to FINAL-FORM");
1364
1365 testIbdo.enqueueCurrentForm("FINAL-FORM-2");
1366 testIbdo.setCurrentForm("FINAL-FORM-3", false);
1367 assertEquals(2, testIbdo.currentFormSize(), "Form stack should be 2, since we didnt clear the entire stack");
1368 assertEquals("FINAL-FORM-3", testIbdo.currentFormAt(0), "Top of form stack should be form 3");
1369 assertEquals("FINAL-FORM-2", testIbdo.currentFormAt(1), "2nd form in stack should be form 2");
1370 }
1371
1372 @Test
1373 void testExtractedRecordClone() {
1374
1375 final List<IBaseDataObject> list = new ArrayList<>();
1376 list.add(new BaseDataObject());
1377 this.b.addExtractedRecords(list);
1378
1379 try {
1380 assertEquals(this.b.getExtractedRecordCount(), this.b.clone()
1381 .getExtractedRecordCount(), "Cloned IBDO should have same sized extracted record list");
1382 } catch (CloneNotSupportedException ex) {
1383 fail("Clone method should have been called", ex);
1384 }
1385 }
1386
1387 @Test
1388 void testNewInputStream() throws IOException {
1389 final IBaseDataObject ibdo = new BaseDataObject();
1390
1391 assertNull(ibdo.newInputStream());
1392
1393 final byte[] bytes1 = new byte[] {0, 1, 2, 3};
1394
1395 ibdo.setData(bytes1);
1396
1397 try (InputStream bytesInputStream = ibdo.newInputStream();
1398 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();) {
1399 IOUtils.copy(bytesInputStream, byteArrayOutputStream);
1400
1401 assertArrayEquals(bytes1, byteArrayOutputStream.toByteArray());
1402 }
1403
1404 final byte[] bytes2 = new byte[] {4, 5, 6, 7};
1405 final SeekableByteChannelFactory sbcf = SeekableByteChannelHelper.memory(bytes2);
1406
1407 ibdo.setChannelFactory(sbcf);
1408
1409 try (InputStream sbcfInputStream = ibdo.newInputStream();
1410 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
1411 IOUtils.copy(sbcfInputStream, byteArrayOutputStream);
1412
1413 assertArrayEquals(bytes2, byteArrayOutputStream.toByteArray());
1414 }
1415 }
1416
1417 @Test
1418 void testGetParameterAsString() throws IOException {
1419 assertNotNull(this.b);
1420
1421 try (LogbackTester logbackTester = new LogbackTester(BaseDataObject.class.getName())) {
1422 this.b.putParameter("A", 1L);
1423 this.b.appendParameter("A", "TWO");
1424 this.b.appendParameter("A", "THREE");
1425 assertEquals("1;TWO;THREE", this.b.getParameterAsString("A"));
1426 assertEquals("1;TWO;THREE", this.b.getParameterAsConcatString("A"));
1427 assertEquals("1;TWO;THREE", this.b.getStringParameter("A"));
1428 LogbackTester.SimplifiedLogEvent logEvent = new LogbackTester.SimplifiedLogEvent(Level.WARN,
1429 "Multiple values for parameter, parameter:A, number of values:3", null);
1430 logbackTester.checkLogList(Collections.singletonList(logEvent));
1431 }
1432
1433 this.b.putParameter("A", 2L);
1434 assertEquals("2", this.b.getParameterAsString("A"));
1435 assertEquals("2", this.b.getParameterAsConcatString("A"));
1436 assertEquals("2", this.b.getStringParameter("A"));
1437
1438 this.b.putParameter("A", "THREE");
1439 assertEquals("THREE", this.b.getParameterAsString("A"));
1440 assertEquals("THREE", this.b.getParameterAsConcatString("A"));
1441 assertEquals("THREE", this.b.getStringParameter("A"));
1442
1443 this.b.putParameter("A", null);
1444 assertNull(this.b.getParameterAsString("A"));
1445 assertNull(this.b.getParameterAsConcatString("A"));
1446 assertNull(this.b.getStringParameter("A"));
1447
1448 this.b.putParameter("A", "");
1449 assertEquals("", this.b.getParameterAsString("A"));
1450 assertEquals("", this.b.getParameterAsConcatString("A"));
1451 assertEquals("", this.b.getStringParameter("A"));
1452
1453 assertNull(this.b.getParameterAsString("DNE"));
1454 assertNull(this.b.getParameterAsConcatString("DNE"));
1455 assertNull(this.b.getStringParameter("DNE"));
1456
1457 this.b.putParameter("A", null);
1458 this.b.appendParameter("A", "FOUR");
1459 this.b.appendParameter("A", " ");
1460 assertEquals("null;FOUR; ", this.b.getParameterAsString("A"));
1461 assertEquals("null;FOUR; ", this.b.getParameterAsConcatString("A"));
1462 assertEquals("null;FOUR; ", this.b.getStringParameter("A"));
1463 }
1464
1465 }