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.

GlobalActionTest.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 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.server.ui.ws;
  21. import java.util.Optional;
  22. import org.junit.Rule;
  23. import org.junit.Test;
  24. import org.sonar.api.config.internal.MapSettings;
  25. import org.sonar.api.platform.Server;
  26. import org.sonar.api.resources.ResourceType;
  27. import org.sonar.api.resources.ResourceTypeTree;
  28. import org.sonar.api.resources.ResourceTypes;
  29. import org.sonar.api.web.page.Page;
  30. import org.sonar.api.web.page.PageDefinition;
  31. import org.sonar.core.extension.CoreExtensionRepository;
  32. import org.sonar.core.platform.EditionProvider;
  33. import org.sonar.core.platform.PlatformEditionProvider;
  34. import org.sonar.core.platform.PluginInfo;
  35. import org.sonar.core.platform.PluginRepository;
  36. import org.sonar.db.DbClient;
  37. import org.sonar.db.dialect.H2;
  38. import org.sonar.db.dialect.PostgreSql;
  39. import org.sonar.server.almsettings.MultipleAlmFeatureProvider;
  40. import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
  41. import org.sonar.server.organization.DefaultOrganizationProvider;
  42. import org.sonar.server.organization.TestDefaultOrganizationProvider;
  43. import org.sonar.server.organization.TestOrganizationFlags;
  44. import org.sonar.server.platform.WebServer;
  45. import org.sonar.server.tester.UserSessionRule;
  46. import org.sonar.server.ui.PageRepository;
  47. import org.sonar.server.ui.WebAnalyticsLoader;
  48. import org.sonar.server.ws.WsActionTester;
  49. import org.sonar.updatecenter.common.Version;
  50. import static org.assertj.core.api.Assertions.assertThat;
  51. import static org.mockito.ArgumentMatchers.any;
  52. import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
  53. import static org.mockito.Mockito.mock;
  54. import static org.mockito.Mockito.when;
  55. import static org.sonar.test.JsonAssert.assertJson;
  56. public class GlobalActionTest {
  57. @Rule
  58. public UserSessionRule userSession = UserSessionRule.standalone();
  59. private MapSettings settings = new MapSettings();
  60. private Server server = mock(Server.class);
  61. private WebServer webServer = mock(WebServer.class);
  62. private DbClient dbClient = mock(DbClient.class, RETURNS_DEEP_STUBS);
  63. private IssueIndexSyncProgressChecker indexSyncProgressChecker = mock(IssueIndexSyncProgressChecker.class);
  64. private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
  65. private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("foo");
  66. private BranchFeatureRule branchFeature = new BranchFeatureRule();
  67. private PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class);
  68. private MultipleAlmFeatureProvider multipleAlmFeatureProvider = mock(MultipleAlmFeatureProvider.class);
  69. private WebAnalyticsLoader webAnalyticsLoader = mock(WebAnalyticsLoader.class);
  70. private WsActionTester ws;
  71. @Test
  72. public void empty_call() {
  73. init();
  74. assertJson(call()).isSimilarTo("{" +
  75. " \"globalPages\": []," +
  76. " \"settings\": {}," +
  77. " \"qualifiers\": []" +
  78. "}");
  79. }
  80. @Test
  81. public void return_qualifiers() {
  82. init(new Page[] {}, new ResourceTypeTree[] {
  83. ResourceTypeTree.builder()
  84. .addType(ResourceType.builder("POL").build())
  85. .addType(ResourceType.builder("LOP").build())
  86. .addRelations("POL", "LOP")
  87. .build(),
  88. ResourceTypeTree.builder()
  89. .addType(ResourceType.builder("PAL").build())
  90. .addType(ResourceType.builder("LAP").build())
  91. .addRelations("PAL", "LAP")
  92. .build()
  93. });
  94. assertJson(call()).isSimilarTo("{" +
  95. " \"qualifiers\": [\"POL\", \"PAL\"]" +
  96. "}");
  97. }
  98. @Test
  99. public void return_settings() {
  100. settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
  101. settings.setProperty("sonar.lf.logoWidthPx", 135);
  102. settings.setProperty("sonar.lf.gravatarServerUrl", "https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon");
  103. settings.setProperty("sonar.lf.enableGravatar", true);
  104. settings.setProperty("sonar.updatecenter.activate", false);
  105. settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
  106. settings.setProperty("sonar.developerAggregatedInfo.disabled", false);
  107. // This setting should be ignored as it's not needed
  108. settings.setProperty("sonar.defaultGroup", "sonar-users");
  109. init();
  110. assertJson(call()).isSimilarTo("{" +
  111. " \"settings\": {" +
  112. " \"sonar.lf.logoUrl\": \"http://example.com/my-custom-logo.png\"," +
  113. " \"sonar.lf.logoWidthPx\": \"135\"," +
  114. " \"sonar.lf.gravatarServerUrl\": \"https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon\"," +
  115. " \"sonar.lf.enableGravatar\": \"true\"," +
  116. " \"sonar.updatecenter.activate\": \"false\"," +
  117. " \"sonar.technicalDebt.ratingGrid\": \"0.05,0.1,0.2,0.5\"" +
  118. " \"sonar.developerAggregatedInfo.disabled\": \"false\"" +
  119. " }" +
  120. "}");
  121. }
  122. @Test
  123. public void return_sonarcloud_settings() {
  124. settings.setProperty("sonar.sonarcloud.enabled", true);
  125. settings.setProperty("sonar.prismic.accessToken", "secret");
  126. settings.setProperty("sonar.analytics.gtm.trackingId", "gtm_id");
  127. settings.setProperty("sonar.homepage.url", "https://s3/homepage.json");
  128. init();
  129. assertJson(call()).isSimilarTo("{" +
  130. " \"settings\": {" +
  131. " \"sonar.prismic.accessToken\": \"secret\"," +
  132. " \"sonar.analytics.gtm.trackingId\": \"gtm_id\"," +
  133. " \"sonar.homepage.url\": \"https://s3/homepage.json\"" +
  134. " }" +
  135. "}");
  136. }
  137. @Test
  138. public void return_developer_info_disabled_setting() {
  139. init();
  140. settings.setProperty("sonar.developerAggregatedInfo.disabled", true);
  141. assertJson(call()).isSimilarTo("{" +
  142. " \"settings\": {" +
  143. " \"sonar.developerAggregatedInfo.disabled\": \"true\"" +
  144. " }" +
  145. "}");
  146. }
  147. @Test
  148. public void return_deprecated_logo_settings() {
  149. init();
  150. settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
  151. settings.setProperty("sonar.lf.logoWidthPx", 135);
  152. assertJson(call()).isSimilarTo("{" +
  153. " \"settings\": {" +
  154. " \"sonar.lf.logoUrl\": \"http://example.com/my-custom-logo.png\"," +
  155. " \"sonar.lf.logoWidthPx\": \"135\"" +
  156. " }," +
  157. " \"logoUrl\": \"http://example.com/my-custom-logo.png\"," +
  158. " \"logoWidth\": \"135\"" +
  159. "}");
  160. }
  161. @Test
  162. public void the_returned_global_pages_do_not_include_administration_pages() {
  163. init(createPages(), new ResourceTypeTree[] {});
  164. assertJson(call()).isSimilarTo("{" +
  165. " \"globalPages\": [" +
  166. " {" +
  167. " \"key\": \"another_plugin/page\"," +
  168. " \"name\": \"My Another Page\"" +
  169. " }," +
  170. " {" +
  171. " \"key\": \"my_plugin/page\"," +
  172. " \"name\": \"My Plugin Page\"" +
  173. " }" +
  174. " ]" +
  175. "}");
  176. }
  177. @Test
  178. public void return_sonarqube_version() {
  179. init();
  180. when(server.getVersion()).thenReturn("6.2");
  181. assertJson(call()).isSimilarTo("{" +
  182. " \"version\": \"6.2\"" +
  183. "}");
  184. }
  185. @Test
  186. public void functional_version_when_4_digits() {
  187. init();
  188. when(server.getVersion()).thenReturn("6.3.1.1234");
  189. String result = call();
  190. assertThat(result).contains("6.3.1 (build 1234)");
  191. }
  192. @Test
  193. public void functional_version_when_third_digit_is_0() {
  194. init();
  195. when(server.getVersion()).thenReturn("6.3.0.1234");
  196. String result = call();
  197. assertThat(result).contains("6.3 (build 1234)");
  198. }
  199. @Test
  200. public void return_if_production_database_or_not() {
  201. init();
  202. when(dbClient.getDatabase().getDialect()).thenReturn(new PostgreSql());
  203. assertJson(call()).isSimilarTo("{" +
  204. " \"productionDatabase\": true" +
  205. "}");
  206. }
  207. @Test
  208. public void organization_support() {
  209. init();
  210. organizationFlags.setEnabled(true);
  211. assertJson(call()).isSimilarTo("{" +
  212. " \"organizationsEnabled\": true," +
  213. " \"defaultOrganization\": \"key_foo\"" +
  214. "}");
  215. }
  216. @Test
  217. public void branch_support() {
  218. init();
  219. branchFeature.setEnabled(true);
  220. assertJson(call()).isSimilarTo("{\"branchesEnabled\":true}");
  221. branchFeature.setEnabled(false);
  222. assertJson(call()).isSimilarTo("{\"branchesEnabled\":false}");
  223. }
  224. @Test
  225. public void multiple_alm_enabled() {
  226. init();
  227. when(multipleAlmFeatureProvider.enabled()).thenReturn(true);
  228. assertJson(call()).isSimilarTo("{\"multipleAlmEnabled\":true}");
  229. when(multipleAlmFeatureProvider.enabled()).thenReturn(false);
  230. assertJson(call()).isSimilarTo("{\"multipleAlmEnabled\":false}");
  231. }
  232. @Test
  233. public void return_need_issue_sync() {
  234. init();
  235. when(indexSyncProgressChecker.isIssueSyncInProgress(any())).thenReturn(true);
  236. assertJson(call()).isSimilarTo("{\"needIssueSync\": true}");
  237. when(indexSyncProgressChecker.isIssueSyncInProgress(any())).thenReturn(false);
  238. assertJson(call()).isSimilarTo("{\"needIssueSync\": false}");
  239. }
  240. @Test
  241. public void can_admin_on_global_level() {
  242. init();
  243. userSession.logIn().setRoot();
  244. assertJson(call()).isSimilarTo("{\"canAdmin\":true}");
  245. }
  246. @Test
  247. public void standalone_flag() {
  248. init();
  249. userSession.logIn().setRoot();
  250. when(webServer.isStandalone()).thenReturn(true);
  251. assertJson(call()).isSimilarTo("{\"standalone\":true}");
  252. }
  253. @Test
  254. public void not_standalone_flag() {
  255. init();
  256. userSession.logIn().setRoot();
  257. when(webServer.isStandalone()).thenReturn(false);
  258. assertJson(call()).isSimilarTo("{\"standalone\":false}");
  259. }
  260. @Test
  261. public void test_example_response() {
  262. settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
  263. settings.setProperty("sonar.lf.logoWidthPx", 135);
  264. settings.setProperty("sonar.lf.gravatarServerUrl", "http://some-server.tld/logo.png");
  265. settings.setProperty("sonar.lf.enableGravatar", true);
  266. settings.setProperty("sonar.updatecenter.activate", false);
  267. settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
  268. init(createPages(), new ResourceTypeTree[] {
  269. ResourceTypeTree.builder()
  270. .addType(ResourceType.builder("POL").build())
  271. .addType(ResourceType.builder("LOP").build())
  272. .addRelations("POL", "LOP")
  273. .build(),
  274. ResourceTypeTree.builder()
  275. .addType(ResourceType.builder("PAL").build())
  276. .addType(ResourceType.builder("LAP").build())
  277. .addRelations("PAL", "LAP")
  278. .build()
  279. });
  280. when(server.getVersion()).thenReturn("6.2");
  281. when(dbClient.getDatabase().getDialect()).thenReturn(new PostgreSql());
  282. when(webServer.isStandalone()).thenReturn(true);
  283. when(editionProvider.get()).thenReturn(Optional.of(EditionProvider.Edition.COMMUNITY));
  284. String result = call();
  285. assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
  286. }
  287. @Test
  288. public void edition_is_not_returned_if_not_defined() {
  289. init();
  290. when(editionProvider.get()).thenReturn(Optional.empty());
  291. String json = call();
  292. assertThat(json).doesNotContain("edition");
  293. }
  294. @Test
  295. public void edition_is_returned_if_defined() {
  296. init();
  297. when(editionProvider.get()).thenReturn(Optional.of(EditionProvider.Edition.DEVELOPER));
  298. String json = call();
  299. assertJson(json).isSimilarTo("{\"edition\":\"developer\"}");
  300. }
  301. @Test
  302. public void web_analytics_js_path_is_not_returned_if_not_defined() {
  303. init();
  304. when(webAnalyticsLoader.getUrlPathToJs()).thenReturn(Optional.empty());
  305. String json = call();
  306. assertThat(json).doesNotContain("webAnalyticsJsPath");
  307. }
  308. @Test
  309. public void web_analytics_js_path_is_returned_if_defined() {
  310. init();
  311. String path = "static/googleanalytics/analytics.js";
  312. when(webAnalyticsLoader.getUrlPathToJs()).thenReturn(Optional.of(path));
  313. String json = call();
  314. assertJson(json).isSimilarTo("{\"webAnalyticsJsPath\":\"" + path + "\"}");
  315. }
  316. private void init() {
  317. init(new org.sonar.api.web.page.Page[] {}, new ResourceTypeTree[] {});
  318. }
  319. private void init(org.sonar.api.web.page.Page[] pages, ResourceTypeTree[] resourceTypeTrees) {
  320. when(dbClient.getDatabase().getDialect()).thenReturn(new H2());
  321. when(server.getVersion()).thenReturn("6.42");
  322. PluginRepository pluginRepository = mock(PluginRepository.class);
  323. when(pluginRepository.hasPlugin(any())).thenReturn(true);
  324. when(pluginRepository.getPluginInfo(any())).thenReturn(new PluginInfo("unused").setVersion(Version.create("1.0")));
  325. CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
  326. when(coreExtensionRepository.isInstalled(any())).thenReturn(false);
  327. PageRepository pageRepository = new PageRepository(pluginRepository, coreExtensionRepository, new PageDefinition[] {context -> {
  328. for (Page page : pages) {
  329. context.addPage(page);
  330. }
  331. }});
  332. pageRepository.start();
  333. GlobalAction wsAction = new GlobalAction(pageRepository, settings.asConfig(), new ResourceTypes(resourceTypeTrees), server,
  334. webServer, dbClient, organizationFlags, defaultOrganizationProvider, branchFeature, userSession, editionProvider, multipleAlmFeatureProvider, webAnalyticsLoader,
  335. indexSyncProgressChecker);
  336. ws = new WsActionTester(wsAction);
  337. wsAction.start();
  338. }
  339. private String call() {
  340. return ws.newRequest().execute().getInput();
  341. }
  342. private Page[] createPages() {
  343. Page page = Page.builder("my_plugin/page").setName("My Plugin Page").build();
  344. Page anotherPage = Page.builder("another_plugin/page").setName("My Another Page").build();
  345. Page adminPage = Page.builder("my_plugin/admin_page").setName("Admin Page").setAdmin(true).build();
  346. return new Page[] {page, anotherPage, adminPage};
  347. }
  348. }