Browse Source

SONAR-6770 Improve logging of cache usage

tags/5.2-RC1
Duarte Meneses 9 years ago
parent
commit
d5f10d28f6
27 changed files with 393 additions and 162 deletions
  1. 31
    0
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/AbstractServerLoader.java
  2. 27
    9
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java
  3. 1
    1
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
  4. 68
    36
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoader.java
  5. 41
    0
      sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoaderResult.java
  6. 9
    3
      sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java
  7. 50
    34
      sonar-batch/src/main/java/org/sonar/batch/issue/tracking/ServerIssueRepository.java
  8. 17
    4
      sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
  9. 7
    3
      sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalRepositoriesLoader.java
  10. 11
    3
      sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
  11. 6
    4
      sonar-batch/src/main/java/org/sonar/batch/repository/DefaultServerIssuesLoader.java
  12. 2
    0
      sonar-batch/src/main/java/org/sonar/batch/repository/GlobalRepositoriesLoader.java
  13. 8
    3
      sonar-batch/src/main/java/org/sonar/batch/repository/GlobalRepositoriesProvider.java
  14. 2
    0
      sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java
  15. 9
    2
      sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesProvider.java
  16. 1
    1
      sonar-batch/src/main/java/org/sonar/batch/repository/ServerIssuesLoader.java
  17. 21
    10
      sonar-batch/src/main/java/org/sonar/batch/repository/user/UserRepository.java
  18. 8
    3
      sonar-batch/src/main/java/org/sonar/batch/rule/DefaultRulesLoader.java
  19. 2
    0
      sonar-batch/src/main/java/org/sonar/batch/rule/RulesLoader.java
  20. 14
    0
      sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java
  21. 6
    5
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java
  22. 19
    28
      sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTest.java
  23. 4
    3
      sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java
  24. 8
    5
      sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java
  25. 3
    2
      sonar-batch/src/test/java/org/sonar/batch/repository/DefaultServerIssuesLoaderTest.java
  26. 3
    2
      sonar-batch/src/test/java/org/sonar/batch/repository/user/UserRepositoryTest.java
  27. 15
    1
      sonar-batch/src/test/java/org/sonar/batch/rule/DefaultRulesLoaderTest.java

+ 31
- 0
sonar-batch/src/main/java/org/sonar/batch/bootstrap/AbstractServerLoader.java View File

@@ -0,0 +1,31 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube 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.
*
* SonarQube 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.batch.bootstrap;

public class AbstractServerLoader {
protected Boolean loadedFromCache = null;

public boolean loadedFromCache() {
if (loadedFromCache == null) {
throw new IllegalStateException("Didn't load");
}
return loadedFromCache;
}
}

+ 27
- 9
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java View File

@@ -19,8 +19,6 @@
*/
package org.sonar.batch.bootstrap;

import com.google.common.io.Files;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;

@@ -54,18 +52,25 @@ public class BatchPluginInstaller implements PluginInstaller {
private final WSLoader wsLoader;
private final FileCache fileCache;
private final BatchPluginPredicate pluginPredicate;
private final ServerClient serverClient;

public BatchPluginInstaller(WSLoader wsLoader, FileCache fileCache, BatchPluginPredicate pluginPredicate) {
public BatchPluginInstaller(WSLoader wsLoader, ServerClient serverClient, FileCache fileCache, BatchPluginPredicate pluginPredicate) {
this.wsLoader = wsLoader;
this.fileCache = fileCache;
this.pluginPredicate = pluginPredicate;
this.serverClient = serverClient;
}

@Override
public Map<String, PluginInfo> installRemotes() {
return loadPlugins(listRemotePlugins());
}

private Map<String, PluginInfo> loadPlugins(List<RemotePlugin> remotePlugins) {
Map<String, PluginInfo> infosByKey = new HashMap<>();
List<RemotePlugin> remotePlugins = listRemotePlugins();
Profiler profiler = Profiler.create(LOG).startDebug("Load plugins");

for (RemotePlugin remotePlugin : remotePlugins) {
if (pluginPredicate.apply(remotePlugin.getKey())) {
File jarFile = download(remotePlugin);
@@ -73,6 +78,7 @@ public class BatchPluginInstaller implements PluginInstaller {
infosByKey.put(info.getKey(), info);
}
}

profiler.stopDebug();
return infosByKey;
}
@@ -100,7 +106,7 @@ public class BatchPluginInstaller implements PluginInstaller {
LOG.info("Download {}", file.getFilename());
}

Files.write(wsLoader.load(url), toFile);
serverClient.download(url, toFile);
}
});

