3 * Copyright (C) 2009-2019 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.scanner.bootstrap;
22 import com.google.common.collect.Lists;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.List;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.picocontainer.behaviors.FieldDecorated;
29 import org.sonar.api.batch.DependedUpon;
30 import org.sonar.api.batch.DependsUpon;
31 import org.sonar.api.batch.Phase;
32 import org.sonar.api.batch.ScannerSide;
33 import org.sonar.api.batch.sensor.Sensor;
34 import org.sonar.api.batch.sensor.SensorContext;
35 import org.sonar.api.batch.sensor.SensorDescriptor;
36 import org.sonar.core.platform.ComponentContainer;
37 import org.sonar.scanner.sensor.DefaultSensorDescriptor;
38 import org.sonar.scanner.sensor.ModuleSensorContext;
39 import org.sonar.scanner.sensor.ModuleSensorExtensionDictionnary;
40 import org.sonar.scanner.sensor.ModuleSensorOptimizer;
41 import org.sonar.scanner.sensor.ModuleSensorWrapper;
43 import static org.assertj.core.api.Assertions.assertThat;
44 import static org.junit.Assert.assertEquals;
45 import static org.mockito.ArgumentMatchers.any;
46 import static org.mockito.Mockito.mock;
47 import static org.mockito.Mockito.when;
49 public class ModuleSensorExtensionDictionnaryTest {
50 private ModuleSensorOptimizer sensorOptimizer = mock(ModuleSensorOptimizer.class);
54 when(sensorOptimizer.shouldExecute(any(DefaultSensorDescriptor.class))).thenReturn(true);
57 private ModuleSensorExtensionDictionnary newSelector(Object... extensions) {
58 ComponentContainer iocContainer = new ComponentContainer();
59 for (Object extension : extensions) {
60 iocContainer.addSingleton(extension);
62 return new ModuleSensorExtensionDictionnary(iocContainer, mock(ModuleSensorContext.class), sensorOptimizer);
66 public void testGetFilteredExtensionWithExtensionMatcher() {
67 final Sensor sensor1 = new FakeSensor();
68 final Sensor sensor2 = new FakeSensor();
70 ModuleSensorExtensionDictionnary selector = newSelector(sensor1, sensor2);
71 Collection<Sensor> sensors = selector.select(Sensor.class, true, extension -> extension.equals(sensor1));
72 assertThat(sensors).contains(sensor1);
73 assertEquals(1, sensors.size());
77 public void testGetFilteredExtensions() {
78 Sensor sensor1 = new FakeSensor();
79 Sensor sensor2 = new FakeSensor();
80 FieldDecorated.Decorator decorator = mock(FieldDecorated.Decorator.class);
82 ModuleSensorExtensionDictionnary selector = newSelector(sensor1, sensor2, decorator);
83 Collection<Sensor> sensors = selector.select(Sensor.class, false, null);
85 assertThat(sensors).containsOnly(sensor1, sensor2);
89 public void shouldSearchInParentContainers() {
90 Sensor a = new FakeSensor();
91 Sensor b = new FakeSensor();
92 Sensor c = new FakeSensor();
94 ComponentContainer grandParent = new ComponentContainer();
95 grandParent.addSingleton(a);
97 ComponentContainer parent = grandParent.createChild();
98 parent.addSingleton(b);
100 ComponentContainer child = parent.createChild();
101 child.addSingleton(c);
103 ModuleSensorExtensionDictionnary dictionnary = new ModuleSensorExtensionDictionnary(child, mock(ModuleSensorContext.class), mock(ModuleSensorOptimizer.class));
104 assertThat(dictionnary.select(Sensor.class, true, null)).containsOnly(a, b, c);
108 public void sortExtensionsByDependency() {
109 Object a = new MethodDependentOf(null);
110 Object b = new MethodDependentOf(a);
111 Object c = new MethodDependentOf(b);
113 ModuleSensorExtensionDictionnary selector = newSelector(b, c, a);
114 List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
116 assertThat(extensions).hasSize(3);
117 assertThat(extensions.get(0)).isEqualTo(a);
118 assertThat(extensions.get(1)).isEqualTo(b);
119 assertThat(extensions.get(2)).isEqualTo(c);
123 public void useMethodAnnotationsToSortExtensions() {
124 Object a = new GeneratesSomething("foo");
125 Object b = new MethodDependentOf("foo");
127 ModuleSensorExtensionDictionnary selector = newSelector(a, b);
128 List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
130 assertThat(extensions.size()).isEqualTo(2);
131 assertThat(extensions.get(0)).isEqualTo(a);
132 assertThat(extensions.get(1)).isEqualTo(b);
134 // different initial order
135 selector = newSelector(b, a);
136 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);
144 public void methodDependsUponCollection() {
145 Object a = new GeneratesSomething("foo");
146 Object b = new MethodDependentOf(Arrays.asList("foo"));
148 ModuleSensorExtensionDictionnary selector = newSelector(a, b);
149 List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
151 assertThat(extensions).hasSize(2);
152 assertThat(extensions.get(0)).isEqualTo(a);
153 assertThat(extensions.get(1)).isEqualTo(b);
155 // different initial order
156 selector = newSelector(b, a);
157 extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
159 assertThat(extensions).hasSize(2);
160 assertThat(extensions.get(0)).isEqualTo(a);
161 assertThat(extensions.get(1)).isEqualTo(b);
165 public void methodDependsUponArray() {
166 Object a = new GeneratesSomething("foo");
167 Object b = new MethodDependentOf(new String[] {"foo"});
169 ModuleSensorExtensionDictionnary selector = newSelector(a, b);
170 List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
172 assertThat(extensions).hasSize(2);
173 assertThat(extensions.get(0)).isEqualTo(a);
174 assertThat(extensions.get(1)).isEqualTo(b);
176 // different initial order
177 selector = newSelector(b, a);
178 extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
180 assertThat(extensions).hasSize(2);
181 assertThat(extensions.get(0)).isEqualTo(a);
182 assertThat(extensions.get(1)).isEqualTo(b);
186 public void useClassAnnotationsToSortExtensions() {
187 Object a = new ClassDependedUpon();
188 Object b = new ClassDependsUpon();
190 ModuleSensorExtensionDictionnary selector = newSelector(a, b);
191 List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
193 assertThat(extensions).hasSize(2);
194 assertThat(extensions.get(0)).isEqualTo(a);
195 assertThat(extensions.get(1)).isEqualTo(b);
197 // different initial order
198 selector = newSelector(b, a);
199 extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
201 assertThat(extensions).hasSize(2);
202 assertThat(extensions.get(0)).isEqualTo(a);
203 assertThat(extensions.get(1)).isEqualTo(b);
207 public void useClassAnnotationsOnInterfaces() {
208 Object a = new InterfaceDependedUpon() {
210 Object b = new InterfaceDependsUpon() {
213 ModuleSensorExtensionDictionnary selector = newSelector(a, b);
214 List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
216 assertThat(extensions).hasSize(2);
217 assertThat(extensions.get(0)).isEqualTo(a);
218 assertThat(extensions.get(1)).isEqualTo(b);
220 // different initial order
221 selector = newSelector(b, a);
222 extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
224 assertThat(extensions).hasSize(2);
225 assertThat(extensions.get(0)).isEqualTo(a);
226 assertThat(extensions.get(1)).isEqualTo(b);
230 public void inheritAnnotations() {
231 Object a = new SubClass("foo");
232 Object b = new MethodDependentOf("foo");
234 ModuleSensorExtensionDictionnary selector = newSelector(b, a);
235 List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
237 assertThat(extensions).hasSize(2);
238 assertThat(extensions.get(0)).isEqualTo(a);
239 assertThat(extensions.get(1)).isEqualTo(b);
241 // change initial order
242 selector = newSelector(a, b);
243 extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
245 assertThat(extensions).hasSize(2);
246 assertThat(extensions.get(0)).isEqualTo(a);
247 assertThat(extensions.get(1)).isEqualTo(b);
250 @Test(expected = IllegalStateException.class)
251 public void annotatedMethodsCanNotBePrivate() {
252 ModuleSensorExtensionDictionnary selector = newSelector();
253 Object wrong = new Object() {
255 private Object foo() {
259 selector.evaluateAnnotatedClasses(wrong, DependsUpon.class);
263 public void dependsUponPhaseForSensors() {
264 PreSensor pre = new PreSensor();
265 NormalSensor normal = new NormalSensor();
266 PostSensor post = new PostSensor();
268 ModuleSensorExtensionDictionnary selector = newSelector(normal, post, pre);
269 assertThat(selector.selectSensors(false)).extracting("wrappedSensor").containsExactly(pre, normal, post);
273 public void dependsUponInheritedPhase() {
274 PreSensorSubclass pre = new PreSensorSubclass();
275 NormalSensor normal = new NormalSensor();
276 PostSensorSubclass post = new PostSensorSubclass();
278 ModuleSensorExtensionDictionnary selector = newSelector(normal, post, pre);
279 List extensions = Lists.newArrayList(selector.select(Sensor.class, true, null));
281 assertThat(extensions).containsExactly(pre, normal, post);
285 public void selectSensors() {
286 FakeSensor nonGlobalSensor = new FakeSensor();
287 FakeGlobalSensor globalSensor = new FakeGlobalSensor();
288 ModuleSensorExtensionDictionnary selector = newSelector(nonGlobalSensor, globalSensor);
290 // verify non-global sensor
291 Collection<ModuleSensorWrapper> extensions = selector.selectSensors(false);
292 assertThat(extensions).hasSize(1);
293 assertThat(extensions).extracting("wrappedSensor").containsExactly(nonGlobalSensor);
295 // verify global sensor
296 extensions = selector.selectSensors(true);
297 assertThat(extensions).extracting("wrappedSensor").containsExactly(globalSensor);
304 class FakeSensor implements Sensor {
307 public void describe(SensorDescriptor descriptor) {
312 public void execute(SensorContext context) {
317 class FakeGlobalSensor implements Sensor {
320 public void describe(SensorDescriptor descriptor) {
325 public void execute(SensorContext context) {
331 class MethodDependentOf implements Marker {
334 MethodDependentOf(Object o) {
339 public Object dependsUponObject() {
346 class ClassDependsUpon implements Marker {
350 @DependedUpon("flag")
351 class ClassDependedUpon implements Marker {
356 interface InterfaceDependsUpon extends Marker {
360 @DependedUpon("flag")
361 interface InterfaceDependedUpon extends Marker {
365 class GeneratesSomething implements Marker {
368 GeneratesSomething(Object o) {
373 public Object generates() {
378 class SubClass extends GeneratesSomething implements Marker {
384 class NormalSensor implements Sensor {
387 public void describe(SensorDescriptor descriptor) {
391 public void execute(SensorContext context) {
396 @Phase(name = Phase.Name.PRE)
397 class PreSensor implements Sensor {
400 public void describe(SensorDescriptor descriptor) {
404 public void execute(SensorContext context) {
409 class PreSensorSubclass extends PreSensor {
413 @Phase(name = Phase.Name.POST)
414 class PostSensor implements Sensor {
417 public void describe(SensorDescriptor descriptor) {
421 public void execute(SensorContext context) {
426 class PostSensorSubclass extends PostSensor {