[jboss-cvs] JBossAS SVN: r111676 - in branches/JBPAPP_5_1/testsuite: src/main/org/jboss/test/scripts and 2 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sun Jun 26 10:55:48 EDT 2011


Author: rsvoboda at redhat.com
Date: 2011-06-26 10:55:47 -0400 (Sun, 26 Jun 2011)
New Revision: 111676

Added:
   branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/PasswordToolTestCase.java
Modified:
   branches/JBPAPP_5_1/testsuite/build.xml
   branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/README.txt
   branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/support/AsyncShellScriptExecutor.java
   branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/RunTestCase.java
   branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/ScriptsTestBase.java
   branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/ShutdownTestCase.java
Log:
JBPAPP-4247 JBQA-4821 JBQA-4827 - tests by jmartisk - new tests for CLI scripts

Modified: branches/JBPAPP_5_1/testsuite/build.xml
===================================================================
--- branches/JBPAPP_5_1/testsuite/build.xml	2011-06-24 19:00:51 UTC (rev 111675)
+++ branches/JBPAPP_5_1/testsuite/build.xml	2011-06-26 14:55:47 UTC (rev 111676)
@@ -4459,6 +4459,7 @@
          <include name="**/test/scripts/test/WsconsumeTestCase.class"/>
          <include name="**/test/scripts/test/WsprovideTestCase.class"/>
          <include name="**/test/scripts/test/WstoolsTestCase.class"/>
+         <include name="**/test/scripts/test/PasswordToolTestCase.class"/>
 	  </fileset>
       </batchtest>
     </junit>

Modified: branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/README.txt
===================================================================
--- branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/README.txt	2011-06-24 19:00:51 UTC (rev 111675)
+++ branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/README.txt	2011-06-26 14:55:47 UTC (rev 111676)
@@ -16,8 +16,8 @@
 
 tests-scripts-noserver:
 - makes use of a JBoss instance 'scripts-noserver' which is based on 'default'
-- executes RunTestCase, ShutdownTestCase, WsconsumeTestCase, WsprovideTestCase
-and WstoolsTestCase
+- executes RunTestCase, ShutdownTestCase, WsconsumeTestCase, WsprovideTestCase,
+WstoolsTestCase and PasswordToolTestCase.
 - run.sh is used to start the servers
 - JMX shutdown or shutdown.sh is used to stop the servers, depending on
 the test case in question

Modified: branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/support/AsyncShellScriptExecutor.java
===================================================================
--- branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/support/AsyncShellScriptExecutor.java	2011-06-24 19:00:51 UTC (rev 111675)
+++ branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/support/AsyncShellScriptExecutor.java	2011-06-26 14:55:47 UTC (rev 111676)
@@ -26,16 +26,10 @@
 import java.io.InputStreamReader ;
 import java.io.PrintWriter ;
 import java.io.StringWriter ;
-import java.io.FileReader ;
-import java.io.FileWriter ;
 import java.io.File ;
-import java.io.FileInputStream ;
-import java.io.FileOutputStream ;
-import java.io.FileNotFoundException ;
 import java.io.IOException ;
+import org.jboss.util.file.Files;
 
