EditorTestBase.java revision 3849:b2e915d476be
1/*
2 * Copyright (c) 2015, 2016, 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.util.concurrent.ExecutorService;
25import java.util.concurrent.Executors;
26import java.util.function.Consumer;
27
28import org.testng.annotations.Test;
29
30import static org.testng.Assert.assertEquals;
31import static org.testng.Assert.assertTrue;
32
33public abstract class EditorTestBase extends ReplToolTesting {
34
35    private static ExecutorService executor;
36
37    public abstract void writeSource(String s);
38    public abstract String getSource();
39    public abstract void accept();
40    public abstract void exit();
41    public abstract void cancel();
42    public abstract void shutdownEditor();
43
44    public void testEditor(ReplTest... tests) {
45        testEditor(false, new String[]{"--no-startup"}, tests);
46    }
47
48    public void testEditor(boolean defaultStartup, String[] args, ReplTest... tests) {
49        test(defaultStartup, args, tests);
50    }
51
52    public abstract void assertEdit(boolean after, String cmd,
53                                    Consumer<String> checkInput, Consumer<String> checkOutput, Action action);
54
55    public void assertEditInput(boolean after, String cmd, Consumer<String> checkInput, Action action) {
56        assertEdit(after, cmd, checkInput, s -> {}, action);
57    }
58
59    public void assertEditOutput(boolean after, String cmd, Consumer<String> checkOutput, Action action) {
60        assertEdit(after, cmd, s -> {}, checkOutput, action);
61    }
62
63    public void assertEditInput(boolean after, String cmd, String input, Action action) {
64        assertEditInput(after, cmd, s -> assertEquals(s, input, "Input"), action);
65    }
66
67    public void assertEditOutput(boolean after, String cmd, String output, Action action) {
68        assertEditOutput(after, cmd, s -> assertEquals(s.trim(), output.trim(), "command"), action);
69    }
70
71    @Test
72    public void testEditNegative() {
73        for (String edit : new String[] {"/ed", "/edit"}) {
74            test(new String[]{"--no-startup"},
75                    a -> assertCommandOutputStartsWith(a, edit + " 1",
76                            "|  No such snippet: 1"),
77                    a -> assertCommandOutputStartsWith(a, edit + " unknown",
78                            "|  No such snippet: unknown")
79            );
80        }
81    }
82
83    @Test
84    public void testDoNothing() {
85        testEditor(
86                a -> assertVariable(a, "int", "a", "0", "0"),
87                a -> assertEditOutput(a, "/ed 1", "", this::exit),
88                a -> assertCommandCheckOutput(a, "/v", assertVariables())
89        );
90    }
91
92    @Test
93    public void testEditVariable1() {
94        testEditor(
95                a -> assertVariable(a, "int", "a", "0", "0"),
96                a -> assertEditOutput(a, "/ed 1", "a ==> 10", () -> {
97                    writeSource("\n\n\nint a = 10;\n\n\n");
98                    exit();
99                    loadVariable(true, "int", "a", "10", "10");
100                }),
101                a -> assertEditOutput(a, "/ed 1", "a ==> 15", () -> {
102                    writeSource("int a = 15;");
103                    exit();
104                    loadVariable(true, "int", "a", "15", "15");
105                }),
106                a -> assertCommandCheckOutput(a, "/v", assertVariables())
107        );
108    }
109
110    @Test
111    public void testEditVariable2() {
112        testEditor(
113                a -> assertVariable(a, "int", "a", "0", "0"),
114                a -> assertEditOutput(a, "/ed 1", "b ==> 10", () -> {
115                    writeSource("int b = 10;");
116                    exit();
117                    loadVariable(true, "int", "b", "10", "10");
118                }),
119                a -> assertEditOutput(a, "/ed 1", "a ==> 15", () -> {
120                    writeSource("int a = 15;");
121                    exit();
122                    loadVariable(true, "int", "a", "15", "15");
123                }),
124                a -> assertCommandCheckOutput(a, "/v", assertVariables())
125        );
126    }
127
128    public void testEditClass1() {
129        testEditor(
130                a -> assertClass(a, "class A {}", "class", "A"),
131                a -> assertEditOutput(a, "/ed 1", "", () -> {
132                    writeSource("\n\n\nclass A {}\n\n\n");
133                    exit();
134                    loadClass(true, "class A {}", "class", "A");
135                }),
136                a -> assertEditOutput(a, "/ed 1",
137                        "|  replaced enum A", () -> {
138                    writeSource("enum A {}");
139                    exit();
140                    loadClass(true, "enum A {}", "enum", "A");
141                }),
142                a -> assertCommandCheckOutput(a, "/types", assertClasses())
143        );
144    }
145
146    @Test
147    public void testEditClass2() {
148        testEditor(
149                a -> assertClass(a, "class A {}", "class", "A"),
150                a -> assertEditOutput(a, "/ed 1", "|  created class B", () -> {
151                    writeSource("class B { }");
152                    exit();
153                    loadClass(true, "class B {}", "class", "B");
154                }),
155                a -> assertEditOutput(a, "/ed 1",
156                        "|  replaced enum A", () -> {
157                    writeSource("enum A {}");
158                    exit();
159                    loadClass(true, "enum A {}", "enum", "A");
160                }),
161                a -> assertCommandCheckOutput(a, "/types", assertClasses())
162        );
163    }
164
165    public void testEditMethod1() {
166        testEditor(
167                a -> assertMethod(a, "void f() {}", "()void", "f"),
168                a -> assertEditOutput(a, "/ed 1", "", () -> {
169                    writeSource("\n\n\nvoid f() {}\n\n\n");
170                    exit();
171                    loadMethod(true, "void f() {}", "()void", "f");
172                }),
173                a -> assertEditOutput(a, "/ed 1",
174                        "|  replaced method f()", () -> {
175                    writeSource("double f() { return 0; }");
176                    exit();
177                    loadMethod(true, "double f() { return 0; }", "()double", "f");
178                }),
179                a -> assertCommandCheckOutput(a, "/m", assertMethods())
180        );
181    }
182
183    @Test
184    public void testEditMethod2() {
185        testEditor(
186                a -> assertMethod(a, "void f() {}", "()void", "f"),
187                a -> assertEditOutput(a, "/ed 1", "|  created method g()", () -> {
188                    writeSource("void g() {}");
189                    exit();
190                    loadMethod(true, "void g() {}", "()void", "g");
191                }),
192                a -> assertEditOutput(a, "/ed 1",
193                        "|  replaced method f()", () -> {
194                    writeSource("double f() { return 0; }");
195                    exit();
196                    loadMethod(true, "double f() { return 0; }", "()double", "f");
197                }),
198                a -> assertCommandCheckOutput(a, "/m", assertMethods())
199        );
200    }
201
202    @Test
203    public void testNoArguments() {
204        testEditor(
205                a -> assertVariable(a, "int", "a"),
206                a -> assertMethod(a, "void f() {}", "()void", "f"),
207                a -> assertClass(a, "class A {}", "class", "A"),
208                a -> assertEditInput(a, "/ed", s -> {
209                    String[] ss = s.split("\n");
210                    assertEquals(ss.length, 3, "Expected 3 lines: " + s);
211                    assertEquals(ss[0], "int a;");
212                    assertEquals(ss[1], "void f() {}");
213                    assertEquals(ss[2], "class A {}");
214                }, this::exit)
215        );
216    }
217
218    @Test
219    public void testStartup() {
220        testEditor(true, new String[0],
221                a -> assertEditInput(a, "/ed", s -> assertTrue(s.isEmpty(), "Checking of startup: " + s), this::cancel),
222                a -> assertEditInput(a, "/ed s1", assertStartsWith("import"), this::cancel));
223    }
224
225    @Test
226    public void testCancel() {
227        testEditor(
228                a -> assertVariable(a, "int", "a"),
229                a -> assertEditOutput(a, "/ed a", "", () -> {
230                    writeSource("int b = 10");
231                    cancel();
232                })
233        );
234    }
235
236    @Test
237    public void testAccept() {
238        testEditor(
239                a -> assertVariable(a, "int", "a"),
240                a -> assertEditOutput(a, "/ed a", "b ==> 10", () -> {
241                    writeSource("int b = 10");
242                    accept();
243                    exit();
244                })
245        );
246    }
247
248    @Test
249    public void testStatementMush() {
250        testEditor(
251                a -> assertCommand(a, "System.out.println(\"Hello\")",
252                        "", "", null, "Hello\n", ""),
253                a -> assertEditOutput(a, "/ed", "b ==> 10", () -> {
254                    writeSource(getSource() + "\nint b = 10");
255                    exit();
256                }),
257
258                //TODO: this is a work-around to JDK-8170369
259                a -> assertCommand(a, "1234",
260                        null, "", null, null, "")
261        );
262    }
263
264    public static ExecutorService getExecutor() {
265        if (executor == null) {
266            executor = Executors.newSingleThreadExecutor();
267        }
268        return executor;
269    }
270
271    public static void executorShutdown() {
272        if (executor != null) {
273            executor.shutdown();
274            executor = null;
275        }
276    }
277
278    interface Action {
279        void accept();
280    }
281}
282