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.io.IOException;
25import java.net.BindException;
26import java.util.Properties;
27import java.util.function.Predicate;
28import static org.testng.Assert.*;
29import org.testng.annotations.AfterMethod;
30import org.testng.annotations.BeforeClass;
31import org.testng.annotations.BeforeMethod;
32import org.testng.annotations.BeforeTest;
33import org.testng.annotations.Test;
34
35import jdk.testlibrary.ProcessTools;
36
37
38/**
39 * @test
40 * @bug 8075926
41 * @key intermittent
42 * @summary Makes sure that the current management agent status is reflected
43 *          in the related performance counters.
44 *
45 * @library /lib/testlibrary
46 *
47 * @build jdk.testlibrary.* PortAllocator TestApp ManagementAgentJcmd
48 * @run testng/othervm -XX:+UsePerfData JMXStatusPerfCountersTest
49 */
50public class JMXStatusPerfCountersTest {
51    private final static String TEST_APP_NAME = "TestApp";
52
53    private final static String REMOTE_STATUS_KEY = "sun.management.JMXConnectorServer.remote.enabled";
54
55    private static ProcessBuilder testAppPb;
56    private Process testApp;
57
58    private ManagementAgentJcmd jcmd;
59
60    @BeforeClass
61    public static void setupClass() throws Exception {
62        testAppPb = ProcessTools.createJavaProcessBuilder(
63            "-XX:+UsePerfData",
64            "-cp", System.getProperty("test.class.path"),
65            TEST_APP_NAME
66        );
67    }
68
69    @BeforeTest
70    public void setup() {
71        jcmd = new ManagementAgentJcmd(TEST_APP_NAME, false);
72    }
73
74    @BeforeMethod
75    public void startTestApp() throws Exception {
76        testApp = ProcessTools.startProcess(
77            TEST_APP_NAME, testAppPb,
78            (Predicate<String>)l->l.trim().equals("main enter")
79        );
80    }
81
82    @AfterMethod
83    public void stopTestApp() throws Exception {
84        testApp.getOutputStream().write(1);
85        testApp.getOutputStream().flush();
86        testApp.waitFor();
87        testApp = null;
88    }
89
90    /**
91     * The 'sun.management.JMXConnectorServer.remote.enabled' counter must not be
92     * exported if the remote agent is not enabled.
93     * @throws Exception
94     */
95    @Test
96    public void testNotInitializedRemote() throws Exception {
97        assertFalse(
98            getCounters().containsKey(REMOTE_STATUS_KEY),
99            "Unexpected occurrence of " + REMOTE_STATUS_KEY + " in perf counters"
100        );
101    }
102
103    /**
104     * After enabling the remote agent the 'sun.management.JMXConnectorServer.remote.enabled'
105     * counter will be exported with value of '0' - corresponding to the actual
106     * version of the associated remote connector perf counters.
107     * @throws Exception
108     */
109    @Test
110    public void testRemoteEnabled() throws Exception {
111        while (true) {
112            try {
113                int[] ports = PortAllocator.allocatePorts(1);
114                jcmd.start(
115                    "jmxremote.port=" + ports[0],
116                    "jmxremote.authenticate=false",
117                    "jmxremote.ssl=false"
118                );
119                String v = getCounters().getProperty(REMOTE_STATUS_KEY);
120                assertNotNull(v);
121                assertEquals("0", v);
122                return;
123            } catch (BindException e) {
124                System.out.println("Failed to allocate ports. Retrying ...");
125            }
126        }
127    }
128
129    /**
130     * After disabling the remote agent the value of 'sun.management.JMXConnectorServer.remote.enabled'
131     * counter will become '-1'.
132     * @throws Exception
133     */
134    @Test
135    public void testRemoteDisabled() throws Exception {
136        while (true) {
137            try {
138                int[] ports = PortAllocator.allocatePorts(1);
139                jcmd.start(
140                    "jmxremote.port=" + ports[0],
141                    "jmxremote.authenticate=false",
142                    "jmxremote.ssl=false"
143                );
144                jcmd.stop();
145                String v = getCounters().getProperty(REMOTE_STATUS_KEY);
146                assertNotNull(v);
147                assertEquals("-1", v);
148                return;
149            } catch (BindException e) {
150                System.out.println("Failed to allocate ports. Retrying ...");
151            }
152        }
153    }
154
155    /**
156     * Each subsequent re-enablement of the remote agent must keep the value of
157     * 'sun.management.JMXConnectorServer.remote.enabled' counter in sync with
158     * the actual version of the associated remote connector perf counters.
159     * @throws Exception
160     */
161    @Test
162    public void testRemoteReEnabled() throws Exception {
163        while (true) {
164            try {
165                int[] ports = PortAllocator.allocatePorts(1);
166                jcmd.start(
167                    "jmxremote.port=" + ports[0],
168                    "jmxremote.authenticate=false",
169                    "jmxremote.ssl=false"
170                );
171                jcmd.stop();
172                jcmd.start(
173                    "jmxremote.port=" + ports[0],
174                    "jmxremote.authenticate=false",
175                    "jmxremote.ssl=false"
176                );
177
178                String v = getCounters().getProperty(REMOTE_STATUS_KEY);
179                assertNotNull(v);
180                assertEquals("1", v);
181                return;
182            } catch (BindException e) {
183                System.out.println("Failed to allocate ports. Retrying ...");
184            }
185        }
186    }
187
188    private Properties getCounters() throws IOException, InterruptedException {
189        return jcmd.perfCounters("sun\\.management\\.JMXConnectorServer\\..*");
190    }
191}
192