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