1 package emissary.test.core.junit5;
2
3 import emissary.core.BaseDataObject;
4 import emissary.core.IBaseDataObject;
5 import emissary.core.IBaseDataObjectHelper;
6 import emissary.core.IBaseDataObjectXmlCodecs;
7 import emissary.core.IBaseDataObjectXmlCodecs.ElementDecoders;
8 import emissary.core.IBaseDataObjectXmlCodecs.ElementEncoders;
9 import emissary.place.IServiceProviderPlace;
10 import emissary.test.core.junit5.LogbackTester.SimplifiedLogEvent;
11 import emissary.util.ByteUtil;
12
13 import com.google.errorprone.annotations.ForOverride;
14 import org.apache.commons.lang3.ArrayUtils;
15 import org.jdom2.Document;
16 import org.junit.jupiter.params.ParameterizedTest;
17 import org.junit.jupiter.params.provider.MethodSource;
18
19 import java.nio.charset.StandardCharsets;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Map.Entry;
23 import java.util.Optional;
24 import java.util.TreeMap;
25
26 import static org.junit.jupiter.api.Assertions.fail;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public abstract class RegressionTest extends ExtractionTest {
51
52
53
54 protected List<SimplifiedLogEvent> actualSimplifiedLogEvents;
55
56
57
58
59
60
61
62 @ForOverride
63 protected boolean generateAnswers() {
64 return Boolean.getBoolean("generateAnswers");
65 }
66
67
68
69
70
71
72
73
74
75 @ForOverride
76 protected IBaseDataObject getInitialIbdo(final String resource) {
77 return RegressionTestUtil.getInitialIbdoWithFormInFilename(new ClearDataBaseDataObject(), resource, kff);
78 }
79
80
81
82
83
84
85
86
87
88
89 @ForOverride
90 protected void tweakInitialIbdoBeforeSerialisation(final String resource, final IBaseDataObject initialIbdo) {
91 if (initialIbdo instanceof ClearDataBaseDataObject) {
92 ((ClearDataBaseDataObject) initialIbdo).clearData();
93 } else {
94 fail("Didn't get an expected type of IBaseDataObject");
95 }
96 }
97
98
99
100
101
102
103
104
105
106
107
108 @ForOverride
109 protected void tweakFinalIbdoBeforeSerialisation(final String resource, final IBaseDataObject finalIbdo) {
110 RegressionTestUtil.tweakFinalIbdoWithFormInFilename(resource, finalIbdo);
111 }
112
113
114
115
116
117
118
119
120
121 @ForOverride
122 protected void tweakFinalResultsBeforeSerialisation(final String resource, final List<IBaseDataObject> children) {
123
124 }
125
126
127
128
129
130
131
132
133
134 @ForOverride
135 protected void tweakFinalLogEventsBeforeSerialisation(final String resource, final List<SimplifiedLogEvent> simplifiedLogEvents) {
136
137 }
138
139 @Override
140 @ForOverride
141 protected String getInitialForm(final String resource) {
142 return RegressionTestUtil.getInitialFormFromFilename(resource);
143 }
144
145
146
147
148
149
150 protected ElementDecoders getDecoders() {
151 return IBaseDataObjectXmlCodecs.DEFAULT_ELEMENT_DECODERS;
152 }
153
154
155
156
157
158
159 protected ElementEncoders getEncoders() {
160 return IBaseDataObjectXmlCodecs.SHA256_ELEMENT_ENCODERS;
161 }
162
163
164
165
166
167
168
169
170 @Override
171 protected void checkAnswersPreHook(final Document answers, final IBaseDataObject payload, final List<IBaseDataObject> attachments,
172 final String tname) {
173
174 if (getLogbackLoggerName() != null) {
175 checkAnswersPreHookLogEvents(actualSimplifiedLogEvents);
176 }
177
178 if (!IBaseDataObjectXmlCodecs.SHA256_ELEMENT_ENCODERS.equals(getEncoders())) {
179 return;
180 }
181
182
183 for (Entry<String, byte[]> entry : new TreeMap<>(payload.getAlternateViews()).entrySet()) {
184 Optional<String> viewSha256 = hashBytesIfNonPrintable(entry.getValue());
185 viewSha256.ifPresent(s -> payload.addAlternateView(entry.getKey(), s.getBytes(StandardCharsets.UTF_8)));
186 }
187
188
189 Optional<String> payloadSha256 = hashBytesIfNonPrintable(payload.data());
190 payloadSha256.ifPresent(s -> payload.setData(s.getBytes(StandardCharsets.UTF_8)));
191
192 if (payload.getExtractedRecords() != null) {
193 for (final IBaseDataObject extractedRecord : payload.getExtractedRecords()) {
194 Optional<String> recordSha256 = hashBytesIfNonPrintable(extractedRecord.data());
195 recordSha256.ifPresent(s -> extractedRecord.setData(s.getBytes(StandardCharsets.UTF_8)));
196 }
197 }
198
199 if (attachments != null) {
200 for (final IBaseDataObject attachment : attachments) {
201 if (ByteUtil.hasNonPrintableValues(attachment.data())) {
202 Optional<String> attachmentSha256 = hashBytesIfNonPrintable(attachment.data());
203 attachmentSha256.ifPresent(s -> attachment.setData(s.getBytes(StandardCharsets.UTF_8)));
204 }
205 }
206 }
207 }
208
209
210
211
212
213
214 protected String getLogbackLoggerName() {
215 return null;
216 }
217
218
219
220
221
222
223
224
225 protected void checkAnswersPreHookLogEvents(List<SimplifiedLogEvent> simplifiedLogEvents) {
226
227 }
228
229
230
231
232
233
234
235 protected Optional<String> hashBytesIfNonPrintable(byte[] bytes) {
236 if (ArrayUtils.isNotEmpty(bytes) && ByteUtil.containsNonIndexableBytes(bytes)) {
237 return Optional.ofNullable(ByteUtil.sha256Bytes(bytes));
238 }
239
240 return Optional.empty();
241 }
242
243 protected static class ClearDataBaseDataObject extends BaseDataObject {
244 private static final long serialVersionUID = -8728006876784881020L;
245
246 protected void clearData() {
247 theData = null;
248 seekableByteChannelFactory = null;
249 }
250 }
251
252 @ParameterizedTest
253 @MethodSource("data")
254 @Override
255 public void testExtractionPlace(final String resource) {
256 logger.debug("Running {} test on resource {}", place.getClass().getName(), resource);
257
258 if (generateAnswers()) {
259 try {
260 generateAnswerFiles(resource);
261 } catch (final Exception e) {
262 logger.error("Error running test {}", resource, e);
263 fail("Unable to generate answer file", e);
264 }
265 }
266
267
268 super.testExtractionPlace(resource);
269 }
270
271
272
273
274
275
276
277
278
279 protected void generateAnswerFiles(final String resource) throws Exception {
280
281 final IBaseDataObject initialIbdo = getInitialIbdo(resource);
282
283 final IBaseDataObject finalIbdo = IBaseDataObjectHelper.clone(initialIbdo, true);
284
285 final List<IBaseDataObject> finalResults;
286 final List<SimplifiedLogEvent> finalLogEvents;
287 if (getLogbackLoggerName() == null) {
288 finalResults = place.agentProcessHeavyDuty(finalIbdo);
289 finalLogEvents = new ArrayList<>();
290 } else {
291 try (LogbackTester logbackTester = new LogbackTester(getLogbackLoggerName())) {
292 finalResults = place.agentProcessHeavyDuty(finalIbdo);
293 finalLogEvents = logbackTester.getSimplifiedLogEvents();
294 }
295 }
296
297
298 tweakInitialIbdoBeforeSerialisation(resource, initialIbdo);
299 tweakFinalIbdoBeforeSerialisation(resource, finalIbdo);
300 tweakFinalResultsBeforeSerialisation(resource, finalResults);
301 tweakFinalLogEventsBeforeSerialisation(resource, finalLogEvents);
302
303
304 RegressionTestUtil.writeAnswerXml(resource, initialIbdo, finalIbdo, finalResults, finalLogEvents, getEncoders(),
305 super.answerFileClassRef);
306 }
307
308 @Override
309 protected List<IBaseDataObject> processHeavyDutyHook(IServiceProviderPlace place, IBaseDataObject payload)
310 throws Exception {
311 if (getLogbackLoggerName() == null) {
312 actualSimplifiedLogEvents = new ArrayList<>();
313
314 return super.processHeavyDutyHook(place, payload);
315 } else {
316 try (LogbackTester logbackTester = new LogbackTester(getLogbackLoggerName())) {
317 final List<IBaseDataObject> attachments = super.processHeavyDutyHook(place, payload);
318
319 actualSimplifiedLogEvents = logbackTester.getSimplifiedLogEvents();
320
321 return attachments;
322 }
323 }
324 }
325
326 @Override
327 protected Document getAnswerDocumentFor(final String resource) {
328
329 return generateAnswers() ? RegressionTestUtil.getAnswerDocumentFor(resource, super.answerFileClassRef) : super.getAnswerDocumentFor(resource);
330 }
331
332 @Override
333 protected void setupPayload(final IBaseDataObject payload, final Document answers) {
334 RegressionTestUtil.setupPayload(payload, answers, getDecoders());
335 }
336
337 @Override
338 protected void checkAnswers(final Document answers, final IBaseDataObject payload,
339 final List<IBaseDataObject> attachments, final String tname) {
340 RegressionTestUtil.checkAnswers(answers, payload, actualSimplifiedLogEvents, attachments, place.getClass().getName(), getDecoders(),
341 generateAnswers());
342 }
343 }