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