]> source.dussan.org Git - sonarqube.git/blob
95b472f58ac80fe7a9f774e936a56bc27c6347fb
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2023 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.telemetry;
21
22 import com.tngtech.java.junit.dataprovider.DataProvider;
23 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
24 import com.tngtech.java.junit.dataprovider.UseDataProvider;
25 import java.sql.DatabaseMetaData;
26 import java.sql.SQLException;
27 import java.util.List;
28 import java.util.Optional;
29 import java.util.Set;
30 import java.util.function.Consumer;
31 import java.util.function.Function;
32 import java.util.stream.Collectors;
33 import java.util.stream.IntStream;
34 import org.junit.Before;
35 import org.junit.Rule;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.sonar.api.config.Configuration;
39 import org.sonar.api.impl.utils.TestSystem2;
40 import org.sonar.core.platform.PlatformEditionProvider;
41 import org.sonar.core.platform.PluginInfo;
42 import org.sonar.core.platform.PluginRepository;
43 import org.sonar.db.DbSession;
44 import org.sonar.db.DbTester;
45 import org.sonar.db.alm.setting.AlmSettingDto;
46 import org.sonar.db.component.AnalysisPropertyDto;
47 import org.sonar.db.component.ComponentDto;
48 import org.sonar.db.component.SnapshotDto;
49 import org.sonar.db.metric.MetricDto;
50 import org.sonar.db.qualitygate.QualityGateDto;
51 import org.sonar.db.user.UserDbTester;
52 import org.sonar.db.user.UserDto;
53 import org.sonar.db.user.UserTelemetryDto;
54 import org.sonar.server.platform.DockerSupport;
55 import org.sonar.server.property.InternalProperties;
56 import org.sonar.server.property.MapInternalProperties;
57 import org.sonar.server.qualitygate.QualityGateCaycChecker;
58 import org.sonar.server.qualitygate.QualityGateFinder;
59 import org.sonar.updatecenter.common.Version;
60
61 import static java.util.Arrays.asList;
62 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
63 import static org.assertj.core.api.Assertions.assertThat;
64 import static org.assertj.core.api.Assertions.entry;
65 import static org.assertj.core.groups.Tuple.tuple;
66 import static org.mockito.Mockito.mock;
67 import static org.mockito.Mockito.spy;
68 import static org.mockito.Mockito.when;
69 import static org.sonar.api.measures.CoreMetrics.BUGS_KEY;
70 import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY;
71 import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST_KEY;
72 import static org.sonar.api.measures.CoreMetrics.LINES_KEY;
73 import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
74 import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY;
75 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_KEY;
76 import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT_KEY;
77 import static org.sonar.api.measures.CoreMetrics.VULNERABILITIES_KEY;
78 import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDCI;
79 import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDSCM;
80 import static org.sonar.core.platform.EditionProvider.Edition.COMMUNITY;
81 import static org.sonar.core.platform.EditionProvider.Edition.DEVELOPER;
82 import static org.sonar.core.platform.EditionProvider.Edition.ENTERPRISE;
83 import static org.sonar.db.component.BranchType.BRANCH;
84 import static org.sonar.server.metric.UnanalyzedLanguageMetrics.UNANALYZED_CPP_KEY;
85 import static org.sonar.server.metric.UnanalyzedLanguageMetrics.UNANALYZED_C_KEY;
86 import static org.sonar.server.telemetry.TelemetryDataLoaderImpl.SCIM_PROPERTY_ENABLED;
87
88 @RunWith(DataProviderRunner.class)
89 public class TelemetryDataLoaderImplTest {
90   private final static Long NOW = 100_000_000L;
91   private final TestSystem2 system2 = new TestSystem2().setNow(NOW);
92
93   @Rule
94   public DbTester db = DbTester.create(system2);
95
96   private final FakeServer server = new FakeServer();
97   private final PluginRepository pluginRepository = mock(PluginRepository.class);
98   private final Configuration configuration = mock(Configuration.class);
99   private final PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class);
100   private final DockerSupport dockerSupport = mock(DockerSupport.class);
101   private final QualityGateCaycChecker qualityGateCaycChecker = mock(QualityGateCaycChecker.class);
102   private final QualityGateFinder qualityGateFinder = new QualityGateFinder(db.getDbClient());
103   private final InternalProperties internalProperties = spy(new MapInternalProperties());
104
105   private final TelemetryDataLoader communityUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, editionProvider,
106       internalProperties, configuration, dockerSupport, qualityGateCaycChecker, qualityGateFinder);
107   private final TelemetryDataLoader commercialUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, editionProvider,
108       internalProperties, configuration, dockerSupport, qualityGateCaycChecker, qualityGateFinder);
109
110   private QualityGateDto builtInDefaultQualityGate;
111   private MetricDto bugsDto;
112   private MetricDto vulnerabilitiesDto;
113   private MetricDto securityHotspotsDto;
114   private MetricDto technicalDebtDto;
115   private MetricDto developmentCostDto;
116
117   @Before
118   public void setUpBuiltInQualityGate() {
119     String builtInQgName = "Sonar Way";
120     builtInDefaultQualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName(builtInQgName).setBuiltIn(true));
121     db.qualityGates().setDefaultQualityGate(builtInDefaultQualityGate);
122
123     bugsDto = db.measures().insertMetric(m -> m.setKey(BUGS_KEY));
124     vulnerabilitiesDto = db.measures().insertMetric(m -> m.setKey(VULNERABILITIES_KEY));
125     securityHotspotsDto = db.measures().insertMetric(m -> m.setKey(SECURITY_HOTSPOTS_KEY));
126     technicalDebtDto = db.measures().insertMetric(m -> m.setKey(TECHNICAL_DEBT_KEY));
127     developmentCostDto = db.measures().insertMetric(m -> m.setKey(DEVELOPMENT_COST_KEY));
128   }
129
130   @Test
131   public void send_telemetry_data() {
132     String serverId = "AU-TpxcB-iU5OvuD2FL7";
133     String version = "7.5.4";
134     Long analysisDate = 1L;
135     Long lastConnectionDate = 5L;
136
137     server.setId(serverId);
138     server.setVersion(version);
139     List<PluginInfo> plugins = asList(newPlugin("java", "4.12.0.11033"), newPlugin("scmgit", "1.2"), new PluginInfo("other"));
140     when(pluginRepository.getPluginInfos()).thenReturn(plugins);
141     when(editionProvider.get()).thenReturn(Optional.of(DEVELOPER));
142
143     List<UserDto> activeUsers = composeActiveUsers(3);
144
145     // update last connection
146     activeUsers.forEach(u -> db.users().updateLastConnectionDate(u, 5L));
147
148     UserDto inactiveUser = db.users().insertUser(u -> u.setActive(false).setExternalIdentityProvider("provider0"));
149
150     MetricDto lines = db.measures().insertMetric(m -> m.setKey(LINES_KEY));
151     MetricDto ncloc = db.measures().insertMetric(m -> m.setKey(NCLOC_KEY));
152     MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY));
153     MetricDto nclocDistrib = db.measures().insertMetric(m -> m.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY));
154
155     ComponentDto project1 = db.components().insertPrivateProject();
156     db.measures().insertLiveMeasure(project1, lines, m -> m.setValue(110d));
157     db.measures().insertLiveMeasure(project1, ncloc, m -> m.setValue(110d));
158     db.measures().insertLiveMeasure(project1, coverage, m -> m.setValue(80d));
159     db.measures().insertLiveMeasure(project1, nclocDistrib, m -> m.setValue(null).setData("java=70;js=30;kotlin=10"));
160     db.measures().insertLiveMeasure(project1, bugsDto, m -> m.setValue(1d));
161     db.measures().insertLiveMeasure(project1, vulnerabilitiesDto, m -> m.setValue(1d).setData((String) null));
162     db.measures().insertLiveMeasure(project1, securityHotspotsDto, m -> m.setValue(1d).setData((String) null));
163     db.measures().insertLiveMeasure(project1, developmentCostDto, m -> m.setData("50").setValue(null));
164     db.measures().insertLiveMeasure(project1, technicalDebtDto, m -> m.setValue(5d).setData((String) null));
165
166     ComponentDto project2 = db.components().insertPrivateProject();
167     db.measures().insertLiveMeasure(project2, lines, m -> m.setValue(200d));
168     db.measures().insertLiveMeasure(project2, ncloc, m -> m.setValue(200d));
169     db.measures().insertLiveMeasure(project2, coverage, m -> m.setValue(80d));
170     db.measures().insertLiveMeasure(project2, nclocDistrib, m -> m.setValue(null).setData("java=180;js=20"));
171
172     SnapshotDto project1Analysis = db.components().insertSnapshot(project1, t -> t.setLast(true).setBuildDate(analysisDate));
173     SnapshotDto project2Analysis = db.components().insertSnapshot(project2, t -> t.setLast(true).setBuildDate(analysisDate));
174     db.measures().insertMeasure(project1, project1Analysis, nclocDistrib, m -> m.setData("java=70;js=30;kotlin=10"));
175     db.measures().insertMeasure(project2, project2Analysis, nclocDistrib, m -> m.setData("java=180;js=20"));
176
177     insertAnalysisProperty(project1Analysis, "prop-uuid-1", SONAR_ANALYSIS_DETECTEDCI, "ci-1");
178     insertAnalysisProperty(project2Analysis, "prop-uuid-2", SONAR_ANALYSIS_DETECTEDCI, "ci-2");
179     insertAnalysisProperty(project1Analysis, "prop-uuid-3", SONAR_ANALYSIS_DETECTEDSCM, "scm-1");
180     insertAnalysisProperty(project2Analysis, "prop-uuid-4", SONAR_ANALYSIS_DETECTEDSCM, "scm-2");
181
182     // alm
183     db.almSettings().insertAzureAlmSetting();
184     db.almSettings().insertGitHubAlmSetting();
185     AlmSettingDto almSettingDto = db.almSettings().insertAzureAlmSetting(a -> a.setUrl("https://dev.azure.com"));
186     AlmSettingDto gitHubAlmSetting = db.almSettings().insertGitHubAlmSetting(a -> a.setUrl("https://api.github.com"));
187     db.almSettings().insertAzureProjectAlmSetting(almSettingDto, db.components().getProjectDto(project1));
188     db.almSettings().insertGitlabProjectAlmSetting(gitHubAlmSetting, db.components().getProjectDto(project2));
189
190     // quality gates
191     QualityGateDto qualityGate1 = db.qualityGates().insertQualityGate(qg -> qg.setName("QG1").setBuiltIn(true));
192     QualityGateDto qualityGate2 = db.qualityGates().insertQualityGate(qg -> qg.setName("QG2"));
193
194     // link one project to a non-default QG
195     db.qualityGates().associateProjectToQualityGate(db.components().getProjectDto(project1), qualityGate1);
196
197     TelemetryData data = communityUnderTest.load();
198     assertThat(data.getServerId()).isEqualTo(serverId);
199     assertThat(data.getVersion()).isEqualTo(version);
200     assertThat(data.getEdition()).contains(DEVELOPER);
201     assertThat(data.getDefaultQualityGate()).isEqualTo(builtInDefaultQualityGate.getUuid());
202     assertThat(data.getMessageSequenceNumber()).isOne();
203     assertDatabaseMetadata(data.getDatabase());
204     assertThat(data.getPlugins()).containsOnly(
205       entry("java", "4.12.0.11033"), entry("scmgit", "1.2"), entry("other", "undefined"));
206     assertThat(data.isInDocker()).isFalse();
207
208     assertThat(data.getUserTelemetries())
209       .extracting(UserTelemetryDto::getUuid, UserTelemetryDto::getLastConnectionDate, UserTelemetryDto::getLastSonarlintConnectionDate, UserTelemetryDto::isActive)
210       .containsExactlyInAnyOrder(
211         tuple(activeUsers.get(0).getUuid(), lastConnectionDate, activeUsers.get(0).getLastSonarlintConnectionDate(), true),
212         tuple(activeUsers.get(1).getUuid(), lastConnectionDate, activeUsers.get(1).getLastSonarlintConnectionDate(), true),
213         tuple(activeUsers.get(2).getUuid(), lastConnectionDate, activeUsers.get(2).getLastSonarlintConnectionDate(), true),
214         tuple(inactiveUser.getUuid(), null, inactiveUser.getLastSonarlintConnectionDate(), false));
215     assertThat(data.getProjects())
216       .extracting(TelemetryData.Project::projectUuid, TelemetryData.Project::language, TelemetryData.Project::loc, TelemetryData.Project::lastAnalysis)
217       .containsExactlyInAnyOrder(
218         tuple(project1.uuid(), "java", 70L, analysisDate),
219         tuple(project1.uuid(), "js", 30L, analysisDate),
220         tuple(project1.uuid(), "kotlin", 10L, analysisDate),
221         tuple(project2.uuid(), "java", 180L, analysisDate),
222         tuple(project2.uuid(), "js", 20L, analysisDate));
223     assertThat(data.getProjectStatistics())
224       .extracting(TelemetryData.ProjectStatistics::getBranchCount, TelemetryData.ProjectStatistics::getPullRequestCount, TelemetryData.ProjectStatistics::getQualityGate,
225         TelemetryData.ProjectStatistics::getScm, TelemetryData.ProjectStatistics::getCi, TelemetryData.ProjectStatistics::getDevopsPlatform,
226         TelemetryData.ProjectStatistics::getBugs, TelemetryData.ProjectStatistics::getVulnerabilities, TelemetryData.ProjectStatistics::getSecurityHotspots,
227         TelemetryData.ProjectStatistics::getDevelopmentCost, TelemetryData.ProjectStatistics::getTechnicalDebt)
228       .containsExactlyInAnyOrder(
229         tuple(1L, 0L, qualityGate1.getUuid(), "scm-1", "ci-1", "azure_devops_cloud", Optional.of(1L), Optional.of(1L), Optional.of(1L), Optional.of(50.0), Optional.of(5.0)),
230         tuple(1L, 0L, builtInDefaultQualityGate.getUuid(), "scm-2", "ci-2", "github_cloud", Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()));
231     assertThat(data.getQualityGates())
232       .extracting(TelemetryData.QualityGate::uuid, TelemetryData.QualityGate::isCaycCompliant)
233       .containsExactlyInAnyOrder(
234         tuple(builtInDefaultQualityGate.getUuid(), false),
235         tuple(qualityGate1.getUuid(), false),
236         tuple(qualityGate2.getUuid(), false)
237       );
238   }
239
240   private List<UserDto> composeActiveUsers(int count) {
241     UserDbTester userDbTester = db.users();
242     Function<Integer, Consumer<UserDto>> userConfigurator = index -> user -> user.setExternalIdentityProvider("provider" + index).setLastSonarlintConnectionDate(index * 2L);
243
244     return IntStream
245       .rangeClosed(1, count)
246       .mapToObj(userConfigurator::apply)
247       .map(userDbTester::insertUser)
248       .collect(Collectors.toList());
249   }
250
251   private void assertDatabaseMetadata(TelemetryData.Database database) {
252     try (DbSession dbSession = db.getDbClient().openSession(false)) {
253       DatabaseMetaData metadata = dbSession.getConnection().getMetaData();
254       assertThat(database.name()).isEqualTo("H2");
255       assertThat(database.version()).isEqualTo(metadata.getDatabaseProductVersion());
256     } catch (SQLException e) {
257       throw new RuntimeException(e);
258     }
259   }
260
261   @Test
262   public void take_largest_branch_snapshot_project_data() {
263     server.setId("AU-TpxcB-iU5OvuD2FL7").setVersion("7.5.4");
264
265     MetricDto lines = db.measures().insertMetric(m -> m.setKey(LINES_KEY));
266     MetricDto ncloc = db.measures().insertMetric(m -> m.setKey(NCLOC_KEY));
267     MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY));
268     MetricDto nclocDistrib = db.measures().insertMetric(m -> m.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY));
269
270     ComponentDto project = db.components().insertPublicProject();
271     db.measures().insertLiveMeasure(project, lines, m -> m.setValue(110d));
272     db.measures().insertLiveMeasure(project, ncloc, m -> m.setValue(110d));
273     db.measures().insertLiveMeasure(project, coverage, m -> m.setValue(80d));
274     db.measures().insertLiveMeasure(project, nclocDistrib, m -> m.setValue(null).setData("java=70;js=30;kotlin=10"));
275
276     ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
277     db.measures().insertLiveMeasure(branch, lines, m -> m.setValue(180d));
278     db.measures().insertLiveMeasure(branch, ncloc, m -> m.setValue(180d));
279     db.measures().insertLiveMeasure(branch, coverage, m -> m.setValue(80d));
280     db.measures().insertLiveMeasure(branch, nclocDistrib, m -> m.setValue(null).setData("java=100;js=50;kotlin=30"));
281
282     SnapshotDto project1Analysis = db.components().insertSnapshot(project, t -> t.setLast(true));
283     SnapshotDto project2Analysis = db.components().insertSnapshot(branch, t -> t.setLast(true));
284     db.measures().insertMeasure(project, project1Analysis, nclocDistrib, m -> m.setData("java=70;js=30;kotlin=10"));
285     db.measures().insertMeasure(branch, project2Analysis, nclocDistrib, m -> m.setData("java=100;js=50;kotlin=30"));
286
287     TelemetryData data = communityUnderTest.load();
288
289     assertThat(data.getProjects()).extracting(TelemetryData.Project::projectUuid, TelemetryData.Project::language, TelemetryData.Project::loc)
290       .containsExactlyInAnyOrder(
291         tuple(project.uuid(), "java", 100L),
292         tuple(project.uuid(), "js", 50L),
293         tuple(project.uuid(), "kotlin", 30L));
294     assertThat(data.getProjectStatistics())
295       .extracting(TelemetryData.ProjectStatistics::getBranchCount, TelemetryData.ProjectStatistics::getPullRequestCount,
296         TelemetryData.ProjectStatistics::getScm, TelemetryData.ProjectStatistics::getCi)
297       .containsExactlyInAnyOrder(
298         tuple(2L, 0L, "undetected", "undetected"));
299   }
300
301   @Test
302   public void data_contains_weekly_count_sonarlint_users() {
303     db.users().insertUser(c -> c.setLastSonarlintConnectionDate(NOW - 100_000L));
304     db.users().insertUser(c -> c.setLastSonarlintConnectionDate(NOW));
305     // these don't count
306     db.users().insertUser(c -> c.setLastSonarlintConnectionDate(NOW - 1_000_000_000L));
307     db.users().insertUser();
308
309     TelemetryData data = communityUnderTest.load();
310     assertThat(data.getUserTelemetries())
311       .hasSize(4);
312   }
313
314   @Test
315   public void send_server_id_and_version() {
316     String id = randomAlphanumeric(40);
317     String version = randomAlphanumeric(10);
318     server.setId(id);
319     server.setVersion(version);
320
321     TelemetryData data = communityUnderTest.load();
322     assertThat(data.getServerId()).isEqualTo(id);
323     assertThat(data.getVersion()).isEqualTo(version);
324
325     data = commercialUnderTest.load();
326     assertThat(data.getServerId()).isEqualTo(id);
327     assertThat(data.getVersion()).isEqualTo(version);
328   }
329
330   @Test
331   public void send_server_installation_date_and_installation_version() {
332     String installationVersion = "7.9.BEST.LTS.EVER";
333     Long installationDate = 1546300800000L; // 2019/01/01
334     internalProperties.write(InternalProperties.INSTALLATION_DATE, String.valueOf(installationDate));
335     internalProperties.write(InternalProperties.INSTALLATION_VERSION, installationVersion);
336
337     TelemetryData data = communityUnderTest.load();
338
339     assertThat(data.getInstallationDate()).isEqualTo(installationDate);
340     assertThat(data.getInstallationVersion()).isEqualTo(installationVersion);
341   }
342
343   @Test
344   public void send_correct_sequence_number() {
345     internalProperties.write(TelemetryDaemon.I_PROP_MESSAGE_SEQUENCE, "10");
346     TelemetryData data = communityUnderTest.load();
347     assertThat(data.getMessageSequenceNumber()).isEqualTo(11L);
348   }
349
350   @Test
351   public void do_not_send_server_installation_details_if_missing_property() {
352     TelemetryData data = communityUnderTest.load();
353     assertThat(data.getInstallationDate()).isNull();
354     assertThat(data.getInstallationVersion()).isNull();
355
356     data = commercialUnderTest.load();
357     assertThat(data.getInstallationDate()).isNull();
358     assertThat(data.getInstallationVersion()).isNull();
359   }
360
361   @Test
362   public void send_unanalyzed_languages_flags_when_edition_is_community() {
363     when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY));
364     MetricDto unanalyzedC = db.measures().insertMetric(m -> m.setKey(UNANALYZED_C_KEY));
365     MetricDto unanalyzedCpp = db.measures().insertMetric(m -> m.setKey(UNANALYZED_CPP_KEY));
366     ComponentDto project1 = db.components().insertPublicProject();
367     ComponentDto project2 = db.components().insertPublicProject();
368     db.measures().insertLiveMeasure(project1, unanalyzedC);
369     db.measures().insertLiveMeasure(project2, unanalyzedC);
370     db.measures().insertLiveMeasure(project2, unanalyzedCpp);
371
372     TelemetryData data = communityUnderTest.load();
373
374     assertThat(data.hasUnanalyzedC().get()).isTrue();
375     assertThat(data.hasUnanalyzedCpp().get()).isTrue();
376   }
377
378   @Test
379   public void do_not_send_unanalyzed_languages_flags_when_edition_is_not_community() {
380     when(editionProvider.get()).thenReturn(Optional.of(DEVELOPER));
381     MetricDto unanalyzedC = db.measures().insertMetric(m -> m.setKey(UNANALYZED_C_KEY));
382     MetricDto unanalyzedCpp = db.measures().insertMetric(m -> m.setKey(UNANALYZED_CPP_KEY));
383     ComponentDto project1 = db.components().insertPublicProject();
384     ComponentDto project2 = db.components().insertPublicProject();
385     db.measures().insertLiveMeasure(project1, unanalyzedC);
386     db.measures().insertLiveMeasure(project2, unanalyzedCpp);
387
388     TelemetryData data = communityUnderTest.load();
389
390     assertThat(data.hasUnanalyzedC()).isEmpty();
391     assertThat(data.hasUnanalyzedCpp()).isEmpty();
392   }
393
394   @Test
395   public void unanalyzed_languages_flags_are_set_to_false_when_no_unanalyzed_languages_and_edition_is_community() {
396     when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY));
397
398     TelemetryData data = communityUnderTest.load();
399
400     assertThat(data.hasUnanalyzedC().get()).isFalse();
401     assertThat(data.hasUnanalyzedCpp().get()).isFalse();
402   }
403
404   @Test
405   public void populate_security_custom_config_for_languages_on_enterprise() {
406     when(editionProvider.get()).thenReturn(Optional.of(ENTERPRISE));
407
408     when(configuration.get("sonar.security.config.javasecurity")).thenReturn(Optional.of("{}"));
409     when(configuration.get("sonar.security.config.phpsecurity")).thenReturn(Optional.of("{}"));
410     when(configuration.get("sonar.security.config.pythonsecurity")).thenReturn(Optional.of("{}"));
411     when(configuration.get("sonar.security.config.roslyn.sonaranalyzer.security.cs")).thenReturn(Optional.of("{}"));
412
413     TelemetryData data = commercialUnderTest.load();
414
415     assertThat(data.getCustomSecurityConfigs())
416       .containsExactlyInAnyOrder("java", "php", "python", "csharp");
417   }
418
419   @Test
420   public void skip_security_custom_config_on_community() {
421     when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY));
422
423     TelemetryData data = communityUnderTest.load();
424
425     assertThat(data.getCustomSecurityConfigs()).isEmpty();
426   }
427
428   @Test
429   public void undetected_alm_ci_slm_data() {
430     server.setId("AU-TpxcB-iU5OvuD2FL7").setVersion("7.5.4");
431     db.components().insertPublicProject();
432     TelemetryData data = communityUnderTest.load();
433     assertThat(data.getProjectStatistics())
434       .extracting(TelemetryData.ProjectStatistics::getDevopsPlatform, TelemetryData.ProjectStatistics::getScm, TelemetryData.ProjectStatistics::getCi)
435       .containsExactlyInAnyOrder(tuple("undetected", "undetected", "undetected"));
436   }
437
438   @Test
439   @UseDataProvider("getScimFeatureStatues")
440   public void detect_scim_feature_status(boolean isEnabled) {
441     db.components().insertPublicProject();
442     when(configuration.getBoolean(SCIM_PROPERTY_ENABLED)).thenReturn(Optional.of(isEnabled));
443
444     TelemetryData data = communityUnderTest.load();
445
446     assertThat(data.isScimEnabled()).isEqualTo(isEnabled);
447   }
448
449   @Test
450   public void default_quality_gate_sent_with_project() {
451     db.components().insertPublicProject();
452     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName("anything").setBuiltIn(true));
453     db.qualityGates().setDefaultQualityGate(qualityGate);
454     TelemetryData data = communityUnderTest.load();
455     assertThat(data.getProjectStatistics())
456       .extracting(TelemetryData.ProjectStatistics::getQualityGate)
457       .containsOnly(qualityGate.getUuid());
458   }
459
460   private PluginInfo newPlugin(String key, String version) {
461     return new PluginInfo(key)
462       .setVersion(Version.create(version));
463   }
464
465   private void insertAnalysisProperty(SnapshotDto snapshotDto, String uuid, String key, String value) {
466     db.getDbClient().analysisPropertiesDao().insert(db.getSession(), new AnalysisPropertyDto()
467       .setUuid(uuid)
468       .setAnalysisUuid(snapshotDto.getUuid())
469       .setKey(key)
470       .setValue(value)
471       .setCreatedAt(1L));
472   }
473
474   @DataProvider
475   public static Set<Boolean> getScimFeatureStatues() {
476     return Set.of(true, false);
477   }
478 }