use of org.batfish.datamodel.answers.Answer in project batfish by batfish.
the class Client method test.
private boolean test(List<String> options, List<String> parameters) throws IOException {
boolean failingTest = false;
boolean missingReferenceFile = false;
int testCommandIndex = 1;
if (!isValidArgument(options, parameters, 1, 2, Integer.MAX_VALUE, Command.TEST)) {
return false;
}
TestComparisonMode comparisonMode = TestComparisonMode.COMPAREANSWER;
if (!options.isEmpty()) {
comparisonMode = // remove '-'
TestComparisonMode.valueOf(options.get(0).substring(1).toUpperCase());
}
if (parameters.get(testCommandIndex).equals(FLAG_FAILING_TEST)) {
testCommandIndex++;
failingTest = true;
}
String referenceFileName = parameters.get(0);
String[] testCommand = parameters.subList(testCommandIndex, parameters.size()).toArray(new String[0]);
_logger.debugf("Ref file is %s. \n", referenceFileName, parameters.size());
_logger.debugf("Test command is %s\n", Arrays.toString(testCommand));
File referenceFile = new File(referenceFileName);
if (!referenceFile.exists()) {
_logger.errorf("Reference file does not exist: %s\n", referenceFileName);
missingReferenceFile = true;
}
// Delete any existing testout filename before running this test.
Path failedTestoutPath = Paths.get(referenceFile + ".testout");
CommonUtil.deleteIfExists(failedTestoutPath);
File testoutFile = Files.createTempFile("test", "out").toFile();
testoutFile.deleteOnExit();
FileWriter testoutWriter = new FileWriter(testoutFile);
boolean testCommandSucceeded = processCommand(testCommand, testoutWriter);
testoutWriter.close();
String testOutput = CommonUtil.readFile(Paths.get(testoutFile.getAbsolutePath()));
boolean testPassed = false;
if (failingTest) {
if (!testCommandSucceeded) {
// Command failed in the client.
testPassed = true;
} else {
try {
Answer testAnswer = BatfishObjectMapper.mapper().readValue(testOutput, Answer.class);
testPassed = (testAnswer.getStatus() == AnswerStatus.FAILURE);
} catch (JsonProcessingException e) {
// pass here and let the test fail.
}
}
} else if (testCommandSucceeded) {
try {
if (TestComparisonMode.RAW != comparisonMode) {
Answer testAnswer = BatfishObjectMapper.mapper().readValue(testOutput, Answer.class);
testOutput = getTestComparisonString(testAnswer, comparisonMode);
}
if (!missingReferenceFile) {
String referenceOutput = CommonUtil.readFile(Paths.get(referenceFileName));
if (referenceOutput.equals(testOutput)) {
testPassed = true;
}
}
} catch (JsonProcessingException e) {
_logger.errorf("Error deserializing answer %s: %s\n", testOutput, ExceptionUtils.getStackTrace(e));
} catch (Exception e) {
_logger.errorf("Exception in comparing test results: %s\n", ExceptionUtils.getStackTrace(e));
}
}
StringBuilder sb = new StringBuilder();
sb.append("'" + testCommand[0]);
for (int i = 1; i < testCommand.length; i++) {
sb.append(" " + testCommand[i]);
}
sb.append("'");
String testCommandText = sb.toString();
_logger.outputf("Test [%s]: %s %s: %s\n", comparisonMode, testCommandText, failingTest ? "results in error as expected" : "matches " + referenceFileName, testPassed ? "Pass" : "Fail");
if (!testPassed) {
CommonUtil.writeFile(failedTestoutPath, testOutput);
_logger.outputf("Copied output to %s\n", failedTestoutPath);
}
return true;
}
use of org.batfish.datamodel.answers.Answer in project batfish by batfish.
the class Client method pollWorkAndGetAnswer.
private boolean pollWorkAndGetAnswer(WorkItem wItem, @Nullable FileWriter outWriter) {
boolean pollResult = pollWork(wItem.getId(), outWriter);
if (!pollResult) {
return false;
}
// get the answer
String ansFileName = wItem.getId() + BfConsts.SUFFIX_ANSWER_JSON_FILE;
String downloadedAnsFile = _workHelper.getObject(wItem.getContainerName(), wItem.getTestrigName(), ansFileName);
if (downloadedAnsFile == null) {
_logger.errorf("Failed to get answer file %s. (Was work killed?)\n", ansFileName);
} else {
String answerString = CommonUtil.readFile(Paths.get(downloadedAnsFile));
// Check if we need to make things pretty
// Don't if we are writing to FileWriter, because we need valid JSON in
// that case
String answerStringToPrint = answerString;
if (outWriter == null && _settings.getPrettyPrintAnswers()) {
Answer answer;
try {
answer = BatfishObjectMapper.mapper().readValue(answerString, Answer.class);
} catch (IOException e) {
throw new BatfishException("Response does not appear to be valid JSON representation of " + Answer.class.getSimpleName(), e);
}
answerStringToPrint = answer.prettyPrint();
}
logOutput(outWriter, answerStringToPrint);
// tests serialization/deserialization when running in debug mode
if (_logger.getLogLevel() >= BatfishLogger.LEVEL_DEBUG) {
try {
ObjectMapper reader = BatfishObjectMapper.mapper();
Answer answer = reader.readValue(answerString, Answer.class);
String newAnswerString = BatfishObjectMapper.writeString(answer);
JsonNode tree = reader.readTree(answerString);
JsonNode newTree = reader.readTree(newAnswerString);
if (!CommonUtil.checkJsonEqual(tree, newTree)) {
// if (!tree.equals(newTree)) {
_logger.errorf("Original and recovered Json are different. Recovered = %s\n", newAnswerString);
}
} catch (Exception e) {
_logger.outputf("Could NOT deserialize Json to Answer: %s\n", e.getMessage());
}
}
}
// get and print the log when in debugging mode
if (_logger.getLogLevel() >= BatfishLogger.LEVEL_DEBUG) {
_logger.output("---------------- Service Log --------------\n");
String logFileName = wItem.getId() + BfConsts.SUFFIX_LOG_FILE;
String downloadedFileStr = _workHelper.getObject(wItem.getContainerName(), wItem.getTestrigName(), logFileName);
if (downloadedFileStr == null) {
_logger.errorf("Failed to get log file %s\n", logFileName);
return false;
} else {
Path downloadedFile = Paths.get(downloadedFileStr);
CommonUtil.outputFileLines(downloadedFile, _logger::output);
}
}
return true;
}
use of org.batfish.datamodel.answers.Answer in project batfish by batfish.
the class ClientTest method testLoadQuestionsNames.
@Test
public void testLoadQuestionsNames() throws Exception {
Client client = new Client(new String[] { "-runmode", "gendatamodel", "-prettyanswers", "false" });
JSONObject testQuestion = new JSONObject();
testQuestion.put("instance", new JSONObject().put("instanceName", "testQuestionName").put("description", "test question description"));
Path questionJsonPath = _folder.newFile("testquestion.json").toPath();
CommonUtil.writeFile(questionJsonPath, testQuestion.toString());
client._logger = new BatfishLogger("output", false);
client.processCommand(new String[] { LOAD_QUESTIONS.commandName(), questionJsonPath.getParent().toString() }, null);
// Reading the answer written by load-questions
Answer answerLoadQuestions = _mapper.readValue(client.getLogger().getHistory().toString(BatfishLogger.LEVEL_OUTPUT), Answer.class);
LoadQuestionAnswerElement ae = (LoadQuestionAnswerElement) answerLoadQuestions.getAnswerElements().get(0);
// Checking that question name in answer element matches instanceName in file
assertEquals("testQuestionName", ae.getAdded().first());
}
use of org.batfish.datamodel.answers.Answer in project batfish by batfish.
the class Batfish method run.
public Answer run() {
newBatch("Begin job", 0);
loadPlugins();
boolean action = false;
Answer answer = new Answer();
if (_settings.getPrintSymmetricEdgePairs()) {
printSymmetricEdgePairs();
return answer;
}
if (_settings.getReport()) {
answer.addAnswerElement(report());
return answer;
}
if (_settings.getSynthesizeJsonTopology()) {
writeJsonTopology();
return answer;
}
if (_settings.getHistogram()) {
histogram(_testrigSettings.getTestRigPath());
return answer;
}
if (_settings.getFlatten()) {
Path flattenSource = _testrigSettings.getTestRigPath();
Path flattenDestination = _settings.getFlattenDestination();
flatten(flattenSource, flattenDestination);
return answer;
}
if (_settings.getGenerateStubs()) {
String inputRole = _settings.getGenerateStubsInputRole();
String interfaceDescriptionRegex = _settings.getGenerateStubsInterfaceDescriptionRegex();
int stubAs = _settings.getGenerateStubsRemoteAs();
generateStubs(inputRole, stubAs, interfaceDescriptionRegex);
return answer;
}
if (_settings.getSerializeVendor()) {
Path testRigPath = _testrigSettings.getTestRigPath();
Path outputPath = _testrigSettings.getSerializeVendorPath();
answer.append(serializeVendorConfigs(testRigPath, outputPath));
action = true;
}
if (_settings.getSerializeIndependent()) {
Path inputPath = _testrigSettings.getSerializeVendorPath();
answer.append(serializeIndependentConfigs(inputPath));
action = true;
}
if (_settings.getInitInfo()) {
InitInfoAnswerElement initInfoAnswerElement = initInfo(true, false);
// In this context we can remove parse trees because they will be returned in preceding answer
// element. Note that parse trees are not removed when asking initInfo as its own question.
initInfoAnswerElement.setParseTrees(Collections.emptySortedMap());
answer.addAnswerElement(initInfoAnswerElement);
action = true;
}
if (_settings.getCompileEnvironment()) {
answer.append(compileEnvironmentConfigurations(_testrigSettings));
action = true;
}
if (_settings.getAnswer()) {
answer.append(answer());
action = true;
}
if (_settings.getAnalyze()) {
answer.append(analyze());
action = true;
}
if (_settings.getDataPlane()) {
answer.addAnswerElement(computeDataPlane(_settings.getDiffActive()));
action = true;
}
if (_settings.getValidateEnvironment()) {
answer.append(validateEnvironment());
action = true;
}
if (!action) {
throw new CleanBatfishException("No task performed! Run with -help flag to see usage\n");
}
return answer;
}
use of org.batfish.datamodel.answers.Answer in project batfish by batfish.
the class Batfish method analyze.
private Answer analyze() {
Answer answer = new Answer();
AnswerSummary summary = new AnswerSummary();
String analysisName = _settings.getAnalysisName();
String containerName = _settings.getContainerDir().getFileName().toString();
Path analysisQuestionsDir = _settings.getContainerDir().resolve(Paths.get(BfConsts.RELPATH_ANALYSES_DIR, analysisName, BfConsts.RELPATH_QUESTIONS_DIR).toString());
if (!Files.exists(analysisQuestionsDir)) {
throw new BatfishException("Analysis questions dir does not exist: '" + analysisQuestionsDir + "'");
}
RunAnalysisAnswerElement ae = new RunAnalysisAnswerElement();
try (Stream<Path> questions = CommonUtil.list(analysisQuestionsDir)) {
questions.forEach(analysisQuestionDir -> {
String questionName = analysisQuestionDir.getFileName().toString();
Path analysisQuestionPath = analysisQuestionDir.resolve(BfConsts.RELPATH_QUESTION_FILE);
_settings.setQuestionPath(analysisQuestionPath);
Answer currentAnswer;
try (ActiveSpan analysisQuestionSpan = GlobalTracer.get().buildSpan(String.format("Getting answer to question %s from analysis %s", questionName, analysisName)).startActive()) {
// make span not show up as unused
assert analysisQuestionSpan != null;
currentAnswer = answer();
}
// Ensuring that question was parsed successfully
if (currentAnswer.getQuestion() != null) {
try {
// TODO: This can be represented much cleanly and easily with a Json
_logger.infof("Ran question:%s from analysis:%s in container:%s; work-id:%s, status:%s, " + "computed dataplane:%s, parameters:%s\n", questionName, analysisName, containerName, getTaskId(), currentAnswer.getSummary().getNumFailed() > 0 ? "failed" : "passed", currentAnswer.getQuestion().getDataPlane(), BatfishObjectMapper.writeString(currentAnswer.getQuestion().getInstance().getVariables()));
} catch (JsonProcessingException e) {
throw new BatfishException(String.format("Error logging question %s in analysis %s", questionName, analysisName), e);
}
}
initAnalysisQuestionPath(analysisName, questionName);
outputAnswer(currentAnswer);
ae.getAnswers().put(questionName, currentAnswer);
_settings.setQuestionPath(null);
summary.combine(currentAnswer.getSummary());
});
}
answer.addAnswerElement(ae);
answer.setSummary(summary);
return answer;
}
Aggregations