1/*
2 * Copyright (c) 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
24/*
25 * @test
26 * @bug 8168615
27 * @summary Test that fail-over works for fail-over ExecutionControlProvider
28 * with direct maps.
29 * @modules jdk.compiler/com.sun.tools.javac.api
30 *          jdk.compiler/com.sun.tools.javac.main
31 *          jdk.jdeps/com.sun.tools.javap
32 *          jdk.jshell/jdk.jshell.execution
33 *          jdk.jshell/jdk.jshell.spi
34 * @library /tools/lib
35 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
36 * @build KullaTesting ExecutionControlTestBase Compiler
37 * @run testng FailOverDirectExecutionControlTest
38 */
39
40import java.nio.file.Path;
41import java.nio.file.Paths;
42import java.util.ArrayList;
43import java.util.HashMap;
44import java.util.List;
45import java.util.Map;
46import java.util.logging.Handler;
47import java.util.logging.Level;
48import java.util.logging.LogRecord;
49import java.util.logging.Logger;
50import org.testng.annotations.AfterMethod;
51import org.testng.annotations.Test;
52import org.testng.annotations.BeforeMethod;
53import jdk.jshell.execution.FailOverExecutionControlProvider;
54import jdk.jshell.spi.ExecutionControlProvider;
55import static org.testng.Assert.assertEquals;
56import static org.testng.Assert.assertNull;
57import static org.testng.Assert.assertTrue;
58
59@Test
60public class FailOverDirectExecutionControlTest extends ExecutionControlTestBase {
61
62    ClassLoader ccl;
63    ExecutionControlProvider provider;
64    LogTestHandler hndlr;
65    Map<Level, List<String>> logged;
66
67    private class LogTestHandler extends Handler {
68
69        LogTestHandler() {
70            setLevel(Level.ALL);
71            setFilter(lr -> lr.getLoggerName().equals("jdk.jshell.execution"));
72        }
73
74        @Override
75        public void publish(LogRecord lr) {
76            List<String> l = logged.get(lr.getLevel());
77            if (l == null) {
78                l = new ArrayList<>();
79                logged.put(lr.getLevel(), l);
80            }
81            l.add(lr.getMessage());
82        }
83
84        @Override
85        public void flush() {
86        }
87
88        @Override
89        public void close() throws SecurityException {
90        }
91
92    }
93
94    @BeforeMethod
95    @Override
96    public void setUp() {
97        Logger logger = Logger.getLogger("jdk.jshell.execution");
98        logger.setLevel(Level.ALL);
99        hndlr = new LogTestHandler();
100        logger.addHandler(hndlr);
101        logged = new HashMap<>();
102        Compiler compiler = new Compiler();
103        Path modDir = Paths.get("mod");
104        compiler.compile(modDir,
105                "package my.provide; import java.util.Map;\n" +
106                "import jdk.jshell.spi.ExecutionControl;\n" +
107                "import jdk.jshell.spi.ExecutionControlProvider;\n" +
108                "import jdk.jshell.spi.ExecutionEnv;\n" +
109                "public class AlwaysFailingProvider implements ExecutionControlProvider {\n" +
110                "    @Override\n" +
111                "    public String name() {\n" +
112                "        return \"alwaysFailing\";\n" +
113                "    }\n" +
114                "    @Override\n" +
115                "    public ExecutionControl generate(ExecutionEnv env, Map<String, String> parameters) throws Throwable {\n" +
116                "        throw new UnsupportedOperationException(\"This operation intentionally broken.\");\n" +
117                "    }\n" +
118                "}\n",
119                "module my.provide {\n" +
120                "    requires transitive jdk.jshell;\n" +
121                "    provides jdk.jshell.spi.ExecutionControlProvider\n" +
122                "        with my.provide.AlwaysFailingProvider;\n" +
123                " }");
124        Path modPath = compiler.getPath(modDir);
125        ccl = createAndRunFromModule("my.provide", modPath);
126
127        provider = new FailOverExecutionControlProvider();
128        Map<String, String> pm = provider.defaultParameters();
129        pm.put("0", "alwaysFailing");
130        pm.put("1", "alwaysFailing");
131        pm.put("2", "jdi");
132        setUp(builder -> builder.executionEngine(provider, pm));
133    }
134
135    @AfterMethod
136    @Override
137    public void tearDown() {
138        super.tearDown();
139        Logger logger = Logger.getLogger("jdk.jshell.execution");
140        logger.removeHandler(hndlr);
141        Thread.currentThread().setContextClassLoader(ccl);
142    }
143
144    @Override
145    public void variables() {
146        super.variables();
147        assertEquals(logged.get(Level.FINEST).size(), 1);
148        assertEquals(logged.get(Level.FINE).size(), 2);
149        assertEquals(logged.get(Level.WARNING).size(), 2);
150        assertNull(logged.get(Level.SEVERE));
151        String log = logged.get(Level.WARNING).get(0);
152        assertTrue(log.contains("Failure failover -- 0 = alwaysFailing"), log);
153        assertTrue(log.contains("This operation intentionally broken"), log);
154        log = logged.get(Level.WARNING).get(1);
155        assertTrue(log.contains("Failure failover -- 1 = alwaysFailing"), log);
156        assertTrue(log.contains("This operation intentionally broken"), log);
157        log = logged.get(Level.FINEST).get(0);
158        assertTrue(log.contains("Success failover -- 2 = jdi"), log);
159    }
160}
161