EditorTestBase.java revision 3403:d59aae1fe07b
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[]{"-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.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[]{"-nostartup"},
75                    a -> assertCommandOutputStartsWith(a, edit + " 1",
76                            "|  No definition or id found named: 1"),
77                    a -> assertCommandOutputStartsWith(a, edit + " -1",
78                            "|  No definition or id found named: -1"),
79                    a -> assertCommandOutputStartsWith(a, edit + " unknown",
80                            "|  No definition or id found named: unknown")
81            );
82        }
83    }
84
85    @Test
86    public void testDoNothing() {
87        testEditor(
88                a -> assertVariable(a, "int", "a", "0", "0"),
89                a -> assertEditOutput(a, "/ed 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, "/ed 1", "a ==> 10", () -> {
99                    writeSource("\n\n\nint a = 10;\n\n\n");
100                    exit();
101                    loadVariable(true, "int", "a", "10", "10");
102                }),
103                a -> assertEditOutput(a, "/ed 1", "a ==> 15", () -> {
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, "/ed 1", "b ==> 10", () -> {
117                    writeSource("int b = 10;");
118                    exit();
119                    loadVariable(true, "int", "b", "10", "10");
120                }),
121                a -> assertEditOutput(a, "/ed 1", "a ==> 15", () -> {
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, "/ed 1", "", () -> {
135                    writeSource("\n\n\nclass A {}\n\n\n");
136                    exit();
137                    loadClass(true, "class A {}", "class", "A");
138                }),
139                a -> assertEditOutput(a, "/ed 1",
140                        "|  replaced enum A", () -> {
141                    writeSource("enum A {}");
142                    exit();
143                    loadClass(true, "enum A {}", "enum", "A");
144                }),
145                a -> assertCommandCheckOutput(a, "/types", assertClasses())
146        );
147    }
148
149    @Test
150    public void testEditClass2() {
151        testEditor(
152                a -> assertClass(a, "class A {}", "class", "A"),
153                a -> assertEditOutput(a, "/ed 1", "|  created class B", () -> {
154                    writeSource("class B { }");
155                    exit();
156                    loadClass(true, "class B {}", "class", "B");
157                }),
158                a -> assertEditOutput(a, "/ed 1",
159                        "|  replaced enum A", () -> {
160                    writeSource("enum A {}");
161                    exit();
162                    loadClass(true, "enum A {}", "enum", "A");
163                }),
164                a -> assertCommandCheckOutput(a, "/types", assertClasses())
165        );
166    }
167
168    @Test
169    public void testEditMethod1() {
170        testEditor(
171                a -> assertMethod(a, "void f() {}", "()void", "f"),
172                a -> assertEditOutput(a, "/ed 1", "", () -> {
173                    writeSource("\n\n\nvoid f() {}\n\n\n");
174                    exit();
175                    loadMethod(true, "void f() {}", "()void", "f");
176                }),
177                a -> assertEditOutput(a, "/ed 1",
178                        "|  replaced method f()", () -> {
179                    writeSource("double f() { return 0; }");
180                    exit();
181                    loadMethod(true, "double f() { return 0; }", "()double", "f");
182                }),
183                a -> assertCommandCheckOutput(a, "/m", assertMethods())
184        );
185    }
186
187    @Test
188    public void testEditMethod2() {
189        testEditor(
190                a -> assertMethod(a, "void f() {}", "()void", "f"),
191                a -> assertEditOutput(a, "/ed 1", "|  created method g()", () -> {
192                    writeSource("void g() {}");
193                    exit();
194                    loadMethod(true, "void g() {}", "()void", "g");
195                }),
196                a -> assertEditOutput(a, "/ed 1",
197                        "|  replaced method f()", () -> {
198                    writeSource("double f() { return 0; }");
199                    exit();
200                    loadMethod(true, "double f() { return 0; }", "()double", "f");
201                }),
202                a -> assertCommandCheckOutput(a, "/m", assertMethods())
203        );
204    }
205
206    @Test
207    public void testNoArguments() {
208        testEditor(
209                a -> assertVariable(a, "int", "a"),
210                a -> assertMethod(a, "void f() {}", "()void", "f"),
211                a -> assertClass(a, "class A {}", "class", "A"),
212                a -> assertEditInput(a, "/ed", s -> {
213                    String[] ss = s.split("\n");
214                    assertEquals(ss.length, 3, "Expected 3 lines: " + s);
215                    assertEquals(ss[0], "int a;");
216                    assertEquals(ss[1], "void f() {}");
217                    assertEquals(ss[2], "class A {}");
218                }, this::exit)
219        );
220    }
221
222    @Test
223    public void testStartup() {
224        testEditor(true, new String[0],
225                a -> assertEditInput(a, "/ed", s -> assertTrue(s.isEmpty(), "Checking of startup: " + s), this::cancel),
226                a -> assertEditInput(a, "/ed printf", assertStartsWith("void printf"), this::cancel));
227    }
228
229    @Test
230    public void testCancel() {
231        testEditor(
232                a -> assertVariable(a, "int", "a"),
233                a -> assertEditOutput(a, "/ed a", "", () -> {
234                    writeSource("int b = 10");
235                    cancel();
236                })
237        );
238    }
239
240    @Test
241    public void testAccept() {
242        testEditor(
243                a -> assertVariable(a, "int", "a"),
244                a -> assertEditOutput(a, "/ed a", "b ==> 10", () -> {
245                    writeSource("int b = 10");
246                    accept();
247                    exit();
248                })
249        );
250    }
251
252    public static ExecutorService getExecutor() {
253        if (executor == null) {
254            executor = Executors.newSingleThreadExecutor();
255        }
256        return executor;
257    }
258
259    public static void executorShutdown() {
260        if (executor != null) {
261            executor.shutdown();
262            executor = null;
263        }
264    }
265
266    interface Action {
267        void accept();
268    }
269}
270