EditorTestBase.java revision 3062:15bdc18525ff
1/*
2 * Copyright (c) 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.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[]{"-nostartup"}, 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, output, "command"), action);
69    }
70
71    @Test
72    public void testEditNegative() {
73        for (String edit : new String[] {"/e", "/edit"}) {
74            test(new String[]{"-nostartup"},
75                    a -> assertCommand(a, edit + " 1",
76                            "|  No definition or id named 1 found.  See /classes /methods /vars or /list\n"),
77                    a -> assertCommand(a, edit + " -1",
78                            "|  No definition or id named -1 found.  See /classes /methods /vars or /list\n"),
79                    a -> assertCommand(a, edit + " unknown",
80                            "|  No definition or id named unknown found.  See /classes /methods /vars or /list\n")
81            );
82        }
83    }
84
85    @Test
86    public void testDoNothing() {
87        testEditor(
88                a -> assertVariable(a, "int", "a", "0", "0"),
89                a -> assertEditOutput(a, "/e 1", "", this::exit),
90                a -> assertCommandCheckOutput(a, "/v", assertVariables())
91        );
92    }
93
94    @Test
95    public void testEditVariable1() {
96        testEditor(
97                a -> assertVariable(a, "int", "a", "0", "0"),
98                a -> assertEditOutput(a, "/e 1", "|  Modified variable a of type int with initial value 10\n", () -> {
99                    writeSource("\n\n\nint a = 10;\n\n\n");
100                    exit();
101                    loadVariable(true, "int", "a", "10", "10");
102                }),
103                a -> assertEditOutput(a, "/e 1", "|  Modified variable a of type int with initial value 15\n", () -> {
104                    writeSource("int a = 15;");
105                    exit();
106                    loadVariable(true, "int", "a", "15", "15");
107                }),
108                a -> assertCommandCheckOutput(a, "/v", assertVariables())
109        );
110    }
111
112    @Test
113    public void testEditVariable2() {
114        testEditor(
115                a -> assertVariable(a, "int", "a", "0", "0"),
116                a -> assertEditOutput(a, "/e 1", "|  Added variable b of type int with initial value 10\n", () -> {
117                    writeSource("int b = 10;");
118                    exit();
119                    loadVariable(true, "int", "b", "10", "10");
120                }),
121                a -> assertEditOutput(a, "/e 1", "|  Modified variable a of type int with initial value 15\n", () -> {
122                    writeSource("int a = 15;");
123                    exit();
124                    loadVariable(true, "int", "a", "15", "15");
125                }),
126                a -> assertCommandCheckOutput(a, "/v", assertVariables())
127        );
128    }
129
130    @Test
131    public void testEditClass1() {
132        testEditor(
133                a -> assertClass(a, "class A {}", "class", "A"),
134                a -> assertEditOutput(a, "/e 1", "", () -> {
135                    writeSource("\n\n\nclass A {}\n\n\n");
136                    exit();
137                    loadClass(true, "class A {}", "class", "A");
138                }),
139                a -> assertEditOutput(a, "/e 1",
140                        "|  Replaced enum A\n" +
141                        "|    Update overwrote class A\n", () -> {
142                    writeSource("enum A {}");
143                    exit();
144                    loadClass(true, "enum A {}", "enum", "A");
145                }),
146                a -> assertCommandCheckOutput(a, "/c", assertClasses())
147        );
148    }
149
150    @Test
151    public void testEditClass2() {
152        testEditor(
153                a -> assertClass(a, "class A {}", "class", "A"),
154                a -> assertEditOutput(a, "/e 1", "|  Added class B\n", () -> {
155                    writeSource("class B { }");
156                    exit();
157                    loadClass(true, "class B {}", "class", "B");
158                }),
159                a -> assertEditOutput(a, "/e 1",
160                        "|  Replaced enum A\n" +
161                        "|    Update overwrote class A\n", () -> {
162                    writeSource("enum A {}");
163                    exit();
164                    loadClass(true, "enum A {}", "enum", "A");
165                }),
166                a -> assertCommandCheckOutput(a, "/c", assertClasses())
167        );
168    }
169
170    @Test
171    public void testEditMethod1() {
172        testEditor(
173                a -> assertMethod(a, "void f() {}", "()void", "f"),
174                a -> assertEditOutput(a, "/e 1", "", () -> {
175                    writeSource("\n\n\nvoid f() {}\n\n\n");
176                    exit();
177                    loadMethod(true, "void f() {}", "()void", "f");
178                }),
179                a -> assertEditOutput(a, "/e 1",
180                        "|  Replaced method f()\n" +
181                        "|    Update overwrote method f()\n", () -> {
182                    writeSource("double f() { return 0; }");
183                    exit();
184                    loadMethod(true, "double f() { return 0; }", "()double", "f");
185                }),
186                a -> assertCommandCheckOutput(a, "/m", assertMethods())
187        );
188    }
189
190    @Test
191    public void testEditMethod2() {
192        testEditor(
193                a -> assertMethod(a, "void f() {}", "()void", "f"),
194                a -> assertEditOutput(a, "/e 1", "|  Added method g()\n", () -> {
195                    writeSource("void g() {}");
196                    exit();
197                    loadMethod(true, "void g() {}", "()void", "g");
198                }),
199                a -> assertEditOutput(a, "/e 1",
200                        "|  Replaced method f()\n" +
201                        "|    Update overwrote method f()\n", () -> {
202                    writeSource("double f() { return 0; }");
203                    exit();
204                    loadMethod(true, "double f() { return 0; }", "()double", "f");
205                }),
206                a -> assertCommandCheckOutput(a, "/m", assertMethods())
207        );
208    }
209
210    @Test
211    public void testNoArguments() {
212        testEditor(
213                a -> assertVariable(a, "int", "a"),
214                a -> assertMethod(a, "void f() {}", "()void", "f"),
215                a -> assertClass(a, "class A {}", "class", "A"),
216                a -> assertEditInput(a, "/e", s -> {
217                    String[] ss = s.split("\n");
218                    assertEquals(ss.length, 3, "Expected 3 lines: " + s);
219                    assertEquals(ss[0], "int a;");
220                    assertEquals(ss[1], "void f() {}");
221                    assertEquals(ss[2], "class A {}");
222                }, this::exit)
223        );
224    }
225
226    @Test
227    public void testStartup() {
228        testEditor(true, new String[0],
229                a -> assertEditInput(a, "/e", s -> assertTrue(s.isEmpty(), "Checking of startup: " + s), this::cancel),
230                a -> assertEditInput(a, "/e printf", assertStartsWith("void printf"), this::cancel));
231    }
232
233    @Test
234    public void testCancel() {
235        testEditor(
236                a -> assertVariable(a, "int", "a"),
237                a -> assertEditOutput(a, "/e a", "", () -> {
238                    writeSource("int b = 10");
239                    cancel();
240                })
241        );
242    }
243
244    @Test
245    public void testAccept() {
246        testEditor(
247                a -> assertVariable(a, "int", "a"),
248                a -> assertEditOutput(a, "/e a", "|  Added variable b of type int with initial value 10\n", () -> {
249                    writeSource("int b = 10");
250                    accept();
251                    exit();
252                })
253        );
254    }
255
256    public static ExecutorService getExecutor() {
257        if (executor == null) {
258            executor = Executors.newSingleThreadExecutor();
259        }
260        return executor;
261    }
262
263    public static void executorShutdown() {
264        if (executor != null) {
265            executor.shutdown();
266            executor = null;
267        }
268    }
269
270    interface Action {
271        void accept();
272    }
273}
274