Search in sources :

Example 1 with Answer

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;
}
Also used : Path(java.nio.file.Path) Answer(org.batfish.datamodel.answers.Answer) FileWriter(java.io.FileWriter) TestComparisonMode(org.batfish.client.Command.TestComparisonMode) File(java.io.File) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) EndOfFileException(org.jline.reader.EndOfFileException) IOException(java.io.IOException) JSONException(org.codehaus.jettison.json.JSONException) UserInterruptException(org.jline.reader.UserInterruptException) PatternSyntaxException(java.util.regex.PatternSyntaxException) FileNotFoundException(java.io.FileNotFoundException) BatfishException(org.batfish.common.BatfishException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException)

Example 2 with Answer

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;
}
Also used : Path(java.nio.file.Path) Answer(org.batfish.datamodel.answers.Answer) BatfishException(org.batfish.common.BatfishException) JsonNode(com.fasterxml.jackson.databind.JsonNode) IOException(java.io.IOException) BatfishObjectMapper(org.batfish.common.util.BatfishObjectMapper) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) EndOfFileException(org.jline.reader.EndOfFileException) IOException(java.io.IOException) JSONException(org.codehaus.jettison.json.JSONException) UserInterruptException(org.jline.reader.UserInterruptException) PatternSyntaxException(java.util.regex.PatternSyntaxException) FileNotFoundException(java.io.FileNotFoundException) BatfishException(org.batfish.common.BatfishException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException)

Example 3 with Answer

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());
}
Also used : Path(java.nio.file.Path) Answer(org.batfish.datamodel.answers.Answer) LoadQuestionAnswerElement(org.batfish.client.answer.LoadQuestionAnswerElement) JSONObject(org.codehaus.jettison.json.JSONObject) BatfishLogger(org.batfish.common.BatfishLogger) Test(org.junit.Test)

Example 4 with Answer

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;
}
Also used : Path(java.nio.file.Path) Answer(org.batfish.datamodel.answers.Answer) InitInfoAnswerElement(org.batfish.datamodel.answers.InitInfoAnswerElement) CleanBatfishException(org.batfish.common.CleanBatfishException)

Example 5 with 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;
}
Also used : Path(java.nio.file.Path) RunAnalysisAnswerElement(org.batfish.datamodel.answers.RunAnalysisAnswerElement) Answer(org.batfish.datamodel.answers.Answer) CleanBatfishException(org.batfish.common.CleanBatfishException) BatfishException(org.batfish.common.BatfishException) ActiveSpan(io.opentracing.ActiveSpan) AnswerSummary(org.batfish.datamodel.answers.AnswerSummary) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException)

Aggregations

Answer (org.batfish.datamodel.answers.Answer)22 BatfishException (org.batfish.common.BatfishException)14 Path (java.nio.file.Path)13 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)8 CleanBatfishException (org.batfish.common.CleanBatfishException)8 IOException (java.io.IOException)7 JSONException (org.codehaus.jettison.json.JSONException)6 ActiveSpan (io.opentracing.ActiveSpan)5 PatternSyntaxException (java.util.regex.PatternSyntaxException)5 TreeMap (java.util.TreeMap)4 ExecutionException (java.util.concurrent.ExecutionException)3 Nullable (javax.annotation.Nullable)3 LoadQuestionAnswerElement (org.batfish.client.answer.LoadQuestionAnswerElement)3 Topology (org.batfish.datamodel.Topology)3 ConvertConfigurationAnswerElement (org.batfish.datamodel.answers.ConvertConfigurationAnswerElement)3 AwsConfiguration (org.batfish.representation.aws.AwsConfiguration)3 IptablesVendorConfiguration (org.batfish.representation.iptables.IptablesVendorConfiguration)3 VendorConfiguration (org.batfish.vendor.VendorConfiguration)3 JSONObject (org.codehaus.jettison.json.JSONObject)3 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)2