-import org.jboss.test.scripts.support.AbstractShellScriptExecutor ;
-
 /**
  * Class to execute shell scripts asynchronously and collect output
  * 
@@ -251,7 +245,7 @@
 			shutdownTarget = deployDir + "/shutdown.sar" ;
 			// System.out.println("source = " + source) ;
 			// System.out.println("target = " + target) ;
-			copyFile(new File(shutdownSource), new File(shutdownTarget));
+                        Files.copy(new File(shutdownSource), new File(shutdownTarget));
 		}
 		catch(Exception e) {
 			throw new IOException("Problem deploying shutdown: " + e.getMessage()) ;
@@ -278,23 +272,4 @@
 		catch(InterruptedException ie2) {
 		}
 	}
-
-	private void copyFile(File in, File out) throws Exception {
-		FileInputStream fis  = new FileInputStream(in);
-		FileOutputStream fos = new FileOutputStream(out);
-		try {
-			byte[] buf = new byte[1024];
-			int i = 0;
-			while ((i = fis.read(buf)) != -1) {
-				fos.write(buf, 0, i);
-			}
-		} 
-		catch (Exception e) {
-			throw e;
-		}
-		finally {
-			if (fis != null) fis.close();
-			if (fos != null) fos.close();
-		}
-	}
 }

Added: branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/PasswordToolTestCase.java
===================================================================
--- branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/PasswordToolTestCase.java	                        (rev 0)
+++ branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/PasswordToolTestCase.java	2011-06-26 14:55:47 UTC (rev 111676)
@@ -0,0 +1,415 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009 Red Hat Middleware, Inc. and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.scripts.test;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.io.InputStreamReader;
+import java.io.ByteArrayOutputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import org.jboss.test.security.beans.TestPasswordInjectedBean;
+import org.jboss.util.file.Files;
+import javax.naming.InitialContext;
+import javax.management.ObjectName;
+
+/**
+ * Unit tests of password_tool.sh / password_tool.bat
+ *
+ * @author Jan Martiska
+ * @version $Revision: $
+ */
+public class PasswordToolTestCase extends ScriptsTestBase
+{
+   private ObjectName SERVER_OBJ_NAME = null;
+
+   private final File WORKING_DIR = new File(getBinDir());
+   private final File JBOSS_DIST_DIR = new File(getDistDir());
+
+   private final String KEYSTORE_PASSWORD = "testpass";
+   private final String ALIAS_NAME = "jboss";
+   private final String DOMAIN_NAME = "test-bean";
+   private final String DOMAIN_PASSWORD = "TaWg84T%$&207";
+
+   private final int STOP_TIMEOUT = Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_JBOSSAS_SHUTDOWN_TIMEOUT, "30"));
+   private final int START_TIMEOUT = Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_JBOSSAS_STARTUP_TIMEOUT, "120"));
+
+   private final PrintStream sysOut = System.out;
+
+   /**
+    * Create a new PasswordToolTestCase.
+    *
+    * @param name
+    */
+   public PasswordToolTestCase(String name)
+   {
+      super(name);
+   }
+
+   /**
+    * preparation before every testing method
+    * Didn't use JUnit setUp method cause it was causing some problems
+    */
+   private void before() throws Exception
+   {
+      // delete the keystore if it already exists
+      File keystore = new File(WORKING_DIR, "server.keystore");
+      if (keystore.exists())
+         keystore.delete();
+
+      // delete directory "bin/password" and all of its contents
+      File passwordDirectory = new File(WORKING_DIR, "password");
+      if (passwordDirectory.exists())
+         Files.delete(passwordDirectory);
+
+      // create new keystore
+      Process p = Runtime.getRuntime().exec(
+            new String[] { "keytool", "-genkey", "-alias", ALIAS_NAME, "-keyalg", "RSA", "-keysize",
+            "1024", "-keystore", "server.keystore", "-storepass", "testpass",
+                  "-dname", "cn=JBoss Security,ou=JBoss Division,o=RedHatInc,l=Raleigh,st=NC,c=US",
+                  "-keypass", "testpass" }, null, WORKING_DIR);
+      BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
+      BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+      p.waitFor();
+
+      assertTrue("keytool command should not return anything in stdout", in.readLine() == null);
+      assertTrue("keytool command should not return anything in stderr", err.readLine() == null);
+   }
+
+   /**
+    * cleanup after every testing method
+    * Didn't use JUnit tearDown method cause it was causing some problems
+    */
+   private void after()
+   {
+      // delete directory "bin/password" and all of its contents
+      File passwordDirectory = new File(WORKING_DIR, "password");
+      if (passwordDirectory.exists())
+         Files.delete(passwordDirectory);
+      // delete file "bin/server.keystore"
+      File keystore = new File(WORKING_DIR, "server.keystore");
+      if (keystore.exists())
+         keystore.delete();
+   }
+
+   /**
+    * Tests option "0" = encrypt a keystore password
+    * Command: echo 0 testpass alongsaltstring 12308 5 | ./password_tool.sh
+    * The result: file $JBOSS_DIST/bin/password/jboss_keystore_pass.dat is created
+    *
+    * @throws Exception
+    */
+   public void testEncryptKeystorePassword() throws Exception
+   {
+      before();
+      this.encryptKeystorePassword(KEYSTORE_PASSWORD);
+      after();
+   }
+
+   /**
+    * Tests option "1" = specify keystore location and alias
+    * Command: echo 1 server.keystore jboss | ./password_tool.sh
+    * This needs to be done before every command following, as the program
+    * doesn't seem to remember the keystore location from one invocation
+    * to the next
+    *
+    * @throws Exception
+    */
+   public void testSpecifyKeystoreLocation() throws Exception
+   {
+      before();
+      this.encryptKeystorePassword(KEYSTORE_PASSWORD); // setup
+
+      Process p = startPasswordTool("1 server.keystore " + ALIAS_NAME + " 5");
+      BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+      BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
+      String s;
+      boolean failed = false;
+      while (stdout.readLine() != null)
+      {
+      }
+      while ((s = stderr.readLine()) != null)
+      { //  the error output must not contain "Exception"
+         if (s.indexOf("Exception") != -1)
+            failed = true;
+         if (failed)
+            System.out.println(s);
+      }
+      p.waitFor();
+      after();
+      if (failed)
+         fail("password_tool threw an exception while specifying keystore location");
+   }
+
+   /**
+    * Tests option "1" = specify a keystore location and an INVALID alias = should FAIL
+    * Command: echo 1 server.keystore foo | ./password_tool.sh
+    *
+    * @throws Exception
+    */
+   public void testSpecifyInvalidKeystoreAlias() throws Exception
+   {
+      before();
+      this.encryptKeystorePassword(KEYSTORE_PASSWORD); // setup
+
+      Process p = startPasswordTool("1 server.keystore " + ALIAS_NAME + "foo 5");
+      BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+      BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
+      while (stdout.readLine() != null)
+      {
+      }
+      String s;
+      // we search the error output for a substring: "Exception" -> one has to be thrown
+      boolean found = false;
+      while ((s = err.readLine()) != null)
+      {
+         if (s.indexOf("Exception") != -1)
+            found = true;
+      }
+      p.waitFor();
+
+      after();
+      assertTrue("password_tool should raise an Exception if given an invalid keystore alias", found);
+   }
+
+   /**
+    * Tests option "4" : checks for security domain password existence
+    * Command: echo "1 server.keystore jboss 4 test-bean 5" | ./password_tool.sh
+    * Result: "Exists = true" in the standard output
+    *
+    * @throws Exception
+    */
+   public void testCheckSecurityDomainExistence() throws Exception
+   {
+      before();
+      this.encryptKeystorePassword(KEYSTORE_PASSWORD); // setup
+      this.createSecurityDomain(DOMAIN_NAME, DOMAIN_PASSWORD); // setup
+      this.checkSecurityDomainExistence(DOMAIN_NAME, true);
+      after();
+   }
+
+   /**
+    * Tests option "3": delete security domain password
+    * Command: echo "1 server.keystore jboss 3 messaging 5" | ./password_tool.sh
+    *
+    * @throws Exception
+    */
+   public void testDeleteSecurityDomain() throws Exception
+   {
+      before();
+      this.encryptKeystorePassword(KEYSTORE_PASSWORD); // setup
+      this.createSecurityDomain(DOMAIN_NAME, DOMAIN_PASSWORD); // setup
+
+      this.deleteSecurityDomain(DOMAIN_NAME);
+      // test if the domain was really deleted
+      this.checkSecurityDomainExistence(DOMAIN_NAME, false);
+      after();
+   }
+
+   /**
+    * simulates the test org.jboss.test.passwordinjection.test.PasswordInjectionUnitTestCase
+    * @throws Exception
+    */
+   public void testPasswordInjection() throws Exception
+   {
+      before();
+
+      final ByteArrayOutputStream myOut = new ByteArrayOutputStream();
+      System.setOut(new PrintStream(myOut));
+
+      // generate new server.keystore and directory password, overwrite those in passwordtest config
+      // a fresh server.keystore already exists. name it password.keystore
+      this.encryptKeystorePassword(KEYSTORE_PASSWORD);
+      this.createSecurityDomain(DOMAIN_NAME, DOMAIN_PASSWORD);
+
+      // mkdir server/production/conf/password
+      File passworddir = new File(JBOSS_DIST_DIR.getAbsolutePath() + FS + "server" +
+              FS + "production" + FS + "conf" + FS + "password");
+      try
+      {
+         if (!passworddir.exists())
+            passworddir.mkdir();
+      }
+      catch (Exception e)
+      {
+         System.out.println("Exception: " + e.getMessage());
+      }
+
+      // copy bin/server.keystore -> server/production/conf/password/password.keystore
+      File serverKeystore = new File(WORKING_DIR, "server.keystore");
+      Files.copy(new File(WORKING_DIR.getAbsolutePath() + FS + "server.keystore"),
+              new File(passworddir.getAbsolutePath() + FS + "password.keystore"));
+
+      // cp  bin/password/jboss_keystore_pass.dat server/production/conf/password/jboss_keystore_pass.dat
+      Files.copy(new File(WORKING_DIR.getAbsolutePath() + FS + "password" + FS + "jboss_keystore_pass.dat"),
+              new File(passworddir.getAbsolutePath() + FS  + "jboss_keystore_pass.dat"));
+      Files.copy(new File(WORKING_DIR.getAbsolutePath() + FS + "password" + FS + "jboss_password_enc.dat"),
+              new File(passworddir.getAbsolutePath() + FS + "jboss_password_enc.dat"));
+
+      // run the "production" configuration
+      Exception fail = null;
+      String[] shellCommand = getShellCommand("run", "-c production -b " + getServerHost(), null);
+      String[] envp = null;
+      try
+      {
+         // execute command
+         getAsyncShellScriptExecutor().startShellCommand(shellCommand, envp, WORKING_DIR);
+         // waitForServerStart kills the process and throws an exception if server does not start
+         waitForServerStart(getAsyncShellScriptExecutor(), getServerHost(), START_TIMEOUT);
+         System.out.println("Server started successfully");
+
+         // run the contents of org.jboss.test.passwordinjection.test.PasswordInjectionUnitTestCase
+         String passBeans = "test-password-jboss-beans.xml";
+         String jarName = "passwordbean.jar";
+         deploy(jarName);
+         // deploy the Password Beans
+         String url1 = getResourceURL("security/password-mask/" + passBeans);
+         deploy(url1);
+
+         InitialContext ic = new InitialContext();
+         TestPasswordInjectedBean tp = (TestPasswordInjectedBean)ic.lookup("testJNDIBean");
+         assertNotNull("Password Bean is in JNDI", tp);
+         assertTrue("Password has not been injected", tp.isPasswordSet());
+
+         // search for expected password in stdout
+         String outStream = myOut.toString();
+         assertTrue("Domain password should appear in the standard output: " + outStream, outStream.indexOf(DOMAIN_PASSWORD) != -1);
+
+         undeploy(jarName);
+         // undeploy the Password Beans
+         url1 = getResourceURL("security/password-mask/" + passBeans);
+         undeploy(url1);
+      }
+      catch (Exception e)
+      {
+         fail = e;
+      }
+      finally
+      {
+         // shutdown the server using the shutdown command
+         String[] shutdownCommand = getShellCommand("shutdown", "-s " + getJndiURL() + " -S", null);
+         getShellScriptExecutor().runShellCommand(shutdownCommand, envp, WORKING_DIR);
+
+         System.out.println("shutdown output = " + getShellScriptExecutor().getOutput());
+         System.out.println("shutdown error = " + getShellScriptExecutor().getError());
+
+         // waitForServerStop kills the process and throws an exception if server does not stop
+         waitForServerStop(getAsyncShellScriptExecutor(), STOP_TIMEOUT);
+         System.out.println("Server stopped successfully");
+         getAsyncShellScriptExecutor().assertOnOutputStream(SERVER_STOPPED_MESSAGE,
+                 "Server shutdown message did not appear in logs");
+
+         // rm -r server/production/conf/password
+         Files.delete(new File(JBOSS_DIST_DIR.getAbsolutePath() + FS + "server" + FS +
+                 "production" + FS + "conf" + FS + "password"));
+
+         System.setOut(sysOut);
+         after();
+         if (fail != null)
+            fail(fail.getMessage());
+      }
+   }
+
+   private void encryptKeystorePassword(String password) throws Exception
+   {
+      Process p = startPasswordTool("0 " + password + " SaltyStringy 208 5");
+      BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
+      String s;
+      // we search the output for a substring: "Keystore Password encrypted into"
+      boolean found = false;
+      while ((s = stdout.readLine()) != null)
+      {
+         if (s.indexOf("Keystore Password encrypted into") != -1)
+            found = true;
+      }
+      p.waitFor();
+      assertTrue("password_tool should return \"Keystore Password encrypted\" into the standard output", found);
+   }
+
+   private void createSecurityDomain(String domain, String password) throws Exception
+   {
+      Process p = startPasswordTool("1 server.keystore jboss 2 " + domain + " " + password + " 5");
+
+      BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
+      String s;
+      // we search the standard output for password creation confirmation
+      boolean found = false;
+      while ((s = stdout.readLine()) != null)
+      {
+         if (s.indexOf("Password created for domain:" + domain) != -1)
+            found = true;
+      }
+      p.waitFor();
+      assertTrue("keytool did not create a password for domain " + domain, found);
+   }
+
+   private void deleteSecurityDomain(String domain) throws Exception
+   {
+      Process p = startPasswordTool("1 server.keystore " + ALIAS_NAME + " 3 " + domain + " 5");
+
+      BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
+      String s;
+      // we search the standard output for password creation confirmation
+      boolean found = false;
+      while (stdout.readLine() != null)
+      {
+      }
+      p.waitFor();
+   }
+
+   private void checkSecurityDomainExistence(String domain, boolean existence) throws Exception
+   {
+      Process p = startPasswordTool("1 server.keystore " + ALIAS_NAME + " 4 " + DOMAIN_NAME + " 5");
+      BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
+      String s;
+      // we search the standard output for password creation confirmation
+      boolean found = false;
+      while ((s = stdout.readLine()) != null)
+      {
+         if (s.indexOf(existence ? "Exists = true" : "Exists = false") != -1)
+            found = true;
+      }
+      p.waitFor();
+      assertTrue(existence ? "password_tool did not confirm existence of a password for security domain"
+            : "password_tool did not confirm non-existence of security domain password", found);
+   }
+
+   /**
+    * starts the password tool and optionally (very recommendedly) sends some data to its standard input
+    * do NOT open its stdin any time after that again  !!!
+    * hint: most likely the string for stdin will end with "5" that means the script will exit
+    *
+    * @param stdin string to be sent to standard input of password_tool.bat/sh
+    * @return password_tool's process
+    */
+   private Process startPasswordTool(String stdin) throws IOException
+   {
+      Process p = Runtime.getRuntime().exec(isWindows() ? new String[] { "cmd", "/c", "password_tool" } : new String[] { "./password_tool.sh" }, null, WORKING_DIR);
+      OutputStream stdinStream = p.getOutputStream();
+      stdinStream.write(stdin.getBytes());
+      stdinStream.close();
+      return p;
+   }
+
+}

