diff --git a/dev/com.ibm.ws.config.schemagen/test/com/ibm/ws/config/schemagen/internal/SchemaGenTest.java b/dev/com.ibm.ws.config.schemagen/test/com/ibm/ws/config/schemagen/internal/SchemaGenTest.java
index 89f9f54f6b3..796f721df94 100644
--- a/dev/com.ibm.ws.config.schemagen/test/com/ibm/ws/config/schemagen/internal/SchemaGenTest.java
+++ b/dev/com.ibm.ws.config.schemagen/test/com/ibm/ws/config/schemagen/internal/SchemaGenTest.java
@@ -1,6 +1,6 @@
package com.ibm.ws.config.schemagen.internal;
/*******************************************************************************
- * Copyright (c) 2022 IBM Corporation and others.
+ * Copyright (c) 2022,2024 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
@@ -12,32 +12,30 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.File;
-import java.io.IOException;
import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
import org.junit.Test;
/**
- * Tests the schemaGen command that exists in the wlp/bin directory.
+ * Test wlp/bin/schemaGen.
+ *
+ *
- with no parameters
+ * - with -help
+ * - with an output file
+ *
*/
public class SchemaGenTest {
- public static final String WLP_BIN_DIR = "../build.image/wlp/bin";
- public static final String OUTPUT_FILE = "schemaGenOutput.xsd";
- public static final String HELP_OPTION = "-help";
- public static final String SCHEMAGEN_BAT = "./schemaGen.bat";
- public static final String SCHEMAGEN_LINUX_SCRIPT = "./schemaGen";
- public static final long TIMEOUT = 30_000_000_000L; // 30-second timeout
- public static final int MAX_OUTPUT_LINES = 500; // Reasonable limit to output to standard output by schemaGen
- public static final boolean IS_WINDOWS = isWindows();
-
public static boolean isWindows() {
String os = System.getProperty("os.name");
if (os.startsWith("Win")) {
@@ -46,194 +44,337 @@ public static boolean isWindows() {
return false;
}
+ public static final boolean IS_WINDOWS = isWindows();
+
+ // Make sure to give the process builder paths with the
+ // correct slash for the test environment!
+
+ // 'schemaGen' is a script in the server bin directory.
+ public static final String WLP_BIN_DIR_WIN = "..\\build.image\\wlp\\bin";
+ public static final String WLP_BIN_DIR_UNIX = "../build.image/wlp/bin";
+ public static final String WLP_BIN_DIR = (IS_WINDOWS ? WLP_BIN_DIR_WIN : WLP_BIN_DIR_UNIX);
+ public static File WLP_BIN = new File(WLP_BIN_DIR);
+
+ // The script has a windows format (batch script) and a unix format (shell script).
+ public static final String SCHEMAGEN_SCRIPT_WIN = ".\\schemaGen.bat";
+ public static final String SCHEMAGEN_SCRIPT_UNIX = "./schemaGen";
+ public static final String SCHEMAGEN_SCRIPT = (IS_WINDOWS ? SCHEMAGEN_SCRIPT_WIN : SCHEMAGEN_SCRIPT_UNIX);
+
+ public static final File SCHEMAGEN = new File(WLP_BIN, SCHEMAGEN_SCRIPT);
+
+ // The option used to request help from schemaGen.
+ public static final String HELP_OPTION = "-help";
+
+ // Output file used by the test.
+ public static final String OUTPUT_FILE = "schemaGenOutput.xsd";
+ public static final File OUTPUT = new File(WLP_BIN, OUTPUT_FILE);
+ public static final String OUTPUT_PATH = OUTPUT.getAbsolutePath();
+
+ // Parameters used to bound the script output and the script running time.
+ public static final int MAX_OUTPUT_LINES = 500; // Reasonable maximum count of output lines.
+ public static final long TIMEOUT_NS = 30_000_000_000L; // Reasonable maximum time to run (30s).
+
+ public static void displayEnv() {
+ System.out.println("Environment:");
+ System.out.println("OS [ os.name ] [ " + System.getProperty("os.name") + " ] isWindows [ " + IS_WINDOWS + " ]");
+ System.out.println("WLP Bin [ " + WLP_BIN_DIR + " ] [ " + WLP_BIN.getAbsolutePath() + " ] Exists [ " + WLP_BIN.exists() + " ]");
+ System.out.println(" Script [ " + SCHEMAGEN_SCRIPT + " ] [ " + SCHEMAGEN.getAbsolutePath() + " ] Exists [ " + SCHEMAGEN.exists() + " ]");
+ System.out.println(" Output [ " + OUTPUT_FILE + " ] [ " + OUTPUT_PATH + " ] Exists [ " + OUTPUT.exists() + " ]");
+ }
+
+ public static ProcessBuilder schemaGen() {
+ return schemaGen(null);
+ }
+
+ public static ProcessBuilder schemaGen(String option) {
+ ProcessBuilder pb;
+ if (IS_WINDOWS) {
+ if ( option == null ) {
+ pb = new ProcessBuilder("cmd", "/c", SCHEMAGEN_SCRIPT_WIN);
+ } else {
+ pb = new ProcessBuilder("cmd", "/c", SCHEMAGEN_SCRIPT_WIN, option);
+ }
+ } else {
+ if ( option == null ) {
+ pb = new ProcessBuilder(SCHEMAGEN_SCRIPT_UNIX);
+ } else {
+ pb = new ProcessBuilder(SCHEMAGEN_SCRIPT_UNIX, option);
+ }
+ }
+
+ pb.directory(WLP_BIN);
+
+ // Only one stream is being captured. If this redirect
+ // is not enabled, error output will not be captured.
+ pb.redirectErrorStream(true);
+
+ return pb;
+ }
+
/**
- * Test that when no parameters are passed, only basic usage info is displayed
- * @throws IOException
+ * Process line processor.
*/
- @Test
- public void testSchemaGenNoParms() throws IOException {
- System.out.println("==== testSchemaGenNoParms ====");
+ public static class ProcessActor {
+ public ProcessActor() {
+ this.numLines = 0;
+ }
+
+ /**
+ * Process a single line.
+ *
+ * Increment the count of lines.
+ *
+ * @param line A line which is to be processed.
+ *
+ * @return The count of lines. (Subclasses are expected
+ * to redefine the return value.)
+ */
+ int process(String line) {
+ numLines++;
+
+ return numLines;
+ }
- ProcessBuilder pb;
+ private int numLines;
+
+ /**
+ * Tell how many lines were processed.
+ *
+ * @return The count of line which were processed.
+ */
+ int getLines() {
+ return numLines;
+ }
+ }
+
+ /**
+ * Launch a process and apply a process actor to its lines.
+ *
+ * The process is bounded. No more than {@link #MAX_OUTPUT_LINES}
+ * will be accept, and the process will not be allowed to run longer
+ * than {@link #TIMEOUT_NS} nano-seconds. An except is thrown if
+ * either bound is exceeded.
+ *
+ * @param pBuild A process builder.
+ * @param pAct A actor to apply to the lines from the process.
+ * @return The return code from the process.
+ *
+ * @return The process return code.
+ *
+ * @throws Exception Thrown if the process did not launch, or if process
+ * lines could not be read, or if a process bound was exceeded. An
+ * exception is not thrown if the process generates a failure return code.
+ */
+ public static int apply(ProcessBuilder pBuild, ProcessActor pAct) throws Exception {
+ System.out.println("Running [ " + pBuild + " ]:");
+
+ long startTime = System.nanoTime();
+ int lines = 0;
+
Process p = null;
-
try {
-
- if (IS_WINDOWS) {
- pb = new ProcessBuilder("cmd", "/c", SCHEMAGEN_BAT);
- } else {
- pb = new ProcessBuilder(SCHEMAGEN_LINUX_SCRIPT);
- }
-
- File dir = new File(WLP_BIN_DIR);
- pb.directory(dir);
- p = pb.start();
+ p = pBuild.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
-
- boolean usageAppears = false;
- boolean encodingAppears = false;
-
- long startTime = System.nanoTime();
- int lineCounter = 0;
+ String line;
while ((line = br.readLine()) != null) {
+ lines++;
System.out.println(line);
-
- if (line.indexOf("Usage") != -1) {
- usageAppears = true;
- }
-
- if (line.indexOf("--encoding") != -1) {
- encodingAppears = true;
- }
- // Exit loop if we are getting hung
- if (lineCounter++ > MAX_OUTPUT_LINES) {
- System.out.println("schemaGen usage info exceeded [ " + MAX_OUTPUT_LINES + " ] lines");
- break;
- } else if (System.nanoTime() - startTime > TIMEOUT) {
- System.out.println("SchemaGen exceeded [ " + TIMEOUT + " ] ns when displaying usage Info");
- break;
+ if (lines > MAX_OUTPUT_LINES) {
+ throw new Exception("Exceeded maximum output [ " + MAX_OUTPUT_LINES + " ] (lines)");
+ } else if (System.nanoTime() - startTime > TIMEOUT_NS) {
+ throw new Exception("Exceeded maximum process time [ " + TIMEOUT_NS + " ] (ns)");
}
+
+ pAct.process(line);
}
-
- assertTrue("'Usage' should appear in command output", usageAppears);
- assertFalse("'--encoding' should NOT appear in command output when no arguments passed.", encodingAppears);
- System.out.println("PASSED");
-
+
} finally {
- if ( p!= null) {
- p.destroy();
+ if (p != null) {
+ if ( !p.waitFor(30, TimeUnit.SECONDS) ) {
+ p.destroyForcibly();
+ fail("Process ran longer than 30 seconds");
+ }
}
}
+
+ int rc = ((p == null) ? -1 : p.exitValue());
+ System.out.println("Return code [ " + rc + " ]");
+ return rc;
}
-
+
/**
- * Test that when -help parameter is passed that help and usage information is displayed.
- * @throws IOException
+ * A process actor used to detect specific values on lines.
+ */
+ public static class TagActor extends ProcessActor {
+ /**
+ * Create a tag actor for specified tags.
+ *
+ * See {@link #process(String)} for processing details.
+ *
+ * @param tags Values which are to be detected.
+ */
+ public TagActor(String... tags) {
+ super();
+
+ Map useHits = new HashMap<>(tags.length);
+
+ for ( String tag : tags ) {
+ useHits.put(tag, new int[] { 0 });
+ }
+
+ this.tagHits = useHits;
+ }
+
+ private final Map tagHits;
+
+ /**
+ * Tell how many hits were recorded for a specified
+ * tag. Answer zero if the tag is not being detected
+ * by this actor.
+ *
+ * @param tag A tag value.
+ *
+ * @return The number of hits which were recorded for the tag.
+ */
+ public int getHits(String tag) {
+ int[] hits = tagHits.get(tag);
+ return ((hits == null) ? 0 : hits[0]);
+ }
+
+ private int totalHits;
+
+ /**
+ * Answer the total number of hits for all tags.
+ *
+ * @return The total number of hits for all tags.
+ */
+ public int getHits() {
+ return totalHits;
+ }
+
+ /**
+ * Subclass extension: Record the tags which appear on the
+ * line. Each tag is detected at most once. Multiple tags
+ * will be detected on the same line.
+ *
+ * Add the number of new hits to the total number of hits.
+ *
+ * @param line A line which is to be processed.
+ *
+ * @return The number of keys which were detected.
+ */
+ @Override
+ public int process(String line) {
+ super.process(line); // Increment the number of lines
+
+ int hits = 0;
+ for ( String key : tagHits.keySet() ) {
+ if ( line.indexOf(key) != -1 ) {
+ (tagHits.get(key))[0]++;
+ hits++;
+ }
+ }
+
+ totalHits += hits;
+
+ return hits;
+ }
+ }
+
+ /**
+ * Test that when no parameters are passed, only basic usage info is displayed.
*/
@Test
- public void testSchemaGenHelp() throws IOException {
- System.out.println("==== testSchemaGenHelp ====");
+ public void testSchemaGenNoParms() throws Exception {
+ System.out.println("==== testSchemaGenNoParms ====");
+ displayEnv();
+
+ TagActor pActor = new TagActor("Usage", "--encoding");
+ int rc = apply( schemaGen(), pActor );
- ProcessBuilder pb;
- Process p = null;
- try {
+ assertEquals("Unexpected return code", 0, rc);
+
+ int usageCount = pActor.getHits("Usage");
+ int encodingCount = pActor.getHits("--encoding");
- if (IS_WINDOWS) {
- pb = new ProcessBuilder("cmd", "/c", SCHEMAGEN_BAT, HELP_OPTION);
- } else {
- pb = new ProcessBuilder(SCHEMAGEN_LINUX_SCRIPT, HELP_OPTION);
- }
+ assertTrue("'Usage' should appear", (usageCount > 0));
+ System.out.println("Detected 'Usage'");
- File dir = new File(WLP_BIN_DIR);
- pb.directory(dir);
- p = pb.start();
+ assertTrue("'--encoding' should NOT appear", (encodingCount == 0));
+ System.out.println("Did not detect detect '--encoding'");
- BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
-
- boolean usageAppears = false;
- boolean encodingAppears = false;
+ System.out.println("PASSED");
+ System.out.println();
+ }
- long startTime = System.nanoTime();
- int lineCounter = 0;
-
- while ((line = br.readLine()) != null) {
- System.out.println(line);
-
- if (line.indexOf("Usage") != -1) {
- usageAppears = true;
- }
-
- if (line.indexOf("--encoding") != -1) {
- encodingAppears = true;
- }
+ /**
+ * Test that when help parameters are passed, help info is displayed.
+ */
+ @Test
+ public void testSchemaGenHelp() throws Exception {
+ System.out.println("==== testSchemaGenHelp ====");
+ displayEnv();
+
+ TagActor pActor = new TagActor("Usage", "--encoding");
+ int rc = apply( schemaGen(HELP_OPTION), pActor );
- // Exit loop if we are getting hung
- if (lineCounter++ > MAX_OUTPUT_LINES) {
- System.out.println("schemaGen help exceeded [ " + MAX_OUTPUT_LINES + " ] lines");
- break;
- } else if (System.nanoTime() - startTime > TIMEOUT) {
- System.out.println("schemaGen exceeded [ " + TIMEOUT + " ] ns when displaying help");
- break;
- }
- }
-
- assertTrue("'Usage' should appear in command output", usageAppears);
- assertTrue("'--encoding' should appear in command output when " + HELP_OPTION + " is passed.", encodingAppears);
- System.out.println("PASSED");
-
- } finally {
- if ( p!= null) {
- p.destroy();
- }
- }
+ assertEquals("Unexpected return code", 0, rc);
+
+ int usageCount = pActor.getHits("Usage");
+ int encodingCount = pActor.getHits("--encoding");
+
+ assertTrue("'Usage' should appear", (usageCount > 0));
+ System.out.println("Detected 'Usage'");
+
+ assertTrue("'--encoding' should appear", (encodingCount > 0));
+ System.out.println("Detected '--encoding'");
+
+ System.out.println("PASSED");
+ System.out.println();
}
/**
* Test that when an output file is specified as parameter that the output file is created,
* and that CWWKG0109I "success" message is created.
- *
- * @throws IOException
*/
@Test
- public void testSchemaGenOutput() throws IOException {
+ public void testSchemaGenOutput() throws Exception {
System.out.println("==== testSchemaGenOutput ====");
+ displayEnv();
- ProcessBuilder pb;
- Process p = null;
- try {
- if (IS_WINDOWS) {
- pb = new ProcessBuilder("cmd", "/c", SCHEMAGEN_BAT, OUTPUT_FILE);
- } else {
- pb = new ProcessBuilder(SCHEMAGEN_LINUX_SCRIPT, OUTPUT_FILE);
- }
+ // Make sure there isn't stale output from another test.
+ OUTPUT.delete();
+ assertFalse("Output [" + OUTPUT_PATH + "] does not exist", OUTPUT.exists());
- File dir = new File(WLP_BIN_DIR);
- pb.directory(dir);
- p = pb.start();
-
- BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
-
- boolean successMsgAppears = false;
+ try {
+ TagActor pActor = new TagActor("CWWKG0109I");
- long startTime = System.nanoTime();
- int lineCounter = 0;
-
- while ((line = br.readLine()) != null) {
- System.out.println(line);
-
- if (line.indexOf("CWWKG0109I") != -1) {
- successMsgAppears = true;
- }
+ int rc = apply( schemaGen(OUTPUT_FILE), pActor);
- // Exit loop if we are getting hung
- if (lineCounter++ > MAX_OUTPUT_LINES) {
- System.out.println("schemaGen help exceeded [ " + MAX_OUTPUT_LINES + " ] lines");
- break;
- } else if (System.nanoTime() - startTime > TIMEOUT) {
- System.out.println("schemaGen exceeded [ " + TIMEOUT + " ] ns when displaying help");
- break;
- }
- }
-
- assertTrue("'CWWKG0109I' should appear in command output", successMsgAppears);
- assertTrue("Should only output 1 message in successful case.", lineCounter==1);
+ assertEquals("Unexpected return code", 0, rc);
+
+ int msgCount = pActor.getHits("CWWKG0109I");
+ int numLines = pActor.getLines();
+
+ assertTrue("'CWWKG0109I' should appear once", (msgCount == 1));
+ System.out.println("Detected 'CWWKG0109I'");
- // It should, however, generate the output file.
- File outputFile = new File(WLP_BIN_DIR + "/" + OUTPUT_FILE);
- assertTrue("File [" + outputFile.getName() + "] should exist.", outputFile.exists());
- outputFile.delete(); // clean up
- System.out.println("PASSED");
+ assertTrue("Should have exactly one output line", (numLines == 1));
+ assertTrue("Output [ " + OUTPUT_PATH + " ] exists", OUTPUT.exists());
+ System.out.println("Detected output [" + OUTPUT_PATH + " ]");
} finally {
- if ( p!= null) {
- p.destroy();
- }
+ // TODO: Would be nice to capture this output file in the build folder.
+
+ // Don't leave the output behind.
+ OUTPUT.delete();
+ assertFalse("Output [" + OUTPUT_PATH + "] does not exist", OUTPUT.exists());
}
+
+ System.out.println("PASSED");
+ System.out.println();
}
}