Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/aod/TargetApplicationWaitingAgents.java
41161 views
/*1* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22package nsk.share.aod;2324import nsk.share.*;25import nsk.share.jpda.SocketIOPipe;2627import java.util.*;2829/*30Class TargetApplicationWaitingAgents is part of the framework used in the AttachOnDemand tests31(tests against Attach API, API from package com.sun.tools.attach).3233Attach API allows to load so called 'agents' in the running VM. In terms of this framework34application running in the VM where agent is loaded to is called 'target application'.3536TargetApplicationWaitingAgents is base class for target applications used in the AttachOnDemand tests37(also TargetApplicationWaitingAgents can be used without modifications in tests where target38application shouldn't execute some test-specific actions).3940AttachOnDemand tests requires synchronization between test agents and target application:41- before target application can start to execute test-specific actions it42should wait when all tests agents will be loaded4344- target application shouldn't finish until all agents finish their work4546TargetApplicationWaitingAgents incapsulates actions common for all target applications. TargetApplicationWaitingAgents47provides 2 methods: 'agentLoaded' and 'agentFinished', test agents use these methods to notify48target application about its status. When target application based on the TargetApplicationWaitingAgents49starts it first waits when all test agents will be loaded (number of expected test agents is50passed via parameter -agentsNumber). After this target application executes test-specific actions,51waits when all test agents will finish, checks agent's status (passed of failed) and52finishes.5354In most cases test target applications should override only method 'targetApplicationActions' and55its 'main' method should contain only call of the method 'TargetApplicationWaitingAgents.runTargetApplication'.5657Typical target application class looks like this:5859public class targetExample extends TargetApplicationWaitingAgents {6061protected void targetApplicationActions() {62// do test-specific actions63}6465public static void main(String[] args) {66new targetExample().runTargetApplication(args);67}68}69*/70public class TargetApplicationWaitingAgents {7172private volatile static boolean testFailed = false;7374private static long AGENTS_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 min7576private static long AGENTS_FINISHING_TIMEOUT = 5 * 60 * 1000; // 5 min7778private static boolean allAgentsAttached;7980private static List<String> attachedAgents = new ArrayList<String>();8182private static boolean allAgentsFinished;8384private static List<String> finishedAgents = new ArrayList<String>();8586private static boolean targetApplicationInitialized;8788static protected AODTargetArgParser argParser;8990protected static Log log;9192static private Object monitor = new Object();9394/*95* Methods96* - agentLoaded(String agentName) and97* - agentFinished(String agentName, boolean finishedSuccessfully)98* are called from test agents to notify target application about its status99*/100101public static void agentLoaded(String agentName) {102synchronized (monitor) {103if (!targetApplicationInitialized)104waitForTargetApplicationInitialization();105106// check test logic107if (attachedAgents.contains(agentName)) {108setStatusFailed("Agent '" + agentName + "' already attached");109110// let TargetApplication complete execution in case of error111allAgentsAttached = true;112monitor.notifyAll();113114throw new TestBug("Agent '" + agentName + "' calls method 'agentLoaded' more than 1 time");115} else {116attachedAgents.add(agentName);117118log.display("Agent '" + agentName + "' was loaded");119120allAgentsAttached = (attachedAgents.size() == argParser.getExpectedAgentsNumber());121122if (allAgentsAttached)123monitor.notifyAll();124125// check test logic126if (attachedAgents.size() > argParser.getExpectedAgentsNumber()) {127setStatusFailed("Unexpected agent attached (expected agents number: " +128argParser.getExpectedAgentsNumber() +129", but " + attachedAgents.size() + " agents were loaded)");130131throw new TestBug("More agents attached than it was expected" +132" (expected: " + argParser.getExpectedAgentsNumber() +133", attached: " + attachedAgents.size() + ")");134}135}136}137}138139public static void agentFinished(String agentName, boolean finishedSuccessfully) {140synchronized (monitor) {141// check test logic142if (!targetApplicationInitialized)143throw new TestBug("Method 'agentFinished' was called before TargetApplication was initialized");144145boolean algorithmError = false;146String errorMessage = "Test algorithm error:";147148if (!attachedAgents.contains(agentName)) {149algorithmError = true;150errorMessage += " agent '" + agentName + "' didn't call method 'agentLoaded';";151log.complain(errorMessage);152}153154if (finishedAgents.contains(agentName)) {155algorithmError = true;156errorMessage += " agent '" + agentName + "' already called method 'agentFinished';";157log.complain(errorMessage);158}159160if (algorithmError) {161// let TargetApplication complete execution in case of error162allAgentsFinished = true;163monitor.notifyAll();164165throw new TestBug(errorMessage);166} else {167finishedAgents.add(agentName);168169log.display("Agent '" + agentName + "' finished execution (finishedSuccessfully: " + finishedSuccessfully + ")");170171if (!finishedSuccessfully)172setStatusFailed("Agent '" + agentName + " finished with error status");173174allAgentsFinished = (finishedAgents.size() == argParser.getExpectedAgentsNumber());175176if (allAgentsAttached)177monitor.notifyAll();178}179}180}181182/*183* This method is called from the method 'agentLoaded' in case184* when target application isn't initialized yet at the moment185* when agent is connecting186*/187static private void waitForTargetApplicationInitialization() {188synchronized (monitor) {189while (!targetApplicationInitialized) {190try {191monitor.wait();192} catch (InterruptedException e) {193// should never happen194exitAsFailed(e);195}196}197}198}199200/*201* This method is introduced to let subclasses to create its own parsers202*/203protected AODTargetArgParser createArgParser(String[] args) {204return new AODTargetArgParser(args);205}206207/*208* Target application initialization209*/210private void initTargetApplication(String[] args) {211synchronized (monitor) {212if (targetApplicationInitialized)213throw new TestBug("TargetApplication already initialized");214215log = new Log(System.out, true);216217argParser = createArgParser(args);218219// test-specific initialization220init(args);221222targetApplicationInitialized = true;223monitor.notifyAll();224}225}226227static private void waitAgentsConnection() {228synchronized (monitor) {229long waitFinishTime = System.currentTimeMillis() + AGENTS_CONNECTION_TIMEOUT;230231while (!allAgentsAttached && (System.currentTimeMillis() < waitFinishTime)) {232try {233monitor.wait(AGENTS_CONNECTION_TIMEOUT);234} catch (InterruptedException e) {235// should never happen236exitAsFailed(e);237}238}239}240241if (!allAgentsAttached) {242exitAsFailed("Agents didn't attach in " + AGENTS_CONNECTION_TIMEOUT + "ms, stop execution " +243"(expected agents number: " + argParser.getExpectedAgentsNumber() +244", attached agents number: " + attachedAgents.size() + ")");245}246}247248static private void waitAgentsFinishing() {249synchronized (monitor) {250long waitFinishTime = System.currentTimeMillis() + AGENTS_FINISHING_TIMEOUT;251252while (!allAgentsFinished && (System.currentTimeMillis() < waitFinishTime)) {253try {254monitor.wait(AGENTS_FINISHING_TIMEOUT);255} catch (InterruptedException e) {256// should never happen257exitAsFailed(e);258}259}260}261262if (!allAgentsFinished)263exitAsFailed("Agents didn't finish in " + AGENTS_FINISHING_TIMEOUT + "ms, stop execution " +264"(attached agents number: " + attachedAgents.size() +265", finished agents number: " + finishedAgents.size() + ")");266}267268/*269* Print error message and set failed status, but don't exit270*/271272static public void setStatusFailed(String message) {273testFailed = true;274log.complain(message);275}276277static public void setStatusFailed(Throwable t) {278testFailed = true;279log.complain("Unexpected exception: " + t);280t.printStackTrace(log.getOutStream());281}282283/*284* Print error message and exit with fail status285*/286static protected void exitAsFailed(String errorMessage) {287try {288log.complain(errorMessage);289log.complain("Stop execution");290} finally {291System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);292}293}294295/*296* Print error message and exit with fail status297*/298static protected void exitAsFailed(Throwable t) {299try {300log.complain("Unexpected exception was thrown during TargetApplication execution: " + t);301t.printStackTrace(log.getOutStream());302log.display("Stop execution");303} finally {304System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);305}306}307308/*309* Following 3 methods can be overridden in subclasses:310*311* - init(String[] args)312*313* - targetApplicationActions()314*315* - afterAgentsFinished()316*/317318/*319* Test-specific initialization320*/321protected void init(String[] args) {322323}324325protected void targetApplicationActions() throws Throwable {326// do nothing by default327}328329protected void afterAgentsFinished() {330// do nothing by default331}332333public final void runTargetApplication(String[] args) {334initTargetApplication(args);335336SocketIOPipe pipe = null;337338try {339if (argParser.getPort() > 0) {340/*341* When target application initialized send signal to AODTestRunner342*/343pipe = SocketIOPipe.createClientIOPipe(log, "localhost", argParser.getPort(), 0);344log.display("Sending signal '" + AODTestRunner.SIGNAL_READY_FOR_ATTACH + "'");345pipe.println(AODTestRunner.SIGNAL_READY_FOR_ATTACH);346}347348log.display("Waiting for agents connection");349waitAgentsConnection();350log.display("All expected agents connected");351352try {353targetApplicationActions();354} catch (Throwable e) {355/*356* If something goes wrong during test execution it is better357* to exit without waiting for agents358*/359360if (pipe != null)361pipe.close();362363exitAsFailed(e);364}365366log.display("Waiting for agents finishing");367waitAgentsFinishing();368log.display("All agents finished execution");369370afterAgentsFinished();371372if (pipe != null) {373/*374* Don't finish execution until AODTestRunner attached agents375*/376String signal = pipe.readln();377log.display("Signal received: '" + signal + "'");378if ((signal == null) || !signal.equals(AODTestRunner.SIGNAL_FINISH))379throw new TestBug("Unexpected AODTestRunner signal: '" + signal + "'");380381if (testFailed) {382if (pipe != null)383pipe.close();384385exitAsFailed("Error happened during TargetApplication execution (see error messages for details)");386} else {387log.display("Test passed");388}389}390} finally {391if (pipe != null)392pipe.close();393}394}395396public static void main(String[] args) {397new TargetApplicationWaitingAgents().runTargetApplication(args);398}399}400401402