Modified: branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/RunTestCase.java
===================================================================
--- branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/RunTestCase.java	2011-06-24 19:00:51 UTC (rev 111675)
+++ branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/RunTestCase.java	2011-06-26 14:55:47 UTC (rev 111676)
@@ -24,6 +24,7 @@
 
 import java.io.File ;
 import java.io.IOException ;
+import java.io.FileReader;
 import javax.management.ObjectName ;
 import javax.management.MalformedObjectNameException ;
 
@@ -56,11 +57,9 @@
  */
 public class RunTestCase extends ScriptsTestBase
 {
-	private ObjectName SERVER_OBJ_NAME = null ;
-        public static final String SYSTEM_PROPERTY_JBOSSAS_STARTUP_TIMEOUT  = "jbosstest.jbossas.startup.timeout";
-        public static final String SYSTEM_PROPERTY_JBOSSAS_SHUTDOWN_TIMEOUT = "jbosstest.jbossas.shutdown.timeout";
-        private static final int STOP_TIMEOUT = Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_JBOSSAS_SHUTDOWN_TIMEOUT, "30"));
-        private static final int START_TIMEOUT = Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_JBOSSAS_STARTUP_TIMEOUT, "120"));
+	private ObjectName SERVER_OBJ_NAME = null ;        
+   private static final int STOP_TIMEOUT = Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_JBOSSAS_SHUTDOWN_TIMEOUT, "30"));
+   private static final int START_TIMEOUT = Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_JBOSSAS_STARTUP_TIMEOUT, "120"));
 
    /**
     * Create a new RunTestCase.
@@ -194,7 +193,97 @@
 		   
 		   fail("Server failed to stop") ;
 	   }
-   }  
+   } 
+
+   /**
+    * Test whether the PIDFILE is correctly removed after stopping a server which
+    * had been started in background ($RUN_JBOSS_IN_BACKGROUND) with $JBOSS_PIDFILE set
+    * can run only on linux systems! (Solaris making trouble too, might be fixed in future)
+    */
+   public void testJBossInBackgroundPlusPidFile() throws Exception
+   {
+      if (!isLinux())
+      {
+          System.out.println("Not Linux, nothing to test.");
+         return;
+      }
+
+      String command = "run";
+      String options = null;
+      String args = "-c production -b " + getServerHost();
+      String[] shellCommand = getShellCommand(command, options, args);
+
+      File pidFile;
+      try
+      {
+         pidFile = File.createTempFile("jbosspidfile", null);
+         pidFile.delete();   // we just need a suitable absolute path, the file will be created later
+      }
+      catch (IOException e)
+      {
+         fail("could not create a temporary file: " + e.getMessage());
+         return;
+      }
+
+      // TODO Solaris machines tend to fail if ANY environment variables are given this way. Why?
+
+      // set the environment
+      String[] envp = new String[] { "LAUNCH_JBOSS_IN_BACKGROUND=true", "JBOSS_PIDFILE=" + pidFile.getAbsolutePath() };
+      System.out.println("created pidFile: " + pidFile.getAbsolutePath());
+
+      // set the working directory
+      File workingDir = new File(getBinDir());
+
+      // run+shutdown the server
+      getAsyncShellScriptExecutor().startShellCommand(shellCommand, envp, workingDir);
+      boolean invalidPidInFile = false;
+      try
+      {
+         waitForServerStart(getAsyncShellScriptExecutor(), getServerHost(), START_TIMEOUT);
+         System.out.println("Server started successfully, START_TIMEOUT is " + START_TIMEOUT);
+
+         // check that the file exists
+         assertTrue("pidFile doesn't exist.", pidFile.exists());
+
+         FileReader pidReader = new FileReader(pidFile);
+         char[] pidArray = new char[30];
+         pidReader.read(pidArray);
+         int pid = Integer.parseInt(new String(pidArray).trim());
+         System.out.println("PID = " + pid);
+
+         // check that this pid really exists
+         Process p = Runtime.getRuntime().exec("kill -0 " + pid);
+         p.waitFor(); // this will return non-zero exit value if no such pid exists
+         assertTrue("Script wrote an invalid pid into pidfile", p.exitValue() == 0);
+
+         Runtime.getRuntime().exec("kill -15 " + pid);
+      }
+      catch (NumberFormatException nfe)
+      {
+         invalidPidInFile = true;
+         fail("could not parse PID from pidFile");
+      }
+      catch (Exception e)
+      {
+         System.out.println("Exception: message = " + e.getMessage());
+         writeLogsToTestCase();
+         fail("Server failed to start");
+      }
+      finally
+      {
+         if (invalidPidInFile)
+         { // just an optimalization, waitForServerStop would do this anyway
+            getServer().invoke(SERVER_OBJ_NAME, "shutdown", new Object[0], new String[0]);
+         }
+         waitForServerStop(getAsyncShellScriptExecutor(), STOP_TIMEOUT);
+         System.out.println("Server stopped successfully");
+         pidFile.deleteOnExit();
+      }
+
+      // check that the file is deleted
+      Thread.sleep(2000);
+      assertFalse("pidfile should be deleted", pidFile.exists());
+   } 
    
    private void writeLogsToTestCase() {
 	   

Modified: branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/ScriptsTestBase.java
===================================================================
--- branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/ScriptsTestBase.java	2011-06-24 19:00:51 UTC (rev 111675)
+++ branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/ScriptsTestBase.java	2011-06-26 14:55:47 UTC (rev 111676)
@@ -24,20 +24,20 @@
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
-import java.io.IOException ;
+import java.io.IOException;
 
-import java.net.URL ;
-import java.net.MalformedURLException ;
-import java.net.URLConnection ;
-import java.net.HttpURLConnection ;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+import java.net.HttpURLConnection;
 
-import org.jboss.test.scripts.support.LogFileAssertionChecker ;
-import org.jboss.test.scripts.support.ShellScriptExecutor ;
-import org.jboss.test.scripts.support.AsyncShellScriptExecutor ;
+import org.jboss.test.scripts.support.LogFileAssertionChecker;
+import org.jboss.test.scripts.support.ShellScriptExecutor;
+import org.jboss.test.scripts.support.AsyncShellScriptExecutor;
 
-import org.jboss.test.JBossTestCase ;
+import org.jboss.test.JBossTestCase;
 
-import junit.framework.Assert ;
+import junit.framework.Assert;
 
 /**
  * Base class to test command-line scripts.
@@ -47,431 +47,509 @@
  */
 public abstract class ScriptsTestBase extends JBossTestCase
 {
-	public static final String SERVER_STARTED_MESSAGE = "Started in" ;
-	public static final String SERVER_STOPPED_MESSAGE = "Shutdown complete" ;
-	public static final String SERVER_HALT_MESSAGE = "Server halt" ;
-	public static final String SERVER_EXIT_MESSAGE = "Server exit" ;
-	public static final String SERVER_HALTED_MESSAGE = "halting the JVM now" ;	
-	
-	ShellScriptExecutor se = null ;
-	AsyncShellScriptExecutor ase = null ;
-	LogFileAssertionChecker errorLogChecker = null ;
-	LogFileAssertionChecker outputLogChecker = null ;
-	LogFileAssertionChecker bootLogChecker = null ;
-	LogFileAssertionChecker systemLogChecker = null ;
-	LogFileAssertionChecker auditLogChecker = null ;
+   public static final String SERVER_STARTED_MESSAGE = "Started in";
+   public static final String SERVER_STOPPED_MESSAGE = "Shutdown complete";
+   public static final String SERVER_HALT_MESSAGE = "Server halt";
+   public static final String SERVER_EXIT_MESSAGE = "Server exit";
+   public static final String SERVER_HALTED_MESSAGE = "halting the JVM now";
 
-        protected static final String FS = System.getProperty("file.separator"); // '/' on unix, '\' on windows
+   public static final String SYSTEM_PROPERTY_JBOSSAS_STARTUP_TIMEOUT = "jbosstest.jbossas.startup.timeout";
+   public static final String SYSTEM_PROPERTY_JBOSSAS_SHUTDOWN_TIMEOUT = "jbosstest.jbossas.shutdown.timeout";
 
-	/**
-	 * There are cases one doesn't want to check for ERRORs or Exceptions in the logs.
-	 * Default set to true to not to interfere with previous behaviour.  
-	 */
-	private boolean checkLogsForErrors = true;
-	
-	public ScriptsTestBase(String name)
-	{
-		super(name);
-		
-		// initialise the script executors
-		se = new ShellScriptExecutor() ;
-		ase = new AsyncShellScriptExecutor() ;
-				
-		// initialise the log checkers (error checking here could be improved)
-		// these will be initialised to a single server instance, so we canb't change server instances
-		// part way through a test suite! :-(
-		String logDir = getLogDir() ;
-		errorLogChecker = new LogFileAssertionChecker(logDir + "/error.log") ;
-		outputLogChecker = new LogFileAssertionChecker(logDir + "/output.log") ;
-		bootLogChecker = new LogFileAssertionChecker(logDir + "/boot.log") ;
-		systemLogChecker = new LogFileAssertionChecker(logDir + "/system.log") ;
-		auditLogChecker = new LogFileAssertionChecker(logDir + "/audit.log") ;
-		
-	}
+   ShellScriptExecutor se = null;
+   AsyncShellScriptExecutor ase = null;
+   LogFileAssertionChecker errorLogChecker = null;
+   LogFileAssertionChecker outputLogChecker = null;
+   LogFileAssertionChecker bootLogChecker = null;
+   LogFileAssertionChecker systemLogChecker = null;
+   LogFileAssertionChecker auditLogChecker = null;
 
-	protected void setUp() throws Exception {
-		super.setUp();		
-		// setup AsyncShellScriptExecutor to deploy shutdown.sar 
-		ase.setUseShutdown(true) ;
-		ase.setPathToShutdownSar(getDeployURL("shutdown.sar").getPath()) ;
-		ase.setDeployDir(getDeployDir()) ;
-	}
-	protected void tearDown() throws Exception {
-		super.tearDown();
-	}
-	public ShellScriptExecutor getShellScriptExecutor() {
-		return se ;
-	}
-	public AsyncShellScriptExecutor getAsyncShellScriptExecutor() {
-		return ase ;
-	}
-	public LogFileAssertionChecker getOutputLogChecker() {
-		return outputLogChecker ;
-	}
-	public LogFileAssertionChecker getErrorLogChecker() {
-		return errorLogChecker ;
-	}
-	public LogFileAssertionChecker getBootLogChecker() {
-		return bootLogChecker ;
-	}
-	public LogFileAssertionChecker getSystemLogChecker() {
-		return systemLogChecker ;
-	}
-	public LogFileAssertionChecker getAuditLogChecker() {
-		return auditLogChecker ;
-	}
-	
-	/* location helpers 
-	 * 
-	 * these really need to be improved to use JBossTestCase, but unfortunately
-	 * JBossTestCase does not give us direct access to the deploy directory
-	 * Here, i'm mimicking what they do
-	 */
-	public String getDistDir() {
-		String distDir = System.getProperty("jboss.dist") ;
-		if (distDir == null)
-			fail("Can't get the JBoss distribution directory") ;
-		return distDir ;
-	}
-	
-	/*
-	 * how to get the server directory?
-	 */
-	public String getServerConfig() {
-		String serverConfig = System.getProperty("jbosstest.server.config");
-	    if (serverConfig == null)
-	    {
-	       serverConfig = "default";
-	    }
-		return serverConfig ;
-	}
-	
-	public String getBinDir() {		
-		return getDistDir() + "/bin" ;
-	}
-	
-	public String getLogDir() {		
-		return getDistDir() + "/server/" + getServerConfig() + "/log" ;
-	}
-	
-	public String getDeployDir() {		
-		return getDistDir() + "/server/" + getServerConfig() + "/deploy" ;
-	}
-	
-	public boolean isWindows() {
-		String osName = System.getProperty("os.name") ;
-		if (osName == null)
-			fail("Can't get the operating system name") ;		
-		return (osName.indexOf("Windows") > -1) || (osName.indexOf("windows") > -1) ;
-	}
-	
-	/* 
-	 * method for constructing command lines for the shell executor, which
-	 * in general takes three arguments
-	 * String[] command, String[] envp, File workingDirectory
-	 * 
-	 * This command creates the first argument. 
-	 * 
-	 * Windows: three tokens need to be passed in String[] command
-	 * cmd /c <entire command string to execute>
-	 * cmd /c "twiddle.bat -s jnp://192.168.0.100 jsr77" 
-	 *  
-	 * UNIX: three tokens need to be passed in String[] command
-	 * bash -c <entire command string to execute>
-	 * bash -c "./twiddle.sh -s jnp://192.168.0.100 jsr77"
-	 * 
-	 * This arrangement may not be optimal ...
-	 */
-	public String[] getShellCommand(String commandName, String options, String args) {
-		
-		String[] shellCommand = new String[3] ;
-		String commandLine = null ;
-		
-		if (commandName == null)
-			fail("No command name specified for shell to execute") ;
-		
-		// set up the base command (platform specific)
-		if (isWindows()) {
-			shellCommand[0] = "cmd" ;
-			shellCommand[1] = "/c" ;
-			commandLine = commandName + ".bat" ;
-		}
-		else {
-			shellCommand[0] = "bash" ;
-			shellCommand[1] = "-c" ;
-			commandLine = "./" + commandName + ".sh" ;
-		}
-		// add in the rest (platform-independent)
-		if (options != null)
-			commandLine += " " + options ;
-		if (args != null)
-			commandLine += " " + args ;
-		
-		shellCommand[2] = commandLine ;
-		
-		return shellCommand ;
-	}
-	
-	/* assertion helpers */	
-	public void assertOnOutputLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint) {
-		if (!outputLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint)) {
-			// assertion does not hold
-			Assert.fail(failureMessage) ;
-		}
-	}
-	
-	public void assertOnErrorLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint) {
-		if (!errorLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint)) {
-			// assertion does not hold
-			Assert.fail(failureMessage) ;
-		}
-	}
-	
-	public void assertOnBootLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint) {
-		if (!bootLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint)) {
-			// assertion does not hold
-			Assert.fail(failureMessage) ;
-		}
-	}
-	
-	public void assertOnSystemLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint) {
-		if (!systemLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint)) {
-			// assertion does not hold
-			Assert.fail(failureMessage) ;
-		}
-	}		
+   protected static final String FS = System.getProperty("file.separator"); // '/' on unix, '\' on windows
 
