diff --git a/integ-archetype/pom.xml b/integ-archetype/pom.xml new file mode 100644 index 0000000..6eb1ca0 --- /dev/null +++ b/integ-archetype/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + automation-infra-tests-archetype + maven-archetype + + automation-infra-tests-archetype + + + + + org.apache.maven.archetype + archetype-packaging + 2.2 + + + + + + maven-archetype-plugin + 2.2 + + + + + + + il.co.topq.integframework + integ-parent + 1.0.5-SNAPSHOT + ../integ-parent + + diff --git a/integ-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/integ-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml new file mode 100644 index 0000000..bc9afd0 --- /dev/null +++ b/integ-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml @@ -0,0 +1,42 @@ + + + + + src/main/java + + **/*.java + + + + src/test/java + + **/*.java + + + + src/test/resources + + **/*.xml + **/*.properties + + + + src/test/resources + + **/*. + **/*.gitignore + + + + + + .gitignore + .springBeans + + + + diff --git a/integ-archetype/src/main/resources/archetype-resources/.gitignore b/integ-archetype/src/main/resources/archetype-resources/.gitignore new file mode 100644 index 0000000..c28e4fa --- /dev/null +++ b/integ-archetype/src/main/resources/archetype-resources/.gitignore @@ -0,0 +1,6 @@ +/target +/.settings +/.classpath +/.project +/automation-*-tests-*-SNAPSHOT-zipTests.zip +/.springBeans diff --git a/integ-archetype/src/main/resources/archetype-resources/pom.xml b/integ-archetype/src/main/resources/archetype-resources/pom.xml new file mode 100644 index 0000000..f19ca01 --- /dev/null +++ b/integ-archetype/src/main/resources/archetype-resources/pom.xml @@ -0,0 +1,253 @@ + +#set( $D = '$' ) + + + 4.0.0 + ${artifactId} + Automation for ${package} + ${groupId} + ${version} + jar + + + UTF-8 + 6.8.8 + 1.0.3-SNAPSHOT + true + 3.1.2.RELEASE + + + + + top-q + http://maven.top-q.co.il/content/groups/public + + + + + top-q + http://maven.top-q.co.il/content/groups/public + + + + + il.co.topq.integframework + integ-testng + ${integ.version} + + + com.google.inject + guice + 3.0 + test + + + il.co.topq.integframework + integ-db + ${integ.version} + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-test + ${spring.version} + + + com.google.guava + guava + 15.0 + + + org.apache.commons + commons-lang3 + 3.1 + + + il.co.topq.integframework + reportng + 1.1.41 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.16 + + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-source-plugin + 2.2 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.16 + + + src/test/resources/suites/${suite} + + -Xms256m -Xmx1536m + target/ + + + usedefaultlisteners + false + + + listener + org.uncommons.reportng.HTMLReporter + + + + + + + integration-test + verify + + + + + + maven-clean-plugin + 2.5 + + + auto-clean + clean + + clean + + + + + lib + + **/*.* + + + + test-output + + **/*.* + + + + target + + **/*.* + + + + ${project.basedir} + + ${project.artifactId}-${project.version}-zipTests.zip + + + + false + + + + + + maven-antrun-plugin + + + compile + + run + + + + To execute just run 'mvn clean integration-test -Dsuite=debug.xml -Dsut=sut.xml' + + + + + + + + + + debug + + true + + + + + + sut + + + + false + + runtests + + integration-test + + + maven-assembly-plugin + 2.3 + + + ${D}{project.testResources[0].directory}/assembly/zipTests.xml + + true + ${project.basedir} + + + + attach-tests + post-integration-test + + single + + + + + + + + + + + + junit + junit + 4.11 + + + + diff --git a/integ-archetype/src/main/resources/archetype-resources/src/main/java/automation/infra/Lab.java b/integ-archetype/src/main/resources/archetype-resources/src/main/java/automation/infra/Lab.java new file mode 100644 index 0000000..c74f180 --- /dev/null +++ b/integ-archetype/src/main/resources/archetype-resources/src/main/java/automation/infra/Lab.java @@ -0,0 +1,8 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +package ${package}.automation.infra; + +public class Lab { + +} diff --git a/integ-archetype/src/main/resources/archetype-resources/src/test/java/automation_infra_tests/BaseTestCase.java b/integ-archetype/src/main/resources/archetype-resources/src/test/java/automation_infra_tests/BaseTestCase.java new file mode 100644 index 0000000..586e82d --- /dev/null +++ b/integ-archetype/src/main/resources/archetype-resources/src/test/java/automation_infra_tests/BaseTestCase.java @@ -0,0 +1,30 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +package ${package}.automation_infra_tests; + +import il.co.topq.integframework.reporting.Reporter; + +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; + +import com.google.common.collect.Sets; +import ${package}.automation.infra.Lab; + +@ContextConfiguration(locations = "classpath:META-INF/context.xml") +public class BaseTestCase extends AbstractTestNGSpringContextTests { + + protected final static Set packagesToFilter = Sets.newHashSet("sun.reflect", "java.lang.reflect", "org.testng", + "org.apache.maven", "org.codehaus.plexus.classworlds.launcher", "org.springframework.test.context.testng"); + @Autowired + protected Lab lab; + + static { + Reporter.filterPackagesOnThrowables(packagesToFilter); + + } + +} diff --git a/integ-archetype/src/main/resources/archetype-resources/src/test/resources/META-INF/context.xml b/integ-archetype/src/main/resources/archetype-resources/src/test/resources/META-INF/context.xml new file mode 100644 index 0000000..0784f89 --- /dev/null +++ b/integ-archetype/src/main/resources/archetype-resources/src/test/resources/META-INF/context.xml @@ -0,0 +1,17 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + + + + + + + + diff --git a/integ-archetype/src/main/resources/archetype-resources/src/test/resources/assembly/zipTests.xml b/integ-archetype/src/main/resources/archetype-resources/src/test/resources/assembly/zipTests.xml new file mode 100644 index 0000000..0383533 --- /dev/null +++ b/integ-archetype/src/main/resources/archetype-resources/src/test/resources/assembly/zipTests.xml @@ -0,0 +1,24 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + zipTests + / + + zip + + + + ${symbol_dollar}{project.build.directory}/failsafe-reports/html/ + /html + + + ${symbol_dollar}{project.build.directory}/failsafe-reports/junitreports/ + /junit + + + + \ No newline at end of file diff --git a/integ-archetype/src/main/resources/archetype-resources/src/test/resources/suites/debug.xml b/integ-archetype/src/main/resources/archetype-resources/src/test/resources/suites/debug.xml new file mode 100644 index 0000000..c0df4ef --- /dev/null +++ b/integ-archetype/src/main/resources/archetype-resources/src/test/resources/suites/debug.xml @@ -0,0 +1,9 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( +$symbol_escape = '\' ) + + + + + \ No newline at end of file diff --git a/integ-archetype/src/main/resources/archetype-resources/src/test/resources/sut.xml b/integ-archetype/src/main/resources/archetype-resources/src/test/resources/sut.xml new file mode 100644 index 0000000..f515bcb --- /dev/null +++ b/integ-archetype/src/main/resources/archetype-resources/src/test/resources/sut.xml @@ -0,0 +1,19 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + + + + + + + \ No newline at end of file diff --git a/integ-archetype/src/test/resources/projects/basic/archetype.properties b/integ-archetype/src/test/resources/projects/basic/archetype.properties new file mode 100644 index 0000000..237499d --- /dev/null +++ b/integ-archetype/src/test/resources/projects/basic/archetype.properties @@ -0,0 +1,5 @@ +#Tue Aug 12 15:38:48 IDT 2014 +package=it.pkg +version=0.1-SNAPSHOT +groupId=archetype.it +artifactId=basic diff --git a/integ-archetype/src/test/resources/projects/basic/goal.txt b/integ-archetype/src/test/resources/projects/basic/goal.txt new file mode 100644 index 0000000..e69de29 diff --git a/integ-bdd/pom.xml b/integ-bdd/pom.xml index f5bd72f..bb152f5 100644 --- a/integ-bdd/pom.xml +++ b/integ-bdd/pom.xml @@ -1,17 +1,18 @@ + 4.0.0 integ-bdd il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT ../integ-parent il.co.topq.integframework integ-testng - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT - \ No newline at end of file + diff --git a/integ-cli/.gitignore b/integ-cli/.gitignore new file mode 100644 index 0000000..1dd3331 --- /dev/null +++ b/integ-cli/.gitignore @@ -0,0 +1,2 @@ +/target/ +/target/ diff --git a/integ-cli/pom.xml b/integ-cli/pom.xml index 3f7ab9a..1be5a9f 100644 --- a/integ-cli/pom.xml +++ b/integ-cli/pom.xml @@ -1,37 +1,38 @@ + - 4.0.0 - integ-cli - - + 4.0.0 + integ-cli + + org.apache.commons commons-exec 1.1 - + ch.ethz.ganymed ganymed-ssh2 - LATEST + 262 javax.comm comm - LATEST + 1.0 il.co.topq.integframework integ-testng - ${project.version} + 1.0.5-SNAPSHOT il.co.topq.integframework integ-support - ${project.version} + 1.0.5-SNAPSHOT - - - il.co.topq.integframework - integ-parent - 1.0.1-SNAPSHOT - ../integ-parent - - \ No newline at end of file + + + il.co.topq.integframework + integ-parent + 1.0.5-SNAPSHOT + ../integ-parent + + diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/BasicCliConnection.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/BasicCliConnection.java index 482a3d9..51824e5 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/BasicCliConnection.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/BasicCliConnection.java @@ -6,6 +6,7 @@ import il.co.topq.integframework.cli.terminal.Prompt; import java.util.ArrayList; +import java.util.List; /** * This CLI connection enable you to describe the basic cli connection @@ -24,12 +25,14 @@ public class BasicCliConnection extends CliConnectionImpl { protected String commandEndPrompts; protected String loginPrompt; protected String passwordPrompt; + @Override public Position[] getPositions() { return null; } + @Override public Prompt[] getPrompts() { - ArrayList prompts = new ArrayList(); + List prompts = new ArrayList<>(); if(getCommandEndPrompts() != null){ String[] pString = getCommandEndPrompts().split(","); for(String ps: pString){ diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliCommand.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliCommand.java index 4b845aa..c72d4d0 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliCommand.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliCommand.java @@ -10,6 +10,7 @@ import il.co.topq.integframework.assertion.TextNotFoundAssertion; import il.co.topq.integframework.cli.terminal.Prompt; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -144,7 +145,7 @@ public class CliCommand { Prompt resultPrompt; - Exception thrown; + IOException thrown; boolean failed = false; @@ -168,7 +169,7 @@ public class CliCommand { boolean suppressEcho = false; - List> analyzers = new ArrayList> (); + List> analyzers = new ArrayList<> (); Prompt[] prompts = null; @@ -396,6 +397,9 @@ public List getMusts() { * @param musts */ public void addMusts(List musts) { + if (this.musts == null) { + this.musts = new ArrayList<>(); + } this.musts.addAll(musts); for (String must: musts){ addAnalyzers(new FindTextAssertion(must)); @@ -446,7 +450,7 @@ public void addResult(String result) { * * @return thrown */ - public Exception getThrown() { + public IOException getThrown() { return thrown; } @@ -455,7 +459,7 @@ public Exception getThrown() { * if it was thrown. * @param thrown */ - public void setThrown(Exception thrown) { + public void setThrown(IOException thrown) { this.thrown = thrown; } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliConnection.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliConnection.java index d435ad8..95529cf 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliConnection.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliConnection.java @@ -8,6 +8,7 @@ import il.co.topq.integframework.cli.terminal.InOutInputStream; import il.co.topq.integframework.cli.terminal.Prompt; +import java.io.IOException; import java.io.PrintStream; /** @@ -34,8 +35,9 @@ public interface CliConnection { * run a given command object * * @param command CliCommand object + * @throws InterruptedException */ - public void command(CliCommand command); + public void command(CliCommand command) throws InterruptedException; /** * @@ -59,7 +61,7 @@ public interface CliConnection { * establish a connection with the CLI * @throws Exception */ - public void connect() throws Exception; + public void connect() throws IOException; public Position[] getPositions(); @@ -209,8 +211,9 @@ public interface CliConnection { * 3. Performs report operation & throws an exception
* in case of an error. (and ignore error flags were not raised)
* 4. Performs Analysis if one or more analyzers are defined (and ignore error flags were not raised) + * @throws InterruptedException */ - public void handleCliCommand( String title,CliCommand command) throws Exception; + public void handleCliCommand( String title,CliCommand command) throws IOException, InterruptedException; /** * add possible Prompts to the CLI diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliConnectionImpl.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliConnectionImpl.java index b20941f..37ca1ce 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliConnectionImpl.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CliConnectionImpl.java @@ -5,34 +5,21 @@ */ package il.co.topq.integframework.cli.conn; +import static java.util.concurrent.TimeUnit.SECONDS; import il.co.topq.integframework.AbstractModuleImpl; import il.co.topq.integframework.assertion.AbstractAssertionLogic; import il.co.topq.integframework.assertion.IAssertionLogic; -import il.co.topq.integframework.cli.terminal.BufferInputStream; -import il.co.topq.integframework.cli.terminal.Cli; -import il.co.topq.integframework.cli.terminal.InOutInputStream; -import il.co.topq.integframework.cli.terminal.Prompt; -import il.co.topq.integframework.cli.terminal.RS232; -import il.co.topq.integframework.cli.terminal.SSH; -import il.co.topq.integframework.cli.terminal.SSHWithRSA; -import il.co.topq.integframework.cli.terminal.Telnet; -import il.co.topq.integframework.cli.terminal.Terminal; -import il.co.topq.integframework.cli.terminal.VT100FilterInputStream; +import il.co.topq.integframework.cli.terminal.*; import il.co.topq.integframework.reporting.Reporter; import il.co.topq.integframework.reporting.Reporter.Color; +import il.co.topq.integframework.utils.StringUtils; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Properties; +import java.io.*; +import java.util.*; import java.util.regex.Pattern; +import org.testng.ITestResult; + /** * This is a default implementation for CliConnection your implementation should * extend this one. @@ -40,30 +27,26 @@ * @author guy.arieli * */ -public abstract class CliConnectionImpl -extends AbstractModuleImpl -implements CliConnection { - - public static enum EnumConnectionType { - COM("com"), - RS232("rs232"), - TELNET("telnet"), - SSH("ssh"), - SSH_RSA("ssh-rsa"); +public abstract class CliConnectionImpl extends AbstractModuleImpl implements CliConnection { + + public static enum EnumConnectionType { + COM("com"), RS232("rs232"), TELNET("telnet"), SSH("ssh"), SSH_RSA("ssh-rsa"); EnumConnectionType(String value) { this.value = value; } + private String value; + public String value() { return value; } } - protected Cli cli; + protected volatile Cli cli; protected Terminal terminal; - protected HashMap positions = new HashMap(); + protected HashMap positions = new HashMap<>(); protected int port = 23; @@ -83,7 +66,7 @@ public String value() { protected String protocol = EnumConnectionType.TELNET.value(); - protected long lastCommandTime = 0; + protected volatile long lastCommandTime = 0; // set to true in windows XP telnet server protected boolean dump = false; @@ -99,14 +82,14 @@ public String value() { protected boolean dummy = false; protected boolean forceIgnoreAnyErrors = false; - + // used for win2K server protected boolean vt100Filter = false; - + // will generate enter upon login (like in rs232) protected boolean leadingEnter = false; - private ArrayList prompts = new ArrayList(); + private List prompts = new ArrayList<>(); // number of times the client will try to connect to the remote cli // agent. @@ -126,7 +109,7 @@ public String value() { * this is the command enter string, can be set from the sut */ protected String enterStr = null; - + /** * The key delay when sending keys to the terminal. Only relevant when * delayTyping is set to true @@ -136,15 +119,16 @@ public String value() { /** * Whether to ignore backspace characters or not */ - private boolean ignoreBackSpace = false; - - private String charSet = "ASCII"; + private boolean ignoreBackSpace = false; + + private String charSet = "ASCII"; /** * SSH2 private key -RSA (ppk or pem file) */ private File privateKey; + @Override public boolean isConnectOnInit() { return connectOnInit; } @@ -153,18 +137,22 @@ public void setConnectOnInit(boolean connectOnInit) { this.connectOnInit = connectOnInit; } + @Override public String getPassword() { return password; } + @Override public void setPassword(String password) { this.password = password; } + @Override public String getUser() { return user; } + @Override public void setUser(String user) { this.user = user; } @@ -178,25 +166,27 @@ public CliConnectionImpl() { } } + @Override public String getHost() { return host; } + @Override public void setHost(String host) { this.host = host; } - protected void navigate(CliCommand command, boolean toPosition) throws Exception { + protected void navigate(CliCommand command, boolean toPosition) throws IOException, InterruptedException { if (command.getPosition() == null) { return; } Position currentPosition = positions.get(command.getPosition()); if (currentPosition == null) { - throw new Exception("Fail to find position: " + command.getPosition()); + throw new IOException("Fail to find position: " + command.getPosition()); } - + String[] commands = toPosition ? currentPosition.getEnters() : currentPosition.getExits(); - + if (commands != null) { for (int ccommandIndex = 0; ccommandIndex < commands.length; ccommandIndex++) { String cmd = changeCommand(commands[ccommandIndex], command.getProperties()); @@ -208,76 +198,133 @@ protected void navigate(CliCommand command, boolean toPosition) throws Exception } } - public void navigateToPosition(CliCommand command) throws Exception { + @Override + public void navigateToPosition(CliCommand command) throws IOException, InterruptedException { navigate(command, true); } - public void returnFromPosition(CliCommand command) throws Exception { + @Override + public void returnFromPosition(CliCommand command) throws IOException, InterruptedException { navigate(command, false); } - - public void init() throws Exception { - - if (isConnectOnInit()) { - connect(); + private boolean useThreads = false; + private Thread initializer = null; + + @Override + public void init() throws IOException { + final List ex = new ArrayList<>(); + Runnable r = new Runnable() { + @Override + public void run() { + if (isConnectOnInit()) { + try { + connect(); + } catch (IOException e) { + ex.add(e); + } + } + } + }; + if (useThreads) { + initializer = new Thread(null, r, "Connector for " + getName()); + initializer.setDaemon(true); + initializer.start(); + } else { + initializer = Thread.currentThread(); + r.run(); + if (ex.size() == 1) { + throw ex.get(0); + } } + } - public void connect() throws Exception { - activateIdleMonitor(); + @Override + public void connect() throws IOException { connectRetries = connectRetries <= 0 ? 1 : connectRetries; - - for (int retriesCounter = 0; retriesCounter < connectRetries; retriesCounter++) { - try { - //TODO: Reporter.getCurrentTestResult().setStatus(ITestResult.SUCCESS); - internalConnect(); - break; - } catch (Exception e) { - Reporter.log("Failed connecting " + getHost() + ". Attempt " + (retriesCounter + 1) + ". " + e.getMessage()); - try { - disconnect(); - } catch (Throwable t) { + if (!Thread.currentThread().equals(initializer)) { + int countdownLatch = 10; + synchronized (initializer) { + while (initializer.isAlive() && (!isConnected())) { + try { + SECONDS.timedJoin(initializer, 5); + if (0 < --countdownLatch) { + initializer.interrupt(); + } + } catch (InterruptedException e) { + continue; + } } - if (retriesCounter == connectRetries - 1) { - throw e; + } + } + synchronized (this) { + if (!isConnected()) { + for (int retriesCounter = 0; retriesCounter < connectRetries; retriesCounter++) { + try { + internalConnect(); + activateIdleMonitor(); + break; + } catch (IOException e) { + Reporter.log("Connecting to " + getHost() + " Failed. (Attempt #" + (retriesCounter + 1) + ")" + + e.getMessage()); + try { + disconnect(); + } catch (Throwable t) { + Reporter.log("Disconnecting to " + getHost() + " Failed."); + } + if (retriesCounter == connectRetries - 1) { + throw new IOException("Connecting to " + getHost() + " Failed." ,e); + } + } catch (InterruptedException e) { + throw new IOException("Connection to " + getHost() + " interrupted", e); + } finally { + Reporter.getCurrentTestResult().setStatus(isConnected()?ITestResult.SUCCESS:ITestResult.FAILURE); + } } - } finally { - //TODO: Reporter.getCurrentTestResult().setStatus(ITestResult.FAILURE); } } } - private void internalConnect() throws Exception { + private synchronized void internalConnect() throws IOException, InterruptedException { if (host == null) { - throw new Exception("Default connection ip/comm is not configured"); + throw new IllegalArgumentException("Default connection ip/comm is not configured"); } - Reporter.log("Init cli, host: " + host); if (dummy) { + Reporter.log("Connecting to a dummy CLI ...",true); + this.cli = new Cli(new DummyTerminal()); + this.cli.setDontWaitForPrompts(true); + this.cli.connect(); + this.connected = cli.isConnected(); return; } + Reporter.log("Connecting to [" + host + "] ...",true); // Terminal t; boolean isRs232 = false; - - boolean isRsa = false; - if (host.toLowerCase().startsWith(EnumConnectionType.COM.value()) || protocol.toLowerCase().equals(EnumConnectionType.RS232.value())) { + boolean isRsa = false; + if (host.toLowerCase().startsWith(EnumConnectionType.COM.value()) + || protocol.toLowerCase().equals(EnumConnectionType.RS232.value())) { // syntax for serial connection found isRs232 = true; String[] params = host.split("\\;"); if (params.length < 5) { - throw new Exception("Unable to extract parameters from host: " + host); + throw new IllegalArgumentException("Unable to extract parameters from host: " + host); + } + try { + terminal = new RS232(params[0], Integer.parseInt(params[1]), Integer.parseInt(params[2]), Integer.parseInt(params[3]), + Integer.parseInt(params[4])); + } + catch (NumberFormatException exception){ + throw new IllegalArgumentException(exception); } - terminal = new RS232(params[0], Integer.parseInt(params[1]), Integer.parseInt(params[2]), Integer.parseInt(params[3]), Integer - .parseInt(params[4])); } else if (protocol.toLowerCase().equals(EnumConnectionType.SSH.value())) { terminal = new SSH(host, user, password); - } else if (protocol.toLowerCase().equals( - EnumConnectionType.SSH_RSA.value())) { + } else if (protocol.toLowerCase().equals(EnumConnectionType.SSH_RSA.value())) { terminal = new SSHWithRSA(host, user, password, privateKey); prompts.add(new Prompt("$", false, true)); prompts.add(new Prompt("]$", false, true)); - + isRsa = true; } else { terminal = new Telnet(host, port, useTelnetInputStream); @@ -285,14 +332,17 @@ private void internalConnect() throws Exception { ((Telnet) terminal).setVtType(null); } } - + terminal.setCharSet(getCharSet()); - + terminal.setIgnoreBackSpace(isIgnoreBackSpace()); - + if (delayedTyping) { terminal.setKeyTypingDelay(keyTypingDelay); } + if (terminal instanceof SSH && getPort() != 23) { + ((SSH) terminal).setPort(getPort()); + } cli = new Cli(terminal); if (enterStr != null) { setEnterStr(enterStr); @@ -303,7 +353,7 @@ private void internalConnect() throws Exception { terminal.addFilter(buffer); buffer.startThread(); } - + if (vt100Filter) { terminal.addFilter(new VT100FilterInputStream()); } @@ -313,9 +363,9 @@ private void internalConnect() throws Exception { } if (isRs232 || leadingEnter) { cli.command(""); - }else if (isRsa){ + } else if (isRsa) { cli.login(); - }else { + } else { cli.login(60000, delayedTyping); } connected = true; @@ -325,12 +375,17 @@ private void internalConnect() throws Exception { public void close() { if (idleMonitor != null) { idleMonitor.setStop(); - idleMonitor.interrupt(); + try { + idleMonitor.join(); + } catch (InterruptedException e) { + Reporter.log("Waiting for idle monitor failed", e); + } } disconnect(); isClosed = true; } + @Override public void disconnect() { connected = false; if (cli != null) { @@ -345,13 +400,18 @@ public void setPosition(Position position) { positions.put(position.getName(), position); } - public void handleCliCommand(String title, CliCommand command) throws Exception { + @Override + public void handleCliCommand(String title, CliCommand command) throws IOException, InterruptedException { if (command.isClone()) { - CliConnectionImpl cloned = (CliConnectionImpl) this.clone(); + CliConnectionImpl cloned; + try { + cloned = (CliConnectionImpl) this.clone(); + } catch (CloneNotSupportedException e) { + throw new IllegalStateException(e); + } try { handleCliCommand(cloned, title, command); setActual(cloned.getActual()); - //setTestAgainstObject(cloned.getTestAgainstObject()); } finally { cloned.close(); } @@ -372,54 +432,69 @@ public void handleCliCommand(String title, CliCommand command) throws Exception * 4. Performs Analysis if one or more analyzers are defined
* (and ignore error flags were not raised) */ - public static void handleCliCommand(CliConnectionImpl cli, String title, CliCommand command) throws Exception { - if (!cli.isConnectOnInit() && !cli.isConnected()) { - cli.connect(); - } - cli.command(command); - - cli.setActual(command.getResult()); - if (command.isFailed() && (!command.isIgnoreErrors()) && (!cli.isForceIgnoreAnyErrors())) { - Reporter.log(title + ", " + command.getFailCause(), command.getResult(),Color.RED); - Exception e = command.getThrown(); - if (e != null) { - throw e; + public static void handleCliCommand(CliConnectionImpl cli, String title, CliCommand command) throws InterruptedException, IOException { + synchronized (cli) { + if (!cli.isConnectOnInit() || cli.useThreads) { + if (!cli.isConnected()) { + cli.connect(); + } } - throw new Exception("Cli command failed"); - } + try { + if (!command.isSilent()) { + Reporter.startLogToggle(title); + } + cli.command(command); + + cli.setActual(command.getResult()); + if (command.isFailed() && (!command.isIgnoreErrors()) && (!cli.isForceIgnoreAnyErrors())) { + Reporter.log(command.getFailCause(), command.getResult(), Color.RED); + IOException e = command.getThrown(); + if (e != null) { + throw e; + } + throw new IOException("Cli command failed"); + } - if (!command.isSilent()) { - Reporter.log(title, command.getResult()); - } - if (command.isIgnoreErrors() || (cli.isForceIgnoreAnyErrors())) { - ; - } else { - List> analyzers = command.getAnalyzers(); - if (analyzers != null) { - for (IAssertionLogic analyzer : analyzers) { - analyzer.setActual(cli.getActual(String.class)); - analyzer.doAssertion(); - if (analyzer instanceof AbstractAssertionLogic ){ - AbstractAssertionLogic stringAssertionLogic = (AbstractAssertionLogic) analyzer; - if (!(command.isSilent() && stringAssertionLogic.isStatus())){ - Reporter.log(stringAssertionLogic.getTitle(), stringAssertionLogic.getMessage(), stringAssertionLogic.isStatus()); + if (!command.isSilent()) { + Reporter.log(command.getResult()); + } + if (command.isIgnoreErrors() || (cli.isForceIgnoreAnyErrors())) { + ; + } else { + List> analyzers = command.getAnalyzers(); + if (analyzers != null) { + for (IAssertionLogic analyzer : analyzers) { + analyzer.setActual(cli.getActual(String.class)); + analyzer.doAssertion(); + if (analyzer instanceof AbstractAssertionLogic) { + AbstractAssertionLogic stringAssertionLogic = (AbstractAssertionLogic) analyzer; + if (!(command.isSilent() && stringAssertionLogic.isStatus())) { + Reporter.log(stringAssertionLogic.getTitle(), stringAssertionLogic.getMessage(), + stringAssertionLogic.isStatus()); + } + } } } } + cli.setForceIgnoreAnyErrors(false); + } finally { + if (!command.isSilent()) { + Reporter.stopLogToggle(); + } } } - cli.setForceIgnoreAnyErrors(false); } - public synchronized void command(CliCommand command) { - + @Override + public synchronized void command(CliCommand command) throws InterruptedException { + lastCommandTime = System.currentTimeMillis(); cli.setDontWaitForPrompts(command.isDontWaitForPrompts()); try { navigateToPosition(command); - } catch (Exception e1) { + } catch (IOException e1) { command.setFailCause("Navigate to position failed"); - command.setThrown(e1); + command.setThrown(new IOException("Navigate to position failed",e1)); command.setFailed(true); return; } @@ -436,12 +511,14 @@ public synchronized void command(CliCommand command) { try { if (command.getPrompts() != null) { - cli.command(cmd, command.getTimeout(), command.isAddEnter(), command.isDelayTyping(), null, command.getPrompts()); + cli.command(cmd, command.getTimeout(), command.isAddEnter(), command.isDelayTyping(), null, + command.getPrompts()); } else { - cli.command(cmd, command.getTimeout(), command.isAddEnter(), command.isDelayTyping(), command.getPromptString()); + cli.command(cmd, command.getTimeout(), command.isAddEnter(), command.isDelayTyping(), + command.getPromptString()); } - } catch (Exception e) { + } catch (IOException e) { command.addResult(cli.getResult()); command.setFailCause("cli command failed: " + cmd); command.setThrown(e); @@ -459,16 +536,14 @@ public synchronized void command(CliCommand command) { command.addResult(lastResult); command.setResultPrompt(cli.getResultPrompt()); - setActual(command.getResult()); + setActual(command.getResult()); // If log file name (+path) defined at the sut, CLI results will // be save also to this file // Add to the sut file under the tag if (cliLogFile != null) { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(cliLogFile, true)); + try (BufferedWriter out = new BufferedWriter(new FileWriter(cliLogFile, true))) { out.write(lastResult); - out.close(); } catch (IOException e) { command.setFailCause("Writing CLI buffer to file " + cliLogFile + " failed"); command.setThrown(e); @@ -485,20 +560,13 @@ public synchronized void command(CliCommand command) { } } - try { - Thread.sleep(command.getDelayInRetries()); - } catch (InterruptedException e2) { - command.setFailCause("Sleep failed"); - command.setThrown(e2); - command.setFailed(true); - return; - } + Thread.sleep(command.getDelayInRetries()); retries++; } } try { returnFromPosition(command); - } catch (Exception e) { + } catch (IOException e) { command.setFailCause("Navigate from position failed"); command.setThrown(e); command.setFailed(true); @@ -512,6 +580,9 @@ public boolean isDummy() { public void setDummy(boolean dummy) { this.dummy = dummy; + if (dummy){ + setScrollEndTimeout(0); + } } public boolean isUseTelnetInputStream() { @@ -542,11 +613,13 @@ protected String changeCommand(String command, Properties p) { return command; } + @Override public void waitForNotifications(String[] notifications, long timeout) throws Exception { cli.command("", timeout, false, false, notifications); cli.command("", timeout, false, false, (String) null); } + @Override public String getCliBuffer() { if (useBuffer) { return buffer.getBuffer(); @@ -554,6 +627,7 @@ public String getCliBuffer() { return null; } + @Override public void cleanCliBuffer() { if (useBuffer) { buffer.clean(); @@ -568,6 +642,7 @@ public void setUseBuffer(boolean useBuffer) { this.useBuffer = useBuffer; } + @Override public boolean isConnected() { if (cli == null) { return false; @@ -579,38 +654,74 @@ public void setConnected(boolean connected) { this.connected = connected; } + @Override public String getProtocol() { return protocol; } + @Override public void setProtocol(String protocol) { this.protocol = protocol; } + @Override public long getLastCommandTime() { return lastCommandTime; } + @Override public long getMaxIdleTime() { return maxIdleTime; } + @Override public void setMaxIdleTime(long maxIdleTime) { this.maxIdleTime = maxIdleTime; } - - /** - * activates the IdleMonitor (if it wasn't activated allready) - * don't use if idleMonitor was allready active - */ - public void activateIdleMonitor() { - if (maxIdleTime > 0 ) { - lastCommandTime = System.currentTimeMillis(); - idleMonitor = new IdleMonitor(this,maxIdleTime); + + /** + * activates the IdleMonitor (if it wasn't activated already) don't use if + * idleMonitor was already active + */ + public synchronized void activateIdleMonitor() { + if (maxIdleTime > 0 && (idleMonitor == null || !idleMonitor.isAlive())) { + idleMonitor = new IdleMonitor(this, maxIdleTime); idleMonitor.start(); + initializer = idleMonitor; + } + } + + /** + * deactivates the IdleMonitor + */ + public synchronized void deactivateIdleMonitor() { + + if (idleMonitor != null) { + synchronized (idleMonitor) { + try { + System.out.println("stopping " + idleMonitor.getName()); + idleMonitor.setStop(); + idleMonitor.join(); + } catch (InterruptedException e) { + Reporter.log("Deactivating idle monitor failed", e); + } finally { + idleMonitor = null; + } + } } - } - + } + + public synchronized boolean idleMonitorIsActive() { + if (idleMonitor == null) { + return false; + } + if (!idleMonitor.isAlive()) { + deactivateIdleMonitor(); + return false; + } + return true; + } + public String getCliLogFile() { return cliLogFile; } @@ -627,6 +738,7 @@ public void setDump(boolean dump) { this.dump = dump; } + @Override public void setGraceful(boolean graceful) { this.graceful = graceful; if (cli != null) { @@ -634,14 +746,17 @@ public void setGraceful(boolean graceful) { } } + @Override public boolean isGraceful() { return graceful; } + @Override public void setPrintStream(PrintStream printStream) { cli.setPrintStream(printStream); } + @Override public Prompt getResultPrompt() { if (cli == null) { return null; @@ -649,21 +764,25 @@ public Prompt getResultPrompt() { return cli.getResultPrompt(); } + @Override public String read() throws Exception { return cli.read(); } + @Override public void reconnect() { - + try { cli.reconnect(); } catch (Exception e) { } } + @Override public Object clone() throws CloneNotSupportedException { try { - CliConnectionImpl newImpl = (CliConnectionImpl) getClass().getClassLoader().loadClass(getClass().getName()).newInstance(); + CliConnectionImpl newImpl = (CliConnectionImpl) getClass().getClassLoader().loadClass(getClass().getName()) + .newInstance(); newImpl.port = port; newImpl.user = user; newImpl.password = password; @@ -698,7 +817,7 @@ public void setForceIgnoreAnyErrors(boolean forceIgnoreAnyErrors) { } private Prompt[] getAllPrompts() { - ArrayList allPrompts = new ArrayList(); + ArrayList allPrompts = new ArrayList<>(); allPrompts.addAll(prompts); Prompt[] pr = getPrompts(); for (Prompt p : pr) { @@ -707,6 +826,7 @@ private Prompt[] getAllPrompts() { return allPrompts.toArray(new Prompt[0]); } + @Override public void addPrompts(Prompt[] promptsToAdd) { if (promptsToAdd == null) { return; @@ -719,8 +839,9 @@ public void addPrompts(Prompt[] promptsToAdd) { } } + @Override public void setPrompts(Prompt[] promptsToAdd) { - prompts = new ArrayList(); + prompts = new ArrayList<>(); if (terminal != null) { terminal.removePrompts(); } @@ -735,6 +856,7 @@ public void setPrompts(Prompt[] promptsToAdd) { } } + @Override public void setEnterStr(String enterStr) { // replace \r string with the '\r' char (the same for \n) enterStr = enterStr.replaceAll(Pattern.quote("\\r"), "\r"); @@ -746,18 +868,22 @@ public void setEnterStr(String enterStr) { } } + @Override public void setScrollEndTimeout(long timeout) { terminal.setScrollEndTimeout(timeout); } + @Override public void addFilter(InOutInputStream stream) { terminal.addFilter(stream); } + @Override public void sendString(String toSend, boolean delayedTyping) throws Exception { terminal.sendString(toSend, delayedTyping); } + @Override public String getEnterStr() { if (cli == null) { return enterStr; @@ -765,10 +891,12 @@ public String getEnterStr() { return cli.getEnterStr(); } + @Override public int getConnectRetries() { return connectRetries; } + @Override public void setConnectRetries(int connectRetries) { this.connectRetries = connectRetries; } @@ -781,14 +909,17 @@ public void setVt100Filter(boolean vt100Filter) { this.vt100Filter = vt100Filter; } + @Override public boolean isLeadingEnter() { return leadingEnter; } + @Override public void setLeadingEnter(boolean leadingEnter) { this.leadingEnter = leadingEnter; } - + + @Override public long getKeyTypingDelay() { if (terminal != null) { return terminal.getKeyTypingDelay(); @@ -796,9 +927,10 @@ public long getKeyTypingDelay() { return keyTypingDelay; } + @Override public void setKeyTypingDelay(long keyTypingDelay) { this.keyTypingDelay = keyTypingDelay; - if (terminal !=null) { + if (terminal != null) { terminal.setKeyTypingDelay(keyTypingDelay); } } @@ -811,7 +943,7 @@ public void setKeyTypingDelay(long keyTypingDelay) { public boolean isIgnoreBackSpace() { return ignoreBackSpace; } - + /** * Whether to ignore backspace characters or not * @@ -819,7 +951,7 @@ public boolean isIgnoreBackSpace() { */ public void setIgnoreBackSpace(boolean ignoreBackSpace) { this.ignoreBackSpace = ignoreBackSpace; - + if (terminal != null) { terminal.setIgnoreBackSpace(ignoreBackSpace); } @@ -841,4 +973,18 @@ public void setPrivateKey(File privateKey) { this.privateKey = privateKey; } + public void setUseThreads(boolean useThreads) { + this.useThreads = useThreads; + } + + @Override + public String getName() { + return StringUtils.either(super.getName()).or(getHost()); + } + + @Override + public String toString() { + return getName(); + } + } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CmdConnection.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CmdConnection.java index 824d93e..4eefd73 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CmdConnection.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/CmdConnection.java @@ -7,6 +7,7 @@ import il.co.topq.integframework.cli.terminal.Cmd; import il.co.topq.integframework.cli.terminal.Prompt; +import java.io.IOException; import java.util.ArrayList; /** @@ -35,11 +36,13 @@ public CmdConnection(String dir){ this(); } - public void init() throws Exception { + @Override + public void init() throws IOException { super.init(); } - public void connect() throws Exception { + @Override + public void connect() throws IOException { terminal = new Cmd(dir); terminal.setPrompts(internalGetPrompts()); cli = new Cli(terminal); @@ -47,7 +50,8 @@ public void connect() throws Exception { ((Cmd)terminal).setCloseOutputOnSend(isCloneOnEveryOperation()); } - public void handleCliCommand(String title,CliCommand command) throws Exception{ + @Override + public void handleCliCommand(String title,CliCommand command) throws IOException, InterruptedException{ boolean commandClone = command.isClone(); boolean isCloneOneveryOp = isCloneOnEveryOperation(); @@ -64,16 +68,18 @@ public void handleCliCommand(String title,CliCommand command) throws Exception{ setCloneOnEveryOperation(isCloneOneveryOp); } } + @Override public Position[] getPositions() { return null; } + @Override public Prompt[] getPrompts() { return internalGetPrompts().toArray(new Prompt[0]); } private ArrayList internalGetPrompts() { - ArrayList prompts = new ArrayList(); + ArrayList prompts = new ArrayList<>(); Prompt p = new Prompt(); p = new Prompt(); p.setPrompt(">"); @@ -98,6 +104,7 @@ public void setCloneOnEveryOperation(boolean resetOnEveryOperation) { this.cloneOnEveryOperation = resetOnEveryOperation; } + @Override public Object clone() throws CloneNotSupportedException{ CmdConnection connection = (CmdConnection)super.clone(); connection.connectOnInit = false; diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/IdleMonitor.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/IdleMonitor.java index 0b3c965..1bc370d 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/IdleMonitor.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/IdleMonitor.java @@ -3,65 +3,100 @@ */ package il.co.topq.integframework.cli.conn; -import il.co.topq.integframework.reporting.Reporter; +import static il.co.topq.integframework.reporting.Reporter.log; +import static il.co.topq.integframework.utils.StringUtils.isEmpty; +import static java.lang.System.currentTimeMillis; +import static java.lang.System.out; +import static org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM; +import il.co.topq.integframework.cli.process.CliCommandExecution; + +import java.io.PrintStream; /** - * Monitors the allowed idle time of a machine. - * (Many devices forces log out in case of the maximum idle time has passed) - * In order to activate this monitor the maxIdleTime tag(in miliSeconds) should be added to the SUT file. - * under conn / cli + * Monitors the allowed idle time of a machine. (Many devices forces log out in + * case of the maximum idle time has passed) In order to activate this monitor + * the maxIdleTime tag(in miliSeconds) should be added to the SUT file. under + * conn / cli * * Note that the actual keep alive 'Enter' will be done at idleTime * 0.9 - * + * */ public class IdleMonitor extends Thread { CliConnectionImpl cli; + final PrintStream silentPrintStream = new PrintStream(NULL_OUTPUT_STREAM); long timeout; - boolean stop = false; - - /** - * @param cli CliConnection - * @param timeout (miliSeconds) the maximum idleTime + + /** + * @param cli + * CliConnection + * @param timeout + * (miliSeconds) the maximum idleTime */ - public IdleMonitor(CliConnectionImpl cli, long timeout){ + public IdleMonitor(CliConnectionImpl cli, long timeout) { + super("Idle monitor for " + cli.getName()); + setDaemon(true); this.cli = cli; this.timeout = timeout; } - - public void run(){ - System.out.println("Idle monitor was started"); - while(!stop){ + + @Override + public void run() { + out.println(this.getName() + " started"); + String position = null; + while (!isInterrupted()) { + try { + synchronized (cli) { + if (!cli.terminal.isConnected()) { + cli.connect(); + } + } + } catch (Exception e) { + continue; + } long lastCommandTime = cli.getLastCommandTime(); - if(lastCommandTime == 0){ + if (lastCommandTime == 0) { try { - Thread.sleep(timeout/2); + sleep(timeout / 2); } catch (InterruptedException e) { - return; + setStop(); } continue; } - if(System.currentTimeMillis() - lastCommandTime > (timeout * 0.9)){ - CliCommand cmd = new CliCommand(); - cmd.setCommands(new String[]{""}); - cli.command(cmd); - if(cmd.isFailed()){ - Reporter.log(" idle monitor failed" , null ,false); - } else { - Reporter.log(" idle monitor keepalive success"); + if (currentTimeMillis() - lastCommandTime > (timeout * 0.9)) { + synchronized (cli) { + CliCommand cmd = new CliCommand(""); + if (!isEmpty(position)) { + cmd.setPosition(position); + } + PrintStream stream = cli.terminal.getPrintStream(); + cli.setPrintStream(silentPrintStream); + try { + cli.command(cmd); + } catch (InterruptedException e) { + setStop(); + } + cli.setPrintStream(stream); + position = cmd.getPosition(); + if (cmd.isFailed()) { + log(getName() + " keepalive failed", null, false); + } else { + // System.out.println(getName() + " keepalive success"); + } } } else { try { - long toSleep = (long)(timeout * 0.9) - (System.currentTimeMillis() - lastCommandTime); - if(toSleep > 0){ - Thread.sleep(toSleep); + long toSleep = (long) (timeout * 0.9) - (currentTimeMillis() - lastCommandTime); + if (toSleep > 0) { + sleep(toSleep); } } catch (InterruptedException e) { - return; + setStop(); } } } } - public void setStop(){ - stop = true; + + public void setStop() { + this.interrupt(); } } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/LinuxDefaultCliConnection.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/LinuxDefaultCliConnection.java index 92805b4..620fad4 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/LinuxDefaultCliConnection.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/LinuxDefaultCliConnection.java @@ -13,9 +13,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; +import java.util.*; /** * Default CliConnection for a Cli connection to a linux machine. Protocol is @@ -40,22 +38,24 @@ public LinuxDefaultCliConnection(String host, String user, String password) { } @Override - public void init() throws Exception { + public void init() throws IOException { super.init(); } @Override - public void connect() throws Exception { + public void connect() throws IOException { super.connect(); terminal.addFilter(new VT100FilterInputStream()); } + @Override public Position[] getPositions() { return null; } + @Override public Prompt[] getPrompts() { - ArrayList prompts = new ArrayList(); + List prompts = new ArrayList<>(); Prompt p = new Prompt(); p.setCommandEnd(true); p.setPrompt("$ "); @@ -87,15 +87,16 @@ public Prompt[] getPrompts() { * @return * @throws IOException */ - public InputStream get(String remoteFile) throws IOException { - if (terminal instanceof SSH) { - SSH ssh = (SSH) terminal; - return ssh.get(remoteFile); - } + public synchronized InputStream get(String remoteFile) throws IOException { + + if (terminal instanceof SSH) { + SSH ssh = (SSH) terminal; + return ssh.get(remoteFile); + } return null; } - public void get(String remoteFile, File dst) throws IOException { + public synchronized void get(String remoteFile, File dst) throws IOException { byte buf[] = new byte[10240]; InputStream in = get(remoteFile); OutputStream out = new FileOutputStream(dst); @@ -125,7 +126,7 @@ public void get(String remoteFile, File dst) throws IOException { * @throws IOException * when */ - public OutputStream put(String remoteDir, String remoteFile, String mode, long length) throws IOException { + public synchronized OutputStream put(String remoteDir, String remoteFile, String mode, long length) throws IOException { if (terminal instanceof SSH) { SSH ssh = (SSH) terminal; return ssh.put(remoteFile, length, remoteDir, mode); @@ -141,9 +142,37 @@ public Iterator fileList(String directory) throws Exception { } public boolean isProccessRunning(String name) throws Exception { - CliCommandExecution execution = new CliCommandExecution(this, "ps -C '" + name + "' -o pid= |wc -l"); + CliCommandExecution execution = new CliCommandExecution(this, processInstancesCounterCommand(name)); execution.withTitle("check if process " + name + " is running").execute(); - return "1".equals(execution.getResult()); + return !"0".equals(execution.getResult()); + } + + public boolean isProccessNotRunning(String name) throws Exception { + CliCommandExecution execution = new CliCommandExecution(this, processInstancesCounterCommand(name)); + execution.withTitle("check if process " + name + " is not running").execute(); + return "0".equals(execution.getResult()); } + public static String processInstancesCounterCommand(String cmd) { + return "ps -C '" + cmd + "' -o pid= |wc -l"; + } + + public Date getRemoteMachineDate() throws IOException { + CliCommandExecution execution = new CliCommandExecution(this, "date +%s"); + // seconds since epoch + execution.execute(); + return new Date(Long.parseLong(execution.getResult() + "000")); + } + + public Calendar getRemoteMachineCalendar() throws Exception { + Calendar calendar = new GregorianCalendar(getRemoteMachineTimeZone()); + calendar.setTimeInMillis(getRemoteMachineDate().getTime()); + return calendar; + } + + public TimeZone getRemoteMachineTimeZone() throws Exception { + CliCommandExecution execution = new CliCommandExecution(this, "date +%Z"); + execution.execute(); + return TimeZone.getTimeZone(execution.getResult()); + } } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/RootLinuxCliConnection.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/RootLinuxCliConnection.java index e1d82f4..56d1488 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/RootLinuxCliConnection.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/RootLinuxCliConnection.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import il.co.topq.integframework.cli.terminal.Prompt; import il.co.topq.integframework.utils.StringUtils; @@ -12,7 +13,7 @@ public class RootLinuxCliConnection extends LinuxDefaultCliConnection { @Override public Prompt[] getPrompts() { - ArrayList prompts = new ArrayList(); + List prompts = new ArrayList<>(); prompts.addAll(Arrays.asList(super.getPrompts())); Prompt rootPrompt = new Prompt(); diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/WindowsDefaultCliConnection.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/WindowsDefaultCliConnection.java index 7448541..4c3f844 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/WindowsDefaultCliConnection.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/conn/WindowsDefaultCliConnection.java @@ -6,7 +6,9 @@ import il.co.topq.integframework.cli.terminal.Prompt; import il.co.topq.integframework.cli.terminal.VT100FilterInputStream; +import java.io.IOException; import java.util.ArrayList; +import java.util.List; /** * Default CliConnection for a Cli connection to a windows xm/vista machine. @@ -31,22 +33,26 @@ public WindowsDefaultCliConnection(String host,String user,String password){ setHost(host); } - public void init() throws Exception { + @Override + public void init() throws IOException { super.init(); } - public void connect() throws Exception { + @Override + public void connect() throws IOException { super.connect(); terminal.addFilter(new VT100FilterInputStream()); } + @Override public Position[] getPositions() { // TODO Auto-generated method stub return null; } + @Override public Prompt[] getPrompts() { - ArrayList prompts = new ArrayList(); + List prompts = new ArrayList<>(); Prompt p = new Prompt(); p.setPrompt("login:"); p.setStringToSend(getUser()); diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/process/CliCommandExecution.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/process/CliCommandExecution.java index 6f9cf96..d468a17 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/process/CliCommandExecution.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/process/CliCommandExecution.java @@ -1,11 +1,15 @@ package il.co.topq.integframework.cli.process; +import static org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM; import il.co.topq.integframework.AbstractModule; -import il.co.topq.integframework.assertion.IAssertionLogic; +import il.co.topq.integframework.Named; +import il.co.topq.integframework.assertion.*; import il.co.topq.integframework.cli.conn.CliCommand; import il.co.topq.integframework.cli.conn.CliConnection; import il.co.topq.integframework.utils.StringUtils; +import java.io.IOException; +import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -13,12 +17,15 @@ public class CliCommandExecution { private final CliConnection cliConnection; - private long timeout = -1; + // setting default timeout to 1 minute. + private long timeout = TimeUnit.MINUTES.toMillis(1); private String title = ""; - private String cmd = ""; + protected String cmd = ""; private List musts, errors; protected String result; + private boolean silently = false; protected final List> assrtions; + public final PrintStream silentPrintStream = new PrintStream(NULL_OUTPUT_STREAM); public CliCommandExecution(CliConnection cliConnection) { this(cliConnection, ""); @@ -27,7 +34,7 @@ public CliCommandExecution(CliConnection cliConnection) { public CliCommandExecution(CliConnection cliConnection, String command) { this.cliConnection = cliConnection; this.cmd = command; - assrtions = new ArrayList>(); + assrtions = new ArrayList<>(); } public CliCommandExecution withTimeout(long timeout) { @@ -46,43 +53,101 @@ public CliCommandExecution withTitle(String title) { } public CliCommandExecution mustHaveResponse(String... strings) { - if (musts == null || musts.isEmpty()) { - musts = new ArrayList(strings.length); + if (musts == null) { + musts = new ArrayList<>(strings.length); } musts.addAll(Arrays.asList(strings)); return this; } - public void execute(String command) throws Exception { + public void execute(String command) throws IOException { this.cmd = command; execute(); } - public void execute() throws Exception { + /** + * execute the command on the {@link CliConnection}. you can gain the result + * by {@link #getResult()}. if any error string was provided in + * {@link #error(String...)}, the result will be the error string + * instance
+ * note that the actual result will be set to the {@link CliConnection}'s + * actual, if it is an {@link AbstractModule}, accessible by + * {@link AbstractModule#getActual()}. the value could contain either the + * first or last prompt. + * + * @throws Exception + */ + public void execute() throws IOException { if (StringUtils.isEmpty(cmd)) { throw new NullPointerException("command is not set"); } CliCommand cliCommand = new CliCommand(cmd); - if (musts != null && !musts.isEmpty()) { - cliCommand.addMusts(musts); - } - if (errors != null && !errors.isEmpty()) { - for (String error : errors) { - cliCommand.addErrors(error); + if (!(cliConnection instanceof AbstractModule)) { + if (musts != null && !musts.isEmpty()) { + cliCommand.addMusts(musts); + } + if (errors != null && !errors.isEmpty()) { + for (String error : errors) { + cliCommand.addErrors(error); + } } } cliCommand.setTimeout(timeout); - this.cliConnection.handleCliCommand(title, cliCommand); - - if (cliConnection instanceof AbstractModule) { - String result = ((AbstractModule) cliConnection).getActual(String.class); - String commandLine = cmd + this.cliConnection.getEnterStr(); - result = StringUtils.getFirstSubStringSuffix(result, commandLine, true); - if (result.contains(this.cliConnection.getEnterStr())) { - result = StringUtils.getPrefix(result, this.cliConnection.getEnterStr()); + cliCommand.setSilent(silently); + synchronized (cliConnection) { + if (!cliConnection.isConnected() /*&& !cliConnection.isConnectOnInit()*/){ + cliConnection.connect(); + } + if (silently) { + cliConnection.setPrintStream(silentPrintStream); + } + try { + this.cliConnection.handleCliCommand(title, cliCommand); + } catch (IOException | InterruptedException e) { + String on = cliConnection.toString(); + if (cliConnection instanceof Named){ + on = ((Named) cliConnection).getName(); + } + throw new IOException("Execution of " + title + " failed on " + on, e); } - setResult(result.trim()); + + if (cliConnection instanceof AbstractModule) { + AbstractModule cliModule = (AbstractModule) cliConnection; + String result = cliModule.getActual(String.class); + String commandLine = cmd + this.cliConnection.getEnterStr(); + result = StringUtils.getFirstSubStringSuffix(result, commandLine, true); + if (result.contains(this.cliConnection.getEnterStr())) { + result = StringUtils.getPrefix(result, this.cliConnection.getEnterStr()); + } + setResult(result.trim()); + cliModule.setActual(this.result); + if (musts != null && !musts.isEmpty()) { + for (String must : musts) { + Assert.assertLogic(cliModule.getActual(String.class), new FindTextAssertion(must)); + } + } + if (errors != null && !errors.isEmpty()) { + for (final String error : errors) { + Assert.assertLogic(cliModule.getActual(String.class), new TextNotFoundAssertion(error), new setResultOnError(error)); + } + } + } + } + } + + private final class setResultOnError extends DefaultAssertionListener { + + private final String error; + + public setResultOnError(String error) { + this.error = error; + } + + @Override + public void assertionFailed(String actual, AbstractAssertionLogic logic) { + setResult(error); + super.assertionFailed(actual, logic); } } @@ -115,10 +180,15 @@ protected void setResult(String result) { // } public CliCommandExecution error(String... errors) { - if (this.errors == null || this.errors.isEmpty()) { - this.errors = new ArrayList(errors.length); + if (this.errors == null) { + this.errors = new ArrayList<>(errors.length); } this.errors.addAll(Arrays.asList(errors)); return this; } + + public CliCommandExecution silently() { + this.silently = true; + return this; + } } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/process/CommandLineModule.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/process/CommandLineModule.java index f040dda..b63e2f5 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/process/CommandLineModule.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/process/CommandLineModule.java @@ -7,7 +7,7 @@ public class CommandLineModule extends AbstractModuleImpl { protected CliConnectionImpl cliConnectionImpl; - public CliCommandExecution execute() { + public CliCommandExecution executer() { return new CliCommandExecution(cliConnectionImpl); } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/process/LinuxCommandLineModule.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/process/LinuxCommandLineModule.java new file mode 100644 index 0000000..328ad42 --- /dev/null +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/process/LinuxCommandLineModule.java @@ -0,0 +1,14 @@ +package il.co.topq.integframework.cli.process; + +import il.co.topq.integframework.cli.conn.LinuxDefaultCliConnection; + +public class LinuxCommandLineModule extends CommandLineModule { + protected LinuxDefaultCliConnection linux; + + @Override + public void init() throws Exception { + super.init(); + linux = (LinuxDefaultCliConnection) cliConnectionImpl; + // casting exception is good!!! misuse of this class will cause it!! + } +} diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/process/ProcessHandler.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/process/ProcessHandler.java index f49c370..5fb98f0 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/process/ProcessHandler.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/process/ProcessHandler.java @@ -129,7 +129,7 @@ public String[] getOut() { class CollectingLogOutputStream extends LogOutputStream { private static final int QUEUE_SIZE = 1000; - private final Queue lines = new LinkedList(); + private final Queue lines = new LinkedList<>(); @Override protected void processLine(String line, int level) { diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliConnectionWait.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliConnectionWait.java index 7fa7a4d..f01af78 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliConnectionWait.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliConnectionWait.java @@ -14,6 +14,7 @@ public CliConnectionWait(CliConnection input) { super(input); withTimeout(DEFAULT_TIMEOUT_IN_MINUTES, TimeUnit.MINUTES); pollingEvery(DEFAULT_POLLING_INTERVAL_IN_MILLISECONDS, TimeUnit.MILLISECONDS); + ignoring(AssertionError.class); } } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionExpectedCondition.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionExpectedCondition.java new file mode 100644 index 0000000..81857b9 --- /dev/null +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionExpectedCondition.java @@ -0,0 +1,9 @@ +package il.co.topq.integframework.cli.support; + +import il.co.topq.integframework.cli.process.CliCommandExecution; + +import com.google.common.base.Function; + +public interface CliExecutionExpectedCondition extends Function { + +} diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionExpectedConditions.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionExpectedConditions.java new file mode 100644 index 0000000..4c2bb4d --- /dev/null +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionExpectedConditions.java @@ -0,0 +1,157 @@ +package il.co.topq.integframework.cli.support; + +import il.co.topq.integframework.assertion.*; +import il.co.topq.integframework.cli.process.CliCommandExecution; +import il.co.topq.integframework.utils.Parser; + +import java.text.ParseException; + +public abstract class CliExecutionExpectedConditions { + final Object __; + + private CliExecutionExpectedConditions() { + __ = null; // util class, do not init! + } + + public static CliExecutionExpectedCondition executionResult() { + return new CliExecutionExpectedCondition() { + + @Override + public String apply(CliCommandExecution execution) { + try { + execution.execute(); + return execution.getResult(); + } catch (Exception e) { + return null; + } + } + }; + } + + public static CliExecutionExpectedCondition executionLogicHappens(final AbstractAssertionLogic logic) { + return new CliExecutionExpectedCondition() { + @Override + public String apply(CliCommandExecution execution) { + try { + FailSafeAssertionListener failSafeListener = new FailSafeAssertionListener<>(); + execution.execute(); + Assert.assertLogic(execution.getResult(), logic, failSafeListener); + if (failSafeListener.getSuppressedThrowables().hasNext()) { + Assert.fail("execution failed", failSafeListener.getSuppressedThrowables().next()); + } + return execution.getResult(); + } catch (Exception e) { + Assert.fail(toString(), e); + } + return null; + } + + @Override + public String toString() { + return logic.getTitle(); + } + }; + + } + + public static CliExecutionExpectedCondition executionResultContains(final String expectedResponse) { + return executionLogicHappens(new FindTextAssertion(expectedResponse) { + @Override + public String toString() { + return "execution response must contain " + expectedResponse; + } + }); + } + + public static CliExecutionExpectedCondition executionResultIs(final String expectedResponse) { + return executionLogicHappens(new ComparableAssertion(expectedResponse, CompareMethod.EQUALS) { + @Override + public String toString() { + return "execution response must be " + expectedResponse; + } + }); + } + + /** + * this condition will return the return value of cli execution, after + * parsed by a parser and analyzed by the assertion logic + * + * @param T + * the type of the value the execution response. e.g. execution + * of wc -l file returns java.lang.Long + * meaning the amount of lines in the file + * @param parser + * an object that gets the string from the execution and + * translates it to a T.
+ * the parser should be able to crop the result. + * @param logic + * the logic and sometimes the expected value to examine. + * @return the parsed value + */ + public static CliExecutionExpectedCondition executionLogicHappens(final AbstractAssertionLogic logic, + final Parser parser) { + return new CliExecutionExpectedCondition() { + + @Override + public T apply(CliCommandExecution execution) { + try { + FailSafeAssertionListener failSafeListener = new FailSafeAssertionListener<>(); + execution.execute(); + T actual = parser.parse(execution.getResult()); + Assert.assertLogic(actual, logic, failSafeListener); + if (failSafeListener.getSuppressedThrowables().hasNext()) { + Throwable cause = failSafeListener.getSuppressedThrowables().next(); + if (cause instanceof AssertionError) { + if (cause.getCause() != null) { + throw new RuntimeException(cause.getCause()); + } + return null; + } + throw new RuntimeException(cause); + } + return actual; + } catch (ParseException pe) { + return null; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String toString() { + return logic.toString(); + } + }; + + } + + /** + * execute the given execution and parse the result. + * + * @param parser + * for parsing the result. the parser may return null. + * @return the result + */ + public static CliExecutionExpectedCondition executionResult(final Parser parser) { + return new CliExecutionExpectedCondition() { + + @Override + public T apply(CliCommandExecution execution) { + try { + execution.execute(); + T actual = parser.parse(execution.getResult()); + if (actual == null) { + throw new NullPointerException(execution.toString() + " result parsed to null\n" + execution.getResult()); + } + return actual; + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + throw new RuntimeException(e); + } + } + }; + + } +} diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionWait.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionWait.java new file mode 100644 index 0000000..7483779 --- /dev/null +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/CliExecutionWait.java @@ -0,0 +1,25 @@ +package il.co.topq.integframework.cli.support; + +import il.co.topq.integframework.cli.conn.CliConnection; +import il.co.topq.integframework.cli.process.CliCommandExecution; +import il.co.topq.integframework.support.FluentWait; + +import java.util.concurrent.TimeUnit; + +public class CliExecutionWait extends FluentWait { + + private static final int DEFAULT_POLLING_INTERVAL_IN_MILLISECONDS = 500; + private static final int DEFAULT_TIMEOUT_IN_MINUTES = 2; + + public CliExecutionWait(CliCommandExecution execution) { + super(execution); + withTimeout(DEFAULT_TIMEOUT_IN_MINUTES, TimeUnit.MINUTES); + pollingEvery(DEFAULT_POLLING_INTERVAL_IN_MILLISECONDS, TimeUnit.MILLISECONDS); + ignoring(AssertionError.class); + } + + public CliExecutionWait(CliConnection cliConnection, String command) { + this(new CliCommandExecution(cliConnection, command)); + } + +} diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxCliExpectedConditions.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxCliExpectedConditions.java index a9c4f5e..a889cca 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxCliExpectedConditions.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxCliExpectedConditions.java @@ -1,7 +1,12 @@ package il.co.topq.integframework.cli.support; +import static il.co.topq.integframework.cli.support.CliExecutionExpectedConditions.executionLogicHappens; +import static il.co.topq.integframework.utils.Parsers.intParser; +import il.co.topq.integframework.assertion.ComparableAssertion; +import il.co.topq.integframework.assertion.CompareMethod; import il.co.topq.integframework.cli.conn.CliConnection; import il.co.topq.integframework.cli.conn.LinuxDefaultCliConnection; +import il.co.topq.integframework.cli.process.CliCommandExecution; import java.io.FileNotFoundException; import java.io.IOException; @@ -18,6 +23,13 @@ private LinuxCliExpectedConditions() { _ = 1; } + /** + * an expectation of existence of a file. + * + * @param path + * the file path to find + * @return true if the file exists + */ public static Predicate fileExists(final String path) { return new Predicate() { @@ -42,12 +54,19 @@ public boolean apply(LinuxDefaultCliConnection cliConnection) { }; } + /** + * expectation for a file to be readable. + * + * @param path + * the file path to find + * @return an input stream to the file + */ public static CliExpectedCondition fileIsReadable(final String path) { return new CliExpectedCondition() { @Override public String toString() { - return "the file in " + path.toString() + " to be openable"; + return "the file in " + path.toString() + " to be readable"; }; public InputStream apply(LinuxDefaultCliConnection cliConnection) { @@ -73,6 +92,15 @@ public InputStream apply(CliConnection input) { }; } + /** + * an expectation for a directory to contain a file + * + * @param directory + * the path of the directory to find the file in + * @param file + * the exact name of the file to find in the folder + * @return the filename + */ public static CliExpectedCondition directoryConatins(final String directory, final String file) { return new CliExpectedCondition() { @Override @@ -166,6 +194,14 @@ public String apply(LinuxDefaultCliConnection linux) { }; } + /** + * an expectation for a process to be running + * + * @param processName + * the name of the process (the name of the binary executable) + * @return true if the process is running + * @see man ps + */ public static CliExpectedCondition processIsRunning(final String processName) { return new CliExpectedCondition() { @@ -193,6 +229,16 @@ public Boolean apply(LinuxDefaultCliConnection linux) throws Exception { }; } + /** + * an expectation for a process not to be running, i.e that the machine does + * not run a process with this name + * + * @param processName + * the name of the process (the name of the binary executable) + * @return true if there is no process running with the given name + * @see man ps + */ + public static CliExpectedCondition processIsNotRunning(final String processName) { return new CliExpectedCondition() { @@ -215,9 +261,47 @@ public Boolean apply(CliConnection cliConnection) { } public Boolean apply(LinuxDefaultCliConnection linux) throws Exception { - return !linux.isProccessRunning(processName); + return linux.isProccessNotRunning(processName); } }; } + public enum DirectoryItemType { + File("f"), Directory("d"), SymbolicLink("l"); + final String typeCmd; + + private DirectoryItemType(String typeCmd) { + this.typeCmd = typeCmd; + } + } + + public static CliExpectedCondition directoryHas(final String directory, final String filenamePattern, + final CompareMethod compareMethod, + final int expectedAmount, final DirectoryItemType itemType) { + + StringBuilder commandBuilder = new StringBuilder().append("find ").append(directory).append(" -maxdepth 1 -type ") + .append(itemType.typeCmd).append(" -name ").append(filenamePattern).append(" | wc -l"); + final String findCommand = commandBuilder.toString(); + final ComparableAssertion amountOfItemsAssertion = new ComparableAssertion<>(compareMethod, expectedAmount); + return new CliExpectedCondition() { + + @Override + public Integer apply(CliConnection cliConnection) { + return executionLogicHappens(amountOfItemsAssertion, intParser).apply( + new CliCommandExecution(cliConnection, findCommand).silently()); + } + + @Override + public String toString() { + return "the directory's " + directory + " amount of " + itemType.name() + "(s) to be " + compareMethod.toString() + + " " + expectedAmount; + } + }; + } + + public static CliExpectedCondition directoryHas(final String directory, final CompareMethod compareMethod, + final int expectedAmount, final DirectoryItemType itemType) { + + return directoryHas(directory, "'*'", compareMethod, expectedAmount, itemType); + } } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxFileContentExecutionBuilder.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxFileContentExecutionBuilder.java new file mode 100644 index 0000000..900b27c --- /dev/null +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxFileContentExecutionBuilder.java @@ -0,0 +1,79 @@ +package il.co.topq.integframework.cli.support; + +import il.co.topq.integframework.assertion.Assert; +import il.co.topq.integframework.cli.conn.CliConnection; +import il.co.topq.integframework.cli.process.CliCommandExecution; + +public class LinuxFileContentExecutionBuilder { + String name = ""; + private final CliConnection cliConnection; + private boolean fromHead = false; + private int maxLines = 10; + + public LinuxFileContentExecutionBuilder(CliConnection cliConnection, String fileName) { + + this.cliConnection = cliConnection; + this.name = fileName; + } + + LinuxFileContentExecutionBuilder named(String name) { + this.name = name; + return this; + } + + public CliCommandExecution build() { + if (name.length() == 0) + throw new IllegalStateException("file name is not set"); + StringBuilder command = new StringBuilder(); + if (fromHead) { + command.append("head "); + } else { + command.append("tail "); + } + command.append("-n ").append(maxLines).append(" "); + command.append(name); + + return new CliCommandExecution(cliConnection, command.toString()); + } + + public CliExecutionExpectedCondition containingText(final String expected) { + return new CliExecutionExpectedCondition() { + @Override + public String toString() { + return "the file " + name + " to contain [" + expected + "]"; + } + + @Override + public String apply(CliCommandExecution input) { + try { + input.mustHaveResponse(expected).execute(); + } catch (Exception e) { + Assert.fail("execution failed", e); + } + return input.getResult(); + } + }; + + } + + public CliExecutionExpectedCondition notContainingText(final String expected) { + + return new CliExecutionExpectedCondition() { + @Override + public String toString() { + return "the file " + name + " not to contain [" + expected + "]"; + } + + @Override + public String apply(CliCommandExecution input) { + try { + input.error(expected).execute(); + } catch (Exception e) { + Assert.fail("execution failed", e); + } + return input.getResult(); + } + }; + + } +} diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxFileInfoExecutionBuilder.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxFileInfoExecutionBuilder.java new file mode 100644 index 0000000..a042205 --- /dev/null +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/support/LinuxFileInfoExecutionBuilder.java @@ -0,0 +1,121 @@ +package il.co.topq.integframework.cli.support; + +import static il.co.topq.integframework.cli.support.CliExecutionExpectedConditions.executionLogicHappens; +import il.co.topq.integframework.assertion.ComparableAssertion; +import il.co.topq.integframework.assertion.CompareMethod; +import il.co.topq.integframework.cli.conn.CliConnection; +import il.co.topq.integframework.cli.process.CliCommandExecution; +import il.co.topq.integframework.utils.Formatter; +import il.co.topq.integframework.utils.Parser; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class LinuxFileInfoExecutionBuilder { + + String name = ""; + private final CliConnection cliConnection; + + private ResultType resultType = ResultType.FileSize; + + public LinuxFileInfoExecutionBuilder(CliConnection cliConnection, String fileName) { + super(); + this.cliConnection = cliConnection; + this.name = fileName; + } + + LinuxFileInfoExecutionBuilder named(String name) { + this.name = name; + return this; + } + + public CliCommandExecution build() { + if (name.length() == 0) + throw new IllegalStateException("file name is not set"); + return new CliCommandExecution(cliConnection, "ls -l --time-style=full-iso " + this.name + + " | grep -v '^total' | awk {'print " + resultType.awkPrint + "'}").error("No such file or directory").error( + "cannot access"); + } + + public LinuxFileInfoExecutionBuilder getFileSize() { + this.resultType = ResultType.FileSize; + return this; + } + + public LinuxFileInfoExecutionBuilder getFileDate() { + this.resultType = ResultType.FileSize; + return this; + } + + public CliExecutionExpectedCondition fileSizeToBe(CompareMethod compareMethod, long expectedSize) { + getFileSize(); + return execute(resultType, expectedSize, compareMethod); + } + + private CliExecutionExpectedCondition execute(final ResultType resultType, final long expected, + final CompareMethod compareMethod) { + StringBuilder examinedObjectName = new StringBuilder("file "); + examinedObjectName.append(name).append(" "); + examinedObjectName.append(resultType.name()); + return executionLogicHappens( + new ComparableAssertion<>(compareMethod, expected).examinedObjectTitled(examinedObjectName.toString()) + .formatObjectWith(resultType) + + , resultType.parser); + + } + + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z"); + + public enum ResultType implements Formatter { + FileDate("$6,$7,$8", new Parser() { + @Override + public Long parse(String s) throws ParseException { + Date actual = dateFormat.parse(s); + return actual.getTime(); + } + + }) { + @Override + public String toString(Long l) { + return dateFormat.format(l); + } + + @Override + public String toString() { + return "date"; + } + }, + + FileSize("$5", new Parser() { + @Override + public Long parse(String s) { + long actual = Long.parseLong(s); + return actual; + } + }) { + @Override + public String toString(Long l) { + return Long.toString(l); + } + + @Override + public String toString() { + return "size"; + } + }; + + final String awkPrint; + final Parser parser; + + ResultType(final String awkPrint, final Parser parser) { + this.awkPrint = awkPrint; + this.parser = parser; + } + + public Parser getParser() { + return parser; + } + } +} diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/BufferInputStream.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/BufferInputStream.java index 842d735..13c6a4f 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/BufferInputStream.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/BufferInputStream.java @@ -29,6 +29,7 @@ public void startThread() { thread.start(); } + @Override public int read() throws IOException { if (ioExp != null) { throw ioExp; @@ -49,6 +50,7 @@ public int read() throws IOException { return c; } + @Override public int available() throws IOException { if (ioExp != null) { throw ioExp; @@ -92,6 +94,7 @@ public void setBufferMaxSize(int bufferMaxSize) { this.bufferMaxSize = bufferMaxSize; } + @Override public void close() throws IOException { thread.interrupt(); super.close(); @@ -102,6 +105,7 @@ public void close() throws IOException { * * @see java.lang.Runnable#run() */ + @Override public void run() { while (true) { diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Cli.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Cli.java index 48e4fc5..f2b7d70 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Cli.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Cli.java @@ -83,8 +83,9 @@ public void setPrintStream(PrintStream printStream) { * send an enter string and wait for a matching Prompt in 60 seconds * * @exception IOException + * @throws InterruptedException */ - public void login() throws Exception { + public void login() throws IOException, InterruptedException { login(60000); } @@ -92,9 +93,10 @@ public void login() throws Exception { * send an enter string and wait for a matching Prompt in given time * * @param timeout the time after which a timeout exception will be thrown + * @throws InterruptedException * @throws Exception */ - public void login(long timeout) throws Exception { + public void login(long timeout) throws IOException, InterruptedException { login(timeout, false); } @@ -103,9 +105,10 @@ public void login(long timeout) throws Exception { * * @param timeout the time after which a timeout exception will be thrown * @param delayedTyping if True then terminal buffer reading will be delayed (20 ms sleep between each byte) + * @throws InterruptedException * @throws Exception */ - public void login(long timeout, boolean delayedTyping) throws Exception { + public void login(long timeout, boolean delayedTyping) throws IOException, InterruptedException { Thread.sleep(1000); command(null, timeout, true, delayedTyping); } @@ -113,8 +116,9 @@ public void login(long timeout, boolean delayedTyping) throws Exception { /** * Sends the command without waiting to any prompt. * If delayedTyping is true, sends each byte desperately + small wait after each byte. + * @throws InterruptedException */ - public void sendString(String command, boolean delayedTyping) throws Exception { + public void sendString(String command, boolean delayedTyping) throws IOException, InterruptedException { terminal.sendString(command, delayedTyping); } @@ -124,8 +128,9 @@ public void sendString(String command, boolean delayedTyping) throws Exception { * @param command Command text. * * @exception IOException + * @throws InterruptedException */ - public void command(String command) throws Exception { + public void command(String command) throws IOException, InterruptedException { command(command, 20000, true, false); } @@ -156,8 +161,9 @@ public Prompt getResultPrompt() { * @param addEnter If true enterString will be add to the command. * * @exception IOException + * @throws InterruptedException */ - public void command(String command, long timeout, boolean addEnter) throws Exception { + public void command(String command, long timeout, boolean addEnter) throws IOException, InterruptedException { command(command, timeout, addEnter, false); } @@ -169,8 +175,9 @@ public void command(String command, long timeout, boolean addEnter) throws Excep * @param addEnter If True, defined enter string will be added to the command. * * @exception IOException + * @throws InterruptedException */ - public void command(String command, long timeout, boolean addEnter, boolean delayedTyping) throws Exception { + public void command(String command, long timeout, boolean addEnter, boolean delayedTyping) throws IOException, InterruptedException { command(command, timeout, addEnter, delayedTyping, (String) null); } @@ -182,9 +189,10 @@ public void command(String command, long timeout, boolean addEnter, boolean dela * @param addEnter If True, defined enter string will be added to the command. * @param delayedTyping if True then terminal buffer reading will be delayed (20 ms sleep between each byte) * @param promptString a Prompt String to wait for (if null then default terminal prompts will be used) + * @throws InterruptedException * @throws Exception */ - public void command(String command, long timeout, boolean addEnter, boolean delayedTyping, String promptString) throws Exception { + public void command(String command, long timeout, boolean addEnter, boolean delayedTyping, String promptString) throws IOException, InterruptedException { if (promptString != null) { command(command, timeout, addEnter, delayedTyping, new String[] { promptString }); } else { @@ -201,9 +209,10 @@ public void command(String command, long timeout, boolean addEnter, boolean dela * @param addEnter If True, defined enter string will be added to the command. * @param delayTyping if True then terminal buffer writing will be delayed (20 ms sleep between each byte) * @param promptStrings an array of all Prompt Strings that should be found (if null then default terminal prompts will be used) + * @throws InterruptedException * @throws Exception */ - public void command(String command, long timeout, boolean addEnter, boolean delayTyping, String[] promptStrings) throws Exception { + public void command(String command, long timeout, boolean addEnter, boolean delayTyping, String[] promptStrings) throws IOException, InterruptedException { command(command, timeout, addEnter, delayTyping, promptStrings, null); } @@ -216,10 +225,11 @@ public void command(String command, long timeout, boolean addEnter, boolean dela * @param delayedTyping if True will sleep 20 ms between each typed byte sent to the terminal * @param promptStrings if not null then wait for ALL Strings in the given Array to be found in the terminal * @param prompts if promptStrings is null, wait for ONE of the prompts, if any exists + * @throws InterruptedException * @throws Exception */ public void command(String command, long timeout, boolean addEnter, boolean delayedTyping, String[] promptStrings, Prompt[] prompts) - throws Exception { + throws IOException, InterruptedException { resultPrompt = null; ArrayList defaultPromts = null; @@ -258,7 +268,7 @@ public void command(String command, long timeout, boolean addEnter, boolean dela } if (timeout > 0) { if (System.currentTimeMillis() - startTime > (timeout)) { - throw new IOException("timeout: " + timeout); + throw new IOException("Timeout waiting for scroll"); } } /* @@ -368,15 +378,16 @@ public boolean isConnected() { * If true will send ENTER if prompt wait fail * @param timeout the timeout to wait * @return the prompt + * @throws InterruptedException * @throws Exception */ - private Prompt waitWithGrace(long timeout) throws Exception { + private Prompt waitWithGrace(long timeout) throws IOException, InterruptedException { try { Prompt p = terminal.waitForPrompt(timeout); result.append(terminal.getResult()); return p; - } catch (Exception e) { + } catch (IOException e) { if ((!graceful) || (waitWithGraceCounter > 2)) { throw e; } @@ -392,9 +403,10 @@ private Prompt waitWithGrace(long timeout) throws Exception { * @param timeout * the prompt timeout * @return the prompt found + * @throws InterruptedException * @throws Exception */ - private Prompt sendEnter(long timeout) throws Exception { + private Prompt sendEnter(long timeout) throws IOException, InterruptedException { startTime = System.currentTimeMillis(); terminal.sendString(getEnterStr(), false); result.append(terminal.getResult()); diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Cmd.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Cmd.java index 45801ca..a1fa94c 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Cmd.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Cmd.java @@ -40,6 +40,7 @@ public Cmd(String dir){ /* (non-Javadoc) * @see il.co.topq.integframework.cli.terminal.Terminal#connect() */ + @Override public void connect() throws IOException { File root = null; if (!StringUtils.isEmpty(processDir)){ @@ -53,7 +54,8 @@ public void connect() throws IOException { out = new BufferedOutputStream(process.getOutputStream()); } - public synchronized void sendString(String command, boolean delayedTyping) throws IOException, InterruptedException{ + @Override + public synchronized void sendString(String command, boolean delayedTyping) throws IOException, InterruptedException{ super.sendString(command, delayedTyping); if (isCloseOutputOnSend()){ out.close(); @@ -62,6 +64,7 @@ public synchronized void sendString(String command, boolean delayedTyping) throw /* (non-Javadoc) * @see il.co.topq.integframework.cli.terminal.Terminal#disconnect() */ + @Override public void disconnect() throws IOException { process.destroy(); } @@ -69,6 +72,7 @@ public void disconnect() throws IOException { /* (non-Javadoc) * @see il.co.topq.integframework.cli.terminal.Terminal#isConnected() */ + @Override public boolean isConnected() { if (process == null){ return false; @@ -84,6 +88,7 @@ public boolean isConnected() { /* (non-Javadoc) * @see il.co.topq.integframework.cli.terminal.Terminal#getConnectionName() */ + @Override public String getConnectionName() { return "cmd"; } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/DummyTerminal.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/DummyTerminal.java new file mode 100644 index 0000000..50b0516 --- /dev/null +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/DummyTerminal.java @@ -0,0 +1,32 @@ +package il.co.topq.integframework.cli.terminal; + +import java.io.IOException; + +public class DummyTerminal extends Terminal { + + public DummyTerminal() { + + } + + private boolean conneted = false; + @Override + public void connect() throws IOException { + conneted = true; + } + + @Override + public void disconnect() throws IOException { + conneted = false; + } + + @Override + public boolean isConnected() { + return conneted; + } + + @Override + public String getConnectionName() { + return "dummy connection"; + } + +} diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/FilterInputStream.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/FilterInputStream.java index b292d26..71c6548 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/FilterInputStream.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/FilterInputStream.java @@ -21,6 +21,7 @@ public void startThread(){ thread.setName(Thread.currentThread().getName()); thread.start(); } + @Override public int read() throws IOException { if(ioExp != null){ throw ioExp; @@ -40,11 +41,13 @@ public int read() throws IOException { inconclusive = false; return c; } + @Override public void close() throws IOException{ thread.interrupt(); super.close(); } - public int available() throws IOException { + @Override + public int available() throws IOException { if(ioExp != null){ throw ioExp; } @@ -59,6 +62,7 @@ public int available() throws IOException { return buf.length(); } + @Override public void run() { while(true){ diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/InOutInputStream.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/InOutInputStream.java index 2031090..b89cd90 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/InOutInputStream.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/InOutInputStream.java @@ -17,6 +17,7 @@ public abstract class InOutInputStream extends InputStream { public void setInputStream(InputStream in){ this.in = in; } + @Override public void close() throws IOException{ if(in != null){ in.close(); diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Prompt.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Prompt.java index a73f521..a14f149 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Prompt.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Prompt.java @@ -180,10 +180,15 @@ public void setRegularExpression(boolean regularExpression) { this.regularExpression = regularExpression; } + @Override public boolean equals(Object o) { return (o instanceof Prompt && ((Prompt) o).getPrompt().equals(getPrompt())); } + @Override + public int hashCode() { + return getPrompt().hashCode(); + } /** * should prompt appear after all input was read? * diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/RS232.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/RS232.java index 6eae1e6..82dad8d 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/RS232.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/RS232.java @@ -7,8 +7,10 @@ import javax.comm.SerialPort; import javax.comm.PortInUseException; import javax.comm.UnsupportedCommOperationException; + import java.util.ArrayList; import java.util.Enumeration; +import java.util.List; import java.io.IOException; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -31,7 +33,7 @@ public class RS232 extends Terminal { private SerialPort serialPort = null; - private static ArrayList comBank = new ArrayList(); + private static List comBank = new ArrayList<>(); public RS232(String portName, int boudRate, int dataBit, int stopBit, int parity) { @@ -42,6 +44,7 @@ public RS232(String portName, int boudRate, int dataBit, int stopBit, this.parity = parity; } + @Override public void connect() throws IOException { portId = findComm(portName); try { @@ -61,6 +64,7 @@ public void connect() throws IOException { out = new BufferedOutputStream(serialPort.getOutputStream()); } + @Override public void disconnect() throws IOException { if (serialPort != null) { serialPort.close(); @@ -69,10 +73,12 @@ public void disconnect() throws IOException { closeStreams(); } + @Override public boolean isConnected() { return true; } + @Override public String getConnectionName() { return portName; } @@ -88,7 +94,7 @@ public static void closeAllComs() { } } } - comBank = new ArrayList(); + comBank = new ArrayList<>(); } private static CommPortIdentifier findComm(String portName) diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/SSH.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/SSH.java index 649d755..8a82256 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/SSH.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/SSH.java @@ -3,16 +3,17 @@ */ package il.co.topq.integframework.cli.terminal; +import il.co.topq.integframework.reporting.Reporter; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; -import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.InteractiveCallback; -import ch.ethz.ssh2.LocalPortForwarder; -import ch.ethz.ssh2.SCPClient; -import ch.ethz.ssh2.Session; +import org.testng.ITestResult; + +import ch.ethz.ssh2.*; +import ch.ethz.ssh2.channel.Channel; /** * A terminal used for SSH Connection @@ -36,6 +37,8 @@ public class SSH extends Terminal { protected int destinationPort = -1; + protected int port = 22; + protected boolean xtermTerminal = true; public SSH(String hostnameP, String usernameP, String passwordP) { @@ -60,18 +63,24 @@ public SSH(String hostnameP, String usernameP, String passwordP, int sourceTunne public void connect() throws IOException { boolean isAuthenticated = false; /* Create a connection instance */ - - conn = new Connection(hostname); + Reporter.log("Connecting to " + hostname + " via " + getConnectionName()); + conn = new Connection(hostname, getPort()); /* Now connect */ + try { + conn.connect(); + } catch (IOException e) { + Reporter.log("Connection to "+ hostname + " Failed", e, ITestResult.SUCCESS_PERCENTAGE_FAILURE); + throw e; + } - conn.connect(); - - // Check what connection options are available to us String[] authMethods = conn.getRemainingAuthMethods(username); - System.out.println("The supported auth Methods are:"); - for(String method: authMethods) { - System.out.println(method); + // Check what connection options are available to us + synchronized (System.out){ + System.out.println("The supported auth Methods are:"); + for(String method: authMethods) { + System.out.println(method); + } } // boolean privateKeyAuthentication = false; boolean passAuthentication = false; @@ -119,6 +128,14 @@ public void connect() throws IOException { out = sess.getStdin(); } + protected int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + @Override public void disconnect() { if (lpf != null) { @@ -137,7 +154,7 @@ public void disconnect() { @Override public boolean isConnected() { - return true; + return sess.getState() == Channel.STATE_OPEN; } @Override @@ -178,6 +195,7 @@ public OutputStream put(final String remoteFile, long length, String remoteTarge */ class InteractiveLogic implements InteractiveCallback { /* the callback may be invoked several times, depending on how many questions-sets the server sends */ + @Override public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) throws IOException { /* Often, servers just send empty strings for "name" and "instruction" */ @@ -245,8 +263,4 @@ protected int getDestinationPort() { protected void setDestinationPort(int destinationPort) { this.destinationPort = destinationPort; } - - - - } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/SSHWithRSA.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/SSHWithRSA.java index 71993c7..50337be 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/SSHWithRSA.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/SSHWithRSA.java @@ -3,10 +3,14 @@ */ package il.co.topq.integframework.cli.terminal; +import il.co.topq.integframework.reporting.Reporter; + import java.io.File; import java.io.IOException; import java.util.Arrays; +import org.testng.ITestResult; + import ch.ethz.ssh2.Connection; /** @@ -27,18 +31,24 @@ public SSHWithRSA(String hostnameP, String usernameP, String passwordP, public void connect() throws IOException { boolean isAuthenticated = false; /* Create a connection instance */ - System.out.println("Connet to Host with SSH and RSA private key"); - conn = new Connection(hostname); + Reporter.log("Connecting to " + hostname + " via " + getConnectionName()); + conn = new Connection(hostname, getPort()); /* Now connect */ + try { + conn.connect(); + } catch (IOException e) { + Reporter.log("Connection to "+ hostname + " Failed", e, ITestResult.SUCCESS_PERCENTAGE_FAILURE); + throw e; + } - conn.connect(); - - // Check what connection options are available to us String[] authMethods = conn.getRemainingAuthMethods(username); - System.out.println("The supported auth Methods are:"); - for (String method : authMethods) { - System.out.println(method); + // Check what connection options are available to us + synchronized (System.out){ + System.out.println("The supported auth Methods are:"); + for (String method : authMethods) { + System.out.println(method); + } } boolean privateKeyAuthentication = false; boolean passAuthentication = false; @@ -54,20 +64,19 @@ public void connect() throws IOException { } /* Authenticate */ - if (passAuthentication) { + if (passAuthentication && password != null) { super.connect(); } else if (privateKeyAuthentication) { try { if (privateKeyFile != null && privateKeyFile.isFile()) { - System.out.println(); isAuthenticated = conn.authenticateWithPublicKey(username, privateKeyFile, ""); } else { - System.out - .println("Auth Error - The privateKeyFile should be init from the SUT with a valid path to ppk/pem RSA private key"); + Reporter.log("Connection to "+hostname+" Failed","Auth Error - The privateKeyFile should be init from the SUT with a valid path to ppk/pem RSA private key",false); + System.out.println(privateKeyFile); } } catch (Exception e) { - System.out.println(e.getMessage()); + Reporter.log("Connection to "+ hostname+" Failed",e); isAuthenticated = false; } } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Telnet.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Telnet.java index 5aa4919..d25490f 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Telnet.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Telnet.java @@ -49,6 +49,7 @@ public Telnet(String address, int port, boolean useTelnetInputStream, int soTime setSocketReceiveBufferSize(socketReceiveBufferSize); } + @Override public void connect() throws IOException { socket = new Socket(getAddress(), getPort()); socket.setReceiveBufferSize(getSocketReceiveBufferSize()); @@ -63,6 +64,7 @@ public void connect() throws IOException { } + @Override public void disconnect() throws IOException { if (socket != null) { socket.shutdownInput(); @@ -73,6 +75,7 @@ public void disconnect() throws IOException { } + @Override public boolean isConnected() { if (socket.isConnected() && !socket.isInputShutdown() && !socket.isOutputShutdown()) { return true; @@ -81,6 +84,7 @@ public boolean isConnected() { } } + @Override public String getConnectionName() { try { return socket.getLocalAddress().getHostAddress(); diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/TelnetInputStream.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/TelnetInputStream.java index 3953d8f..7f459a9 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/TelnetInputStream.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/TelnetInputStream.java @@ -38,9 +38,9 @@ //package net.mpowers.telnet; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.IOException; /** * A minimal telnet protocol filter that handles only @@ -83,7 +83,8 @@ public TelnetInputStream( if ( terminal == null ) terminal = "dumb"; } - public int read() throws IOException + @Override + public int read() throws IOException { byte b; @@ -207,23 +208,25 @@ public int read() throws IOException } } - public void close() throws IOException + @Override + public void close() throws IOException { in.close(); } - private void write( byte inByte ) throws IOException - { - output.write( inByte ); - output.flush(); - } + // private void write( byte inByte ) throws IOException + // { + // output.write( inByte ); + // output.flush(); + // } private void write( byte[] inBytes ) throws IOException { output.write( inBytes ); output.flush(); } - public int available() throws IOException { + @Override + public int available() throws IOException { return in.available(); } @@ -246,17 +249,17 @@ public int available() throws IOException { private final static byte IAC = (byte) 255; // -1 // options - private final static byte TRANSMIT_BINARY = (byte) 0; - private final static byte ECHO = (byte) 1; - private final static byte SUPPRESS_GO_AHEAD = (byte) 3; - private final static byte STATUS = (byte) 5; - private final static byte TIMING_MARK = (byte) 6; + // private final static byte TRANSMIT_BINARY = (byte) 0; + // private final static byte ECHO = (byte) 1; + // private final static byte SUPPRESS_GO_AHEAD = (byte) 3; + // private final static byte STATUS = (byte) 5; + // private final static byte TIMING_MARK = (byte) 6; private final static byte TERMINAL_TYPE = (byte) 24; - private final static byte END_OF_RECORD = (byte) 25; + // private final static byte END_OF_RECORD = (byte) 25; private final static byte WINDOW_SIZE = (byte) 31; // used with END_OF_RECORD - private final static byte EOR = (byte) 239; + // private final static byte EOR = (byte) 239; // used with TERMINAL_TYPE private final static byte TERMINAL_IS = (byte) 0; diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/TelnetOption.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/TelnetOption.java index 5cecc03..eb2838f 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/TelnetOption.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/TelnetOption.java @@ -114,7 +114,7 @@ public class TelnetOption public static int EXTENDED_OPTIONS_LIST = 255; - private static int __FIRST_OPTION = BINARY; + // private static int __FIRST_OPTION = BINARY; private static int __LAST_OPTION = EXTENDED_OPTIONS_LIST; private static final String __optionString[] = { diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Terminal.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Terminal.java index 10faff7..80a75c6 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Terminal.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/Terminal.java @@ -8,82 +8,91 @@ import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; +import java.util.List; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; public abstract class Terminal { - + Logger log = Logger.getLogger(Terminal.class.getName()); - protected static final int IN_BUFFER_SIZE = 65536; - private StringBuffer result = new StringBuffer(); - protected OutputStream out = null; - protected InputStream in = null; - protected int bufChar = 10; - protected long scrollEndTimeout = 200; - ArrayList prompts = new ArrayList(); - - public abstract void connect() throws IOException; - public abstract void disconnect() throws IOException; - public abstract boolean isConnected(); - public abstract String getConnectionName(); - - private boolean delayedTyping = false; - private boolean asciiFilter = true; - private PrintStream printStream = System.out; - private long keyTypingDelay = 20; - private boolean ignoreBackSpace = false; - private String charSet = "ASCII"; - - /** - * create a filter input stream:
- * 1) add the current input stream to the given stream.
- * 2) set the new input stream to the given one.
- * - * @param input the filter stream - */ - public void addFilter(InOutInputStream input) { - input.setInputStream(in); - in = input; - } - - /** - * send a given string to the terminal (no prompt waiting) - * - * @param command the command to send - * @param delayedTyping if True will sleep keyTypingDelay ms between each typed byte entered to the terminal - * @throws IOException - * @throws InterruptedException - */ - public synchronized void sendString(String command, boolean delayedTyping) throws IOException, InterruptedException{ - - byte[] buf = command.getBytes(charSet); - - // Do not override if delayed typing was set to TRUE from elsewhere - if (this.delayedTyping != true) { - setDelayedTyping(delayedTyping); - } - - if (isDelayedTyping()) { - for (int i = 0; i < buf.length; i++) { - out.write(buf[i]); - out.flush(); - Thread.sleep(keyTypingDelay); - } - } else { - out.write(buf); - out.flush(); - } - } - - /** - * get the input buffer data - * @return a String of all data in the input buffer - * @throws Exception - */ - public String readInputBuffer() throws Exception { + protected static final int IN_BUFFER_SIZE = 65536; + private StringBuffer result = new StringBuffer(); + protected OutputStream out = null; + protected InputStream in = null; + protected int bufChar = 10; + protected long scrollEndTimeout = 200; + List prompts = new ArrayList<>(); + + public abstract void connect() throws IOException; + + public abstract void disconnect() throws IOException; + + public abstract boolean isConnected(); + + public abstract String getConnectionName(); + + private boolean delayedTyping = false; + private boolean asciiFilter = true; + PrintStream printStream = System.out; + private long keyTypingDelay = 20; + private boolean ignoreBackSpace = false; + private String charSet = "ASCII"; + + /** + * create a filter input stream:
+ * 1) add the current input stream to the given stream.
+ * 2) set the new input stream to the given one.
+ * + * @param input + * the filter stream + */ + public void addFilter(InOutInputStream input) { + input.setInputStream(in); + in = input; + } + + /** + * send a given string to the terminal (no prompt waiting) + * + * @param command + * the command to send + * @param delayedTyping + * if True will sleep keyTypingDelay ms between each typed byte + * entered to the terminal + * @throws IOException + * @throws InterruptedException + */ + public synchronized void sendString(String command, boolean delayedTyping) throws IOException, InterruptedException { + + byte[] buf = command.getBytes(charSet); + + // Do not override if delayed typing was set to TRUE from elsewhere + if (this.delayedTyping != true) { + setDelayedTyping(delayedTyping); + } + + if (isDelayedTyping()) { + for (int i = 0; i < buf.length; i++) { + out.write(buf[i]); + out.flush(); + Thread.sleep(keyTypingDelay); + } + } else { + out.write(buf); + out.flush(); + } + } + + /** + * get the input buffer data + * + * @return a String of all data in the input buffer + * @throws Exception + */ + public String readInputBuffer() throws IOException { int avail = in.available(); - if (avail <= 0 ) { + if (avail <= 0) { return ""; } byte[] bytes = new byte[avail]; @@ -94,338 +103,369 @@ public String readInputBuffer() throws Exception { /** * add a remark to the result buffer * - * @param remark the String to add + * @param remark + * the String to add + */ + public synchronized void addRemark(String remark) { + result.append(remark); + } + + /** + * checks if there is more input in the buffer + * + * @return True if there isn't any new input after ${scrollEndTimeout} ms + * @throws InterruptedException + * @throws Exception + */ + public synchronized boolean isScrallEnd() throws IOException, InterruptedException { + if (scrollEndTimeout == 0) { // if set to 0 always return true. + return true; + } + int avil0 = in.available(); + Thread.sleep(scrollEndTimeout); + int avil1 = in.available(); + if (avil1 > bufChar) { + return false; + } + if (avil0 == avil1) { // no change after 1/2 time and avail under + // bufChar + return true; + } + Thread.sleep(scrollEndTimeout); + if (in.available() < bufChar) { + return true; + } + return false; + } + + /** + * wait for ALL Strings in the given Array to be found, in the given + * time + * + * @param prompts + * the Strings to check + * @param timeout + * the time (in ms) before throwing a timeout exception + * @throws IOException + * @throws InterruptedException + */ + public synchronized void waitForPrompt(String[] prompts, long timeout) throws IOException, InterruptedException { + + long startTime = System.currentTimeMillis(); + StringBuffer sb = new StringBuffer(); + try { + while (true) { + if (timeout > 0) { + if (System.currentTimeMillis() - startTime > timeout) { + result.append(sb); + throw new IOException("timeout: " + timeout); + } + } + int avail = in.available(); + if (avail > 0) { + while (avail > 0) { + int b = in.read(); + if (b < 0) { + avail = in.available(); + continue; + } + if (b == 8 && !isIgnoreBackSpace()) { + sb.append('B'); + } + if (b >= 127 || b < 9 || (b >= 14 && b <= 31) || b == 11 || b == 12) { + // not ascii byte will be ignored + avail = in.available(); + continue; + } + sb.append((char) b); + + String bufString = sb.toString(); + boolean allPromptsFound = true; + for (int i = 0; i < prompts.length; i++) { + if (bufString.indexOf(prompts[i]) < 0) { + allPromptsFound = false; + break; + } + } + if (allPromptsFound) { + result.append(sb); + return; + } + avail = in.available(); + if (timeout > 0) { + if (System.currentTimeMillis() - startTime > timeout) { + result.append(sb); + throw new IOException("timeout: " + timeout); + } + } + } + } else { + Thread.sleep(10); + } + } + } finally { + if (printStream != null) { + printStream.println(result); + } + } + + } + + /** + * wait for one of the terminal defined prompts to be found in the input + * buffer + * + * @param timeout + * the time on which timeout exception will be thrown + * @return the found Prompt if any was found + * @throws IOException + * if Timeout was reached + * @throws InterruptedException + */ + public Prompt waitForPrompt(long timeout) throws IOException, InterruptedException { + + long startTime = System.currentTimeMillis(); + StringBuffer sb = new StringBuffer(); + if (prompts == null || prompts.size() == 0) { + return null; + } + try { + while (true) { + if (timeout > 0) { + if (System.currentTimeMillis() - startTime > timeout) { + result.append(sb); + throw new IOException("Timeout (" + timeout+ "ms) waiting for prompt"); + } + } + int avail = in.available(); + if (avail > 0) { + sb.ensureCapacity(sb.length() + avail); + result.ensureCapacity(result.length() + avail); + + while (avail > 0) { + int b = in.read(); + if (b < 0) { + avail = in.available(); + continue; + } + if (b == 8 && !isIgnoreBackSpace()) { + sb.append('B'); + } + if (asciiFilter) { + if (b >= 127 || b < 9 || (b >= 14 && b <= 31) || b == 11 || b == 12) { + // not ascii byte will be ignored + avail = in.available(); + // if the last value is a non-ascii character + continue; + } + } + sb.append((char) b); + int promptArraySize = prompts.size(); + boolean skipNonExact = false; + if (in.available() > 40 + bufChar) { + skipNonExact = true; + } + for (int j = 0; j < promptArraySize; j++) { + Prompt prompt = (Prompt) prompts.get(j); + if (prompt == null || prompt.getPrompt() == null) { + continue; + } + String bufString = sb.toString(); + if (prompt.isRegularExpression()) { + Pattern p = prompt.getPattern(); + Matcher m = p.matcher(bufString); + if (m.find()) { + result.append(sb); + return prompt; + } + } else { + // accelerate cases with long output + if (!prompt.dontWaitForScrollEnd() && skipNonExact) { + continue; + } + if (bufString.endsWith(prompt.getPrompt())) { + result.append(sb); + return prompt; + } + } + } + avail = in.available(); + /** + * change the timeout to be activate in a state were + * there is endless amount of output from the cli. + */ + if (timeout > 0) { + if (System.currentTimeMillis() - startTime > timeout) { + result.append(sb); + throw new IOException("Timeout waiting for response"); + } + } + } + } else { + Thread.sleep(10); + } + } + } finally { + if (printStream != null) { + printStream.println(result); + } + } + } + + /** + * wait for one of the terminal Prompts for 20 seconds + * + * @return the found Prompt if any was found + * @throws IOException + * if no prompt was found after 20 seconds + * @throws InterruptedException + */ + public synchronized Prompt waitFor() throws IOException, InterruptedException { + return waitForPrompt(20000); + } + + /** + * get all data gathered by the input buffer + * + * @return a String of all input data gathered by the terminal + */ + public synchronized String getResult() { + String toRetun = result.toString(); + result = new StringBuffer(); + return toRetun; + } + + /** + * close input and output streams + * + * @throws IOException + */ + public void closeStreams() throws IOException { + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + } + + /** + * add a given Prompt to the Terminal Prompts array + * + * @param promptString + * the prompt String to add + * @param isRegExp + * if True then Prompt will be marked as a regular expression + */ + public void addPrompt(String promptString, boolean isRegExp) { + Prompt prompt = new Prompt(promptString, isRegExp); + addPrompt(prompt); + } + + /** + * add a given Prompt to the Terminal Prompts array + * + * @param prompt + * the prompt to add + */ + public void addPrompt(Prompt prompt) { + prompts.remove(prompt); + prompts.add(prompt); + } + + /** + * locate the matching Terminal Prompt object by the given Prompt String + * + * @param prompt + * the Prompt String + * @return the Prompt object from the Terminal Prompts list or null if none + * was found + */ + public Prompt getPrompt(String prompt) { + for (int i = 0; i < prompts.size(); i++) { + Prompt p = (Prompt) prompts.get(i); + if (p.getPrompt().equals(prompt)) { + return p; + } + } + return null; + } + + /** + * clear all Terminal Prompts + */ + public void removePrompts() { + prompts = new ArrayList<>(); + } + + /** + * get a clone of the Terminal Prompts list + * + * @return */ - public synchronized void addRemark(String remark) { - result.append(remark); - } - - /** - * checks if there is more input in the buffer - * - * @return True if there isn't any new input after ${scrollEndTimeout} ms - * @throws Exception - */ - public synchronized boolean isScrallEnd() throws Exception{ - if (scrollEndTimeout == 0) { // if set to 0 always return true. - return true; - } - int avil0 = in.available(); - Thread.sleep(scrollEndTimeout); - int avil1 = in.available(); - if (avil1 > bufChar) { - return false; - } - if (avil0 == avil1) { // no change after 1/2 time and avail under bufChar - return true; - } - Thread.sleep(scrollEndTimeout); - if (in.available() < bufChar) { - return true; - } - return false; - } - - /** - * wait for ALL Strings in the given Array to be found, in the given time - * - * @param prompts the Strings to check - * @param timeout the time (in ms) before throwing a timeout exception - * @throws IOException - * @throws InterruptedException - */ - public synchronized void waitForPrompt(String[] prompts, long timeout) throws IOException, InterruptedException{ - - long startTime = System.currentTimeMillis(); - StringBuffer sb = new StringBuffer(); - while (true) { - if (timeout > 0) { - if (System.currentTimeMillis() - startTime > timeout) { - result.append(sb); - throw new IOException("timeout: " + timeout); - } - } - int avail = in.available(); - if (avail > 0) { - while (avail > 0) { - int b = in.read(); - if (b < 0) { - avail = in.available(); - continue; - } - if (b == 8 && !isIgnoreBackSpace()) { - sb.append('B'); - } - if (b >= 127 || - b < 9 || - (b >= 14 && b <= 31) || - b == 11 || - b == 12) { // not ascii byte will be ignored - avail = in.available(); - continue; - } - sb.append((char)b); - if (printStream != null) { - printStream.print((char)b); - } - - String bufString = sb.toString(); - boolean allPromptsFound = true; - for (int i = 0; i < prompts.length; i++) { - if (bufString.indexOf(prompts[i]) < 0) { - allPromptsFound = false; - break; - } - } - if (allPromptsFound) { - result.append(sb); - return; - } - avail = in.available(); - if (timeout > 0) { - if (System.currentTimeMillis() - startTime > timeout) { - result.append(sb); - throw new IOException("timeout: " + timeout); - } - } - } - } else { - Thread.sleep(10); - } - } - - } - - /** - * wait for one of the terminal defined prompts to be found in the input buffer - * - * @param timeout the time on which timeout exception will be thrown - * @return the found Prompt if any was found - * @throws IOException if Timeout was reached - * @throws InterruptedException - */ - public synchronized Prompt waitForPrompt(long timeout) throws IOException, InterruptedException{ - - long startTime = System.currentTimeMillis(); - StringBuffer sb = new StringBuffer(); - if (prompts == null || prompts.size() == 0) { - return null; - } - while (true) { - if (timeout > 0) { - if (System.currentTimeMillis() - startTime > timeout) { - result.append(sb); - throw new IOException("timeout: " + timeout); - } - } - int avail = in.available(); - if (avail > 0) { - while (avail > 0) { - int b = in.read(); - if (b < 0) { - avail = in.available(); - continue; - } - if (b == 8 && !isIgnoreBackSpace()) { - sb.append('B'); - } - if (asciiFilter) { - if (b >= 127 || b < 9 || (b >= 14 && b <= 31) || b == 11 || b == 12) { // not ascii byte will be ignored - avail = in.available(); // if the last value is a non-ascii character - continue; - } - } - sb.append((char)b); - if (printStream != null) { - printStream.print((char)b); - } - int promptArraySize = prompts.size(); - boolean skipNonExact = false; - if (in.available() > 40 + bufChar) { - skipNonExact = true; - } - for (int j = 0; j < promptArraySize; j++) { - Prompt prompt = (Prompt)prompts.get(j); - if (prompt == null || prompt.getPrompt() == null) { - continue; - } - String bufString = sb.toString(); - if (prompt.isRegularExpression()) { - Pattern p = prompt.getPattern(); - Matcher m = p.matcher(bufString); - if (m.find()) { - result.append(sb); - return prompt; - } - } else { - // accelerate cases with long output - if (!prompt.dontWaitForScrollEnd() && skipNonExact) { - continue; - } - if (bufString.endsWith(prompt.getPrompt())) { - result.append(sb); - return prompt; - } - } - } - avail = in.available(); - /** - * change the timeout to be activate in a state were there is endless amount of output - * from the cli. - */ - if (timeout > 0) { - if (System.currentTimeMillis() - startTime > timeout) { - result.append(sb); - throw new IOException("timeout: " + timeout); - } - } - } - } else { - Thread.sleep(10); - } - } - } - - /** - * wait for one of the terminal Prompts for 20 seconds - * - * @return the found Prompt if any was found - * @throws IOException if no prompt was found after 20 seconds - * @throws InterruptedException - */ - public synchronized Prompt waitFor() throws IOException, InterruptedException{ - return waitForPrompt(20000); - } - - /** - * get all data gathered by the input buffer - * - * @return a String of all input data gathered by the terminal - */ - public synchronized String getResult() { - String toRetun = result.toString(); - result = new StringBuffer(); - return toRetun; - } - - /** - * close input and output streams - * - * @throws IOException - */ - public void closeStreams() throws IOException{ - if (in != null) { - in.close(); - } - if (out != null) { - out.close(); - } - } - - /** - * add a given Prompt to the Terminal Prompts array - * - * @param promptString the prompt String to add - * @param isRegExp if True then Prompt will be marked as a regular expression - */ - public void addPrompt(String promptString, boolean isRegExp) { - Prompt prompt = new Prompt(promptString,isRegExp); - addPrompt(prompt); - } - - /** - * add a given Prompt to the Terminal Prompts array - * - * @param prompt the prompt to add - */ - public void addPrompt(Prompt prompt) { - prompts.remove(prompt); - prompts.add(prompt); - } - - /** - * locate the matching Terminal Prompt object by the given Prompt String - * @param prompt the Prompt String - * @return the Prompt object from the Terminal Prompts list or null if none was found - */ - public Prompt getPrompt(String prompt) { - for (int i = 0; i < prompts.size(); i++) { - Prompt p = (Prompt)prompts.get(i); - if (p.getPrompt().equals(prompt)) { - return p; - } - } - return null; - } - - /** - * clear all Terminal Prompts - */ - public void removePrompts() { - prompts = new ArrayList(); - } - - /** - * get a clone of the Terminal Prompts list - * @return - */ - @SuppressWarnings("unchecked") public ArrayList getPrompts() { - return (ArrayList)prompts.clone(); - } - - /** - * set the Terminal Prompts list - * - * @param prompts the Prompts to set - */ - public void setPrompts(ArrayList prompts) { - this.prompts = prompts; - } + return new ArrayList<>(prompts); + } + + /** + * set the Terminal Prompts list + * + * @param prompts + * the Prompts to set + */ + public void setPrompts(ArrayList prompts) { + this.prompts = prompts; + } + public int getBufChar() { return bufChar; } + public void setBufChar(int bufChar) { this.bufChar = bufChar; } - + /** - * the time (in ms) to wait for a terminal input to be received before declaring scroll end (no more input) + * the time (in ms) to wait for a terminal input to be received before + * declaring scroll end (no more input) * * @return */ public long getScrollEndTimeout() { return scrollEndTimeout; } - + /** - * the time (in ms) to wait for a terminal input to be received before declaring scroll end (no more input) + * the time (in ms) to wait for a terminal input to be received before + * declaring scroll end (no more input) * * @param scrollEndTimeout */ public void setScrollEndTimeout(long scrollEndTimeout) { this.scrollEndTimeout = scrollEndTimeout; } - + /** - * signals if input String should be typed char by char with 20ms delay or all at once + * signals if input String should be typed char by char with 20ms delay or + * all at once + * * @return */ public boolean isDelayedTyping() { return delayedTyping; } - + /** - * if set to True then input String (command) will be typed char by char with 20ms delay
- * if set to False all String will be send at once - * default is false + * if set to True then input String (command) will be typed char by char + * with 20ms delay
+ * if set to False all String will be send at once default is false * * @param delayedTyping */ public void setDelayedTyping(boolean delayedTyping) { this.delayedTyping = delayedTyping; } - + /** * signals if ascii chars should be ignored when reading from the buffer * @@ -434,7 +474,7 @@ public void setDelayedTyping(boolean delayedTyping) { public boolean isAsciiFilter() { return asciiFilter; } - + /** * if set to True then non ascii chars will be ignored * @@ -445,15 +485,14 @@ public void setAsciiFilter(boolean asciiFilter) { } /** - * Sets the print stream to which the stream of the connection - * will be dumped to. - * Set the print stream to System.out to dump terminal stream to the console, - * Set print stream to null to turn off stream dump. + * Sets the print stream to which the stream of the connection will be + * dumped to. Set the print stream to System.out to dump terminal stream to + * the console, Set print stream to null to turn off stream dump. */ public void setPrintStream(PrintStream printStream) { this.printStream = printStream; } - + /** * the time (in ms) to sleep between each typed byte entered to the terminal * @@ -462,7 +501,7 @@ public void setPrintStream(PrintStream printStream) { public long getKeyTypingDelay() { return keyTypingDelay; } - + /** * the time (in ms) to sleep between each typed byte entered to the terminal * @@ -480,7 +519,7 @@ public void setKeyTypingDelay(long keyTypingDelay) { public boolean isIgnoreBackSpace() { return ignoreBackSpace; } - + /** * Whether to ignore backspace characters or not * @@ -489,13 +528,17 @@ public boolean isIgnoreBackSpace() { public void setIgnoreBackSpace(boolean ignoreBackSpace) { this.ignoreBackSpace = ignoreBackSpace; } - + public void setCharSet(String charSet) { this.charSet = charSet; } - + public String getCharSet() { return charSet; } - + + public PrintStream getPrintStream() { + return printStream; + } + } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/ThreadedBufferedInputStream.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/ThreadedBufferedInputStream.java index 35cff71..b0083b1 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/ThreadedBufferedInputStream.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/ThreadedBufferedInputStream.java @@ -18,9 +18,11 @@ public ThreadedBufferedInputStream(InputStream in){ /* (non-Javadoc) * @see java.io.InputStream#read() */ + @Override public int read() throws IOException { return reader.read(); } + @Override public int available() throws IOException{ return reader.getSize(); } @@ -37,6 +39,7 @@ public ReaderThread(InputStream in){ this.in = in; bufferSize = 0; } + @Override public void run(){ while (true){ int avail; diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/UniteInputStream.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/UniteInputStream.java index 961437b..5618ede 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/UniteInputStream.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/UniteInputStream.java @@ -24,6 +24,7 @@ public UniteInputStream(InputStream in, InputStream err){ /** * @see java.io.InputStream#read() */ + @Override public int read() throws IOException { if(err.available() > 0){ return err.read(); @@ -32,11 +33,13 @@ public int read() throws IOException { } } - public int available() throws IOException { + @Override + public int available() throws IOException { return in.available() + err.available(); } - public void close() throws IOException{ + @Override + public void close() throws IOException{ err.close(); in.close(); } diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/VT100.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/VT100.java index ee572b9..9b17ef0 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/VT100.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/VT100.java @@ -148,6 +148,7 @@ public ScreenReader(int screenHight, int screenWidth, InputStream in) { char[][] screen; + @Override public void run() { int c; try { diff --git a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/VT100FilterInputStream.java b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/VT100FilterInputStream.java index bd03f40..bf0c2e3 100644 --- a/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/VT100FilterInputStream.java +++ b/integ-cli/src/main/java/il/co/topq/integframework/cli/terminal/VT100FilterInputStream.java @@ -14,6 +14,7 @@ public class VT100FilterInputStream extends InOutInputStream { public VT100FilterInputStream() { } + @Override public int read() throws IOException { int c = in.read(); while (true) { @@ -424,6 +425,7 @@ private static boolean isDigit(int c) { } + @Override public int available() throws IOException { return in.available(); diff --git a/integ-db/.gitignore b/integ-db/.gitignore new file mode 100644 index 0000000..d2d9c31 --- /dev/null +++ b/integ-db/.gitignore @@ -0,0 +1,3 @@ +/target +/target/ +/target/ diff --git a/integ-db/pom.xml b/integ-db/pom.xml index 079ea66..140b5cc 100644 --- a/integ-db/pom.xml +++ b/integ-db/pom.xml @@ -1,17 +1,19 @@ - + + 4.0.0 integ-db org.springframework spring-jdbc + 3.1.3.RELEASE + provided il.co.topq.integframework integ-testng - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT commons-dbcp @@ -22,7 +24,7 @@ il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT ../integ-parent - \ No newline at end of file + diff --git a/integ-db/src/main/java/il/co/topq/integframework/db/CSVResultSetPrinter.java b/integ-db/src/main/java/il/co/topq/integframework/db/CSVResultSetPrinter.java new file mode 100644 index 0000000..0118d37 --- /dev/null +++ b/integ-db/src/main/java/il/co/topq/integframework/db/CSVResultSetPrinter.java @@ -0,0 +1,188 @@ +package il.co.topq.integframework.db; + +/** + * based on code of au.com.bytecode.opencsv + */ +import il.co.topq.integframework.reporting.Reporter; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.testng.ITestResult; + +public class CSVResultSetPrinter implements ResultSetPrinter { + + public static final int INITIAL_STRING_SIZE = 128; + + + private char separator = DEFAULT_ESCAPE_CHARACTER; + + private char quotechar = DEFAULT_QUOTE_CHARACTER; + + private char escapechar = DEFAULT_ESCAPE_CHARACTER; + + private String lineEnd = DEFAULT_LINE_END; + + private String nullString = "~NULL~"; + + /** The character used for escaping quotes. */ + public static final char DEFAULT_ESCAPE_CHARACTER = '"'; + + /** The default separator to use if none is supplied to the constructor. */ + public static final char DEFAULT_SEPARATOR = ','; + + /** + * The default quote character to use if none is supplied to the + * constructor. + */ + public static final char DEFAULT_QUOTE_CHARACTER = '"'; + + /** The quote constant to use when you wish to suppress all quoting. */ + public static final char NO_QUOTE_CHARACTER = '\u0000'; + + /** The escape constant to use when you wish to suppress all escaping. */ + public static final char NO_ESCAPE_CHARACTER = '\u0000'; + + /** Default line terminator uses platform encoding. */ + public static final String DEFAULT_LINE_END = "\n"; + + @Override + public void print(List> resultList) { + + File file = null; + boolean headerLine = true; + try { + file = File.createTempFile("resultsTable", ".csv"); + file.deleteOnExit(); + + try { + Writer writer = new FileWriter(file); + for (Map map : resultList) { + Set fields = map.keySet(); + if (headerLine) { + writeNext(new ArrayList<>(fields), writer); + headerLine = false; + } + List nextLine = new ArrayList<>(fields.size()); + + for (String field : fields) { + Object value = map.get(field); + if (value == null) { + value = nullString; + } + nextLine.add(value.toString()); + } + writeNext(nextLine, writer); + } + writer.close(); + } catch (IOException exception) { + throw exception; + } + + } catch (IOException e) { + Reporter.log("failed to print resultset", e); + } + if (file != null && file.exists()) { + if (!headerLine) { + Reporter.logFile("SQL Table", file); + file.delete(); + } + } else { + Reporter.log("failed to print resultset", ITestResult.SUCCESS_PERCENTAGE_FAILURE); + } + } + + protected final void writeNext(List nextLine, Writer pw) throws IOException { + + if (nextLine == null) + return; + + StringBuilder sb = new StringBuilder(100); + for (int i = 0; i < nextLine.size(); i++) { + + if (i != 0) { + sb.append(getSeparator()); + } + + String nextElement = nextLine.get(i); + if (nextElement == null) + continue; + if (getQuotechar() != NO_QUOTE_CHARACTER) + sb.append(getQuotechar()); + + sb.append(stringContainsSpecialCharacters(nextElement) ? processLine(nextElement) : nextElement); + + if (getQuotechar() != NO_QUOTE_CHARACTER) + sb.append(getQuotechar()); + } + + sb.append(getLineEnd()); + pw.write(sb.toString()); + + } + + private boolean stringContainsSpecialCharacters(String line) { + return line.indexOf(quotechar) != -1 || line.indexOf(escapechar) != -1; + } + + private StringBuilder processLine(String nextElement) { + StringBuilder sb = new StringBuilder(INITIAL_STRING_SIZE); + for (int j = 0; j < nextElement.length(); j++) { + char nextChar = nextElement.charAt(j); + if (escapechar != NO_ESCAPE_CHARACTER && nextChar == quotechar) { + sb.append(escapechar).append(nextChar); + } else if (escapechar != NO_ESCAPE_CHARACTER && nextChar == escapechar) { + sb.append(escapechar).append(nextChar); + } else { + sb.append(nextChar); + } + } + return sb; + } + + public void setSeparator(char separator) { + this.separator = separator; + } + + public void setQuotechar(char quotechar) { + this.quotechar = quotechar; + } + + public void setEscapechar(char escapechar) { + this.escapechar = escapechar; + } + + public void setLineEnd(String lineEnd) { + this.lineEnd = lineEnd; + } + + public void setNullString(String nullString) { + this.nullString = nullString; + } + + public char getSeparator() { + return separator; + } + + public char getQuotechar() { + return quotechar; + } + + public char getEscapechar() { + return escapechar; + } + + public String getLineEnd() { + return lineEnd; + } + + public String getNullString() { + return nullString; + } +} \ No newline at end of file diff --git a/integ-db/src/main/java/il/co/topq/integframework/db/DatabaseSystemModule.java b/integ-db/src/main/java/il/co/topq/integframework/db/DatabaseSystemModule.java index 5a28ca4..3c3de32 100644 --- a/integ-db/src/main/java/il/co/topq/integframework/db/DatabaseSystemModule.java +++ b/integ-db/src/main/java/il/co/topq/integframework/db/DatabaseSystemModule.java @@ -2,8 +2,8 @@ import il.co.topq.integframework.AbstractModuleImpl; import il.co.topq.integframework.assertion.Assert; +import il.co.topq.integframework.assertion.CompareMethod; import il.co.topq.integframework.assertion.NumberCompareAssertion; -import il.co.topq.integframework.assertion.NumberCompareAssertion.CompareMethod; import java.util.ArrayList; import java.util.List; @@ -11,25 +11,31 @@ import javax.sql.DataSource; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; public class DatabaseSystemModule extends AbstractModuleImpl { protected final JdbcTemplate template; private List resultSetPrinterList; + private int queryTimeout = 0; public DatabaseSystemModule(final DataSource dataSource) { super(); this.template = new JdbcTemplate(dataSource); + if (queryTimeout > 0) + this.template.setQueryTimeout(queryTimeout); } @Override public void init() throws Exception { - initResultSetPrinters(); + if (resultSetPrinterList == null) { + initResultSetPrinters(); + } } - + public void initResultSetPrinters() { - resultSetPrinterList = new ArrayList(); + resultSetPrinterList = new ArrayList<>(); resultSetPrinterList.addAll(tablePrinters()); } @@ -40,7 +46,7 @@ public void initResultSetPrinters() { * @return The table printers to add for each query */ protected List tablePrinters() { - List printers = new ArrayList(); + List printers = new ArrayList<>(); printers.add(new ResultSetHTMLPrinter()); return printers; } @@ -56,10 +62,10 @@ public List> getResultList(final String sql) { } List> resultList = template.queryForList(sql); + setActual(resultList); for (ResultSetPrinter printer : resultSetPrinterList) { printer.print(resultList); } - setActual(resultList); return resultList; } @@ -72,7 +78,7 @@ public List> getResultList(final String sql) { * expectedNumOfAffectedRows * @throws Exception */ - public void executeUpdateStatement(final String sql) throws Exception { + public void executeUpdateStatement(final String sql) throws DataAccessException { executeUpdateStatement(sql, -1); } @@ -89,17 +95,30 @@ public void executeUpdateStatement(final String sql) throws Exception { * assertion. * @throws Exception */ - public void executeUpdateStatement(final String sql, int expectedNumOfAffectedRows) throws Exception { + public void executeUpdateStatement(final String sql, int expectedNumOfAffectedRows) throws DataAccessException { if (null == sql || sql.isEmpty()) { throw new IllegalArgumentException("SQL query can't be empty"); } int rows = template.update(sql); if (expectedNumOfAffectedRows >= 0) { - Assert.assertLogicHappens(rows, - new NumberCompareAssertion(expectedNumOfAffectedRows, CompareMethod.EQUALS), 0l, true); + Assert.assertLogic(rows, new NumberCompareAssertion(expectedNumOfAffectedRows, CompareMethod.EQUALS)); } } + /** + * Executes the given SQL statement, which may be an DROP, ALTER etc,. + * + * @param sql + * the statement to execute + * @throws Exception + */ + public void executeStatement(final String sql) { + if (null == sql || sql.isEmpty()) { + throw new IllegalArgumentException("SQL query can't be empty"); + } + template.execute(sql); + } + /** * Compare between the number of rows returned as a result of executing the * specified query and the given number. @@ -115,7 +134,7 @@ public void executeUpdateStatement(final String sql, int expectedNumOfAffectedRo */ public void assertNumOfRows(final String sql, int expectedNumOfRows, CompareMethod compareMethod) throws Exception { int actual = getResultList(sql).size(); - Assert.assertLogicHappens(actual, new NumberCompareAssertion(expectedNumOfRows, compareMethod), 0l, true); + Assert.assertLogic(actual, new NumberCompareAssertion(expectedNumOfRows, compareMethod)); } public void assertNumOfRows(final String sql, int expectedNumOfRows) throws Exception { @@ -133,4 +152,24 @@ public int countRowsInTable(final String table) { return getResultList(String.format("SELECT * FROM %s", table)).size(); } + public List getResultSetPrinterList() { + return resultSetPrinterList; + } + + public void setResultSetPrinterList(List resultSetPrinterList) { + if (resultSetPrinterList == null) { + this.resultSetPrinterList = new ArrayList<>(); + } else { + this.resultSetPrinterList = resultSetPrinterList; + } + } + + public int getQueryTimeout() { + return queryTimeout; + } + + public void setQueryTimeout(int queryTimeout) { + this.queryTimeout = queryTimeout; + } + } diff --git a/integ-db/src/main/java/il/co/topq/integframework/db/ResultSetHTMLPrinter.java b/integ-db/src/main/java/il/co/topq/integframework/db/ResultSetHTMLPrinter.java index 513ecf5..62e5b33 100644 --- a/integ-db/src/main/java/il/co/topq/integframework/db/ResultSetHTMLPrinter.java +++ b/integ-db/src/main/java/il/co/topq/integframework/db/ResultSetHTMLPrinter.java @@ -29,7 +29,7 @@ public void print(List> resultList) { } sb.append(""); for (Object column : row.values()) { - sb.append("").append(column).append(""); + sb.append("
").append(column).append("
"); } sb.append(""); } diff --git a/integ-example/pom.xml b/integ-example/pom.xml index 5e08f30..e1a359f 100644 --- a/integ-example/pom.xml +++ b/integ-example/pom.xml @@ -1,240 +1,234 @@ - 4.0.0 - integration-test - - - - org.apache.activemq.tooling - maven-activemq-plugin - 5.7.0 - - - configure-activemq - pre-integration-test - - xbean:file:../src/main/resources/activemq.xml - false - - - javax.net.ssl.keyStorePassword - password - - - org.apache.activemq.default.directory.prefix - ./target/ - - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + integration-test + + + + + + + + + + + + + + + + + + + + + + + + - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - - org.apache.maven.plugins - maven-surefire-plugin - - 2.12 - - - org.apache.maven.surefire - surefire-junit47 - 2.13 - - - - - test - - - - - org.codehaus.groovy.maven - gmaven-plugin - 1.0 - - - - generateTestStubs - testCompile - - - - - - maven-antrun-plugin - 1.7 - - - prepare-environment - package - - - Preparing environment - Extracting resources - - Launching JMS server - - - - - - run - - - - + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 2.12 + + + org.apache.maven.surefire + surefire-junit47 + 2.13 + + + + + test + + + + + org.codehaus.groovy.maven + gmaven-plugin + 1.0 + + + + generateTestStubs + testCompile + + + + + + maven-antrun-plugin + 1.7 + + + prepare-environment + package + + + Preparing environment + Extracting resources + + Launching JMS server + + + + + + run + + + + - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.12 - - - org.apache.maven.surefire - surefire-testng - 2.12 - - - org.testng - testng - - - - - + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.12 + + + org.apache.maven.surefire + surefire-testng + 2.12 + + + org.testng + testng + + + + + - - - usedefaultlisteners - false - - - listener - org.uncommons.reportng.HTMLReporter - - - - testng.xml - - target/ - - - - - integration-test - verify - - - - + + + usedefaultlisteners + false + + + listener + org.uncommons.reportng.HTMLReporter + + + + testng.xml + + target/ + + + + + integration-test + verify + + + + - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.codehaus.groovy.maven - - - gmaven-plugin - - - [1.0,) - - - testCompile - - generateTestStubs - - - - - - - - - - - - - - - - - org.springframework - spring-context - 3.1.2.RELEASE - + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.codehaus.groovy.maven + + + gmaven-plugin + + + [1.0,) + + + testCompile + + generateTestStubs + + + + + + + + + + + + + + + + + org.springframework + spring-context + 3.1.2.RELEASE + - - - - il.co.topq.integframework - integ-bdd - 0.0.1-SNAPSHOT - - - il.co.topq.integframework - integ-cli - 0.0.1-SNAPSHOT - - - il.co.topq.integframework - integ-db - 0.0.1-SNAPSHOT - - - il.co.topq.integframework - integ-jms - 0.0.1-SNAPSHOT - - - il.co.topq.integframwork - integ-junit - 0.0.1-SNAPSHOT - - - - il.co.topq.integframework - integ-parent - 1.0.0-SNAPSHOT - + + il.co.topq.integframework + integ-bdd + ${project.version} + + + il.co.topq.integframework + integ-cli + ${project.version} + + + il.co.topq.integframework + integ-db + ${project.version} + + + il.co.topq.integframework + integ-jms + ${project.version} + + + il.co.topq.integframework + integ-junit + ${project.version} + + \ No newline at end of file diff --git a/integ-groovy-bdd/pom.xml b/integ-groovy-bdd/pom.xml index 7a2638c..d8be81b 100644 --- a/integ-groovy-bdd/pom.xml +++ b/integ-groovy-bdd/pom.xml @@ -1,5 +1,5 @@ - + + 4.0.0 integ-groovy-bdd @@ -70,7 +70,7 @@ - + @@ -83,7 +83,7 @@ il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT ../integ-parent - \ No newline at end of file + diff --git a/integ-hdfs/.gitignore b/integ-hdfs/.gitignore new file mode 100644 index 0000000..d2d9c31 --- /dev/null +++ b/integ-hdfs/.gitignore @@ -0,0 +1,3 @@ +/target +/target/ +/target/ diff --git a/integ-hdfs/pom.xml b/integ-hdfs/pom.xml index 57e9900..27fd403 100644 --- a/integ-hdfs/pom.xml +++ b/integ-hdfs/pom.xml @@ -1,5 +1,5 @@ - + + 4.0.0 integ-hdfs @@ -11,7 +11,7 @@ il.co.topq.integframework integ-testng - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT commons-dbcp @@ -21,26 +21,34 @@ org.apache.hadoop hadoop-hdfs - [2.0.0,) + ${hadoop.provided.version} provided org.apache.hadoop hadoop-common - [2.0.0,) provided + ${hadoop.provided.version} il.co.topq.integframework integ-support - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT + + + il.co.topq.integframework + integ-cli + 1.0.5-SNAPSHOT il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT ../integ-parent - - \ No newline at end of file + + + [2.0.0,2.4.1) + + diff --git a/integ-hdfs/src/main/java/il/co/topq/integframework/hdfs/HDFSSystemModule.java b/integ-hdfs/src/main/java/il/co/topq/integframework/hdfs/HDFSSystemModule.java index a4f07f5..5893f8c 100644 --- a/integ-hdfs/src/main/java/il/co/topq/integframework/hdfs/HDFSSystemModule.java +++ b/integ-hdfs/src/main/java/il/co/topq/integframework/hdfs/HDFSSystemModule.java @@ -1,48 +1,77 @@ package il.co.topq.integframework.hdfs; import static org.apache.hadoop.io.IOUtils.copyBytes; +import il.co.topq.integframework.AbstractModuleImpl; +import il.co.topq.integframework.cli.conn.LinuxDefaultCliConnection; import il.co.topq.integframework.hdfs.support.HdfsExpectedCondition; +import il.co.topq.integframework.hdfs.support.HdfsExpectedConditions; import il.co.topq.integframework.hdfs.support.HdfsWait; import il.co.topq.integframework.reporting.Reporter; import il.co.topq.integframework.support.TimeoutException; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.*; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.DirectoryNotEmptyException; +import java.security.PrivilegedExceptionAction; import java.util.EnumSet; import java.util.concurrent.TimeUnit; import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.CreateFlag; -import org.apache.hadoop.fs.FileAlreadyExistsException; -import org.apache.hadoop.fs.Hdfs; +import org.apache.hadoop.fs.*; import org.apache.hadoop.fs.Options.CreateOpts; -import org.apache.hadoop.fs.ParentNotDirectoryException; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.fs.UnresolvedLinkException; -import org.apache.hadoop.fs.UnsupportedFileSystemException; +import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.hdfs.protocol.HdfsConstants; import org.apache.hadoop.security.AccessControlException; +import org.apache.hadoop.security.UserGroupInformation; +import com.google.common.base.Optional; import com.google.common.base.Predicate; -public class HDFSSystemModule { +public class HDFSSystemModule extends AbstractModuleImpl { - protected final Hdfs hdfs; + protected Hdfs hdfs; private HdfsWait wait; + protected UserGroupInformation ugi; + protected LinuxDefaultCliConnection gateway = null; + protected String[] resourcesPaths = null; + protected final int port; + protected final String host; + protected final String userinfo; - public HDFSSystemModule(String host, int port, String userinfo) - throws URISyntaxException, UnsupportedFileSystemException { - Configuration conf = new Configuration(); + public HDFSSystemModule(final String host, final int port, final String userinfo) throws URISyntaxException, IOException, + InterruptedException { + this.host = host; + this.port = port; + this.userinfo = userinfo; + ugi = UserGroupInformation.getCurrentUser(); + if (userinfo != null) { + String username; + if (userinfo.contains(":")) { + username = userinfo.split(":")[0]; + } else { + username = userinfo; + } + ugi = UserGroupInformation.createRemoteUser(username); + } + } - hdfs = (Hdfs) Hdfs.get(new URI(HdfsConstants.HDFS_URI_SCHEME, userinfo, - host, port, "", "", ""), conf); + @Override + public void init() throws Exception { + super.init(); + hdfs = ugi.doAs(new PrivilegedExceptionAction() { + @Override + public Hdfs run() throws Exception { + Configuration conf = new Configuration(); + if (gateway != null) { + for (String resourcePath : resourcesPaths) { + conf.addResource(new BufferedInputStream(gateway.get(resourcePath))); + } + } + UserGroupInformation.setConfiguration(conf); + return (Hdfs) Hdfs.get(new URI(HdfsConstants.HDFS_URI_SCHEME, userinfo, host, port, "", "", ""), conf); + } + }); } public Hdfs getHdfs() { @@ -56,48 +85,82 @@ public HdfsWait getWait() { return wait; } - public void copyFromLocal(File src, Path dst, - EnumSet createFlag, CreateOpts... opts) - throws AccessControlException, FileAlreadyExistsException, - FileNotFoundException, ParentNotDirectoryException, - UnsupportedFileSystemException, UnresolvedLinkException, - IOException { + public void copyFromLocal(File src, Path dst, EnumSet createFlag, CreateOpts... opts) + throws AccessControlException, FileAlreadyExistsException, FileNotFoundException, ParentNotDirectoryException, + UnsupportedFileSystemException, UnresolvedLinkException, IOException { - copyBytes(new BufferedInputStream(new FileInputStream(src)), - new BufferedOutputStream(hdfs.create(dst, createFlag, opts)), + copyBytes(new BufferedInputStream(new FileInputStream(src)), new BufferedOutputStream(hdfs.create(dst, createFlag, opts)), 10240, true); } - public void copyFromRemote(Path src, File dst) - throws AccessControlException, - FileNotFoundException, - UnresolvedLinkException, + public void copyFromRemote(Path src, File dst) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { - copyBytes(new BufferedInputStream(hdfs.open(src)), - new BufferedOutputStream(new FileOutputStream(dst)), 10240, - true); + copyBytes(new BufferedInputStream(hdfs.open(src)), new BufferedOutputStream(new FileOutputStream(dst)), 10240, true); + } + + public OutputStream create(Path f, EnumSet createFlag, CreateOpts... opts) throws AccessControlException, + FileAlreadyExistsException, FileNotFoundException, ParentNotDirectoryException, UnsupportedFileSystemException, + UnresolvedLinkException, IOException { + return hdfs.create(f, createFlag, opts); + } + + public InputStream open(Path f) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { + return hdfs.open(f); + } + + public void mkdir(Path dir, FsPermission permission, boolean createParent) throws UnresolvedLinkException, IOException { + hdfs.mkdir(dir, permission, createParent); + } + + public void rmdir(Path dir) throws UnresolvedLinkException, IOException { + rmdir(dir, false); + } + + public void rmdir(Path dir, boolean throwFileNotFoundException) throws UnresolvedLinkException, IOException { + if (validateThat(HdfsExpectedConditions.isDirectory(dir))) { + if (!hdfs.delete(dir, true)) { + throw new DirectoryNotEmptyException("delete of " + dir.toString() + " failed"); + } + } else if (throwFileNotFoundException) { + throw new FileNotFoundException(dir.toString()); + } } - public T validateThat(HdfsExpectedCondition expectedCondition) throws Exception{ + public T validateThat(HdfsExpectedCondition expectedCondition) throws Throwable { Reporter.log("Validating: " + expectedCondition.toString()); HdfsWait oldWait = this.wait; this.wait = new HdfsWait(hdfs); - wait.withTimeout(0, TimeUnit.MILLISECONDS); try { - return wait.until(expectedCondition); - } - catch (TimeoutException exception){ - throw new Exception(exception.getCause()); + return wait.withTimeout(0, TimeUnit.MILLISECONDS).until(expectedCondition); + } catch (TimeoutException exception) { + throw Optional.fromNullable(exception.getCause()).or(exception); } finally { - this.wait=oldWait; + this.wait = oldWait; } - + } - - public boolean validateThat(Predicate predicate){ + + public boolean validateThat(Predicate predicate) { // TODO AssertTrue Reporter.log("Validating " + predicate.toString()); return predicate.apply(hdfs); } + + public LinuxDefaultCliConnection getGateway() { + return gateway; + } + + public void setGateway(LinuxDefaultCliConnection gateway) { + this.gateway = gateway; + } + + public String[] getResourcesPaths() { + return resourcesPaths; + } + + public void setResourcesPaths(String[] resourcesPaths) { + this.resourcesPaths = resourcesPaths; + } + } diff --git a/integ-hdfs/src/main/java/il/co/topq/integframework/hdfs/support/HdfsExpectedConditions.java b/integ-hdfs/src/main/java/il/co/topq/integframework/hdfs/support/HdfsExpectedConditions.java index dd1ed0e..868d568 100644 --- a/integ-hdfs/src/main/java/il/co/topq/integframework/hdfs/support/HdfsExpectedConditions.java +++ b/integ-hdfs/src/main/java/il/co/topq/integframework/hdfs/support/HdfsExpectedConditions.java @@ -4,11 +4,7 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.hadoop.fs.Hdfs; -import org.apache.hadoop.fs.LocatedFileStatus; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.fs.RemoteIterator; -import org.apache.hadoop.fs.UnresolvedLinkException; +import org.apache.hadoop.fs.*; import org.apache.hadoop.security.AccessControlException; import com.google.common.base.Predicate; @@ -16,23 +12,23 @@ public abstract class HdfsExpectedConditions { @SuppressWarnings("unused") private final int _; - private HdfsExpectedConditions(){ - _=1; + + private HdfsExpectedConditions() { + _ = 1; } - - public static Predicate fileExists(final String path){ + + public static Predicate fileExists(final String path) { return fileExists(new Path(path)); } - - - public static Predicate fileExists(final Path path){ + + public static Predicate fileExists(final Path path) { return new Predicate() { - + @Override public String toString() { return "the file in " + path.toString() + " to be openable"; }; - + @Override public boolean apply(Hdfs hdfs) { try { @@ -53,14 +49,14 @@ public boolean apply(Hdfs hdfs) { }; } - public static HdfsExpectedCondition fileIsReadable(final Path path){ + public static HdfsExpectedCondition fileIsReadable(final Path path) { return new HdfsExpectedCondition() { - + @Override public String toString() { - return "the file in " + path.toString() + " to be openable"; + return "the file in " + path.toString() + " to be openable"; }; - + @Override public InputStream apply(Hdfs hdfs) { try { @@ -80,22 +76,22 @@ public InputStream apply(Hdfs hdfs) { }; } - public static HdfsExpectedCondition directoryConatins(final Path directory, final String file){ - return new HdfsExpectedCondition () { + public static HdfsExpectedCondition directoryConatins(final Path directory, final String file) { + return new HdfsExpectedCondition() { @Override public String toString() { return "the directory " + directory.toString() + " to contain the file " + file; }; - + @Override public Path apply(Hdfs hdfs) { try { RemoteIterator locatedStatusIterator = hdfs.listLocatedStatus(directory); - while (locatedStatusIterator.hasNext()){ + while (locatedStatusIterator.hasNext()) { LocatedFileStatus locatedFileStatus = locatedStatusIterator.next(); - if (0==locatedFileStatus.getPath().compareTo(new Path(directory, file))){ + if (0 == locatedFileStatus.getPath().compareTo(new Path(directory, file))) { return locatedFileStatus.getPath(); - } + } } } catch (AccessControlException e) { throw new RuntimeException(e); @@ -126,22 +122,23 @@ public Path apply(Hdfs hdfs) { * @return the path of the found file */ public static HdfsExpectedCondition directoryContains(final Path directory, final String file, final boolean isRegexp) { - if (!isRegexp) return directoryConatins(directory, file); - return new HdfsExpectedCondition () { + if (!isRegexp) + return directoryConatins(directory, file); + return new HdfsExpectedCondition() { @Override public String toString() { return "the directory " + directory.toString() + " to contain a file matchin the regular expression " + file; }; - + @Override public Path apply(Hdfs hdfs) { try { RemoteIterator locatedStatusIterator = hdfs.listLocatedStatus(directory); - while (locatedStatusIterator.hasNext()){ + while (locatedStatusIterator.hasNext()) { LocatedFileStatus locatedFileStatus = locatedStatusIterator.next(); - if (locatedFileStatus.getPath().getName().matches(file)){ + if (locatedFileStatus.getPath().getName().matches(file)) { return locatedFileStatus.getPath(); - } + } } } catch (AccessControlException e) { throw new RuntimeException(e); @@ -158,4 +155,24 @@ public Path apply(Hdfs hdfs) { } }; } + + public static Predicate isDirectory(final Path path) { + return new Predicate() { + @Override + public String toString() { + return "the path " + path.toString() + " is a directory"; + } + + @Override + public boolean apply(Hdfs hdfs) { + try { + return hdfs.getFileStatus(path).isDirectory(); + } catch (UnresolvedLinkException e) { + return false; + } catch (IOException e) { + return false; + } + } + }; + } } diff --git a/integ-image-validator/pom.xml b/integ-image-validator/pom.xml index 5ec9f9a..db0e022 100644 --- a/integ-image-validator/pom.xml +++ b/integ-image-validator/pom.xml @@ -1,29 +1,39 @@ - - 4.0.0 - integ-image-validator - - - - junit - junit - 4.10 - - - il.co.topq.integframework - integ-cli - ${project.version} - - - il.co.topq.integframework - integ-testng - ${project.version} - - - - il.co.topq.integframework - integ-parent - 1.0.1-SNAPSHOT - ../integ-parent - - \ No newline at end of file + + + 4.0.0 + integ-image-validator + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + junit + junit + 4.10 + + + il.co.topq.integframework + integ-cli + 1.0.5-SNAPSHOT + + + il.co.topq.integframework + integ-testng + 1.0.5-SNAPSHOT + + + + il.co.topq.integframework + integ-parent + 1.0.5-SNAPSHOT + ../integ-parent + + diff --git a/integ-image-validator/repository/prop1/prop2/prop3/mask1.png b/integ-image-validator/repository/prop1/prop2/prop3/mask1.png deleted file mode 100644 index eee13b9..0000000 Binary files a/integ-image-validator/repository/prop1/prop2/prop3/mask1.png and /dev/null differ diff --git a/integ-jms/pom.xml b/integ-jms/pom.xml index 108f542..9438a67 100644 --- a/integ-jms/pom.xml +++ b/integ-jms/pom.xml @@ -1,5 +1,5 @@ - + + 4.0.0 integ-jms @@ -16,13 +16,13 @@ il.co.topq.integframework integ-testng - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT ../integ-parent - \ No newline at end of file + diff --git a/integ-junit/pom.xml b/integ-junit/pom.xml index ac17c61..6a3c8ae 100644 --- a/integ-junit/pom.xml +++ b/integ-junit/pom.xml @@ -1,5 +1,5 @@ - + + 4.0.0 integ-junit @@ -18,7 +18,7 @@ il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT - ../integ-parent + 1.0.5-SNAPSHOT + ../integ-parent/pom.xml - \ No newline at end of file + diff --git a/integ-junit/src/main/java/il/co/topq/integframework/junit/report/ReportersManager.java b/integ-junit/src/main/java/il/co/topq/integframework/junit/report/ReportersManager.java index 014cbed..fcdc708 100644 --- a/integ-junit/src/main/java/il/co/topq/integframework/junit/report/ReportersManager.java +++ b/integ-junit/src/main/java/il/co/topq/integframework/junit/report/ReportersManager.java @@ -25,7 +25,7 @@ private ReportersManager() { public void addReporter(ReporterI reporter) { if (null == reporters) { - reporters = new ArrayList(); + reporters = new ArrayList<>(); } reporters.add(reporter); if (reporter instanceof RunListener) { diff --git a/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/ExecutionStatusCollector.java b/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/ExecutionStatusCollector.java index 6333bff..d6a4523 100644 --- a/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/ExecutionStatusCollector.java +++ b/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/ExecutionStatusCollector.java @@ -12,10 +12,12 @@ public class ExecutionStatusCollector extends RunListener { private int numberOfIgnored; private long executionTime; + @Override public void testStarted(Description description) throws Exception { numberOfTests++; } + @Override public void testFailure(Failure failure) throws Exception { numberOfFailures++; } @@ -27,10 +29,12 @@ public void testFailure(Failure failure) throws Exception { * @param description * describes the test that will not be run */ + @Override public void testIgnored(Description description) throws Exception { numberOfIgnored++; } + @Override public void testRunFinished(Result result) throws Exception { executionTime += result.getRunTime(); } diff --git a/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/IntegrationJUnit4ClassRunner.java b/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/IntegrationJUnit4ClassRunner.java index 12eecea..1d179a9 100644 --- a/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/IntegrationJUnit4ClassRunner.java +++ b/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/IntegrationJUnit4ClassRunner.java @@ -20,6 +20,7 @@ public IntegrationJUnit4ClassRunner(Class clazz) throws InitializationError { super(clazz); } + @Override public void run(RunNotifier notifier) { //Make sure that the system is configured Configurator.getInstance(); diff --git a/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/RunListenerManager.java b/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/RunListenerManager.java index d73a85d..c991d07 100644 --- a/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/RunListenerManager.java +++ b/integ-junit/src/main/java/il/co/topq/integframework/junit/runner/RunListenerManager.java @@ -25,7 +25,7 @@ public static RunListenerManager getInstance() { public void addRunListener(RunListener listener) { if (null == listeners) { - listeners = new ArrayList(); + listeners = new ArrayList<>(); } listeners.add(listener); } diff --git a/integ-kinesis/.gitignore b/integ-kinesis/.gitignore new file mode 100644 index 0000000..63e2211 --- /dev/null +++ b/integ-kinesis/.gitignore @@ -0,0 +1,4 @@ +/target +/target/ +/target/ +/dependency-reduced-pom.xml diff --git a/integ-kinesis/pom.xml b/integ-kinesis/pom.xml new file mode 100644 index 0000000..37d125e --- /dev/null +++ b/integ-kinesis/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + integ-kinesis + + il.co.topq.integframework + integ-parent + 1.0.5-SNAPSHOT + ../integ-parent + + + + com.amazonaws + amazon-kinesis-client + 1.2.0 + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + shade + + + + org.apache.http + org.xapachex.http + + + + + + + + + diff --git a/integ-parent/pom.xml b/integ-parent/pom.xml index 137c17a..4a70076 100644 --- a/integ-parent/pom.xml +++ b/integ-parent/pom.xml @@ -1,9 +1,9 @@ - + + 4.0.0 il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT pom UTF-8 @@ -11,14 +11,23 @@ http://maven.top-q.co.il + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18 + + + org.apache.maven.plugins maven-compiler-plugin 2.5.1 - 1.6 - 1.6 + 1.7 + 1.7 @@ -80,5 +89,11 @@ ../integ-hdfs ../integ-support ../integ-rest + ../integ-wget + ../integ-archetype + ../integ-kinesis - \ No newline at end of file + + scm:git:https://github.com/aharonha/integ-framework + + diff --git a/integ-rest/.gitignore b/integ-rest/.gitignore new file mode 100644 index 0000000..d2d9c31 --- /dev/null +++ b/integ-rest/.gitignore @@ -0,0 +1,3 @@ +/target +/target/ +/target/ diff --git a/integ-rest/pom.xml b/integ-rest/pom.xml index 06af590..dfe76f1 100644 --- a/integ-rest/pom.xml +++ b/integ-rest/pom.xml @@ -1,17 +1,18 @@ + 4.0.0 il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT - ../../integ/integ-parent + 1.0.5-SNAPSHOT + ../integ-parent integ-rest il.co.topq.integframework integ-testng - ${project.version} + 1.0.5-SNAPSHOT org.codehaus.jettison @@ -26,4 +27,4 @@ provided - \ No newline at end of file + diff --git a/integ-rest/src/main/java/il/co/topq/integframework/rest/RESTClientModule.java b/integ-rest/src/main/java/il/co/topq/integframework/rest/RESTClientModule.java index bbc01c9..4619c89 100644 --- a/integ-rest/src/main/java/il/co/topq/integframework/rest/RESTClientModule.java +++ b/integ-rest/src/main/java/il/co/topq/integframework/rest/RESTClientModule.java @@ -1,10 +1,15 @@ package il.co.topq.integframework.rest; import static com.sun.jersey.api.client.Client.create; + +import javax.ws.rs.core.MediaType; + import il.co.topq.integframework.AbstractModuleImpl; import il.co.topq.integframework.reporting.Reporter; import il.co.topq.integframework.reporting.Reporter.Color; +import il.co.topq.integframework.reporting.Reporter.Style; +import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import com.sun.jersey.api.client.ClientResponse; @@ -13,8 +18,7 @@ public class RESTClientModule extends AbstractModuleImpl { String uri; public ClientResponse post(JSONObject input, String action) throws Exception { - Reporter.log("Request", Color.BLUE); - Reporter.log("
\n" + input.toString() + "
\n"); + Reporter.log("Request", action + "\nBody:" + input.toString(3), Style.PLAINTEXT); StringBuilder builder = new StringBuilder(uri); if (!uri.endsWith("/")) { builder.append("/"); @@ -24,8 +28,61 @@ public ClientResponse post(JSONObject input, String action) throws Exception { .accept("application/json").post(ClientResponse.class, input); setActual(clientResponse.getEntity(String.class)); - Reporter.log("Response", Color.BLUE); - Reporter.log("
\n" + getActual(String.class) + "
\n"); + try { + JSONObject response = new JSONObject(getActual(String.class)); + Reporter.log("Response", response.toString(3), Style.PLAINTEXT); + } catch (JSONException e) { + Reporter.log("Response", getActual(String.class), Style.PLAINTEXT);// should + // never + // happen!! + } + + return clientResponse; + } + + public ClientResponse post(String postData,MediaType postDataMediaType, String action) throws Exception { + Reporter.log("Request", action + "\nBody:" + postData, Style.PLAINTEXT); + StringBuilder builder = new StringBuilder(uri); + if (!uri.endsWith("/")) { + builder.append("/"); + } + builder.append(action); + ClientResponse clientResponse = create().resource(builder.toString()).type(postDataMediaType) + .accept("application/json").post(ClientResponse.class, postData); + + setActual(clientResponse.getEntity(String.class)); + try { + JSONObject response = new JSONObject(getActual(String.class)); + Reporter.log("Response", response.toString(3), Style.PLAINTEXT); + } catch (JSONException e) { + Reporter.log("Response", getActual(String.class), Style.PLAINTEXT); + // should never happen!! + } + + return clientResponse; + } + + + public ClientResponse get(String action) throws Exception { + Reporter.log("Request", action, Style.PLAINTEXT); + StringBuilder builder = new StringBuilder(uri); + if (!uri.endsWith("/")) { + builder.append("/"); + } + builder.append(action); + ClientResponse clientResponse = create().resource(builder.toString()).accept("application/json") + .get(ClientResponse.class); + + setActual(clientResponse.getEntity(String.class)); + try { + JSONObject response = new JSONObject(getActual(String.class)); + Reporter.log("Response", response.toString(3), Style.PLAINTEXT); + } catch (JSONException e) { + Reporter.log("Response", getActual(String.class), Style.PLAINTEXT);// should + // never + // happen!! + } + return clientResponse; } @@ -39,7 +96,7 @@ public void setUri(String uri) { public ClientResponse put(JSONObject input, String action) { Reporter.log("Request", Color.BLUE); - Reporter.log("
\n" + input.toString() + "
\n"); + Reporter.log(input.toString(), Style.PLAINTEXT); StringBuilder builder = new StringBuilder(uri); if (!uri.endsWith("/")) { builder.append("/"); @@ -50,7 +107,7 @@ public ClientResponse put(JSONObject input, String action) { setActual(clientResponse.getEntity(String.class)); Reporter.log("Response", Color.BLUE); - Reporter.log("
\n" + getActual(String.class) + "
\n"); + Reporter.log(getActual(String.class), Style.PLAINTEXT); return clientResponse; } diff --git a/integ-rest/src/main/java/il/co/topq/integframework/rest/TomcatRESTApplicationContainer.java b/integ-rest/src/main/java/il/co/topq/integframework/rest/TomcatRESTApplicationContainer.java index 5da7e56..2d4b27d 100644 --- a/integ-rest/src/main/java/il/co/topq/integframework/rest/TomcatRESTApplicationContainer.java +++ b/integ-rest/src/main/java/il/co/topq/integframework/rest/TomcatRESTApplicationContainer.java @@ -4,6 +4,7 @@ import static il.co.topq.integframework.utils.StringUtils.isEmpty; import il.co.topq.integframework.reporting.Reporter; import il.co.topq.integframework.reporting.Reporter.Color; +import il.co.topq.integframework.reporting.Reporter.Style; import il.co.topq.integframework.utils.StringUtils; import java.net.URI; @@ -70,7 +71,7 @@ public ClientResponse reload() throws URISyntaxException { setActual(clientResponse.getEntity(String.class)); Reporter.log("Response", Color.BLUE); - Reporter.log("
\n" + getActual(String.class) + "
\n"); + Reporter.log(getActual(String.class), Style.PLAINTEXT); return clientResponse; } diff --git a/integ-support/.gitignore b/integ-support/.gitignore new file mode 100644 index 0000000..d2d9c31 --- /dev/null +++ b/integ-support/.gitignore @@ -0,0 +1,3 @@ +/target +/target/ +/target/ diff --git a/integ-support/pom.xml b/integ-support/pom.xml index c72a92a..d9eee9a 100644 --- a/integ-support/pom.xml +++ b/integ-support/pom.xml @@ -1,9 +1,10 @@ + 4.0.0 il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT ../integ-parent integ-support @@ -11,7 +12,7 @@ org.seleniumhq.selenium selenium-support - [2.0.0,) + 2.48.2 - \ No newline at end of file + diff --git a/integ-support/src/main/java/il/co/topq/integframework/support/FluentWait.java b/integ-support/src/main/java/il/co/topq/integframework/support/FluentWait.java index 358c1a7..1c16bbb 100644 --- a/integ-support/src/main/java/il/co/topq/integframework/support/FluentWait.java +++ b/integ-support/src/main/java/il/co/topq/integframework/support/FluentWait.java @@ -40,7 +40,8 @@ public String toString() { * on a function. * @return Nothing will ever be returned; this return type is only specified as a convenience. */ - protected RuntimeException timeoutException(String message, Throwable lastException) { + @Override + protected RuntimeException timeoutException(String message, Throwable lastException) { throw new TimeoutException(message, lastException); } } diff --git a/integ-support/src/main/java/il/co/topq/integframework/support/guava/Utils.java b/integ-support/src/main/java/il/co/topq/integframework/support/guava/Utils.java new file mode 100644 index 0000000..ba42883 --- /dev/null +++ b/integ-support/src/main/java/il/co/topq/integframework/support/guava/Utils.java @@ -0,0 +1,126 @@ +package il.co.topq.integframework.support.guava; + +import static com.google.common.base.Optional.fromNullable; +import static com.google.common.base.Suppliers.compose; +import static com.google.common.base.Verify.verifyNotNull; + +import java.lang.reflect.Constructor; +import java.util.List; +import java.util.Map; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +public abstract class Utils { + @SuppressWarnings("unused") + private final int _; + + private Utils() { + _ = 0; + } + + public static Supplier> newHashMap() { + return new Supplier>() { + @Override + public Map get() { + return Maps. newHashMap(); + } + }; + } + + public static Supplier> newBiHashMap() { + return new Supplier>() { + @Override + public HashBiMap get() { + return HashBiMap. create(); + } + }; + } + + public static Supplier> newArrayList() { + return new Supplier>() { + @Override + public List get() { + return Lists.newArrayList(); + } + }; + } + + public static Supplier forConstructor(final Constructor constructor) { + return new Supplier() { + @Override + public T get() { + try { + return constructor.newInstance(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + }; + } + + /** + * Get an item from a map, for the given key.
+ * If the item does not exist, putting the result of {@link Supplier#get()} + * to the map for this key. + * + * @param map + * the map to get the item from + * @param key + * the key to search in the map using {@link Map#get} + * @param supplier + * a {@link Supplier} that provides a default value if the item + * does not exist + * @return the value in the map. + */ + public static V getOrAdd(Map map, K key, Supplier supplier) { + return fromNullable(verifyNotNull(map).get(key)).or(fromNullable(compose(addToMap(map, key), supplier)).orNull()); + } + + /** + * + * @param map + * @param key + * @return a function that puts an item to the map to the given key + */ + public static Function addToMap(final Map map, final K key) { + return new Function() { + @Override + public V apply(V input) { + map.put(key, input); + return map.get(key); + } + }; + }; + + public static Function getSimpleClassName() { + return new Function() { + @Override + public String apply(T t) { + return t.getClass().getSimpleName(); + } + }; + } + + + public static Function getClassName() { + return new Function() { + @Override + public String apply(T t) { + return t.getClass().getName(); + } + }; + } + + public static Function getCanonicalClassName() { + return new Function() { + @Override + public String apply(T t) { + return t.getClass().getCanonicalName(); + } + }; + } +} diff --git a/integ-support/src/main/java/il/co/topq/integframework/support/threads/ExecutionTerminatorService.java b/integ-support/src/main/java/il/co/topq/integframework/support/threads/ExecutionTerminatorService.java new file mode 100644 index 0000000..36db8b8 --- /dev/null +++ b/integ-support/src/main/java/il/co/topq/integframework/support/threads/ExecutionTerminatorService.java @@ -0,0 +1,117 @@ +package il.co.topq.integframework.support.threads; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.*; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +public class ExecutionTerminatorService implements ExecutorService { + + private ExecutorService realTerminator; + + private final static class Terminator implements Runnable { + private final ExecutorService toTerminate; + final int timeout; + final TimeUnit unit; + + public Terminator(ExecutorService toTerminate, int timeoutForAll, final TimeUnit unit) { + this.toTerminate = toTerminate; + this.timeout = timeoutForAll; + this.unit = unit; + } + + @Override + public void run() { + try { + toTerminate.awaitTermination(timeout, unit); + } catch (InterruptedException e) { + Thread t = Thread.currentThread(); + t.getUncaughtExceptionHandler().uncaughtException(t, e); + } + } + }; + + final int timeout; + final TimeUnit unit; + + public ExecutionTerminatorService(Collection executorServicesToWaitFor, final int timeoutForAll, + final TimeUnit unit) { + this.timeout = timeoutForAll; + this.unit = unit; + + realTerminator = Executors.newFixedThreadPool(executorServicesToWaitFor.size(), + new ThreadFactoryBuilder().setNameFormat("Terminator %d").build()); + for (final ExecutorService executorService : executorServicesToWaitFor) { + realTerminator.execute(new Terminator(executorService, timeoutForAll, unit)); + } + realTerminator.shutdown(); + } + + @Override + public void execute(Runnable command) { + throw new IllegalArgumentException(); + } + + @Override + public void shutdown() { + // already done in c'Tor + } + + @Override + public List shutdownNow() { + return realTerminator.shutdownNow(); + } + + @Override + public boolean isShutdown() { + return realTerminator.isShutdown(); + } + + @Override + public boolean isTerminated() { + return realTerminator.isTerminated(); + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + return realTerminator.awaitTermination(timeout, unit); + } + + @Override + public Future submit(Callable task) { + throw new IllegalArgumentException(); + } + + @Override + public Future submit(Runnable task, T result) { + throw new IllegalArgumentException(); + } + + @Override + public Future submit(Runnable task) { + throw new IllegalArgumentException(); + } + + @Override + public List> invokeAll(Collection> tasks) throws InterruptedException { + throw new IllegalArgumentException(); + } + + @Override + public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) + throws InterruptedException { + throw new IllegalArgumentException(); + } + + @Override + public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { + throw new IllegalArgumentException(); + } + + @Override + public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException, + ExecutionException, TimeoutException { + throw new IllegalArgumentException(); + } +} diff --git a/integ-support/src/main/java/il/co/topq/integframework/support/threads/NamedThreadFactory.java b/integ-support/src/main/java/il/co/topq/integframework/support/threads/NamedThreadFactory.java new file mode 100644 index 0000000..b5dc80e --- /dev/null +++ b/integ-support/src/main/java/il/co/topq/integframework/support/threads/NamedThreadFactory.java @@ -0,0 +1,28 @@ +package il.co.topq.integframework.support.threads; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +public class NamedThreadFactory implements ThreadFactory { + private final String name; + private static Map names = new ConcurrentHashMap<>(); + + public NamedThreadFactory(String name) { + synchronized (names) { + if (!names.containsKey(name)) { + names.put(name, new AtomicInteger()); + } + } + this.name = name; + } + + @Override + public Thread newThread(Runnable r) { + Thread thread = Executors.defaultThreadFactory().newThread(r); + thread.setName(name + "#" + names.get(name).incrementAndGet()); + return thread; + } +} \ No newline at end of file diff --git a/integ-support/src/main/java/il/co/topq/integframework/support/threads/SingleHashThreadFactory.java b/integ-support/src/main/java/il/co/topq/integframework/support/threads/SingleHashThreadFactory.java new file mode 100644 index 0000000..09d7c20 --- /dev/null +++ b/integ-support/src/main/java/il/co/topq/integframework/support/threads/SingleHashThreadFactory.java @@ -0,0 +1,67 @@ +package il.co.topq.integframework.support.threads; + +import static java.util.Collections.synchronizedMap; +import static java.util.concurrent.Executors.defaultThreadFactory; + +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.ThreadFactory; + +/** + * This {@link ThreadFactory} constructs a new thread only for newly added + * {@link Runnable}s
+ * + * + * @author Aharon + * + */ +public final class SingleHashThreadFactory implements ThreadFactory { + final ThreadFactory bakingThreadFactory; + + /** + * Create a new instance + * + * @param bakedThreadFactory + * a factory to delegate creations to + * + */ + public SingleHashThreadFactory(ThreadFactory bakedThreadFactory) { + this.bakingThreadFactory = bakedThreadFactory; + } + + /** + * Create a new instance, delegate {@link #newThread(Runnable)} to + * {@link Executors#defaultThreadFactory()} if needed + */ + public SingleHashThreadFactory() { + this(defaultThreadFactory()); + } + + private final Map allThreads = synchronizedMap(new WeakHashMap()); + + /** + * Constructs a new {@link Thread} for the given {@link Runnable}, if it is + * the first time for it.
+ * On next invocations of this method, the returned thread is the one that + * provided for the first one.
+ * Note that the given runnable {@code (r1)} is regarded as old if + * another runnable {@code (r2)} was invoked on, and which
+ * {@code r1.hashCode() == r2.hashCode() && r1.equals(r2)}. + * + * @see Object#hashCode() + * @see Object#equals(Object) + * @see java.util.HashMap#get(Object) + * @see java.util.HashMap#put(Object, Object) + */ + @Override + public Thread newThread(Runnable r) { + synchronized (allThreads) { + Thread targetThread = allThreads.get(r); + if (targetThread == null) { + allThreads.put(r, targetThread = bakingThreadFactory.newThread(r)); + } + return targetThread; + } + } + +} diff --git a/integ-testng/.gitignore b/integ-testng/.gitignore new file mode 100644 index 0000000..29546b5 --- /dev/null +++ b/integ-testng/.gitignore @@ -0,0 +1,2 @@ +/target +/target/ diff --git a/integ-testng/pom.xml b/integ-testng/pom.xml index 3a4a705..408fe9a 100644 --- a/integ-testng/pom.xml +++ b/integ-testng/pom.xml @@ -1,12 +1,12 @@ - + + 4.0.0 integ-testng - org.uncommons + il.co.topq.integframework reportng - 1.1.2 + 1.1.41 org.testng @@ -18,7 +18,6 @@ com.google.inject guice 3.0 - test org.testng @@ -44,18 +43,38 @@ maven-compiler-plugin 2.3.2 - 1.6 - 1.6 + 1.7 + 1.7 - + + org.apache.maven.plugins + maven-surefire-plugin + + target/surefire/reportng + + + usedefaultlisteners + true + + + listener + org.uncommons.reportng.HTMLReporter + + + + **/*Tests.java + + + + il.co.topq.integframework integ-parent - 1.0.1-SNAPSHOT + 1.0.5-SNAPSHOT ../integ-parent - \ No newline at end of file + diff --git a/integ-testng/src/main/java/il/co/topq/integframework/AbstractModule.java b/integ-testng/src/main/java/il/co/topq/integframework/AbstractModule.java index 9638e0e..f70c33a 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/AbstractModule.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/AbstractModule.java @@ -12,33 +12,40 @@ public abstract class AbstractModule implements Module { * @see il.co.topq.integframework.Module#getActual() */ @Override - public Object getActual() { + public final Object getActual() { return actual; } - @SuppressWarnings("unchecked") - public T getActual(Class clazz) { - if (clazz.isInstance(actual)) { - return (T) getActual(); - } - throw new ClassCastException(actual.toString() + " is not castable to " + clazz.getName()); + /** + * Casts the actual object to the class or interface represented by the + * given {@code Class} object. + * + * @return the object after casting, or null if obj is null + * + * @throws ClassCastException + * if the object is not null and is not assignable to the type + * T. + */ + public final T getActual(Class clazz) { + return clazz.cast(getActual()); + } /* (non-Javadoc) * @see il.co.topq.integframework.Module#setActual(java.lang.Object) */ @Override - public void setActual(Object actual) { + public final void setActual(Object actual) { this.actual = actual; } @PostConstruct - public void initializeObject() throws Exception{ + public final void initializeObject() throws Exception { init(); } @PreDestroy - public void closeObject() throws Exception{ + public final void closeObject() throws Exception { close(); } diff --git a/integ-testng/src/main/java/il/co/topq/integframework/AbstractModuleImpl.java b/integ-testng/src/main/java/il/co/topq/integframework/AbstractModuleImpl.java index 3f52f10..7ef9c4e 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/AbstractModuleImpl.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/AbstractModuleImpl.java @@ -1,12 +1,23 @@ package il.co.topq.integframework; -public class AbstractModuleImpl extends AbstractModule { +public class AbstractModuleImpl extends AbstractModule implements Namefull { @Override public void init() throws Exception { } + @Override public void close() throws Exception { } + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + } diff --git a/integ-testng/src/main/java/il/co/topq/integframework/Named.java b/integ-testng/src/main/java/il/co/topq/integframework/Named.java new file mode 100644 index 0000000..3b555ed --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/Named.java @@ -0,0 +1,5 @@ +package il.co.topq.integframework; + +public interface Named { + public String getName(); +} \ No newline at end of file diff --git a/integ-testng/src/main/java/il/co/topq/integframework/Namefull.java b/integ-testng/src/main/java/il/co/topq/integframework/Namefull.java new file mode 100644 index 0000000..63d0990 --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/Namefull.java @@ -0,0 +1,5 @@ +package il.co.topq.integframework; + +public interface Namefull extends Named { + public void setName(String name); +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/NamingFunctions.java b/integ-testng/src/main/java/il/co/topq/integframework/NamingFunctions.java new file mode 100644 index 0000000..5189858 --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/NamingFunctions.java @@ -0,0 +1,12 @@ +package il.co.topq.integframework; + +import com.google.common.base.Function; + +public enum NamingFunctions implements Function { + getName { + @Override + public String apply(Named input) { + return input.getName(); + } + }; +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/AllItemsAre.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/AllItemsAre.java new file mode 100644 index 0000000..f4cdc3e --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/AllItemsAre.java @@ -0,0 +1,22 @@ +package il.co.topq.integframework.assertion; + +import com.google.common.base.Predicate; + +public class AllItemsAre extends AbstractAssertionLogic> { + + private final Predicate isTrue; + + public AllItemsAre(Predicate isTrue) { + this.isTrue = isTrue; + } + + @Override + public void doAssertion() { + boolean all = true; + for (T actualItem : actual) { + all = all && isTrue.apply(actualItem); + } + status = all; + } + +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/Assert.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/Assert.java index a41b7f9..57f1e50 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/assertion/Assert.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/Assert.java @@ -3,8 +3,11 @@ import il.co.topq.integframework.reporting.Reporter; import il.co.topq.integframework.reporting.Reporter.Color; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import com.google.common.base.Function; + /** * Class for comparing between actual and expected states * @@ -18,7 +21,7 @@ static public void assertStringContains(final String actual, final String expect throw new IllegalArgumentException("Actual can't be null"); } if (null == expected) { - throw new IllegalArgumentException("logic can't be null"); + throw new IllegalArgumentException("expected can't be null"); } if (!actual.contains(expected)) { fail(expected + " is not contained in " + actual); @@ -41,11 +44,17 @@ static public void assertStringContains(final String actual, final String expect * If exception occurced during assertion * @throws AssertionError * If assertion fails + * @deprecated actual value is set only once, loop has no meaning!
+ * use + * {@link #assertLogic(Object, Function, AbstractAssertionLogic, long, TimeUnit, long, TimeUnit)} + * instead */ - static public void assertLogic(final T actual, final AbstractAssertionLogic logic, final long timeout) throws TimeoutException { + @Deprecated + static public void assertLogic(final T actual, final AbstractAssertionLogic logic, final long timeout) + throws TimeoutException { long timeUp = System.currentTimeMillis() + timeout; do { - assertLogic(actual, logic,null); + assertLogic(actual, logic, null); if (!logic.status) { try { Thread.sleep(3000); @@ -53,12 +62,12 @@ static public void assertLogic(final T actual, final AbstractAssertionLogic< throw new TimeoutException("Assertion interrupted"); } } - } while (timeUp < System.currentTimeMillis() || !logic.status); + } while (timeUp < System.currentTimeMillis() && !logic.status); if (!logic.status) { throw new TimeoutException("Assertion failed"); } } - + /** * Execute the logic on the the actual object. * @@ -69,11 +78,9 @@ static public void assertLogic(final T actual, final AbstractAssertionLogic< * @throws AssertionError * If assertion fails */ - static public void assertLogic(final T actual, - final AbstractAssertionLogic logic) { + static public void assertLogic(final T actual, final AbstractAssertionLogic logic) { assertLogic(actual, logic, null); } - /** * Execute the logic on the the actual object. @@ -96,7 +103,7 @@ static public void assertLogic(final T actual, final AbstractAssertionLogic< throw new IllegalArgumentException("logic can't be null"); } if (null == listener) { - listener = new DefaultAssertionListener(); + listener = new DefaultAssertionListener<>(); } logic.setActual(actual); @@ -105,18 +112,124 @@ static public void assertLogic(final T actual, final AbstractAssertionLogic< if (logic.isStatus()) { listener.assertionPassed(actual, logic); } else { - Reporter.log("Assertion failed: " + logic.getTitle(), - logic.getMessage(), false); + // Reporter.log("Assertion failed: " + logic.getTitle(), + // logic.getMessage(), false); listener.assertionFailed(actual, logic); } } catch (Throwable t) { - Reporter.log("Assertion process failed: ", t); + // Reporter.log("Assertion process failed: ", t); listener.assertionFailed(actual, logic, t); } } - static public void assertLogicHappens(final T actual, - final AbstractAssertionLogic logic, final long timeout, + /** + * Execute the logic and repeating on the the + * actual object, as gained from the actualValueGenerator
+ * stop when either one of the following occurs: + *
    + *
  1. the actual object is null
  2. + *
  3. the thread was interrupted while sleeping
  4. + *
  5. timeout expires
  6. + *
+ * + * @param + * the type of actual to examine + * @param + * the type of the resource to gain the actual value from + * @param resource + * a {@link il.co.topq.integframework.Module} or another kind of + * external {@link Object}, from which the actual value is + * gained. + * @param actualValueGenerator + * a function from the resource above to the actual value- on + * which to perform assertion on + * @param logic + * Logic to operate on the actual object + * @param timeout + * maximum time for this operation + * @param timeoutUnit + * time unit for the parameter above + * @param interval + * time to sleep between assertions + * @param intervalUnit + * time unit for the parameter above + * @throws AssertionError + * If assertion fails + * @return true if assertion finished due to timeout i.e. the assertion + * passed on all invocations of + * {@link AbstractAssertionLogic#doAssertion()} + */ + static public void assertLogic(R resource, final Function actualValueGenerator, AbstractAssertionLogic logic, + long timeout, TimeUnit timeoutUnit, long interval, TimeUnit intervalUnit) { + assertLogic(resource, actualValueGenerator, logic, new DefaultAssertionListener(), timeout, timeoutUnit, interval, + intervalUnit); + } + + /** + * Execute the logic and repeating on the the + * actual object, as gained from the actualValueGenerator
+ * stop when either one of the following occurs: + *
    + *
  1. the actual object is null
  2. + *
  3. the thread was interrupted while sleeping
  4. + *
  5. timeout expires
  6. + *
+ * + * @param
+ * the type of actual to examine + * @param + * the type of the resource to gain the actual value from + * @param resource + * a {@link il.co.topq.integframework.Module} or another kind of + * external {@link Object}, from which the actual value is + * gained. + * @param actualValueGenerator + * a function from the resource above to the actual value- on + * which to perform assertion on + * @param logic + * Logic to operate on the actual object + * @param listener + * an {@link AssertionListener} for ssertion events. + * @param timeout + * maximum time for this operation + * @param timeoutUnit + * time unit for the parameter above + * @param interval + * time to sleep between assertions + * @param intervalUnit + * time unit for the parameter above + * @throws AssertionError + * If assertion fails + * @return true if assertion finished due to timeout i.e. the assertion + * passed on all invocations of + * {@link AbstractAssertionLogic#doAssertion()} + */ + static public void assertLogic(R resource, final Function actualValueGenerator, AbstractAssertionLogic logic, + AssertionListener listener, long timeout, TimeUnit timeoutUnit, long interval, TimeUnit intervalUnit) { + long end = System.currentTimeMillis() + timeoutUnit.toMillis(timeout); + A actual; + do { + actual = actualValueGenerator.apply(resource); + if (actual == null) { + listener.assertionFailed(actual, logic, new NullPointerException(logic.getMessage())); + } + Assert.assertLogic(actual, logic, listener); + try { + Thread.sleep(intervalUnit.toMillis(interval)); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + listener.assertionFailed(actual, logic); + } + } while (end < System.currentTimeMillis()); + listener.assertionPassed(actual, logic); + } + + /** + * @deprecated use + * {@link Assert#assertLogic(Object, Function, AbstractAssertionLogic, long, TimeUnit, long, TimeUnit) + */ + @Deprecated + static public void assertLogicHappens(final T actual, final AbstractAssertionLogic logic, final long timeout, boolean silent) throws TimeoutException { assertLogic(actual, logic, timeout); diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/AssertionListener.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/AssertionListener.java index 2a3fa5f..deff26b 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/assertion/AssertionListener.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/AssertionListener.java @@ -1,7 +1,23 @@ package il.co.topq.integframework.assertion; +/** + * + * Listen to assertion pseodo-events: + *
    + *
  1. pass
  2. + *
  3. fail
  4. + *
  5. exception thrown
  6. + *
+ * + * @author Aharon Hacmon + * + * @param + * the type of actual. you may get it's value + */ public interface AssertionListener { public void assertionPassed(final T actual, final AbstractAssertionLogic logic); + public void assertionFailed(final T actual, final AbstractAssertionLogic logic); + public void assertionFailed(final T actual, final AbstractAssertionLogic logic, Throwable t); } \ No newline at end of file diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/CollectionAssertion.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/CollectionAssertion.java index 7c245c9..84e9f60 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/assertion/CollectionAssertion.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/CollectionAssertion.java @@ -1,21 +1,26 @@ package il.co.topq.integframework.assertion; +import static il.co.topq.integframework.utils.StringUtils.either; +import static il.co.topq.integframework.utils.StringUtils.isEmpty; +import il.co.topq.integframework.Named; import il.co.topq.integframework.reporting.Reporter; -import il.co.topq.integframework.utils.StringUtils; +import il.co.topq.integframework.reporting.Reporter.Color; +import il.co.topq.integframework.utils.Formatter; +import il.co.topq.integframework.utils.FormattingComparator; +import il.co.topq.integframework.utils.FormattingComparatorDecorator; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import java.util.*; import org.testng.xml.XmlSuite; +import com.google.common.base.Optional; + public class CollectionAssertion extends AbstractAssertionLogic> { private String expectedTitle = "", actualTitle = ""; final protected List expected; private List singlesInActual, singlesInExpected; + private long maxMismatchesToReport = -1, maxNotFoundToReport = -1, maxUnexpectedToReport = -1; private static final class PairOfMatches { final E actual, expected; @@ -26,24 +31,25 @@ public PairOfMatches(E actual, E expected) { } } - protected boolean keepMatches = true; + protected boolean keepMatches = false; private List> matches; protected void addMatch(E actual, E expected) { if (keepMatches) { if (matches == null) { - matches = new ArrayList>(); + matches = new ArrayList<>(); } - matches.add(new PairOfMatches(actual, expected)); + matches.add(new PairOfMatches<>(actual, expected)); } } protected boolean allItems = false, exitIfSizeDoesNotMatch = true; - private List> comparators; + private List> comparators; + private Formatter formatter; - public CollectionAssertion(List expected) { - this.expected = new ArrayList(expected); + public CollectionAssertion(Collection expected) { + this.expected = new ArrayList<>(expected); } public CollectionAssertion containsAllItems() { @@ -56,6 +62,21 @@ public CollectionAssertion dontExitIfSizeDoesNotMatch() { return this; } + public CollectionAssertion maxMismatchesToReport(long max) { + this.maxMismatchesToReport = max; + return this; + } + + public CollectionAssertion maxNotFoundToReport(long max) { + this.maxNotFoundToReport = max; + return this; + } + + public CollectionAssertion maxUnexpectedToReport(long max) { + this.maxUnexpectedToReport = max; + return this; + } + public CollectionAssertion withActualTitled(String title) { actualTitle = title; return this; @@ -74,11 +95,11 @@ public CollectionAssertion andKeepMatchesForFurtherAnalysis() { @Override public String getTitle() { StringBuilder titleBuilder = new StringBuilder("all items"); - if (!StringUtils.isEmpty(expectedTitle)) { + if (!isEmpty(expectedTitle)) { titleBuilder.append(" from ").append(expectedTitle); } titleBuilder.append(" should exists"); - if (!StringUtils.isEmpty(actualTitle)) { + if (!isEmpty(actualTitle)) { titleBuilder.append(" in ").append(actualTitle); } if (allItems) { @@ -87,31 +108,36 @@ public String getTitle() { return titleBuilder.toString(); } + @Override public String getMessage() { return status ? "passed" : "failed"; } @Override public void doAssertion() { - Comparator comparator; + FormattingComparator comparator; if (this.comparators == null) { comparator = simpleComparator; } else { if (comparators.size() == 1) { comparator = comparators.get(0); } else { - comparator = new CombinedComparator(comparators); + comparator = new FormattingComparatorDecorator<>(new CombinedComparator<>(comparators)); } } + Formatter formatter = Optional.fromNullable(this.formatter).or(comparator); + if (keepMatches && matches == null || !keepMatches) { message = ""; - singlesInExpected = new ArrayList(expected.size()); - singlesInActual = new ArrayList(actual.size()); + singlesInExpected = new ArrayList<>(expected.size()); + singlesInActual = new ArrayList<>(actual.size()); if (!allItems) { if (expected.size() > actual.size()) { status = false; - Reporter.log(new AssertionError(new StringBuilder("Size of actual items is ").append(actual.size()) + + Reporter.logToFile(new AssertionError(new StringBuilder("size of ") + .append(either(actualTitle).or("actual items")).append(" ").append(actual.size()) .append(", should be at least ").append(expected.size()).append("\n"))); if (exitIfSizeDoesNotMatch) { return; @@ -120,8 +146,9 @@ public void doAssertion() { singlesInActual.addAll(actual); } else { if (expected.size() != actual.size()) { - Reporter.log(new AssertionError(new StringBuilder("Size of actual items is ").append(actual.size()) - .append("instead of ").append(expected.size()).append("\n"))); + Reporter.logToFile(new AssertionError(new StringBuilder("size of ") + .append(either(actualTitle).or("actual items")).append(" ").append(actual.size()) + .append(" instead of ").append(expected.size()).append("\n"))); status = false; if (exitIfSizeDoesNotMatch) { return; @@ -132,8 +159,8 @@ public void doAssertion() { List sortedActual = actual.subList(0, actual.size()); List sortedExpected = expected.subList(0, expected.size()); - Collections.sort(sortedActual, comparator); - Collections.sort(sortedExpected, comparator); + Collections.sort(sortedActual, sortingComparator(comparator, either(actualTitle).or("actual"))); + Collections.sort(sortedExpected, sortingComparator(comparator, either(actualTitle).or("expected"))); for (int iactual = 0, iexpected = 0; (iactual < sortedActual.size() || !allItems) && (iexpected < sortedExpected.size());) { if (iactual >= sortedActual.size()) { @@ -161,18 +188,24 @@ public void doAssertion() { iactual++; } } - + long singlesCounter = 0; for (E e : singlesInExpected) { - Reporter.log(new AssertionError(new StringBuilder(e.toString()).append(" was expected but not found"))); - + Reporter.logToFile("Item not found", + new AssertionError(new StringBuilder(formatter.toString(e)).append(" was expected but not found"))); + if (++singlesCounter > maxNotFoundToReport) { + break; + } } + singlesCounter = 0; for (E e : singlesInActual) { - StringBuilder itemFound = new StringBuilder(e.toString()).append(" was found"); - + StringBuilder itemFound = new StringBuilder(formatter.toString(e)).append(" was found"); if (!allItems) { + if (++singlesCounter > maxUnexpectedToReport) { + break; + } itemFound.append(" unexpectedly"); - Reporter.log(new AssertionError(itemFound)); + Reporter.logToFile("Unexpected item found", new AssertionError(itemFound)); } else { Reporter.log(itemFound.toString(), XmlSuite.DEFAULT_VERBOSE + 1); } @@ -181,29 +214,45 @@ public void doAssertion() { status = singlesInExpected.isEmpty() && (singlesInActual.isEmpty() || !allItems); if (!status) { - message = "Total items not found: " + singlesInExpected.size() + "\n"; + message = "Total items not found: " + singlesInExpected.size(); if (allItems) { - message = message + "Total unexpected items found: " + singlesInActual.size() + "\n"; + message = message + "\nTotal unexpected items found: " + singlesInActual.size() + "\n"; } } } else if (matches != null) { status = true; - Reporter.step("Validating matches data:\n"); + Named matchName; + if (formatter instanceof Named){ + matchName = (Named) formatter; + } else if (comparator instanceof Named) { + matchName = (Named) comparator; + } else { + matchName = new Named() { + @Override + public String getName() { + return ""; + } + }; + } + + Reporter.log("Validating matches data using " + matchName.getName(), XmlSuite.DEFAULT_VERBOSE + 1); long mismatchCounter = 0; + String itemMismatchTitle = "Item mismatch when comparing " + matchName.getName(); for (PairOfMatches match : matches) { if (comparator.compare(match.actual, match.expected) != 0) { status = false; - StringBuilder itemMismatch = new StringBuilder("The item [").append(match.actual) - .append("]\n, which was acually found, did not match the expected item \n[") - .append(match.expected.toString()).append("]\n when comparing ").append(comparator.toString()) - .append("\n"); - Reporter.log(new AssertionError(itemMismatch)); - mismatchCounter++; + StringBuilder itemMismatch = new StringBuilder("The item:\n[").append(formatter.toString(match.actual)) + .append("]\nwhich was acually found, did not match the expected item\n[") + .append(formatter.toString(match.expected)).append("]"); + if (++mismatchCounter <= maxMismatchesToReport) { + Reporter.logToFile(itemMismatchTitle, itemMismatch.toString(), Color.RED); + } } } - message = message + "Total reproccessed items:" + matches.size() + "\n"; + message = "Total reproccessed items:" + matches.size() + "\n"; if (mismatchCounter > 0) { - message = message + "Total mismatch data items found:" + mismatchCounter + "\n"; + message = message + "Total mismatch data items found:" + mismatchCounter + "\n when comparing " + + matchName.getName(); } } @@ -211,14 +260,25 @@ public void doAssertion() { public CollectionAssertion withComparator(Comparator comparator) { if (this.comparators == null) { - comparators = new ArrayList>(); + comparators = new ArrayList<>(); } - comparators.add(comparator); + FormattingComparator formattingComparator; + if (comparator instanceof FormattingComparator) { + formattingComparator = (FormattingComparator) comparator; + } else { + formattingComparator = new FormattingComparatorDecorator<>(comparator); + } + comparators.add(formattingComparator); + return this; + } + + public CollectionAssertion withFormatter(Formatter formatter) { + this.formatter = formatter; return this; } @SafeVarargs - public CollectionAssertion compareWith(Comparator... comparators) { + public final CollectionAssertion compareWith(Comparator... comparators) { return compareWith(Arrays.asList(comparators)); } @@ -235,7 +295,8 @@ public CollectionAssertion compareWith(List> comparators) { * @param comparators * @return */ - public CollectionAssertion andNowCompareWith(Comparator... comparators) { + @SafeVarargs + public final CollectionAssertion andNowCompareWith(Comparator... comparators) { this.comparators = null; return andNowCompareWith(Arrays.asList(comparators)); } @@ -254,8 +315,7 @@ public CollectionAssertion andNowCompareWith(List> comparators) return this; } - protected final Comparator simpleComparator = new Comparator() { - + protected final FormattingComparator simpleComparator = new FormattingComparatorDecorator(new Comparator() { @Override public int compare(E o1, E o2) { if (o1 instanceof Comparable) { @@ -272,6 +332,24 @@ public int compare(E o1, E o2) { return Integer.compare(o1.hashCode(), o2.hashCode()); } } + + }) { + @Override + public String toString() { + return "Simple comparator"; + }; }; + protected final Comparator sortingComparator(final Comparator delegate, final String title) { + return new Comparator() { + @Override + public int compare(E o1, E o2) { + int res = delegate.compare(o1, o2); + if (res == 0) { + Assert.fail("Duplicates found in " + title); + } + return res; + } + }; + } } diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/CombinedComparator.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/CombinedComparator.java index 1e46972..b48914d 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/assertion/CombinedComparator.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/CombinedComparator.java @@ -6,17 +6,17 @@ public class CombinedComparator implements Comparator { - private final List> comparators; + private final List> comparators; private String lastFailedComparatorName; - public CombinedComparator(List> comparators) { + public CombinedComparator(List> comparators) { this.comparators = comparators.subList(0, comparators.size()); } @Override public int compare(T o1, T o2) { int comparisonResult = 0; - Iterator> comparatorsIterator = this.comparators.iterator(); + Iterator> comparatorsIterator = this.comparators.iterator(); while (comparisonResult == 0 && comparatorsIterator.hasNext()) { Comparator currComparator = comparatorsIterator.next(); comparisonResult = currComparator.compare(o1, o2); diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/ComparableAssertion.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/ComparableAssertion.java new file mode 100644 index 0000000..5078598 --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/ComparableAssertion.java @@ -0,0 +1,56 @@ +package il.co.topq.integframework.assertion; + +import il.co.topq.integframework.utils.Formatter; +import il.co.topq.integframework.utils.FormatterImpl; + +public class ComparableAssertion> extends AbstractAssertionLogic { + + private final T expected; + + private String titleOfExaminedObject = "value"; + private Formatter formatter = new FormatterImpl<>(); + + private final CompareMethod compareMethod; + + public ComparableAssertion(T expected, CompareMethod compareMethod) { + super(); + this.expected = expected; + this.compareMethod = compareMethod; + } + + public ComparableAssertion(CompareMethod compareMethod, T expected) { + this(expected, compareMethod); + } + + public ComparableAssertion examinedObjectTitled(String title) { + this.titleOfExaminedObject = title; + return this; + + } + + public ComparableAssertion formatObjectWith(Formatter formatter) { + this.formatter = formatter; + return this; + } + + @Override + public void doAssertion() { + status = compareMethod.compare(actual, expected); + StringBuilder titleBuilder = new StringBuilder(); + titleBuilder.append("Actual ").append(titleOfExaminedObject).append(" [").append(formatter.toString(actual)) + .append("] is "); + if (!status) { + titleBuilder.append("NOT "); + } + titleBuilder.append(compareMethod.toString()).append(" [").append(formatter.toString(expected)).append("]"); + this.title = titleBuilder.toString(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.titleOfExaminedObject).append(" to be "); + builder.append(compareMethod.toString()).append(" ").append(formatter.toString(expected)); + return builder.toString(); + } + +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/CompareMethod.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/CompareMethod.java new file mode 100644 index 0000000..cdf4bcf --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/CompareMethod.java @@ -0,0 +1,117 @@ +package il.co.topq.integframework.assertion; + +import com.google.common.base.Predicate; + +public enum CompareMethod { + + BIGGER { + @Override + public > boolean compare(T o1, T o2) { + return o1.compareTo(o2) > 0; + } + }, + AFTER { + @Override + public > boolean compare(T o1, T o2) { + return BIGGER.compare(o1, o2); + } + }, + BIGGER_OR_EQUALS { + @Override + public > boolean compare(T o1, T o2) { + return o1.compareTo(o2) >= 0; + } + }, + AFTER_OR_WHEN { + @Override + public > boolean compare(T o1, T o2) { + return BIGGER_OR_EQUALS.compare(o1, o2); + } + }, + EQUALS { + @Override + public > boolean compare(T o1, T o2) { + return o1.compareTo(o2) == 0; + } + }, + WHEN { + @Override + public > boolean compare(T o1, T o2) { + return EQUALS.compare(o1, o2); + } + + }, + SMALLER_OR_EQUALS { + @Override + public > boolean compare(T o1, T o2) { + return o1.compareTo(o2) <= 0; + } + }, + BEFORE_OR_WHEN { + @Override + public > boolean compare(T o1, T o2) { + return SMALLER_OR_EQUALS.compare(o1, o2); + } + }, + SMALLER { + @Override + public > boolean compare(T o1, T o2) { + return o1.compareTo(o2) < 0; + } + }, + BEFORE { + @Override + public > boolean compare(T o1, T o2) { + return SMALLER.compare(o1, o2); + } + + }; + @Override + public String toString() { + switch (this) { + case BIGGER: + return "bigger then"; + case AFTER: + return "after"; + case BIGGER_OR_EQUALS: + return "bigger then or equals to"; + case AFTER_OR_WHEN: + return "after or when"; + case EQUALS: + return "equals to"; + case WHEN: + return "when"; + case SMALLER_OR_EQUALS: + return "smaller then or equals to"; + case BEFORE_OR_WHEN: + return "before or when"; + case SMALLER: + return "smaller then"; + case BEFORE: + return "before"; + default: + return null; + } + }; + + public abstract > boolean compare(T o1, T o2); + + public final > Predicate to(final T that) { + return than(that); + } + + public final > Predicate than(final T that) { + final CompareMethod me = this; + return new Predicate() { + + @Override + public boolean apply(T t) { + return me.compare(t, that); + } + }; + } + + public static final > boolean is(T one, CompareMethod compare, T another) { + return compare.compare(one, another); + } +} \ No newline at end of file diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/DefaultAssertionListener.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/DefaultAssertionListener.java index 951264c..b895baa 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/assertion/DefaultAssertionListener.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/DefaultAssertionListener.java @@ -1,5 +1,7 @@ package il.co.topq.integframework.assertion; +import il.co.topq.integframework.reporting.Reporter; + public class DefaultAssertionListener implements AssertionListener{ @Override @@ -9,12 +11,14 @@ public void assertionPassed(T actual, AbstractAssertionLogic logic) { @Override public void assertionFailed(T actual, AbstractAssertionLogic logic) { - org.testng.Assert.fail(logic.message); + Reporter.log("Assertion failed: " + logic.getTitle(), logic.getMessage(), false); + org.testng.Assert.fail(logic.getTitle()); } @Override public void assertionFailed(T actual, AbstractAssertionLogic logic, Throwable t) { - org.testng.Assert.fail(logic.message, t); + Reporter.log("Assertion process failed: ", t); + org.testng.Assert.fail(logic.getTitle(), t); } }; \ No newline at end of file diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/FailSafeAssertionListener.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/FailSafeAssertionListener.java index f5256ab..ef7b1e8 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/assertion/FailSafeAssertionListener.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/FailSafeAssertionListener.java @@ -3,6 +3,8 @@ */ package il.co.topq.integframework.assertion; +import il.co.topq.integframework.utils.StringUtils; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -23,13 +25,13 @@ public void assertionPassed(T actual, AbstractAssertionLogic logic) { } - protected final List suppressed = new ArrayList(); + protected final List suppressed = new ArrayList<>(); /* (non-Javadoc) * @see il.co.topq.integframework.assertion.AssertionListener#assertionFailed(java.lang.Object, il.co.topq.integframework.assertion.AbstractAssertionLogic) */ @Override public void assertionFailed(T actual, AbstractAssertionLogic logic) { - suppressed.add(new AssertionError(logic.message)); + suppressed.add(new AssertionError(StringUtils.either(logic.message).or(logic.getTitle()))); } /* (non-Javadoc) @@ -38,12 +40,27 @@ public void assertionFailed(T actual, AbstractAssertionLogic logic) { @Override public void assertionFailed(T actual, AbstractAssertionLogic logic, Throwable t) { - suppressed.add(new AssertionError(logic.message, t)); + suppressed.add(new AssertionError(StringUtils.either(logic.message).or(logic.getTitle()), t)); } public Iterator getSuppressedThrowables(){ - return new ArrayList(suppressed).iterator(); + return new ArrayList<>(suppressed).iterator(); + } + + public Throwable getLastSuppressedThrowable() { + if (suppressed.size() > 0) { + return suppressed.get(suppressed.size() - 1); + } + return null; } + public Throwable getRootSuppressedThrowable() { + Throwable t; + for (t = getLastSuppressedThrowable(); t != null && t.getCause() != null + && (t.getCause() != t || !(t instanceof AssertionError)); t = t + .getCause()) + ;/* DoNothing */ + return t; + } } diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/FindTextAssertion.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/FindTextAssertion.java index 864b168..8412b7a 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/assertion/FindTextAssertion.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/FindTextAssertion.java @@ -6,15 +6,13 @@ /** * Asserts that given text exists in an actual text * - * @author Ita Agmon + * @author Itai Agmon * */ public class FindTextAssertion extends AbstractAssertionLogic { private final String expectedText; - private String actualText; - private final boolean isRegex; /** @@ -37,7 +35,7 @@ public FindTextAssertion(String expectedText) { @Override public void doAssertion() { - if (actualText == null) { + if (actual == null) { status = false; title = "Actual text can't be null"; return; @@ -51,7 +49,7 @@ public void doAssertion() { if (isRegex) { try { Pattern pattern = Pattern.compile(expectedText); - Matcher matcher = pattern.matcher(actualText); + Matcher matcher = pattern.matcher(actual); status = matcher.find(); } catch (Throwable t) { @@ -59,30 +57,17 @@ public void doAssertion() { } } else { - status = actualText.contains(expectedText); - } - if (status) { - title = "Expected text was found in actual text"; - } else { - title = "Expected text was not found in actual text"; + status = actual.contains(expectedText); } + + title = "Expected text [" + expectedText + "] was " + (status ? "" : "not ") + "found in actual text [" + actual + "]"; + StringBuilder messageBuilder = new StringBuilder(); messageBuilder.append("Text to find: \n"); messageBuilder.append(expectedText).append("\n\n"); messageBuilder.append("Actual text\n"); - messageBuilder.append(actualText); + messageBuilder.append(actual); message = messageBuilder.toString(); } - - - - @Override - public void setActual(String actual) { - this.actual = actual; - if (actual != null) { - actualText = (String) actual; - } - } - } diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/LongCompareAssertion.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/LongCompareAssertion.java new file mode 100644 index 0000000..08510c5 --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/LongCompareAssertion.java @@ -0,0 +1,82 @@ +package il.co.topq.integframework.assertion; + +public class LongCompareAssertion extends AbstractAssertionLogic { + + + private final long expected; + + private long actualLong; + + private final CompareMethod compareMethod; + + public LongCompareAssertion(long expected, CompareMethod compareMethod) { + super(); + this.expected = expected; + this.compareMethod = compareMethod; + } + + @Override + public void doAssertion() { + status = true; + switch (compareMethod) { + case BIGGER: + if (actualLong > expected) { + title = "Actual number " + actualLong + " is bigger then " + expected; + } else { + title = "Actual number " + actualLong + " is NOT bigger then " + expected; + status = false; + } + break; + case BIGGER_OR_EQUALS: + if (actualLong >= expected) { + title = "Actual number " + actualLong + " is bigger or equals to " + expected; + } else { + title = "Actual number " + actualLong + " is NOT bigger or equals to " + expected; + status = false; + } + + break; + case EQUALS: + if (actualLong == expected) { + title = "Actual number " + actualLong + " is equals to " + expected; + } else { + title = "Actual number " + actualLong + " is NOT equals to " + expected; + status = false; + } + break; + + case SMALLER_OR_EQUALS: + if (actualLong <= expected) { + title = "Actual number " + actualLong + " is smaller or equals to " + expected; + } else { + title = "Actual number " + actualLong + " is NOT smaller or equals to " + expected; + status = false; + } + break; + case SMALLER: + if (actualLong < expected) { + title = "Actual number " + actualLong + " is smaller then " + expected; + } else { + title = "Actual number " + actualLong + " is NOT smaller then " + expected; + status = false; + } + break; + + default: + break; + } + + } + + + /** + * Sets the actual object to perfrom assertion on + */ + @Override + public void setActual(Long actual) { + if (actual != null) { + actualLong = actual; + } + } + +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/NumberCompareAssertion.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/NumberCompareAssertion.java index 43126a3..c8c8abd 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/assertion/NumberCompareAssertion.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/NumberCompareAssertion.java @@ -2,11 +2,6 @@ public class NumberCompareAssertion extends AbstractAssertionLogic { - public enum CompareMethod { - BIGGER, BIGGER_OR_EQUALS, EQUALS, SMALLER_OR_EQUALS, SMALLER - - } - private final int expected; private int actualInt; diff --git a/integ-testng/src/main/java/il/co/topq/integframework/assertion/PredicateAssertionLogic.java b/integ-testng/src/main/java/il/co/topq/integframework/assertion/PredicateAssertionLogic.java new file mode 100644 index 0000000..9366ea1 --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/assertion/PredicateAssertionLogic.java @@ -0,0 +1,19 @@ +package il.co.topq.integframework.assertion; + +import com.google.common.base.Predicate; + +public class PredicateAssertionLogic extends AbstractAssertionLogic { + + private final Predicate isTrue; + + public PredicateAssertionLogic(Predicate isTrue) { + this.isTrue = isTrue; + } + + @Override + public void doAssertion() { + message = isTrue.toString(); + status = isTrue.apply(actual); + } + +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/issue/IssueType.java b/integ-testng/src/main/java/il/co/topq/integframework/issue/IssueType.java new file mode 100644 index 0000000..eefbe7c --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/issue/IssueType.java @@ -0,0 +1,10 @@ +package il.co.topq.integframework.issue; + +public enum IssueType { + /** should have pass, but failed */ + PASS, + /** + * should have fail. put this on negative tests that passes + */ + FAIL +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/issue/KnownIssue.java b/integ-testng/src/main/java/il/co/topq/integframework/issue/KnownIssue.java new file mode 100644 index 0000000..cf854fc --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/issue/KnownIssue.java @@ -0,0 +1,24 @@ +package il.co.topq.integframework.issue; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface KnownIssue { + public @interface KnownIssues { + KnownIssue[] value(); + } + + String issue() default "Known Issue"; + + Class throwableType() default AssertionError.class; + + IssueType type() default IssueType.PASS; + + String messageMustMatch() default ".*"; + + long dueTo() default -1; +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/issue/KnownIssueTestListener.java b/integ-testng/src/main/java/il/co/topq/integframework/issue/KnownIssueTestListener.java new file mode 100644 index 0000000..88d47b9 --- /dev/null +++ b/integ-testng/src/main/java/il/co/topq/integframework/issue/KnownIssueTestListener.java @@ -0,0 +1,98 @@ +package il.co.topq.integframework.issue; + +import static com.google.common.collect.Lists.newArrayList; +import static il.co.topq.integframework.assertion.CompareMethod.BEFORE; +import static il.co.topq.integframework.assertion.CompareMethod.is; +import static il.co.topq.integframework.issue.IssueType.PASS; +import static org.testng.ITestResult.FAILURE; +import static org.testng.ITestResult.SUCCESS; +import static org.testng.ITestResult.SUCCESS_PERCENTAGE_FAILURE; +import il.co.topq.integframework.issue.KnownIssue.KnownIssues; +import il.co.topq.integframework.reporting.Reporter; + +import java.util.List; + +import org.testng.ITestContext; +import org.testng.ITestListener; +import org.testng.ITestResult; + +public class KnownIssueTestListener implements ITestListener { + + @Override + public void onTestStart(ITestResult result) { + // TODO Auto-generated method stub + + } + + @Override + public void onTestSuccess(ITestResult result) { + // handleIssue(result, IssueType.FAIL); + // TBD: negative tests + + } + + @Override + public void onTestFailure(ITestResult result) { + handleIssue(result, IssueType.PASS); + } + + protected static void handleIssue(ITestResult result, IssueType whatItShouldHave) { + KnownIssue issue = result.getMethod().getConstructorOrMethod().getMethod().getAnnotation(KnownIssue.class); + KnownIssues issues = result.getMethod().getConstructorOrMethod().getMethod().getAnnotation(KnownIssues.class); + + List allIssues = newArrayList(); + allIssues.add(issue); + if (issues != null) { + allIssues.addAll(newArrayList(issues.value())); + } + + boolean isKnownIssue = false; + for (KnownIssue knownIssue : allIssues) { + if (knownIssue != null) { + if (knownIssue.type().equals(whatItShouldHave)) { + if (knownIssue.throwableType().isInstance(result.getThrowable())) { + if (result.getThrowable().getMessage().matches(knownIssue.messageMustMatch())) { + boolean passedDueDate; + if (knownIssue.dueTo() == -1) { + passedDueDate = false; + } else { + passedDueDate = is(knownIssue.dueTo(), BEFORE, System.currentTimeMillis()); + } + Reporter.log(knownIssue.issue(), result.getThrowable(), passedDueDate ? FAILURE + : SUCCESS_PERCENTAGE_FAILURE); + isKnownIssue = true; + } + } + } + } + } + if (isKnownIssue) { + result.setStatus((whatItShouldHave == PASS) ? SUCCESS : FAILURE); + } + } + + @Override + public void onTestSkipped(ITestResult result) { + // TODO Auto-generated method stub + + } + + @Override + public void onTestFailedButWithinSuccessPercentage(ITestResult result) { + // TODO Auto-generated method stub + + } + + @Override + public void onStart(ITestContext context) { + // TODO Auto-generated method stub + + } + + @Override + public void onFinish(ITestContext context) { + // TODO Auto-generated method stub + + } + +} diff --git a/integ-testng/src/main/java/il/co/topq/integframework/reporting/Reporter.java b/integ-testng/src/main/java/il/co/topq/integframework/reporting/Reporter.java index 0a0de38..8b04e76 100644 --- a/integ-testng/src/main/java/il/co/topq/integframework/reporting/Reporter.java +++ b/integ-testng/src/main/java/il/co/topq/integframework/reporting/Reporter.java @@ -1,17 +1,22 @@ package il.co.topq.integframework.reporting; +import il.co.topq.integframework.utils.RandomUtils; import il.co.topq.integframework.utils.StringUtils; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random; +import java.util.Set; import org.apache.commons.io.FileUtils; import org.testng.ITestResult; +import com.google.common.collect.Sets; + /** * Wrapper for the TestNG HTML report * @@ -28,7 +33,7 @@ public class Reporter extends org.testng.Reporter { } public enum Style { - REGULAR(""), BOLD("b"), ITALIC("i"), PLAINTEXT("pre"), EMPHASIZED("em"), STRIKETHROUGH("strike"); + REGULAR(""), BOLD("b"), ITALIC("i"), PLAINTEXT("pre"), EMPHASIZED("em"), STRIKETHROUGH("strike"), CENTER("center"); private final String value; @@ -39,7 +44,13 @@ private Style(String value) { } public enum Color { - RED, BLUE, YELLOW, GREEN + RED, BLUE, YELLOW { + @Override + public String toString() { + return "gold"; + } + }, + GREEN } public void logEscapeHtml(String s) { @@ -52,57 +63,163 @@ public void logEscapeHtml(String s) { public static void log(String s) { log(s, false, null, null); } - + public static void log(String s, boolean logToStandardOut) { log(s, logToStandardOut, null, null); } - + public static void log(final String s, Style style) { log(s, false, style, null); } - + public static void log(final String s, Color color) { log(s, false, null, color); } - + public static void log(final String s, Style style, Color color) { log(s, false, style, color); } public static void step(String step) { + System.err.println(step); log(step, Style.EMPHASIZED, Color.BLUE); } + + static Set packagesToFilter = Sets.newHashSet(); + + public static void filterPackagesOnThrowables(String packageName) { + if (StringUtils.isEmpty(packageName)) { + packagesToFilter.clear();; + } else { + packagesToFilter.add(packageName); + } + } + + public static void filterPackagesOnThrowables(Set packages) { + for (String packageName : packages) { + filterPackagesOnThrowables(packageName); + if (StringUtils.isEmpty(packageName)) { + return; + } + } + } + + /** + * report an error or exception + * + * @param t + * the {@link Throwable} to be reported + */ public static void log(final Throwable t) { log(t.getMessage(), t); } + /** + * report an error or exception + * + * @param t + * @param status + * a status to set.
+ * shuold be either {@link ITestResult#SUCCESS}, + * {@link ITestResult#FAILURE} or + * {@link ITestResult#SUCCESS_PERCENTAGE_FAILURE}
+ * default is {@link ITestResult#FAILURE} + * + */ + public static void log(final Throwable t, int status) { + log(t.getMessage(), t, status); + } + + /** + * report an error or exception + * + * @param title + * the title of the link to put + * @param t + * the {@link Throwable} to be reported + */ public static void log(final String title, final Throwable t) { - log(title, StringUtils.getStackTrace(t), false); + log(title, t, packagesToFilter); + } + + /** + * report an error or exception + * + * @param title + * the title of the link to put + * @param t + * the {@link Throwable} to be reported + * @param status + * a status to set.
+ * shuold be either {@link ITestResult#SUCCESS}, + * {@link ITestResult#FAILURE} or + * {@link ITestResult#SUCCESS_PERCENTAGE_FAILURE}
+ * default is {@link ITestResult#FAILURE} + */ + public static void log(final String title, final Throwable t, int status) { + log(title, t, packagesToFilter, status); + } + + /** + * report an error or exception + * + * @param title + * the title of the link to put + * @param t + * the {@link Throwable} to be reported + * @param packagesToFilter + * a set of packages (as can be gained from + * {@link Class#getPackage()}) + * {@link StackTraceElement#getClassName()} to be omitted from + * the reported StackTrace of t + */ + public static void log(final Throwable t, final Set packagesToFilter) { + log(t.getMessage(), t, packagesToFilter); + } + + public static void log(final String title, final Throwable t, final Set packagesToFilter) { + log(title, StringUtils.getStackTrace(t, packagesToFilter), false); + } + + public static void log(final String title, final Throwable t, final Set packagesToFilter, int status) { + log(title, StringUtils.getStackTrace(t, packagesToFilter), status); + } + + public static void logToFile(Throwable t) { + logToFile(t.getMessage(), t); + } + + public static void logToFile(final String title, Throwable t) { + logToFile(title, t, packagesToFilter); + } + + public static void logToFile(final String title, final Throwable t, final Set packagesToFilter) { + logToFile(title, StringUtils.getStackTrace(t, packagesToFilter), Color.RED); } + protected static DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS"); + private static Random random = new Random(System.currentTimeMillis()); + /** * Appending s to the report with time stamp * * @param s */ public static void log(String s, boolean logToStandardOut, Style style, Color color) { - if(!s.startsWith(""); + toggleElement.append("").append(title).append("
"); + + // Creating body + toggleElement.append(""); + log(toggleElement.toString(), false, null, null); + } + + public synchronized static void startLogToggle(String title, Color color) { if (inToggle) { return; } @@ -191,19 +405,19 @@ public static void startLogToggle(String title, Color color) { title = "link"; } StringBuilder toggleElement = new StringBuilder(); - final String id = System.currentTimeMillis() + "_" + new Random().nextInt(10000); + final String id = System.currentTimeMillis() + "_" + RandomUtils.getRandomInt(1000, 9999, random); // Creating link toggleElement.append(" "); - toggleElement.append(title).append("
"); + toggleElement.append(appendColorParagraph(title, color)).append("
"); // Creating body toggleElement.append("