package org.jboss.arquillian.drone.webdriver.binary.process; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.regex.Pattern; import org.arquillian.spacelift.process.OutputTransformer; import org.arquillian.spacelift.process.ProcessInteraction; import org.jboss.arquillian.drone.webdriver.utils.Validate; /** * Creates a Spacelift interaction for process that are usually tight with some specific output and for which you can * define which output should be printed to stdout */ public class BinaryInteraction { private List<Pattern> allowedOutput; private OutputTransformer transformer; private Pattern expectedPattern; private CountDownLatch countDownLatch; /** * Creates empty interaction builder */ public BinaryInteraction() { allowedOutput = new ArrayList<Pattern>(); transformer = output -> { checkCountDownLatch(output.toString()); return output; }; } /** * Defines an interaction when {@code pattern} is matched * * @param pattern * the line * * @return current instance to allow chaining */ public BinaryInteraction.MatchedOutputProcessInteractionBuilder when(String pattern) { this.expectedPattern = Pattern.compile(pattern); return new BinaryInteraction.MatchedOutputProcessInteractionBuilder(); } public BinaryInteraction printToOut(String pattern) { allowedOutput.add(Pattern.compile(pattern)); return BinaryInteraction.this; } /** * Defines a prefix for standard output and standard error output. Might be {@code null} or empty string, * in such case no prefix is added and process outputs cannot be distinguished * * @param prefix * the prefix * * @return current instance to allow chaining */ public BinaryInteraction outputPrefix(final String prefix) { if (!Validate.empty(prefix)) { transformer = output -> { checkCountDownLatch(output.toString()); return output.prepend(prefix); }; } return this; } private void checkCountDownLatch(String string) { if (countDownLatch != null && countDownLatch.getCount() > 0 && !Validate.empty(string)) { if (string.matches(expectedPattern.toString())) { countDownLatch.countDown(); } } } /** * Builds {@link ProcessInteraction} object from defined data * * @return {@link ProcessInteraction} */ public ProcessInteraction build() { return new BinaryInteraction.ProcessInteractionImpl(transformer, allowedOutput); } private static class ProcessInteractionImpl implements ProcessInteraction { private final List<Pattern> allowedOutput; private final OutputTransformer transformer; ProcessInteractionImpl(OutputTransformer outputTransformer, List<Pattern> allowedOutput) { this.transformer = outputTransformer; this.allowedOutput = allowedOutput; } @Override public List<Pattern> allowedOutput() { return allowedOutput; } @Override public List<Pattern> errorOutput() { return new ArrayList<>(); } @Override public Map<Pattern, String> replyMap() { return new LinkedHashMap<>(); } @Override public List<Pattern> terminatingOutput() { return new ArrayList<>(); } @Override public String textTypedIn() { return ""; } @Override public OutputTransformer transformer() { return transformer; } } /** * Definition of allowed actions when output is matched */ public class MatchedOutputProcessInteractionBuilder { /** * Counts down the latch (if not null and is bigger than zero) * * @param countDownLatch * A {@link CountDownLatch} to be counted down * * @return current instance to allow chaining */ public BinaryInteraction thenCountDown(CountDownLatch countDownLatch) { BinaryInteraction.this.countDownLatch = countDownLatch; return BinaryInteraction.this; } } }