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.

DefaultAnalysisCacheLoaderTest.java 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2022 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.cache;
  21. import com.google.protobuf.ByteString;
  22. import java.io.ByteArrayInputStream;
  23. import java.io.ByteArrayOutputStream;
  24. import java.io.IOException;
  25. import java.io.InputStream;
  26. import java.nio.charset.StandardCharsets;
  27. import java.util.Optional;
  28. import java.util.zip.DeflaterInputStream;
  29. import org.junit.Before;
  30. import org.junit.Test;
  31. import org.mockito.ArgumentCaptor;
  32. import org.sonar.api.scanner.fs.InputProject;
  33. import org.sonar.api.utils.MessageException;
  34. import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
  35. import org.sonar.scanner.protocol.internal.ScannerInternal.AnalysisCacheMsg;
  36. import org.sonar.scanner.scan.branch.BranchConfiguration;
  37. import org.sonarqube.ws.client.GetRequest;
  38. import org.sonarqube.ws.client.HttpException;
  39. import org.sonarqube.ws.client.WsResponse;
  40. import static org.assertj.core.api.Assertions.assertThat;
  41. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  42. import static org.mockito.ArgumentMatchers.any;
  43. import static org.mockito.Mockito.mock;
  44. import static org.mockito.Mockito.verify;
  45. import static org.mockito.Mockito.when;
  46. import static org.sonar.scanner.cache.DefaultAnalysisCacheLoader.CONTENT_ENCODING;
  47. public class DefaultAnalysisCacheLoaderTest {
  48. private final static AnalysisCacheMsg MSG = AnalysisCacheMsg.newBuilder()
  49. .putMap("key", ByteString.copyFrom("value", StandardCharsets.UTF_8))
  50. .build();
  51. private final WsResponse response = mock(WsResponse.class);
  52. private final DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class);
  53. private final InputProject project = mock(InputProject.class);
  54. private final BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
  55. private final DefaultAnalysisCacheLoader loader = new DefaultAnalysisCacheLoader(wsClient, project, branchConfiguration);
  56. @Before
  57. public void before() {
  58. when(project.key()).thenReturn("myproject");
  59. when(wsClient.call(any(GetRequest.class))).thenReturn(response);
  60. }
  61. @Test
  62. public void loads_content() throws IOException {
  63. setResponse(MSG);
  64. AnalysisCacheMsg msg = loader.load().get();
  65. assertThat(msg).isEqualTo(MSG);
  66. assertRequestPath("api/analysis_cache/get?project=myproject");
  67. }
  68. @Test
  69. public void loads_content_for_branch() throws IOException {
  70. when(branchConfiguration.referenceBranchName()).thenReturn("name");
  71. setResponse(MSG);
  72. AnalysisCacheMsg msg = loader.load().get();
  73. assertThat(msg).isEqualTo(MSG);
  74. assertRequestPath("api/analysis_cache/get?project=myproject&branch=name");
  75. }
  76. @Test
  77. public void loads_compressed_content() throws IOException {
  78. setCompressedResponse(MSG);
  79. AnalysisCacheMsg msg = loader.load().get();
  80. assertThat(msg).isEqualTo(MSG);
  81. }
  82. @Test
  83. public void returns_empty_if_404() {
  84. when(wsClient.call(any(GetRequest.class))).thenThrow(new HttpException("url", 404, "content"));
  85. assertThat(loader.load()).isEmpty();
  86. }
  87. @Test
  88. public void throw_error_if_http_exception_not_404() {
  89. when(wsClient.call(any(GetRequest.class))).thenThrow(new HttpException("url", 401, "content"));
  90. assertThatThrownBy(loader::load)
  91. .isInstanceOf(MessageException.class)
  92. .hasMessage("Failed to download analysis cache: HTTP code 401: content");
  93. }
  94. @Test
  95. public void throw_error_if_cant_decompress_content() {
  96. setInvalidCompressedResponse();
  97. assertThatThrownBy(loader::load)
  98. .isInstanceOf(IllegalStateException.class)
  99. .hasMessage("Failed to download analysis cache");
  100. }
  101. private void assertRequestPath(String expectedPath) {
  102. ArgumentCaptor<GetRequest> requestCaptor = ArgumentCaptor.forClass(GetRequest.class);
  103. verify(wsClient).call(requestCaptor.capture());
  104. assertThat(requestCaptor.getValue().getPath()).isEqualTo(expectedPath);
  105. }
  106. private void setResponse(AnalysisCacheMsg msg) throws IOException {
  107. when(response.contentStream()).thenReturn(createInputStream(msg));
  108. }
  109. private void setCompressedResponse(AnalysisCacheMsg msg) throws IOException {
  110. when(response.contentStream()).thenReturn(new DeflaterInputStream(createInputStream(msg)));
  111. when(response.header(CONTENT_ENCODING)).thenReturn(Optional.of("gzip"));
  112. }
  113. private void setInvalidCompressedResponse() {
  114. when(response.contentStream()).thenReturn(new ByteArrayInputStream(new byte[] {1, 2, 3}));
  115. when(response.header(CONTENT_ENCODING)).thenReturn(Optional.of("gzip"));
  116. }
  117. private InputStream createInputStream(AnalysisCacheMsg analysisCacheMsg) throws IOException {
  118. ByteArrayOutputStream serialized = new ByteArrayOutputStream(analysisCacheMsg.getSerializedSize());
  119. analysisCacheMsg.writeTo(serialized);
  120. return new ByteArrayInputStream(serialized.toByteArray());
  121. }
  122. }