-	public void assertOnAuditLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint) {
-		if (!auditLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint)) {
-			// assertion does not hold
-			Assert.fail(failureMessage) ;
-		}
-	}		
-	
-	/* check if there is a Tomcat connection to the server */
-	private boolean isServerStarted(String host) throws MalformedURLException {
-		// URL to Tomcat 
-		URL url = new URL("http", host, 8080, "/") ;
-		try {
-			log.trace("Trying to open the connection to host " + host);
-			URLConnection conn = url.openConnection() ;
-			log.trace("URLConnection class name="+conn.getClass().getName());
-			if (conn instanceof HttpURLConnection) {
-				HttpURLConnection http = (HttpURLConnection) conn ;
-				int responseCode = http.getResponseCode();
-				log.trace("responseCode="+responseCode);
-				
-				if (responseCode > 0 && responseCode < 400) {
-					return true ;
-				}
-			}
-		}
-		catch(IOException e) {
-			return false ;
-		}
-		return false ;
-	}
-	
-	/* 
-	* Wait for the server (started by the AsyncShellExecutor) to start
-	* 
-	* @throws Exception 	if server does not start successfully
-	*  
-	* A successful server start means: 
-	* (i) we can reach Tomcat 
-	* (ii) no exceptions in error log
-	* (iii) no ERROR statements in the server log
-	* If the server does not start successfully, we call joinShellCommand with a 1 second timout.
-	* This will wait for one second and then attempt to shutdown both the server and the bash shell,
-	* before throwing an exception. 
-	*   
-	* NOTE: this is a hack, and assumes the process has been started using the AsynchShellExecutor   
-	*/
-	protected void waitForServerStart(AsyncShellScriptExecutor ase, String host, int timeout) throws IOException  {
-		boolean serverStarted = false ;
-		boolean logsExceptionFree = true ;
-		
-		int tries = 0 ;	
-		while (tries++ < timeout) {
-			if (!ase.isRunning()) {
-				throw new IOException("Server failed to start. See logs.") ;
-			}
-			// wait for a sec
-			sleepForSeconds(1) ;
-			
-			if (isServerStarted(host)) {
-				serverStarted = true ;
-				break ;
-			}
-		}		
-		
-		// problem here is that if another server is started:
-		// (i) the preceeding code will indicate serverStarted=true
-		// (iI) the following code will get executed before the starting server has had a chance to start 
-		// (and before exceptions are written).
-		// This results in two servers being started, one incompletely.
-		// So wait here for 5 seconds to allow the logs to accumulate exceptions.
-		sleepForSeconds(5) ;
-		
-		// check for startup errors in the server logs. We check both because:
-		// (i) log4j will write all CONSOLE appender logging to System.in only, and these
-		// may contain ERROR log entries corresponding to exceptions
-		// (ii) other exceptions in the AS should get written to System.err if not handled
-		// via log4j
-		if (isCheckLogsForErrors() && 
-				((ase.getOutput().indexOf("ERROR") > -1) || ase.getError().indexOf("Exception") > -1)) {
-			logsExceptionFree = false ;
-		}
-		
-		// debugging
-		//System.out.println("Server started = " + serverStarted) ;
-		//System.out.println("logsExceptionFree = " + logsExceptionFree) ;
-		//System.out.println("output = " + ase.getOutput()) ;
-		//System.out.println("error = " + ase.getError()) ;
-		
-		// kill the server before going on if not correctly started 
-		if (!serverStarted || !logsExceptionFree) {
-			// kill process and close streams
-			ase.joinShellCommand(1) ;
-			
-			// now throw exception 
-			if (!serverStarted)
-				throw new IOException("Server failed to start: couldn't connect to Tomcat. See logs.") ;
-			else if (!logsExceptionFree) {
-				throw new IOException("Server failed to start: ERROR statements found. See logs.") ;				
-			}
-		}
-		// if we reach here, the server started and no ERRORs were found
-	}
-	
-	/* Wait for the server (started by the AsyncShellExecutor) to stop
-	* 
-	* @throws Exception 	if server does not stop successfully
-	*  
-	* A successful server start means: 
-	* (i) we see the "VM halted" message in the server log
-	* (ii) no ERROR statements in the server log
-	* If the server does not stop successfully, we call joinShellCommand with a 1 second timout.
-	* This will wait for one second and then attempt to shutdown both the server and the bash shell,
-	* before throwing an exception. 
-	*/
-	protected void waitForServerStop(AsyncShellScriptExecutor ase, int timeout) throws IOException {
-		boolean serverStopped = false ;
-		boolean logsExceptionFree = true ;
-		boolean haltCalled = false ;
+   /**
+    * There are cases one doesn't want to check for ERRORs or Exceptions in the logs.
+    * Default set to true to not to interfere with previous behaviour.  
+    */
+   private boolean checkLogsForErrors = true;
 
-		System.out.println("waitForServerStop: waiting " + timeout + " seconds") ;
-		
-		int tries = 0 ;
-		while (tries++ < timeout) {
-			if (!ase.isRunning()) {
-				// FIX-ME
-				throw new IOException("Server not running on shutdown. Something fishy") ;
-			}	
-			// check if stopped by inspecting console log
-			String currentOutput = ase.getOutput() ;
-			if (currentOutput.indexOf(SERVER_STOPPED_MESSAGE) > -1 || currentOutput.indexOf(SERVER_HALTED_MESSAGE) > -1) {
-				serverStopped = true ;
-				break;
-			}
-			
-			// wait for a sec
-			sleepForSeconds(1) ;
-		}
-		
-		// Wait here for 5 seconds to allow the logs to accumulate.
-		sleepForSeconds(5) ;
+   public ScriptsTestBase(String name)
+   {
+      super(name);
 
-		// check for shutdown errors in the server logs. We check both because:
-		// (i) log4j will write all CONSOLE appender logging to System.in only, and these
-		// may contain ERROR log entries corresponding to exceptions
-		// (ii) other exceptions in the AS should get written to System.err if not handled
-		// via log4j
-		
-		// NOTE: when we halt, an ERROR log message is written so we have to be careful
-		// 
-		if (ase.getOutput().indexOf(SERVER_HALTED_MESSAGE) > -1)
-			haltCalled = true ;
-		
-		if (!haltCalled 
-				&& (isCheckLogsForErrors() 
-						&& (ase.getOutput().indexOf("ERROR") > -1 || ase.getError().indexOf("Exception") > -1))) {
-			logsExceptionFree = false ;
-		}
-		
-		// kill the server before going on if not correctly started 
-		if (!serverStopped || !logsExceptionFree) {
-			// kill process and close streams
-			ase.joinShellCommand(1) ;
-			
-			// now throw exception 
-			if (!serverStopped)
-				throw new IOException("Server failed to stop: didn't find message in logs. See logs.") ;
-			else if (!logsExceptionFree) {
-				throw new IOException("Server failed to stop: ERROR statements found. See logs.") ;				
-			}
-		}
-		// if we reach here, the server stopped and no ERRORs were found
-	}
-	
-	private static void sleepForSeconds(int seconds) {
-		try {
-			Thread.sleep(seconds * 1000) ;
-		}
-		catch(InterruptedException e) {
-		}			
-	}
+      // initialise the script executors
+      se = new ShellScriptExecutor();
+      ase = new AsyncShellScriptExecutor();
 
-	/**
-	 * @return the checkLogsForErrors
-	 */
-	public boolean isCheckLogsForErrors() {
-		return checkLogsForErrors;
-	}
+      // initialise the log checkers (error checking here could be improved)
+      // these will be initialised to a single server instance, so we canb't change server instances
+      // part way through a test suite! :-(
+      String logDir = getLogDir();
+      errorLogChecker = new LogFileAssertionChecker(logDir + "/error.log");
+      outputLogChecker = new LogFileAssertionChecker(logDir + "/output.log");
+      bootLogChecker = new LogFileAssertionChecker(logDir + "/boot.log");
+      systemLogChecker = new LogFileAssertionChecker(logDir + "/system.log");
+      auditLogChecker = new LogFileAssertionChecker(logDir + "/audit.log");
 
-	/**
-	 * @param checkLogsForErrors the checkLogsForErrors to set
-	 */
-	public void setCheckLogsForErrors(boolean checkLogsForErrors) {
-		this.checkLogsForErrors = checkLogsForErrors;
-	}
+   }
 
