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.net.BindException;
  25 import java.util.ArrayList;
  26 import java.util.List;
  27 import java.util.function.Predicate;
  28 import java.util.regex.Pattern;
  29 import org.testng.annotations.*;
  30 import static org.testng.Assert.*;
  31 
  32 import jdk.testlibrary.ProcessTools;
  33 
  34 /**
  35  * @test
  36  * @bug 8023093 8138748 8142398
  37  * @summary Performs a sanity test for the ManagementAgent.status diagnostic command.
  38  *          Management agent may be disabled, started (only local connections) and started.
  39  *          The test asserts that the expected text is being printed.
  40  *
  41  * @library /lib/testlibrary
  42  *
  43  * @build jdk.testlibrary.* PortAllocator TestApp ManagementAgentJcmd
  44  *        JMXStatusTest JMXStatus1Test JMXStatus2Test
  45  * @run testng/othervm -XX:+UsePerfData JMXStatus1Test
  46  * @run testng/othervm -XX:+UsePerfData JMXStatus2Test
  47  */
  48 abstract public class JMXStatusTest {
  49     private final static String TEST_APP_NAME = "TestApp";
  50 
  51     protected final static Pattern DISABLED_AGENT_STATUS = Pattern.compile(
  52         "Agent\\s*\\: disabled$"
  53     );
  54 
  55     protected final static Pattern LOCAL_AGENT_STATUS = Pattern.compile(
  56         "Agent\\s*\\:\\s*enabled\\n+" +
  57         "Connection Type\\s*\\:\\s*local\\n+" +
  58         "Protocol\\s*\\:\\s*[a-z]+\\n+" +
  59         "Host\\s*\\:\\s*.+\\n+" +
  60         "URL\\s*\\:\\s*service\\:jmx\\:.+\\n+" +
  61         "Properties\\s*\\:\\n+(\\s*\\S+\\s*=\\s*\\S+(\\s+\\[default\\])?\\n*)+",
  62         Pattern.MULTILINE
  63     );
  64 
  65     protected final static Pattern REMOTE_AGENT_STATUS = Pattern.compile(
  66         "Agent\\s*\\: enabled\\n+" +
  67         ".*" +
  68         "Connection Type\\s*\\: remote\\n+" +
  69         "Protocol\\s*\\: [a-z]+\\n+" +
  70         "Host\\s*\\: .+\\n+" +
  71         "URL\\s*\\: service\\:jmx\\:.+\\n+" +
  72         "Properties\\s*\\:\\n+(\\s*\\S+\\s*=\\s*\\S+(\\s+\\[default\\])?\\n*)+",
  73         Pattern.MULTILINE | Pattern.DOTALL
  74     );
  75 
  76     private static ProcessBuilder testAppPb;
  77     private Process testApp;
  78 
  79     private ManagementAgentJcmd jcmd;
  80 
  81     abstract protected List<String> getCustomVmArgs();
  82     abstract protected Pattern getDefaultPattern();
  83 
  84     @BeforeTest
  85     public final void setup() throws Exception {
  86         List<String> args = new ArrayList<>();
  87         args.add("-cp");
  88         args.add(System.getProperty("test.class.path"));
  89         args.add("-XX:+UsePerfData");
  90         args.addAll(getCustomVmArgs());
  91         args.add(TEST_APP_NAME);
  92         testAppPb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[args.size()]));
  93 
  94         jcmd = new ManagementAgentJcmd(TEST_APP_NAME, false);
  95     }
  96 
  97     @BeforeMethod
  98     public final void startTestApp() throws Exception {
  99         testApp = ProcessTools.startProcess(
 100             TEST_APP_NAME, testAppPb,
 101             (Predicate<String>)l->l.trim().equals("main enter")
 102         );
 103     }
 104 
 105     @AfterMethod
 106     public final void stopTestApp() throws Exception {
 107         testApp.getOutputStream().write(1);
 108         testApp.getOutputStream().flush();
 109         testApp.waitFor();
 110         testApp = null;
 111     }
 112 
 113     @Test
 114     public final void testAgentLocal() throws Exception {
 115         jcmd.startLocal();
 116         String status = jcmd.status();
 117 
 118         assertStatusMatches(LOCAL_AGENT_STATUS, status);
 119     }
 120 
 121     @Test
 122     public final void testAgentRemote() throws Exception {
 123         while (true) {
 124             try {
 125                 int[] ports = PortAllocator.allocatePorts(1);
 126                 jcmd.start(
 127                     "jmxremote.port=" + ports[0],
 128                     "jmxremote.authenticate=false",
 129                     "jmxremote.ssl=false"
 130                 );
 131                 String status = jcmd.status();
 132 
 133                 assertStatusMatches(REMOTE_AGENT_STATUS, status);
 134                 return;
 135             } catch (BindException e) {
 136                 System.out.println("Failed to allocate ports. Retrying ...");
 137             }
 138         }
 139     }
 140 
 141     @Test
 142     public final void testAgentDefault() throws Exception {
 143         String status = jcmd.status();
 144         assertStatusMatches(getDefaultPattern(), status);
 145     }
 146 
 147     protected void assertStatusMatches(Pattern expected, String value) {
 148         assertStatusMatches(expected, value, "");
 149     }
 150 
 151     protected void assertStatusMatches(Pattern expected, String value, String msg) {
 152         int idx = value.indexOf('\n');
 153         if (idx > -1) {
 154             value = value.substring(idx + 1).trim();
 155             assertTrue(expected.matcher(value).find(), msg);
 156         } else {
 157             fail("The management agent status must contain more then one line of text");
 158         }
 159     }
 160 }