public void init(ScannerReportWriter writer) { if (mode.isIssues()) { return; } File analysisLog = writer.getFileStructure().analysisLog(); try (BufferedWriter fileWriter = Files.newBufferedWriter(analysisLog.toPath(), StandardCharsets.UTF_8)) { if (LOG.isDebugEnabled()) { writeEnvVariables(fileWriter); writeSystemProps(fileWriter); } writePlugins(fileWriter); writeGlobalSettings(fileWriter); writeProjectSettings(fileWriter); writeModulesSettings(fileWriter); } catch (IOException e) { throw new IllegalStateException("Unable to write analysis log", e); } }
@Test public void readScannerLogs() throws IOException { File scannerLogFile = writer.getFileStructure().analysisLog(); FileUtils.write(scannerLogFile, "log1\nlog2"); CloseableIterator<String> logs = underTest.readScannerLogs(); assertThat(logs).containsExactly("log1", "log2"); }
@Test public void do_not_write_warnings_report_when_empty() throws IOException { File outputDir = temp.newFolder(); ScannerReportWriter writer = new ScannerReportWriter(outputDir); underTest.publish(writer); assertThat(writer.getFileStructure().analysisWarnings()).doesNotExist(); ScannerReportReader reader = new ScannerReportReader(outputDir); List<ScannerReport.AnalysisWarning> warnings = Lists.newArrayList(reader.readAnalysisWarnings()); assertThat(warnings).isEmpty(); } }
@Test public void shouldNotDumpInIssuesMode() throws Exception { when(analysisMode.isIssues()).thenReturn(true); ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); publisher.init(writer); assertThat(writer.getFileStructure().analysisLog()).doesNotExist(); }
@Test public void shouldOnlyDumpPluginsByDefault() throws Exception { when(pluginRepo.getPluginInfos()).thenReturn(singletonList(new PluginInfo("xoo").setName("Xoo").setVersion(Version.create("1.0")))); ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) .setWorkDir(temp.newFolder())); when(store.allModules()).thenReturn(singletonList(rootModule)); when(hierarchy.root()).thenReturn(rootModule); publisher.init(writer); assertThat(writer.getFileStructure().analysisLog()).exists(); assertThat(FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8)).contains("Xoo 1.0 (xoo)"); verifyZeroInteractions(system2); }
@Test public void read_source_lines() throws Exception { ScannerReportWriter writer = new ScannerReportWriter(dir); File file = writer.getFileStructure().fileFor(FileStructure.Domain.SOURCE, 1); FileUtils.writeLines(file, Lists.newArrayList("line1", "line2")); File sourceFile = new ScannerReportReader(dir).readFileSource(1); assertThat(sourceFile).isEqualTo(file); }
@Test public void write_metadata() { ScannerReport.Metadata.Builder metadata = ScannerReport.Metadata.newBuilder() .setAnalysisDate(15000000L) .setProjectKey("PROJECT_A") .setRootComponentRef(1); underTest.writeMetadata(metadata.build()); ScannerReport.Metadata read = Protobuf.read(underTest.getFileStructure().metadataFile(), ScannerReport.Metadata.parser()); assertThat(read.getAnalysisDate()).isEqualTo(15000000L); assertThat(read.getProjectKey()).isEqualTo("PROJECT_A"); assertThat(read.getRootComponentRef()).isEqualTo(1); }
@Test public void dumpServerSideGlobalProps() throws Exception { logTester.setLevel(LoggerLevel.DEBUG); ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); when(globalServerSettings.properties()).thenReturn(ImmutableMap.of(COM_FOO, "bar", SONAR_SKIP, "true")); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) .setWorkDir(temp.newFolder()) .setProperty("sonar.projectKey", "foo")); when(store.allModules()).thenReturn(singletonList(rootModule)); when(hierarchy.root()).thenReturn(rootModule); publisher.init(writer); String content = FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8); assertThat(content).containsOnlyOnce(COM_FOO); assertThat(content).containsOnlyOnce(SONAR_SKIP); }
@Test public void shouldNotDumpSensitiveGlobalProperties() throws Exception { ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); when(globalServerSettings.properties()).thenReturn(ImmutableMap.of("sonar.login", "my_token", "sonar.password", "azerty", "sonar.cpp.license.secured", "AZERTY")); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) .setWorkDir(temp.newFolder()) .setProperty("sonar.projectKey", "foo")); when(store.allModules()).thenReturn(singletonList(rootModule)); when(hierarchy.root()).thenReturn(rootModule); publisher.init(writer); assertThat(FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8)).containsSubsequence( "sonar.cpp.license.secured=******", "sonar.login=******", "sonar.password=******"); }
@Test public void write_external_issues() { // no data yet assertThat(underTest.hasComponentData(FileStructure.Domain.EXTERNAL_ISSUES, 1)).isFalse(); // write data ScannerReport.ExternalIssue issue = ScannerReport.ExternalIssue.newBuilder() .setMsg("the message") .build(); underTest.appendComponentExternalIssue(1, issue); assertThat(underTest.hasComponentData(FileStructure.Domain.EXTERNAL_ISSUES, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.EXTERNAL_ISSUES, 1); assertThat(file).exists().isFile(); try (CloseableIterator<ScannerReport.ExternalIssue> read = Protobuf.readStream(file, ScannerReport.ExternalIssue.parser())) { assertThat(Iterators.size(read)).isEqualTo(1); } }
@Test public void write_measures() { assertThat(underTest.hasComponentData(FileStructure.Domain.MEASURES, 1)).isFalse(); ScannerReport.Measure measure = ScannerReport.Measure.newBuilder() .setDoubleValue(DoubleValue.newBuilder().setValue(2.5d).setData("text-value")) .build(); underTest.writeComponentMeasures(1, asList(measure)); assertThat(underTest.hasComponentData(FileStructure.Domain.MEASURES, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.MEASURES, 1); assertThat(file).exists().isFile(); try (CloseableIterator<ScannerReport.Measure> read = Protobuf.readStream(file, ScannerReport.Measure.parser())) { assertThat(Iterators.size(read)).isEqualTo(1); } }
@Test public void write_issues() { // no data yet assertThat(underTest.hasComponentData(FileStructure.Domain.ISSUES, 1)).isFalse(); // write data ScannerReport.Issue issue = ScannerReport.Issue.newBuilder() .setMsg("the message") .build(); underTest.writeComponentIssues(1, asList(issue)); assertThat(underTest.hasComponentData(FileStructure.Domain.ISSUES, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.ISSUES, 1); assertThat(file).exists().isFile(); try (CloseableIterator<ScannerReport.Issue> read = Protobuf.readStream(file, ScannerReport.Issue.parser())) { assertThat(Iterators.size(read)).isEqualTo(1); } }
@Test public void shouldShortenModuleProperties() throws Exception { File baseDir = temp.newFolder(); ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(baseDir) .setWorkDir(temp.newFolder()) .setProperty("sonar.projectKey", "foo") .setProperty("sonar.projectBaseDir", baseDir.toString()) .setProperty("sonar.aVeryLongProp", StringUtils.repeat("abcde", 1000))); when(store.allModules()).thenReturn(singletonList(rootModule)); when(hierarchy.root()).thenReturn(rootModule); publisher.init(writer); assertThat(writer.getFileStructure().analysisLog()).exists(); assertThat(FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8)).containsSubsequence( "sonar.aVeryLongProp=" + StringUtils.repeat("abcde", 199) + "ab...", "sonar.projectBaseDir=" + baseDir.toString(), "sonar.projectKey=foo"); }
@Test public void shouldNotDumpEnvTwice() throws Exception { logTester.setLevel(LoggerLevel.DEBUG); ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); Map<String, String> env = new HashMap<>(); env.put(FOO, "BAR"); env.put(BIZ, "BAZ"); when(system2.envVariables()).thenReturn(env); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) .setWorkDir(temp.newFolder()) .setProperty("sonar.projectKey", "foo") .setProperty("env." + FOO, "BAR")); when(store.allModules()).thenReturn(singletonList(rootModule)); when(hierarchy.root()).thenReturn(rootModule); publisher.init(writer); String content = FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8); assertThat(content).containsOnlyOnce(FOO); assertThat(content).containsOnlyOnce(BIZ); assertThat(content).containsSubsequence(BIZ, FOO); content = FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8); assertThat(content).containsOnlyOnce(FOO); assertThat(content).containsOnlyOnce(BIZ); assertThat(content).doesNotContain("env." + FOO); }
@Test public void write_changed_lines() { assertThat(underTest.hasComponentData(FileStructure.Domain.CHANGED_LINES, 1)).isFalse(); ScannerReport.ChangedLines changedLines = ScannerReport.ChangedLines.newBuilder() .addLine(1) .addLine(3) .build(); underTest.writeComponentChangedLines(1, changedLines); assertThat(underTest.hasComponentData(FileStructure.Domain.CHANGED_LINES, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.CHANGED_LINES, 1); assertThat(file).exists().isFile(); ScannerReport.ChangedLines loadedChangedLines = Protobuf.read(file, ScannerReport.ChangedLines.parser()); assertThat(loadedChangedLines.getLineList()).containsExactly(1, 3); }
@Test public void shouldNotDumpSQPropsInSystemProps() throws Exception { logTester.setLevel(LoggerLevel.DEBUG); ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); Properties props = new Properties(); props.setProperty(COM_FOO, "bar"); props.setProperty(SONAR_SKIP, "true"); when(system2.properties()).thenReturn(props); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) .setWorkDir(temp.newFolder()) .setProperty("sonar.projectKey", "foo") .setProperty(COM_FOO, "bar") .setProperty(SONAR_SKIP, "true")); when(store.allModules()).thenReturn(singletonList(rootModule)); when(hierarchy.root()).thenReturn(rootModule); publisher.init(writer); List<String> lines = FileUtils.readLines(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8); assertThat(lines).containsExactly("Environment variables:", "System properties:", " - com.foo=bar", "SonarQube plugins:", "Global server settings:", "Project server settings:", "Project scanner properties:", " - sonar.projectKey=foo", " - sonar.skip=true"); }
@Test public void shouldNotDumpSensitiveModuleProperties() throws Exception { ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) .setWorkDir(temp.newFolder()) .setProperty("sonar.projectKey", "foo") .setProperty("sonar.projectKey", "foo") .setProperty("sonar.login", "my_token") .setProperty("sonar.password", "azerty") .setProperty("sonar.cpp.license.secured", "AZERTY")); when(store.allModules()).thenReturn(singletonList(rootModule)); when(hierarchy.root()).thenReturn(rootModule); publisher.init(writer); assertThat(writer.getFileStructure().analysisLog()).exists(); assertThat(FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8)).containsSubsequence( "sonar.cpp.license.secured=******", "sonar.login=******", "sonar.password=******", "sonar.projectKey=foo"); }
@Test public void write_component() { // no data yet assertThat(underTest.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isFalse(); // write data ScannerReport.Component.Builder component = ScannerReport.Component.newBuilder() .setRef(1) .setLanguage("java") .setProjectRelativePath("src/Foo.java") .setType(ComponentType.FILE) .setIsTest(false) .addChildRef(5) .addChildRef(42); underTest.writeComponent(component.build()); assertThat(underTest.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.COMPONENT, 1); assertThat(file).exists().isFile(); ScannerReport.Component read = Protobuf.read(file, ScannerReport.Component.parser()); assertThat(read.getRef()).isEqualTo(1); assertThat(read.getChildRefList()).containsOnly(5, 42); assertThat(read.getName()).isEmpty(); assertThat(read.getIsTest()).isFalse(); }
@Test public void write_adhoc_rule() { // write data ScannerReport.AdHocRule rule = ScannerReport.AdHocRule.newBuilder() .setEngineId("eslint") .setRuleId("123") .setName("Foo") .setDescription("Description") .setSeverity(Constants.Severity.BLOCKER) .setType(ScannerReport.IssueType.BUG) .build(); underTest.appendAdHocRule(rule); File file = underTest.getFileStructure().adHocRules(); assertThat(file).exists().isFile(); try (CloseableIterator<ScannerReport.AdHocRule> read = Protobuf.readStream(file, ScannerReport.AdHocRule.parser())) { assertThat(Iterators.size(read)).isEqualTo(1); } }
@Test public void write_symbols() { // no data yet assertThat(underTest.hasComponentData(FileStructure.Domain.SYMBOLS, 1)).isFalse(); // write data ScannerReport.Symbol symbol = ScannerReport.Symbol.newBuilder() .setDeclaration(ScannerReport.TextRange.newBuilder() .setStartLine(1) .setStartOffset(3) .setEndLine(1) .setEndOffset(5) .build()) .addReference(ScannerReport.TextRange.newBuilder() .setStartLine(10) .setStartOffset(15) .setEndLine(11) .setEndOffset(2) .build()) .build(); underTest.writeComponentSymbols(1, asList(symbol)); assertThat(underTest.hasComponentData(FileStructure.Domain.SYMBOLS, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.SYMBOLS, 1); assertThat(file).exists().isFile(); try (CloseableIterator<ScannerReport.Symbol> read = Protobuf.readStream(file, ScannerReport.Symbol.parser())) { assertThat(read).hasSize(1); } }