-        /**
-         * Checks if JBossWS CXF stack is installed
-         *
-         * @return true if JBossWS CXF stack is installed
-         */
-        protected boolean isCXFInstalled() {
-            final File cxfClientFile = new File(getDistDir() + FS + "client" + FS + "jbossws-cxf-client.jar");
-            return cxfClientFile.exists();
-        }
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      // setup AsyncShellScriptExecutor to deploy shutdown.sar 
+      ase.setUseShutdown(true);
+      ase.setPathToShutdownSar(getDeployURL("shutdown.sar").getPath());
+      ase.setDeployDir(getDeployDir());
+   }
 
-        /**
-         * Checks if File contains specified text.
-         * 
-         * @param text 
-         * @param file
-         * @return true if file contains specified text
-         */
-        protected boolean fileContainsText(File file, String text) {
-            boolean containText = false;
-            try {
-                BufferedReader input = new BufferedReader(new FileReader(file));
-                try {
-                    String line = null;
-                    while ((line = input.readLine()) != null) {
-                        if (line.contains(text)) {
-                            containText = true;
-                            break;
-                        }
-                    }
-                } finally {
-                    input.close();
-                }
-            } catch (Exception ex) {
-                fail("Exception " + ex.getMessage());
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+   }
+
+   public ShellScriptExecutor getShellScriptExecutor()
+   {
+      return se;
+   }
+
+   public AsyncShellScriptExecutor getAsyncShellScriptExecutor()
+   {
+      return ase;
+   }
+
+   public LogFileAssertionChecker getOutputLogChecker()
+   {
+      return outputLogChecker;
+   }
+
+   public LogFileAssertionChecker getErrorLogChecker()
+   {
+      return errorLogChecker;
+   }
+
+   public LogFileAssertionChecker getBootLogChecker()
+   {
+      return bootLogChecker;
+   }
+
+   public LogFileAssertionChecker getSystemLogChecker()
+   {
+      return systemLogChecker;
+   }
+
+   public LogFileAssertionChecker getAuditLogChecker()
+   {
+      return auditLogChecker;
+   }
+
+   /* location helpers 
+    * 
+    * these really need to be improved to use JBossTestCase, but unfortunately
+    * JBossTestCase does not give us direct access to the deploy directory
+    * Here, i'm mimicking what they do
+    */
+   public String getDistDir()
+   {
+      String distDir = System.getProperty("jboss.dist");
+      if (distDir == null)
+         fail("Can't get the JBoss distribution directory");
+      return distDir;
+   }
+
+   /*
+    * how to get the server directory?
+    */
+   public String getServerConfig()
+   {
+      String serverConfig = System.getProperty("jbosstest.server.config");
+      if (serverConfig == null)
+      {
+         serverConfig = "default";
+      }
+      return serverConfig;
+   }
+
+   public String getBinDir()
+   {
+      return getDistDir() + "/bin";
+   }
+
+   public String getLogDir()
+   {
+      return getDistDir() + "/server/" + getServerConfig() + "/log";
+   }
+
+   public String getDeployDir()
+   {
+      return getDistDir() + "/server/" + getServerConfig() + "/deploy";
+   }
+
+   public boolean isWindows()
+   {
+      String osName = System.getProperty("os.name");
+      if (osName == null)
+         fail("Can't get the operating system name");
+      return (osName.indexOf("Windows") > -1) || (osName.indexOf("windows") > -1);
+   }
+
+   public boolean isLinux()
+   {
+      String osName = System.getProperty("os.name");
+      if (osName == null)
+         fail("Can't get the operating system name");
+      return (osName.indexOf("Linux") > -1) || (osName.indexOf("linux") > -1);
+   }
+
+   /* 
+    * method for constructing command lines for the shell executor, which
+    * in general takes three arguments
+    * String[] command, String[] envp, File workingDirectory
+    * 
+    * This command creates the first argument. 
+    * 
+    * Windows: three tokens need to be passed in String[] command
+    * cmd /c <entire command string to execute>
+    * cmd /c "twiddle.bat -s jnp://192.168.0.100 jsr77" 
+    *  
+    * UNIX: three tokens need to be passed in String[] command
+    * bash -c <entire command string to execute>
+    * bash -c "./twiddle.sh -s jnp://192.168.0.100 jsr77"
+    * 
+    * This arrangement may not be optimal ...
+    */
+   public String[] getShellCommand(String commandName, String options, String args)
+   {
+
+      String[] shellCommand = new String[3];
+      String commandLine = null;
+
+      if (commandName == null)
+         fail("No command name specified for shell to execute");
+
+      // set up the base command (platform specific)
+      if (isWindows())
+      {
+         shellCommand[0] = "cmd";
+         shellCommand[1] = "/c";
+         commandLine = commandName + ".bat";
+      }
+      else
+      {
+         shellCommand[0] = "bash";
+         shellCommand[1] = "-c";
+         commandLine = "./" + commandName + ".sh";
+      }
+      // add in the rest (platform-independent)
+      if (options != null)
+         commandLine += " " + options;
+      if (args != null)
+         commandLine += " " + args;
+
+      shellCommand[2] = commandLine;
+
+      return shellCommand;
+   }
+
+   /* assertion helpers */
+   public void assertOnOutputLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint)
+   {
+      if (!outputLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint))
+      {
+         // assertion does not hold
+         Assert.fail(failureMessage);
+      }
+   }
+
+   public void assertOnErrorLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint)
+   {
+      if (!errorLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint))
+      {
+         // assertion does not hold
+         Assert.fail(failureMessage);
+      }
+   }
+
+   public void assertOnBootLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint)
+   {
+      if (!bootLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint))
+      {
+         // assertion does not hold
+         Assert.fail(failureMessage);
+      }
+   }
+
+   public void assertOnSystemLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint)
+   {
+      if (!systemLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint))
+      {
+         // assertion does not hold
+         Assert.fail(failureMessage);
+      }
+   }
+
+   public void assertOnAuditLog(String string, String failureMessage, boolean useCheckpoint, boolean resetCheckpoint)
+   {
+      if (!auditLogChecker.isStringInLog(string, useCheckpoint, resetCheckpoint))
+      {
+         // assertion does not hold
+         Assert.fail(failureMessage);
+      }
+   }
+
+   /* check if there is a Tomcat connection to the server */
+   private boolean isServerStarted(String host) throws MalformedURLException
+   {
+      // URL to Tomcat 
+      URL url = new URL("http", host, 8080, "/");
+      try
+      {
+         log.trace("Trying to open the connection to host " + host);
+         URLConnection conn = url.openConnection();
+         log.trace("URLConnection class name=" + conn.getClass().getName());
+         if (conn instanceof HttpURLConnection)
+         {
+            HttpURLConnection http = (HttpURLConnection)conn;
+            int responseCode = http.getResponseCode();
+            log.trace("responseCode=" + responseCode);
+
+            if (responseCode > 0 && responseCode < 400)
+            {
+               return true;
             }
+         }
+      }
+      catch (IOException e)
+      {
+         return false;
+      }
+      return false;
+   }
 
