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