Skip to content
Permalink
Browse files

cli.doc capture output and matched lines

  • Loading branch information...
MykolaGolubyev committed Jun 14, 2019
1 parent 1b01c53 commit 85fada58ea77c91653cc7f13d98b9b651130095e
@@ -14,3 +14,4 @@ webtau-feature-testing/doc-artifacts/*
webtau-feature-testing/examples/doc-artifacts/*
webtau-groovy/doc-artifacts/*
webtau-http/doc-artifacts/*
webtau-cli/doc-artifacts/*
@@ -1,2 +1,7 @@
#!/bin/bash
echo "hello world" $1 $NAME
echo "hello world" $1 $NAME
echo "line in the middle"
echo "more text"
>&2 echo "error line one"
>&2 echo "error line two"
exit 5
@@ -33,6 +33,10 @@
public class Cli {
public static final Cli cli = new Cli();

private final ThreadLocal<CliValidationResult> lastValidationResult = new ThreadLocal<>();

public final CliDocumentation doc = new CliDocumentation();

private Cli() {
}

@@ -49,7 +53,9 @@ public void run(String command, CliValidationOutputOnlylHandler handler) {
}

public void run(String command, ProcessEnv env, CliValidationOutputOnlylHandler handler) {
cliStep(command, env, (runResult) -> handler.handle(cliOutput(runResult), cliError(runResult)));
cliStep(command, env, (validationResult) -> handler.handle(
validationResult.getOut(),
validationResult.getErr()));
}

public void run(String command, CliValidationExitCodeOutputHandler handler) {
@@ -58,10 +64,18 @@ public void run(String command, CliValidationExitCodeOutputHandler handler) {

public void run(String command, ProcessEnv env, CliValidationExitCodeOutputHandler handler) {
cliStep(command, env,
(runResult) -> handler.handle(exitCode(runResult), cliOutput(runResult), cliError(runResult)));
(validationResult) -> handler.handle(
exitCode(validationResult),
validationResult.getOut(),
validationResult.getErr()));

}

private void cliStep(String command, ProcessEnv env, Consumer<ProcessRunResult> validationCode) {
public CliValidationResult getLastValidationResult() {
return lastValidationResult.get();
}

private void cliStep(String command, ProcessEnv env, Consumer<CliValidationResult> validationCode) {
TestStep.createAndExecuteStep(null,
tokenizedMessage(action("running cli command "), stringValue(command)),
() -> tokenizedMessage(action("ran cli command"), stringValue(command)),
@@ -75,12 +89,19 @@ private void cliStep(String command, ProcessEnv env, Consumer<ProcessRunResult>
throw new RuntimeException(runResult.getOutputReadingException());
}

validationCode.accept(runResult);
CliValidationResult validationResult = new CliValidationResult(
command,
runResult.getExitCode(),
cliOutput(runResult),
cliError(runResult));

validationCode.accept(validationResult);
lastValidationResult.set(validationResult);
});
}

private CliExitCode exitCode(ProcessRunResult runResult) {
return new CliExitCode(runResult.getExitCode());
private CliExitCode exitCode(CliValidationResult validationResult) {
return new CliExitCode(validationResult.getExitCode());
}

private static CliOutput cliOutput(ProcessRunResult runResult) {
@@ -0,0 +1,88 @@
/*
* Copyright 2019 TWO SIGMA OPEN SOURCE, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.twosigma.webtau.cli;

import com.twosigma.webtau.cli.expectation.CliOutput;
import com.twosigma.webtau.documentation.DocumentationArtifactsLocation;
import com.twosigma.webtau.utils.FileUtils;

import java.nio.file.Path;
import java.util.List;

public class CliDocumentation {
public void capture(String artifactName) {
Capture capture = new Capture(artifactName);
capture.capture();
}

private static class Capture {
private final Path path;
private final CliValidationResult lastValidationResult;

public Capture(String artifactName) {
this.path = DocumentationArtifactsLocation.resolve(artifactName);

this.lastValidationResult = Cli.cli.getLastValidationResult();
if (this.lastValidationResult == null) {
throw new IllegalStateException("no cli calls were made yet");
}
}

public void capture() {
captureCommand();
captureOut();
captureErr();
captureOutMatchedLines();
captureErrMatchedLines();
}

private void captureCommand() {
FileUtils.writeTextContent(path.resolve("command.txt"), lastValidationResult.getCommand());

}

private void captureOut() {
capture("out.txt", lastValidationResult.getOut());
}

private void captureErr() {
capture("err.txt", lastValidationResult.getErr());
}

private void capture(String fileName, CliOutput output) {
String out = output.get();
if (!out.isEmpty()) {
FileUtils.writeTextContent(path.resolve(fileName), out);
}
}

private void captureOutMatchedLines() {
captureMatched("out.matched.txt", lastValidationResult.getOut());
}

private void captureErrMatchedLines() {
captureMatched("err.matched.txt", lastValidationResult.getErr());
}

private void captureMatched(String fileName, CliOutput output) {
List<String> lines = output.extractMatchedLines();
if (!lines.isEmpty()) {
FileUtils.writeTextContent(path.resolve(fileName), String.join("\n", lines));
}
}
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2019 TWO SIGMA OPEN SOURCE, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.twosigma.webtau.cli;

import com.twosigma.webtau.cli.expectation.CliOutput;
import com.twosigma.webtau.reporter.TestStepPayload;

import java.util.LinkedHashMap;
import java.util.Map;

public class CliValidationResult implements TestStepPayload {
private final String command;
private final Integer exitCode;
private final CliOutput out;
private final CliOutput err;

public CliValidationResult(String command, Integer exitCode, CliOutput out, CliOutput err) {
this.command = command;
this.exitCode = exitCode;
this.out = out;
this.err = err;
}

public String getCommand() {
return command;
}

public Integer getExitCode() {
return exitCode;
}

public CliOutput getOut() {
return out;
}

public CliOutput getErr() {
return err;
}

@Override
public Map<String, ?> toMap() {
Map<String, Object> result = new LinkedHashMap<>();
return result;
}
}
@@ -18,17 +18,24 @@

import com.twosigma.webtau.expectation.ActualPath;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

public class CliOutput implements CliResultExpectations {
private String id;
private List<String> lines;

private Set<Integer> matchedLinesIdx;

private String full;

public CliOutput(String id, List<String> lines) {
this.id = id;
this.lines = lines;
this.matchedLinesIdx = new TreeSet<>();
this.full = String.join("\n", lines);
}

@@ -44,4 +51,12 @@ public String get() {
public List<String> getLines() {
return lines;
}

public void registerMatchedLine(Integer idx) {
matchedLinesIdx.add(idx);
}

public List<String> extractMatchedLines() {
return matchedLinesIdx.stream().map(lines::get).collect(Collectors.toList());
}
}
@@ -16,9 +16,16 @@

package com.twosigma.webtau.cli.expectation;

import com.twosigma.webtau.data.render.DataRenderers;
import com.twosigma.webtau.expectation.ActualPath;
import com.twosigma.webtau.expectation.contain.ContainAnalyzer;
import com.twosigma.webtau.expectation.contain.ContainHandler;
import com.twosigma.webtau.expectation.contain.handlers.IndexedValue;
import com.twosigma.webtau.expectation.contain.handlers.IterableContainAnalyzer;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class CliOutputContainHandler implements ContainHandler {
@Override
@@ -28,11 +35,38 @@ public boolean handle(Object actual, Object expected) {

@Override
public void analyzeContain(ContainAnalyzer containAnalyzer, ActualPath actualPath, Object actual, Object expected) {
containAnalyzer.contains(actualPath, ((CliOutput) actual).get(), expected);
CliOutput cliOutput = ((CliOutput) actual);
IterableContainAnalyzer analyzer = new IterableContainAnalyzer(actualPath, cliOutput.getLines(), expected);
List<IndexedValue> indexedValues = analyzer.containingIndexedValues();

if (indexedValues.isEmpty()) {
containAnalyzer.reportMismatch(this, actualPath, analyzer.getComparator()
.generateEqualMismatchReport());
}

indexedValues.forEach(iv -> cliOutput.registerMatchedLine(iv.getIdx()));
}

@Override
public void analyzeNotContain(ContainAnalyzer containAnalyzer, ActualPath actualPath, Object actual, Object expected) {
containAnalyzer.notContains(actualPath, ((CliOutput) actual).get(), expected);
CliOutput cliOutput = ((CliOutput) actual);

IterableContainAnalyzer analyzer = new IterableContainAnalyzer(actualPath, cliOutput.getLines(), expected);
List<IndexedValue> indexedValues = analyzer.containingIndexedValues();

Set<Integer> matchedLinesIdx = new HashSet<>();
indexedValues.forEach(indexedValue -> {
containAnalyzer.reportMismatch(this, actualPath.index(indexedValue.getIdx()),
"equals " + DataRenderers.render(indexedValue.getValue()));

matchedLinesIdx.add(indexedValue.getIdx());
}
);

for (int lineIdx = 0; lineIdx < cliOutput.getLines().size(); lineIdx++) {
if (!matchedLinesIdx.contains(lineIdx)) {
cliOutput.registerMatchedLine(lineIdx);
}
}
}
}
@@ -16,12 +16,15 @@

package com.twosigma.webtau.cli;

import com.twosigma.webtau.documentation.DocumentationArtifactsLocation;
import com.twosigma.webtau.utils.FileUtils;
import org.junit.Test;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.regex.Pattern;

import static com.twosigma.webtau.Ddjt.contain;
import static com.twosigma.webtau.Ddjt.equal;
import static com.twosigma.webtau.Ddjt.*;
import static com.twosigma.webtau.cli.Cli.cli;
import static com.twosigma.webtau.cli.CliTestUtils.nixOnly;

@@ -37,7 +40,7 @@ public void outputOnlyValidation() {
public void outputAndExitCodeValidation() {
nixOnly(() -> {
cli.run("scripts/hello \"message to world\"", (exitCode, output, error) -> {
exitCode.should(equal(0));
exitCode.should(equal(5));

output.should(equal(Pattern.compile("hello")));
output.should(contain("world"));
@@ -54,4 +57,37 @@ public void envVars() {
});
});
}

@Test
public void docCapture() {
nixOnly(() -> {
cli.run("scripts/hello", ((output, error) -> {
output.should(contain("line in the middle"));
output.should(contain(Pattern.compile("line in the")));
output.should(contain("more text"));

error.should(contain("error line one"));
}));

String artifactName = "hello-script";
cli.doc.capture(artifactName);

validateCapturedDocs(artifactName, "out.txt", "hello world\n" +
"line in the middle\n" +
"more text");

validateCapturedDocs(artifactName, "err.txt", "error line one\n" +
"error line two");

validateCapturedDocs(artifactName, "out.matched.txt", "line in the middle\nmore text");
validateCapturedDocs(artifactName, "err.matched.txt", "error line one");
});
}

private static void validateCapturedDocs(String artifactName, String fileName, String expectedContent) {
Path path = DocumentationArtifactsLocation.resolve(artifactName).resolve(fileName);
actual(Files.exists(path)).should(equal(true));

actual(FileUtils.fileTextContent(path)).should(equal(expectedContent));
}
}

0 comments on commit 85fada5

Please sign in to comment.
You can’t perform that action at this time.