-            return containText;
-        }
+   /* 
+   * Wait for the server (started by the AsyncShellExecutor) to start
+   * 
+   * @throws Exception 	if server does not start successfully
+   *  
+   * A successful server start means: 
+   * (i) we can reach Tomcat 
+   * (ii) no exceptions in error log
+   * (iii) no ERROR statements in the server log
+   * If the server does not start successfully, we call joinShellCommand with a 1 second timout.
+   * This will wait for one second and then attempt to shutdown both the server and the bash shell,
+   * before throwing an exception. 
+   *   
+   * NOTE: this is a hack, and assumes the process has been started using the AsynchShellExecutor   
+   */
+   protected void waitForServerStart(AsyncShellScriptExecutor ase, String host, int timeout) throws IOException
+   {
+      boolean serverStarted = false;
+      boolean logsExceptionFree = true;
+
+      int tries = 0;
+      while (tries++ < timeout)
+      {
+         if (!ase.isRunning())
+         {
+            throw new IOException("Server failed to start. See logs.");
+         }
+         // wait for a sec
+         sleepForSeconds(1);
+
+         if (isServerStarted(host))
+         {
+            serverStarted = true;
+            break;
+         }
+      }
+
+      // problem here is that if another server is started:
+      // (i) the preceeding code will indicate serverStarted=true
+      // (iI) the following code will get executed before the starting server has had a chance to start 
+      // (and before exceptions are written).
+      // This results in two servers being started, one incompletely.
+      // So wait here for 5 seconds to allow the logs to accumulate exceptions.
+      sleepForSeconds(5);
+
+      // check for startup errors in the server logs. We check both because:
+      // (i) log4j will write all CONSOLE appender logging to System.in only, and these
+      // may contain ERROR log entries corresponding to exceptions
+      // (ii) other exceptions in the AS should get written to System.err if not handled
+      // via log4j
+      if (isCheckLogsForErrors() && ((ase.getOutput().indexOf("ERROR") > -1) || ase.getError().indexOf("Exception") > -1))
+      {
+         logsExceptionFree = false;
+      }
+
+      // debugging
+      //System.out.println("Server started = " + serverStarted) ;
+      //System.out.println("logsExceptionFree = " + logsExceptionFree) ;
+      //System.out.println("output = " + ase.getOutput()) ;
+      //System.out.println("error = " + ase.getError()) ;
+
+      // kill the server before going on if not correctly started 
+      if (!serverStarted || !logsExceptionFree)
+      {
+         // kill process and close streams
+         ase.joinShellCommand(1);
+
+         // now throw exception 
+         if (!serverStarted)
+            throw new IOException("Server failed to start: couldn't connect to Tomcat. See logs.");
+         else if (!logsExceptionFree)
+         {
+            throw new IOException("Server failed to start: ERROR statements found. See logs.");
+         }
+      }
+      // if we reach here, the server started and no ERRORs were found
+   }
+
+   /* Wait for the server (started by the AsyncShellExecutor) to stop
+   * 
+   * @throws Exception 	if server does not stop successfully
+   *  
+   * A successful server start means: 
+   * (i) we see the "VM halted" message in the server log
+   * (ii) no ERROR statements in the server log
+   * If the server does not stop successfully, we call joinShellCommand with a 1 second timout.
+   * This will wait for one second and then attempt to shutdown both the server and the bash shell,
+   * before throwing an exception. 
+   */
+   protected void waitForServerStop(AsyncShellScriptExecutor ase, int timeout) throws IOException
+   {
+      boolean serverStopped = false;
+      boolean logsExceptionFree = true;
+      boolean haltCalled = false;
+
+      System.out.println("waitForServerStop: waiting " + timeout + " seconds");
+
+      int tries = 0;
+      while (tries++ < timeout)
+      {
+         if (!ase.isRunning())
+         {
+            // FIX-ME
+            throw new IOException("Server not running on shutdown. Something fishy");
+         }
+         // check if stopped by inspecting console log
+         String currentOutput = ase.getOutput();
+         if (currentOutput.indexOf(SERVER_STOPPED_MESSAGE) > -1 || currentOutput.indexOf(SERVER_HALTED_MESSAGE) > -1)
+         {
+            serverStopped = true;
+            break;
+         }
+
+         // wait for a sec
+         sleepForSeconds(1);
+      }
+
+      // Wait here for 5 seconds to allow the logs to accumulate.
+      sleepForSeconds(5);
+
+      // check for shutdown errors in the server logs. We check both because:
+      // (i) log4j will write all CONSOLE appender logging to System.in only, and these
+      // may contain ERROR log entries corresponding to exceptions
+      // (ii) other exceptions in the AS should get written to System.err if not handled
+      // via log4j
+
+      // NOTE: when we halt, an ERROR log message is written so we have to be careful
+      // 
+      if (ase.getOutput().indexOf(SERVER_HALTED_MESSAGE) > -1)
+         haltCalled = true;
+
+      if (!haltCalled && (isCheckLogsForErrors() && (ase.getOutput().indexOf("ERROR") > -1 || ase.getError().indexOf("Exception") > -1)))
+      {
+         logsExceptionFree = false;
+      }
+
+      // kill the server before going on if not correctly started 
+      if (!serverStopped || !logsExceptionFree)
+      {
+         // kill process and close streams
+         ase.joinShellCommand(1);
+
+         // now throw exception 
+         if (!serverStopped)
+            throw new IOException("Server failed to stop: didn't find message in logs. See logs.");
+         else if (!logsExceptionFree)
+         {
+            throw new IOException("Server failed to stop: ERROR statements found. See logs.");
+         }
+      }
+      // if we reach here, the server stopped and no ERRORs were found
+   }
+
+   private static void sleepForSeconds(int seconds)
+   {
+      try
+      {
+         Thread.sleep(seconds * 1000);
+      }
+      catch (InterruptedException e)
+      {
+      }
+   }
+
+   /**
+    * @return the checkLogsForErrors
+    */
+   public boolean isCheckLogsForErrors()
+   {
+      return checkLogsForErrors;
+   }
+
+   /**
+    * @param checkLogsForErrors the checkLogsForErrors to set
+    */
+   public void setCheckLogsForErrors(boolean checkLogsForErrors)
+   {
+      this.checkLogsForErrors = checkLogsForErrors;
+   }
+
+   /**
+    * Checks if JBossWS CXF stack is installed
+    *
+    * @return true if JBossWS CXF stack is installed
+    */
+   protected boolean isCXFInstalled()
+   {
+      final File cxfClientFile = new File(getDistDir() + FS + "client" + FS + "jbossws-cxf-client.jar");
+      return cxfClientFile.exists();
+   }
+
+   /**
+    * Checks if File contains specified text.
+    * 
+    * @param text 
+    * @param file
+    * @return true if file contains specified text
+    */
+   protected boolean fileContainsText(File file, String text)
+   {
+      boolean containText = false;
+      try
+      {
+         BufferedReader input = new BufferedReader(new FileReader(file));
+         try
+         {
+            String line = null;
+            while ((line = input.readLine()) != null)
+            {
+               if (line.contains(text))
+               {
+                  containText = true;
+                  break;
+               }
+            }
+         }
+         finally
+         {
+            input.close();
+         }
+      }
+      catch (Exception ex)
+      {
+         fail("Exception " + ex.getMessage());
+      }
+
+      return containText;
+   }
 }

