From 8b2213ef7a6777709d981a83c4d875951f225cc5 Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Fri, 6 Jan 2023 17:42:28 -0600 Subject: SONAR-18174 Analyzer cache should be kept in the file system to decrease memory use --- .../sonar/scanner/cache/AnalysisCacheLoader.java | 4 +- .../scanner/cache/AnalysisCacheMemoryStorage.java | 8 +-- .../sonar/scanner/cache/AnalysisCacheProvider.java | 16 ++--- .../scanner/cache/DefaultAnalysisCacheLoader.java | 24 ++++--- .../org/sonar/scanner/cache/ScannerWriteCache.java | 3 +- .../org/sonar/scanner/cache/WriteCacheImpl.java | 77 +++++++++++++--------- .../sonar/scanner/mediumtest/AnalysisResult.java | 8 +-- .../scanner/report/AnalysisCachePublisher.java | 23 +------ .../org/sonar/scanner/report/ReportPublisher.java | 9 +-- .../report/ScannerFileStructureProvider.java | 37 +++++++++++ .../scanner/scan/SpringProjectScanContainer.java | 2 + .../scanner/cache/AnalysisCacheEnabledTest.java | 2 +- .../cache/AnalysisCacheMemoryStorageTest.java | 16 +++-- .../scanner/cache/AnalysisCacheProviderTest.java | 37 +++++++++-- .../cache/DefaultAnalysisCacheLoaderTest.java | 35 +++++----- .../sonar/scanner/cache/WriteCacheImplTest.java | 53 +++++++++++---- .../org/sonar/scanner/cpd/CpdExecutorTest.java | 6 +- .../scanner/mediumtest/ScannerMediumTester.java | 4 +- .../scanner/mediumtest/scm/ScmMediumTest.java | 4 +- .../scanner/report/ActiveRulesPublisherTest.java | 6 +- .../scanner/report/AnalysisCachePublisherTest.java | 50 ++------------ .../report/AnalysisContextReportPublisherTest.java | 34 ++++------ .../report/AnalysisWarningsPublisherTest.java | 23 +++---- .../scanner/report/ChangedLinesPublisherTest.java | 7 +- .../scanner/report/ComponentsPublisherTest.java | 13 ++-- .../scanner/report/MetadataPublisherTest.java | 66 +++++++------------ .../sonar/scanner/report/ReportPublisherTest.java | 16 ++--- .../sonar/scanner/report/SourcePublisherTest.java | 4 +- .../scanner/sensor/DefaultSensorStorageTest.java | 5 +- 29 files changed, 318 insertions(+), 274 deletions(-) create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ScannerFileStructureProvider.java (limited to 'sonar-scanner-engine') diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheLoader.java index c4857c5575b..6ea0b6c05c9 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheLoader.java @@ -20,8 +20,8 @@ package org.sonar.scanner.cache; import java.util.Optional; -import org.sonar.scanner.protocol.internal.ScannerInternal; +import org.sonar.scanner.protocol.internal.SensorCacheData; public interface AnalysisCacheLoader { - Optional load(); + Optional load(); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorage.java index d3ea7d26df1..5bb3c3c1048 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorage.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorage.java @@ -21,12 +21,12 @@ package org.sonar.scanner.cache; import java.io.InputStream; import javax.annotation.Nullable; -import org.sonar.scanner.protocol.internal.ScannerInternal.AnalysisCacheMsg; +import org.sonar.scanner.protocol.internal.SensorCacheData; public class AnalysisCacheMemoryStorage implements AnalysisCacheStorage { private final AnalysisCacheLoader loader; @Nullable - private AnalysisCacheMsg cache; + private SensorCacheData cache; public AnalysisCacheMemoryStorage(AnalysisCacheLoader loader) { this.loader = loader; @@ -37,7 +37,7 @@ public class AnalysisCacheMemoryStorage implements AnalysisCacheStorage { if (!contains(key)) { throw new IllegalArgumentException("Key not found: " + key); } - return cache.getMapOrThrow(key).newInput(); + return cache.getEntries().get(key).newInput(); } @Override @@ -45,7 +45,7 @@ public class AnalysisCacheMemoryStorage implements AnalysisCacheStorage { if (cache == null) { return false; } - return cache.containsMap(key); + return cache.getEntries().containsKey(key); } public void load() { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheProvider.java index 48bf18c2512..c468ffd2b1a 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheProvider.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/AnalysisCacheProvider.java @@ -20,15 +20,14 @@ package org.sonar.scanner.cache; import java.io.InputStream; -import java.util.Map; import org.jetbrains.annotations.Nullable; import org.sonar.api.batch.sensor.cache.ReadCache; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.scan.branch.BranchConfiguration; import org.springframework.context.annotation.Bean; -import static java.util.Collections.emptyMap; - public class AnalysisCacheProvider { + @Bean("ReadCache") public ReadCache provideReader(AnalysisCacheEnabled analysisCacheEnabled, AnalysisCacheMemoryStorage storage) { if (analysisCacheEnabled.isEnabled()) { @@ -39,14 +38,13 @@ public class AnalysisCacheProvider { } @Bean("WriteCache") - public ScannerWriteCache provideWriter(AnalysisCacheEnabled analysisCacheEnabled, ReadCache readCache, BranchConfiguration branchConfiguration) { - if (analysisCacheEnabled.isEnabled()) { - return new WriteCacheImpl(readCache, branchConfiguration); + public ScannerWriteCache provideWriter(AnalysisCacheEnabled analysisCacheEnabled, ReadCache readCache, BranchConfiguration branchConfiguration, FileStructure fileStructure) { + if (analysisCacheEnabled.isEnabled() && !branchConfiguration.isPullRequest()) { + return new WriteCacheImpl(readCache, fileStructure); } return new NoOpWriteCache(); } - static class NoOpWriteCache implements ScannerWriteCache { @Override public void write(String s, InputStream inputStream) { @@ -64,8 +62,8 @@ public class AnalysisCacheProvider { } @Override - public Map getCache() { - return emptyMap(); + public void close() { + // no op } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoader.java index 2095c44917d..dab9488a737 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoader.java @@ -22,6 +22,8 @@ package org.sonar.scanner.cache; import java.io.IOException; import java.io.InputStream; import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import java.util.zip.GZIPInputStream; import org.sonar.api.scanner.fs.InputProject; import org.sonar.api.utils.MessageException; @@ -30,8 +32,8 @@ import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Profiler; import org.sonar.core.util.Protobuf; import org.sonar.scanner.bootstrap.DefaultScannerWsClient; -import org.sonar.scanner.protocol.internal.ScannerInternal; -import org.sonar.scanner.protocol.internal.ScannerInternal.AnalysisCacheMsg; +import org.sonar.scanner.protocol.internal.ScannerInternal.SensorCacheEntry; +import org.sonar.scanner.protocol.internal.SensorCacheData; import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.HttpException; @@ -61,7 +63,7 @@ public class DefaultAnalysisCacheLoader implements AnalysisCacheLoader { } @Override - public Optional load() { + public Optional load() { String url = URL + "?project=" + project.key(); if (branchConfiguration.referenceBranchName() != null) { url = url + "&branch=" + branchConfiguration.referenceBranchName(); @@ -75,13 +77,13 @@ public class DefaultAnalysisCacheLoader implements AnalysisCacheLoader { Optional length = response.header(CONTENT_LENGTH).map(Integer::parseInt); boolean hasGzipEncoding = contentEncoding.isPresent() && contentEncoding.get().equals("gzip"); - AnalysisCacheMsg msg = hasGzipEncoding ? decompress(is) : Protobuf.read(is, AnalysisCacheMsg.parser()); + SensorCacheData cache = hasGzipEncoding ? decompress(is) : read(is); if (length.isPresent()) { profiler.stopInfo(LOG_MSG + String.format(" (%s)", humanReadableByteCountSI(length.get()))); } else { profiler.stopInfo(LOG_MSG); } - return Optional.of(msg); + return Optional.of(cache); } catch (HttpException e) { if (e.code() == 404) { profiler.stopInfo(LOG_MSG + " (404)"); @@ -93,11 +95,15 @@ public class DefaultAnalysisCacheLoader implements AnalysisCacheLoader { } } - private static AnalysisCacheMsg decompress(InputStream is) { + public SensorCacheData decompress(InputStream is) throws IOException { try (GZIPInputStream gzipInputStream = new GZIPInputStream(is)) { - return Protobuf.read(gzipInputStream, ScannerInternal.AnalysisCacheMsg.parser()); - } catch (IOException e) { - throw new IllegalStateException("Failed to decompress analysis cache", e); + return read(gzipInputStream); } } + + public SensorCacheData read(InputStream is) { + Iterable it = () -> Protobuf.readStream(is, SensorCacheEntry.parser()); + return new SensorCacheData(StreamSupport.stream(it.spliterator(), false).collect(Collectors.toList())); + } } + diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/ScannerWriteCache.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/ScannerWriteCache.java index 054d7037298..a901010f086 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/ScannerWriteCache.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/ScannerWriteCache.java @@ -19,9 +19,8 @@ */ package org.sonar.scanner.cache; -import java.util.Map; import org.sonar.api.batch.sensor.cache.WriteCache; public interface ScannerWriteCache extends WriteCache { - Map getCache(); + void close(); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/WriteCacheImpl.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/WriteCacheImpl.java index 1d4172b2bea..543b0b5a79b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/WriteCacheImpl.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cache/WriteCacheImpl.java @@ -19,40 +19,40 @@ */ package org.sonar.scanner.cache; +import com.google.protobuf.ByteString; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; +import java.io.OutputStream; +import java.util.HashSet; +import java.util.Set; +import java.util.zip.GZIPOutputStream; import org.sonar.api.batch.sensor.cache.ReadCache; -import org.sonar.scanner.scan.branch.BranchConfiguration; +import org.sonar.scanner.protocol.internal.ScannerInternal.SensorCacheEntry; +import org.sonar.scanner.protocol.output.FileStructure; -import static java.util.Collections.unmodifiableMap; import static org.sonar.api.utils.Preconditions.checkArgument; import static org.sonar.api.utils.Preconditions.checkNotNull; public class WriteCacheImpl implements ScannerWriteCache { private final ReadCache readCache; - private final BranchConfiguration branchConfiguration; - private final Map cache = new HashMap<>(); + private final Set keys = new HashSet<>(); + private final FileStructure fileStructure; - public WriteCacheImpl(ReadCache readCache, BranchConfiguration branchConfiguration) { + private OutputStream stream = null; + + public WriteCacheImpl(ReadCache readCache, FileStructure fileStructure) { this.readCache = readCache; - this.branchConfiguration = branchConfiguration; + this.fileStructure = fileStructure; } @Override public void write(String key, InputStream data) { checkNotNull(data); - checkKey(key); - if (branchConfiguration.isPullRequest()) { - return; - } try { - byte[] arr = data.readAllBytes(); - cache.put(key, arr); + write(key, data.readAllBytes()); } catch (IOException e) { - throw new IllegalStateException("Failed to read stream", e); + throw new IllegalStateException("Failed to read sensor write cache data", e); } } @@ -60,33 +60,48 @@ public class WriteCacheImpl implements ScannerWriteCache { public void write(String key, byte[] data) { checkNotNull(data); checkKey(key); - if (branchConfiguration.isPullRequest()) { - return; + try { + OutputStream out = getStream(); + toProto(key, data).writeDelimitedTo(out); + keys.add(key); + } catch (IOException e) { + throw new IllegalStateException("Failed to write to sensor cache file", e); + } + } + + private OutputStream getStream() throws IOException { + if (stream == null) { + stream = new GZIPOutputStream(new FileOutputStream(fileStructure.analysisCache())); } - cache.put(key, Arrays.copyOf(data, data.length)); + return stream; } @Override public void copyFromPrevious(String key) { checkArgument(readCache.contains(key), "Previous cache doesn't contain key '%s'", key); - checkKey(key); - if (branchConfiguration.isPullRequest()) { - return; - } - try { - cache.put(key, readCache.read(key).readAllBytes()); - } catch (IOException e) { - throw new IllegalStateException("Failed to read plugin cache for key " + key, e); - } + write(key, readCache.read(key)); + } + + private static SensorCacheEntry toProto(String key, byte[] data) { + return SensorCacheEntry.newBuilder() + .setKey(key) + .setData(ByteString.copyFrom(data)) + .build(); } @Override - public Map getCache() { - return unmodifiableMap(cache); + public void close() { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + throw new IllegalStateException("Failed to close sensor cache file", e); + } + } } private void checkKey(String key) { checkNotNull(key); - checkArgument(!cache.containsKey(key), "Cache already contains key '%s'", key); + checkArgument(!keys.contains(key), "Cache already contains key '%s'", key); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java index ba2149e9f1c..3e8af218976 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java @@ -32,16 +32,16 @@ import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.TextPointer; import org.sonar.api.batch.fs.TextRange; -import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.fs.internal.DefaultInputComponent; import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.scanner.fs.InputProject; import org.sonar.core.util.CloseableIterator; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReport.Component; import org.sonar.scanner.protocol.output.ScannerReport.Symbol; import org.sonar.scanner.protocol.output.ScannerReportReader; -import org.sonar.scanner.report.ReportPublisher; import org.sonar.scanner.report.ScannerReportUtils; import org.sonar.scanner.scan.SpringProjectScanContainer; import org.sonar.scanner.scan.filesystem.InputComponentStore; @@ -57,8 +57,8 @@ public class AnalysisResult implements AnalysisObserver { @Override public void analysisCompleted(SpringProjectScanContainer container) { LOG.info("Store analysis results in memory for later assertions in medium test"); - ReportPublisher reportPublisher = container.getComponentByType(ReportPublisher.class); - reader = new ScannerReportReader(reportPublisher.getReportDir().toFile()); + FileStructure fileStructure = container.getComponentByType(FileStructure.class); + reader = new ScannerReportReader(fileStructure); project = container.getComponentByType(InputProject.class); storeFs(container); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisCachePublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisCachePublisher.java index 258ff9fe521..bb3c6b7182a 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisCachePublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisCachePublisher.java @@ -19,37 +19,18 @@ */ package org.sonar.scanner.report; -import com.google.protobuf.ByteString; -import java.util.Map; -import org.sonar.scanner.cache.AnalysisCacheEnabled; import org.sonar.scanner.cache.ScannerWriteCache; -import org.sonar.scanner.protocol.internal.ScannerInternal; -import org.sonar.scanner.protocol.internal.ScannerInternal.AnalysisCacheMsg; import org.sonar.scanner.protocol.output.ScannerReportWriter; -import org.sonar.scanner.scan.branch.BranchConfiguration; public class AnalysisCachePublisher implements ReportPublisherStep { - private final AnalysisCacheEnabled analysisCacheEnabled; - private final BranchConfiguration branchConfiguration; private final ScannerWriteCache cache; - public AnalysisCachePublisher(AnalysisCacheEnabled analysisCacheEnabled, BranchConfiguration branchConfiguration, ScannerWriteCache cache) { - this.analysisCacheEnabled = analysisCacheEnabled; - this.branchConfiguration = branchConfiguration; + public AnalysisCachePublisher(ScannerWriteCache cache) { this.cache = cache; } @Override public void publish(ScannerReportWriter writer) { - if (!analysisCacheEnabled.isEnabled() || branchConfiguration.isPullRequest() || cache.getCache().isEmpty()) { - return; - } - AnalysisCacheMsg.Builder analysisCacheMsg = ScannerInternal.AnalysisCacheMsg.newBuilder(); - - for (Map.Entry entry : cache.getCache().entrySet()) { - analysisCacheMsg.putMap(entry.getKey(), ByteString.copyFrom(entry.getValue())); - } - - writer.writeAnalysisCache(analysisCacheMsg.build()); + cache.close(); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java index bb1ab78dd6f..a4783bab3f4 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java @@ -45,6 +45,7 @@ import org.sonar.api.utils.log.Loggers; import org.sonar.scanner.bootstrap.DefaultScannerWsClient; import org.sonar.scanner.bootstrap.GlobalAnalysisMode; import org.sonar.scanner.fs.InputModuleHierarchy; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReportReader; import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.scan.ScanProperties; @@ -94,7 +95,7 @@ public class ReportPublisher implements Startable { public ReportPublisher(ScanProperties properties, DefaultScannerWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher, InputModuleHierarchy moduleHierarchy, GlobalAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers, BranchConfiguration branchConfiguration, CeTaskReportDataHolder ceTaskReportDataHolder, AnalysisWarnings analysisWarnings, - JavaArchitectureInformationProvider javaArchitectureInformationProvider) { + JavaArchitectureInformationProvider javaArchitectureInformationProvider, FileStructure fileStructure) { this.wsClient = wsClient; this.server = server; this.contextPublisher = contextPublisher; @@ -105,11 +106,11 @@ public class ReportPublisher implements Startable { this.branchConfiguration = branchConfiguration; this.properties = properties; this.ceTaskReportDataHolder = ceTaskReportDataHolder; - this.reportDir = moduleHierarchy.root().getWorkDir().resolve("scanner-report"); + this.reportDir = fileStructure.root().toPath(); this.analysisWarnings = analysisWarnings; this.javaArchitectureInformationProvider = javaArchitectureInformationProvider; - this.writer = new ScannerReportWriter(reportDir.toFile()); - this.reader = new ScannerReportReader(reportDir.toFile()); + this.writer = new ScannerReportWriter(fileStructure); + this.reader = new ScannerReportReader(fileStructure); } @Override diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ScannerFileStructureProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ScannerFileStructureProvider.java new file mode 100644 index 00000000000..eea9d56119d --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ScannerFileStructureProvider.java @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scanner.report; + +import java.io.File; +import org.sonar.scanner.fs.InputModuleHierarchy; +import org.sonar.scanner.protocol.output.FileStructure; +import org.springframework.context.annotation.Bean; + +public class ScannerFileStructureProvider { + @Bean + public FileStructure fileStructure(InputModuleHierarchy inputModuleHierarchy) { + File reportDir = inputModuleHierarchy.root().getWorkDir().resolve("scanner-report").toFile(); + + if (!reportDir.exists() && !reportDir.mkdirs()) { + throw new IllegalStateException("Unable to create directory: " + reportDir); + } + return new FileStructure(reportDir); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java index 652860e4808..c5d38375188 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java @@ -91,6 +91,7 @@ import org.sonar.scanner.report.ContextPropertiesPublisher; import org.sonar.scanner.report.JavaArchitectureInformationProvider; import org.sonar.scanner.report.MetadataPublisher; import org.sonar.scanner.report.ReportPublisher; +import org.sonar.scanner.report.ScannerFileStructureProvider; import org.sonar.scanner.report.SourcePublisher; import org.sonar.scanner.report.TestExecutionPublisher; import org.sonar.scanner.repository.ContextPropertiesCache; @@ -242,6 +243,7 @@ public class SpringProjectScanContainer extends SpringComponentContainer { ScannerMetrics.class, JavaArchitectureInformationProvider.class, ReportPublisher.class, + ScannerFileStructureProvider.class, AnalysisContextReportPublisher.class, MetadataPublisher.class, ActiveRulesPublisher.class, diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheEnabledTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheEnabledTest.java index b4ee81594e8..a9bb804d5bf 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheEnabledTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheEnabledTest.java @@ -33,7 +33,7 @@ public class AnalysisCacheEnabledTest { private final AnalysisCacheEnabled analysisCacheEnabled = new AnalysisCacheEnabled(configuration); @Test - public void enabled_by_default() { + public void enabled_by_default_if_not_pr() { assertThat(analysisCacheEnabled.isEnabled()).isTrue(); } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorageTest.java index ae69cf3ae63..a4406a2be50 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorageTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorageTest.java @@ -21,12 +21,14 @@ package org.sonar.scanner.cache; import com.google.protobuf.ByteString; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Optional; import org.apache.commons.io.IOUtils; import org.junit.Test; -import org.sonar.scanner.protocol.internal.ScannerInternal.AnalysisCacheMsg; +import org.sonar.scanner.protocol.internal.ScannerInternal.SensorCacheEntry; +import org.sonar.scanner.protocol.internal.SensorCacheData; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; @@ -39,19 +41,21 @@ public class AnalysisCacheMemoryStorageTest { @Test public void storage_loads_with_loader() throws IOException { - when(loader.load()).thenReturn(Optional.of(AnalysisCacheMsg.newBuilder() - .putMap("key1", ByteString.copyFrom("value1", StandardCharsets.UTF_8)) + SensorCacheData data = new SensorCacheData(List.of(SensorCacheEntry.newBuilder() + .setKey("key1") + .setData(ByteString.copyFrom("value1", UTF_8)) .build())); + when(loader.load()).thenReturn(Optional.of(data)); storage.load(); verify(loader).load(); - assertThat(IOUtils.toString(storage.get("key1"), StandardCharsets.UTF_8)).isEqualTo("value1"); + assertThat(IOUtils.toString(storage.get("key1"), UTF_8)).isEqualTo("value1"); assertThat(storage.contains("key1")).isTrue(); } @Test public void get_throws_IAE_if_doesnt_contain_key() { - when(loader.load()).thenReturn(Optional.of(AnalysisCacheMsg.newBuilder().build())); + when(loader.load()).thenReturn(Optional.empty()); storage.load(); assertThat(storage.contains("key1")).isFalse(); assertThatThrownBy(() -> storage.get("key1")).isInstanceOf(IllegalArgumentException.class); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheProviderTest.java index e8325c25566..0dc0eb900b1 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheProviderTest.java @@ -19,8 +19,15 @@ */ package org.sonar.scanner.cache; +import java.io.IOException; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.sensor.cache.ReadCache; +import org.sonar.scanner.cache.AnalysisCacheProvider.NoOpReadCache; +import org.sonar.scanner.cache.AnalysisCacheProvider.NoOpWriteCache; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.scan.branch.BranchConfiguration; import static org.assertj.core.api.Assertions.assertThat; @@ -29,25 +36,43 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class AnalysisCacheProviderTest { - private final AnalysisCacheEnabled analysisCacheEnabled = mock(AnalysisCacheEnabled.class); private final AnalysisCacheMemoryStorage storage = mock(AnalysisCacheMemoryStorage.class); private final ReadCache readCache = mock(ReadCache.class); - private final AnalysisCacheProvider cacheProvider = new AnalysisCacheProvider(); private final BranchConfiguration branchConfiguration = mock(BranchConfiguration.class); + private final AnalysisCacheProvider cacheProvider = new AnalysisCacheProvider(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private FileStructure fileStructure; + + @Before + public void setup() throws IOException { + fileStructure = new FileStructure(temp.newFolder()); + when(branchConfiguration.isPullRequest()).thenReturn(false); + } + + @Test + public void provide_noop_writer_cache_if_pr() { + when(branchConfiguration.isPullRequest()).thenReturn(true); + when(analysisCacheEnabled.isEnabled()).thenReturn(true); + var cache = cacheProvider.provideWriter(analysisCacheEnabled, readCache, branchConfiguration, fileStructure); + assertThat(cache).isInstanceOf(AnalysisCacheProvider.NoOpWriteCache.class); + } @Test public void provide_noop_reader_cache_when_disable() { when(analysisCacheEnabled.isEnabled()).thenReturn(false); var cache = cacheProvider.provideReader(analysisCacheEnabled, storage); - assertThat(cache).isInstanceOf(AnalysisCacheProvider.NoOpReadCache.class); + assertThat(cache).isInstanceOf(NoOpReadCache.class); } @Test public void provide_noop_writer_cache_when_disable() { when(analysisCacheEnabled.isEnabled()).thenReturn(false); - var cache = cacheProvider.provideWriter(analysisCacheEnabled, readCache, branchConfiguration); - assertThat(cache).isInstanceOf(AnalysisCacheProvider.NoOpWriteCache.class); + var cache = cacheProvider.provideWriter(analysisCacheEnabled, readCache, branchConfiguration, fileStructure); + assertThat(cache).isInstanceOf(NoOpWriteCache.class); } @Test @@ -61,7 +86,7 @@ public class AnalysisCacheProviderTest { @Test public void provide_real_writer_cache_when_enable() { when(analysisCacheEnabled.isEnabled()).thenReturn(true); - var cache = cacheProvider.provideWriter(analysisCacheEnabled, readCache, branchConfiguration); + var cache = cacheProvider.provideWriter(analysisCacheEnabled, readCache, branchConfiguration, fileStructure); assertThat(cache).isInstanceOf(WriteCacheImpl.class); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoaderTest.java index 5a0253a89ef..52bc139c101 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoaderTest.java @@ -26,8 +26,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Optional; -import java.util.zip.DeflaterInputStream; -import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import org.junit.Before; import org.junit.Rule; @@ -37,7 +35,8 @@ import org.sonar.api.scanner.fs.InputProject; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.LogTester; import org.sonar.scanner.bootstrap.DefaultScannerWsClient; -import org.sonar.scanner.protocol.internal.ScannerInternal.AnalysisCacheMsg; +import org.sonar.scanner.protocol.internal.ScannerInternal.SensorCacheEntry; +import org.sonar.scanner.protocol.internal.SensorCacheData; import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonarqube.ws.client.HttpException; import org.sonarqube.ws.client.WsRequest; @@ -45,6 +44,7 @@ import org.sonarqube.ws.client.WsResponse; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.entry; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -52,8 +52,9 @@ import static org.mockito.Mockito.when; import static org.sonar.scanner.cache.DefaultAnalysisCacheLoader.CONTENT_ENCODING; public class DefaultAnalysisCacheLoaderTest { - private final static AnalysisCacheMsg MSG = AnalysisCacheMsg.newBuilder() - .putMap("key", ByteString.copyFrom("value", StandardCharsets.UTF_8)) + private final static SensorCacheEntry MSG = SensorCacheEntry.newBuilder() + .setKey("key") + .setData(ByteString.copyFrom("value", StandardCharsets.UTF_8)) .build(); private final WsResponse response = mock(WsResponse.class); private final DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class); @@ -73,8 +74,8 @@ public class DefaultAnalysisCacheLoaderTest { public void loads_content_and_logs_size() throws IOException { setResponse(MSG); when(response.header("Content-Length")).thenReturn(Optional.of("123")); - AnalysisCacheMsg msg = loader.load().get(); - assertThat(msg).isEqualTo(MSG); + SensorCacheData msg = loader.load().get(); + assertThat(msg.getEntries()).containsOnly(entry(MSG.getKey(), MSG.getData())); assertRequestPath("api/analysis_cache/get?project=myproject"); assertThat(logs.logs()).anyMatch(s -> s.startsWith("Load analysis cache (123 bytes)")); } @@ -84,9 +85,9 @@ public class DefaultAnalysisCacheLoaderTest { when(branchConfiguration.referenceBranchName()).thenReturn("name"); setResponse(MSG); - AnalysisCacheMsg msg = loader.load().get(); + SensorCacheData msg = loader.load().get(); - assertThat(msg).isEqualTo(MSG); + assertThat(msg.getEntries()).containsOnly(entry(MSG.getKey(), MSG.getData())); assertRequestPath("api/analysis_cache/get?project=myproject&branch=name"); assertThat(logs.logs()).anyMatch(s -> s.startsWith("Load analysis cache | time=")); } @@ -94,8 +95,8 @@ public class DefaultAnalysisCacheLoaderTest { @Test public void loads_compressed_content() throws IOException { setCompressedResponse(MSG); - AnalysisCacheMsg msg = loader.load().get(); - assertThat(msg).isEqualTo(MSG); + SensorCacheData msg = loader.load().get(); + assertThat(msg.getEntries()).containsOnly(entry(MSG.getKey(), MSG.getData())); } @Test @@ -127,11 +128,11 @@ public class DefaultAnalysisCacheLoaderTest { assertThat(requestCaptor.getValue().getPath()).isEqualTo(expectedPath); } - private void setResponse(AnalysisCacheMsg msg) throws IOException { + private void setResponse(SensorCacheEntry msg) throws IOException { when(response.contentStream()).thenReturn(createInputStream(msg)); } - private void setCompressedResponse(AnalysisCacheMsg msg) throws IOException { + private void setCompressedResponse(SensorCacheEntry msg) throws IOException { when(response.contentStream()).thenReturn(createCompressedInputStream(msg)); when(response.header(CONTENT_ENCODING)).thenReturn(Optional.of("gzip")); } @@ -141,16 +142,16 @@ public class DefaultAnalysisCacheLoaderTest { when(response.header(CONTENT_ENCODING)).thenReturn(Optional.of("gzip")); } - private InputStream createInputStream(AnalysisCacheMsg analysisCacheMsg) throws IOException { + private InputStream createInputStream(SensorCacheEntry analysisCacheMsg) throws IOException { ByteArrayOutputStream serialized = new ByteArrayOutputStream(analysisCacheMsg.getSerializedSize()); - analysisCacheMsg.writeTo(serialized); + analysisCacheMsg.writeDelimitedTo(serialized); return new ByteArrayInputStream(serialized.toByteArray()); } - private InputStream createCompressedInputStream(AnalysisCacheMsg analysisCacheMsg) throws IOException { + private InputStream createCompressedInputStream(SensorCacheEntry analysisCacheMsg) throws IOException { ByteArrayOutputStream serialized = new ByteArrayOutputStream(analysisCacheMsg.getSerializedSize()); GZIPOutputStream compressed = new GZIPOutputStream(serialized); - analysisCacheMsg.writeTo(compressed); + analysisCacheMsg.writeDelimitedTo(compressed); compressed.close(); return new ByteArrayInputStream(serialized.toByteArray()); } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/WriteCacheImplTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/WriteCacheImplTest.java index 9c1f1a840ba..fe86282effe 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/WriteCacheImplTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/WriteCacheImplTest.java @@ -20,48 +20,68 @@ package org.sonar.scanner.cache; import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; import java.io.InputStream; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.core.util.Protobuf; +import org.sonar.scanner.protocol.internal.ScannerInternal.SensorCacheEntry; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.scan.branch.BranchConfiguration; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.data.MapEntry.entry; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class WriteCacheImplTest { private final ReadCacheImpl readCache = mock(ReadCacheImpl.class); private final BranchConfiguration branchConfiguration = mock(BranchConfiguration.class); - private final WriteCacheImpl writeCache = new WriteCacheImpl(readCache, branchConfiguration); + private FileStructure fileStructure; + private WriteCacheImpl writeCache; + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Before + public void setUp() throws IOException { + fileStructure = new FileStructure(temp.newFolder()); + writeCache = new WriteCacheImpl(readCache, fileStructure); + } @Test - public void write_bytes_adds_entries() { + public void write_bytes_adds_entries() throws IOException { byte[] b1 = new byte[] {1, 2, 3}; byte[] b2 = new byte[] {3, 4}; writeCache.write("key", b1); writeCache.write("key2", b2); - assertThat(writeCache.getCache()).containsOnly(entry("key", b1), entry("key2", b2)); + assertThatCacheContains(Map.of("key", b1, "key2", b2)); } @Test - public void dont_write_if_its_pull_request() { + public void dont_write_if_its_pull_request() throws IOException { byte[] b1 = new byte[] {1, 2, 3}; when(branchConfiguration.isPullRequest()).thenReturn(true); writeCache.write("key1", b1); writeCache.write("key2", new ByteArrayInputStream(b1)); - assertThat(writeCache.getCache()).isEmpty(); + assertThatCacheContains(Map.of()); } @Test - public void write_inputStream_adds_entries() { + public void write_inputStream_adds_entries() throws IOException { byte[] b1 = new byte[] {1, 2, 3}; byte[] b2 = new byte[] {3, 4}; writeCache.write("key", new ByteArrayInputStream(b1)); writeCache.write("key2", new ByteArrayInputStream(b2)); - assertThat(writeCache.getCache()).containsOnly(entry("key", b1), entry("key2", b2)); + assertThatCacheContains(Map.of("key", b1, "key2", b2)); } @Test @@ -69,7 +89,6 @@ public class WriteCacheImplTest { byte[] b1 = new byte[] {1}; byte[] b2 = new byte[] {2}; - writeCache.write("key", b1); assertThatThrownBy(() -> writeCache.write("key", b2)) .isInstanceOf(IllegalArgumentException.class) @@ -78,19 +97,29 @@ public class WriteCacheImplTest { @Test public void copyFromPrevious_throws_IAE_if_read_cache_doesnt_contain_key() { - assertThatThrownBy(() -> writeCache.copyFromPrevious("key")) + assertThatThrownBy(() -> writeCache.copyFromPrevious("key")) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Previous cache doesn't contain key 'key'"); } @Test - public void copyFromPrevious_reads_from_readCache() { + public void copyFromPrevious_reads_from_readCache() throws IOException { byte[] b = new byte[] {1}; InputStream value = new ByteArrayInputStream(b); when(readCache.contains("key")).thenReturn(true); when(readCache.read("key")).thenReturn(value); writeCache.copyFromPrevious("key"); - assertThat(writeCache.getCache()).containsOnly(entry("key", b)); + assertThatCacheContains(Map.of("key", b)); + } + + private void assertThatCacheContains(Map expectedData) { + writeCache.close(); + File cacheFile = fileStructure.analysisCache(); + Iterable it = () -> Protobuf.readGzipStream(cacheFile, SensorCacheEntry.parser()); + Map data = StreamSupport.stream(it.spliterator(), false) + .collect(Collectors.toMap(SensorCacheEntry::getKey, e -> e.getData().toByteArray())); + + assertThat(data).containsAllEntriesOf(expectedData); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java index 865b365ee42..97e6faf3d97 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java @@ -47,6 +47,7 @@ import org.sonar.duplications.block.ByteArray; import org.sonar.duplications.index.CloneGroup; import org.sonar.duplications.index.ClonePart; import org.sonar.scanner.cpd.index.SonarCpdBlockIndex; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReport.Duplicate; import org.sonar.scanner.protocol.output.ScannerReport.Duplication; import org.sonar.scanner.protocol.output.ScannerReportReader; @@ -84,13 +85,14 @@ public class CpdExecutorTest { @Before public void setUp() throws IOException { File outputDir = temp.newFolder(); + FileStructure fileStructure = new FileStructure(outputDir); baseDir = temp.newFolder(); - when(publisher.getWriter()).thenReturn(new ScannerReportWriter(outputDir)); + when(publisher.getWriter()).thenReturn(new ScannerReportWriter(fileStructure)); DefaultInputProject project = TestInputFileBuilder.newDefaultInputProject("foo", baseDir); componentStore = new InputComponentStore(mock(BranchConfiguration.class), sonarRuntime); executor = new CpdExecutor(settings, index, publisher, componentStore, executorService); - reader = new ScannerReportReader(outputDir); + reader = new ScannerReportReader(fileStructure); batchComponent1 = createComponent("src/Foo.php", 5); batchComponent2 = createComponent("src/Foo2.php", 5); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java index 45879eb75b5..26d02e97523 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java @@ -59,7 +59,7 @@ import org.sonar.batch.bootstrapper.EnvironmentInformation; import org.sonar.batch.bootstrapper.LogOutput; import org.sonar.scanner.bootstrap.GlobalAnalysisMode; import org.sonar.scanner.cache.AnalysisCacheLoader; -import org.sonar.scanner.protocol.internal.ScannerInternal; +import org.sonar.scanner.protocol.internal.SensorCacheData; import org.sonar.scanner.report.CeTaskReportDataHolder; import org.sonar.scanner.repository.FileData; import org.sonar.scanner.repository.MetricsRepository; @@ -525,7 +525,7 @@ public class ScannerMediumTester extends ExternalResource { @Priority(1) private static class FakeAnalysisCacheLoader implements AnalysisCacheLoader { @Override - public Optional load() { + public Optional load() { return Optional.empty(); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java index bbdac66a16a..ec81163c4c6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java @@ -35,6 +35,7 @@ import org.sonar.api.SonarEdition; import org.sonar.api.utils.log.LogTester; import org.sonar.scanner.mediumtest.ScannerMediumTester; import org.sonar.scanner.mediumtest.ScannerMediumTester.AnalysisBuilder; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReport.Changesets.Changeset; import org.sonar.scanner.protocol.output.ScannerReport.Component; @@ -108,7 +109,8 @@ public class ScmMediumTest { private ScannerReport.Changesets getChangesets(File baseDir, String path) { File reportDir = new File(baseDir, ".sonar/scanner-report"); - ScannerReportReader reader = new ScannerReportReader(reportDir); + FileStructure fileStructure = new FileStructure(reportDir); + ScannerReportReader reader = new ScannerReportReader(fileStructure); Component project = reader.readComponent(reader.readMetadata().getRootComponentRef()); for (Integer fileRef : project.getChildRefList()) { diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java index bebc30951b0..19799751906 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java @@ -29,6 +29,7 @@ import org.sonar.api.batch.rule.internal.NewActiveRule; import org.sonar.api.rule.RuleKey; import org.sonar.core.util.CloseableIterator; import org.sonar.scanner.protocol.Constants; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReportReader; import org.sonar.scanner.protocol.output.ScannerReportWriter; @@ -44,7 +45,8 @@ public class ActiveRulesPublisherTest { @Test public void write() throws Exception { File outputDir = temp.newFolder(); - ScannerReportWriter writer = new ScannerReportWriter(outputDir); + FileStructure fileStructure = new FileStructure(outputDir); + ScannerReportWriter writer = new ScannerReportWriter(fileStructure); NewActiveRule ar = new NewActiveRule.Builder() .setRuleKey(RuleKey.of("java", "S001")) @@ -59,7 +61,7 @@ public class ActiveRulesPublisherTest { ActiveRulesPublisher underTest = new ActiveRulesPublisher(activeRules); underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); + ScannerReportReader reader = new ScannerReportReader(fileStructure); try (CloseableIterator readIt = reader.readActiveRules()) { ScannerReport.ActiveRule reportAr = readIt.next(); assertThat(reportAr.getRuleRepository()).isEqualTo("java"); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisCachePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisCachePublisherTest.java index 77157974080..573b8ce5c48 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisCachePublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisCachePublisherTest.java @@ -20,73 +20,35 @@ package org.sonar.scanner.report; import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Map; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import org.sonar.scanner.cache.AnalysisCacheEnabled; import org.sonar.scanner.cache.ScannerWriteCache; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReportWriter; -import org.sonar.scanner.scan.branch.BranchConfiguration; -import static java.util.Collections.emptyMap; -import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; public class AnalysisCachePublisherTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); private final ScannerWriteCache writeCache = mock(ScannerWriteCache.class); - private final AnalysisCacheEnabled analysisCacheEnabled = mock(AnalysisCacheEnabled.class); - private final BranchConfiguration branchConfiguration = mock(BranchConfiguration.class); - private final AnalysisCachePublisher publisher = new AnalysisCachePublisher(analysisCacheEnabled, branchConfiguration, writeCache); + private final AnalysisCachePublisher publisher = new AnalysisCachePublisher(writeCache); private ScannerReportWriter scannerReportWriter; @Before public void before() throws IOException { - scannerReportWriter = new ScannerReportWriter(temp.newFolder()); + FileStructure fileStructure = new FileStructure(temp.newFolder()); + scannerReportWriter = new ScannerReportWriter(fileStructure); } @Test - public void publish_does_nothing_if_cache_not_enabled() { - when(analysisCacheEnabled.isEnabled()).thenReturn(false); + public void publish_closes_cache() { publisher.publish(scannerReportWriter); - verifyNoInteractions(writeCache); - assertThat(scannerReportWriter.getFileStructure().root()).isEmptyDirectory(); - } - - @Test - public void publish_does_nothing_if_pull_request() { - when(analysisCacheEnabled.isEnabled()).thenReturn(true); - when(branchConfiguration.isPullRequest()).thenReturn(true); - publisher.publish(scannerReportWriter); - verifyNoInteractions(writeCache); - assertThat(scannerReportWriter.getFileStructure().root()).isEmptyDirectory(); - } - - @Test - public void publish_cache() { - when(writeCache.getCache()).thenReturn(Map.of("key1", "value1".getBytes(StandardCharsets.UTF_8))); - when(analysisCacheEnabled.isEnabled()).thenReturn(true); - publisher.publish(scannerReportWriter); - verify(writeCache, times(2)).getCache(); - assertThat(scannerReportWriter.getFileStructure().analysisCache()).exists(); - } - - @Test - public void publish_empty_cache() { - when(writeCache.getCache()).thenReturn(emptyMap()); - when(analysisCacheEnabled.isEnabled()).thenReturn(true); - publisher.publish(scannerReportWriter); - verify(writeCache).getCache(); - assertThat(scannerReportWriter.getFileStructure().analysisCache()).doesNotExist(); + verify(writeCache).close(); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java index f29233327fb..8ee25330d28 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java @@ -41,6 +41,7 @@ import org.sonar.core.platform.PluginInfo; import org.sonar.scanner.bootstrap.GlobalServerSettings; import org.sonar.scanner.bootstrap.ScannerPluginRepository; import org.sonar.scanner.fs.InputModuleHierarchy; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.scan.ProjectServerSettings; import org.sonar.scanner.scan.filesystem.InputComponentStore; @@ -64,30 +65,26 @@ public class AnalysisContextReportPublisherTest { public TemporaryFolder temp = new TemporaryFolder(); private final ScannerPluginRepository pluginRepo = mock(ScannerPluginRepository.class); - private AnalysisContextReportPublisher publisher; - private System2 system2; - private GlobalServerSettings globalServerSettings; - private InputModuleHierarchy hierarchy; - private InputComponentStore store; - private ProjectServerSettings projectServerSettings; + private final System2 system2 = mock(System2.class); + private final GlobalServerSettings globalServerSettings = mock(GlobalServerSettings.class); + private final InputModuleHierarchy hierarchy = mock(InputModuleHierarchy.class); + private final InputComponentStore store = mock(InputComponentStore.class); + private final ProjectServerSettings projectServerSettings = mock(ProjectServerSettings.class); + private final AnalysisContextReportPublisher publisher = new AnalysisContextReportPublisher(projectServerSettings, pluginRepo, system2, globalServerSettings, hierarchy, store); + private ScannerReportWriter writer; @Before - public void prepare() { + public void prepare() throws IOException { logTester.setLevel(LoggerLevel.INFO); - system2 = mock(System2.class); + FileStructure fileStructure = new FileStructure(temp.newFolder()); + writer = new ScannerReportWriter(fileStructure); when(system2.properties()).thenReturn(new Properties()); - globalServerSettings = mock(GlobalServerSettings.class); - hierarchy = mock(InputModuleHierarchy.class); - store = mock(InputComponentStore.class); - projectServerSettings = mock(ProjectServerSettings.class); - publisher = new AnalysisContextReportPublisher(projectServerSettings, pluginRepo, system2, globalServerSettings, hierarchy, store); } @Test public void shouldOnlyDumpPluginsByDefault() throws Exception { when(pluginRepo.getExternalPluginsInfos()).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())); @@ -104,7 +101,6 @@ public class AnalysisContextReportPublisherTest { @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()) @@ -123,7 +119,6 @@ public class AnalysisContextReportPublisherTest { @Test public void dumpServerSideProjectProps() throws Exception { logTester.setLevel(LoggerLevel.DEBUG); - ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) @@ -150,7 +145,6 @@ public class AnalysisContextReportPublisherTest { @Test public void shouldNotDumpSensitiveModuleProperties() throws Exception { - ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) .setWorkDir(temp.newFolder()) @@ -175,7 +169,6 @@ public class AnalysisContextReportPublisherTest { @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()) @@ -190,14 +183,13 @@ public class AnalysisContextReportPublisherTest { assertThat(FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8)).containsSubsequence( "sonar.aVeryLongProp=" + StringUtils.repeat("abcde", 199) + "ab...", - "sonar.projectBaseDir=" + baseDir.toString(), + "sonar.projectBaseDir=" + baseDir, "sonar.projectKey=foo"); } // SONAR-7598 @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()) @@ -217,7 +209,6 @@ public class AnalysisContextReportPublisherTest { @Test public void dontDumpParentProps() throws Exception { logTester.setLevel(LoggerLevel.DEBUG); - ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); DefaultInputModule module = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) @@ -253,7 +244,6 @@ public class AnalysisContextReportPublisherTest { @Test public void init_splitsPluginsByTypeInTheFile() throws IOException { - ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder()); DefaultInputModule parent = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(temp.newFolder()) .setWorkDir(temp.newFolder()) diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisWarningsPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisWarningsPublisherTest.java index b5341358134..47b5fc1aad0 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisWarningsPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisWarningsPublisherTest.java @@ -23,12 +23,14 @@ import com.google.common.collect.Lists; import java.io.File; import java.io.IOException; import java.util.List; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.api.utils.System2; import org.sonar.scanner.notifications.DefaultAnalysisWarnings; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReportReader; import org.sonar.scanner.protocol.output.ScannerReportWriter; @@ -41,19 +43,18 @@ public class AnalysisWarningsPublisherTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); - private final AnalysisWarnings analysisWarnings; - private final AnalysisWarningsPublisher underTest; + private final DefaultAnalysisWarnings analysisWarnings = new DefaultAnalysisWarnings(mock(System2.class)); + private final AnalysisWarningsPublisher underTest = new AnalysisWarningsPublisher(analysisWarnings); + private FileStructure fileStructure; - public AnalysisWarningsPublisherTest() { - DefaultAnalysisWarnings defaultAnalysisWarnings = new DefaultAnalysisWarnings(mock(System2.class)); - this.analysisWarnings = defaultAnalysisWarnings; - this.underTest = new AnalysisWarningsPublisher(defaultAnalysisWarnings); + @Before + public void setUp() throws IOException { + fileStructure = new FileStructure(temp.newFolder()); } @Test public void publish_warnings() throws IOException { - File outputDir = temp.newFolder(); - ScannerReportWriter writer = new ScannerReportWriter(outputDir); + ScannerReportWriter writer = new ScannerReportWriter(fileStructure); String warning1 = "warning 1"; String warning2 = "warning 2"; @@ -63,7 +64,7 @@ public class AnalysisWarningsPublisherTest { underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); + ScannerReportReader reader = new ScannerReportReader(fileStructure); List warnings = Lists.newArrayList(reader.readAnalysisWarnings()); assertThat(warnings) @@ -74,13 +75,13 @@ public class AnalysisWarningsPublisherTest { @Test public void do_not_write_warnings_report_when_empty() throws IOException { File outputDir = temp.newFolder(); - ScannerReportWriter writer = new ScannerReportWriter(outputDir); + ScannerReportWriter writer = new ScannerReportWriter(fileStructure); underTest.publish(writer); assertThat(writer.getFileStructure().analysisWarnings()).doesNotExist(); - ScannerReportReader reader = new ScannerReportReader(outputDir); + ScannerReportReader reader = new ScannerReportReader(fileStructure); List warnings = Lists.newArrayList(reader.readAnalysisWarnings()); assertThat(warnings).isEmpty(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java index ae84d54d3bd..d9de9f51e4b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java @@ -37,6 +37,7 @@ import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.batch.scm.ScmProvider; import org.sonar.api.utils.log.LogTester; import org.sonar.scanner.fs.InputModuleHierarchy; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReportReader; import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.repository.ReferenceBranchSupplier; @@ -65,6 +66,7 @@ public class ChangedLinesPublisherTest { private final BranchConfiguration branchConfiguration = mock(BranchConfiguration.class); private final ReferenceBranchSupplier referenceBranchSupplier = mock(ReferenceBranchSupplier.class); private ScannerReportWriter writer; + private FileStructure fileStructure; private final ScmProvider provider = mock(ScmProvider.class); private final DefaultInputProject project = mock(DefaultInputProject.class); @@ -78,7 +80,8 @@ public class ChangedLinesPublisherTest { @Before public void setUp() { - writer = new ScannerReportWriter(temp.getRoot()); + fileStructure = new FileStructure(temp.getRoot()); + writer = new ScannerReportWriter(fileStructure); when(branchConfiguration.isPullRequest()).thenReturn(true); when(scmConfiguration.isDisabled()).thenReturn(false); when(scmConfiguration.provider()).thenReturn(provider); @@ -198,7 +201,7 @@ public class ChangedLinesPublisherTest { private void assertPublished(DefaultInputFile file, Set lines) { assertThat(new File(temp.getRoot(), "changed-lines-" + file.scannerId() + ".pb")).exists(); - ScannerReportReader reader = new ScannerReportReader(temp.getRoot()); + ScannerReportReader reader = new ScannerReportReader(fileStructure); assertThat(reader.readComponentChangedLines(file.scannerId()).getLineList()).containsExactlyElementsOf(lines); } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java index b8045a51127..b758bb5ea15 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java @@ -56,15 +56,16 @@ public class ComponentsPublisherTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); - private File outputDir; + private FileStructure fileStructure; private ScannerReportWriter writer; private BranchConfiguration branchConfiguration; @Before public void setUp() throws IOException { branchConfiguration = mock(BranchConfiguration.class); - outputDir = temp.newFolder(); - writer = new ScannerReportWriter(outputDir); + File outputDir = temp.newFolder(); + fileStructure = new FileStructure(outputDir); + writer = new ScannerReportWriter(fileStructure); } @Test @@ -124,7 +125,7 @@ public class ComponentsPublisherTest { // no such reference assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 8)).isFalse(); - ScannerReportReader reader = new ScannerReportReader(outputDir); + ScannerReportReader reader = new ScannerReportReader(fileStructure); Component rootProtobuf = reader.readComponent(1); assertThat(rootProtobuf.getKey()).isEqualTo("foo"); assertThat(rootProtobuf.getDescription()).isEqualTo("Root description"); @@ -197,7 +198,7 @@ public class ComponentsPublisherTest { assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue(); - ScannerReportReader reader = new ScannerReportReader(outputDir); + ScannerReportReader reader = new ScannerReportReader(fileStructure); Component rootProtobuf = reader.readComponent(1); assertThat(rootProtobuf.getKey()).isEqualTo("foo"); assertThat(rootProtobuf.getName()).isEmpty(); @@ -225,7 +226,7 @@ public class ComponentsPublisherTest { ComponentsPublisher publisher = new ComponentsPublisher(project, store); publisher.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); + ScannerReportReader reader = new ScannerReportReader(fileStructure); Component rootProtobuf = reader.readComponent(1); assertThat(rootProtobuf.getLinkCount()).isEqualTo(2); assertThat(rootProtobuf.getLink(0).getType()).isEqualTo(ComponentLinkType.HOME); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java index c3617f925e3..453c5864ead 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java @@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableMap; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -47,6 +46,7 @@ import org.sonar.scanner.bootstrap.ScannerPlugin; import org.sonar.scanner.bootstrap.ScannerPluginRepository; import org.sonar.scanner.cpd.CpdSettings; import org.sonar.scanner.fs.InputModuleHierarchy; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReportReader; import org.sonar.scanner.protocol.output.ScannerReportWriter; @@ -84,9 +84,14 @@ public class MetadataPublisherTest { private final ScmProvider scmProvider = mock(ScmProvider.class); private final ScmRevision scmRevision = mock(ScmRevision.class); private final InputComponentStore componentStore = mock(InputComponentStore.class); + private ScannerReportWriter writer; + private ScannerReportReader reader; @Before public void prepare() throws IOException { + FileStructure fileStructure = new FileStructure(temp.newFolder()); + writer = new ScannerReportWriter(fileStructure); + reader = new ScannerReportReader(fileStructure); when(projectInfo.getAnalysisDate()).thenReturn(new Date(1234567L)); when(scmProvider.relativePathFromScmRoot(any(Path.class))).thenReturn(Paths.get("dummy/path")); when(scmProvider.revisionId(any(Path.class))).thenReturn("dummy-sha1"); @@ -120,18 +125,15 @@ public class MetadataPublisherTest { } @Test - public void write_metadata() throws Exception { + public void write_metadata() { Date date = new Date(); when(qProfiles.findAll()).thenReturn(Collections.singletonList(new QProfile("q1", "Q1", "java", date))); when(pluginRepository.getPluginsByKey()).thenReturn(ImmutableMap.of( - "java", new ScannerPlugin("java", 12345L, PluginType.BUNDLED, null), + "java", new ScannerPlugin("java", 12345L, PluginType.BUNDLED, null), "php", new ScannerPlugin("php", 45678L, PluginType.BUNDLED, null))); - File outputDir = temp.newFolder(); - ScannerReportWriter writer = new ScannerReportWriter(outputDir); when(referenceBranchSupplier.getFromProperties()).thenReturn("newCodeReference"); underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L); assertThat(metadata.getNewCodeReferenceBranch()).isEqualTo("newCodeReference"); @@ -146,9 +148,9 @@ public class MetadataPublisherTest { .setRulesUpdatedAt(date.getTime()) .build())); assertThat(metadata.getPluginsByKey()).containsOnly(entry("java", org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin.newBuilder() - .setKey("java") - .setUpdatedAt(12345) - .build()), + .setKey("java") + .setUpdatedAt(12345) + .build()), entry("php", org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin.newBuilder() .setKey("php") .setUpdatedAt(45678) @@ -156,30 +158,22 @@ public class MetadataPublisherTest { } @Test - public void write_not_analysed_file_counts() throws Exception { + public void write_not_analysed_file_counts() { when(componentStore.getNotAnalysedFilesByLanguage()).thenReturn(ImmutableMap.of("c", 10, "cpp", 20)); - File outputDir = temp.newFolder(); - ScannerReportWriter writer = new ScannerReportWriter(outputDir); - underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getNotAnalyzedFilesByLanguageMap()).contains(entry("c", 10), entry("cpp", 20)); } @Test @UseDataProvider("projectVersions") - public void write_project_version(@Nullable String projectVersion, String expected) throws Exception { + public void write_project_version(@Nullable String projectVersion, String expected) { when(projectInfo.getProjectVersion()).thenReturn(Optional.ofNullable(projectVersion)); - File outputDir = temp.newFolder(); - ScannerReportWriter writer = new ScannerReportWriter(outputDir); - underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getProjectVersion()).isEqualTo(expected); } @@ -197,15 +191,11 @@ public class MetadataPublisherTest { @Test @UseDataProvider("buildStrings") - public void write_buildString(@Nullable String buildString, String expected) throws Exception { + public void write_buildString(@Nullable String buildString, String expected) { when(projectInfo.getBuildString()).thenReturn(Optional.ofNullable(buildString)); - File outputDir = temp.newFolder(); - ScannerReportWriter writer = new ScannerReportWriter(outputDir); - underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getBuildString()).isEqualTo(expected); } @@ -222,7 +212,7 @@ public class MetadataPublisherTest { } @Test - public void write_branch_info() throws Exception { + public void write_branch_info() { String branchName = "name"; String targetName = "target"; @@ -230,10 +220,8 @@ public class MetadataPublisherTest { when(branches.branchType()).thenReturn(BranchType.BRANCH); when(branches.targetBranchName()).thenReturn(targetName); - File outputDir = temp.newFolder(); - underTest.publish(new ScannerReportWriter(outputDir)); + underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getBranchName()).isEqualTo(branchName); assertThat(metadata.getBranchType()).isEqualTo(ScannerReport.Metadata.BranchType.BRANCH); @@ -242,29 +230,25 @@ public class MetadataPublisherTest { } @Test - public void dont_write_new_code_reference_if_not_specified_in_properties() throws IOException { + public void dont_write_new_code_reference_if_not_specified_in_properties() { when(referenceBranchSupplier.get()).thenReturn("ref"); when(referenceBranchSupplier.getFromProperties()).thenReturn(null); - File outputDir = temp.newFolder(); - underTest.publish(new ScannerReportWriter(outputDir)); + underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getNewCodeReferenceBranch()).isEmpty(); } @Test - public void write_project_basedir() throws Exception { + public void write_project_basedir() { String path = "some/dir"; Path relativePathFromScmRoot = Paths.get(path); when(scmProvider.relativePathFromScmRoot(any(Path.class))).thenReturn(relativePathFromScmRoot); - File outputDir = temp.newFolder(); - underTest.publish(new ScannerReportWriter(outputDir)); + underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getRelativePathFromScmRoot()).isEqualTo(path); } @@ -274,16 +258,14 @@ public class MetadataPublisherTest { String revisionId = "some-sha1"; when(scmRevision.get()).thenReturn(Optional.of(revisionId)); - File outputDir = temp.newFolder(); - underTest.publish(new ScannerReportWriter(outputDir)); + underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getScmRevisionId()).isEqualTo(revisionId); } @Test - public void should_not_crash_when_scm_provider_does_not_support_relativePathFromScmRoot() throws IOException { + public void should_not_crash_when_scm_provider_does_not_support_relativePathFromScmRoot() { ScmProvider fakeScmProvider = new ScmProvider() { @Override public String key() { @@ -292,10 +274,8 @@ public class MetadataPublisherTest { }; when(scmConfiguration.provider()).thenReturn(fakeScmProvider); - File outputDir = temp.newFolder(); - underTest.publish(new ScannerReportWriter(outputDir)); + underTest.publish(writer); - ScannerReportReader reader = new ScannerReportReader(outputDir); ScannerReport.Metadata metadata = reader.readMetadata(); assertThat(metadata.getRelativePathFromScmRoot()).isEmpty(); } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java index 71764605df1..ffbe3971c1a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java @@ -42,6 +42,7 @@ import org.sonar.api.utils.log.LoggerLevel; import org.sonar.scanner.bootstrap.DefaultScannerWsClient; import org.sonar.scanner.bootstrap.GlobalAnalysisMode; import org.sonar.scanner.fs.InputModuleHierarchy; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.scan.ScanProperties; import org.sonar.scanner.scan.branch.BranchConfiguration; @@ -83,6 +84,7 @@ public class ReportPublisherTest { private CeTaskReportDataHolder reportMetadataHolder = mock(CeTaskReportDataHolder.class); private ReportPublisher underTest; private AnalysisWarnings analysisWarnings = mock(AnalysisWarnings.class); + private FileStructure fileStructure; private JavaArchitectureInformationProvider javaArchitectureInformationProvider = mock(JavaArchitectureInformationProvider.class); @Before @@ -90,13 +92,14 @@ public class ReportPublisherTest { root = new DefaultInputModule( ProjectDefinition.create().setKey("org.sonarsource.sonarqube:sonarqube").setBaseDir(reportTempFolder.newDir()).setWorkDir(reportTempFolder.getRoot())); when(moduleHierarchy.root()).thenReturn(root); + fileStructure = new FileStructure(reportTempFolder.getRoot()); when(server.getPublicRootUrl()).thenReturn("https://localhost"); when(server.getVersion()).thenReturn("6.4"); when(properties.metadataFilePath()).thenReturn(reportTempFolder.newDir().toPath() .resolve("folder") .resolve("report-task.txt")); underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, reportTempFolder, - new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider); + new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider, fileStructure); } @Test @@ -193,7 +196,7 @@ public class ReportPublisherTest { when(branchConfiguration.branchType()).thenReturn(BRANCH); when(branchConfiguration.branchName()).thenReturn("branch-6.7"); ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class), - new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider); + new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider, fileStructure); underTest.prepareAndDumpMetadata("TASK-123"); @@ -214,7 +217,7 @@ public class ReportPublisherTest { when(branchConfiguration.pullRequestKey()).thenReturn("105"); ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class), - new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider); + new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider, fileStructure); underTest.prepareAndDumpMetadata("TASK-123"); @@ -279,20 +282,17 @@ public class ReportPublisherTest { @Test public void should_not_delete_report_if_property_is_set() throws IOException { when(properties.shouldKeepReport()).thenReturn(true); - Path reportDir = reportTempFolder.getRoot().toPath().resolve("scanner-report"); underTest.start(); underTest.stop(); - assertThat(reportDir).isDirectory(); + assertThat(fileStructure.root()).isDirectory(); } @Test public void should_delete_report_by_default() throws IOException { - Path reportDir = reportTempFolder.getRoot().toPath().resolve("scanner-report"); - underTest.start(); underTest.stop(); - assertThat(reportDir).doesNotExist(); + assertThat(fileStructure.root()).doesNotExist(); } @Test diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java index 444dc3b1bba..feb78850d88 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java @@ -31,6 +31,7 @@ import org.sonar.api.SonarRuntime; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputProject; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; +import org.sonar.scanner.protocol.output.FileStructure; import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonar.scanner.scan.filesystem.InputComponentStore; @@ -64,7 +65,8 @@ public class SourcePublisherTest { publisher = new SourcePublisher(componentStore); File outputDir = temp.newFolder(); - writer = new ScannerReportWriter(outputDir); + FileStructure fileStructure = new FileStructure(outputDir); + writer = new ScannerReportWriter(fileStructure); } @Test diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java index 2b0ee2953a4..10f0b9662e8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java @@ -96,8 +96,9 @@ public class DefaultSensorStorageTest { reportPublisher = mock(ReportPublisher.class); final File reportDir = temp.newFolder(); - reportWriter = new ScannerReportWriter(reportDir); - reportReader = new ScannerReportReader(reportDir); + FileStructure fileStructure = new FileStructure(reportDir); + reportWriter = new ScannerReportWriter(fileStructure); + reportReader = new ScannerReportReader(fileStructure); when(reportPublisher.getWriter()).thenReturn(reportWriter); when(reportPublisher.getReader()).thenReturn(reportReader); -- cgit v1.2.3