You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DefaultActiveRulesLoaderTest.java 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.scanner.rule;
  21. import com.google.common.collect.ImmutableSortedMap;
  22. import java.io.ByteArrayInputStream;
  23. import java.io.InputStream;
  24. import java.util.Collection;
  25. import java.util.stream.IntStream;
  26. import org.junit.Before;
  27. import org.junit.Test;
  28. import org.sonar.api.batch.rule.LoadedActiveRule;
  29. import org.sonar.api.rule.RuleKey;
  30. import org.sonar.api.rule.Severity;
  31. import org.sonar.api.utils.MessageException;
  32. import org.sonar.scanner.WsTestUtil;
  33. import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
  34. import org.sonar.scanner.scan.branch.BranchConfiguration;
  35. import org.sonarqube.ws.Rules;
  36. import org.sonarqube.ws.Rules.Active;
  37. import org.sonarqube.ws.Rules.ActiveList;
  38. import org.sonarqube.ws.Rules.Actives;
  39. import org.sonarqube.ws.Rules.Rule;
  40. import org.sonarqube.ws.Rules.SearchResponse;
  41. import org.sonarqube.ws.Rules.SearchResponse.Builder;
  42. import static org.assertj.core.api.Assertions.assertThat;
  43. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  44. import static org.mockito.Mockito.mock;
  45. import static org.mockito.Mockito.verifyNoMoreInteractions;
  46. import static org.mockito.Mockito.when;
  47. public class DefaultActiveRulesLoaderTest {
  48. private static final int PAGE_SIZE_1 = 150;
  49. private static final int PAGE_SIZE_2 = 76;
  50. private static final RuleKey EXAMPLE_KEY = RuleKey.of("java", "S108");
  51. private static final String FORMAT_KEY = "format";
  52. private static final String FORMAT_VALUE = "^[a-z][a-zA-Z0-9]*$";
  53. private static final String SEVERITY_VALUE = Severity.MINOR;
  54. private DefaultActiveRulesLoader loader;
  55. private DefaultScannerWsClient wsClient;
  56. @Before
  57. public void setUp() {
  58. wsClient = mock(DefaultScannerWsClient.class);
  59. BranchConfiguration branchConfig = mock(BranchConfiguration.class);
  60. when(branchConfig.isPullRequest()).thenReturn(false);
  61. loader = new DefaultActiveRulesLoader(wsClient);
  62. }
  63. @Test
  64. public void feed_real_response_encode_qp() {
  65. int total = PAGE_SIZE_1 + PAGE_SIZE_2;
  66. WsTestUtil.mockStream(wsClient, urlOfPage(1), responseOfSize(PAGE_SIZE_1, total));
  67. WsTestUtil.mockStream(wsClient, urlOfPage(2), responseOfSize(PAGE_SIZE_2, total));
  68. Collection<LoadedActiveRule> activeRules = loader.load("c+-test_c+-values-17445");
  69. assertThat(activeRules).hasSize(total);
  70. assertThat(activeRules)
  71. .filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY))
  72. .extracting(LoadedActiveRule::getParams)
  73. .extracting(p -> p.get(FORMAT_KEY))
  74. .containsExactly(FORMAT_VALUE);
  75. assertThat(activeRules)
  76. .filteredOn(r -> r.getRuleKey().equals(EXAMPLE_KEY))
  77. .extracting(LoadedActiveRule::getSeverity)
  78. .containsExactly(SEVERITY_VALUE);
  79. WsTestUtil.verifyCall(wsClient, urlOfPage(1));
  80. WsTestUtil.verifyCall(wsClient, urlOfPage(2));
  81. verifyNoMoreInteractions(wsClient);
  82. }
  83. @Test
  84. public void exception_thrown_when_elasticsearch_index_inconsistent() {
  85. WsTestUtil.mockStream(wsClient, urlOfPage(1), prepareCorruptedResponse());
  86. assertThatThrownBy(() -> loader.load("c+-test_c+-values-17445"))
  87. .isInstanceOf(MessageException.class)
  88. .hasMessage("Elasticsearch indices have become inconsistent. Consider re-indexing. " +
  89. "Check documentation for more information https://docs.sonarqube.org/latest/setup/troubleshooting");
  90. }
  91. private String urlOfPage(int page) {
  92. return "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt,updatedAt,deprecatedKeys&activation=true"
  93. + ("") + "&qprofile=c%2B-test_c%2B-values-17445&ps=500&p=" + page + "";
  94. }
  95. /**
  96. * Generates an imaginary protobuf result.
  97. *
  98. * @param numberOfRules the number of rules, that the response should contain
  99. * @param total the number of results on all pages
  100. * @return the binary stream
  101. */
  102. private InputStream responseOfSize(int numberOfRules, int total) {
  103. Builder rules = SearchResponse.newBuilder();
  104. Actives.Builder actives = Actives.newBuilder();
  105. IntStream.rangeClosed(1, numberOfRules)
  106. .mapToObj(i -> RuleKey.of("java", "S" + i))
  107. .forEach(key -> {
  108. Rule.Builder ruleBuilder = Rule.newBuilder();
  109. ruleBuilder.setKey(key.toString());
  110. rules.addRules(ruleBuilder);
  111. Active.Builder activeBuilder = Active.newBuilder();
  112. activeBuilder.setCreatedAt("2014-05-27T15:50:45+0100");
  113. activeBuilder.setUpdatedAt("2014-05-27T15:50:45+0100");
  114. if (EXAMPLE_KEY.equals(key)) {
  115. activeBuilder.addParams(Rules.Active.Param.newBuilder().setKey(FORMAT_KEY).setValue(FORMAT_VALUE));
  116. activeBuilder.setSeverity(SEVERITY_VALUE);
  117. }
  118. ActiveList activeList = Rules.ActiveList.newBuilder().addActiveList(activeBuilder).build();
  119. actives.putAllActives(ImmutableSortedMap.of(key.toString(), activeList));
  120. });
  121. rules.setActives(actives);
  122. rules.setPs(numberOfRules);
  123. rules.setTotal(total);
  124. return new ByteArrayInputStream(rules.build().toByteArray());
  125. }
  126. private InputStream prepareCorruptedResponse() {
  127. Builder rules = SearchResponse.newBuilder();
  128. Actives.Builder actives = Actives.newBuilder();
  129. IntStream.rangeClosed(1, 3)
  130. .mapToObj(i -> RuleKey.of("java", "S" + i))
  131. .forEach(key -> {
  132. Rule.Builder ruleBuilder = Rule.newBuilder();
  133. ruleBuilder.setKey(key.toString());
  134. rules.addRules(ruleBuilder);
  135. });
  136. rules.setActives(actives);
  137. rules.setPs(3);
  138. rules.setTotal(3);
  139. return new ByteArrayInputStream(rules.build().toByteArray());
  140. }
  141. }