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