@@ -115,10 +121,8 @@ public class BatchPluginInstaller implements PluginInstaller {
@VisibleForTesting
List<RemotePlugin> listRemotePlugins() {
try {
Profiler profiler = Profiler.create(LOG).startInfo("Load plugins index");
String indexContent = wsLoader.loadString(PLUGINS_INDEX_URL);
profiler.stopInfo();
String[] rows = StringUtils.split(indexContent, CharUtils.LF);
String pluginIndex = loadPluginIndex();
String[] rows = StringUtils.split(pluginIndex, CharUtils.LF);
List<RemotePlugin> result = Lists.newArrayList();
for (String row : rows) {
result.add(RemotePlugin.unmarshal(row));
@@ -129,4 +133,18 @@ public class BatchPluginInstaller implements PluginInstaller {
throw new IllegalStateException("Fail to load plugin index: " + PLUGINS_INDEX_URL, e);
}
}

private String loadPluginIndex() {
Profiler profiler = Profiler.create(LOG).startInfo("Load plugins index");
WSLoaderResult<String> wsResult = wsLoader.loadString(PLUGINS_INDEX_URL);

if (wsResult.isFromCache()) {
profiler.stopInfo("Load plugins index (done from cache)");
} else {
profiler.stopInfo();
}

return wsResult.get();
}

}

+ 1
- 1
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java View File

@@ -107,7 +107,7 @@ public class ServerClient {

/**
* @throws IllegalStateException on I/O error, not limited to the network connection and if HTTP response code > 400 and wrapHttpException is true
* @throws HttpException if HTTP response code > 400 and wrapHttpException is false
* @throws HttpDownloader.HttpException if HTTP response code > 400 and wrapHttpException is false
*/
public InputStream load(String pathStartingWithSlash, String requestMethod, boolean wrapHttpException, @Nullable Integer connectTimeoutMs,
@Nullable Integer readTimeoutMs) {

+ 68
- 36
sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoader.java View File

@@ -19,6 +19,9 @@
*/
package org.sonar.batch.bootstrap;

import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

import javax.annotation.Nonnull;

import org.sonar.api.utils.HttpDownloader;
@@ -34,6 +37,7 @@ import static org.sonar.batch.bootstrap.WSLoader.LoadStrategy.*;
import org.sonar.home.cache.PersistentCache;

public class WSLoader {
private static final Logger LOG = Loggers.get(WSLoader.class);
private static final String FAIL_MSG = "Server is not accessible and data is not cached";
private static final int CONNECT_TIMEOUT = 5000;
private static final int READ_TIMEOUT = 10000;
@@ -65,16 +69,20 @@ public class WSLoader {
this(false, cache, client);
}

public ByteSource loadSource(String id) {
return ByteSource.wrap(load(id));
@Nonnull
public WSLoaderResult<ByteSource> loadSource(String id) {
WSLoaderResult<byte[]> byteResult = load(id);
return new WSLoaderResult<ByteSource>(ByteSource.wrap(byteResult.get()), byteResult.isFromCache());
}

public String loadString(String id) {
return new String(load(id), StandardCharsets.UTF_8);
@Nonnull
public WSLoaderResult<String> loadString(String id) {
WSLoaderResult<byte[]> byteResult = load(id);
return new WSLoaderResult<String>(new String(byteResult.get(), StandardCharsets.UTF_8), byteResult.isFromCache());
}

@Nonnull
public byte[] load(String id) {
public WSLoaderResult<byte[]> load(String id) {
if (loadStrategy == CACHE_FIRST) {
return loadFromCacheFirst(id);
} else {
@@ -99,6 +107,7 @@ public class WSLoader {
}

private void switchToOffline() {
LOG.debug("server not available - switching to offline mode");
serverStatus = NOT_ACCESSIBLE;
}

@@ -110,71 +119,94 @@ public class WSLoader {
return serverStatus == NOT_ACCESSIBLE;
}

@Nonnull
private byte[] loadFromCacheFirst(String id) {
byte[] cached = loadFromCache(id);
if (cached != null) {
return cached;
private void updateCache(String id, byte[] value) {
if (cacheEnabled) {
try {
cache.put(client.getURI(id).toString(), value);
} catch (IOException e) {
LOG.warn("Error saving to WS cache", e);
}
}
}

@Nonnull
private WSLoaderResult<byte[]> loadFromCacheFirst(String id) {
try {
return loadFromServer(id);
} catch (Exception e) {
if (e.getCause() instanceof HttpDownloader.HttpException) {
throw e;
return loadFromCache(id);
} catch (NotAvailableException cacheNotAvailable) {
try {
return loadFromServer(id);
} catch (NotAvailableException serverNotAvailable) {
throw new IllegalStateException(FAIL_MSG, serverNotAvailable.getCause());
}
throw new IllegalStateException(FAIL_MSG, e);
}
}

@Nonnull
private byte[] loadFromServerFirst(String id) {
private WSLoaderResult<byte[]> loadFromServerFirst(String id) {
try {
return loadFromServer(id);
} catch (Exception serverException) {
if (serverException.getCause() instanceof HttpDownloader.HttpException) {
// http exceptions should always be thrown (no fallback)
throw serverException;
}
byte[] cached = loadFromCache(id);
if (cached != null) {
return cached;
} catch (NotAvailableException serverNotAvailable) {
try {
return loadFromCache(id);
} catch (NotAvailableException cacheNotAvailable) {
throw new IllegalStateException(FAIL_MSG, serverNotAvailable.getCause());
}
throw new IllegalStateException(FAIL_MSG, serverException);
}
}

private byte[] loadFromCache(String id) {
@Nonnull
private WSLoaderResult<byte[]> loadFromCache(String id) throws NotAvailableException {
if (!cacheEnabled) {
return null;
throw new NotAvailableException("cache disabled");
}

try {
return cache.get(client.getURI(id).toString(), null);
byte[] result = cache.get(client.getURI(id).toString(), null);
if (result == null) {
throw new NotAvailableException("resource not cached");
}
return new WSLoaderResult<byte[]>(result, true);
} catch (IOException e) {
// any exception on the cache should fail fast
throw new IllegalStateException(e);
}
}

private byte[] loadFromServer(String id) {
@Nonnull
private WSLoaderResult<byte[]> loadFromServer(String id) throws NotAvailableException {
if (isOffline()) {
throw new IllegalStateException("Server is not accessible");
throw new NotAvailableException("Server not available");
}

try {
InputStream is = client.load(id, REQUEST_METHOD, true, CONNECT_TIMEOUT, READ_TIMEOUT);
switchToOnline();
byte[] value = IOUtils.toByteArray(is);
if (cacheEnabled) {
cache.put(client.getURI(id).toString(), value);
}
return value;
updateCache(client.getURI(id).toString(), value);
return new WSLoaderResult<byte[]>(value, false);
} catch (IllegalStateException e) {
if (e.getCause() instanceof HttpDownloader.HttpException) {
// fail fast if it could connect but there was a application-level error
throw e;
}
switchToOffline();
throw e;
throw new NotAvailableException(e);
} catch (Exception e) {
switchToOffline();
// fail fast
throw new IllegalStateException(e);
}
}

private class NotAvailableException extends Exception {
private static final long serialVersionUID = 1L;

public NotAvailableException(String message) {
super(message);
}

public NotAvailableException(Throwable cause) {
super(cause);
}
}
}

+ 41
- 0
sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoaderResult.java View File

@@ -0,0 +1,41 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube 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.
*
* SonarQube 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.batch.bootstrap;

import javax.annotation.Nonnull;

public class WSLoaderResult<T> {
private T result;
private boolean fromCache;

public WSLoaderResult(T result, boolean fromCache) {
this.result = result;
this.fromCache = fromCache;
}

@Nonnull
public T get() {
return result;
}

public boolean isFromCache() {
return fromCache;
}
}

+ 9
- 3
sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java View File

@@ -19,8 +19,9 @@
*/
package org.sonar.batch.issue.tracking;

import org.sonar.batch.util.BatchUtils;
import org.sonar.batch.bootstrap.WSLoaderResult;

import org.sonar.batch.util.BatchUtils;
import org.sonar.batch.bootstrap.WSLoader;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterators;
@@ -45,10 +46,15 @@ public class DefaultServerLineHashesLoader implements ServerLineHashesLoader {
Profiler profiler = Profiler.createIfDebug(Loggers.get(getClass()))
.addContext("file", fileKey)
.startDebug("Load line hashes");
WSLoaderResult<String> result = wsLoader.loadString("/api/sources/hash?key=" + BatchUtils.encodeForUrl(fileKey));
try {
return wsLoader.loadString("/api/sources/hash?key=" + BatchUtils.encodeForUrl(fileKey));
return result.get();
} finally {
profiler.stopDebug();
if (result.isFromCache()) {
profiler.stopDebug();
} else {
profiler.stopDebug("Load line hashes (done from cache)");
}
}
}
}

+ 50
- 34
sonar-batch/src/main/java/org/sonar/batch/issue/tracking/ServerIssueRepository.java View File

@@ -20,10 +20,13 @@
package org.sonar.batch.issue.tracking;

import com.google.common.base.Function;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.annotation.Nullable;

import org.sonar.api.batch.AnalysisMode;
import org.sonar.api.batch.BatchSide;
import org.sonar.api.batch.InstantiationStrategy;
@@ -73,25 +76,8 @@ public class ServerIssueRepository {
Profiler profiler = Profiler.create(LOG).startInfo("Load server issues");
this.issuesCache = caches.createCache("previousIssues");
caches.registerValueCoder(ServerIssue.class, new ServerIssueValueCoder());
previousIssuesLoader.load(reactor.getRoot().getKeyWithBranch(), new Function<ServerIssue, Void>() {

@Override
public Void apply(@Nullable ServerIssue issue) {
if (issue == null) {
return null;
}
String componentKey = ComponentKeys.createEffectiveKey(issue.getModuleKey(), issue.hasPath() ? issue.getPath() : null);
BatchComponent r = resourceCache.get(componentKey);
if (r == null) {
// Deleted resource
issuesCache.put(0, issue.getKey(), issue);
} else {
issuesCache.put(r.batchId(), issue.getKey(), issue);
}
return null;
}
}, false);
profiler.stopDebug();
boolean fromCache = previousIssuesLoader.load(reactor.getRoot().getKeyWithBranch(), new SaveIssueConsumer(), false);
stopDebug(profiler, "Load server issues", fromCache);
}

public Iterable<ServerIssue> byComponent(BatchComponent component) {
@@ -104,25 +90,55 @@ public class ServerIssueRepository {
return Collections.emptyList();
}
Profiler profiler = Profiler.create(LOG).startInfo("Load server issues for " + component.resource().getPath());
final List<ServerIssue> result = new ArrayList<>();
previousIssuesLoader.load(component.key(), new Function<ServerIssue, Void>() {

@Override
public Void apply(@Nullable ServerIssue issue) {
if (issue == null) {
return null;
}
result.add(issue);
return null;
}
}, true);
profiler.stopDebug();
return result;
ServerIssueConsumer consumer = new ServerIssueConsumer();
boolean fromCache = previousIssuesLoader.load(component.key(), consumer, true);
stopDebug(profiler, "Load server issues for " + component.resource().getPath(), fromCache);
return consumer.issueList;
} else {
return issuesCache.values(component.batchId());
}
}

private void stopDebug(Profiler profiler, String msg, boolean fromCache) {
if (fromCache) {
profiler.stopDebug(msg + " (done from cache)");
} else {
profiler.stopDebug(msg + " (done)");
}
}

private class SaveIssueConsumer implements Function<ServerIssue, Void> {

@Override
public Void apply(@Nullable ServerIssue issue) {
if (issue == null) {
return null;
}
String componentKey = ComponentKeys.createEffectiveKey(issue.getModuleKey(), issue.hasPath() ? issue.getPath() : null);
BatchComponent r = resourceCache.get(componentKey);
if (r == null) {
// Deleted resource
issuesCache.put(0, issue.getKey(), issue);
} else {
issuesCache.put(r.batchId(), issue.getKey(), issue);
}
return null;
}
}

private static class ServerIssueConsumer implements Function<ServerIssue, Void> {
List<ServerIssue> issueList = new LinkedList<>();

@Override
public Void apply(@Nullable ServerIssue issue) {
if (issue == null) {
return null;
}
issueList.add(issue);
return null;
}
}

public Iterable<ServerIssue> issuesOnMissingComponents() {
if (analysisMode.isIncremental()) {
throw new UnsupportedOperationException("Only issues of analyzed components are loaded in incremental mode");

+ 17
- 4
sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java View File

@@ -181,7 +181,7 @@ public class BatchMediumTester {
projectRefProvider.addFileData(moduleKey, path, fileData);
return this;
}
public BatchMediumTesterBuilder setLastBuildDate(Date d) {
projectRefProvider.setLastAnalysisDate(d);
return this;
@@ -292,6 +292,10 @@ public class BatchMediumTester {
return rules;
}

@Override
public boolean loadedFromCache() {
return false;
}
}

private static class FakeGlobalRepositoriesLoader implements GlobalRepositoriesLoader {
@@ -325,6 +329,11 @@ public class BatchMediumTester {
metricId++;
return this;
}

@Override
public boolean loadedFromCache() {
return true;
}
}

private static class FakeProjectRepositoriesLoader implements ProjectRepositoriesLoader {
@@ -351,12 +360,16 @@ public class BatchMediumTester {
ref.addFileData(moduleKey, path, fileData);
return this;
}
public FakeProjectRepositoriesLoader setLastAnalysisDate(Date d) {
ref.setLastAnalysisDate(d);
return this;
}

@Override
public boolean loadedFromCache() {
return true;
}
}

private static class FakeServerIssuesLoader implements ServerIssuesLoader {
@@ -368,13 +381,13 @@ public class BatchMediumTester {
}

@Override
public void load(String componentKey, Function<ServerIssue, Void> consumer, boolean incremental) {
public boolean load(String componentKey, Function<ServerIssue, Void> consumer, boolean incremental) {
for (ServerIssue serverIssue : serverIssues) {
if (!incremental || ComponentKeys.createEffectiveKey(serverIssue.getModuleKey(), serverIssue.hasPath() ? serverIssue.getPath() : null).equals(componentKey)) {
consumer.apply(serverIssue);
}
}
return false;
}

}

+ 7
- 3
sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalRepositoriesLoader.java View File

@@ -19,11 +19,13 @@
*/
package org.sonar.batch.repository;

import org.sonar.batch.bootstrap.WSLoader;
import org.sonar.batch.bootstrap.AbstractServerLoader;

import org.sonar.batch.bootstrap.WSLoaderResult;
import org.sonar.batch.bootstrap.WSLoader;
import org.sonar.batch.protocol.input.GlobalRepositories;

public class DefaultGlobalRepositoriesLoader implements GlobalRepositoriesLoader {
public class DefaultGlobalRepositoriesLoader extends AbstractServerLoader implements GlobalRepositoriesLoader {

private static final String BATCH_GLOBAL_URL = "/batch/global";

@@ -35,7 +37,9 @@ public class DefaultGlobalRepositoriesLoader implements GlobalRepositoriesLoader

@Override
public GlobalRepositories load() {
return GlobalRepositories.fromJson(wsLoader.loadString(BATCH_GLOBAL_URL));
WSLoaderResult<String> result = wsLoader.loadString(BATCH_GLOBAL_URL);
super.loadedFromCache = result.isFromCache();
return GlobalRepositories.fromJson(result.get());
}

}

+ 11
- 3
sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java View File

@@ -19,6 +19,9 @@
*/
package org.sonar.batch.repository;

import org.sonar.batch.bootstrap.AbstractServerLoader;

import org.sonar.batch.bootstrap.WSLoaderResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.bootstrap.ProjectReactor;
@@ -30,10 +33,9 @@ import org.sonar.batch.protocol.input.ProjectRepositories;
import org.sonar.batch.rule.ModuleQProfiles;
import org.sonar.batch.util.BatchUtils;

public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoader {
public class DefaultProjectRepositoriesLoader extends AbstractServerLoader implements ProjectRepositoriesLoader {

private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectRepositoriesLoader.class);

private static final String BATCH_PROJECT_URL = "/batch/project";

private final WSLoader wsLoader;
@@ -54,11 +56,17 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad
url += "&profile=" + BatchUtils.encodeForUrl(taskProperties.properties().get(ModuleQProfiles.SONAR_PROFILE_PROP));
}
url += "&preview=" + globalMode.isPreview();
ProjectRepositories projectRepositories = ProjectRepositories.fromJson(wsLoader.loadString(url));
ProjectRepositories projectRepositories = ProjectRepositories.fromJson(load(url));
validateProjectRepositories(projectRepositories, reactor.getRoot().getKey());
return projectRepositories;
}

private String load(String resource) {
WSLoaderResult<String> result = wsLoader.loadString(resource);
super.loadedFromCache = result.isFromCache();
return result.get();
}

private static void validateProjectRepositories(ProjectRepositories projectRepositories, String projectKey) {
if (projectRepositories.qProfiles().isEmpty()) {
throw MessageException.of("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis.");

+ 6
- 4
sonar-batch/src/main/java/org/sonar/batch/repository/DefaultServerIssuesLoader.java View File

@@ -19,8 +19,9 @@
*/
package org.sonar.batch.repository;

import org.sonar.batch.util.BatchUtils;
import org.sonar.batch.bootstrap.WSLoaderResult;

import org.sonar.batch.util.BatchUtils;
import com.google.common.io.ByteSource;
import org.sonar.batch.bootstrap.WSLoader;
import com.google.common.base.Function;
@@ -38,9 +39,10 @@ public class DefaultServerIssuesLoader implements ServerIssuesLoader {
}

@Override
public void load(String componentKey, Function<ServerIssue, Void> consumer, boolean incremental) {
ByteSource request = wsLoader.loadSource("/batch/issues?key=" + BatchUtils.encodeForUrl(componentKey));
parseIssues(request, consumer);
public boolean load(String componentKey, Function<ServerIssue, Void> consumer, boolean incremental) {
WSLoaderResult<ByteSource> result = wsLoader.loadSource("/batch/issues?key=" + BatchUtils.encodeForUrl(componentKey));
parseIssues(result.get(), consumer);
return result.isFromCache();
}

private static void parseIssues(ByteSource input, Function<ServerIssue, Void> consumer) {

+ 2
- 0
sonar-batch/src/main/java/org/sonar/batch/repository/GlobalRepositoriesLoader.java View File

@@ -25,4 +25,6 @@ public interface GlobalRepositoriesLoader {

GlobalRepositories load();

boolean loadedFromCache();

}

+ 8
- 3
sonar-batch/src/main/java/org/sonar/batch/repository/GlobalRepositoriesProvider.java View File

@@ -28,14 +28,19 @@ import org.sonar.batch.protocol.input.GlobalRepositories;
public class GlobalRepositoriesProvider extends ProviderAdapter {

private static final Logger LOG = Loggers.get(GlobalRepositoriesProvider.class);
private static final String LOG_MSG = "Load global repositories";
private GlobalRepositories globalReferentials;

public GlobalRepositories provide(GlobalRepositoriesLoader loader) {
if (globalReferentials == null) {
Profiler profiler = Profiler.create(LOG).startInfo("Load global repositories");
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
globalReferentials = loader.load();
profiler.stopInfo();

if (loader.loadedFromCache()) {
profiler.stopInfo(LOG_MSG + " (done from cache)");
} else {
profiler.stopInfo();
}
}
return globalReferentials;
}

+ 2
- 0
sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java View File

@@ -26,5 +26,7 @@ import org.sonar.batch.protocol.input.ProjectRepositories;
public interface ProjectRepositoriesLoader {

ProjectRepositories load(ProjectReactor reactor, AnalysisProperties taskProperties);
boolean loadedFromCache();

}

+ 9
- 2
sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesProvider.java View File

@@ -30,15 +30,22 @@ import org.sonar.batch.protocol.input.ProjectRepositories;

public class ProjectRepositoriesProvider extends ProviderAdapter {

private static final String LOG_MSG = "Load project repositories";
private static final Logger LOG = Loggers.get(ProjectRepositoriesProvider.class);

private ProjectRepositories projectReferentials;

public ProjectRepositories provide(ProjectRepositoriesLoader loader, ProjectReactor reactor, AnalysisProperties taskProps, AnalysisMode analysisMode) {
if (projectReferentials == null) {
Profiler profiler = Profiler.create(LOG).startInfo("Load project repositories");
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
projectReferentials = loader.load(reactor, taskProps);
profiler.stopInfo();

if (loader.loadedFromCache()) {
profiler.stopInfo(LOG_MSG + " (done from cache)");
} else {
profiler.stopInfo();
}

if (analysisMode.isPreview() && projectReferentials.lastAnalysisDate() == null) {
LOG.warn("No analysis has been found on the server for this project. All issues will be marked as 'new'.");
}

+ 1
- 1
sonar-batch/src/main/java/org/sonar/batch/repository/ServerIssuesLoader.java View File

@@ -24,6 +24,6 @@ import org.sonar.batch.protocol.input.BatchInput.ServerIssue;

public interface ServerIssuesLoader {

void load(String componentKey, Function<ServerIssue, Void> consumer, boolean incremental);
boolean load(String componentKey, Function<ServerIssue, Void> consumer, boolean incremental);

}

+ 21
- 10
sonar-batch/src/main/java/org/sonar/batch/repository/user/UserRepository.java View File

@@ -19,8 +19,12 @@
*/
package org.sonar.batch.repository.user;

import org.sonar.batch.util.BatchUtils;
import org.sonar.batch.bootstrap.WSLoaderResult;

import org.sonar.api.utils.log.Profiler;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.batch.util.BatchUtils;
import org.sonar.batch.bootstrap.WSLoader;
import com.google.common.io.ByteSource;
import com.google.common.base.Function;
@@ -36,8 +40,8 @@ import java.util.Collections;
import java.util.List;

public class UserRepository {
private WSLoader wsLoader;
private static final Logger LOG = Loggers.get(UserRepository.class);
private final WSLoader wsLoader;

public UserRepository(WSLoader wsLoader) {
this.wsLoader = wsLoader;
@@ -47,15 +51,22 @@ public class UserRepository {
if (userLogins.isEmpty()) {
return Collections.emptyList();
}
Profiler profiler = Profiler.create(LOG).startDebug("Load user repository");
WSLoaderResult<ByteSource> result = wsLoader.loadSource("/batch/users?logins=" + Joiner.on(',').join(Lists.transform(userLogins, new UserEncodingFunction())));
if (result.isFromCache()) {
profiler.stopInfo("Load user repository (done from cache)");
} else {
profiler.stopInfo();
}

ByteSource source = wsLoader.loadSource("/batch/users?logins=" + Joiner.on(',').join(Lists.transform(userLogins, new Function<String, String>() {
@Override
public String apply(String input) {
return BatchUtils.encodeForUrl(input);
}
})));
return parseUsers(result.get());
}

return parseUsers(source);
private static class UserEncodingFunction implements Function<String, String> {
@Override
public String apply(String input) {
return BatchUtils.encodeForUrl(input);
}
}

private static Collection<BatchInput.User> parseUsers(ByteSource input) {

+ 8
- 3
sonar-batch/src/main/java/org/sonar/batch/rule/DefaultRulesLoader.java View File

@@ -19,6 +19,9 @@
*/
package org.sonar.batch.rule;

import org.sonar.batch.bootstrap.AbstractServerLoader;

import org.sonar.batch.bootstrap.WSLoaderResult;
import org.sonarqube.ws.Rules.ListResponse.Rule;
import com.google.common.io.ByteSource;
import org.sonarqube.ws.Rules.ListResponse;
@@ -29,7 +32,7 @@ import java.util.List;

import org.sonar.batch.bootstrap.WSLoader;

public class DefaultRulesLoader implements RulesLoader {
public class DefaultRulesLoader extends AbstractServerLoader implements RulesLoader {
private static final String RULES_SEARCH_URL = "/api/rules/list";

private final WSLoader wsLoader;
@@ -40,11 +43,13 @@ public class DefaultRulesLoader implements RulesLoader {

@Override
public List<Rule> load() {
ListResponse list = loadFromSource(wsLoader.loadSource(RULES_SEARCH_URL));
WSLoaderResult<ByteSource> result = wsLoader.loadSource(RULES_SEARCH_URL);
ListResponse list = loadFromSource(result.get());
super.loadedFromCache = result.isFromCache();
return list.getRulesList();
}

private ListResponse loadFromSource(ByteSource input) {
private static ListResponse loadFromSource(ByteSource input) {
try (InputStream is = input.openStream()) {
return ListResponse.parseFrom(is);
} catch (IOException e) {

+ 2
- 0
sonar-batch/src/main/java/org/sonar/batch/rule/RulesLoader.java View File

@@ -25,4 +25,6 @@ import org.sonarqube.ws.Rules.ListResponse.Rule;

public interface RulesLoader {
List<Rule> load();

boolean loadedFromCache();
}

+ 14
- 0
sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java View File

@@ -19,6 +19,11 @@
*/
package org.sonar.batch.rule;

import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

import org.sonar.api.utils.log.Profiler;

import java.util.List;

import org.sonarqube.ws.Rules.ListResponse.Rule;
@@ -29,6 +34,8 @@ import org.sonar.api.batch.rule.internal.NewRule;
import org.sonar.api.batch.rule.Rules;

public class RulesProvider extends ProviderAdapter {
private static final Logger LOG = Loggers.get(RulesProvider.class);
private static final String LOG_MSG = "Load server rules";
private Rules singleton = null;

public Rules provide(RulesLoader ref) {
@@ -39,6 +46,7 @@ public class RulesProvider extends ProviderAdapter {
}

private static Rules load(RulesLoader ref) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
List<Rule> loadedRules = ref.load();
RulesBuilder builder = new RulesBuilder();

@@ -48,6 +56,12 @@ public class RulesProvider extends ProviderAdapter {
newRule.setInternalKey(r.getInternalKey());
}

if (ref.loadedFromCache()) {
profiler.stopInfo(LOG_MSG + " (done from cache)");
} else {
profiler.stopInfo();
}

return builder.build();
}
}

+ 6
- 5
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java View File

@@ -45,15 +45,16 @@ public class BatchPluginInstallerTest {
public ExpectedException thrown = ExpectedException.none();

FileCache fileCache = mock(FileCache.class);
ServerClient serverClient = mock(ServerClient.class);
BatchPluginPredicate pluginPredicate = mock(BatchPluginPredicate.class);

@Test
public void listRemotePlugins() {

WSLoader wsLoader = mock(WSLoader.class);
when(wsLoader.load("/deploy/plugins/index.txt")).thenReturn("checkstyle\nsqale".getBytes());
when(wsLoader.loadString("/deploy/plugins/index.txt")).thenReturn("checkstyle\nsqale");
BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, fileCache, pluginPredicate);
when(wsLoader.load("/deploy/plugins/index.txt")).thenReturn(new WSLoaderResult<byte[]>("checkstyle\nsqale".getBytes(), true));
when(wsLoader.loadString("/deploy/plugins/index.txt")).thenReturn(new WSLoaderResult<String>("checkstyle\nsqale", true));
BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, serverClient, fileCache, pluginPredicate);

List<RemotePlugin> remotePlugins = installer.listRemotePlugins();
assertThat(remotePlugins).extracting("key").containsOnly("checkstyle", "sqale");
@@ -65,7 +66,7 @@ public class BatchPluginInstallerTest {
when(fileCache.get(eq("checkstyle-plugin.jar"), eq("fakemd5_1"), any(FileCache.Downloader.class))).thenReturn(pluginJar);

WSLoader wsLoader = mock(WSLoader.class);
BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, fileCache, pluginPredicate);
BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, serverClient, fileCache, pluginPredicate);

RemotePlugin remote = new RemotePlugin("checkstyle").setFile("checkstyle-plugin.jar", "fakemd5_1");
File file = installer.download(remote);
@@ -80,6 +81,6 @@ public class BatchPluginInstallerTest {
WSLoader wsLoader = mock(WSLoader.class);
doThrow(new IllegalStateException()).when(wsLoader).load("/deploy/plugins/index.txt");

new BatchPluginInstaller(wsLoader, fileCache, pluginPredicate).installRemotes();
new BatchPluginInstaller(wsLoader, serverClient, fileCache, pluginPredicate).installRemotes();
}
}

+ 19
- 28
sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTest.java View File

@@ -74,10 +74,9 @@ public class WSLoaderTest {
when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
WSLoader loader = new WSLoader(true, cache, client);
loader.setStrategy(LoadStrategy.SERVER_FIRST);
loader.setCacheEnabled(true);

assertThat(loader.loadString(ID)).isEqualTo(cacheValue);
assertThat(loader.loadString(ID)).isEqualTo(cacheValue);
assertResult(loader.loadString(ID), cacheValue, true);
assertResult(loader.loadString(ID), cacheValue, true);

// only try once the server
verify(client, times(1)).load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt());
@@ -89,9 +88,8 @@ public class WSLoaderTest {
when(cache.get(ID, null)).thenReturn(null);
WSLoader loader = new WSLoader(true, cache, client);
loader.setStrategy(LoadStrategy.CACHE_FIRST);
loader.setCacheEnabled(true);

loader.load(ID);
assertResult(loader.load(ID), serverValue.getBytes(), false);

InOrder inOrder = Mockito.inOrder(client, cache);
inOrder.verify(cache).get(ID, null);
@@ -103,8 +101,8 @@ public class WSLoaderTest {
when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
WSLoader loader = new WSLoader(true, cache, client);
loader.setStrategy(LoadStrategy.SERVER_FIRST);
loader.setCacheEnabled(true);
assertThat(loader.loadString(ID)).isEqualTo(cacheValue);
assertResult(loader.loadString(ID), cacheValue, true);

InOrder inOrder = Mockito.inOrder(client, cache);
inOrder.verify(client).load(eq(ID), anyString(), anyBoolean(), anyInt(), anyInt());
@@ -123,9 +121,9 @@ public class WSLoaderTest {
public void test_throw_cache_exception_fallback() throws IOException {
when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
when(cache.get(ID, null)).thenThrow(new NullPointerException());

WSLoader loader = new WSLoader(true, cache, client);
loader.setStrategy(LoadStrategy.SERVER_FIRST);
loader.setCacheEnabled(true);

loader.load(ID);
}
@@ -133,9 +131,9 @@ public class WSLoaderTest {
@Test(expected = IllegalStateException.class)
public void test_throw_cache_exception() throws IOException {
when(cache.get(ID, null)).thenThrow(new IllegalStateException());

WSLoader loader = new WSLoader(true, cache, client);
loader.setStrategy(LoadStrategy.CACHE_FIRST);
loader.setCacheEnabled(true);

loader.load(ID);
}
@@ -144,34 +142,21 @@ public class WSLoaderTest {
public void test_throw_http_exceptions() {
HttpDownloader.HttpException httpException = mock(HttpDownloader.HttpException.class);
IllegalStateException wrapperException = new IllegalStateException(httpException);
when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(wrapperException);
WSLoader loader = new WSLoader(true, cache, client);
loader.setStrategy(LoadStrategy.SERVER_FIRST);
try {
loader.load(ID);
} catch(IllegalStateException e) {
} catch (IllegalStateException e) {
// cache should not be used
verifyNoMoreInteractions(cache);
throw e;
}
}

@Test
public void test_server_not_accessible() throws IOException {
when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
WSLoader loader = new WSLoader(true, cache, client);
loader.setStrategy(LoadStrategy.SERVER_FIRST);
loader.load(ID);
loader.load(ID);

// only try once from server
verify(client, times(1)).load(eq(ID), anyString(), anyBoolean(), anyInt(), anyInt());
verify(cache, times(2)).get(ID, null);
}

@Test
public void test_change_strategy() throws IOException {
WSLoader loader = new WSLoader(true, cache, client);
@@ -190,7 +175,7 @@ public class WSLoaderTest {
public void test_server_strategy() throws IOException {
WSLoader loader = new WSLoader(true, cache, client);
loader.setStrategy(LoadStrategy.SERVER_FIRST);
loader.load(ID);
assertResult(loader.load(ID), serverValue.getBytes(), false);

// should not fetch from cache
verify(cache).put(ID, serverValue.getBytes());
@@ -209,6 +194,12 @@ public class WSLoaderTest {
@Test
public void test_string() {
WSLoader loader = new WSLoader(cache, client);
assertThat(loader.loadString(ID)).isEqualTo(serverValue);
assertResult(loader.loadString(ID), serverValue, false);
}

private <T> void assertResult(WSLoaderResult<T> result, T expected, boolean fromCache) {
assertThat(result).isNotNull();
assertThat(result.get()).isEqualTo(expected);
assertThat(result.isFromCache()).isEqualTo(fromCache);
}
}

+ 4
- 3
sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java View File

@@ -19,8 +19,9 @@
*/
package org.sonar.batch.issue.tracking;

import org.sonar.batch.bootstrap.WSLoader;
import org.sonar.batch.bootstrap.WSLoaderResult;

import org.sonar.batch.bootstrap.WSLoader;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -48,7 +49,7 @@ public class DefaultServerLineHashesLoaderTest {
@Test
public void should_download_source_from_ws_if_preview_mode() {
WSLoader wsLoader = mock(WSLoader.class);
when(wsLoader.loadString(anyString())).thenReturn("ae12\n\n43fb");
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult("ae12\n\n43fb", true));

ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(wsLoader);

@@ -60,7 +61,7 @@ public class DefaultServerLineHashesLoaderTest {
@Test
public void should_download_source_with_space_from_ws_if_preview_mode() {
WSLoader server = mock(WSLoader.class);
when(server.loadString(anyString())).thenReturn("ae12\n\n43fb");
when(server.loadString(anyString())).thenReturn(new WSLoaderResult("ae12\n\n43fb", true));

ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(server);


+ 8
- 5
sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java View File

@@ -19,8 +19,12 @@
*/
package org.sonar.batch.repository;

import org.sonar.batch.bootstrap.WSLoaderResult;

import com.google.common.collect.Maps;

import java.util.Date;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -34,7 +38,6 @@ import org.sonar.batch.bootstrap.WSLoader;
import org.sonar.batch.protocol.input.ProjectRepositories;
import org.sonar.batch.protocol.input.QProfile;
import org.sonar.batch.rule.ModuleQProfiles;

import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -58,7 +61,7 @@ public class DefaultProjectRepositoriesLoaderTest {
globalMode = mock(GlobalMode.class);
loader = new DefaultProjectRepositoriesLoader(wsLoader, globalMode);
loader = spy(loader);
when(wsLoader.loadString(anyString())).thenReturn("{}");
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult("{}", true));
taskProperties = new AnalysisProperties(Maps.<String, String>newHashMap(), "");
}

@@ -98,15 +101,15 @@ public class DefaultProjectRepositoriesLoaderTest {
thrown.expectMessage("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis.");

reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
when(wsLoader.loadString(anyString())).thenReturn(new ProjectRepositories().toJson());
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult(new ProjectRepositories().toJson(), true));

loader.load(reactor, taskProperties);
}

private void addQualityProfile(){
private void addQualityProfile() {
ProjectRepositories projectRepositories = new ProjectRepositories();
projectRepositories.addQProfile(new QProfile("key", "name", "language", new Date()));
when(wsLoader.loadString(anyString())).thenReturn(projectRepositories.toJson());
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult(projectRepositories.toJson(), true));
}

}

+ 3
- 2
sonar-batch/src/test/java/org/sonar/batch/repository/DefaultServerIssuesLoaderTest.java View File

@@ -19,8 +19,9 @@
*/
package org.sonar.batch.repository;

import com.google.common.io.ByteSource;
import org.sonar.batch.bootstrap.WSLoaderResult;

import com.google.common.io.ByteSource;
import org.sonar.batch.bootstrap.WSLoader;
import com.google.common.base.Function;
import org.junit.Before;
@@ -50,7 +51,7 @@ public class DefaultServerIssuesLoaderTest {
@Test
public void loadFromWs() throws Exception {
ByteSource bs = mock(ByteSource.class);
when(wsLoader.loadSource("/batch/issues?key=foo")).thenReturn(bs);
when(wsLoader.loadSource("/batch/issues?key=foo")).thenReturn(new WSLoaderResult(bs, true));

ByteArrayOutputStream bos = new ByteArrayOutputStream();


+ 3
- 2
sonar-batch/src/test/java/org/sonar/batch/repository/user/UserRepositoryTest.java View File

@@ -19,8 +19,9 @@
*/
package org.sonar.batch.repository.user;

import com.google.common.io.ByteSource;
import org.sonar.batch.bootstrap.WSLoaderResult;

import com.google.common.io.ByteSource;
import org.sonar.batch.bootstrap.WSLoader;
import org.junit.Test;
import org.sonar.batch.protocol.input.BatchInput;
@@ -48,7 +49,7 @@ public class UserRepositoryTest {
builder.setLogin("sbrandhof").setName("Simon").build().writeDelimitedTo(out);

ByteSource source = mock(ByteSource.class);
when(wsLoader.loadSource("/batch/users?logins=fmallet,sbrandhof")).thenReturn(source);
when(wsLoader.loadSource("/batch/users?logins=fmallet,sbrandhof")).thenReturn(new WSLoaderResult(source, true));
when(source.openStream()).thenReturn(new ByteArrayInputStream(out.toByteArray()));

assertThat(userRepo.loadFromWs(Arrays.asList("fmallet", "sbrandhof"))).extracting("login", "name").containsOnly(tuple("fmallet", "Freddy Mallet"), tuple("sbrandhof", "Simon"));

+ 15
- 1
sonar-batch/src/test/java/org/sonar/batch/rule/DefaultRulesLoaderTest.java View File

@@ -21,6 +21,9 @@ package org.sonar.batch.rule;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.sonar.batch.bootstrap.WSLoaderResult;

import org.sonarqube.ws.Rules.ListResponse.Rule;
import com.google.common.io.ByteSource;
import com.google.common.io.Resources;
@@ -38,9 +41,20 @@ public class DefaultRulesLoaderTest {
public void testParseServerResponse() throws IOException {
WSLoader wsLoader = mock(WSLoader.class);
ByteSource source = Resources.asByteSource(this.getClass().getResource("DefaultRulesLoader/response.protobuf"));
when(wsLoader.loadSource(anyString())).thenReturn(source);
when(wsLoader.loadSource(anyString())).thenReturn(new WSLoaderResult(source, true));
DefaultRulesLoader loader = new DefaultRulesLoader(wsLoader);
List<Rule> ruleList = loader.load();
assertThat(ruleList).hasSize(318);
}

@Test
public void testLoadedFromCache() {
WSLoader wsLoader = mock(WSLoader.class);
ByteSource source = Resources.asByteSource(this.getClass().getResource("DefaultRulesLoader/response.protobuf"));
when(wsLoader.loadSource(anyString())).thenReturn(new WSLoaderResult(source, true));
DefaultRulesLoader loader = new DefaultRulesLoader(wsLoader);
loader.load();

assertThat(loader.loadedFromCache()).isTrue();
}
}

Loading…
Cancel
Save