0N/A/*
5266N/A * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/**
0N/A *
0N/A *
0N/A * @author Adrian Colley
0N/A * @author Laird Dornin
0N/A * @author Peter Jones
0N/A * @author Ann Wollrath
0N/A *
0N/A * The rmi library directory contains a set of simple utiltity classes
0N/A * for use in rmi regression tests.
0N/A *
0N/A * NOTE: The JavaTest group has recommended that regression tests do
0N/A * not make use of packages.
0N/A */
0N/A
5266N/Aimport java.io.ByteArrayOutputStream;
0N/Aimport java.io.File;
0N/Aimport java.io.FileInputStream;
0N/Aimport java.io.FileOutputStream;
0N/Aimport java.io.IOException;
0N/Aimport java.io.PrintStream;
0N/Aimport java.net.MalformedURLException;
5266N/Aimport java.net.ServerSocket;
5266N/Aimport java.net.URL;
0N/Aimport java.rmi.NoSuchObjectException;
5266N/Aimport java.rmi.Remote;
5266N/Aimport java.rmi.RemoteException;
5266N/Aimport java.rmi.registry.LocateRegistry;
0N/Aimport java.rmi.registry.Registry;
5266N/Aimport java.rmi.server.RemoteRef;
0N/Aimport java.rmi.server.UnicastRemoteObject;
0N/Aimport java.util.Enumeration;
0N/Aimport java.util.Properties;
5673N/A
5266N/Aimport sun.rmi.registry.RegistryImpl;
5266N/Aimport sun.rmi.server.UnicastServerRef;
5266N/Aimport sun.rmi.transport.Endpoint;
5266N/Aimport sun.rmi.transport.LiveRef;
5266N/Aimport sun.rmi.transport.tcp.TCPEndpoint;
0N/A
0N/A/**
0N/A * Class of utility/library methods (i.e. procedures) that assist with
0N/A * the writing and maintainance of rmi regression tests.
0N/A */
0N/Apublic class TestLibrary {
5266N/A /**
5266N/A * IMPORTANT!
5266N/A *
5266N/A * RMI tests are run concurrently and port conflicts result when a single
5266N/A * port number is used by multiple tests. When needing a port, use
5266N/A * getUnusedRandomPort() wherever possible. If getUnusedRandomPort() cannot
5266N/A * be used, reserve and specify a port to use for your test here. This
5266N/A * will ensure there are no port conflicts amongst the RMI tests. The
5266N/A * port numbers specified here may also be specified in the respective
5266N/A * tests. Do not change the reserved port numbers here without also
5266N/A * changing the port numbers in the respective tests.
5266N/A *
5266N/A * When needing an instance of the RMIRegistry, use
5266N/A * createRegistryOnUnusedPort wherever possible to prevent port conflicts.
5266N/A *
5266N/A * Reserved port range: FIXED_PORT_MIN to FIXED_PORT_MAX (inclusive) for
5266N/A * tests which cannot use a random port. If new fixed ports are added below
5266N/A * FIXED_PORT_MIN or above FIXED_PORT_MAX, then adjust
5266N/A * FIXED_PORT_MIN/MAX appropriately.
5266N/A */
5266N/A public final static int FIXED_PORT_MIN = 64001;
5266N/A public final static int FIXED_PORT_MAX = 64010;
5266N/A public final static int RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT = 64001;
5266N/A public final static int RMIDVIAINHERITEDCHANNEL_REGISTRY_PORT = 64002;
5266N/A public final static int INHERITEDCHANNELNOTSERVERSOCKET_ACTIVATION_PORT = 64003;
5266N/A public final static int INHERITEDCHANNELNOTSERVERSOCKET_REGISTRY_PORT = 64004;
5266N/A public final static int READTEST_REGISTRY_PORT = 64005;
5674N/A private final static int MAX_SERVER_SOCKET_TRIES = 2*(FIXED_PORT_MAX-FIXED_PORT_MIN+1);
0N/A
0N/A static void mesg(Object mesg) {
0N/A System.err.println("TEST_LIBRARY: " + mesg.toString());
0N/A }
0N/A
0N/A /**
0N/A * Routines that enable rmi tests to fail in a uniformly
0N/A * informative fashion.
0N/A */
0N/A public static void bomb(String message, Exception e) {
0N/A String testFailed = "TEST FAILED: ";
0N/A
0N/A if ((message == null) && (e == null)) {
0N/A testFailed += " No relevant information";
0N/A } else if (e == null) {
0N/A testFailed += message;
0N/A }
0N/A
0N/A System.err.println(testFailed);
0N/A if (e != null) {
0N/A System.err.println("Test failed with: " +
0N/A e.getMessage());
0N/A e.printStackTrace(System.err);
0N/A }
0N/A throw new TestFailedException(testFailed, e);
0N/A }
0N/A public static void bomb(String message) {
0N/A bomb(message, null);
0N/A }
0N/A public static void bomb(Exception e) {
0N/A bomb(null, e);
0N/A }
0N/A
0N/A public static String getProperty(String property, String defaultVal) {
0N/A final String prop = property;
0N/A final String def = defaultVal;
5673N/A return java.security.AccessController.doPrivileged(
5673N/A new java.security.PrivilegedAction<String>() {
5673N/A public String run() {
0N/A return System.getProperty(prop, def);
0N/A }
5673N/A });
0N/A }
0N/A
0N/A /**
0N/A * Property mutators
0N/A */
0N/A public static void setBoolean(String property, boolean value) {
0N/A setProperty(property, (new Boolean(value)).toString());
0N/A }
0N/A public static void setInteger(String property, int value) {
0N/A setProperty(property, Integer.toString(value));
0N/A }
0N/A public static void setProperty(String property, String value) {
0N/A final String prop = property;
0N/A final String val = value;
5673N/A java.security.AccessController.doPrivileged(
5673N/A new java.security.PrivilegedAction<Void>() {
5673N/A public Void run() {
0N/A System.setProperty(prop, val);
0N/A return null;
0N/A }
0N/A });
0N/A }
0N/A
0N/A /**
0N/A * Routines to print out a test's properties environment.
0N/A */
0N/A public static void printEnvironment() {
0N/A printEnvironment(System.err);
0N/A }
0N/A public static void printEnvironment(PrintStream out) {
0N/A out.println("-------------------Test environment----------" +
0N/A "---------");
0N/A
5673N/A for(Enumeration<?> keys = System.getProperties().keys();
0N/A keys.hasMoreElements();) {
0N/A
0N/A String property = (String) keys.nextElement();
0N/A out.println(property + " = " + getProperty(property, null));
0N/A }
0N/A out.println("---------------------------------------------" +
0N/A "---------");
0N/A }
0N/A
0N/A /**
0N/A * Routine that "works-around" a limitation in jtreg.
0N/A * Currently it is not possible for a test to specify that the
0N/A * test harness should build a given source file and install the
0N/A * resulting class in a location that is not accessible from the
0N/A * test's classpath. This method enables a test to move a
0N/A * compiled test class file from the test's class directory into a
0N/A * given "codebase" directory. As a result the test can only
0N/A * access the class file for <code>className</code>if the test loads
0N/A * it from a classloader (e.g. RMIClassLoader).
0N/A *
0N/A * Tests that use this routine must have the following permissions
0N/A * granted to them:
0N/A *
0N/A * getProperty user.dir
0N/A * getProperty etc.
0N/A */
0N/A public static URL installClassInCodebase(String className,
0N/A String codebase)
0N/A throws MalformedURLException
0N/A {
0N/A return installClassInCodebase(className, codebase, true);
0N/A }
0N/A
0N/A public static URL installClassInCodebase(String className,
0N/A String codebase,
0N/A boolean delete)
0N/A throws MalformedURLException
0N/A {
0N/A /*
0N/A * NOTES/LIMITATIONS: The class must not be in a named package,
0N/A * and the codebase must be a relative path (it's created relative
0N/A * to the working directory).
0N/A */
0N/A String classFileName = className + ".class";
0N/A
0N/A /*
0N/A * Specify the file to contain the class definition. Make sure
0N/A * that the codebase directory exists (underneath the working
0N/A * directory).
0N/A */
0N/A File dstDir = (new File(getProperty("user.dir", "."), codebase));
0N/A
0N/A if (!dstDir.exists()) {
0N/A if (!dstDir.mkdir()) {
0N/A throw new RuntimeException(
0N/A "could not create codebase directory");
0N/A }
0N/A }
0N/A File dstFile = new File(dstDir, classFileName);
0N/A
0N/A /*
0N/A * Obtain the URL for the codebase.
0N/A */
5673N/A URL codebaseURL = dstDir.toURI().toURL();
0N/A
0N/A /*
0N/A * Specify where we will copy the class definition from, if
0N/A * necessary. After the test is built, the class file can be
0N/A * found in the "test.classes" directory.
0N/A */
0N/A File srcDir = new File(getProperty("test.classes", "."));
0N/A File srcFile = new File(srcDir, classFileName);
0N/A
0N/A mesg(srcFile);
0N/A mesg(dstFile);
0N/A
0N/A /*
0N/A * If the class definition is not already located at the codebase,
0N/A * copy it there from the test build area.
0N/A */
0N/A if (!dstFile.exists()) {
0N/A if (!srcFile.exists()) {
0N/A throw new RuntimeException(
0N/A "could not find class file to install in codebase " +
0N/A "(try rebuilding the test): " + srcFile);
0N/A }
0N/A
0N/A try {
0N/A copyFile(srcFile, dstFile);
0N/A } catch (IOException e) {
0N/A throw new RuntimeException(
0N/A "could not install class file in codebase");
0N/A }
0N/A
0N/A mesg("Installed class \"" + className +
0N/A "\" in codebase " + codebaseURL);
0N/A }
0N/A
0N/A /*
0N/A * After the class definition is successfully installed at the
0N/A * codebase, delete it from the test's CLASSPATH, so that it will
0N/A * not be found there first before the codebase is searched.
0N/A */
0N/A if (srcFile.exists()) {
0N/A if (delete && !srcFile.delete()) {
0N/A throw new RuntimeException(
0N/A "could not delete duplicate class file in CLASSPATH");
0N/A }
0N/A }
0N/A
0N/A return codebaseURL;
0N/A }
0N/A
0N/A public static void copyFile(File srcFile, File dstFile)
0N/A throws IOException
0N/A {
0N/A FileInputStream src = new FileInputStream(srcFile);
0N/A FileOutputStream dst = new FileOutputStream(dstFile);
0N/A
0N/A byte[] buf = new byte[32768];
0N/A while (true) {
0N/A int count = src.read(buf);
0N/A if (count < 0) {
0N/A break;
0N/A }
0N/A dst.write(buf, 0, count);
0N/A }
0N/A
0N/A dst.close();
0N/A src.close();
0N/A }
0N/A
0N/A /** routine to unexport an object */
0N/A public static void unexport(Remote obj) {
0N/A if (obj != null) {
0N/A try {
0N/A mesg("unexporting object...");
0N/A UnicastRemoteObject.unexportObject(obj, true);
0N/A } catch (NoSuchObjectException munch) {
0N/A } catch (Exception e) {
0N/A e.getMessage();
0N/A e.printStackTrace();
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Allow test framework to control the security manager set in
0N/A * each test.
0N/A *
0N/A * @param managerClassName The class name of the security manager
0N/A * to be instantiated and set if no security
0N/A * manager has already been set.
0N/A */
0N/A public static void suggestSecurityManager(String managerClassName) {
0N/A SecurityManager manager = null;
0N/A
0N/A if (System.getSecurityManager() == null) {
0N/A try {
0N/A if (managerClassName == null) {
0N/A managerClassName = TestParams.defaultSecurityManager;
0N/A }
0N/A manager = ((SecurityManager) Class.
0N/A forName(managerClassName).newInstance());
0N/A } catch (ClassNotFoundException cnfe) {
0N/A bomb("Security manager could not be found: " +
0N/A managerClassName, cnfe);
0N/A } catch (Exception e) {
0N/A bomb("Error creating security manager. ", e);
0N/A }
0N/A
0N/A System.setSecurityManager(manager);
0N/A }
0N/A }
0N/A
0N/A /**
5266N/A * Creates an RMI {@link Registry} on a random, un-reserved port.
5266N/A *
5266N/A * @returns an RMI Registry, using a random port.
5266N/A * @throws RemoteException if there was a problem creating a Registry.
5266N/A */
5266N/A public static Registry createRegistryOnUnusedPort() throws RemoteException {
5266N/A return LocateRegistry.createRegistry(getUnusedRandomPort());
5266N/A }
5266N/A
5266N/A /**
5266N/A * Returns the port number the RMI {@link Registry} is running on.
5266N/A *
5266N/A * @param registry the registry to find the port of.
5266N/A * @return the port number the registry is using.
5266N/A * @throws RuntimeException if there was a problem getting the port number.
5266N/A */
5266N/A public static int getRegistryPort(Registry registry) {
5266N/A int port = -1;
5266N/A
5266N/A try {
5266N/A RemoteRef remoteRef = ((RegistryImpl)registry).getRef();
5266N/A LiveRef liveRef = ((UnicastServerRef)remoteRef).getLiveRef();
5266N/A Endpoint endpoint = liveRef.getChannel().getEndpoint();
5266N/A TCPEndpoint tcpEndpoint = (TCPEndpoint) endpoint;
5266N/A port = tcpEndpoint.getPort();
5266N/A } catch (Exception ex) {
5266N/A throw new RuntimeException("Error getting registry port.", ex);
5266N/A }
5266N/A
5266N/A return port;
5266N/A }
5266N/A
5266N/A /**
5266N/A * Returns an unused random port number which is not a reserved port. Will
5266N/A * try up to 10 times to get a random port before giving up and throwing a
5266N/A * RuntimeException.
5266N/A *
5266N/A * @return an unused random port number.
5266N/A * @throws RuntimeException if there was a problem getting a port.
5266N/A */
5266N/A public static int getUnusedRandomPort() {
5266N/A int numTries = 0;
5673N/A IOException ex = null;
5266N/A
5673N/A while (numTries++ < MAX_SERVER_SOCKET_TRIES) {
5673N/A int unusedRandomPort = -1;
5266N/A ex = null; //reset
5266N/A
5266N/A try (ServerSocket ss = new ServerSocket(0)) {
5266N/A unusedRandomPort = ss.getLocalPort();
5673N/A } catch (IOException e) {
5266N/A ex = e;
5673N/A // temporarily print stack trace here until we find out why
5673N/A // tests are failing.
5673N/A System.err.println("TestLibrary.getUnusedRandomPort() caught "
5673N/A + "exception on iteration " + numTries
5673N/A + (numTries==MAX_SERVER_SOCKET_TRIES ? " (the final try)."
5673N/A : "."));
5673N/A ex.printStackTrace();
5266N/A }
5266N/A
5673N/A if (unusedRandomPort >= 0) {
5673N/A if (isReservedPort(unusedRandomPort)) {
5673N/A System.out.println("INFO: On try # " + numTries
5673N/A + (numTries==MAX_SERVER_SOCKET_TRIES ? ", the final try, ": ",")
5673N/A + " ServerSocket(0) returned the reserved port "
5673N/A + unusedRandomPort
5673N/A + " in TestLibrary.getUnusedRandomPort() ");
5673N/A } else {
5673N/A return unusedRandomPort;
5673N/A }
5266N/A }
5266N/A }
5266N/A
5266N/A // If we're here, then either an exception was thrown or the port is
5266N/A // a reserved port.
5673N/A if (ex==null) {
5673N/A throw new RuntimeException("Error getting unused random port. The"
5673N/A +" last port returned by ServerSocket(0) was a reserved port");
5673N/A } else {
5673N/A throw new RuntimeException("Error getting unused random port.", ex);
5673N/A }
5266N/A }
5266N/A
5266N/A /**
5266N/A * Determines if a port is one of the reserved port numbers.
5266N/A *
5266N/A * @param port the port to test.
5266N/A * @return {@code true} if the port is a reserved port, otherwise
5266N/A * {@code false}.
5266N/A */
5266N/A public static boolean isReservedPort(int port) {
5266N/A return ((port >= FIXED_PORT_MIN) && (port <= FIXED_PORT_MAX) ||
5266N/A (port == 1099));
5266N/A }
5266N/A
5266N/A /**
0N/A * Method to capture the stack trace of an exception and return it
0N/A * as a string.
0N/A */
0N/A public String stackTraceToString(Exception e) {
0N/A ByteArrayOutputStream bos = new ByteArrayOutputStream();
0N/A PrintStream ps = new PrintStream(bos);
0N/A
0N/A e.printStackTrace(ps);
0N/A return bos.toString();
0N/A }
0N/A
0N/A /** extra properties */
0N/A private static Properties props;
0N/A
0N/A /**
0N/A * Returns extra test properties. Looks for the file "../../test.props"
0N/A * and reads it in as a Properties file. Assuming the working directory
0N/A * is "<path>/JTwork/scratch", this will find "<path>/test.props".
0N/A */
0N/A private static synchronized Properties getExtraProperties() {
0N/A if (props != null) {
0N/A return props;
0N/A }
0N/A props = new Properties();
0N/A File f = new File(".." + File.separator + ".." + File.separator +
0N/A "test.props");
0N/A if (!f.exists()) {
0N/A return props;
0N/A }
0N/A try {
0N/A FileInputStream in = new FileInputStream(f);
0N/A try {
0N/A props.load(in);
0N/A } finally {
0N/A in.close();
0N/A }
0N/A } catch (IOException e) {
0N/A e.printStackTrace();
0N/A throw new RuntimeException("extra property setup failed", e);
0N/A }
0N/A return props;
0N/A }
0N/A
0N/A /**
0N/A * Returns an extra test property. Looks for the file "../../test.props"
0N/A * and reads it in as a Properties file. Assuming the working directory
0N/A * is "<path>/JTwork/scratch", this will find "<path>/test.props".
0N/A * If the property isn't found, defaultVal is returned.
0N/A */
0N/A public static String getExtraProperty(String property, String defaultVal) {
0N/A return getExtraProperties().getProperty(property, defaultVal);
0N/A }
0N/A}