diff options
author | Lukasz Jarocki <lukasz.jarocki@sonarsource.com> | 2022-07-20 14:08:09 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-07-21 20:03:05 +0000 |
commit | b65c752c9a177e2401037dbc822a4362470be650 (patch) | |
tree | a2af58a9399a0e9e8a9311b1219e6dc4168fc519 | |
parent | 0a7d6f7245e753feb25bceae733fd659591b8f81 (diff) | |
download | sonarqube-b65c752c9a177e2401037dbc822a4362470be650.tar.gz sonarqube-b65c752c9a177e2401037dbc822a4362470be650.zip |
SONAR-16610 added example plugin to test education topics in SonarQube
20 files changed, 972 insertions, 0 deletions
diff --git a/plugins/sonar-education-plugin/build.gradle b/plugins/sonar-education-plugin/build.gradle new file mode 100644 index 00000000000..71bad6499f1 --- /dev/null +++ b/plugins/sonar-education-plugin/build.gradle @@ -0,0 +1,43 @@ +configurations { + testImplementation.extendsFrom(compileOnly) +} + +dependencies { + compileOnly 'org.sonarsource.api.plugin:sonar-plugin-api' + + testCompile 'junit:junit' + testCompile 'org.assertj:assertj-core' + testCompile 'org.mockito:mockito-core' + testCompile project(':sonar-plugin-api-impl') +} + +jar { + manifest { + attributes( + 'Plugin-Key': 'education', + 'Plugin-Version': project.version, + 'Plugin-Class': 'org.sonar.education.EducationPlugin', + 'Plugin-ChildFirstClassLoader': 'false', + 'Sonar-Version': project.version, + 'SonarLint-Supported': 'true', + 'Plugin-Name': 'Education' + ) + } + into('META-INF/lib') { + from configurations.compileClasspath + } +} + +artifactoryPublish.skip = false + +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + if (release) { + artifact sourcesJar + artifact javadocJar + } + } + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationBuiltInQualityProfileDefinition.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationBuiltInQualityProfileDefinition.java new file mode 100644 index 00000000000..14a36f8c524 --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationBuiltInQualityProfileDefinition.java @@ -0,0 +1,42 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education; + +import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; + +import static org.sonar.education.EducationRulesDefinition.EDUCATION_KEY; +import static org.sonar.education.EducationRulesDefinition.EDUCATION_RULE_REPOSITORY_KEY; +import static org.sonar.education.sensors.EducationPrinciplesSensor.EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY; +import static org.sonar.education.sensors.EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY; +import static org.sonar.education.sensors.EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY; +import static org.sonar.education.sensors.EducationWithSingleContextSensor.EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY; + +public class EducationBuiltInQualityProfileDefinition implements BuiltInQualityProfilesDefinition { + @Override + public void define(Context context) { + NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile("Built in QP for Education", EDUCATION_KEY); + profile.setDefault(true); + profile.activateRule(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY); + profile.activateRule(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY); + profile.activateRule(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_WITH_CONTEXTS_RULE_KEY); + profile.activateRule(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY); + profile.done(); + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationLanguage.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationLanguage.java new file mode 100644 index 00000000000..5487da02d3d --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationLanguage.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education; + +import org.sonar.api.resources.Language; + +public class EducationLanguage implements Language { + + @Override + public String getKey() { + return EducationRulesDefinition.EDUCATION_KEY; + } + + @Override + public String getName() { + return "Education"; + } + + @Override + public String[] getFileSuffixes() { + return new String[]{".edu"}; + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationPlugin.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationPlugin.java new file mode 100644 index 00000000000..6cae2713a50 --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationPlugin.java @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education; + +import org.sonar.education.sensors.EducationWithContextsSensor; +import org.sonar.education.sensors.EducationWithDetectedContextSensor; +import org.sonar.education.sensors.EducationPrinciplesSensor; +import org.sonar.education.sensors.EducationWithSingleContextSensor; +import org.sonar.api.Plugin; + +public class EducationPlugin implements Plugin { + @Override + public void define(Context context) { + context.addExtensions( + EducationRulesDefinition.class, + EducationLanguage.class, + EducationWithContextsSensor.class, + EducationWithDetectedContextSensor.class, + EducationPrinciplesSensor.class, + EducationWithSingleContextSensor.class, + EducationBuiltInQualityProfileDefinition.class); + + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationRulesDefinition.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationRulesDefinition.java new file mode 100644 index 00000000000..79887611754 --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/EducationRulesDefinition.java @@ -0,0 +1,149 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education; + +import org.sonar.api.server.rule.RuleDescriptionSection; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.education.sensors.EducationPrinciplesSensor; +import org.sonar.education.sensors.EducationWithContextsSensor; +import org.sonar.education.sensors.EducationWithDetectedContextSensor; + +import static org.sonar.education.sensors.EducationWithSingleContextSensor.EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY; +import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ASSESS_THE_PROBLEM_SECTION_KEY; +import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.HOW_TO_FIX_SECTION_KEY; +import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.INTRODUCTION_SECTION_KEY; +import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.RESOURCES_SECTION_KEY; +import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ROOT_CAUSE_SECTION_KEY; + +public class EducationRulesDefinition implements RulesDefinition { + + public static final String EDUCATION_RULE_REPOSITORY_KEY = "edu"; + public static final String EDUCATION_KEY = "education"; + + private static final String IGNORED_FAKE_SECTION = "fake_section_to_be_ignored"; + + public static final String[] CONTEXTS = {"spring", "hibernate", "apache-commons", "vaadin", "mybatis"}; + + private static final String HTML_LOREM_IPSUM = "<a href=\"https://google.com\">Lorem</a> ipsum dolor sit amet, consectetur adipiscing " + + "elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " + + "laboris nisi ut aliquip ex ea commodo consequat.<br />Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu " + + "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + + @Override + public void define(Context context) { + NewRepository repo = context.createRepository(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_KEY); + + createRuleWithDescriptionSectionsAndEducationPrinciples(repo); + createRuleWithDescriptionSectionsAndSingleContext(repo); + createRuleWithDescriptionSectionsAndMultipleContexts(repo); + createRuleWithDescriptionSectionsAndMultipleContextsIncludingOneDetected(repo); + + repo.done(); + } + + private void createRuleWithDescriptionSectionsAndEducationPrinciples(NewRepository repo) { + String[] educationPrinciples = {"defense_in_depth", "least_trust_principle"}; + String ruleKey = EducationPrinciplesSensor.EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY; + NewRule ruleWithSingleContext = repo.createRule(ruleKey).setName("Rule with description sections and education principles") + .addTags(EDUCATION_KEY); + + ruleWithSingleContext + .setHtmlDescription(String.format("This rule contains description sections. To trigger an issue using this rule you need to " + + "scan any text file with a line containing %s key word. This rule also contains 2 education principles - %s and %s", + ruleKey, educationPrinciples[0], educationPrinciples[1])) + .addEducationPrincipleKeys(educationPrinciples); + + addNonContextualizedDescriptionSections(ruleWithSingleContext); + descriptionSection(HOW_TO_FIX_SECTION_KEY); + } + + private void createRuleWithDescriptionSectionsAndSingleContext(NewRepository repo) { + String ruleKey = EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY; + NewRule ruleWithSingleContext = repo.createRule(ruleKey).setName("Rule with description sections and single " + + "contexts for 'how to fix'") + .addTags(EDUCATION_KEY); + + ruleWithSingleContext + .setHtmlDescription(String.format("This rule contains description sections and single context for 'how to fix' section. To " + + "trigger an issue using this rule you need to scan any text file with a line containing %s key word.", ruleKey)); + + addNonContextualizedDescriptionSections(ruleWithSingleContext); + + ruleWithSingleContext.addDescriptionSection(descriptionHowToFixSectionWithContext(CONTEXTS[0])); + } + + private void createRuleWithDescriptionSectionsAndMultipleContexts(NewRepository repo) { + NewRule ruleWithMultipleContexts = repo.createRule(EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY) + .setName("Rule with description sections and multiple contexts for 'how to fix'") + .addTags(EDUCATION_KEY); + + ruleWithMultipleContexts + .setHtmlDescription(String.format("This rule contains description sections and multiple contexts for 'how to fix' section. To trigger " + + "an issue using this rule you need to scan any text file with a line containing %s keyword.", + EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY)); + + addNonContextualizedDescriptionSections(ruleWithMultipleContexts); + + for (String context : CONTEXTS) { + ruleWithMultipleContexts.addDescriptionSection(descriptionHowToFixSectionWithContext(context)); + } + } + + private void createRuleWithDescriptionSectionsAndMultipleContextsIncludingOneDetected(NewRepository repo) { + NewRule ruleWithMultipleContexts = repo.createRule(EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY) + .setName("Rule with description sections and multiple contexts (including one detected) for 'how to fix'") + .addTags(EDUCATION_KEY); + + ruleWithMultipleContexts + .setHtmlDescription(String.format("This rule contains description sections and multiple contexts (including one detected) for " + + "'how to fix' section. To trigger an issue using this rule you need to scan any text file with a line containing %s keyword.", + EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY)); + + addNonContextualizedDescriptionSections(ruleWithMultipleContexts); + + for (String context : CONTEXTS) { + ruleWithMultipleContexts.addDescriptionSection(descriptionHowToFixSectionWithContext(context)); + } + } + + private static void addNonContextualizedDescriptionSections(NewRule newRule) { + newRule.addDescriptionSection(descriptionSection(INTRODUCTION_SECTION_KEY)) + .addDescriptionSection(descriptionSection(ROOT_CAUSE_SECTION_KEY)) + .addDescriptionSection(descriptionSection(ASSESS_THE_PROBLEM_SECTION_KEY)) + .addDescriptionSection(descriptionSection(RESOURCES_SECTION_KEY)) + .addDescriptionSection(descriptionSection(IGNORED_FAKE_SECTION)); + } + + private static RuleDescriptionSection descriptionHowToFixSectionWithContext(String context) { + var ruleContext = new org.sonar.api.server.rule.Context(context, context); + return RuleDescriptionSection.builder() + .sectionKey(HOW_TO_FIX_SECTION_KEY) + .context(ruleContext) + .htmlContent(String.format("%s: %s", HOW_TO_FIX_SECTION_KEY, HTML_LOREM_IPSUM)) + .build(); + } + + private static RuleDescriptionSection descriptionSection(String sectionKey) { + return RuleDescriptionSection.builder() + .sectionKey(sectionKey) + .htmlContent(String.format("%s: %s", sectionKey, HTML_LOREM_IPSUM)) + .build(); + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationPrinciplesSensor.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationPrinciplesSensor.java new file mode 100644 index 00000000000..66a759fd8ad --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationPrinciplesSensor.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.rule.ActiveRules; + +public class EducationPrinciplesSensor extends EducationRuleSensor { + + public static final String EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY = "EDUCATION"; + + public EducationPrinciplesSensor(FileSystem fs, ActiveRules activeRules) { + super(fs, activeRules, EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY); + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationRuleSensor.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationRuleSensor.java new file mode 100644 index 00000000000..72be37bb1f8 --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationRuleSensor.java @@ -0,0 +1,97 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorDescriptor; +import org.sonar.api.batch.sensor.issue.NewIssue; +import org.sonar.api.rule.RuleKey; + +import static org.sonar.education.EducationRulesDefinition.EDUCATION_KEY; +import static org.sonar.education.EducationRulesDefinition.EDUCATION_RULE_REPOSITORY_KEY; + +public abstract class EducationRuleSensor implements Sensor { + + private final FileSystem fs; + private final ActiveRules activeRules; + private final String ruleKeyName; + private final String tag; + + EducationRuleSensor(FileSystem fs, ActiveRules activeRules, String ruleKey) { + this.fs = fs; + this.activeRules = activeRules; + this.ruleKeyName = ruleKey; + this.tag = ruleKey; + } + + @Override + public void describe(SensorDescriptor descriptor) { + descriptor + .name("Education sensor for " + tag) + .createIssuesForRuleRepository(EDUCATION_RULE_REPOSITORY_KEY); + } + + @Override + public void execute(SensorContext context) { + RuleKey ruleKey = RuleKey.of(EDUCATION_RULE_REPOSITORY_KEY, ruleKeyName); + if (activeRules.find(ruleKey) == null) { + return; + } + for (InputFile inputFile : fs.inputFiles(fs.predicates().hasLanguage(EDUCATION_KEY))) { + processFile(inputFile, context, ruleKey); + } + } + + protected String getDetectedContext() { + return null; + } + + protected void processFile(InputFile inputFile, SensorContext context, RuleKey ruleKey) { + try { + int[] lineCounter = {1}; + try (InputStreamReader isr = new InputStreamReader(inputFile.inputStream(), inputFile.charset()); + BufferedReader reader = new BufferedReader(isr)) { + reader.lines().forEachOrdered(lineStr -> { + int startIndex = -1; + while ((startIndex = lineStr.indexOf(tag, startIndex + 1)) != -1) { + NewIssue newIssue = context.newIssue(); + newIssue + .forRule(ruleKey) + .at(newIssue.newLocation() + .on(inputFile) + .at(inputFile.newRange(lineCounter[0], startIndex, lineCounter[0], startIndex + tag.length()))) + .setRuleDescriptionContextKey(getDetectedContext()) + .save(); + } + lineCounter[0]++; + }); + } + } catch (IOException e) { + throw new IllegalStateException("Fail to process " + inputFile, e); + } + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithContextsSensor.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithContextsSensor.java new file mode 100644 index 00000000000..00e9365d5c1 --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithContextsSensor.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.rule.ActiveRules; + +public class EducationWithContextsSensor extends EducationRuleSensor { + + public static final String EDUCATION_WITH_CONTEXTS_RULE_KEY = "CONTEXTS"; + + public EducationWithContextsSensor(FileSystem fs, ActiveRules activeRules) { + super(fs, activeRules, EDUCATION_WITH_CONTEXTS_RULE_KEY); + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithDetectedContextSensor.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithDetectedContextSensor.java new file mode 100644 index 00000000000..1163dec0153 --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithDetectedContextSensor.java @@ -0,0 +1,39 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.rule.ActiveRules; + +import static org.sonar.education.EducationRulesDefinition.CONTEXTS; + +public class EducationWithDetectedContextSensor extends EducationRuleSensor { + + public static final String EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY = "DETECTED_CONTEXT"; + + public EducationWithDetectedContextSensor(FileSystem fs, ActiveRules activeRules) { + super(fs, activeRules, EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY); + } + + @Override + protected String getDetectedContext() { + return CONTEXTS[0]; + } +} diff --git a/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithSingleContextSensor.java b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithSingleContextSensor.java new file mode 100644 index 00000000000..45e2f76ab78 --- /dev/null +++ b/plugins/sonar-education-plugin/src/main/java/org/sonar/education/sensors/EducationWithSingleContextSensor.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.rule.ActiveRules; + +public class EducationWithSingleContextSensor extends EducationRuleSensor { + + public static final String EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY = "SINGLE_CONTEXT"; + + public EducationWithSingleContextSensor(FileSystem fs, ActiveRules activeRules) { + super(fs, activeRules, EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationBuiltInQualityProfileDefinitionTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationBuiltInQualityProfileDefinitionTest.java new file mode 100644 index 00000000000..abb44b76dfb --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationBuiltInQualityProfileDefinitionTest.java @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education; + +import org.junit.Test; +import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; + +import static org.assertj.core.api.Assertions.assertThat; + +public class EducationBuiltInQualityProfileDefinitionTest { + + private final EducationBuiltInQualityProfileDefinition underTest = new EducationBuiltInQualityProfileDefinition(); + + @Test + public void define_definesAtLeast4rules() { + BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context(); + + underTest.define(context); + + BuiltInQualityProfilesDefinition.BuiltInQualityProfile profile = context.profile("education", "Built in QP for Education"); + assertThat(profile.isDefault()).isTrue(); + assertThat(profile.rules()).hasSizeGreaterThanOrEqualTo(4); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationLanguageTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationLanguageTest.java new file mode 100644 index 00000000000..623c3358dda --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationLanguageTest.java @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class EducationLanguageTest { + + private final EducationLanguage underTest = new EducationLanguage(); + + @Test + public void getFileSuffixes_notEmpty() { + String[] fileSuffixes = underTest.getFileSuffixes(); + + assertThat(fileSuffixes).isNotEmpty(); + } + + @Test + public void getName_notEmpty() { + String name = underTest.getName(); + + assertThat(name).isNotEmpty(); + } + + @Test + public void getKey_notEmpty() { + String key = underTest.getKey(); + + assertThat(key).isNotEmpty(); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationPluginTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationPluginTest.java new file mode 100644 index 00000000000..f60199703e9 --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationPluginTest.java @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education; + +import org.junit.Test; +import org.sonar.api.Plugin; +import org.sonar.api.SonarEdition; +import org.sonar.api.SonarQubeSide; +import org.sonar.api.SonarRuntime; +import org.sonar.api.internal.PluginContextImpl; +import org.sonar.api.internal.SonarRuntimeImpl; +import org.sonar.api.utils.Version; + +import static org.assertj.core.api.Assertions.assertThat; + +public class EducationPluginTest { + + @Test + public void define_addSomeExtensionsForSonarQube() { + SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("9.5"), SonarQubeSide.SCANNER, SonarEdition.COMMUNITY); + Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build(); + EducationPlugin plugin = new EducationPlugin(); + + plugin.define(context); + + assertThat(context.getExtensions()).isNotEmpty(); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationRulesDefinitionTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationRulesDefinitionTest.java new file mode 100644 index 00000000000..233bba84fc1 --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/EducationRulesDefinitionTest.java @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education; + +import java.util.List; +import org.junit.Test; +import org.sonar.api.server.rule.RulesDefinition; + +import static org.assertj.core.api.Assertions.assertThat; + +public class EducationRulesDefinitionTest { + + @Test + public void define_addsRuleDefinitions() { + EducationRulesDefinition educationRulesDefinition = new EducationRulesDefinition(); + + RulesDefinition.Context context = new RulesDefinition.Context(); + + educationRulesDefinition.define(context); + + List<RulesDefinition.Repository> repositories = context.repositories(); + assertThat(repositories).hasSize(1); + + RulesDefinition.Repository repository = context.repositories().get(0); + List<RulesDefinition.Rule> rules = repository.rules(); + assertThat(rules).hasSizeGreaterThanOrEqualTo(4); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationPrinciplesSensorTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationPrinciplesSensorTest.java new file mode 100644 index 00000000000..8e9c9ef722c --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationPrinciplesSensorTest.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import java.io.IOException; +import org.junit.Test; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.internal.SensorContextTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.education.sensors.EducationPrinciplesSensor.EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY; + +public class EducationPrinciplesSensorTest extends EducationSensorTest { + + @Test + public void processFile_givenCorrectTagPassed_oneSecurityHotspotWithContextsIsRaised() throws IOException { + DefaultInputFile inputFile = newTestFile(EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY); + + DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); + fs.add(inputFile); + + SensorContextTester sensorContextTester = SensorContextTester.create(temp.newFolder().toPath()); + var sensor = new EducationPrinciplesSensor(fs, activeRules); + + sensor.execute(sensorContextTester); + + assertThat(sensorContextTester.allIssues()).hasSize(1); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationSensorTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationSensorTest.java new file mode 100644 index 00000000000..f8ac4520d99 --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationSensorTest.java @@ -0,0 +1,55 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import java.nio.charset.Charset; +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.fs.internal.TestInputFileBuilder; +import org.sonar.api.batch.rule.ActiveRule; +import org.sonar.api.batch.rule.ActiveRules; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.education.EducationRulesDefinition.EDUCATION_KEY; + +public class EducationSensorTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + protected final ActiveRules activeRules = mock(ActiveRules.class); + + @Before + public void before() { + when(activeRules.find(any())).thenReturn(mock(ActiveRule.class)); + } + + protected DefaultInputFile newTestFile(String content) { + return new TestInputFileBuilder("foo", "hello.edu") + .setLanguage(EDUCATION_KEY) + .setContents(content) + .setCharset(Charset.defaultCharset()) + .build(); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithContextsSensorTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithContextsSensorTest.java new file mode 100644 index 00000000000..55d6856d063 --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithContextsSensorTest.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import java.io.IOException; +import org.junit.Test; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.internal.SensorContextTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.education.sensors.EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY; + +public class EducationWithContextsSensorTest extends EducationSensorTest { + + @Test + public void processFile_givenCorrectTagPassed_oneSecurityHotspotWithContextsIsRaised() throws IOException { + DefaultInputFile inputFile = newTestFile(EDUCATION_WITH_CONTEXTS_RULE_KEY); + + DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); + fs.add(inputFile); + + SensorContextTester sensorContextTester = SensorContextTester.create(temp.newFolder().toPath()); + var sensor = new EducationWithContextsSensor(fs, activeRules); + + sensor.execute(sensorContextTester); + + assertThat(sensorContextTester.allIssues()).hasSize(1); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithDetectedContextSensorTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithDetectedContextSensorTest.java new file mode 100644 index 00000000000..e3b6c81e296 --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithDetectedContextSensorTest.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import java.io.IOException; +import org.junit.Test; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.internal.SensorContextTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.education.sensors.EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY; + +public class EducationWithDetectedContextSensorTest extends EducationSensorTest { + + @Test + public void processFile_givenCorrectTagPassed_oneSecurityHotspotWithContextsIsRaised() throws IOException { + DefaultInputFile inputFile = newTestFile(EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY); + + DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); + fs.add(inputFile); + + SensorContextTester sensorContextTester = SensorContextTester.create(temp.newFolder().toPath()); + var sensor = new EducationWithDetectedContextSensor(fs, activeRules); + + sensor.execute(sensorContextTester); + + assertThat(sensorContextTester.allIssues()).hasSize(1); + } +} diff --git a/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithSingleContextSensorTest.java b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithSingleContextSensorTest.java new file mode 100644 index 00000000000..7b56e152911 --- /dev/null +++ b/plugins/sonar-education-plugin/src/test/java/org/sonar/education/sensors/EducationWithSingleContextSensorTest.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.education.sensors; + +import java.io.IOException; +import org.junit.Test; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.internal.SensorContextTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.education.sensors.EducationWithSingleContextSensor.EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY; + +public class EducationWithSingleContextSensorTest extends EducationSensorTest { + + @Test + public void processFile_givenCorrectTagPassed_oneSecurityHotspotWithContextsIsRaised() throws IOException { + DefaultInputFile inputFile = newTestFile(EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY); + + DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); + fs.add(inputFile); + + SensorContextTester sensorContextTester = SensorContextTester.create(temp.newFolder().toPath()); + var sensor = new EducationWithSingleContextSensor(fs, activeRules); + + sensor.execute(sensorContextTester); + + assertThat(sensorContextTester.allIssues()).hasSize(1); + } +} diff --git a/settings.gradle b/settings.gradle index b1998de61aa..6980a920f6c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,7 @@ pluginManagement { rootProject.name = 'sonarqube' include 'plugins:sonar-xoo-plugin' +include 'plugins:sonar-education-plugin' include 'server:sonar-auth-common' include 'server:sonar-auth-bitbucket' |