From 266bcc800c202ed94438036a4d104688941416ec Mon Sep 17 00:00:00 2001 From: Daniel Schwarz Date: Tue, 7 Feb 2017 12:33:35 +0100 Subject: [PATCH] SONAR-8745 refactor test to generate response, instead of using file --- .../rule/DefaultActiveRulesLoaderTest.java | 107 ++++++++++++------ .../active_rule_search1.protobuf | Bin 27828 -> 0 bytes .../active_rule_search2.protobuf | Bin 14446 -> 0 bytes 3 files changed, 74 insertions(+), 33 deletions(-) delete mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest/active_rule_search1.protobuf delete mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest/active_rule_search2.protobuf diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java index 18d6081f02c..1b373162db7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java @@ -19,24 +19,39 @@ */ package org.sonar.scanner.rule; -import org.sonar.api.rule.RuleKey; -import org.sonar.scanner.WsTestUtil; -import org.sonar.scanner.bootstrap.ScannerWsClient; -import org.sonar.scanner.rule.DefaultActiveRulesLoader; -import org.sonar.scanner.rule.LoadedActiveRule; -import com.google.common.io.Resources; -import org.junit.Test; - +import com.google.common.collect.ImmutableSortedMap; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; +import java.util.stream.IntStream; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.Severity; +import org.sonar.scanner.WsTestUtil; +import org.sonar.scanner.bootstrap.ScannerWsClient; +import org.sonarqube.ws.Rules; +import org.sonarqube.ws.Rules.Active; +import org.sonarqube.ws.Rules.ActiveList; +import org.sonarqube.ws.Rules.Actives; +import org.sonarqube.ws.Rules.Rule; +import org.sonarqube.ws.Rules.SearchResponse; +import org.sonarqube.ws.Rules.SearchResponse.Builder; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoMoreInteractions; -import org.junit.Before; public class DefaultActiveRulesLoaderTest { + + private static final int PAGE_SIZE_1 = 150; + private static final int PAGE_SIZE_2 = 76; + private static final RuleKey EXAMPLE_KEY = RuleKey.of("squid", "S108"); + private static final String FORMAT_KEY = "format"; + private static final String FORMAT_VALUE = "^[a-z][a-zA-Z0-9]*$"; + private static final String SEVERITY_VALUE = Severity.MINOR; + private DefaultActiveRulesLoader loader; private ScannerWsClient wsClient; @@ -48,39 +63,65 @@ public class DefaultActiveRulesLoaderTest { @Test public void feed_real_response_encode_qp() throws IOException { - InputStream response1 = loadResource("active_rule_search1.protobuf"); - InputStream response2 = loadResource("active_rule_search2.protobuf"); + int total = PAGE_SIZE_1 + PAGE_SIZE_2; - String req1 = "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives&activation=true&qprofile=c%2B-test_c%2B-values-17445&p=1&ps=500"; - String req2 = "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives&activation=true&qprofile=c%2B-test_c%2B-values-17445&p=2&ps=500"; - WsTestUtil.mockStream(wsClient, req1, response1); - WsTestUtil.mockStream(wsClient, req2, response2); + WsTestUtil.mockStream(wsClient, urlOfPage(1), responseOfSize(PAGE_SIZE_1, total)); + WsTestUtil.mockStream(wsClient, urlOfPage(2), responseOfSize(PAGE_SIZE_2, total)); Collection activeRules = loader.load("c+-test_c+-values-17445"); - assertThat(activeRules).hasSize(226); - assertActiveRule(activeRules); + assertThat(activeRules).hasSize(total); + assertThat(activeRules) + .filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY)) + .extracting(LoadedActiveRule::getParams) + .extracting(p -> p.get(FORMAT_KEY)) + .containsExactly(FORMAT_VALUE); + assertThat(activeRules) + .filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY)) + .extracting(LoadedActiveRule::getSeverity) + .containsExactly(SEVERITY_VALUE); - WsTestUtil.verifyCall(wsClient, req1); - WsTestUtil.verifyCall(wsClient, req2); + WsTestUtil.verifyCall(wsClient, urlOfPage(1)); + WsTestUtil.verifyCall(wsClient, urlOfPage(2)); verifyNoMoreInteractions(wsClient); } - private static void assertActiveRule(Collection activeRules) { - RuleKey key = RuleKey.of("squid", "S3008"); - for (LoadedActiveRule r : activeRules) { - if (!r.getRuleKey().equals(key)) { - continue; - } - - assertThat(r.getParams().get("format")).isEqualTo("^[a-z][a-zA-Z0-9]*$"); - assertThat(r.getSeverity()).isEqualTo("MINOR"); - } + private String urlOfPage(int page) { + return "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives&activation=true&qprofile=c%2B-test_c%2B-values-17445&p=" + page + + "&ps=500"; } - private InputStream loadResource(String name) throws IOException { - return Resources.asByteSource(this.getClass().getResource("DefaultActiveRulesLoaderTest/" + name)) - .openBufferedStream(); - } + /** + * Generates an imaginary protobuf result. + * + * @param numberOfRules the number of rules, that the response should contain + * @param total TODO + * @return the binary stream + */ + private InputStream responseOfSize(int numberOfRules, int total) { + Builder rules = SearchResponse.newBuilder(); + Actives.Builder actives = Actives.newBuilder(); + IntStream.rangeClosed(1, numberOfRules) + .mapToObj(i -> RuleKey.of("squid", "S" + i)) + .forEach(key -> { + + Rule.Builder ruleBuilder = Rule.newBuilder(); + ruleBuilder.setKey(key.toString()); + rules.addRules(ruleBuilder); + + Active.Builder activeBuilder = Active.newBuilder(); + if (EXAMPLE_KEY.equals(key)) { + activeBuilder.addParams(Rules.Active.Param.newBuilder().setKey(FORMAT_KEY).setValue(FORMAT_VALUE)); + activeBuilder.setSeverity(SEVERITY_VALUE); + } + ActiveList activeList = Rules.ActiveList.newBuilder().addActiveList(activeBuilder).build(); + actives.putAllActives(ImmutableSortedMap.of(key.toString(), activeList)); + }); + + rules.setActives(actives); + rules.setPs(numberOfRules); + rules.setTotal(total); + return new ByteArrayInputStream(rules.build().toByteArray()); + } } diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest/active_rule_search1.protobuf b/sonar-scanner-engine/src/test/resources/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest/active_rule_search1.protobuf deleted file mode 100644 index 5544968df4b2244f0e3e984d92fdd7f363f3d2f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27828 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 diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest/active_rule_search2.protobuf b/sonar-scanner-engine/src/test/resources/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest/active_rule_search2.protobuf deleted file mode 100644 index a23bd1d5d8188bb59e735ab2978e82693ebcaf62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14446 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