1 /*
2  * Copyright (c) 2015, 2018, 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 import java.io.IOException;
25 import java.net.BindException;
26 import java.util.Properties;
27 import java.util.function.Predicate;
28 import static org.testng.Assert.*;
29 import org.testng.annotations.AfterMethod;
30 import org.testng.annotations.BeforeClass;
31 import org.testng.annotations.BeforeMethod;
32 import org.testng.annotations.BeforeTest;
33 import org.testng.annotations.Test;
34 
35 import jdk.test.lib.process.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 /test/lib
46  *
47  * @build PortAllocator TestApp ManagementAgentJcmd
48  * @run testng/othervm -XX:+UsePerfData JMXStatusPerfCountersTest
49  */
50 public 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
setupClass()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
setup()70     public void setup() {
71         jcmd = new ManagementAgentJcmd(TEST_APP_NAME, false);
72     }
73 
74     @BeforeMethod
startTestApp()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
stopTestApp()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
testNotInitializedRemote()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
testRemoteEnabled()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
testRemoteDisabled()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
testRemoteReEnabled()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 
getCounters()188     private Properties getCounters() throws IOException, InterruptedException {
189         return jcmd.perfCounters("sun\\.management\\.JMXConnectorServer\\..*");
190     }
191 }
192