Path: blob/jdk8u272-b10-aarch32-20201026/jdk/test/java/rmi/testlibrary/TestLibrary.java
83402 views
/*1* Copyright (c) 1998, 2013, 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*/2223/**24*25*26* @author Adrian Colley27* @author Laird Dornin28* @author Peter Jones29* @author Ann Wollrath30*31* The rmi library directory contains a set of simple utiltity classes32* for use in rmi regression tests.33*34* NOTE: The JavaTest group has recommended that regression tests do35* not make use of packages.36*/3738import java.io.ByteArrayOutputStream;39import java.io.File;40import java.io.FileInputStream;41import java.io.FileOutputStream;42import java.io.IOException;43import java.io.PrintStream;44import java.net.MalformedURLException;45import java.net.ServerSocket;46import java.net.URL;47import java.rmi.NoSuchObjectException;48import java.rmi.Remote;49import java.rmi.RemoteException;50import java.rmi.registry.LocateRegistry;51import java.rmi.registry.Registry;52import java.rmi.server.RemoteRef;53import java.rmi.server.UnicastRemoteObject;54import java.util.Enumeration;55import java.util.Properties;5657import sun.rmi.registry.RegistryImpl;58import sun.rmi.server.UnicastServerRef;59import sun.rmi.transport.Endpoint;60import sun.rmi.transport.LiveRef;61import sun.rmi.transport.tcp.TCPEndpoint;6263/**64* Class of utility/library methods (i.e. procedures) that assist with65* the writing and maintainance of rmi regression tests.66*/67public class TestLibrary {68/**69* IMPORTANT!70*71* RMI tests are run concurrently and port conflicts result when a single72* port number is used by multiple tests. When needing a port, use73* getUnusedRandomPort() wherever possible. If getUnusedRandomPort() cannot74* be used, reserve and specify a port to use for your test here. This75* will ensure there are no port conflicts amongst the RMI tests. The76* port numbers specified here may also be specified in the respective77* tests. Do not change the reserved port numbers here without also78* changing the port numbers in the respective tests.79*80* When needing an instance of the RMIRegistry, use81* createRegistryOnUnusedPort wherever possible to prevent port conflicts.82*83* Reserved port range: FIXED_PORT_MIN to FIXED_PORT_MAX (inclusive) for84* tests which cannot use a random port. If new fixed ports are added below85* FIXED_PORT_MIN or above FIXED_PORT_MAX, then adjust86* FIXED_PORT_MIN/MAX appropriately.87*/88public final static int FIXED_PORT_MIN = 60001;89public final static int FIXED_PORT_MAX = 60010;90public final static int RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT = 60001;91public final static int RMIDVIAINHERITEDCHANNEL_REGISTRY_PORT = 60002;92public final static int INHERITEDCHANNELNOTSERVERSOCKET_ACTIVATION_PORT = 60003;93public final static int INHERITEDCHANNELNOTSERVERSOCKET_REGISTRY_PORT = 60004;94public final static int READTEST_REGISTRY_PORT = 60005;95private final static int MAX_SERVER_SOCKET_TRIES = 2*(FIXED_PORT_MAX-FIXED_PORT_MIN+1);9697static void mesg(Object mesg) {98System.err.println("TEST_LIBRARY: " + mesg.toString());99}100101/**102* Routines that enable rmi tests to fail in a uniformly103* informative fashion.104*/105public static void bomb(String message, Exception e) {106String testFailed = "TEST FAILED: ";107108if ((message == null) && (e == null)) {109testFailed += " No relevant information";110} else if (e == null) {111testFailed += message;112}113114System.err.println(testFailed);115if (e != null) {116System.err.println("Test failed with: " +117e.getMessage());118e.printStackTrace(System.err);119}120throw new TestFailedException(testFailed, e);121}122public static void bomb(String message) {123bomb(message, null);124}125public static void bomb(Exception e) {126bomb(null, e);127}128129/**130* Helper method to determine if registry has started131*132* @param port The port number to check133* @param msTimeout The amount of milliseconds to spend checking134*/135136public static boolean checkIfRegistryRunning(int port, int msTimeout) {137long stopTime = System.currentTimeMillis() + msTimeout;138do {139try {140Registry r = LocateRegistry.getRegistry(port);141String[] s = r.list();142// no exception. We're now happy that registry is running143return true;144} catch (RemoteException e) {145// problem - not ready ? Try again146try {147Thread.sleep(500);148} catch (InterruptedException ie) {149// not expected150}151}152} while (stopTime > System.currentTimeMillis());153return false;154}155156public static String getProperty(String property, String defaultVal) {157final String prop = property;158final String def = defaultVal;159return java.security.AccessController.doPrivileged(160new java.security.PrivilegedAction<String>() {161public String run() {162return System.getProperty(prop, def);163}164});165}166167/**168* Property mutators169*/170public static void setBoolean(String property, boolean value) {171setProperty(property, (new Boolean(value)).toString());172}173public static void setInteger(String property, int value) {174setProperty(property, Integer.toString(value));175}176public static void setProperty(String property, String value) {177final String prop = property;178final String val = value;179java.security.AccessController.doPrivileged(180new java.security.PrivilegedAction<Void>() {181public Void run() {182System.setProperty(prop, val);183return null;184}185});186}187188/**189* Routines to print out a test's properties environment.190*/191public static void printEnvironment() {192printEnvironment(System.err);193}194public static void printEnvironment(PrintStream out) {195out.println("-------------------Test environment----------" +196"---------");197198for(Enumeration<?> keys = System.getProperties().keys();199keys.hasMoreElements();) {200201String property = (String) keys.nextElement();202out.println(property + " = " + getProperty(property, null));203}204out.println("---------------------------------------------" +205"---------");206}207208/**209* Routine that "works-around" a limitation in jtreg.210* Currently it is not possible for a test to specify that the211* test harness should build a given source file and install the212* resulting class in a location that is not accessible from the213* test's classpath. This method enables a test to move a214* compiled test class file from the test's class directory into a215* given "codebase" directory. As a result the test can only216* access the class file for <code>className</code>if the test loads217* it from a classloader (e.g. RMIClassLoader).218*219* Tests that use this routine must have the following permissions220* granted to them:221*222* getProperty user.dir223* getProperty etc.224*/225public static URL installClassInCodebase(String className,226String codebase)227throws MalformedURLException228{229return installClassInCodebase(className, codebase, true);230}231232public static URL installClassInCodebase(String className,233String codebase,234boolean delete)235throws MalformedURLException236{237/*238* NOTES/LIMITATIONS: The class must not be in a named package,239* and the codebase must be a relative path (it's created relative240* to the working directory).241*/242String classFileName = className + ".class";243244/*245* Specify the file to contain the class definition. Make sure246* that the codebase directory exists (underneath the working247* directory).248*/249File dstDir = (new File(getProperty("user.dir", "."), codebase));250251if (!dstDir.exists()) {252if (!dstDir.mkdir()) {253throw new RuntimeException(254"could not create codebase directory");255}256}257File dstFile = new File(dstDir, classFileName);258259/*260* Obtain the URL for the codebase.261*/262URL codebaseURL = dstDir.toURI().toURL();263264/*265* Specify where we will copy the class definition from, if266* necessary. After the test is built, the class file can be267* found in the "test.classes" directory.268*/269File srcDir = new File(getProperty("test.classes", "."));270File srcFile = new File(srcDir, classFileName);271272mesg(srcFile);273mesg(dstFile);274275/*276* If the class definition is not already located at the codebase,277* copy it there from the test build area.278*/279if (!dstFile.exists()) {280if (!srcFile.exists()) {281throw new RuntimeException(282"could not find class file to install in codebase " +283"(try rebuilding the test): " + srcFile);284}285286try {287copyFile(srcFile, dstFile);288} catch (IOException e) {289throw new RuntimeException(290"could not install class file in codebase");291}292293mesg("Installed class \"" + className +294"\" in codebase " + codebaseURL);295}296297/*298* After the class definition is successfully installed at the299* codebase, delete it from the test's CLASSPATH, so that it will300* not be found there first before the codebase is searched.301*/302if (srcFile.exists()) {303if (delete && !srcFile.delete()) {304throw new RuntimeException(305"could not delete duplicate class file in CLASSPATH");306}307}308309return codebaseURL;310}311312public static void copyFile(File srcFile, File dstFile)313throws IOException314{315FileInputStream src = new FileInputStream(srcFile);316FileOutputStream dst = new FileOutputStream(dstFile);317318byte[] buf = new byte[32768];319while (true) {320int count = src.read(buf);321if (count < 0) {322break;323}324dst.write(buf, 0, count);325}326327dst.close();328src.close();329}330331/** routine to unexport an object */332public static void unexport(Remote obj) {333if (obj != null) {334try {335mesg("unexporting object...");336UnicastRemoteObject.unexportObject(obj, true);337} catch (NoSuchObjectException munch) {338} catch (Exception e) {339e.getMessage();340e.printStackTrace();341}342}343}344345/**346* Allow test framework to control the security manager set in347* each test.348*349* @param managerClassName The class name of the security manager350* to be instantiated and set if no security351* manager has already been set.352*/353public static void suggestSecurityManager(String managerClassName) {354SecurityManager manager = null;355356if (System.getSecurityManager() == null) {357try {358if (managerClassName == null) {359managerClassName = TestParams.defaultSecurityManager;360}361manager = ((SecurityManager) Class.362forName(managerClassName).newInstance());363} catch (ClassNotFoundException cnfe) {364bomb("Security manager could not be found: " +365managerClassName, cnfe);366} catch (Exception e) {367bomb("Error creating security manager. ", e);368}369370System.setSecurityManager(manager);371}372}373374/**375* Creates an RMI {@link Registry} on a random, un-reserved port.376*377* @returns an RMI Registry, using a random port.378* @throws RemoteException if there was a problem creating a Registry.379*/380public static Registry createRegistryOnUnusedPort() throws RemoteException {381return LocateRegistry.createRegistry(getUnusedRandomPort());382}383384/**385* Creates an RMI {@link Registry} on an ephemeral port.386*387* @returns an RMI Registry388* @throws RemoteException if there was a problem creating a Registry.389*/390public static Registry createRegistryOnEphemeralPort() throws RemoteException {391return LocateRegistry.createRegistry(0);392}393394/**395* Returns the port number the RMI {@link Registry} is running on.396*397* @param registry the registry to find the port of.398* @return the port number the registry is using.399* @throws RuntimeException if there was a problem getting the port number.400*/401public static int getRegistryPort(Registry registry) {402int port = -1;403404try {405RemoteRef remoteRef = ((RegistryImpl)registry).getRef();406LiveRef liveRef = ((UnicastServerRef)remoteRef).getLiveRef();407Endpoint endpoint = liveRef.getChannel().getEndpoint();408TCPEndpoint tcpEndpoint = (TCPEndpoint) endpoint;409port = tcpEndpoint.getPort();410} catch (Exception ex) {411throw new RuntimeException("Error getting registry port.", ex);412}413414return port;415}416417/**418* Returns an unused random port number which is not a reserved port. Will419* try up to 10 times to get a random port before giving up and throwing a420* RuntimeException.421*422* @return an unused random port number.423* @throws RuntimeException if there was a problem getting a port.424*/425public static int getUnusedRandomPort() {426int numTries = 0;427IOException ex = null;428429while (numTries++ < MAX_SERVER_SOCKET_TRIES) {430int unusedRandomPort = -1;431ex = null; //reset432433try (ServerSocket ss = new ServerSocket(0)) {434unusedRandomPort = ss.getLocalPort();435} catch (IOException e) {436ex = e;437// temporarily print stack trace here until we find out why438// tests are failing.439System.err.println("TestLibrary.getUnusedRandomPort() caught "440+ "exception on iteration " + numTries441+ (numTries==MAX_SERVER_SOCKET_TRIES ? " (the final try)."442: "."));443ex.printStackTrace();444}445446if (unusedRandomPort >= 0) {447if (isReservedPort(unusedRandomPort)) {448System.out.println("INFO: On try # " + numTries449+ (numTries==MAX_SERVER_SOCKET_TRIES ? ", the final try, ": ",")450+ " ServerSocket(0) returned the reserved port "451+ unusedRandomPort452+ " in TestLibrary.getUnusedRandomPort() ");453} else {454return unusedRandomPort;455}456}457}458459// If we're here, then either an exception was thrown or the port is460// a reserved port.461if (ex==null) {462throw new RuntimeException("Error getting unused random port. The"463+" last port returned by ServerSocket(0) was a reserved port");464} else {465throw new RuntimeException("Error getting unused random port.", ex);466}467}468469/**470* Determines if a port is one of the reserved port numbers.471*472* @param port the port to test.473* @return {@code true} if the port is a reserved port, otherwise474* {@code false}.475*/476public static boolean isReservedPort(int port) {477return ((port >= FIXED_PORT_MIN) && (port <= FIXED_PORT_MAX) ||478(port == 1099));479}480481/**482* Method to capture the stack trace of an exception and return it483* as a string.484*/485public String stackTraceToString(Exception e) {486ByteArrayOutputStream bos = new ByteArrayOutputStream();487PrintStream ps = new PrintStream(bos);488489e.printStackTrace(ps);490return bos.toString();491}492493/** extra properties */494private static Properties props;495496/**497* Returns extra test properties. Looks for the file "../../test.props"498* and reads it in as a Properties file. Assuming the working directory499* is "<path>/JTwork/scratch", this will find "<path>/test.props".500*/501private static synchronized Properties getExtraProperties() {502if (props != null) {503return props;504}505props = new Properties();506File f = new File(".." + File.separator + ".." + File.separator +507"test.props");508if (!f.exists()) {509return props;510}511try {512FileInputStream in = new FileInputStream(f);513try {514props.load(in);515} finally {516in.close();517}518} catch (IOException e) {519e.printStackTrace();520throw new RuntimeException("extra property setup failed", e);521}522return props;523}524525/**526* Returns an extra test property. Looks for the file "../../test.props"527* and reads it in as a Properties file. Assuming the working directory528* is "<path>/JTwork/scratch", this will find "<path>/test.props".529* If the property isn't found, defaultVal is returned.530*/531public static String getExtraProperty(String property, String defaultVal) {532return getExtraProperties().getProperty(property, defaultVal);533}534}535536537