KullaTesting.java revision 3738:6ef8a1453577
1/* 2 * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import java.io.ByteArrayInputStream; 25import java.io.ByteArrayOutputStream; 26import java.io.IOException; 27import java.io.InputStream; 28import java.io.PrintStream; 29import java.io.StringWriter; 30import java.lang.reflect.Method; 31import java.nio.file.Path; 32import java.util.ArrayList; 33import java.util.Arrays; 34import java.util.Collection; 35import java.util.Collections; 36import java.util.HashMap; 37import java.util.LinkedHashMap; 38import java.util.LinkedHashSet; 39import java.util.List; 40import java.util.Map; 41import java.util.Set; 42import java.util.TreeMap; 43import java.util.function.Consumer; 44import java.util.function.Predicate; 45import java.util.function.Supplier; 46import java.util.stream.Collectors; 47import java.util.stream.Stream; 48 49import javax.tools.Diagnostic; 50 51import jdk.jshell.EvalException; 52import jdk.jshell.JShell; 53import jdk.jshell.JShell.Subscription; 54import jdk.jshell.Snippet; 55import jdk.jshell.DeclarationSnippet; 56import jdk.jshell.ExpressionSnippet; 57import jdk.jshell.ImportSnippet; 58import jdk.jshell.Snippet.Kind; 59import jdk.jshell.MethodSnippet; 60import jdk.jshell.Snippet.Status; 61import jdk.jshell.Snippet.SubKind; 62import jdk.jshell.TypeDeclSnippet; 63import jdk.jshell.VarSnippet; 64import jdk.jshell.SnippetEvent; 65import jdk.jshell.SourceCodeAnalysis; 66import jdk.jshell.SourceCodeAnalysis.CompletionInfo; 67import jdk.jshell.SourceCodeAnalysis.Completeness; 68import jdk.jshell.SourceCodeAnalysis.QualifiedNames; 69import jdk.jshell.SourceCodeAnalysis.Suggestion; 70import jdk.jshell.UnresolvedReferenceException; 71import org.testng.annotations.AfterMethod; 72import org.testng.annotations.BeforeMethod; 73 74import jdk.jshell.Diag; 75 76import static java.util.stream.Collectors.toList; 77import static java.util.stream.Collectors.toSet; 78 79import static jdk.jshell.Snippet.Status.*; 80import static org.testng.Assert.*; 81import static jdk.jshell.Snippet.SubKind.METHOD_SUBKIND; 82import jdk.jshell.SourceCodeAnalysis.Documentation; 83 84public class KullaTesting { 85 86 public static final String IGNORE_VALUE = "<ignore-value>"; 87 public static final Class<? extends Throwable> IGNORE_EXCEPTION = (new Throwable() {}).getClass(); 88 public static final Snippet MAIN_SNIPPET; 89 90 private SourceCodeAnalysis analysis = null; 91 private JShell state = null; 92 private InputStream inStream = null; 93 private ByteArrayOutputStream outStream = null; 94 private ByteArrayOutputStream errStream = null; 95 96 private Map<String, Snippet> idToSnippet = new LinkedHashMap<>(); 97 private Set<Snippet> allSnippets = new LinkedHashSet<>(); 98 private List<String> classpath; 99 100 static { 101 JShell js = JShell.create(); 102 MAIN_SNIPPET = js.eval("MAIN_SNIPPET").get(0).snippet(); 103 js.close(); 104 assertTrue(MAIN_SNIPPET != null, "Bad MAIN_SNIPPET set-up -- must not be null"); 105 } 106 107 public enum DiagCheck { 108 DIAG_OK, 109 DIAG_WARNING, 110 DIAG_ERROR, 111 DIAG_IGNORE 112 } 113 114 public void setInput(String s) { 115 setInput(new ByteArrayInputStream(s.getBytes())); 116 } 117 118 public void setInput(InputStream in) { 119 inStream = in; 120 } 121 122 public String getOutput() { 123 String s = outStream.toString(); 124 outStream.reset(); 125 return s; 126 } 127 128 public String getErrorOutput() { 129 String s = errStream.toString(); 130 errStream.reset(); 131 return s; 132 } 133 134 /** 135 * @return the analysis 136 */ 137 public SourceCodeAnalysis getAnalysis() { 138 if (analysis == null) { 139 analysis = state.sourceCodeAnalysis(); 140 } 141 return analysis; 142 } 143 144 /** 145 * @return the state 146 */ 147 public JShell getState() { 148 return state; 149 } 150 151 public List<Snippet> getActiveKeys() { 152 return allSnippets.stream() 153 .filter(k -> getState().status(k).isActive()) 154 .collect(Collectors.toList()); 155 } 156 157 public void addToClasspath(String path) { 158 classpath.add(path); 159 getState().addToClasspath(path); 160 } 161 162 public void addToClasspath(Path path) { 163 addToClasspath(path.toString()); 164 } 165 166 @BeforeMethod 167 public void setUp() { 168 setUp(b -> {}); 169 } 170 171 public void setUp(Consumer<JShell.Builder> bc) { 172 InputStream in = new InputStream() { 173 @Override 174 public int read() throws IOException { 175 assertNotNull(inStream); 176 return inStream.read(); 177 } 178 @Override 179 public int read(byte[] b) throws IOException { 180 assertNotNull(inStream); 181 return inStream.read(b); 182 } 183 @Override 184 public int read(byte[] b, int off, int len) throws IOException { 185 assertNotNull(inStream); 186 return inStream.read(b, off, len); 187 } 188 }; 189 outStream = new ByteArrayOutputStream(); 190 errStream = new ByteArrayOutputStream(); 191 JShell.Builder builder = JShell.builder() 192 .in(in) 193 .out(new PrintStream(outStream)) 194 .err(new PrintStream(errStream)); 195 bc.accept(builder); 196 state = builder.build(); 197 allSnippets = new LinkedHashSet<>(); 198 idToSnippet = new LinkedHashMap<>(); 199 classpath = new ArrayList<>(); 200 } 201 202 @AfterMethod 203 public void tearDown() { 204 if (state != null) state.close(); 205 state = null; 206 analysis = null; 207 allSnippets = null; 208 idToSnippet = null; 209 classpath = null; 210 } 211 212 public List<String> assertUnresolvedDependencies(DeclarationSnippet key, int unresolvedSize) { 213 List<String> unresolved = getState().unresolvedDependencies(key).collect(toList()); 214 assertEquals(unresolved.size(), unresolvedSize, "Input: " + key.source() + ", checking unresolved: "); 215 return unresolved; 216 } 217 218 public DeclarationSnippet assertUnresolvedDependencies1(DeclarationSnippet key, Status status, String name) { 219 List<String> unresolved = assertUnresolvedDependencies(key, 1); 220 String input = key.source(); 221 assertEquals(unresolved.size(), 1, "Given input: " + input + ", checking unresolved"); 222 assertEquals(unresolved.get(0), name, "Given input: " + input + ", checking unresolved: "); 223 assertEquals(getState().status(key), status, "Given input: " + input + ", checking status: "); 224 return key; 225 } 226 227 public DeclarationSnippet assertEvalUnresolvedException(String input, String name, int unresolvedSize, int diagnosticsSize) { 228 List<SnippetEvent> events = assertEval(input, null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null); 229 SnippetEvent ste = events.get(0); 230 DeclarationSnippet sn = ((UnresolvedReferenceException) ste.exception()).getSnippet(); 231 assertEquals(sn.name(), name, "Given input: " + input + ", checking name"); 232 assertEquals(getState().unresolvedDependencies(sn).count(), unresolvedSize, "Given input: " + input + ", checking unresolved"); 233 assertEquals(getState().diagnostics(sn).count(), (long) diagnosticsSize, "Given input: " + input + ", checking diagnostics"); 234 return sn; 235 } 236 237 public Snippet assertKeyMatch(String input, boolean isExecutable, SubKind expectedSubKind, STEInfo mainInfo, STEInfo... updates) { 238 Snippet key = key(assertEval(input, IGNORE_VALUE, mainInfo, updates)); 239 String source = key.source(); 240 assertEquals(source, input, "Key \"" + input + "\" source mismatch, got: " + source + ", expected: " + input); 241 SubKind subkind = key.subKind(); 242 assertEquals(subkind, expectedSubKind, "Key \"" + input + "\" subkind mismatch, got: " 243 + subkind + ", expected: " + expectedSubKind); 244 assertEquals(subkind.isExecutable(), isExecutable, "Key \"" + input + "\", expected isExecutable: " 245 + isExecutable + ", got: " + subkind.isExecutable()); 246 Snippet.Kind expectedKind = getKind(key); 247 assertEquals(key.kind(), expectedKind, "Checking kind: "); 248 assertEquals(expectedSubKind.kind(), expectedKind, "Checking kind: "); 249 return key; 250 } 251 252 private Kind getKind(Snippet key) { 253 SubKind expectedSubKind = key.subKind(); 254 Kind expectedKind; 255 switch (expectedSubKind) { 256 case SINGLE_TYPE_IMPORT_SUBKIND: 257 case SINGLE_STATIC_IMPORT_SUBKIND: 258 case TYPE_IMPORT_ON_DEMAND_SUBKIND: 259 case STATIC_IMPORT_ON_DEMAND_SUBKIND: 260 expectedKind = Kind.IMPORT; 261 break; 262 case CLASS_SUBKIND: 263 case INTERFACE_SUBKIND: 264 case ENUM_SUBKIND: 265 case ANNOTATION_TYPE_SUBKIND: 266 expectedKind = Kind.TYPE_DECL; 267 break; 268 case METHOD_SUBKIND: 269 expectedKind = Kind.METHOD; 270 break; 271 case VAR_DECLARATION_SUBKIND: 272 case TEMP_VAR_EXPRESSION_SUBKIND: 273 case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND: 274 expectedKind = Kind.VAR; 275 break; 276 case VAR_VALUE_SUBKIND: 277 case ASSIGNMENT_SUBKIND: 278 expectedKind = Kind.EXPRESSION; 279 break; 280 case STATEMENT_SUBKIND: 281 expectedKind = Kind.STATEMENT; 282 break; 283 case UNKNOWN_SUBKIND: 284 expectedKind = Kind.ERRONEOUS; 285 break; 286 default: 287 throw new AssertionError("Unsupported key: " + key.getClass().getCanonicalName()); 288 } 289 return expectedKind; 290 } 291 292 public ImportSnippet assertImportKeyMatch(String input, String name, SubKind subkind, STEInfo mainInfo, STEInfo... updates) { 293 Snippet key = assertKeyMatch(input, false, subkind, mainInfo, updates); 294 295 assertTrue(key instanceof ImportSnippet, "Expected an ImportKey, got: " + key.getClass().getName()); 296 ImportSnippet importKey = (ImportSnippet) key; 297 assertEquals(importKey.name(), name, "Input \"" + input + 298 "\" name mismatch, got: " + importKey.name() + ", expected: " + name); 299 assertEquals(importKey.kind(), Kind.IMPORT, "Checking kind: "); 300 return importKey; 301 } 302 303 public DeclarationSnippet assertDeclarationKeyMatch(String input, boolean isExecutable, String name, SubKind subkind, STEInfo mainInfo, STEInfo... updates) { 304 Snippet key = assertKeyMatch(input, isExecutable, subkind, mainInfo, updates); 305 306 assertTrue(key instanceof DeclarationSnippet, "Expected a DeclarationKey, got: " + key.getClass().getName()); 307 DeclarationSnippet declKey = (DeclarationSnippet) key; 308 assertEquals(declKey.name(), name, "Input \"" + input + 309 "\" name mismatch, got: " + declKey.name() + ", expected: " + name); 310 return declKey; 311 } 312 313 public VarSnippet assertVarKeyMatch(String input, boolean isExecutable, String name, SubKind kind, String typeName, STEInfo mainInfo, STEInfo... updates) { 314 Snippet sn = assertDeclarationKeyMatch(input, isExecutable, name, kind, mainInfo, updates); 315 assertTrue(sn instanceof VarSnippet, "Expected a VarKey, got: " + sn.getClass().getName()); 316 VarSnippet variableKey = (VarSnippet) sn; 317 String signature = variableKey.typeName(); 318 assertEquals(signature, typeName, "Key \"" + input + 319 "\" typeName mismatch, got: " + signature + ", expected: " + typeName); 320 assertEquals(variableKey.kind(), Kind.VAR, "Checking kind: "); 321 return variableKey; 322 } 323 324 public void assertExpressionKeyMatch(String input, String name, SubKind kind, String typeName) { 325 Snippet key = assertKeyMatch(input, true, kind, added(VALID)); 326 assertTrue(key instanceof ExpressionSnippet, "Expected a ExpressionKey, got: " + key.getClass().getName()); 327 ExpressionSnippet exprKey = (ExpressionSnippet) key; 328 assertEquals(exprKey.name(), name, "Input \"" + input + 329 "\" name mismatch, got: " + exprKey.name() + ", expected: " + name); 330 assertEquals(exprKey.typeName(), typeName, "Key \"" + input + 331 "\" typeName mismatch, got: " + exprKey.typeName() + ", expected: " + typeName); 332 assertEquals(exprKey.kind(), Kind.EXPRESSION, "Checking kind: "); 333 } 334 335 // For expressions throwing an EvalException 336 public SnippetEvent assertEvalException(String input) { 337 List<SnippetEvent> events = assertEval(input, null, EvalException.class, 338 DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null); 339 return events.get(0); 340 } 341 342 343 public List<SnippetEvent> assertEvalFail(String input) { 344 return assertEval(input, null, null, 345 DiagCheck.DIAG_ERROR, DiagCheck.DIAG_IGNORE, added(REJECTED)); 346 } 347 348 public List<SnippetEvent> assertEval(String input) { 349 return assertEval(input, IGNORE_VALUE, null, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(VALID)); 350 } 351 352 public List<SnippetEvent> assertEval(String input, String value) { 353 return assertEval(input, value, null, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(VALID)); 354 } 355 356 public List<SnippetEvent> assertEval(String input, STEInfo mainInfo, STEInfo... updates) { 357 return assertEval(input, IGNORE_VALUE, null, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, mainInfo, updates); 358 } 359 360 public List<SnippetEvent> assertEval(String input, String value, 361 STEInfo mainInfo, STEInfo... updates) { 362 return assertEval(input, value, null, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, mainInfo, updates); 363 } 364 365 public List<SnippetEvent> assertEval(String input, DiagCheck diagMain, DiagCheck diagUpdates) { 366 return assertEval(input, IGNORE_VALUE, null, diagMain, diagUpdates, added(VALID)); 367 } 368 369 public List<SnippetEvent> assertEval(String input, DiagCheck diagMain, DiagCheck diagUpdates, 370 STEInfo mainInfo, STEInfo... updates) { 371 return assertEval(input, IGNORE_VALUE, null, diagMain, diagUpdates, mainInfo, updates); 372 } 373 374 public List<SnippetEvent> assertEval(String input, 375 String value, Class<? extends Throwable> exceptionClass, 376 DiagCheck diagMain, DiagCheck diagUpdates, 377 STEInfo mainInfo, STEInfo... updates) { 378 return assertEval(input, diagMain, diagUpdates, new EventChain(mainInfo, value, exceptionClass, updates)); 379 } 380 381 // Use this directly or usually indirectly for all non-empty calls to eval() 382 public List<SnippetEvent> assertEval(String input, 383 DiagCheck diagMain, DiagCheck diagUpdates, EventChain... eventChains) { 384 return checkEvents(() -> getState().eval(input), "eval(" + input + ")", diagMain, diagUpdates, eventChains); 385 } 386 387 <T> void assertStreamMatch(Stream<T> result, T... expected) { 388 Set<T> sns = result.collect(toSet()); 389 Set<T> exp = Stream.of(expected).collect(toSet()); 390 assertEquals(sns, exp); 391 } 392 393 private Map<Snippet, Snippet> closure(List<SnippetEvent> events) { 394 Map<Snippet, Snippet> transitions = new HashMap<>(); 395 for (SnippetEvent event : events) { 396 transitions.put(event.snippet(), event.causeSnippet()); 397 } 398 Map<Snippet, Snippet> causeSnippets = new HashMap<>(); 399 for (Map.Entry<Snippet, Snippet> entry : transitions.entrySet()) { 400 Snippet snippet = entry.getKey(); 401 Snippet cause = getInitialCause(transitions, entry.getValue()); 402 causeSnippets.put(snippet, cause); 403 } 404 return causeSnippets; 405 } 406 407 private Snippet getInitialCause(Map<Snippet, Snippet> transitions, Snippet snippet) { 408 Snippet result; 409 while ((result = transitions.get(snippet)) != null) { 410 snippet = result; 411 } 412 return snippet; 413 } 414 415 private Map<Snippet, List<SnippetEvent>> groupByCauseSnippet(List<SnippetEvent> events) { 416 Map<Snippet, List<SnippetEvent>> map = new TreeMap<>((a, b) -> a.id().compareTo(b.id())); 417 for (SnippetEvent event : events) { 418 if (event == null) { 419 throw new InternalError("null event found in " + events); 420 } 421 if (event.snippet() == null) { 422 throw new InternalError("null event Snippet found in " + events); 423 } 424 if (event.snippet().id() == null) { 425 throw new InternalError("null event Snippet id() found in " + events); 426 } 427 } 428 for (SnippetEvent event : events) { 429 if (event.causeSnippet() == null) { 430 map.computeIfAbsent(event.snippet(), ($) -> new ArrayList<>()).add(event); 431 } 432 } 433 Map<Snippet, Snippet> causeSnippets = closure(events); 434 for (SnippetEvent event : events) { 435 Snippet causeSnippet = causeSnippets.get(event.snippet()); 436 if (causeSnippet != null) { 437 map.get(causeSnippet).add(event); 438 } 439 } 440 for (Map.Entry<Snippet, List<SnippetEvent>> entry : map.entrySet()) { 441 Collections.sort(entry.getValue(), 442 (a, b) -> a.causeSnippet() == null 443 ? -1 : b.causeSnippet() == null 444 ? 1 : a.snippet().id().compareTo(b.snippet().id())); 445 } 446 return map; 447 } 448 449 private List<STEInfo> getInfos(EventChain... eventChains) { 450 List<STEInfo> list = new ArrayList<>(); 451 for (EventChain i : eventChains) { 452 list.add(i.mainInfo); 453 Collections.addAll(list, i.updates); 454 } 455 return list; 456 } 457 458 private List<SnippetEvent> checkEvents(Supplier<List<SnippetEvent>> toTest, 459 String descriptor, 460 DiagCheck diagMain, DiagCheck diagUpdates, 461 EventChain... eventChains) { 462 List<SnippetEvent> dispatched = new ArrayList<>(); 463 Subscription token = getState().onSnippetEvent(kse -> { 464 if (dispatched.size() > 0 && dispatched.get(dispatched.size() - 1) == null) { 465 throw new RuntimeException("dispatch event after done"); 466 } 467 dispatched.add(kse); 468 }); 469 List<SnippetEvent> events = toTest.get(); 470 getState().unsubscribe(token); 471 assertEquals(dispatched.size(), events.size(), "dispatched event size not the same as event size"); 472 for (int i = events.size() - 1; i >= 0; --i) { 473 assertEquals(dispatched.get(i), events.get(i), "Event element " + i + " does not match"); 474 } 475 dispatched.add(null); // mark end of dispatchs 476 477 for (SnippetEvent evt : events) { 478 assertTrue(evt.snippet() != null, "key must never be null, but it was for: " + descriptor); 479 assertTrue(evt.previousStatus() != null, "previousStatus must never be null, but it was for: " + descriptor); 480 assertTrue(evt.status() != null, "status must never be null, but it was for: " + descriptor); 481 assertTrue(evt.status() != NONEXISTENT, "status must not be NONEXISTENT: " + descriptor); 482 if (evt.previousStatus() != NONEXISTENT) { 483 Snippet old = idToSnippet.get(evt.snippet().id()); 484 if (old != null) { 485 switch (evt.status()) { 486 case DROPPED: 487 assertEquals(old, evt.snippet(), 488 "Drop: Old snippet must be what is dropped -- input: " + descriptor); 489 break; 490 case OVERWRITTEN: 491 assertEquals(old, evt.snippet(), 492 "Overwrite: Old snippet (" + old 493 + ") must be what is overwritten -- input: " 494 + descriptor + " -- " + evt); 495 break; 496 default: 497 if (evt.causeSnippet() == null) { 498 // New source 499 assertNotEquals(old, evt.snippet(), 500 "New source: Old snippet must be different from the replacing -- input: " 501 + descriptor); 502 } else { 503 // An update (key Overwrite??) 504 assertEquals(old, evt.snippet(), 505 "Update: Old snippet must be equal to the replacing -- input: " 506 + descriptor); 507 } 508 break; 509 } 510 } 511 } 512 } 513 for (SnippetEvent evt : events) { 514 if (evt.causeSnippet() == null && evt.status() != DROPPED) { 515 allSnippets.add(evt.snippet()); 516 idToSnippet.put(evt.snippet().id(), evt.snippet()); 517 } 518 } 519 assertTrue(events.size() >= 1, "Expected at least one event, got none."); 520 List<STEInfo> all = getInfos(eventChains); 521 if (events.size() != all.size()) { 522 StringBuilder sb = new StringBuilder(); 523 sb.append("Got events --\n"); 524 for (SnippetEvent evt : events) { 525 sb.append(" key: ").append(evt.snippet()); 526 sb.append(" before: ").append(evt.previousStatus()); 527 sb.append(" status: ").append(evt.status()); 528 sb.append(" isSignatureChange: ").append(evt.isSignatureChange()); 529 sb.append(" cause: "); 530 if (evt.causeSnippet() == null) { 531 sb.append("direct"); 532 } else { 533 sb.append(evt.causeSnippet()); 534 } 535 sb.append("\n"); 536 } 537 sb.append("Expected ").append(all.size()); 538 sb.append(" events, got: ").append(events.size()); 539 fail(sb.toString()); 540 } 541 542 int impactId = 0; 543 Map<Snippet, List<SnippetEvent>> groupedEvents = groupByCauseSnippet(events); 544 assertEquals(groupedEvents.size(), eventChains.length, "Number of main events"); 545 for (Map.Entry<Snippet, List<SnippetEvent>> entry : groupedEvents.entrySet()) { 546 EventChain eventChain = eventChains[impactId++]; 547 SnippetEvent main = entry.getValue().get(0); 548 Snippet mainKey = main.snippet(); 549 if (eventChain.mainInfo != null) { 550 eventChain.mainInfo.assertMatch(entry.getValue().get(0), mainKey); 551 if (eventChain.updates.length > 0) { 552 if (eventChain.updates.length == 1) { 553 eventChain.updates[0].assertMatch(entry.getValue().get(1), mainKey); 554 } else { 555 Arrays.sort(eventChain.updates, (a, b) -> ((a.snippet() == MAIN_SNIPPET) 556 ? mainKey 557 : a.snippet()).id().compareTo(b.snippet().id())); 558 List<SnippetEvent> updateEvents = new ArrayList<>(entry.getValue().subList(1, entry.getValue().size())); 559 int idx = 0; 560 for (SnippetEvent ste : updateEvents) { 561 eventChain.updates[idx++].assertMatch(ste, mainKey); 562 } 563 } 564 } 565 } 566 if (((Object) eventChain.value) != IGNORE_VALUE) { 567 assertEquals(main.value(), eventChain.value, "Expected execution value of: " + eventChain.value + 568 ", but got: " + main.value()); 569 } 570 if (eventChain.exceptionClass != IGNORE_EXCEPTION) { 571 if (main.exception() == null) { 572 assertEquals(eventChain.exceptionClass, null, "Expected an exception of class " 573 + eventChain.exceptionClass + " got no exception"); 574 } else if (eventChain.exceptionClass == null) { 575 fail("Expected no exception but got " + main.exception().toString()); 576 } else { 577 assertTrue(eventChain.exceptionClass.isInstance(main.exception()), 578 "Expected an exception of class " + eventChain.exceptionClass + 579 " got: " + main.exception().toString()); 580 } 581 } 582 List<Diag> diagnostics = getState().diagnostics(mainKey).collect(toList()); 583 switch (diagMain) { 584 case DIAG_OK: 585 assertEquals(diagnostics.size(), 0, "Expected no diagnostics, got: " + diagnosticsToString(diagnostics)); 586 break; 587 case DIAG_WARNING: 588 assertFalse(hasFatalError(diagnostics), "Expected no errors, got: " + diagnosticsToString(diagnostics)); 589 break; 590 case DIAG_ERROR: 591 assertTrue(hasFatalError(diagnostics), "Expected errors, got: " + diagnosticsToString(diagnostics)); 592 break; 593 } 594 if (eventChain.mainInfo != null) { 595 for (STEInfo ste : eventChain.updates) { 596 diagnostics = getState().diagnostics(ste.snippet()).collect(toList()); 597 switch (diagUpdates) { 598 case DIAG_OK: 599 assertEquals(diagnostics.size(), 0, "Expected no diagnostics, got: " + diagnosticsToString(diagnostics)); 600 break; 601 case DIAG_WARNING: 602 assertFalse(hasFatalError(diagnostics), "Expected no errors, got: " + diagnosticsToString(diagnostics)); 603 break; 604 } 605 } 606 } 607 } 608 return events; 609 } 610 611 // Use this for all EMPTY calls to eval() 612 public void assertEvalEmpty(String input) { 613 List<SnippetEvent> events = getState().eval(input); 614 assertEquals(events.size(), 0, "Expected no events, got: " + events.size()); 615 } 616 617 public VarSnippet varKey(List<SnippetEvent> events) { 618 Snippet key = key(events); 619 assertTrue(key instanceof VarSnippet, "Expected a VariableKey, got: " + key); 620 return (VarSnippet) key; 621 } 622 623 public MethodSnippet methodKey(List<SnippetEvent> events) { 624 Snippet key = key(events); 625 assertTrue(key instanceof MethodSnippet, "Expected a MethodKey, got: " + key); 626 return (MethodSnippet) key; 627 } 628 629 public TypeDeclSnippet classKey(List<SnippetEvent> events) { 630 Snippet key = key(events); 631 assertTrue(key instanceof TypeDeclSnippet, "Expected a ClassKey, got: " + key); 632 return (TypeDeclSnippet) key; 633 } 634 635 public ImportSnippet importKey(List<SnippetEvent> events) { 636 Snippet key = key(events); 637 assertTrue(key instanceof ImportSnippet, "Expected a ImportKey, got: " + key); 638 return (ImportSnippet) key; 639 } 640 641 public Snippet key(List<SnippetEvent> events) { 642 assertTrue(events.size() >= 1, "Expected at least one event, got none."); 643 return events.get(0).snippet(); 644 } 645 646 public void assertVarValue(Snippet key, String expected) { 647 String value = state.varValue((VarSnippet) key); 648 assertEquals(value, expected, "Expected var value of: " + expected + ", but got: " + value); 649 } 650 651 public Snippet assertDeclareFail(String input, String expectedErrorCode) { 652 return assertDeclareFail(input, expectedErrorCode, added(REJECTED)); 653 } 654 655 public Snippet assertDeclareFail(String input, String expectedErrorCode, 656 STEInfo mainInfo, STEInfo... updates) { 657 return assertDeclareFail(input, 658 new ExpectedDiagnostic(expectedErrorCode, -1, -1, -1, -1, -1, Diagnostic.Kind.ERROR), 659 mainInfo, updates); 660 } 661 662 public Snippet assertDeclareFail(String input, ExpectedDiagnostic expectedDiagnostic) { 663 return assertDeclareFail(input, expectedDiagnostic, added(REJECTED)); 664 } 665 666 public Snippet assertDeclareFail(String input, ExpectedDiagnostic expectedDiagnostic, 667 STEInfo mainInfo, STEInfo... updates) { 668 List<SnippetEvent> events = assertEval(input, null, null, 669 DiagCheck.DIAG_ERROR, DiagCheck.DIAG_IGNORE, mainInfo, updates); 670 SnippetEvent e = events.get(0); 671 Snippet key = e.snippet(); 672 assertEquals(getState().status(key), REJECTED); 673 List<Diag> diagnostics = getState().diagnostics(e.snippet()).collect(toList()); 674 assertTrue(diagnostics.size() > 0, "Expected diagnostics, got none"); 675 assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic); 676 assertTrue(key != null, "key must never be null, but it was for: " + input); 677 return key; 678 } 679 680 public Snippet assertDeclareWarn1(String input, String expectedErrorCode) { 681 return assertDeclareWarn1(input, new ExpectedDiagnostic(expectedErrorCode, -1, -1, -1, -1, -1, Diagnostic.Kind.WARNING)); 682 } 683 684 public Snippet assertDeclareWarn1(String input, ExpectedDiagnostic expectedDiagnostic) { 685 return assertDeclareWarn1(input, expectedDiagnostic, added(VALID)); 686 } 687 688 public Snippet assertDeclareWarn1(String input, ExpectedDiagnostic expectedDiagnostic, STEInfo mainInfo, STEInfo... updates) { 689 List<SnippetEvent> events = assertEval(input, IGNORE_VALUE, null, 690 DiagCheck.DIAG_WARNING, DiagCheck.DIAG_IGNORE, mainInfo, updates); 691 SnippetEvent e = events.get(0); 692 List<Diag> diagnostics = getState().diagnostics(e.snippet()).collect(toList()); 693 if (expectedDiagnostic != null) assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic); 694 return e.snippet(); 695 } 696 697 private void assertDiagnostic(String input, Diag diagnostic, ExpectedDiagnostic expectedDiagnostic) { 698 if (expectedDiagnostic != null) expectedDiagnostic.assertDiagnostic(diagnostic); 699 // assertEquals(diagnostic.getSource(), input, "Diagnostic source"); 700 } 701 702 public void assertTypeDeclSnippet(TypeDeclSnippet type, String expectedName, 703 Status expectedStatus, SubKind expectedSubKind, 704 int unressz, int othersz) { 705 assertDeclarationSnippet(type, expectedName, expectedStatus, 706 expectedSubKind, unressz, othersz); 707 } 708 709 public void assertMethodDeclSnippet(MethodSnippet method, 710 String expectedName, String expectedSignature, 711 Status expectedStatus, int unressz, int othersz) { 712 assertDeclarationSnippet(method, expectedName, expectedStatus, 713 METHOD_SUBKIND, unressz, othersz); 714 String signature = method.signature(); 715 assertEquals(signature, expectedSignature, 716 "Expected " + method.source() + " to have the name: " + 717 expectedSignature + ", got: " + signature); 718 } 719 720 public void assertVariableDeclSnippet(VarSnippet var, 721 String expectedName, String expectedTypeName, 722 Status expectedStatus, SubKind expectedSubKind, 723 int unressz, int othersz) { 724 assertDeclarationSnippet(var, expectedName, expectedStatus, 725 expectedSubKind, unressz, othersz); 726 String signature = var.typeName(); 727 assertEquals(signature, expectedTypeName, 728 "Expected " + var.source() + " to have the name: " + 729 expectedTypeName + ", got: " + signature); 730 } 731 732 public void assertDeclarationSnippet(DeclarationSnippet declarationKey, 733 String expectedName, 734 Status expectedStatus, SubKind expectedSubKind, 735 int unressz, int othersz) { 736 assertKey(declarationKey, expectedStatus, expectedSubKind); 737 String source = declarationKey.source(); 738 assertEquals(declarationKey.name(), expectedName, 739 "Expected " + source + " to have the name: " + expectedName + ", got: " + declarationKey.name()); 740 long unresolved = getState().unresolvedDependencies(declarationKey).count(); 741 assertEquals(unresolved, unressz, "Expected " + source + " to have " + unressz 742 + " unresolved symbols, got: " + unresolved); 743 long otherCorralledErrorsCount = getState().diagnostics(declarationKey).count(); 744 assertEquals(otherCorralledErrorsCount, othersz, "Expected " + source + " to have " + othersz 745 + " other errors, got: " + otherCorralledErrorsCount); 746 } 747 748 public void assertKey(Snippet key, Status expectedStatus, SubKind expectedSubKind) { 749 String source = key.source(); 750 SubKind actualSubKind = key.subKind(); 751 assertEquals(actualSubKind, expectedSubKind, 752 "Expected " + source + " to have the subkind: " + expectedSubKind + ", got: " + actualSubKind); 753 Status status = getState().status(key); 754 assertEquals(status, expectedStatus, "Expected " + source + " to be " 755 + expectedStatus + ", but it is " + status); 756 Snippet.Kind expectedKind = getKind(key); 757 assertEquals(key.kind(), expectedKind, "Checking kind: "); 758 assertEquals(expectedSubKind.kind(), expectedKind, "Checking kind: "); 759 } 760 761 public void assertDrop(Snippet key, STEInfo mainInfo, STEInfo... updates) { 762 assertDrop(key, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, mainInfo, updates); 763 } 764 765 public void assertDrop(Snippet key, DiagCheck diagMain, DiagCheck diagUpdates, STEInfo mainInfo, STEInfo... updates) { 766 assertDrop(key, diagMain, diagUpdates, new EventChain(mainInfo, null, null, updates)); 767 } 768 769 public void assertDrop(Snippet key, DiagCheck diagMain, DiagCheck diagUpdates, EventChain... eventChains) { 770 checkEvents(() -> getState().drop(key), "drop(" + key + ")", diagMain, diagUpdates, eventChains); 771 } 772 773 public void assertAnalyze(String input, String source, String remaining, boolean isComplete) { 774 assertAnalyze(input, null, source, remaining, isComplete); 775 } 776 777 public void assertAnalyze(String input, Completeness status, String source) { 778 assertAnalyze(input, status, source, null, null); 779 } 780 781 public void assertAnalyze(String input, Completeness status, String source, String remaining, Boolean isComplete) { 782 CompletionInfo ci = getAnalysis().analyzeCompletion(input); 783 if (status != null) assertEquals(ci.completeness(), status, "Input : " + input + ", status: "); 784 if (source != null) assertEquals(ci.source(), source, "Input : " + input + ", source: "); 785 if (remaining != null) assertEquals(ci.remaining(), remaining, "Input : " + input + ", remaining: "); 786 if (isComplete != null) { 787 boolean isExpectedComplete = isComplete; 788 assertEquals(ci.completeness().isComplete(), isExpectedComplete, "Input : " + input + ", isComplete: "); 789 } 790 } 791 792 public void assertNumberOfActiveVariables(int cnt) { 793 assertEquals(getState().variables().count(), cnt, "Variables : " + getState().variables().collect(toList())); 794 } 795 796 public void assertNumberOfActiveMethods(int cnt) { 797 assertEquals(getState().methods().count(), cnt, "Methods : " + getState().methods().collect(toList())); 798 } 799 800 public void assertNumberOfActiveClasses(int cnt) { 801 assertEquals(getState().types().count(), cnt, "Types : " + getState().types().collect(toList())); 802 } 803 804 public void assertKeys(MemberInfo... expected) { 805 int index = 0; 806 List<Snippet> snippets = getState().snippets().collect(toList()); 807 assertEquals(allSnippets.size(), snippets.size()); 808 for (Snippet sn : snippets) { 809 if (sn.kind().isPersistent() && getState().status(sn).isActive()) { 810 MemberInfo actual = getMemberInfo(sn); 811 MemberInfo exp = expected[index]; 812 assertEquals(actual, exp, String.format("Difference in #%d. Expected: %s, actual: %s", 813 index, exp, actual)); 814 ++index; 815 } 816 } 817 } 818 819 public void assertActiveKeys() { 820 Collection<Snippet> expected = getActiveKeys(); 821 assertActiveKeys(expected.toArray(new Snippet[expected.size()])); 822 } 823 824 public void assertActiveKeys(Snippet... expected) { 825 int index = 0; 826 for (Snippet key : getState().snippets().collect(toList())) { 827 if (state.status(key).isActive()) { 828 assertEquals(expected[index], key, String.format("Difference in #%d. Expected: %s, actual: %s", index, key, expected[index])); 829 ++index; 830 } 831 } 832 } 833 834 private void assertActiveSnippets(Stream<? extends Snippet> snippets, Predicate<Snippet> p, String label) { 835 Set<Snippet> active = getActiveKeys().stream() 836 .filter(p) 837 .collect(Collectors.toSet()); 838 Set<Snippet> got = snippets 839 .collect(Collectors.toSet()); 840 assertEquals(active, got, label); 841 } 842 843 public void assertVariables() { 844 assertActiveSnippets(getState().variables(), (key) -> key instanceof VarSnippet, "Variables"); 845 } 846 847 public void assertMethods() { 848 assertActiveSnippets(getState().methods(), (key) -> key instanceof MethodSnippet, "Methods"); 849 } 850 851 public void assertClasses() { 852 assertActiveSnippets(getState().types(), (key) -> key instanceof TypeDeclSnippet, "Classes"); 853 } 854 855 public void assertMembers(Stream<? extends Snippet> members, MemberInfo...expectedInfos) { 856 Set<MemberInfo> expected = Stream.of(expectedInfos).collect(Collectors.toSet()); 857 Set<MemberInfo> got = members 858 .map(this::getMemberInfo) 859 .collect(Collectors.toSet()); 860 assertEquals(got.size(), expected.size(), "Expected : " + expected + ", actual : " + members); 861 assertEquals(got, expected); 862 } 863 864 public void assertVariables(MemberInfo...expected) { 865 assertMembers(getState().variables(), expected); 866 } 867 868 public void assertMethods(MemberInfo...expected) { 869 assertMembers(getState().methods(), expected); 870 getState().methods().forEach(methodKey -> { 871 MemberInfo expectedInfo = null; 872 for (MemberInfo info : expected) { 873 if (info.name.equals(methodKey.name()) && info.type.equals(methodKey.signature())) { 874 expectedInfo = getMemberInfo(methodKey); 875 } 876 } 877 assertNotNull(expectedInfo, "Not found method: " + methodKey.name()); 878 int lastIndexOf = expectedInfo.type.lastIndexOf(')'); 879 assertEquals(methodKey.parameterTypes(), expectedInfo.type.substring(1, lastIndexOf), "Parameter types"); 880 }); 881 } 882 883 public void assertClasses(MemberInfo...expected) { 884 assertMembers(getState().types(), expected); 885 } 886 887 public void assertCompletion(String code, String... expected) { 888 assertCompletion(code, null, expected); 889 } 890 891 public void assertCompletion(String code, Boolean isSmart, String... expected) { 892 List<String> completions = computeCompletions(code, isSmart); 893 assertEquals(completions, Arrays.asList(expected), "Input: " + code + ", " + completions.toString()); 894 } 895 896 public void assertCompletionIncludesExcludes(String code, Set<String> expected, Set<String> notExpected) { 897 assertCompletionIncludesExcludes(code, null, expected, notExpected); 898 } 899 900 public void assertCompletionIncludesExcludes(String code, Boolean isSmart, Set<String> expected, Set<String> notExpected) { 901 List<String> completions = computeCompletions(code, isSmart); 902 assertTrue(completions.containsAll(expected), String.valueOf(completions)); 903 assertTrue(Collections.disjoint(completions, notExpected), String.valueOf(completions)); 904 } 905 906 private List<String> computeCompletions(String code, Boolean isSmart) { 907 waitIndexingFinished(); 908 909 int cursor = code.indexOf('|'); 910 code = code.replace("|", ""); 911 assertTrue(cursor > -1, "'|' expected, but not found in: " + code); 912 List<Suggestion> completions = 913 getAnalysis().completionSuggestions(code, cursor, new int[1]); //XXX: ignoring anchor for now 914 return completions.stream() 915 .filter(s -> isSmart == null || isSmart == s.matchesType()) 916 .map(s -> s.continuation()) 917 .distinct() 918 .collect(Collectors.toList()); 919 } 920 921 public void assertInferredType(String code, String expectedType) { 922 String inferredType = getAnalysis().analyzeType(code, code.length()); 923 924 assertEquals(inferredType, expectedType, "Input: " + code + ", " + inferredType); 925 } 926 927 public void assertInferredFQNs(String code, String... fqns) { 928 assertInferredFQNs(code, code.length(), false, fqns); 929 } 930 931 public void assertInferredFQNs(String code, int simpleNameLen, boolean resolvable, String... fqns) { 932 waitIndexingFinished(); 933 934 QualifiedNames candidates = getAnalysis().listQualifiedNames(code, code.length()); 935 936 assertEquals(candidates.getNames(), Arrays.asList(fqns), "Input: " + code + ", candidates=" + candidates.getNames()); 937 assertEquals(candidates.getSimpleNameLength(), simpleNameLen, "Input: " + code + ", simpleNameLen=" + candidates.getSimpleNameLength()); 938 assertEquals(candidates.isResolvable(), resolvable, "Input: " + code + ", resolvable=" + candidates.isResolvable()); 939 } 940 941 protected void waitIndexingFinished() { 942 try { 943 Method waitBackgroundTaskFinished = getAnalysis().getClass().getDeclaredMethod("waitBackgroundTaskFinished"); 944 945 waitBackgroundTaskFinished.setAccessible(true); 946 waitBackgroundTaskFinished.invoke(getAnalysis()); 947 } catch (Exception ex) { 948 throw new AssertionError("Cannot wait for indexing end.", ex); 949 } 950 } 951 952 public void assertSignature(String code, String... expected) { 953 int cursor = code.indexOf('|'); 954 code = code.replace("|", ""); 955 assertTrue(cursor > -1, "'|' expected, but not found in: " + code); 956 List<Documentation> documentation = getAnalysis().documentation(code, cursor, false); 957 Set<String> docSet = documentation.stream().map(doc -> doc.signature()).collect(Collectors.toSet()); 958 Set<String> expectedSet = Stream.of(expected).collect(Collectors.toSet()); 959 assertEquals(docSet, expectedSet, "Input: " + code); 960 } 961 962 public void assertJavadoc(String code, String... expected) { 963 int cursor = code.indexOf('|'); 964 code = code.replace("|", ""); 965 assertTrue(cursor > -1, "'|' expected, but not found in: " + code); 966 List<Documentation> documentation = getAnalysis().documentation(code, cursor, true); 967 Set<String> docSet = documentation.stream() 968 .map(doc -> doc.signature() + "\n" + doc.javadoc()) 969 .collect(Collectors.toSet()); 970 Set<String> expectedSet = Stream.of(expected).collect(Collectors.toSet()); 971 assertEquals(docSet, expectedSet, "Input: " + code); 972 } 973 974 public enum ClassType { 975 CLASS("CLASS_SUBKIND", "class", "class"), 976 ENUM("ENUM_SUBKIND", "enum", "enum"), 977 INTERFACE("INTERFACE_SUBKIND", "interface", "interface"), 978 ANNOTATION("ANNOTATION_TYPE_SUBKIND", "@interface", "annotation interface"); 979 980 private final String classType; 981 private final String name; 982 private final String displayed; 983 984 ClassType(String classType, String name, String displayed) { 985 this.classType = classType; 986 this.name = name; 987 this.displayed = displayed; 988 } 989 990 public String getClassType() { 991 return classType; 992 } 993 994 public String getDisplayed() { 995 return displayed; 996 } 997 998 @Override 999 public String toString() { 1000 return name; 1001 } 1002 } 1003 1004 public static MemberInfo variable(String type, String name) { 1005 return new MemberInfo(type, name); 1006 } 1007 1008 public static MemberInfo method(String signature, String name) { 1009 return new MemberInfo(signature, name); 1010 } 1011 1012 public static MemberInfo clazz(ClassType classType, String className) { 1013 return new MemberInfo(classType.getClassType(), className); 1014 } 1015 1016 public static class MemberInfo { 1017 public final String type; 1018 public final String name; 1019 1020 public MemberInfo(String type, String name) { 1021 this.type = type; 1022 this.name = name; 1023 } 1024 1025 @Override 1026 public int hashCode() { 1027 return type.hashCode() + 3 * name.hashCode(); 1028 } 1029 1030 @Override 1031 public boolean equals(Object o) { 1032 if (o instanceof MemberInfo) { 1033 MemberInfo other = (MemberInfo) o; 1034 return type.equals(other.type) && name.equals(other.name); 1035 } 1036 return false; 1037 } 1038 1039 @Override 1040 public String toString() { 1041 return String.format("%s %s", type, name); 1042 } 1043 } 1044 1045 public MemberInfo getMemberInfo(Snippet key) { 1046 SubKind subkind = key.subKind(); 1047 switch (subkind) { 1048 case CLASS_SUBKIND: 1049 case INTERFACE_SUBKIND: 1050 case ENUM_SUBKIND: 1051 case ANNOTATION_TYPE_SUBKIND: 1052 return new MemberInfo(subkind.name(), ((DeclarationSnippet) key).name()); 1053 case METHOD_SUBKIND: 1054 MethodSnippet method = (MethodSnippet) key; 1055 return new MemberInfo(method.signature(), method.name()); 1056 case VAR_DECLARATION_SUBKIND: 1057 case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND: 1058 case TEMP_VAR_EXPRESSION_SUBKIND: 1059 VarSnippet var = (VarSnippet) key; 1060 return new MemberInfo(var.typeName(), var.name()); 1061 default: 1062 throw new AssertionError("Unknown snippet : " + key.kind() + " in expression " + key.toString()); 1063 } 1064 } 1065 1066 public String diagnosticsToString(List<Diag> diagnostics) { 1067 StringWriter writer = new StringWriter(); 1068 for (Diag diag : diagnostics) { 1069 writer.write("Error --\n"); 1070 for (String line : diag.getMessage(null).split("\\r?\\n")) { 1071 writer.write(String.format("%s\n", line)); 1072 } 1073 } 1074 return writer.toString().replace("\n", System.lineSeparator()); 1075 } 1076 1077 public boolean hasFatalError(List<Diag> diagnostics) { 1078 for (Diag diag : diagnostics) { 1079 if (diag.isError()) { 1080 return true; 1081 } 1082 } 1083 return false; 1084 } 1085 1086 public static EventChain chain(STEInfo mainInfo, STEInfo... updates) { 1087 return chain(mainInfo, IGNORE_VALUE, null, updates); 1088 } 1089 1090 public static EventChain chain(STEInfo mainInfo, String value, Class<? extends Throwable> exceptionClass, STEInfo... updates) { 1091 return new EventChain(mainInfo, value, exceptionClass, updates); 1092 } 1093 1094 public static STEInfo ste(Snippet key, Status previousStatus, Status status, 1095 Boolean isSignatureChange, Snippet causeKey) { 1096 return new STEInfo(key, previousStatus, status, isSignatureChange, causeKey); 1097 } 1098 1099 public static STEInfo added(Status status) { 1100 return new STEInfo(MAIN_SNIPPET, NONEXISTENT, status, status.isDefined(), null); 1101 } 1102 1103 public static class EventChain { 1104 public final STEInfo mainInfo; 1105 public final STEInfo[] updates; 1106 public final String value; 1107 public final Class<? extends Throwable> exceptionClass; 1108 1109 public EventChain(STEInfo mainInfo, String value, Class<? extends Throwable> exceptionClass, STEInfo... updates) { 1110 this.mainInfo = mainInfo; 1111 this.updates = updates; 1112 this.value = value; 1113 this.exceptionClass = exceptionClass; 1114 } 1115 } 1116 1117 public static class STEInfo { 1118 1119 STEInfo(Snippet snippet, Status previousStatus, Status status, 1120 Boolean isSignatureChange, Snippet causeSnippet) { 1121 this.snippet = snippet; 1122 this.previousStatus = previousStatus; 1123 this.status = status; 1124 this.checkIsSignatureChange = isSignatureChange != null; 1125 this.isSignatureChange = checkIsSignatureChange ? isSignatureChange : false; 1126 this.causeSnippet = causeSnippet; 1127 assertTrue(snippet != null, "Bad test set-up. The match snippet must not be null"); 1128 } 1129 1130 final Snippet snippet; 1131 final Status previousStatus; 1132 final Status status; 1133 final boolean isSignatureChange; 1134 final Snippet causeSnippet; 1135 1136 final boolean checkIsSignatureChange; 1137 public Snippet snippet() { 1138 return snippet; 1139 } 1140 public Status previousStatus() { 1141 return previousStatus; 1142 } 1143 public Status status() { 1144 return status; 1145 } 1146 public boolean isSignatureChange() { 1147 if (!checkIsSignatureChange) { 1148 throw new IllegalStateException("isSignatureChange value is undefined"); 1149 } 1150 return isSignatureChange; 1151 } 1152 public Snippet causeSnippet() { 1153 return causeSnippet; 1154 } 1155 public String value() { 1156 return null; 1157 } 1158 public Exception exception() { 1159 return null; 1160 } 1161 1162 public void assertMatch(SnippetEvent ste, Snippet mainSnippet) { 1163 assertKeyMatch(ste, ste.snippet(), snippet(), mainSnippet); 1164 assertStatusMatch(ste, ste.previousStatus(), previousStatus()); 1165 assertStatusMatch(ste, ste.status(), status()); 1166 if (checkIsSignatureChange) { 1167 assertEquals(ste.isSignatureChange(), isSignatureChange(), 1168 "Expected " + 1169 (isSignatureChange()? "" : "no ") + 1170 "signature-change, got: " + 1171 (ste.isSignatureChange()? "" : "no ") + 1172 "signature-change" + 1173 "\n expected-event: " + this + "\n got-event: " + toString(ste)); 1174 } 1175 assertKeyMatch(ste, ste.causeSnippet(), causeSnippet(), mainSnippet); 1176 } 1177 1178 private void assertKeyMatch(SnippetEvent ste, Snippet sn, Snippet expected, Snippet mainSnippet) { 1179 Snippet testKey = expected; 1180 if (testKey != null) { 1181 if (expected == MAIN_SNIPPET) { 1182 assertNotNull(mainSnippet, "MAIN_SNIPPET used, test must pass value to assertMatch"); 1183 testKey = mainSnippet; 1184 } 1185 if (ste.causeSnippet() == null && ste.status() != DROPPED && expected != MAIN_SNIPPET) { 1186 // Source change, always new snippet -- only match id() 1187 assertTrue(sn != testKey, 1188 "Main-event: Expected new snippet to be != : " + testKey 1189 + "\n got-event: " + toString(ste)); 1190 assertEquals(sn.id(), testKey.id(), "Expected IDs to match: " + testKey + ", got: " + sn 1191 + "\n expected-event: " + this + "\n got-event: " + toString(ste)); 1192 } else { 1193 assertEquals(sn, testKey, "Expected key to be: " + testKey + ", got: " + sn 1194 + "\n expected-event: " + this + "\n got-event: " + toString(ste)); 1195 } 1196 } 1197 } 1198 1199 private void assertStatusMatch(SnippetEvent ste, Status status, Status expected) { 1200 if (expected != null) { 1201 assertEquals(status, expected, "Expected status to be: " + expected + ", got: " + status + 1202 "\n expected-event: " + this + "\n got-event: " + toString(ste)); 1203 } 1204 } 1205 1206 @Override 1207 public String toString() { 1208 return "STEInfo key: " + 1209 (snippet()==MAIN_SNIPPET? "MAIN_SNIPPET" : (snippet()==null? "ignore" : snippet().id())) + 1210 " before: " + previousStatus() + 1211 " status: " + status() + " sig: " + isSignatureChange() + 1212 " cause: " + (causeSnippet()==null? "null" : causeSnippet().id()); 1213 } 1214 1215 private String toString(SnippetEvent ste) { 1216 return "key: " + (ste.snippet()==MAIN_SNIPPET? "MAIN_SNIPPET" : ste.snippet().id()) + " before: " + ste.previousStatus() 1217 + " status: " + ste.status() + " sig: " + ste.isSignatureChange() 1218 + " cause: " + ste.causeSnippet(); 1219 } 1220 } 1221} 1222