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.

GitlabHttpClientTest.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 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.alm.client.gitlab;
  21. import java.io.IOException;
  22. import java.util.Optional;
  23. import java.util.concurrent.TimeUnit;
  24. import okhttp3.mockwebserver.MockResponse;
  25. import okhttp3.mockwebserver.MockWebServer;
  26. import okhttp3.mockwebserver.RecordedRequest;
  27. import org.junit.After;
  28. import org.junit.Before;
  29. import org.junit.Rule;
  30. import org.junit.Test;
  31. import org.sonar.alm.client.ConstantTimeoutConfiguration;
  32. import org.sonar.alm.client.TimeoutConfiguration;
  33. import org.sonar.api.utils.log.LogTester;
  34. import org.sonar.api.utils.log.LoggerLevel;
  35. import static org.assertj.core.api.Assertions.assertThat;
  36. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  37. import static org.assertj.core.api.Assertions.tuple;
  38. public class GitlabHttpClientTest {
  39. @Rule
  40. public LogTester logTester = new LogTester();
  41. private final MockWebServer server = new MockWebServer();
  42. private GitlabHttpClient underTest;
  43. private String gitlabUrl;
  44. @Before
  45. public void prepare() throws IOException {
  46. server.start();
  47. String urlWithEndingSlash = server.url("").toString();
  48. gitlabUrl = urlWithEndingSlash.substring(0, urlWithEndingSlash.length() - 1);
  49. TimeoutConfiguration timeoutConfiguration = new ConstantTimeoutConfiguration(10_000);
  50. underTest = new GitlabHttpClient(timeoutConfiguration);
  51. }
  52. @After
  53. public void stopServer() throws IOException {
  54. server.shutdown();
  55. }
  56. @Test
  57. public void should_throw_IllegalArgumentException_when_token_is_revoked() {
  58. MockResponse response = new MockResponse()
  59. .setResponseCode(401)
  60. .setBody("{\"error\":\"invalid_token\",\"error_description\":\"Token was revoked. You have to re-authorize from the user.\"}");
  61. server.enqueue(response);
  62. assertThatThrownBy(() -> underTest.searchProjects(gitlabUrl, "pat", "example", 1, 2))
  63. .isInstanceOf(IllegalArgumentException.class)
  64. .hasMessage("Your GitLab token was revoked");
  65. }
  66. @Test
  67. public void should_throw_IllegalArgumentException_when_token_insufficient_scope() {
  68. MockResponse response = new MockResponse()
  69. .setResponseCode(403)
  70. .setBody("{\"error\":\"insufficient_scope\"," +
  71. "\"error_description\":\"The request requires higher privileges than provided by the access token.\"," +
  72. "\"scope\":\"api read_api\"}");
  73. server.enqueue(response);
  74. assertThatThrownBy(() -> underTest.searchProjects(gitlabUrl, "pat", "example", 1, 2))
  75. .isInstanceOf(IllegalArgumentException.class)
  76. .hasMessage("Your GitLab token has insufficient scope");
  77. }
  78. @Test
  79. public void should_throw_IllegalArgumentException_when_invalide_json_in_401_response() {
  80. MockResponse response = new MockResponse()
  81. .setResponseCode(401)
  82. .setBody("error in pat");
  83. server.enqueue(response);
  84. assertThatThrownBy(() -> underTest.searchProjects(gitlabUrl, "pat", "example", 1, 2))
  85. .isInstanceOf(IllegalArgumentException.class)
  86. .hasMessage("Invalid personal access token");
  87. }
  88. @Test
  89. public void should_throw_IllegalArgumentException_when_redirected() {
  90. MockResponse response = new MockResponse()
  91. .setResponseCode(308);
  92. server.enqueue(response);
  93. assertThatThrownBy(() -> underTest.searchProjects(gitlabUrl, "pat", "example", 1, 2))
  94. .isInstanceOf(IllegalArgumentException.class)
  95. .hasMessage("Request was redirected, please provide the correct URL");
  96. }
  97. @Test
  98. public void get_project() {
  99. MockResponse response = new MockResponse()
  100. .setResponseCode(200)
  101. .setBody("{\n"
  102. + " \"id\": 12345,\n"
  103. + " \"name\": \"SonarQube example 1\",\n"
  104. + " \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 1\",\n"
  105. + " \"path\": \"sonarqube-example-1\",\n"
  106. + " \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-1\",\n"
  107. + " \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1\"\n"
  108. + " }");
  109. server.enqueue(response);
  110. assertThat(underTest.getProject(gitlabUrl, "pat", 12345L))
  111. .extracting(Project::getId, Project::getName)
  112. .containsExactly(12345L, "SonarQube example 1");
  113. }
  114. @Test
  115. public void get_project_fail_if_non_json_payload() {
  116. MockResponse response = new MockResponse()
  117. .setResponseCode(200)
  118. .setBody("non json payload");
  119. server.enqueue(response);
  120. assertThatThrownBy(() -> underTest.getProject(gitlabUrl, "pat", 12345L))
  121. .isInstanceOf(IllegalArgumentException.class)
  122. .hasMessage("Could not parse GitLab answer to retrieve a project. Got a non-json payload as result.");
  123. }
  124. @Test
  125. public void get_branches() {
  126. MockResponse response = new MockResponse()
  127. .setResponseCode(200)
  128. .setBody("[{\n"
  129. + " \"name\": \"main\",\n"
  130. + " \"default\": true\n"
  131. + "},{\n"
  132. + " \"name\": \"other\",\n"
  133. + " \"default\": false\n"
  134. + "}]");
  135. server.enqueue(response);
  136. assertThat(underTest.getBranches(gitlabUrl, "pat", 12345L))
  137. .extracting(GitLabBranch::getName, GitLabBranch::isDefault)
  138. .containsExactly(
  139. tuple("main", true),
  140. tuple("other", false)
  141. );
  142. }
  143. @Test
  144. public void get_branches_fail_if_non_json_payload() {
  145. MockResponse response = new MockResponse()
  146. .setResponseCode(200)
  147. .setBody("non json payload");
  148. server.enqueue(response);
  149. String instanceUrl = gitlabUrl;
  150. assertThatThrownBy(() -> underTest.getBranches(instanceUrl, "pat", 12345L))
  151. .isInstanceOf(IllegalArgumentException.class)
  152. .hasMessage("Could not parse GitLab answer to retrieve project branches. Got a non-json payload as result.");
  153. }
  154. @Test
  155. public void get_branches_fail_if_exception() throws IOException {
  156. server.shutdown();
  157. String instanceUrl = gitlabUrl;
  158. assertThatThrownBy(() -> underTest.getBranches(instanceUrl, "pat", 12345L))
  159. .isInstanceOf(IllegalStateException.class)
  160. .hasMessageContaining("Failed to connect to");
  161. }
  162. @Test
  163. public void search_projects() throws InterruptedException {
  164. MockResponse projects = new MockResponse()
  165. .setResponseCode(200)
  166. .setBody("[\n"
  167. + " {\n"
  168. + " \"id\": 1,\n"
  169. + " \"name\": \"SonarQube example 1\",\n"
  170. + " \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 1\",\n"
  171. + " \"path\": \"sonarqube-example-1\",\n"
  172. + " \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-1\",\n"
  173. + " \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1\"\n"
  174. + " },\n"
  175. + " {\n"
  176. + " \"id\": 2,\n"
  177. + " \"name\": \"SonarQube example 2\",\n"
  178. + " \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 2\",\n"
  179. + " \"path\": \"sonarqube-example-2\",\n"
  180. + " \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-2\",\n"
  181. + " \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-2\"\n"
  182. + " },\n"
  183. + " {\n"
  184. + " \"id\": 3,\n"
  185. + " \"name\": \"SonarQube example 3\",\n"
  186. + " \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 3\",\n"
  187. + " \"path\": \"sonarqube-example-3\",\n"
  188. + " \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-3\",\n"
  189. + " \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-3\"\n"
  190. + " }\n"
  191. + "]");
  192. projects.addHeader("X-Page", 1);
  193. projects.addHeader("X-Per-Page", 10);
  194. projects.addHeader("X-Total", 3);
  195. server.enqueue(projects);
  196. ProjectList projectList = underTest.searchProjects(gitlabUrl, "pat", "example", 1, 10);
  197. assertThat(projectList.getPageNumber()).isOne();
  198. assertThat(projectList.getPageSize()).isEqualTo(10);
  199. assertThat(projectList.getTotal()).isEqualTo(3);
  200. assertThat(projectList.getProjects()).hasSize(3);
  201. assertThat(projectList.getProjects()).extracting(
  202. Project::getId, Project::getName, Project::getNameWithNamespace, Project::getPath, Project::getPathWithNamespace, Project::getWebUrl).containsExactly(
  203. tuple(1L, "SonarQube example 1", "SonarSource / SonarQube / SonarQube example 1", "sonarqube-example-1", "sonarsource/sonarqube/sonarqube-example-1",
  204. "https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1"),
  205. tuple(2L, "SonarQube example 2", "SonarSource / SonarQube / SonarQube example 2", "sonarqube-example-2", "sonarsource/sonarqube/sonarqube-example-2",
  206. "https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-2"),
  207. tuple(3L, "SonarQube example 3", "SonarSource / SonarQube / SonarQube example 3", "sonarqube-example-3", "sonarsource/sonarqube/sonarqube-example-3",
  208. "https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-3"));
  209. RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
  210. String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
  211. assertThat(gitlabUrlCall).isEqualTo(server.url("") + "projects?archived=false&simple=true&membership=true&order_by=name&sort=asc&search=example&page=1&per_page=10");
  212. assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
  213. }
  214. @Test
  215. public void search_projects_dont_fail_if_no_x_total() throws InterruptedException {
  216. MockResponse projects = new MockResponse()
  217. .setResponseCode(200)
  218. .setBody("[\n"
  219. + " {\n"
  220. + " \"id\": 1,\n"
  221. + " \"name\": \"SonarQube example 1\",\n"
  222. + " \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 1\",\n"
  223. + " \"path\": \"sonarqube-example-1\",\n"
  224. + " \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-1\",\n"
  225. + " \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1\"\n"
  226. + " }"
  227. + "]");
  228. projects.addHeader("X-Page", 1);
  229. projects.addHeader("X-Per-Page", 10);
  230. server.enqueue(projects);
  231. ProjectList projectList = underTest.searchProjects(gitlabUrl, "pat", "example", 1, 10);
  232. assertThat(projectList.getPageNumber()).isOne();
  233. assertThat(projectList.getPageSize()).isEqualTo(10);
  234. assertThat(projectList.getTotal()).isNull();
  235. assertThat(projectList.getProjects()).hasSize(1);
  236. assertThat(projectList.getProjects()).extracting(
  237. Project::getId, Project::getName, Project::getNameWithNamespace, Project::getPath, Project::getPathWithNamespace, Project::getWebUrl).containsExactly(
  238. tuple(1L, "SonarQube example 1", "SonarSource / SonarQube / SonarQube example 1", "sonarqube-example-1", "sonarsource/sonarqube/sonarqube-example-1",
  239. "https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1"));
  240. RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
  241. String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
  242. assertThat(gitlabUrlCall).isEqualTo(server.url("") + "projects?archived=false&simple=true&membership=true&order_by=name&sort=asc&search=example&page=1&per_page=10");
  243. assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
  244. }
  245. @Test
  246. public void search_projects_with_case_insensitive_pagination_headers() throws InterruptedException {
  247. MockResponse projects1 = new MockResponse()
  248. .setResponseCode(200)
  249. .setBody("[\n"
  250. + " {\n"
  251. + " \"id\": 1,\n"
  252. + " \"name\": \"SonarQube example 1\",\n"
  253. + " \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 1\",\n"
  254. + " \"path\": \"sonarqube-example-1\",\n"
  255. + " \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-1\",\n"
  256. + " \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1\"\n"
  257. + " }"
  258. + "]");
  259. projects1.addHeader("x-page", 1);
  260. projects1.addHeader("x-Per-page", 1);
  261. projects1.addHeader("X-Total", 2);
  262. server.enqueue(projects1);
  263. ProjectList projectList = underTest.searchProjects(gitlabUrl, "pat", "example", 1, 10);
  264. assertThat(projectList.getPageNumber()).isOne();
  265. assertThat(projectList.getPageSize()).isOne();
  266. assertThat(projectList.getTotal()).isEqualTo(2);
  267. assertThat(projectList.getProjects()).hasSize(1);
  268. assertThat(projectList.getProjects()).extracting(
  269. Project::getId, Project::getName, Project::getNameWithNamespace, Project::getPath, Project::getPathWithNamespace, Project::getWebUrl).containsExactly(
  270. tuple(1L, "SonarQube example 1", "SonarSource / SonarQube / SonarQube example 1", "sonarqube-example-1", "sonarsource/sonarqube/sonarqube-example-1",
  271. "https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1"));
  272. RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
  273. String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
  274. assertThat(gitlabUrlCall).isEqualTo(server.url("") + "projects?archived=false&simple=true&membership=true&order_by=name&sort=asc&search=example&page=1&per_page=10");
  275. assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
  276. }
  277. @Test
  278. public void search_projects_projectName_param_should_be_encoded() throws InterruptedException {
  279. MockResponse projects = new MockResponse()
  280. .setResponseCode(200)
  281. .setBody("[]");
  282. projects.addHeader("X-Page", 1);
  283. projects.addHeader("X-Per-Page", 10);
  284. projects.addHeader("X-Total", 0);
  285. server.enqueue(projects);
  286. ProjectList projectList = underTest.searchProjects(gitlabUrl, "pat", "&page=<script>alert('nasty')</script>", 1, 10);
  287. RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
  288. String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
  289. assertThat(projectList.getProjects()).isEmpty();
  290. assertThat(gitlabUrlCall).isEqualTo(
  291. server.url("")
  292. + "projects?archived=false&simple=true&membership=true&order_by=name&sort=asc&search=%26page%3D%3Cscript%3Ealert%28%27nasty%27%29%3C%2Fscript%3E&page=1&per_page=10");
  293. assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
  294. }
  295. @Test
  296. public void search_projects_projectName_param_null_should_pass_empty_string() throws InterruptedException {
  297. MockResponse projects = new MockResponse()
  298. .setResponseCode(200)
  299. .setBody("[]");
  300. projects.addHeader("X-Page", 1);
  301. projects.addHeader("X-Per-Page", 10);
  302. projects.addHeader("X-Total", 0);
  303. server.enqueue(projects);
  304. ProjectList projectList = underTest.searchProjects(gitlabUrl, "pat", null, 1, 10);
  305. RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
  306. String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
  307. assertThat(projectList.getProjects()).isEmpty();
  308. assertThat(gitlabUrlCall).isEqualTo(
  309. server.url("") + "projects?archived=false&simple=true&membership=true&order_by=name&sort=asc&search=&page=1&per_page=10");
  310. assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
  311. }
  312. @Test
  313. public void get_project_details() throws InterruptedException {
  314. MockResponse projectResponse = new MockResponse()
  315. .setResponseCode(200)
  316. .setBody("{"
  317. + " \"id\": 1234,"
  318. + " \"name\": \"SonarQube example 2\","
  319. + " \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 2\","
  320. + " \"path\": \"sonarqube-example-2\","
  321. + " \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-2\","
  322. + " \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-2\""
  323. + "}");
  324. server.enqueue(projectResponse);
  325. Project project = underTest.getProject(gitlabUrl, "pat", 1234L);
  326. RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
  327. String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
  328. assertThat(project).isNotNull();
  329. assertThat(gitlabUrlCall).isEqualTo(
  330. server.url("") + "projects/1234");
  331. assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
  332. }
  333. @Test
  334. public void get_reporter_level_access_project() throws InterruptedException {
  335. MockResponse projectResponse = new MockResponse()
  336. .setResponseCode(200)
  337. .setBody("[{"
  338. + " \"id\": 1234,"
  339. + " \"name\": \"SonarQube example 2\","
  340. + " \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 2\","
  341. + " \"path\": \"sonarqube-example-2\","
  342. + " \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-2\","
  343. + " \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-2\""
  344. + "}]");
  345. server.enqueue(projectResponse);
  346. Optional<Project> project = underTest.getReporterLevelAccessProject(gitlabUrl, "pat", 1234L);
  347. RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
  348. String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
  349. assertThat(project).isNotNull();
  350. assertThat(gitlabUrlCall).isEqualTo(
  351. server.url("") + "projects?min_access_level=20&id_after=1233&id_before=1235");
  352. assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
  353. }
  354. @Test
  355. public void search_projects_fail_if_could_not_parse_pagination_number() {
  356. MockResponse projects = new MockResponse()
  357. .setResponseCode(200)
  358. .setBody("[ ]");
  359. projects.addHeader("X-Page", "bad-page-number");
  360. projects.addHeader("X-Per-Page", "bad-per-page-number");
  361. projects.addHeader("X-Total", "bad-total-number");
  362. server.enqueue(projects);
  363. assertThatThrownBy(() -> underTest.searchProjects(gitlabUrl, "pat", "example", 1, 10))
  364. .isInstanceOf(IllegalArgumentException.class)
  365. .hasMessage("Could not parse pagination number");
  366. }
  367. @Test
  368. public void search_projects_fail_if_pagination_data_not_returned() {
  369. MockResponse projects = new MockResponse()
  370. .setResponseCode(200)
  371. .setBody("[ ]");
  372. server.enqueue(projects);
  373. assertThatThrownBy(() -> underTest.searchProjects(gitlabUrl, "pat", "example", 1, 10))
  374. .isInstanceOf(IllegalArgumentException.class)
  375. .hasMessage("Pagination data from GitLab response is missing");
  376. }
  377. @Test
  378. public void throws_ISE_when_get_projects_not_http_200() {
  379. MockResponse projects = new MockResponse()
  380. .setResponseCode(500)
  381. .setBody("test");
  382. server.enqueue(projects);
  383. assertThatThrownBy(() -> underTest.searchProjects(gitlabUrl, "pat", "example", 1, 2))
  384. .isInstanceOf(IllegalArgumentException.class)
  385. .hasMessage("Could not get projects from GitLab instance");
  386. }
  387. @Test
  388. public void fail_check_read_permission_with_unexpected_io_exception_with_detailed_log() throws IOException {
  389. server.shutdown();
  390. assertThatThrownBy(() -> underTest.checkReadPermission(gitlabUrl, "token"))
  391. .isInstanceOf(IllegalArgumentException.class)
  392. .hasMessage("Could not validate GitLab read permission. Got an unexpected answer.");
  393. assertThat(logTester.logs(LoggerLevel.INFO).get(0))
  394. .contains("Gitlab API call to [" + server.url("/projects") + "] " +
  395. "failed with error message : [Failed to connect to " + server.getHostName());
  396. }
  397. @Test
  398. public void fail_check_token_with_unexpected_io_exception_with_detailed_log() throws IOException {
  399. server.shutdown();
  400. assertThatThrownBy(() -> underTest.checkToken(gitlabUrl, "token"))
  401. .isInstanceOf(IllegalArgumentException.class)
  402. .hasMessage("Could not validate GitLab token. Got an unexpected answer.");
  403. assertThat(logTester.logs(LoggerLevel.INFO).get(0))
  404. .contains("Gitlab API call to [" + server.url("user") + "] " +
  405. "failed with error message : [Failed to connect to " + server.getHostName());
  406. }
  407. @Test
  408. public void fail_check_write_permission_with_unexpected_io_exception_with_detailed_log() throws IOException {
  409. server.shutdown();
  410. assertThatThrownBy(() -> underTest.checkWritePermission(gitlabUrl, "token"))
  411. .isInstanceOf(IllegalArgumentException.class)
  412. .hasMessage("Could not validate GitLab write permission. Got an unexpected answer.");
  413. assertThat(logTester.logs(LoggerLevel.INFO).get(0))
  414. .contains("Gitlab API call to [" + server.url("/markdown") + "] " +
  415. "failed with error message : [Failed to connect to " + server.getHostName());
  416. }
  417. @Test
  418. public void fail_get_project_with_unexpected_io_exception_with_detailed_log() throws IOException {
  419. server.shutdown();
  420. assertThatThrownBy(() -> underTest.getProject(gitlabUrl, "token", 0L))
  421. .isInstanceOf(IllegalStateException.class)
  422. .hasMessageContaining("Failed to connect to");
  423. assertThat(logTester.logs(LoggerLevel.INFO).get(0))
  424. .contains("Gitlab API call to [" + server.url("/projects/0") + "] " +
  425. "failed with error message : [Failed to connect to " + server.getHostName());
  426. }
  427. @Test
  428. public void fail_get_branches_with_unexpected_io_exception_with_detailed_log() throws IOException {
  429. server.shutdown();
  430. assertThatThrownBy(() -> underTest.getBranches(gitlabUrl, "token", 0L))
  431. .isInstanceOf(IllegalStateException.class)
  432. .hasMessageContaining("Failed to connect to " + server.getHostName());
  433. assertThat(logTester.logs(LoggerLevel.INFO).get(0))
  434. .contains("Gitlab API call to [" + server.url("/projects/0/repository/branches") + "] " +
  435. "failed with error message : [Failed to connect to " + server.getHostName());
  436. }
  437. @Test
  438. public void fail_search_projects_with_unexpected_io_exception_with_detailed_log() throws IOException {
  439. server.shutdown();
  440. assertThatThrownBy(() -> underTest.searchProjects(gitlabUrl, "token", null, 1, 1))
  441. .isInstanceOf(IllegalStateException.class)
  442. .hasMessageContaining("Failed to connect to");
  443. assertThat(logTester.logs(LoggerLevel.INFO).get(0))
  444. .contains(
  445. "Gitlab API call to [" + server.url("/projects?archived=false&simple=true&membership=true&order_by=name&sort=asc&search=&page=1&per_page=1")
  446. + "] " +
  447. "failed with error message : [Failed to connect to " + server.getHostName());
  448. }
  449. }