]> source.dussan.org Git - sonarqube.git/blob
b32a7aeb3b08355723d11eda6b5d0199ba1470a4
[sonarqube.git] /
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.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.io.StringWriter;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.Random;
32 import java.util.Set;
33 import java.util.stream.Collectors;
34 import java.util.stream.IntStream;
35 import org.apache.commons.codec.digest.DigestUtils;
36 import org.jetbrains.annotations.NotNull;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.sonar.api.utils.text.JsonWriter;
40 import org.sonar.core.platform.EditionProvider;
41 import org.sonar.core.util.stream.MoreCollectors;
42 import org.sonar.db.user.UserTelemetryDto;
43
44 import static java.lang.String.format;
45 import static java.util.stream.Collectors.joining;
46 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
47 import static org.assertj.core.api.Assertions.assertThat;
48 import static org.sonar.server.telemetry.TelemetryDataJsonWriter.SCIM_PROPERTY;
49 import static org.sonar.test.JsonAssert.assertJson;
50
51 @RunWith(DataProviderRunner.class)
52 public class TelemetryDataJsonWriterTest {
53
54   private final Random random = new Random();
55
56   private final TelemetryDataJsonWriter underTest = new TelemetryDataJsonWriter();
57
58   @Test
59   public void write_server_id_and_version() {
60     TelemetryData data = telemetryBuilder().build();
61
62     String json = writeTelemetryData(data);
63
64     assertJson(json).isSimilarTo("{" +
65       "  \"id\": \"" + data.getServerId() + "\"," +
66       "  \"version\": \"" + data.getVersion() + "\"" +
67       "}");
68   }
69
70   @Test
71   public void does_not_write_edition_if_null() {
72     TelemetryData data = telemetryBuilder().build();
73
74     String json = writeTelemetryData(data);
75
76     assertThat(json).doesNotContain("edition");
77   }
78
79   @Test
80   @UseDataProvider("allEditions")
81   public void writes_edition_if_non_null(EditionProvider.Edition edition) {
82     TelemetryData data = telemetryBuilder()
83       .setEdition(edition)
84       .build();
85
86     String json = writeTelemetryData(data);
87
88     assertJson(json).isSimilarTo("{" +
89       "  \"edition\": \"" + edition.name().toLowerCase(Locale.ENGLISH) + "\"" +
90       "}");
91   }
92
93   @Test
94   public void does_not_write_license_type_if_null() {
95     TelemetryData data = telemetryBuilder().build();
96
97     String json = writeTelemetryData(data);
98
99     assertThat(json).doesNotContain("licenseType");
100   }
101
102   @Test
103   public void writes_licenseType_if_non_null() {
104     String expected = randomAlphabetic(12);
105     TelemetryData data = telemetryBuilder()
106       .setLicenseType(expected)
107       .build();
108
109     String json = writeTelemetryData(data);
110
111     assertJson(json).isSimilarTo("{" +
112       "  \"licenseType\": \"" + expected + "\"" +
113       "}");
114   }
115
116   @Test
117   public void writes_database() {
118     String name = randomAlphabetic(12);
119     String version = randomAlphabetic(10);
120     TelemetryData data = telemetryBuilder()
121       .setDatabase(new TelemetryData.Database(name, version))
122       .build();
123
124     String json = writeTelemetryData(data);
125
126     assertJson(json).isSimilarTo("{" +
127       "  \"database\": {" +
128       "    \"name\": \"" + name + "\"," +
129       "    \"version\": \"" + version + "\"" +
130       "  }" +
131       "}");
132   }
133
134   @Test
135   public void writes_no_plugins() {
136     TelemetryData data = telemetryBuilder()
137       .setPlugins(Collections.emptyMap())
138       .build();
139
140     String json = writeTelemetryData(data);
141
142     assertJson(json).isSimilarTo("{" +
143       "  \"plugins\": []" +
144       "}");
145   }
146
147   @Test
148   public void writes_all_plugins() {
149     Map<String, String> plugins = IntStream.range(0, 1 + random.nextInt(10))
150       .boxed()
151       .collect(MoreCollectors.uniqueIndex(i -> "P" + i, i -> "V" + i));
152     TelemetryData data = telemetryBuilder()
153       .setPlugins(plugins)
154       .build();
155
156     String json = writeTelemetryData(data);
157
158     assertJson(json).isSimilarTo("{" +
159       "  \"plugins\": " +
160       "[" +
161       plugins.entrySet().stream().map(e -> "{\"name\":\"" + e.getKey() + "\",\"version\":\"" + e.getValue() + "\"}").collect(joining(",")) +
162       "]" +
163       "}");
164   }
165
166   @Test
167   public void does_not_write_installation_date_if_null() {
168     TelemetryData data = telemetryBuilder()
169       .setInstallationDate(null)
170       .build();
171
172     String json = writeTelemetryData(data);
173
174     assertThat(json).doesNotContain("installationDate");
175   }
176
177   @Test
178   public void write_installation_date_in_utc_format() {
179     TelemetryData data = telemetryBuilder()
180       .setInstallationDate(1_000L)
181       .build();
182
183     String json = writeTelemetryData(data);
184
185     assertJson(json).isSimilarTo("{" +
186       "  \"installationDate\":\"1970-01-01T00:00:01+0000\"," +
187       "}");
188   }
189
190   @Test
191   public void does_not_write_installation_version_if_null() {
192     TelemetryData data = telemetryBuilder()
193       .setInstallationVersion(null)
194       .build();
195
196     String json = writeTelemetryData(data);
197
198     assertThat(json).doesNotContain("installationVersion");
199   }
200
201   @Test
202   public void write_installation_version() {
203     String installationVersion = randomAlphabetic(5);
204     TelemetryData data = telemetryBuilder()
205       .setInstallationVersion(installationVersion)
206       .build();
207
208     String json = writeTelemetryData(data);
209
210     assertJson(json).isSimilarTo("{" +
211       "  \"installationVersion\":\"" + installationVersion + "\"" +
212       "}");
213   }
214
215   @Test
216   @UseDataProvider("getFeatureFlagEnabledStates")
217   public void write_docker_flag(boolean isInDocker) {
218     TelemetryData data = telemetryBuilder()
219       .setInDocker(isInDocker)
220       .build();
221
222     String json = writeTelemetryData(data);
223
224     assertJson(json).isSimilarTo("{" +
225       "  \"docker\":" + isInDocker +
226       "}");
227   }
228
229   @Test
230   @UseDataProvider("getFeatureFlagEnabledStates")
231   public void write_scim_feature_flag(boolean isScimEnabled) {
232     TelemetryData data = telemetryBuilder()
233       .setIsScimEnabled(isScimEnabled)
234       .build();
235
236     String json = writeTelemetryData(data);
237
238     assertJson(json).isSimilarTo("{" + format("  \"%s\":", SCIM_PROPERTY) + isScimEnabled + "}");
239   }
240
241   @Test
242   public void writes_security_custom_config() {
243     TelemetryData data = telemetryBuilder()
244       .setCustomSecurityConfigs(Set.of("php", "java"))
245       .build();
246
247     String json = writeTelemetryData(data);
248
249     assertJson(json).isSimilarTo("{" +
250       "  \"customSecurityConfig\": [\"php\", \"java\"]" +
251       "}");
252   }
253
254   @Test
255   public void writes_all_users_with_anonymous_md5_uuids() {
256     TelemetryData data = telemetryBuilder()
257       .setUsers(attachUsers())
258       .build();
259
260     String json = writeTelemetryData(data);
261
262     assertJson(json).isSimilarTo("{" +
263       "  \"users\": [" +
264       "    {" +
265       "      \"userUuid\":\"" + DigestUtils.sha3_224Hex("uuid-0") + "\"," +
266       "      \"lastActivity\":\"1970-01-01T00:00:00+0000\"," +
267       "      \"identityProvider\":\"gitlab\"," +
268       "      \"lastSonarlintActivity\":\"1970-01-01T00:00:00+0000\"," +
269       "      \"status\":\"active\"" +
270       "    }," +
271       "    {" +
272       "      \"userUuid\":\"" + DigestUtils.sha3_224Hex("uuid-1") + "\"," +
273       "      \"lastActivity\":\"1970-01-01T00:00:00+0000\"," +
274       "      \"identityProvider\":\"gitlab\"," +
275       "      \"lastSonarlintActivity\":\"1970-01-01T00:00:00+0000\"," +
276       "      \"status\":\"inactive\"" +
277       "    }," +
278       "    {" +
279       "      \"userUuid\":\"" + DigestUtils.sha3_224Hex("uuid-2") + "\"," +
280       "      \"lastActivity\":\"1970-01-01T00:00:00+0000\"," +
281       "      \"identityProvider\":\"gitlab\"," +
282       "      \"lastSonarlintActivity\":\"1970-01-01T00:00:00+0000\"," +
283       "      \"status\":\"active\"" +
284       "    }" +
285       "  ]" +
286       "}");
287   }
288
289   @Test
290   public void writes_all_projects() {
291     TelemetryData data = telemetryBuilder()
292       .setProjects(attachProjects())
293       .build();
294
295     String json = writeTelemetryData(data);
296
297     assertJson(json).isSimilarTo("{" +
298       "  \"projects\": [" +
299       "    {" +
300       "      \"projectUuid\": \"uuid-0\"," +
301       "      \"lastAnalysis\":\"1970-01-01T00:00:00+0000\"," +
302       "      \"language\": \"lang-0\"," +
303       "      \"loc\": 2" +
304       "    }," +
305       "    {" +
306       "      \"projectUuid\": \"uuid-1\"," +
307       "      \"lastAnalysis\":\"1970-01-01T00:00:00+0000\"," +
308       "      \"language\": \"lang-1\"," +
309       "      \"loc\": 4" +
310       "    }," +
311       "    {" +
312       "      \"projectUuid\": \"uuid-2\"," +
313       "      \"lastAnalysis\":\"1970-01-01T00:00:00+0000\"," +
314       "      \"language\": \"lang-2\"," +
315       "      \"loc\": 6" +
316       "    }" +
317       "  ]" +
318       "}");
319   }
320
321   @Test
322   public void writes_all_projects_stats_with_analyzed_languages() {
323     TelemetryData data = telemetryBuilder()
324       .setProjectStatistics(attachProjectStats(true))
325       .build();
326
327     String json = writeTelemetryData(data);
328
329     assertJson(json).isSimilarTo("{" +
330       "  \"projects-general-stats\": [" +
331       "    {" +
332       "      \"projectUuid\": \"uuid-0\"," +
333       "      \"branchCount\": 2," +
334       "      \"pullRequestCount\": 2," +
335       "      \"scm\": \"scm-0\"," +
336       "      \"ci\": \"ci-0\"," +
337       "      \"devopsPlatform\": \"devops-0\"," +
338       "      \"hasUnanalyzedC\": true," +
339       "      \"hasUnanalyzedCpp\": false" +
340       "    }," +
341       "    {" +
342       "      \"projectUuid\": \"uuid-1\"," +
343       "      \"branchCount\": 4," +
344       "      \"pullRequestCount\": 4," +
345       "      \"scm\": \"scm-1\"," +
346       "      \"ci\": \"ci-1\"," +
347       "      \"devopsPlatform\": \"devops-1\"," +
348       "      \"hasUnanalyzedC\": false," +
349       "      \"hasUnanalyzedCpp\": true" +
350       "    }," +
351       "    {" +
352       "      \"projectUuid\": \"uuid-2\"," +
353       "      \"branchCount\": 6," +
354       "      \"pullRequestCount\": 6," +
355       "      \"scm\": \"scm-2\"," +
356       "      \"ci\": \"ci-2\"," +
357       "      \"devopsPlatform\": \"devops-2\"," +
358       "      \"hasUnanalyzedC\": true," +
359       "      \"hasUnanalyzedCpp\": false" +
360       "    }" +
361       "  ]" +
362       "}");
363   }
364
365   @Test
366   public void writes_all_projects_stats_with_unanalyzed_languages() {
367     TelemetryData data = telemetryBuilder()
368       .setProjectStatistics(attachProjectStats(false))
369       .build();
370
371     String json = writeTelemetryData(data);
372     assertThat(json).doesNotContain("hasUnanalyzedC", "hasUnanalyzedCpp");
373   }
374
375   private static TelemetryData.Builder telemetryBuilder() {
376     return TelemetryData.builder()
377       .setServerId("foo")
378       .setVersion("bar")
379       .setPlugins(Collections.emptyMap())
380       .setDatabase(new TelemetryData.Database("H2", "11"));
381   }
382
383   @NotNull
384   private static List<UserTelemetryDto> attachUsers() {
385     return IntStream.range(0, 3)
386       .mapToObj(
387         i -> new UserTelemetryDto().setUuid("uuid-" + i).setActive(i % 2 == 0).setLastConnectionDate(1L).setLastSonarlintConnectionDate(2L).setExternalIdentityProvider("gitlab"))
388       .collect(Collectors.toList());
389   }
390
391   private static List<TelemetryData.Project> attachProjects() {
392     return IntStream.range(0, 3).mapToObj(i -> new TelemetryData.Project("uuid-" + i, 1L, "lang-" + i, (i + 1L) * 2L)).collect(Collectors.toList());
393   }
394
395   private List<TelemetryData.ProjectStatistics> attachProjectStats(boolean hasUnanalyzedLanguages) {
396     return IntStream.range(0, 3).mapToObj(i -> new TelemetryData.ProjectStatistics("uuid-" + i, (i + 1L) * 2L, (i + 1L) * 2L, hasUnanalyzedLanguages ? i % 2 == 0 : null, hasUnanalyzedLanguages ? i % 2 != 0 : null, "scm-" + i, "ci-" + i, "devops-" + i))
397       .collect(Collectors.toList());
398   }
399
400   @DataProvider
401   public static Object[][] allEditions() {
402     return Arrays.stream(EditionProvider.Edition.values())
403       .map(t -> new Object[] {t})
404       .toArray(Object[][]::new);
405   }
406
407   private String writeTelemetryData(TelemetryData data) {
408     StringWriter jsonString = new StringWriter();
409     try (JsonWriter json = JsonWriter.of(jsonString)) {
410       underTest.writeTelemetryData(json, data);
411     }
412     return jsonString.toString();
413   }
414
415   @DataProvider
416   public static Set<Boolean> getFeatureFlagEnabledStates() {
417     return Set.of(true, false);
418   }
419 }