KullaTesting.java revision 4104:4012b3f11f0d
138032Speter/*
2261370Sgshapiro * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
364562Sgshapiro * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
438032Speter *
538032Speter * This code is free software; you can redistribute it and/or modify it
638032Speter * under the terms of the GNU General Public License version 2 only, as
738032Speter * published by the Free Software Foundation.
838032Speter *
938032Speter * This code is distributed in the hope that it will be useful, but WITHOUT
1038032Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1138032Speter * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1238032Speter * version 2 for more details (a copy is included in the LICENSE file that
1338032Speter * accompanied this code).
1464562Sgshapiro *
1590792Sgshapiro * You should have received a copy of the GNU General Public License version
16132943Sgshapiro * 2 along with this work; if not, write to the Free Software Foundation,
1790792Sgshapiro * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1890792Sgshapiro *
1964562Sgshapiro * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20266711Sgshapiro * or visit www.oracle.com if you need additional information or have any
2164562Sgshapiro * questions.
22157001Sgshapiro */
23132943Sgshapiro
24132943Sgshapiroimport java.io.ByteArrayInputStream;
2590792Sgshapiroimport java.io.ByteArrayOutputStream;
2690792Sgshapiroimport java.io.IOException;
2790792Sgshapiroimport java.io.InputStream;
2890792Sgshapiroimport java.io.PrintStream;
2990792Sgshapiroimport java.io.StringWriter;
3064562Sgshapiroimport java.lang.reflect.Method;
3190792Sgshapiroimport java.lang.module.Configuration;
3290792Sgshapiroimport java.lang.module.ModuleFinder;
33244928Sgshapiroimport java.nio.file.Paths;
3490792Sgshapiroimport java.nio.file.Path;
3538032Speterimport java.util.ArrayList;
3690792Sgshapiroimport java.util.Arrays;
3790792Sgshapiroimport java.util.Collection;
3838032Speterimport java.util.Collections;
3990792Sgshapiroimport java.util.HashMap;
4090792Sgshapiroimport java.util.LinkedHashMap;
4190792Sgshapiroimport java.util.LinkedHashSet;
4290792Sgshapiroimport java.util.List;
4390792Sgshapiroimport java.util.Map;
4490792Sgshapiroimport java.util.Set;
45168515Sgshapiroimport java.util.TreeMap;
46168515Sgshapiroimport java.util.function.Consumer;
47168515Sgshapiroimport java.util.function.Predicate;
48168515Sgshapiroimport java.util.function.Supplier;
4990792Sgshapiroimport java.util.stream.Collectors;
5090792Sgshapiroimport java.util.stream.Stream;
5190792Sgshapiro
5290792Sgshapiroimport javax.tools.Diagnostic;
5390792Sgshapiro
5490792Sgshapiroimport jdk.jshell.EvalException;
5590792Sgshapiroimport jdk.jshell.JShell;
5690792Sgshapiroimport jdk.jshell.JShell.Subscription;
5790792Sgshapiroimport jdk.jshell.Snippet;
5890792Sgshapiroimport jdk.jshell.DeclarationSnippet;
5990792Sgshapiroimport jdk.jshell.ExpressionSnippet;
6090792Sgshapiroimport jdk.jshell.ImportSnippet;
6190792Sgshapiroimport jdk.jshell.Snippet.Kind;
6290792Sgshapiroimport jdk.jshell.MethodSnippet;
6390792Sgshapiroimport jdk.jshell.Snippet.Status;
6490792Sgshapiroimport jdk.jshell.Snippet.SubKind;
6590792Sgshapiroimport jdk.jshell.TypeDeclSnippet;
66132943Sgshapiroimport jdk.jshell.VarSnippet;
6790792Sgshapiroimport jdk.jshell.SnippetEvent;
6890792Sgshapiroimport jdk.jshell.SourceCodeAnalysis;
6990792Sgshapiroimport jdk.jshell.SourceCodeAnalysis.CompletionInfo;
7090792Sgshapiroimport jdk.jshell.SourceCodeAnalysis.Completeness;
71132943Sgshapiroimport jdk.jshell.SourceCodeAnalysis.QualifiedNames;
72132943Sgshapiroimport jdk.jshell.SourceCodeAnalysis.Suggestion;
73132943Sgshapiroimport jdk.jshell.UnresolvedReferenceException;
7464562Sgshapiroimport org.testng.annotations.AfterMethod;
7564562Sgshapiroimport org.testng.annotations.BeforeMethod;
7690792Sgshapiro
77120256Sgshapiroimport jdk.jshell.Diag;
78120256Sgshapiro
79120256Sgshapiroimport static java.util.stream.Collectors.toList;
80120256Sgshapiroimport static java.util.stream.Collectors.toSet;
81120256Sgshapiro
82120256Sgshapiroimport static jdk.jshell.Snippet.Status.*;
83120256Sgshapiroimport static org.testng.Assert.*;
84120256Sgshapiroimport static jdk.jshell.Snippet.SubKind.METHOD_SUBKIND;
85147078Sgshapiroimport jdk.jshell.SourceCodeAnalysis.Documentation;
86147078Sgshapiro
87147078Sgshapiropublic class KullaTesting {
88147078Sgshapiro
89147078Sgshapiro    public static final String IGNORE_VALUE = "<ignore-value>";
90147078Sgshapiro    public static final Class<? extends Throwable> IGNORE_EXCEPTION = (new Throwable() {}).getClass();
91147078Sgshapiro    public static final Snippet MAIN_SNIPPET;
92120256Sgshapiro
93120256Sgshapiro    private SourceCodeAnalysis analysis = null;
94120256Sgshapiro    private JShell state = null;
95120256Sgshapiro    private InputStream inStream = null;
96120256Sgshapiro    private ByteArrayOutputStream outStream = null;
97120256Sgshapiro    private ByteArrayOutputStream errStream = null;
98120256Sgshapiro
99147078Sgshapiro    private Map<String, Snippet> idToSnippet = new LinkedHashMap<>();
100147078Sgshapiro    private Set<Snippet> allSnippets = new LinkedHashSet<>();
101147078Sgshapiro
102147078Sgshapiro    static {
103147078Sgshapiro        JShell js = JShell.create();
104147078Sgshapiro        MAIN_SNIPPET = js.eval("MAIN_SNIPPET").get(0).snippet();
105147078Sgshapiro        js.close();
106120256Sgshapiro        assertTrue(MAIN_SNIPPET != null, "Bad MAIN_SNIPPET set-up -- must not be null");
107120256Sgshapiro    }
108120256Sgshapiro
109120256Sgshapiro    public enum DiagCheck {
11064562Sgshapiro        DIAG_OK,
11138032Speter        DIAG_WARNING,
112132943Sgshapiro        DIAG_ERROR,
113132943Sgshapiro        DIAG_IGNORE
114132943Sgshapiro    }
115132943Sgshapiro
116168515Sgshapiro    public void setInput(String s) {
117132943Sgshapiro        setInput(new ByteArrayInputStream(s.getBytes()));
118132943Sgshapiro    }
119132943Sgshapiro
120132943Sgshapiro    public void setInput(InputStream in) {
121132943Sgshapiro        inStream = in;
12290792Sgshapiro    }
12390792Sgshapiro
12490792Sgshapiro    public String getOutput() {
12538032Speter        String s = outStream.toString();
126168515Sgshapiro        outStream.reset();
127168515Sgshapiro        return s;
128168515Sgshapiro    }
129168515Sgshapiro
130168515Sgshapiro    public String getErrorOutput() {
131168515Sgshapiro        String s = errStream.toString();
132168515Sgshapiro        errStream.reset();
133168515Sgshapiro        return s;
134168515Sgshapiro    }
135168515Sgshapiro
136168515Sgshapiro    /**
137168515Sgshapiro     * @return the analysis
138168515Sgshapiro     */
139168515Sgshapiro    public SourceCodeAnalysis getAnalysis() {
140168515Sgshapiro        if (analysis == null) {
141168515Sgshapiro            analysis = state.sourceCodeAnalysis();
142168515Sgshapiro        }
143168515Sgshapiro        return analysis;
144168515Sgshapiro    }
145168515Sgshapiro
146168515Sgshapiro    /**
147168515Sgshapiro     * @return the state
148168515Sgshapiro     */
149168515Sgshapiro    public JShell getState() {
150168515Sgshapiro        return state;
151168515Sgshapiro    }
152168515Sgshapiro
153168515Sgshapiro    public List<Snippet> getActiveKeys() {
154168515Sgshapiro        return allSnippets.stream()
155168515Sgshapiro                .filter(k -> getState().status(k).isActive())
156168515Sgshapiro                .collect(Collectors.toList());
157168515Sgshapiro    }
158168515Sgshapiro
159168515Sgshapiro    public void addToClasspath(String path) {
160168515Sgshapiro        getState().addToClasspath(path);
161168515Sgshapiro    }
162168515Sgshapiro
163168515Sgshapiro    public void addToClasspath(Path path) {
164168515Sgshapiro        addToClasspath(path.toString());
165168515Sgshapiro    }
166168515Sgshapiro
167168515Sgshapiro    @BeforeMethod
168168515Sgshapiro    public void setUp() {
169168515Sgshapiro        setUp(b -> {});
170168515Sgshapiro    }
171168515Sgshapiro
172168515Sgshapiro    public void setUp(Consumer<JShell.Builder> bc) {
173168515Sgshapiro        InputStream in = new InputStream() {
174168515Sgshapiro            @Override
175168515Sgshapiro            public int read() throws IOException {
176168515Sgshapiro                assertNotNull(inStream);
177168515Sgshapiro                return inStream.read();
178168515Sgshapiro            }
179168515Sgshapiro            @Override
180168515Sgshapiro            public int read(byte[] b) throws IOException {
181168515Sgshapiro                assertNotNull(inStream);
182168515Sgshapiro                return inStream.read(b);
183168515Sgshapiro            }
184168515Sgshapiro            @Override
185168515Sgshapiro            public int read(byte[] b, int off, int len) throws IOException {
186168515Sgshapiro                assertNotNull(inStream);
187168515Sgshapiro                return inStream.read(b, off, len);
188168515Sgshapiro            }
189168515Sgshapiro        };
190168515Sgshapiro        outStream = new ByteArrayOutputStream();
191168515Sgshapiro        errStream = new ByteArrayOutputStream();
192168515Sgshapiro        JShell.Builder builder = JShell.builder()
193168515Sgshapiro                .in(in)
194168515Sgshapiro                .out(new PrintStream(outStream))
195168515Sgshapiro                .err(new PrintStream(errStream));
196168515Sgshapiro        bc.accept(builder);
197168515Sgshapiro        state = builder.build();
198168515Sgshapiro        allSnippets = new LinkedHashSet<>();
199168515Sgshapiro        idToSnippet = new LinkedHashMap<>();
200168515Sgshapiro    }
201168515Sgshapiro
202168515Sgshapiro    @AfterMethod
203168515Sgshapiro    public void tearDown() {
204168515Sgshapiro        if (state != null) state.close();
205168515Sgshapiro        state = null;
206168515Sgshapiro        analysis = null;
207168515Sgshapiro        allSnippets = null;
20838032Speter        idToSnippet = null;
20938032Speter    }
21038032Speter
21138032Speter    public ClassLoader createAndRunFromModule(String moduleName, Path modPath) {
21290792Sgshapiro        ModuleFinder finder = ModuleFinder.of(modPath);
21390792Sgshapiro        ModuleLayer parent = ModuleLayer.boot();
21438032Speter        Configuration cf = parent.configuration()
21538032Speter                .resolve(finder, ModuleFinder.of(), Set.of(moduleName));
21638032Speter        ClassLoader scl = ClassLoader.getSystemClassLoader();
21738032Speter        ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
21838032Speter        ClassLoader loader = layer.findLoader(moduleName);
21938032Speter        ClassLoader ccl = Thread.currentThread().getContextClassLoader();
22090792Sgshapiro        Thread.currentThread().setContextClassLoader(loader);
22138032Speter        return ccl;
22238032Speter    }
22390792Sgshapiro
22490792Sgshapiro    public List<String> assertUnresolvedDependencies(DeclarationSnippet key, int unresolvedSize) {
22590792Sgshapiro        List<String> unresolved = getState().unresolvedDependencies(key).collect(toList());
22690792Sgshapiro        assertEquals(unresolved.size(), unresolvedSize, "Input: " + key.source() + ", checking unresolved: ");
22790792Sgshapiro        return unresolved;
22890792Sgshapiro    }
22990792Sgshapiro
23038032Speter    public DeclarationSnippet assertUnresolvedDependencies1(DeclarationSnippet key, Status status, String name) {
23138032Speter        List<String> unresolved = assertUnresolvedDependencies(key, 1);
23264562Sgshapiro        String input = key.source();
23364562Sgshapiro        assertEquals(unresolved.size(), 1, "Given input: " + input + ", checking unresolved");
23438032Speter        assertEquals(unresolved.get(0), name, "Given input: " + input + ", checking unresolved: ");
23538032Speter        assertEquals(getState().status(key), status, "Given input: " + input + ", checking status: ");
23664562Sgshapiro        return key;
23790792Sgshapiro    }
23890792Sgshapiro
23990792Sgshapiro    public DeclarationSnippet assertEvalUnresolvedException(String input, String name, int unresolvedSize, int diagnosticsSize) {
24090792Sgshapiro        List<SnippetEvent> events = assertEval(input, null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null);
24190792Sgshapiro        SnippetEvent ste = events.get(0);
24290792Sgshapiro        DeclarationSnippet sn = ((UnresolvedReferenceException) ste.exception()).getSnippet();
24390792Sgshapiro        assertEquals(sn.name(), name, "Given input: " + input + ", checking name");
24490792Sgshapiro        assertEquals(getState().unresolvedDependencies(sn).count(), unresolvedSize, "Given input: " + input + ", checking unresolved");
24590792Sgshapiro        assertEquals(getState().diagnostics(sn).count(), (long) diagnosticsSize, "Given input: " + input + ", checking diagnostics");
24690792Sgshapiro        return sn;
24790792Sgshapiro    }
24890792Sgshapiro
24990792Sgshapiro    public Snippet assertKeyMatch(String input, boolean isExecutable, SubKind expectedSubKind, STEInfo mainInfo, STEInfo... updates) {
25090792Sgshapiro        Snippet key = key(assertEval(input, IGNORE_VALUE, mainInfo, updates));
25190792Sgshapiro        String source = key.source();
25290792Sgshapiro        assertEquals(source, input, "Key \"" + input + "\" source mismatch, got: " + source + ", expected: " + input);
25390792Sgshapiro        SubKind subkind = key.subKind();
25490792Sgshapiro        assertEquals(subkind, expectedSubKind, "Key \"" + input + "\" subkind mismatch, got: "
25590792Sgshapiro                + subkind + ", expected: " + expectedSubKind);
25638032Speter        assertEquals(subkind.isExecutable(), isExecutable, "Key \"" + input + "\", expected isExecutable: "
25790792Sgshapiro                + isExecutable + ", got: " + subkind.isExecutable());
25864562Sgshapiro        Snippet.Kind expectedKind = getKind(key);
25990792Sgshapiro        assertEquals(key.kind(), expectedKind, "Checking kind: ");
26038032Speter        assertEquals(expectedSubKind.kind(), expectedKind, "Checking kind: ");
26190792Sgshapiro        return key;
26238032Speter    }
26390792Sgshapiro
26490792Sgshapiro    private Kind getKind(Snippet key) {
26538032Speter        SubKind expectedSubKind = key.subKind();
26666494Sgshapiro        Kind expectedKind;
26790792Sgshapiro        switch (expectedSubKind) {
26866494Sgshapiro            case SINGLE_TYPE_IMPORT_SUBKIND:
26966494Sgshapiro            case SINGLE_STATIC_IMPORT_SUBKIND:
27038032Speter            case TYPE_IMPORT_ON_DEMAND_SUBKIND:
27138032Speter            case STATIC_IMPORT_ON_DEMAND_SUBKIND:
27238032Speter                expectedKind = Kind.IMPORT;
27338032Speter                break;
27438032Speter            case CLASS_SUBKIND:
27538032Speter            case INTERFACE_SUBKIND:
27638032Speter            case ENUM_SUBKIND:
27738032Speter            case ANNOTATION_TYPE_SUBKIND:
27838032Speter                expectedKind = Kind.TYPE_DECL;
27938032Speter                break;
28038032Speter            case METHOD_SUBKIND:
28138032Speter                expectedKind = Kind.METHOD;
28238032Speter                break;
28338032Speter            case VAR_DECLARATION_SUBKIND:
28438032Speter            case TEMP_VAR_EXPRESSION_SUBKIND:
28564562Sgshapiro            case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND:
28664562Sgshapiro                expectedKind = Kind.VAR;
28764562Sgshapiro                break;
28864562Sgshapiro            case VAR_VALUE_SUBKIND:
28990792Sgshapiro            case ASSIGNMENT_SUBKIND:
29064562Sgshapiro                expectedKind = Kind.EXPRESSION;
29190792Sgshapiro                break;
29290792Sgshapiro            case STATEMENT_SUBKIND:
29364562Sgshapiro                expectedKind = Kind.STATEMENT;
29490792Sgshapiro                break;
29538032Speter            case UNKNOWN_SUBKIND:
29638032Speter                expectedKind = Kind.ERRONEOUS;
29738032Speter                break;
29838032Speter            default:
29938032Speter                throw new AssertionError("Unsupported key: " + key.getClass().getCanonicalName());
30038032Speter        }
30138032Speter        return expectedKind;
30238032Speter    }
30364562Sgshapiro
30438032Speter    public ImportSnippet assertImportKeyMatch(String input, String name, SubKind subkind, STEInfo mainInfo, STEInfo... updates) {
30590792Sgshapiro        Snippet key = assertKeyMatch(input, false, subkind, mainInfo, updates);
30690792Sgshapiro
30794334Sgshapiro        assertTrue(key instanceof ImportSnippet, "Expected an ImportKey, got: " + key.getClass().getName());
30890792Sgshapiro        ImportSnippet importKey = (ImportSnippet) key;
30990792Sgshapiro        assertEquals(importKey.name(), name, "Input \"" + input +
31094334Sgshapiro                "\" name mismatch, got: " + importKey.name() + ", expected: " + name);
31190792Sgshapiro        assertEquals(importKey.kind(), Kind.IMPORT, "Checking kind: ");
31290792Sgshapiro        return importKey;
31394334Sgshapiro    }
31490792Sgshapiro
31590792Sgshapiro    public DeclarationSnippet assertDeclarationKeyMatch(String input, boolean isExecutable, String name, SubKind subkind, STEInfo mainInfo, STEInfo... updates) {
31694334Sgshapiro        Snippet key = assertKeyMatch(input, isExecutable, subkind, mainInfo, updates);
31790792Sgshapiro
31890792Sgshapiro        assertTrue(key instanceof DeclarationSnippet, "Expected a DeclarationKey, got: " + key.getClass().getName());
31994334Sgshapiro        DeclarationSnippet declKey = (DeclarationSnippet) key;
32038032Speter        assertEquals(declKey.name(), name, "Input \"" + input +
321132943Sgshapiro                "\" name mismatch, got: " + declKey.name() + ", expected: " + name);
322132943Sgshapiro        return declKey;
323132943Sgshapiro    }
324132943Sgshapiro
325132943Sgshapiro    public VarSnippet assertVarKeyMatch(String input, boolean isExecutable, String name, SubKind kind, String typeName, STEInfo mainInfo, STEInfo... updates) {
326132943Sgshapiro        Snippet sn = assertDeclarationKeyMatch(input, isExecutable, name, kind, mainInfo, updates);
327132943Sgshapiro        assertTrue(sn instanceof VarSnippet, "Expected a VarKey, got: " + sn.getClass().getName());
328132943Sgshapiro        VarSnippet variableKey = (VarSnippet) sn;
329132943Sgshapiro        String signature = variableKey.typeName();
330132943Sgshapiro        assertEquals(signature, typeName, "Key \"" + input +
331132943Sgshapiro                "\" typeName mismatch, got: " + signature + ", expected: " + typeName);
332132943Sgshapiro        assertEquals(variableKey.kind(), Kind.VAR, "Checking kind: ");
333132943Sgshapiro        return variableKey;
334132943Sgshapiro    }
335132943Sgshapiro
336132943Sgshapiro    public void assertExpressionKeyMatch(String input, String name, SubKind kind, String typeName) {
337132943Sgshapiro        Snippet key = assertKeyMatch(input, true, kind, added(VALID));
338132943Sgshapiro        assertTrue(key instanceof ExpressionSnippet, "Expected a ExpressionKey, got: " + key.getClass().getName());
339132943Sgshapiro        ExpressionSnippet exprKey = (ExpressionSnippet) key;
340132943Sgshapiro        assertEquals(exprKey.name(), name, "Input \"" + input +
341132943Sgshapiro                "\" name mismatch, got: " + exprKey.name() + ", expected: " + name);
342132943Sgshapiro        assertEquals(exprKey.typeName(), typeName, "Key \"" + input +
343132943Sgshapiro                "\" typeName mismatch, got: " + exprKey.typeName() + ", expected: " + typeName);
344132943Sgshapiro        assertEquals(exprKey.kind(), Kind.EXPRESSION, "Checking kind: ");
345132943Sgshapiro    }
34690792Sgshapiro
34790792Sgshapiro    // For expressions throwing an EvalException
34890792Sgshapiro    public SnippetEvent assertEvalException(String input) {
34990792Sgshapiro        List<SnippetEvent> events = assertEval(input, null, EvalException.class,
35038032Speter                DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null);
35190792Sgshapiro        return events.get(0);
35290792Sgshapiro    }
353173340Sgshapiro
354173340Sgshapiro
355173340Sgshapiro    public List<SnippetEvent> assertEvalFail(String input) {
35690792Sgshapiro        return assertEval(input, null, null,
357173340Sgshapiro                DiagCheck.DIAG_ERROR, DiagCheck.DIAG_IGNORE, added(REJECTED));
358173340Sgshapiro    }
359173340Sgshapiro
360173340Sgshapiro    public List<SnippetEvent> assertEval(String input) {
361173340Sgshapiro        return assertEval(input, IGNORE_VALUE, null, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(VALID));
362173340Sgshapiro    }
36390792Sgshapiro
364173340Sgshapiro    public List<SnippetEvent> assertEval(String input, String value) {
36590792Sgshapiro        return assertEval(input, value, null, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(VALID));
36690792Sgshapiro    }
367132943Sgshapiro
36890792Sgshapiro    public List<SnippetEvent> assertEval(String input, STEInfo mainInfo, STEInfo... updates) {
369132943Sgshapiro        return assertEval(input, IGNORE_VALUE, null, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, mainInfo, updates);
37090792Sgshapiro    }
37190792Sgshapiro
37290792Sgshapiro    public List<SnippetEvent> assertEval(String input, String value,
373110560Sgshapiro            STEInfo mainInfo, STEInfo... updates) {
37490792Sgshapiro        return assertEval(input, value, null, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, mainInfo, updates);
37590792Sgshapiro    }
37690792Sgshapiro
37790792Sgshapiro    public List<SnippetEvent> assertEval(String input, DiagCheck diagMain, DiagCheck diagUpdates) {
378168515Sgshapiro        return assertEval(input, IGNORE_VALUE, null, diagMain, diagUpdates, added(VALID));
37990792Sgshapiro    }
38090792Sgshapiro
381157001Sgshapiro    public List<SnippetEvent> assertEval(String input, DiagCheck diagMain, DiagCheck diagUpdates,
382157001Sgshapiro            STEInfo mainInfo, STEInfo... updates) {
383157001Sgshapiro        return assertEval(input, IGNORE_VALUE, null, diagMain, diagUpdates, mainInfo, updates);
384157001Sgshapiro    }
385157001Sgshapiro
386157001Sgshapiro    public List<SnippetEvent> assertEval(String input,
387157001Sgshapiro            String value, Class<? extends Throwable> exceptionClass,
388157001Sgshapiro            DiagCheck diagMain, DiagCheck diagUpdates,
389157001Sgshapiro            STEInfo mainInfo, STEInfo... updates) {
390157001Sgshapiro        return assertEval(input, diagMain, diagUpdates, new EventChain(mainInfo, value, exceptionClass, updates));
391157001Sgshapiro    }
392157001Sgshapiro
393157001Sgshapiro    // Use this directly or usually indirectly for all non-empty calls to eval()
394157001Sgshapiro    public List<SnippetEvent> assertEval(String input,
395157001Sgshapiro           DiagCheck diagMain, DiagCheck diagUpdates, EventChain... eventChains) {
396157001Sgshapiro        return checkEvents(() -> getState().eval(input), "eval(" + input + ")", diagMain, diagUpdates, eventChains);
397157001Sgshapiro    }
398157001Sgshapiro
39990792Sgshapiro    <T> void assertStreamMatch(Stream<T> result, T... expected) {
40090792Sgshapiro        Set<T> sns = result.collect(toSet());
40190792Sgshapiro        Set<T> exp = Stream.of(expected).collect(toSet());
40290792Sgshapiro        assertEquals(sns, exp);
40390792Sgshapiro    }
40490792Sgshapiro
40590792Sgshapiro    private Map<Snippet, Snippet> closure(List<SnippetEvent> events) {
40690792Sgshapiro        Map<Snippet, Snippet> transitions = new HashMap<>();
407157001Sgshapiro        for (SnippetEvent event : events) {
408157001Sgshapiro            transitions.put(event.snippet(), event.causeSnippet());
409132943Sgshapiro        }
410132943Sgshapiro        Map<Snippet, Snippet> causeSnippets = new HashMap<>();
411132943Sgshapiro        for (Map.Entry<Snippet, Snippet> entry : transitions.entrySet()) {
412132943Sgshapiro            Snippet snippet = entry.getKey();
413132943Sgshapiro            Snippet cause = getInitialCause(transitions, entry.getValue());
414132943Sgshapiro            causeSnippets.put(snippet, cause);
415132943Sgshapiro        }
416132943Sgshapiro        return causeSnippets;
417132943Sgshapiro    }
418132943Sgshapiro
419132943Sgshapiro    private Snippet getInitialCause(Map<Snippet, Snippet> transitions, Snippet snippet) {
42090792Sgshapiro        Snippet result;
42190792Sgshapiro        while ((result = transitions.get(snippet)) != null) {
42290792Sgshapiro            snippet = result;
42390792Sgshapiro        }
42490792Sgshapiro        return snippet;
42590792Sgshapiro    }
42690792Sgshapiro
42790792Sgshapiro    private Map<Snippet, List<SnippetEvent>> groupByCauseSnippet(List<SnippetEvent> events) {
42890792Sgshapiro        Map<Snippet, List<SnippetEvent>> map = new TreeMap<>((a, b) -> a.id().compareTo(b.id()));
42990792Sgshapiro        for (SnippetEvent event : events) {
43090792Sgshapiro            if (event == null) {
43190792Sgshapiro                throw new InternalError("null event found in " + events);
43290792Sgshapiro            }
43390792Sgshapiro            if (event.snippet() == null) {
43490792Sgshapiro                throw new InternalError("null event Snippet found in " + events);
43590792Sgshapiro            }
43690792Sgshapiro            if (event.snippet().id() == null) {
43790792Sgshapiro                throw new InternalError("null event Snippet id() found in " + events);
43890792Sgshapiro            }
439168515Sgshapiro        }
44090792Sgshapiro        for (SnippetEvent event : events) {
44190792Sgshapiro            if (event.causeSnippet() == null) {
44290792Sgshapiro                map.computeIfAbsent(event.snippet(), ($) -> new ArrayList<>()).add(event);
44390792Sgshapiro            }
44490792Sgshapiro        }
44590792Sgshapiro        Map<Snippet, Snippet> causeSnippets = closure(events);
44690792Sgshapiro        for (SnippetEvent event : events) {
44790792Sgshapiro            Snippet causeSnippet = causeSnippets.get(event.snippet());
44890792Sgshapiro            if (causeSnippet != null) {
44990792Sgshapiro                map.get(causeSnippet).add(event);
45090792Sgshapiro            }
45190792Sgshapiro        }
452168515Sgshapiro        for (Map.Entry<Snippet, List<SnippetEvent>> entry : map.entrySet()) {
453168515Sgshapiro            Collections.sort(entry.getValue(),
454168515Sgshapiro                    (a, b) -> a.causeSnippet() == null
45590792Sgshapiro                            ? -1 : b.causeSnippet() == null
45690792Sgshapiro                            ? 1 : a.snippet().id().compareTo(b.snippet().id()));
45790792Sgshapiro        }
45890792Sgshapiro        return map;
45990792Sgshapiro    }
46090792Sgshapiro
46190792Sgshapiro    private List<STEInfo> getInfos(EventChain... eventChains) {
46290792Sgshapiro        List<STEInfo> list = new ArrayList<>();
46390792Sgshapiro        for (EventChain i : eventChains) {
46490792Sgshapiro            list.add(i.mainInfo);
46590792Sgshapiro            Collections.addAll(list, i.updates);
46690792Sgshapiro        }
467132943Sgshapiro        return list;
46890792Sgshapiro    }
46990792Sgshapiro
47090792Sgshapiro    private List<SnippetEvent> checkEvents(Supplier<List<SnippetEvent>> toTest,
47190792Sgshapiro             String descriptor,
47290792Sgshapiro             DiagCheck diagMain, DiagCheck diagUpdates,
47390792Sgshapiro             EventChain... eventChains) {
47490792Sgshapiro        List<SnippetEvent> dispatched = new ArrayList<>();
47590792Sgshapiro        Subscription token = getState().onSnippetEvent(kse -> {
47690792Sgshapiro            if (dispatched.size() > 0 && dispatched.get(dispatched.size() - 1) == null) {
47790792Sgshapiro                throw new RuntimeException("dispatch event after done");
47890792Sgshapiro            }
47990792Sgshapiro            dispatched.add(kse);
48090792Sgshapiro        });
48190792Sgshapiro        List<SnippetEvent> events = toTest.get();
48290792Sgshapiro        getState().unsubscribe(token);
483203004Sgshapiro        assertEquals(dispatched.size(), events.size(), "dispatched event size not the same as event size");
484203004Sgshapiro        for (int i = events.size() - 1; i >= 0; --i) {
485203004Sgshapiro            assertEquals(dispatched.get(i), events.get(i), "Event element " + i + " does not match");
48690792Sgshapiro        }
48790792Sgshapiro        dispatched.add(null); // mark end of dispatchs
48890792Sgshapiro
48990792Sgshapiro        for (SnippetEvent evt : events) {
49090792Sgshapiro            assertTrue(evt.snippet() != null, "key must never be null, but it was for: " + descriptor);
49190792Sgshapiro            assertTrue(evt.previousStatus() != null, "previousStatus must never be null, but it was for: " + descriptor);
49290792Sgshapiro            assertTrue(evt.status() != null, "status must never be null, but it was for: " + descriptor);
493203004Sgshapiro            assertTrue(evt.status() != NONEXISTENT, "status must not be NONEXISTENT: " + descriptor);
49490792Sgshapiro            if (evt.previousStatus() != NONEXISTENT) {
49590792Sgshapiro                Snippet old = idToSnippet.get(evt.snippet().id());
49690792Sgshapiro                if (old != null) {
497168515Sgshapiro                    switch (evt.status()) {
498132943Sgshapiro                        case DROPPED:
499132943Sgshapiro                            assertEquals(old, evt.snippet(),
500132943Sgshapiro                                    "Drop: Old snippet must be what is dropped -- input: " + descriptor);
501132943Sgshapiro                            break;
502132943Sgshapiro                        case OVERWRITTEN:
503132943Sgshapiro                            assertEquals(old, evt.snippet(),
504132943Sgshapiro                                    "Overwrite: Old snippet (" + old
505132943Sgshapiro                                    + ") must be what is overwritten -- input: "
506132943Sgshapiro                                    + descriptor + " -- " + evt);
507132943Sgshapiro                            break;
508132943Sgshapiro                        default:
509132943Sgshapiro                            if (evt.causeSnippet() == null) {
510132943Sgshapiro                                // New source
511132943Sgshapiro                                assertNotEquals(old, evt.snippet(),
512132943Sgshapiro                                        "New source: Old snippet must be different from the replacing -- input: "
513132943Sgshapiro                                        + descriptor);
514132943Sgshapiro                            } else {
515132943Sgshapiro                                // An update (key Overwrite??)
516132943Sgshapiro                                assertEquals(old, evt.snippet(),
517132943Sgshapiro                                        "Update: Old snippet must be equal to the replacing -- input: "
51890792Sgshapiro                                        + descriptor);
51990792Sgshapiro                            }
52090792Sgshapiro                            break;
52190792Sgshapiro                    }
52290792Sgshapiro                }
52390792Sgshapiro            }
52490792Sgshapiro        }
52590792Sgshapiro        for (SnippetEvent evt : events) {
52690792Sgshapiro            if (evt.causeSnippet() == null && evt.status() != DROPPED) {
52790792Sgshapiro                allSnippets.add(evt.snippet());
52890792Sgshapiro                idToSnippet.put(evt.snippet().id(), evt.snippet());
52990792Sgshapiro            }
53090792Sgshapiro        }
53190792Sgshapiro        assertTrue(events.size() >= 1, "Expected at least one event, got none.");
53290792Sgshapiro        List<STEInfo> all = getInfos(eventChains);
53390792Sgshapiro        if (events.size() != all.size()) {
53490792Sgshapiro            StringBuilder sb = new StringBuilder();
53590792Sgshapiro            sb.append("Got events --\n");
53690792Sgshapiro            for (SnippetEvent evt : events) {
53790792Sgshapiro                sb.append("  key: ").append(evt.snippet());
53890792Sgshapiro                sb.append(" before: ").append(evt.previousStatus());
53990792Sgshapiro                sb.append(" status: ").append(evt.status());
54090792Sgshapiro                sb.append(" isSignatureChange: ").append(evt.isSignatureChange());
54190792Sgshapiro                sb.append(" cause: ");
54290792Sgshapiro                if (evt.causeSnippet() == null) {
54390792Sgshapiro                    sb.append("direct");
544168515Sgshapiro                } else {
54590792Sgshapiro                    sb.append(evt.causeSnippet());
54638032Speter                }
54764562Sgshapiro                sb.append("\n");
54864562Sgshapiro            }
54964562Sgshapiro            sb.append("Expected ").append(all.size());
55038032Speter            sb.append(" events, got: ").append(events.size());
55138032Speter            fail(sb.toString());
55238032Speter        }
55364562Sgshapiro
55438032Speter        int impactId = 0;
55538032Speter        Map<Snippet, List<SnippetEvent>> groupedEvents = groupByCauseSnippet(events);
55638032Speter        assertEquals(groupedEvents.size(), eventChains.length, "Number of main events");
55738032Speter        for (Map.Entry<Snippet, List<SnippetEvent>> entry : groupedEvents.entrySet()) {
55838032Speter            EventChain eventChain = eventChains[impactId++];
55938032Speter            SnippetEvent main = entry.getValue().get(0);
56038032Speter            Snippet mainKey = main.snippet();
56138032Speter            if (eventChain.mainInfo != null) {
56238032Speter                eventChain.mainInfo.assertMatch(entry.getValue().get(0), mainKey);
56338032Speter                if (eventChain.updates.length > 0) {
56490792Sgshapiro                    if (eventChain.updates.length == 1) {
56590792Sgshapiro                        eventChain.updates[0].assertMatch(entry.getValue().get(1), mainKey);
56690792Sgshapiro                    } else {
56790792Sgshapiro                        Arrays.sort(eventChain.updates, (a, b) -> ((a.snippet() == MAIN_SNIPPET)
56890792Sgshapiro                                ? mainKey
56990792Sgshapiro                                : a.snippet()).id().compareTo(b.snippet().id()));
57038032Speter                        List<SnippetEvent> updateEvents = new ArrayList<>(entry.getValue().subList(1, entry.getValue().size()));
57190792Sgshapiro                        int idx = 0;
57290792Sgshapiro                        for (SnippetEvent ste : updateEvents) {
57364562Sgshapiro                            eventChain.updates[idx++].assertMatch(ste, mainKey);
57464562Sgshapiro                        }
57590792Sgshapiro                    }
57638032Speter                }
57790792Sgshapiro            }
57864562Sgshapiro            if (((Object) eventChain.value) != IGNORE_VALUE) {
57964562Sgshapiro                assertEquals(main.value(), eventChain.value, "Expected execution value of: " + eventChain.value +
58090792Sgshapiro                        ", but got: " + main.value());
58138032Speter            }
58264562Sgshapiro            if (eventChain.exceptionClass != IGNORE_EXCEPTION) {
583168515Sgshapiro                if (main.exception() == null) {
584168515Sgshapiro                    assertEquals(eventChain.exceptionClass, null, "Expected an exception of class "
585168515Sgshapiro                            + eventChain.exceptionClass + " got no exception");
586168515Sgshapiro                } else if (eventChain.exceptionClass == null) {
58738032Speter                    fail("Expected no exception but got " + main.exception().toString());
58890792Sgshapiro                } else {
58964562Sgshapiro                    assertTrue(eventChain.exceptionClass.isInstance(main.exception()),
59064562Sgshapiro                            "Expected an exception of class " + eventChain.exceptionClass +
59190792Sgshapiro                                    " got: " + main.exception().toString());
59264562Sgshapiro                }
59364562Sgshapiro            }
59464562Sgshapiro            List<Diag> diagnostics = getState().diagnostics(mainKey).collect(toList());
59564562Sgshapiro            switch (diagMain) {
59698121Sgshapiro                case DIAG_OK:
59798121Sgshapiro                    assertEquals(diagnostics.size(), 0, "Expected no diagnostics, got: " + diagnosticsToString(diagnostics));
598168515Sgshapiro                    break;
59998121Sgshapiro                case DIAG_WARNING:
600102528Sgshapiro                    assertFalse(hasFatalError(diagnostics), "Expected no errors, got: " + diagnosticsToString(diagnostics));
601120256Sgshapiro                    break;
60298121Sgshapiro                case DIAG_ERROR:
60398121Sgshapiro                    assertTrue(hasFatalError(diagnostics), "Expected errors, got: " + diagnosticsToString(diagnostics));
60464562Sgshapiro                    break;
60598121Sgshapiro            }
606120256Sgshapiro            if (eventChain.mainInfo != null) {
607120256Sgshapiro                for (STEInfo ste : eventChain.updates) {
60898121Sgshapiro                    diagnostics = getState().diagnostics(ste.snippet()).collect(toList());
60998121Sgshapiro                    switch (diagUpdates) {
61098121Sgshapiro                        case DIAG_OK:
61190792Sgshapiro                            assertEquals(diagnostics.size(), 0, "Expected no diagnostics, got: " + diagnosticsToString(diagnostics));
61264562Sgshapiro                            break;
61364562Sgshapiro                        case DIAG_WARNING:
61464562Sgshapiro                            assertFalse(hasFatalError(diagnostics), "Expected no errors, got: " + diagnosticsToString(diagnostics));
61590792Sgshapiro                            break;
61690792Sgshapiro                    }
617168515Sgshapiro                }
61890792Sgshapiro            }
619132943Sgshapiro        }
62090792Sgshapiro        return events;
62166494Sgshapiro    }
62290792Sgshapiro
623132943Sgshapiro    // Use this for all EMPTY calls to eval()
62464562Sgshapiro    public void assertEvalEmpty(String input) {
62564562Sgshapiro        List<SnippetEvent> events = getState().eval(input);
62690792Sgshapiro        assertEquals(events.size(), 0, "Expected no events, got: " + events.size());
62790792Sgshapiro    }
62890792Sgshapiro
62990792Sgshapiro    public VarSnippet varKey(List<SnippetEvent> events) {
63090792Sgshapiro        Snippet key = key(events);
63190792Sgshapiro        assertTrue(key instanceof VarSnippet, "Expected a VariableKey, got: " + key);
63290792Sgshapiro        return (VarSnippet) key;
63390792Sgshapiro    }
63490792Sgshapiro
635168515Sgshapiro    public MethodSnippet methodKey(List<SnippetEvent> events) {
636168515Sgshapiro        Snippet key = key(events);
637168515Sgshapiro        assertTrue(key instanceof MethodSnippet, "Expected a MethodKey, got: " + key);
638168515Sgshapiro        return (MethodSnippet) key;
639168515Sgshapiro    }
640168515Sgshapiro
641168515Sgshapiro    public TypeDeclSnippet classKey(List<SnippetEvent> events) {
642168515Sgshapiro        Snippet key = key(events);
643168515Sgshapiro        assertTrue(key instanceof TypeDeclSnippet, "Expected a ClassKey, got: " + key);
644182352Sgshapiro        return (TypeDeclSnippet) key;
645182352Sgshapiro    }
646182352Sgshapiro
64738032Speter    public ImportSnippet importKey(List<SnippetEvent> events) {
648168515Sgshapiro        Snippet key = key(events);
64990792Sgshapiro        assertTrue(key instanceof ImportSnippet, "Expected a ImportKey, got: " + key);
65090792Sgshapiro        return (ImportSnippet) key;
65190792Sgshapiro    }
65290792Sgshapiro
653168515Sgshapiro    public Snippet key(List<SnippetEvent> events) {
65490792Sgshapiro        assertTrue(events.size() >= 1, "Expected at least one event, got none.");
65590792Sgshapiro        return events.get(0).snippet();
65690792Sgshapiro    }
65790792Sgshapiro
65890792Sgshapiro    public void assertVarValue(Snippet key, String expected) {
65990792Sgshapiro        String value = state.varValue((VarSnippet) key);
66090792Sgshapiro        assertEquals(value, expected, "Expected var value of: " + expected + ", but got: " + value);
66138032Speter    }
66290792Sgshapiro
66390792Sgshapiro    public Snippet assertDeclareFail(String input, String expectedErrorCode) {
66438032Speter        return assertDeclareFail(input, expectedErrorCode, added(REJECTED));
66590792Sgshapiro    }
66664562Sgshapiro
66790792Sgshapiro    public Snippet assertDeclareFail(String input, String expectedErrorCode,
66890792Sgshapiro            STEInfo mainInfo, STEInfo... updates) {
66990792Sgshapiro        return assertDeclareFail(input,
67090792Sgshapiro                new ExpectedDiagnostic(expectedErrorCode, -1, -1, -1, -1, -1, Diagnostic.Kind.ERROR),
67138032Speter                mainInfo, updates);
67290792Sgshapiro    }
67338032Speter
67438032Speter    public Snippet assertDeclareFail(String input, ExpectedDiagnostic expectedDiagnostic) {
67538032Speter        return assertDeclareFail(input, expectedDiagnostic, added(REJECTED));
67638032Speter    }
67738032Speter
67838032Speter    public Snippet assertDeclareFail(String input, ExpectedDiagnostic expectedDiagnostic,
67938032Speter            STEInfo mainInfo, STEInfo... updates) {
68038032Speter        List<SnippetEvent> events = assertEval(input, null, null,
68138032Speter                DiagCheck.DIAG_ERROR, DiagCheck.DIAG_IGNORE, mainInfo, updates);
68290792Sgshapiro        SnippetEvent e = events.get(0);
68338032Speter        Snippet key = e.snippet();
68490792Sgshapiro        assertEquals(getState().status(key), REJECTED);
68590792Sgshapiro        List<Diag> diagnostics = getState().diagnostics(e.snippet()).collect(toList());
68690792Sgshapiro        assertTrue(diagnostics.size() > 0, "Expected diagnostics, got none");
68790792Sgshapiro        assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic);
68864562Sgshapiro        assertTrue(key != null, "key must never be null, but it was for: " + input);
68990792Sgshapiro        return key;
69090792Sgshapiro    }
69190792Sgshapiro
69290792Sgshapiro    public Snippet assertDeclareWarn1(String input, String expectedErrorCode) {
69390792Sgshapiro        return assertDeclareWarn1(input, new ExpectedDiagnostic(expectedErrorCode, -1, -1, -1, -1, -1, Diagnostic.Kind.WARNING));
69490792Sgshapiro    }
69590792Sgshapiro
69690792Sgshapiro    public Snippet assertDeclareWarn1(String input, ExpectedDiagnostic expectedDiagnostic) {
69790792Sgshapiro        return assertDeclareWarn1(input, expectedDiagnostic, added(VALID));
69890792Sgshapiro    }
699159609Sgshapiro
700159609Sgshapiro    public Snippet assertDeclareWarn1(String input, ExpectedDiagnostic expectedDiagnostic, STEInfo mainInfo, STEInfo... updates) {
70190792Sgshapiro        List<SnippetEvent> events = assertEval(input, IGNORE_VALUE, null,
70290792Sgshapiro                DiagCheck.DIAG_WARNING, DiagCheck.DIAG_IGNORE, mainInfo, updates);
703132943Sgshapiro        SnippetEvent e = events.get(0);
704132943Sgshapiro        List<Diag> diagnostics = getState().diagnostics(e.snippet()).collect(toList());
70590792Sgshapiro        if (expectedDiagnostic != null) assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic);
70690792Sgshapiro        return e.snippet();
70790792Sgshapiro    }
70890792Sgshapiro
70990792Sgshapiro    private void assertDiagnostic(String input, Diag diagnostic, ExpectedDiagnostic expectedDiagnostic) {
71090792Sgshapiro        if (expectedDiagnostic != null) expectedDiagnostic.assertDiagnostic(diagnostic);
71190792Sgshapiro        // assertEquals(diagnostic.getSource(), input, "Diagnostic source");
71290792Sgshapiro    }
71390792Sgshapiro
71490792Sgshapiro    public void assertTypeDeclSnippet(TypeDeclSnippet type, String expectedName,
71590792Sgshapiro            Status expectedStatus, SubKind expectedSubKind,
71690792Sgshapiro            int unressz, int othersz) {
71790792Sgshapiro        assertDeclarationSnippet(type, expectedName, expectedStatus,
71890792Sgshapiro                expectedSubKind, unressz, othersz);
71990792Sgshapiro    }
72090792Sgshapiro
72190792Sgshapiro    public void assertMethodDeclSnippet(MethodSnippet method,
72290792Sgshapiro            String expectedName, String expectedSignature,
72390792Sgshapiro            Status expectedStatus, int unressz, int othersz) {
72490792Sgshapiro        assertDeclarationSnippet(method, expectedName, expectedStatus,
72590792Sgshapiro                METHOD_SUBKIND, unressz, othersz);
726132943Sgshapiro        String signature = method.signature();
727132943Sgshapiro        assertEquals(signature, expectedSignature,
72890792Sgshapiro                "Expected " + method.source() + " to have the name: " +
72990792Sgshapiro                        expectedSignature + ", got: " + signature);
730132943Sgshapiro    }
731132943Sgshapiro
732132943Sgshapiro    public void assertVariableDeclSnippet(VarSnippet var,
733132943Sgshapiro            String expectedName, String expectedTypeName,
734132943Sgshapiro            Status expectedStatus, SubKind expectedSubKind,
73590792Sgshapiro            int unressz, int othersz) {
73690792Sgshapiro        assertDeclarationSnippet(var, expectedName, expectedStatus,
737132943Sgshapiro                expectedSubKind, unressz, othersz);
738132943Sgshapiro        String signature = var.typeName();
739132943Sgshapiro        assertEquals(signature, expectedTypeName,
740132943Sgshapiro                "Expected " + var.source() + " to have the name: " +
741132943Sgshapiro                        expectedTypeName + ", got: " + signature);
742132943Sgshapiro    }
743132943Sgshapiro
74490792Sgshapiro    public void assertDeclarationSnippet(DeclarationSnippet declarationKey,
745132943Sgshapiro            String expectedName,
746132943Sgshapiro            Status expectedStatus, SubKind expectedSubKind,
747132943Sgshapiro            int unressz, int othersz) {
748132943Sgshapiro        assertKey(declarationKey, expectedStatus, expectedSubKind);
749132943Sgshapiro        String source = declarationKey.source();
75090792Sgshapiro        assertEquals(declarationKey.name(), expectedName,
751168515Sgshapiro                "Expected " + source + " to have the name: " + expectedName + ", got: " + declarationKey.name());
75290792Sgshapiro        long unresolved = getState().unresolvedDependencies(declarationKey).count();
75390792Sgshapiro        assertEquals(unresolved, unressz, "Expected " + source + " to have " + unressz
754132943Sgshapiro                + " unresolved symbols, got: " + unresolved);
755132943Sgshapiro        long otherCorralledErrorsCount = getState().diagnostics(declarationKey).count();
75690792Sgshapiro        assertEquals(otherCorralledErrorsCount, othersz, "Expected " + source + " to have " + othersz
75764562Sgshapiro                + " other errors, got: " + otherCorralledErrorsCount);
75890792Sgshapiro    }
75964562Sgshapiro
76064562Sgshapiro    public void assertKey(Snippet key, Status expectedStatus, SubKind expectedSubKind) {
76190792Sgshapiro        String source = key.source();
76238032Speter        SubKind actualSubKind = key.subKind();
76398121Sgshapiro        assertEquals(actualSubKind, expectedSubKind,
764132943Sgshapiro                "Expected " + source + " to have the subkind: " + expectedSubKind + ", got: " + actualSubKind);
76598121Sgshapiro        Status status = getState().status(key);
76698121Sgshapiro        assertEquals(status, expectedStatus, "Expected " + source + " to be "
76790792Sgshapiro                + expectedStatus + ", but it is " + status);
768132943Sgshapiro        Snippet.Kind expectedKind = getKind(key);
76998121Sgshapiro        assertEquals(key.kind(), expectedKind, "Checking kind: ");
77090792Sgshapiro        assertEquals(expectedSubKind.kind(), expectedKind, "Checking kind: ");
771132943Sgshapiro    }
77290792Sgshapiro
77398121Sgshapiro    public void assertDrop(Snippet key, STEInfo mainInfo, STEInfo... updates) {
77490792Sgshapiro        assertDrop(key, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, mainInfo, updates);
77590792Sgshapiro    }
77690792Sgshapiro
77790792Sgshapiro    public void assertDrop(Snippet key, DiagCheck diagMain, DiagCheck diagUpdates, STEInfo mainInfo, STEInfo... updates) {
77890792Sgshapiro        assertDrop(key, diagMain, diagUpdates, new EventChain(mainInfo, null, null, updates));
77990792Sgshapiro    }
78090792Sgshapiro
78190792Sgshapiro    public void assertDrop(Snippet key, DiagCheck diagMain, DiagCheck diagUpdates, EventChain... eventChains) {
78290792Sgshapiro        checkEvents(() -> getState().drop(key), "drop(" + key + ")", diagMain, diagUpdates, eventChains);
78390792Sgshapiro    }
78490792Sgshapiro
78564562Sgshapiro    public void assertAnalyze(String input, String source, String remaining, boolean isComplete) {
78664562Sgshapiro        assertAnalyze(input, null, source, remaining, isComplete);
78764562Sgshapiro    }
78898121Sgshapiro
78964562Sgshapiro     public void assertAnalyze(String input, Completeness status, String source) {
79064562Sgshapiro        assertAnalyze(input, status, source, null, null);
79164562Sgshapiro    }
79264562Sgshapiro
79364562Sgshapiro    public void assertAnalyze(String input, Completeness status, String source, String remaining, Boolean isComplete) {
79498121Sgshapiro        CompletionInfo ci = getAnalysis().analyzeCompletion(input);
795147078Sgshapiro        if (status != null) assertEquals(ci.completeness(), status, "Input : " + input + ", status: ");
79698121Sgshapiro        if (source != null) assertEquals(ci.source(), source, "Input : " + input + ", source: ");
79790792Sgshapiro        if (remaining != null) assertEquals(ci.remaining(), remaining, "Input : " + input + ", remaining: ");
79898121Sgshapiro        if (isComplete != null) {
79998121Sgshapiro            boolean isExpectedComplete = isComplete;
80098121Sgshapiro            assertEquals(ci.completeness().isComplete(), isExpectedComplete, "Input : " + input + ", isComplete: ");
80198121Sgshapiro        }
80298121Sgshapiro    }
80398121Sgshapiro
80498121Sgshapiro    public void assertNumberOfActiveVariables(int cnt) {
80598121Sgshapiro        assertEquals(getState().variables().count(), cnt, "Variables : " + getState().variables().collect(toList()));
80698121Sgshapiro    }
80798121Sgshapiro
80898121Sgshapiro    public void assertNumberOfActiveMethods(int cnt) {
80998121Sgshapiro        assertEquals(getState().methods().count(), cnt, "Methods : " + getState().methods().collect(toList()));
81098121Sgshapiro    }
81198121Sgshapiro
81298121Sgshapiro    public void assertNumberOfActiveClasses(int cnt) {
81398121Sgshapiro        assertEquals(getState().types().count(), cnt, "Types : " + getState().types().collect(toList()));
81498121Sgshapiro    }
815168515Sgshapiro
81698121Sgshapiro    public void assertKeys(MemberInfo... expected) {
81798121Sgshapiro        int index = 0;
81898121Sgshapiro        List<Snippet> snippets = getState().snippets().collect(toList());
81998121Sgshapiro        assertEquals(allSnippets.size(), snippets.size());
82098121Sgshapiro        for (Snippet sn : snippets) {
82198121Sgshapiro            if (sn.kind().isPersistent() && getState().status(sn).isActive()) {
82298121Sgshapiro                MemberInfo actual = getMemberInfo(sn);
82398121Sgshapiro                MemberInfo exp = expected[index];
82498121Sgshapiro                assertEquals(actual, exp, String.format("Difference in #%d. Expected: %s, actual: %s",
82598121Sgshapiro                        index, exp, actual));
82698121Sgshapiro                ++index;
82798121Sgshapiro            }
82898121Sgshapiro        }
829168515Sgshapiro    }
83098121Sgshapiro
83198121Sgshapiro    public void assertActiveKeys() {
83298121Sgshapiro        Collection<Snippet> expected = getActiveKeys();
83398121Sgshapiro        assertActiveKeys(expected.toArray(new Snippet[expected.size()]));
83498121Sgshapiro    }
83598121Sgshapiro
83698121Sgshapiro    public void assertActiveKeys(Snippet... expected) {
83798121Sgshapiro        int index = 0;
83898121Sgshapiro        for (Snippet key : getState().snippets().collect(toList())) {
83998121Sgshapiro            if (state.status(key).isActive()) {
84098121Sgshapiro                assertEquals(expected[index], key, String.format("Difference in #%d. Expected: %s, actual: %s", index, key, expected[index]));
84198121Sgshapiro                ++index;
84264562Sgshapiro            }
84364562Sgshapiro        }
84464562Sgshapiro    }
84564562Sgshapiro
84664562Sgshapiro    private void assertActiveSnippets(Stream<? extends Snippet> snippets, Predicate<Snippet> p, String label) {
84790792Sgshapiro        Set<Snippet> active = getActiveKeys().stream()
84890792Sgshapiro                .filter(p)
84964562Sgshapiro                .collect(Collectors.toSet());
85064562Sgshapiro        Set<Snippet> got = snippets
85164562Sgshapiro                .collect(Collectors.toSet());
85264562Sgshapiro        assertEquals(active, got, label);
85364562Sgshapiro    }
85490792Sgshapiro
85590792Sgshapiro    public void assertVariables() {
85690792Sgshapiro        assertActiveSnippets(getState().variables(), (key) -> key instanceof VarSnippet, "Variables");
85764562Sgshapiro    }
85864562Sgshapiro
85964562Sgshapiro    public void assertMethods() {
86064562Sgshapiro        assertActiveSnippets(getState().methods(), (key) -> key instanceof MethodSnippet, "Methods");
86164562Sgshapiro    }
86264562Sgshapiro
86398121Sgshapiro    public void assertClasses() {
86498121Sgshapiro        assertActiveSnippets(getState().types(), (key) -> key instanceof TypeDeclSnippet, "Classes");
86564562Sgshapiro    }
86664562Sgshapiro
86764562Sgshapiro    public void assertMembers(Stream<? extends Snippet> members, MemberInfo...expectedInfos) {
86864562Sgshapiro        Set<MemberInfo> expected = Stream.of(expectedInfos).collect(Collectors.toSet());
86990792Sgshapiro        Set<MemberInfo> got = members
87090792Sgshapiro                        .map(this::getMemberInfo)
87190792Sgshapiro                        .collect(Collectors.toSet());
87290792Sgshapiro        assertEquals(got.size(), expected.size(), "Expected : " + expected + ", actual : " + members);
87364562Sgshapiro        assertEquals(got, expected);
87464562Sgshapiro    }
875168515Sgshapiro
87690792Sgshapiro    public void assertVariables(MemberInfo...expected) {
87764562Sgshapiro        assertMembers(getState().variables(), expected);
87864562Sgshapiro    }
879223067Sgshapiro
880223067Sgshapiro    public void assertMethods(MemberInfo...expected) {
88164562Sgshapiro        assertMembers(getState().methods(), expected);
88264562Sgshapiro        getState().methods().forEach(methodKey -> {
88364562Sgshapiro            MemberInfo expectedInfo = null;
88464562Sgshapiro            for (MemberInfo info : expected) {
88564562Sgshapiro                if (info.name.equals(methodKey.name()) && info.type.equals(methodKey.signature())) {
88664562Sgshapiro                    expectedInfo = getMemberInfo(methodKey);
88764562Sgshapiro                }
88890792Sgshapiro            }
88964562Sgshapiro            assertNotNull(expectedInfo, "Not found method: " + methodKey.name());
89090792Sgshapiro            int lastIndexOf = expectedInfo.type.lastIndexOf(')');
89198121Sgshapiro            assertEquals(methodKey.parameterTypes(), expectedInfo.type.substring(1, lastIndexOf), "Parameter types");
89298121Sgshapiro        });
89398121Sgshapiro    }
89498121Sgshapiro
89598121Sgshapiro    public void assertClasses(MemberInfo...expected) {
89698121Sgshapiro        assertMembers(getState().types(), expected);
897102528Sgshapiro    }
89898121Sgshapiro
89964562Sgshapiro    public void assertCompletion(String code, String... expected) {
90064562Sgshapiro        assertCompletion(code, null, expected);
90164562Sgshapiro    }
90264562Sgshapiro
90398121Sgshapiro    public void assertCompletion(String code, Boolean isSmart, String... expected) {
90464562Sgshapiro        List<String> completions = computeCompletions(code, isSmart);
90564562Sgshapiro        assertEquals(completions, Arrays.asList(expected), "Input: " + code + ", " + completions.toString());
90664562Sgshapiro    }
90738032Speter
90890792Sgshapiro    public void assertCompletionIncludesExcludes(String code, Set<String> expected, Set<String> notExpected) {
90938032Speter        assertCompletionIncludesExcludes(code, null, expected, notExpected);
910120256Sgshapiro    }
911182352Sgshapiro
912203004Sgshapiro    public void assertCompletionIncludesExcludes(String code, Boolean isSmart, Set<String> expected, Set<String> notExpected) {
913182352Sgshapiro        List<String> completions = computeCompletions(code, isSmart);
914120256Sgshapiro        assertTrue(completions.containsAll(expected), String.valueOf(completions));
915120256Sgshapiro        assertTrue(Collections.disjoint(completions, notExpected), String.valueOf(completions));
91690792Sgshapiro    }
91790792Sgshapiro
91864562Sgshapiro    private List<String> computeCompletions(String code, Boolean isSmart) {
91964562Sgshapiro        waitIndexingFinished();
92064562Sgshapiro
92164562Sgshapiro        int cursor =  code.indexOf('|');
922173340Sgshapiro        code = code.replace("|", "");
92364562Sgshapiro        assertTrue(cursor > -1, "'|' expected, but not found in: " + code);
92464562Sgshapiro        List<Suggestion> completions =
92564562Sgshapiro                getAnalysis().completionSuggestions(code, cursor, new int[1]); //XXX: ignoring anchor for now
92690792Sgshapiro        return completions.stream()
92790792Sgshapiro                          .filter(s -> isSmart == null || isSmart == s.matchesType())
92894334Sgshapiro                          .map(s -> s.continuation())
92964562Sgshapiro                          .distinct()
93064562Sgshapiro                          .collect(Collectors.toList());
93190792Sgshapiro    }
93264562Sgshapiro
93364562Sgshapiro    public void assertInferredType(String code, String expectedType) {
93464562Sgshapiro        String inferredType = getAnalysis().analyzeType(code, code.length());
93590792Sgshapiro
93690792Sgshapiro        assertEquals(inferredType, expectedType, "Input: " + code + ", " + inferredType);
93794334Sgshapiro    }
93890792Sgshapiro
93990792Sgshapiro    public void assertInferredFQNs(String code, String... fqns) {
94064562Sgshapiro        assertInferredFQNs(code, code.length(), false, fqns);
941157001Sgshapiro    }
942157001Sgshapiro
943157001Sgshapiro    public void assertInferredFQNs(String code, int simpleNameLen, boolean resolvable, String... fqns) {
944157001Sgshapiro        waitIndexingFinished();
945157001Sgshapiro
946157001Sgshapiro        QualifiedNames candidates = getAnalysis().listQualifiedNames(code, code.length());
947157001Sgshapiro
948157001Sgshapiro        assertEquals(candidates.getNames(), Arrays.asList(fqns), "Input: " + code + ", candidates=" + candidates.getNames());
949157001Sgshapiro        assertEquals(candidates.getSimpleNameLength(), simpleNameLen, "Input: " + code + ", simpleNameLen=" + candidates.getSimpleNameLength());
950157001Sgshapiro        assertEquals(candidates.isResolvable(), resolvable, "Input: " + code + ", resolvable=" + candidates.isResolvable());
951157001Sgshapiro    }
952157001Sgshapiro
953182352Sgshapiro    protected void waitIndexingFinished() {
954157001Sgshapiro        try {
95564562Sgshapiro            Method waitBackgroundTaskFinished = getAnalysis().getClass().getDeclaredMethod("waitBackgroundTaskFinished");
95664562Sgshapiro
95764562Sgshapiro            waitBackgroundTaskFinished.setAccessible(true);
95890792Sgshapiro            waitBackgroundTaskFinished.invoke(getAnalysis());
95990792Sgshapiro        } catch (Exception ex) {
96064562Sgshapiro            throw new AssertionError("Cannot wait for indexing end.", ex);
96164562Sgshapiro        }
96290792Sgshapiro    }
96364562Sgshapiro
964161389Sgshapiro    public void assertSignature(String code, String... expected) {
965168515Sgshapiro        int cursor =  code.indexOf('|');
966168515Sgshapiro        code = code.replace("|", "");
967168515Sgshapiro        assertTrue(cursor > -1, "'|' expected, but not found in: " + code);
968161389Sgshapiro        List<Documentation> documentation = getAnalysis().documentation(code, cursor, false);
96964562Sgshapiro        Set<String> docSet = documentation.stream().map(doc -> doc.signature()).collect(Collectors.toSet());
97064562Sgshapiro        Set<String> expectedSet = Stream.of(expected).collect(Collectors.toSet());
97164562Sgshapiro        assertEquals(docSet, expectedSet, "Input: " + code);
97264562Sgshapiro    }
97390792Sgshapiro
97490792Sgshapiro    public void assertJavadoc(String code, String... expected) {
97590792Sgshapiro        int cursor =  code.indexOf('|');
97690792Sgshapiro        code = code.replace("|", "");
97790792Sgshapiro        assertTrue(cursor > -1, "'|' expected, but not found in: " + code);
97864562Sgshapiro        List<Documentation> documentation = getAnalysis().documentation(code, cursor, true);
97964562Sgshapiro        Set<String> docSet = documentation.stream()
98090792Sgshapiro                                          .map(doc -> doc.signature() + "\n" + doc.javadoc())
98164562Sgshapiro                                          .collect(Collectors.toSet());
98264562Sgshapiro        Set<String> expectedSet = Stream.of(expected).collect(Collectors.toSet());
98364562Sgshapiro        assertEquals(docSet, expectedSet, "Input: " + code);
98490792Sgshapiro    }
98590792Sgshapiro
98690792Sgshapiro    public enum ClassType {
98790792Sgshapiro        CLASS("CLASS_SUBKIND", "class", "class"),
98890792Sgshapiro        ENUM("ENUM_SUBKIND", "enum", "enum"),
98990792Sgshapiro        INTERFACE("INTERFACE_SUBKIND", "interface", "interface"),
99090792Sgshapiro        ANNOTATION("ANNOTATION_TYPE_SUBKIND", "@interface", "annotation interface");
99164562Sgshapiro
992110560Sgshapiro        private final String classType;
993110560Sgshapiro        private final String name;
994110560Sgshapiro        private final String displayed;
995110560Sgshapiro
996110560Sgshapiro        ClassType(String classType, String name, String displayed) {
997110560Sgshapiro            this.classType = classType;
998110560Sgshapiro            this.name = name;
999110560Sgshapiro            this.displayed = displayed;
1000110560Sgshapiro        }
1001110560Sgshapiro
1002110560Sgshapiro        public String getClassType() {
1003110560Sgshapiro            return classType;
1004110560Sgshapiro        }
1005110560Sgshapiro
1006110560Sgshapiro        public String getDisplayed() {
100764562Sgshapiro            return displayed;
100890792Sgshapiro        }
100990792Sgshapiro
101064562Sgshapiro        @Override
101190792Sgshapiro        public String toString() {
101264562Sgshapiro            return name;
1013132943Sgshapiro        }
1014132943Sgshapiro    }
1015132943Sgshapiro
1016132943Sgshapiro    public static MemberInfo variable(String type, String name) {
1017132943Sgshapiro        return new MemberInfo(type, name);
1018132943Sgshapiro    }
101990792Sgshapiro
1020132943Sgshapiro    public static MemberInfo method(String signature, String name) {
1021132943Sgshapiro        return new MemberInfo(signature, name);
1022168515Sgshapiro    }
1023132943Sgshapiro
1024132943Sgshapiro    public static MemberInfo clazz(ClassType classType, String className) {
1025132943Sgshapiro        return new MemberInfo(classType.getClassType(), className);
1026132943Sgshapiro    }
1027132943Sgshapiro
1028132943Sgshapiro    public static class MemberInfo {
1029132943Sgshapiro        public final String type;
1030132943Sgshapiro        public final String name;
1031132943Sgshapiro
1032132943Sgshapiro        public MemberInfo(String type, String name) {
1033132943Sgshapiro            this.type = type;
1034132943Sgshapiro            this.name = name;
1035132943Sgshapiro        }
1036132943Sgshapiro
1037132943Sgshapiro        @Override
1038132943Sgshapiro        public int hashCode() {
1039132943Sgshapiro            return type.hashCode() + 3 * name.hashCode();
1040132943Sgshapiro        }
1041132943Sgshapiro
1042132943Sgshapiro        @Override
1043132943Sgshapiro        public boolean equals(Object o) {
1044157001Sgshapiro            if (o instanceof MemberInfo) {
1045168515Sgshapiro                MemberInfo other = (MemberInfo) o;
1046132943Sgshapiro                return type.equals(other.type) && name.equals(other.name);
1047132943Sgshapiro            }
1048132943Sgshapiro            return false;
1049132943Sgshapiro        }
1050132943Sgshapiro
1051132943Sgshapiro        @Override
1052132943Sgshapiro        public String toString() {
1053132943Sgshapiro            return String.format("%s %s", type, name);
1054132943Sgshapiro        }
1055132943Sgshapiro    }
1056132943Sgshapiro
1057132943Sgshapiro    public MemberInfo getMemberInfo(Snippet key) {
1058132943Sgshapiro        SubKind subkind = key.subKind();
1059132943Sgshapiro        switch (subkind) {
1060132943Sgshapiro            case CLASS_SUBKIND:
1061132943Sgshapiro            case INTERFACE_SUBKIND:
1062157001Sgshapiro            case ENUM_SUBKIND:
1063132943Sgshapiro            case ANNOTATION_TYPE_SUBKIND:
1064132943Sgshapiro                return new MemberInfo(subkind.name(), ((DeclarationSnippet) key).name());
1065168515Sgshapiro            case METHOD_SUBKIND:
1066182352Sgshapiro                MethodSnippet method = (MethodSnippet) key;
1067168515Sgshapiro                return new MemberInfo(method.signature(), method.name());
1068132943Sgshapiro            case VAR_DECLARATION_SUBKIND:
1069182352Sgshapiro            case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND:
1070168515Sgshapiro            case TEMP_VAR_EXPRESSION_SUBKIND:
1071157001Sgshapiro                VarSnippet var = (VarSnippet) key;
1072157001Sgshapiro                return new MemberInfo(var.typeName(), var.name());
1073132943Sgshapiro            default:
1074132943Sgshapiro                throw new AssertionError("Unknown snippet : " + key.kind() + " in expression " + key.toString());
1075132943Sgshapiro        }
1076168515Sgshapiro    }
1077132943Sgshapiro
1078168515Sgshapiro    public String diagnosticsToString(List<Diag> diagnostics) {
1079168515Sgshapiro        StringWriter writer = new StringWriter();
1080157001Sgshapiro        for (Diag diag : diagnostics) {
1081157001Sgshapiro            writer.write("Error --\n");
1082132943Sgshapiro            for (String line : diag.getMessage(null).split("\\r?\\n")) {
1083132943Sgshapiro                writer.write(String.format("%s\n", line));
1084132943Sgshapiro            }
1085132943Sgshapiro        }
1086132943Sgshapiro        return writer.toString().replace("\n", System.lineSeparator());
108790792Sgshapiro    }
108890792Sgshapiro
1089120256Sgshapiro    public boolean hasFatalError(List<Diag> diagnostics) {
1090120256Sgshapiro        for (Diag diag : diagnostics) {
109190792Sgshapiro            if (diag.isError()) {
1092120256Sgshapiro                return true;
109390792Sgshapiro            }
109490792Sgshapiro        }
109590792Sgshapiro        return false;
109690792Sgshapiro    }
109790792Sgshapiro
109838032Speter    public static EventChain chain(STEInfo mainInfo, STEInfo... updates) {
109990792Sgshapiro        return chain(mainInfo, IGNORE_VALUE, null, updates);
1100168515Sgshapiro    }
1101168515Sgshapiro
110290792Sgshapiro    public static EventChain chain(STEInfo mainInfo, String value, Class<? extends Throwable> exceptionClass, STEInfo... updates) {
1103168515Sgshapiro        return new EventChain(mainInfo, value, exceptionClass, updates);
110490792Sgshapiro    }
110538032Speter
110638032Speter    public static STEInfo ste(Snippet key, Status previousStatus, Status status,
110738032Speter                Boolean isSignatureChange, Snippet causeKey) {
110838032Speter        return new STEInfo(key, previousStatus, status, isSignatureChange, causeKey);
110938032Speter    }
111038032Speter
111164562Sgshapiro    public static STEInfo added(Status status) {
1112168515Sgshapiro        return new STEInfo(MAIN_SNIPPET, NONEXISTENT, status, status.isDefined(), null);
111364562Sgshapiro    }
111464562Sgshapiro
1115168515Sgshapiro    public static class EventChain {
111664562Sgshapiro        public final STEInfo mainInfo;
111766494Sgshapiro        public final STEInfo[] updates;
111838032Speter        public final String value;
111938032Speter        public final Class<? extends Throwable> exceptionClass;
112038032Speter
112138032Speter        public EventChain(STEInfo mainInfo, String value, Class<? extends Throwable> exceptionClass, STEInfo... updates) {
112238032Speter            this.mainInfo = mainInfo;
112338032Speter            this.updates = updates;
112438032Speter            this.value = value;
1125168515Sgshapiro            this.exceptionClass = exceptionClass;
112664562Sgshapiro        }
112738032Speter    }
112838032Speter
112938032Speter    public static class STEInfo {
113038032Speter
113138032Speter        STEInfo(Snippet snippet, Status previousStatus, Status status,
1132168515Sgshapiro                Boolean isSignatureChange, Snippet causeSnippet) {
113364562Sgshapiro            this.snippet = snippet;
113438032Speter            this.previousStatus = previousStatus;
113538032Speter            this.status = status;
113638032Speter            this.checkIsSignatureChange = isSignatureChange != null;
113738032Speter            this.isSignatureChange = checkIsSignatureChange ? isSignatureChange : false;
113890792Sgshapiro            this.causeSnippet = causeSnippet;
113990792Sgshapiro            assertTrue(snippet != null, "Bad test set-up. The match snippet must not be null");
114090792Sgshapiro        }
114190792Sgshapiro
114290792Sgshapiro        final Snippet snippet;
114390792Sgshapiro        final Status previousStatus;
114490792Sgshapiro        final Status status;
114590792Sgshapiro        final boolean isSignatureChange;
114690792Sgshapiro        final Snippet causeSnippet;
114790792Sgshapiro
114890792Sgshapiro         final boolean checkIsSignatureChange;
114990792Sgshapiro        public Snippet snippet() {
115090792Sgshapiro            return snippet;
115138032Speter        }
115238032Speter        public Status previousStatus() {
115390792Sgshapiro            return previousStatus;
115490792Sgshapiro        }
115590792Sgshapiro        public Status status() {
115690792Sgshapiro            return status;
115790792Sgshapiro        }
115890792Sgshapiro        public boolean isSignatureChange() {
115990792Sgshapiro            if (!checkIsSignatureChange) {
116038032Speter                throw new IllegalStateException("isSignatureChange value is undefined");
1161168515Sgshapiro            }
1162168515Sgshapiro            return isSignatureChange;
1163168515Sgshapiro        }
116438032Speter        public Snippet causeSnippet() {
116538032Speter            return causeSnippet;
116638032Speter        }
116738032Speter        public String value() {
116864562Sgshapiro            return null;
116990792Sgshapiro        }
117038032Speter        public Exception exception() {
117138032Speter            return null;
117238032Speter        }
117390792Sgshapiro
117438032Speter        public void assertMatch(SnippetEvent ste, Snippet mainSnippet) {
117538032Speter            assertKeyMatch(ste, ste.snippet(), snippet(), mainSnippet);
117690792Sgshapiro            assertStatusMatch(ste, ste.previousStatus(), previousStatus());
1177168515Sgshapiro            assertStatusMatch(ste, ste.status(), status());
117864562Sgshapiro            if (checkIsSignatureChange) {
117938032Speter                assertEquals(ste.isSignatureChange(), isSignatureChange(),
118064562Sgshapiro                        "Expected " +
118164562Sgshapiro                                (isSignatureChange()? "" : "no ") +
118290792Sgshapiro                                "signature-change, got: " +
118364562Sgshapiro                                (ste.isSignatureChange()? "" : "no ") +
118464562Sgshapiro                                "signature-change" +
118538032Speter                        "\n   expected-event: " + this + "\n   got-event: " + toString(ste));
118638032Speter            }
118764562Sgshapiro            assertKeyMatch(ste, ste.causeSnippet(), causeSnippet(), mainSnippet);
118890792Sgshapiro        }
118964562Sgshapiro
119064562Sgshapiro        private void assertKeyMatch(SnippetEvent ste, Snippet sn, Snippet expected, Snippet mainSnippet) {
119190792Sgshapiro            Snippet testKey = expected;
119264562Sgshapiro            if (testKey != null) {
119364562Sgshapiro                if (expected == MAIN_SNIPPET) {
119438032Speter                    assertNotNull(mainSnippet, "MAIN_SNIPPET used, test must pass value to assertMatch");
119590792Sgshapiro                    testKey = mainSnippet;
119638032Speter                }
1197110560Sgshapiro                if (ste.causeSnippet() == null && ste.status() != DROPPED && expected != MAIN_SNIPPET) {
119864562Sgshapiro                    // Source change, always new snippet -- only match id()
119964562Sgshapiro                    assertTrue(sn != testKey,
120038032Speter                            "Main-event: Expected new snippet to be != : " + testKey
120142575Speter                            + "\n   got-event: " + toString(ste));
120242575Speter                    assertEquals(sn.id(), testKey.id(), "Expected IDs to match: " + testKey + ", got: " + sn
120338032Speter                            + "\n   expected-event: " + this + "\n   got-event: " + toString(ste));
120464562Sgshapiro                } else {
120538032Speter                    assertEquals(sn, testKey, "Expected key to be: " + testKey + ", got: " + sn
120638032Speter                            + "\n   expected-event: " + this + "\n   got-event: " + toString(ste));
120764562Sgshapiro                }
120838032Speter            }
120938032Speter        }
1210168515Sgshapiro
1211168515Sgshapiro        private void assertStatusMatch(SnippetEvent ste, Status status, Status expected) {
1212168515Sgshapiro            if (expected != null) {
1213168515Sgshapiro                assertEquals(status, expected, "Expected status to be: " + expected + ", got: " + status +
1214168515Sgshapiro                        "\n   expected-event: " + this + "\n   got-event: " + toString(ste));
1215168515Sgshapiro            }
1216168515Sgshapiro        }
1217168515Sgshapiro
1218168515Sgshapiro        @Override
1219168515Sgshapiro        public String toString() {
1220168515Sgshapiro            return "STEInfo key: " +
1221168515Sgshapiro                    (snippet()==MAIN_SNIPPET? "MAIN_SNIPPET" : (snippet()==null? "ignore" : snippet().id())) +
1222168515Sgshapiro                    " before: " + previousStatus() +
1223168515Sgshapiro                    " status: " + status() + " sig: " + isSignatureChange() +
1224168515Sgshapiro                    " cause: " + (causeSnippet()==null? "null" : causeSnippet().id());
1225168515Sgshapiro        }
1226168515Sgshapiro
1227168515Sgshapiro        private String toString(SnippetEvent ste) {
1228168515Sgshapiro            return "key: " + (ste.snippet()==MAIN_SNIPPET? "MAIN_SNIPPET" : ste.snippet().id()) + " before: " + ste.previousStatus()
1229168515Sgshapiro                    + " status: " + ste.status() + " sig: " + ste.isSignatureChange()
1230168515Sgshapiro                    + " cause: " + ste.causeSnippet();
1231168515Sgshapiro        }
123290792Sgshapiro    }
123390792Sgshapiro}
1234168515Sgshapiro