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  * @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  *
  47  * @build jdk.testlibrary.* 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
  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
  70     public void setup() {
  71         jcmd = new ManagementAgentJcmd(TEST_APP_NAME, false);
  72     }
  73 
  74     @BeforeMethod
  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
  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
  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
 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
 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
 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 
 188     private Properties getCounters() throws IOException, InterruptedException {
 189         return jcmd.perfCounters("sun\\.management\\.JMXConnectorServer\\..*");
 190     }
 191 }