Modified: branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/ShutdownTestCase.java
===================================================================
--- branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/ShutdownTestCase.java	2011-06-24 19:00:51 UTC (rev 111675)
+++ branches/JBPAPP_5_1/testsuite/src/main/org/jboss/test/scripts/test/ShutdownTestCase.java	2011-06-26 14:55:47 UTC (rev 111676)
@@ -51,9 +51,6 @@
  */
 public class ShutdownTestCase extends ScriptsTestBase
 {
-	private ObjectName SERVER_OBJ_NAME = null ;
-        public static final String SYSTEM_PROPERTY_JBOSSAS_STARTUP_TIMEOUT  = "jbosstest.jbossas.startup.timeout";
-        public static final String SYSTEM_PROPERTY_JBOSSAS_SHUTDOWN_TIMEOUT = "jbosstest.jbossas.shutdown.timeout";
         private static final int STOP_TIMEOUT = Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_JBOSSAS_SHUTDOWN_TIMEOUT, "30"));
         private static final int START_TIMEOUT = Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_JBOSSAS_STARTUP_TIMEOUT, "120"));
 		
@@ -65,13 +62,6 @@
    public ShutdownTestCase(String name)
    {
       super(name);     
-      
-      // init the server ON
-      try {
-    	  SERVER_OBJ_NAME = new ObjectName("jboss.system:type=Server") ;
-      }
-      catch(MalformedObjectNameException mfe) {
-      }      
    }
    
    



More information about the jboss-cvs-commits mailing list