1 /* 2 * Copyright (c) 2008, 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 package nsk.share.aod; 24 25 import java.io.*; 26 import nsk.share.*; 27 import nsk.share.jpda.SocketIOPipe; 28 29 /* 30 Class AODTestRunner is part of the framework used in the AttachOnDemand tests 31 (tests against Attach API, API from package com.sun.tools.attach). 32 33 AODTestRunner is used as main class in AttachOnDemand tests, it performs following 34 actions: 35 - starts target application 36 37 - finds VM id for target VM (this id is needed for dynamic attach) 38 39 - by default AODTestRunner tries to attach specified via command line agents to target VM 40 (subclasses can override this default behavior) 41 42 - waits for target application completion 43 44 Target application class, agents that should be attached, JDK used to run target application and 45 VM options passed to target VM should be specified via command line. 46 */ 47 public class AODTestRunner { 48 49 public static final String targetAppIdProperty = "vmsqe.aod.targetAppId"; 50 public static final String appIdProperty = "vmsqe.aod.AppId"; 51 52 public static final long TARGET_APP_CONNECT_TIMEOUT = 5 * 60 * 1000; // 5 min 53 54 public static final long TARGET_APP_WORK_TIMEOUT = 30 * 60 * 1000; // 30 min (standard VM testbase test timeout) 55 56 protected Log log; 57 58 protected SocketIOPipe pipe; 59 60 protected ProcessExecutor targetAppExecutor; 61 62 // target application ready for attach 63 public static final String SIGNAL_READY_FOR_ATTACH = "ready"; 64 65 // target application may finish execution 66 public static final String SIGNAL_FINISH = "finish"; 67 68 protected AODRunnerArgParser argParser; 69 AODTestRunner(String[] args)70 protected AODTestRunner(String[] args) { 71 log = new Log(System.out, true); 72 73 argParser = createArgParser(args); 74 } 75 76 /* 77 * This method is introduced to let subclasses to create its own parsers 78 */ createArgParser(String[] args)79 protected AODRunnerArgParser createArgParser(String[] args) { 80 return new AODRunnerArgParser(args); 81 } 82 doTestActions(String targetVMId)83 protected void doTestActions(String targetVMId) throws Throwable { 84 AgentsAttacher attacher = new AgentsAttacher(targetVMId, argParser.getAgents(), log); 85 attacher.attachAgents(); 86 } 87 getCurrentVMId()88 protected String getCurrentVMId() { 89 String currentVMId = "" + ProcessHandle.current().pid(); 90 log.display("Current VM id was identified: " + currentVMId); 91 92 return currentVMId; 93 } 94 runTest()95 protected void runTest() { 96 97 try { 98 String targetAppId = System.getProperty(targetAppIdProperty); 99 if(targetAppId == null || targetAppId.isEmpty()) { 100 // use PID as default appID 101 targetAppId = "" + ProcessHandle.current().pid(); 102 } 103 /* 104 * Create target application id required by the Utils.findVMIdUsingJPS 105 */ 106 String targetAppCmd = 107 // path to java 108 argParser.getTestedJDK() + File.separator + "bin" + File.separator + "java " + 109 // VM property to identify VM running target application 110 "-D" + appIdProperty + "=" + targetAppId + " " + 111 // VM opts 112 argParser.getJavaOpts() + " -XX:+EnableDynamicAgentLoading " + 113 // target application class 114 argParser.getTargetApp() + " " + 115 // additional target application parameter - number of 116 // agents that will be attached 117 "-" + AODTargetArgParser.agentsNumberParam + " " + argParser.getAgents().size(); 118 119 pipe = SocketIOPipe.createServerIOPipe(log, 0, TARGET_APP_CONNECT_TIMEOUT); 120 targetAppCmd += " -" + AODTargetArgParser.socketPortParam + " " + pipe.getPort(); 121 122 log.display("Starting target application: " + targetAppCmd); 123 targetAppExecutor = new ProcessExecutor(targetAppCmd, TARGET_APP_WORK_TIMEOUT, "TargetApp"); 124 targetAppExecutor.startProcess(); 125 126 /* 127 * Don't try to attach agents until target application isn't initialized 128 */ 129 String signal = pipe.readln(); 130 log.display("Signal received: '" + signal + "'"); 131 if ((signal == null) || !signal.equals(SIGNAL_READY_FOR_ATTACH)) 132 throw new TestBug("Unexpected TargetApplication signal: '" + signal + "'"); 133 134 String targetVMId = Long.toString(targetAppExecutor.pid()); 135 log.display("Target VM id was identified: " + targetVMId); 136 137 doTestActions(targetVMId); 138 139 /* 140 * When test actions finished let target application finish execution 141 */ 142 log.display("Sending signal: '" + SIGNAL_FINISH + "'"); 143 pipe.println(SIGNAL_FINISH); 144 145 targetAppExecutor.waitForProcess(); 146 147 File file = new File(targetAppId); 148 if (file.exists()) { 149 file.deleteOnExit(); 150 } 151 152 if (targetAppExecutor.getExitCode() != 0) { 153 throw new Failure("Target application finished with non-zero code " + targetAppExecutor.getExitCode()); 154 } 155 156 postTargetExitHook(); 157 158 } catch (Failure f) { 159 throw f; 160 } catch (Throwable t) { 161 throw new Failure("Unexpected exception during test execution: " + t, t); 162 } finally { 163 if (pipe != null) { 164 pipe.close(); 165 } 166 if (targetAppExecutor != null) { 167 targetAppExecutor.destroyProcess(); 168 } 169 } 170 } 171 172 /* 173 * Allow users of this class to specify actions to be taken after the target exits 174 */ postTargetExitHook()175 protected void postTargetExitHook() { 176 // do nothing by default 177 } 178 createApplicationId()179 public static String createApplicationId() { 180 return new Long(System.currentTimeMillis()).toString(); 181 } 182 main(String[] args)183 public static void main(String[] args) { 184 new AODTestRunner(args).runTest(); 185 } 186 } 187