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.

ModuleSensorExtensionDictionaryTest.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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.bootstrap;
  21. import com.google.common.collect.Lists;
  22. import org.junit.Before;
  23. import org.junit.Test;
  24. import org.picocontainer.behaviors.FieldDecorated;
  25. import org.sonar.api.batch.DependedUpon;
  26. import org.sonar.api.batch.DependsUpon;
  27. import org.sonar.api.batch.Phase;
  28. import org.sonar.api.batch.ScannerSide;
  29. import org.sonar.api.batch.bootstrap.ProjectDefinition;
  30. import org.sonar.api.batch.fs.internal.DefaultInputModule;
  31. import org.sonar.api.batch.sensor.Sensor;
  32. import org.sonar.api.batch.sensor.SensorContext;
  33. import org.sonar.api.batch.sensor.SensorDescriptor;
  34. import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
  35. import org.sonar.scanner.scan.SpringModuleScanContainer;
  36. import org.sonar.scanner.scan.branch.BranchConfiguration;
  37. import org.sonar.scanner.scan.filesystem.MutableFileSystem;
  38. import org.sonar.scanner.sensor.ModuleSensorContext;
  39. import org.sonar.scanner.sensor.ModuleSensorExtensionDictionary;
  40. import org.sonar.scanner.sensor.ModuleSensorOptimizer;
  41. import org.sonar.scanner.sensor.ModuleSensorWrapper;
  42. import java.util.Arrays;
  43. import java.util.Collection;
  44. import java.util.List;
  45. import static org.assertj.core.api.Assertions.assertThat;
  46. import static org.junit.Assert.assertEquals;
  47. import static org.mockito.ArgumentMatchers.any;
  48. import static org.mockito.Mockito.mock;
  49. import static org.mockito.Mockito.when;
  50. public class ModuleSensorExtensionDictionaryTest {
  51. private final ModuleSensorOptimizer sensorOptimizer = mock(ModuleSensorOptimizer.class);
  52. private final MutableFileSystem fileSystem = mock(MutableFileSystem.class);
  53. private final BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
  54. @Before
  55. public void setUp() {
  56. when(sensorOptimizer.shouldExecute(any(DefaultSensorDescriptor.class))).thenReturn(true);
  57. }
  58. private ModuleSensorExtensionDictionary newSelector(Object... extensions) {
  59. DefaultInputModule inputModule = mock(DefaultInputModule.class);
  60. when(inputModule.definition()).thenReturn(mock(ProjectDefinition.class));
  61. SpringComponentContainer parent = new SpringComponentContainer();
  62. parent.context.refresh();
  63. SpringComponentContainer iocContainer = new SpringModuleScanContainer(parent, inputModule);
  64. iocContainer.add(Arrays.asList(extensions));
  65. iocContainer.context.refresh();
  66. return new ModuleSensorExtensionDictionary(iocContainer, mock(ModuleSensorContext.class), sensorOptimizer, fileSystem, branchConfiguration);
  67. }
  68. @Test
  69. public void testGetFilteredExtensionWithExtensionMatcher() {
  70. final Sensor sensor1 = new FakeSensor();
  71. final Sensor sensor2 = new FakeSensor();
  72. ModuleSensorExtensionDictionary selector = newSelector(sensor1, sensor2);
  73. Collection<Sensor> sensors = selector.select(Sensor.class, true, extension -> extension.equals(sensor1));
  74. assertThat(sensors).contains(sensor1);
  75. assertEquals(1, sensors.size());
  76. }
  77. @Test
  78. public void testGetFilteredExtensions() {
  79. Sensor sensor1 = new FakeSensor();
  80. Sensor sensor2 = new FakeSensor();
  81. FieldDecorated.Decorator decorator = mock(FieldDecorated.Decorator.class);
  82. ModuleSensorExtensionDictionary selector = newSelector(sensor1, sensor2, decorator);
  83. Collection<Sensor> sensors = selector.select(Sensor.class, false, null);
  84. assertThat(sensors).containsOnly(sensor1, sensor2);
  85. }
  86. @Test
  87. public void shouldSearchInParentContainers() {
  88. Sensor a = new FakeSensor();
  89. Sensor b = new FakeSensor();
  90. Sensor c = new FakeSensor();
  91. SpringComponentContainer grandParent = new SpringComponentContainer();
  92. grandParent.add(a);
  93. grandParent.context.refresh();
  94. SpringComponentContainer parent = grandParent.createChild();
  95. parent.add(b);
  96. parent.context.refresh();
  97. SpringComponentContainer child = parent.createChild();
  98. child.add(c);
  99. child.context.refresh();
  100. ModuleSensorExtensionDictionary dictionnary = new ModuleSensorExtensionDictionary(child, mock(ModuleSensorContext.class), mock(ModuleSensorOptimizer.class),
  101. fileSystem, branchConfiguration);
  102. assertThat(dictionnary.select(Sensor.class, true, null)).containsOnly(a, b, c);
  103. }
  104. @Test
  105. public void sortExtensionsByDependency() {
  106. Object a = new MethodDependentOf(null);
  107. Object b = new MethodDependentOf(a);
  108. Object c = new MethodDependentOf(b);
  109. ModuleSensorExtensionDictionary selector = newSelector(b, c, a);
  110. List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  111. assertThat(extensions).hasSize(3);
  112. assertThat(extensions.get(0)).isEqualTo(a);
  113. assertThat(extensions.get(1)).isEqualTo(b);
  114. assertThat(extensions.get(2)).isEqualTo(c);
  115. }
  116. @Test
  117. public void useMethodAnnotationsToSortExtensions() {
  118. Object a = new GeneratesSomething("foo");
  119. Object b = new MethodDependentOf("foo");
  120. ModuleSensorExtensionDictionary selector = newSelector(a, b);
  121. List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  122. assertThat(extensions.size()).isEqualTo(2);
  123. assertThat(extensions.get(0)).isEqualTo(a);
  124. assertThat(extensions.get(1)).isEqualTo(b);
  125. // different initial order
  126. selector = newSelector(b, a);
  127. extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  128. assertThat(extensions).hasSize(2);
  129. assertThat(extensions.get(0)).isEqualTo(a);
  130. assertThat(extensions.get(1)).isEqualTo(b);
  131. }
  132. @Test
  133. public void methodDependsUponCollection() {
  134. Object a = new GeneratesSomething("foo");
  135. Object b = new MethodDependentOf(Arrays.asList("foo"));
  136. ModuleSensorExtensionDictionary selector = newSelector(a, b);
  137. List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  138. assertThat(extensions).hasSize(2);
  139. assertThat(extensions.get(0)).isEqualTo(a);
  140. assertThat(extensions.get(1)).isEqualTo(b);
  141. // different initial order
  142. selector = newSelector(b, a);
  143. extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  144. assertThat(extensions).hasSize(2);
  145. assertThat(extensions.get(0)).isEqualTo(a);
  146. assertThat(extensions.get(1)).isEqualTo(b);
  147. }
  148. @Test
  149. public void methodDependsUponArray() {
  150. Object a = new GeneratesSomething("foo");
  151. Object b = new MethodDependentOf(new String[] {"foo"});
  152. ModuleSensorExtensionDictionary selector = newSelector(a, b);
  153. List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  154. assertThat(extensions).hasSize(2);
  155. assertThat(extensions.get(0)).isEqualTo(a);
  156. assertThat(extensions.get(1)).isEqualTo(b);
  157. // different initial order
  158. selector = newSelector(b, a);
  159. extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  160. assertThat(extensions).hasSize(2);
  161. assertThat(extensions.get(0)).isEqualTo(a);
  162. assertThat(extensions.get(1)).isEqualTo(b);
  163. }
  164. @Test
  165. public void useClassAnnotationsToSortExtensions() {
  166. Object a = new ClassDependedUpon();
  167. Object b = new ClassDependsUpon();
  168. ModuleSensorExtensionDictionary selector = newSelector(a, b);
  169. List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  170. assertThat(extensions).hasSize(2);
  171. assertThat(extensions.get(0)).isEqualTo(a);
  172. assertThat(extensions.get(1)).isEqualTo(b);
  173. // different initial order
  174. selector = newSelector(b, a);
  175. extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  176. assertThat(extensions).hasSize(2);
  177. assertThat(extensions.get(0)).isEqualTo(a);
  178. assertThat(extensions.get(1)).isEqualTo(b);
  179. }
  180. @Test
  181. public void useClassAnnotationsOnInterfaces() {
  182. Object a = new InterfaceDependedUpon() {
  183. };
  184. Object b = new InterfaceDependsUpon() {
  185. };
  186. ModuleSensorExtensionDictionary selector = newSelector(a, b);
  187. List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  188. assertThat(extensions).hasSize(2);
  189. assertThat(extensions.get(0)).isEqualTo(a);
  190. assertThat(extensions.get(1)).isEqualTo(b);
  191. // different initial order
  192. selector = newSelector(b, a);
  193. extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  194. assertThat(extensions).hasSize(2);
  195. assertThat(extensions.get(0)).isEqualTo(a);
  196. assertThat(extensions.get(1)).isEqualTo(b);
  197. }
  198. @Test
  199. public void inheritAnnotations() {
  200. Object a = new SubClass("foo");
  201. Object b = new MethodDependentOf("foo");
  202. ModuleSensorExtensionDictionary selector = newSelector(b, a);
  203. List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  204. assertThat(extensions).hasSize(2);
  205. assertThat(extensions.get(0)).isEqualTo(a);
  206. assertThat(extensions.get(1)).isEqualTo(b);
  207. // change initial order
  208. selector = newSelector(a, b);
  209. extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
  210. assertThat(extensions).hasSize(2);
  211. assertThat(extensions.get(0)).isEqualTo(a);
  212. assertThat(extensions.get(1)).isEqualTo(b);
  213. }
  214. @Test(expected = IllegalStateException.class)
  215. public void annotatedMethodsCanNotBePrivate() {
  216. ModuleSensorExtensionDictionary selector = newSelector();
  217. Object wrong = new Object() {
  218. @DependsUpon
  219. private Object foo() {
  220. return "foo";
  221. }
  222. };
  223. selector.evaluateAnnotatedClasses(wrong, DependsUpon.class);
  224. }
  225. @Test
  226. public void dependsUponPhaseForSensors() {
  227. PreSensor pre = new PreSensor();
  228. NormalSensor normal = new NormalSensor();
  229. PostSensor post = new PostSensor();
  230. ModuleSensorExtensionDictionary selector = newSelector(normal, post, pre);
  231. assertThat(selector.selectSensors(false)).extracting("wrappedSensor").containsExactly(pre, normal, post);
  232. }
  233. @Test
  234. public void dependsUponInheritedPhase() {
  235. PreSensorSubclass pre = new PreSensorSubclass();
  236. NormalSensor normal = new NormalSensor();
  237. PostSensorSubclass post = new PostSensorSubclass();
  238. ModuleSensorExtensionDictionary selector = newSelector(normal, post, pre);
  239. List extensions = Lists.newArrayList(selector.select(Sensor.class, true, null));
  240. assertThat(extensions).containsExactly(pre, normal, post);
  241. }
  242. @Test
  243. public void selectSensors() {
  244. FakeSensor nonGlobalSensor = new FakeSensor();
  245. FakeGlobalSensor globalSensor = new FakeGlobalSensor();
  246. ModuleSensorExtensionDictionary selector = newSelector(nonGlobalSensor, globalSensor);
  247. // verify non-global sensor
  248. Collection<ModuleSensorWrapper> extensions = selector.selectSensors(false);
  249. assertThat(extensions).hasSize(1);
  250. assertThat(extensions).extracting("wrappedSensor").containsExactly(nonGlobalSensor);
  251. // verify global sensor
  252. extensions = selector.selectSensors(true);
  253. assertThat(extensions).extracting("wrappedSensor").containsExactly(globalSensor);
  254. }
  255. interface Marker {
  256. }
  257. static class FakeSensor implements Sensor {
  258. @Override
  259. public void describe(SensorDescriptor descriptor) {
  260. }
  261. @Override
  262. public void execute(SensorContext context) {
  263. }
  264. }
  265. static class FakeGlobalSensor implements Sensor {
  266. @Override
  267. public void describe(SensorDescriptor descriptor) {
  268. descriptor.global();
  269. }
  270. @Override
  271. public void execute(SensorContext context) {
  272. }
  273. }
  274. @ScannerSide static
  275. class MethodDependentOf implements Marker {
  276. private Object dep;
  277. MethodDependentOf(Object o) {
  278. this.dep = o;
  279. }
  280. @DependsUpon
  281. public Object dependsUponObject() {
  282. return dep;
  283. }
  284. }
  285. @ScannerSide
  286. @DependsUpon("flag") static
  287. class ClassDependsUpon implements Marker {
  288. }
  289. @ScannerSide
  290. @DependedUpon("flag") static
  291. class ClassDependedUpon implements Marker {
  292. }
  293. @ScannerSide
  294. @DependsUpon("flag")
  295. interface InterfaceDependsUpon extends Marker {
  296. }
  297. @ScannerSide
  298. @DependedUpon("flag")
  299. interface InterfaceDependedUpon extends Marker {
  300. }
  301. @ScannerSide static
  302. class GeneratesSomething implements Marker {
  303. private Object gen;
  304. GeneratesSomething(Object o) {
  305. this.gen = o;
  306. }
  307. @DependedUpon
  308. public Object generates() {
  309. return gen;
  310. }
  311. }
  312. class SubClass extends GeneratesSomething implements Marker {
  313. SubClass(Object o) {
  314. super(o);
  315. }
  316. }
  317. static class NormalSensor implements Sensor {
  318. @Override
  319. public void describe(SensorDescriptor descriptor) {
  320. }
  321. @Override
  322. public void execute(SensorContext context) {
  323. }
  324. }
  325. @Phase(name = Phase.Name.PRE) static
  326. class PreSensor implements Sensor {
  327. @Override
  328. public void describe(SensorDescriptor descriptor) {
  329. }
  330. @Override
  331. public void execute(SensorContext context) {
  332. }
  333. }
  334. class PreSensorSubclass extends PreSensor {
  335. }
  336. @Phase(name = Phase.Name.POST) static
  337. class PostSensor implements Sensor {
  338. @Override
  339. public void describe(SensorDescriptor descriptor) {
  340. }
  341. @Override
  342. public void execute(SensorContext context) {
  343. }
  344. }
  345. class PostSensorSubclass extends PostSensor {
  346. }
  347. }