From c48cd42b789d639549260642966e9448980eb735 Mon Sep 17 00:00:00 2001 From: Guillaume Jambet Date: Wed, 17 Jan 2018 17:04:45 +0100 Subject: [PATCH] SONAR-10257 Added ITs --- .../scm-repository.zip | Bin 0 -> 37476 bytes .../sonar-project.properties | 5 + .../src/main/xoo/sample/Sample.xoo | 7 + .../src/main/xoo/sample/Sample.xoo.new | 13 ++ .../scm-repository.zip | Bin 0 -> 17704 bytes .../sonar-project.properties | 5 + .../src/main/xoo/sample/Sample.xoo | 7 + .../src/main/xoo/sample/Sample.xoo.new | 13 ++ .../src/main/xoo/sample/Sample.xoo.updated | 7 + .../tests/source/NoScmThenScmTest.java | 174 ++++++++++++++++++ .../tests/source/ScmThenNoScmTest.java | 137 ++++++++++++++ .../sonarqube/tests/source/SourceSuite.java | 8 +- .../org/sonarqube/tests/source/ZipUtils.java | 70 +++++++ 13 files changed, 444 insertions(+), 2 deletions(-) create mode 100644 tests/projects/scm/xoo-sample-with-then-without-scm/scm-repository.zip create mode 100644 tests/projects/scm/xoo-sample-with-then-without-scm/sonar-project.properties create mode 100644 tests/projects/scm/xoo-sample-with-then-without-scm/src/main/xoo/sample/Sample.xoo create mode 100644 tests/projects/scm/xoo-sample-with-then-without-scm/src/main/xoo/sample/Sample.xoo.new create mode 100644 tests/projects/scm/xoo-sample-without-then-with-scm/scm-repository.zip create mode 100644 tests/projects/scm/xoo-sample-without-then-with-scm/sonar-project.properties create mode 100644 tests/projects/scm/xoo-sample-without-then-with-scm/src/main/xoo/sample/Sample.xoo create mode 100644 tests/projects/scm/xoo-sample-without-then-with-scm/src/main/xoo/sample/Sample.xoo.new create mode 100644 tests/projects/scm/xoo-sample-without-then-with-scm/src/main/xoo/sample/Sample.xoo.updated create mode 100644 tests/src/test/java/org/sonarqube/tests/source/NoScmThenScmTest.java create mode 100644 tests/src/test/java/org/sonarqube/tests/source/ScmThenNoScmTest.java create mode 100644 tests/src/test/java/org/sonarqube/tests/source/ZipUtils.java diff --git a/tests/projects/scm/xoo-sample-with-then-without-scm/scm-repository.zip b/tests/projects/scm/xoo-sample-with-then-without-scm/scm-repository.zip new file mode 100644 index 0000000000000000000000000000000000000000..f0dada50b669ae5a5e0da5b7c8551cfc323b0a7e GIT binary patch literal 37476 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 z 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 scmData = ws.getScmData(FILE_TO_ANALYSE); + assertThat(scmData.size()).isEqualTo(1); + assertThat(scmData.get(1).revision).isEmpty(); + assertThat(scmData.get(1).author).isEmpty(); + assertThat(scmData.get(1).date).isInSameMinuteWindowAs(new Date()); + + // Restore SCM Repository + unzip(new File(source, "scm-repository.zip"), source.getAbsolutePath()); + + // 2nd run + orchestrator.executeBuild(newScannerWithSCM(source)); + + scmData = ws.getScmData(FILE_TO_ANALYSE); + assertThat(scmData.size()).isEqualTo(1); + assertThat(scmData.get(1).revision).isEqualTo("6664564f3358c9abf5f595eca31f228b3a95c886"); + assertThat(scmData.get(1).author).isEqualTo("guillaume.jambet@sonarsource.com"); + assertThat(scmData.get(1).date).isEqualToIgnoringMillis("2018-01-18T09:56:01"); + } + + @Test + public void without_and_then_with_scm_on_modified_file() throws ParseException, IOException { + + File source = disposableWorkspaceFor(PROJECT_DIRECTORY); + + // First run + orchestrator.executeBuild(newScannerWithoutSCM(source)); + + Map scmData = ws.getScmData(FILE_TO_ANALYSE); + assertThat(scmData.size()).isEqualTo(1); + assertThat(scmData.get(1).revision).isEmpty(); + assertThat(scmData.get(1).author).isEmpty(); + assertThat(scmData.get(1).date).isInSameMinuteWindowAs(new Date()); + + // Restore SCM Repository + unzip(new File(source, "scm-repository.zip"), source.getAbsolutePath()); + + // Swap analysed fo to a modified one + File sample = new File(source, PATH_TO_SAMPLE); + sample.delete(); + moveFile(new File(source, "src/main/xoo/sample/Sample.xoo.updated"), sample); + + // 2nd run + orchestrator.executeBuild(newScannerWithSCM(source)); + + scmData = ws.getScmData(FILE_TO_ANALYSE); + assertThat(scmData.get(1).revision).isEmpty(); + assertThat(scmData.get(1).author).isEmpty(); + assertThat(scmData.get(1).date).isEqualTo(scmData.get(1).date); + + assertThat(scmData.get(4).revision).isEmpty(); + assertThat(scmData.get(4).author).isEmpty(); + assertThat(scmData.get(4).date).isInSameMinuteWindowAs(new Date()); + + } + + @Test + public void without_and_then_with_scm_on_modified_file_with_new_lines() throws ParseException, IOException { + + File source = disposableWorkspaceFor(PROJECT_DIRECTORY); + + // First run + orchestrator.executeBuild(newScannerWithoutSCM(source)); + + Map scmData = ws.getScmData(FILE_TO_ANALYSE); + assertThat(scmData.size()).isEqualTo(1); + assertThat(scmData.get(1).revision).isEmpty(); + assertThat(scmData.get(1).author).isEmpty(); + assertThat(scmData.get(1).date).isInSameMinuteWindowAs(new Date()); + + // Restore SCM Repository + unzip(new File(source, "scm-repository.zip"), source.getAbsolutePath()); + + // Swap analysed fo to a modified one + File sample = new File(source, PATH_TO_SAMPLE); + sample.delete(); + moveFile(new File(source, "src/main/xoo/sample/Sample.xoo.new"), sample); + + // 2nd run + orchestrator.executeBuild(newScannerWithSCM(source)); + + scmData = ws.getScmData(FILE_TO_ANALYSE); + assertThat(scmData.get(1).revision).isEmpty(); + assertThat(scmData.get(1).author).isEmpty(); + assertThat(scmData.get(1).date).isEqualToIgnoringMillis("2018-01-17T10:35:23"); + + assertThat(scmData.get(5).revision).isEmpty(); + assertThat(scmData.get(5).author).isEmpty(); + assertThat(scmData.get(5).date).isInSameMinuteWindowAs(new Date()); + + } + + private SonarScanner newScannerWithoutSCM(File source) { + return SonarScanner.create(source); + } + + private SonarScanner newScannerWithSCM(File source) { + return SonarScanner.create(source) + .setProperty("sonar.scm.provider", "git") + .setProperty("sonar.scm.disabled", "false"); + } + + private File disposableWorkspaceFor(String project) throws IOException { + File origin = projectDir("scm/" + project); + copyDirectory(origin.getParentFile(), temporaryFolder.getRoot()); + return new File(temporaryFolder.getRoot(), project); + } + +} diff --git a/tests/src/test/java/org/sonarqube/tests/source/ScmThenNoScmTest.java b/tests/src/test/java/org/sonarqube/tests/source/ScmThenNoScmTest.java new file mode 100644 index 00000000000..0437a4899ea --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/source/ScmThenNoScmTest.java @@ -0,0 +1,137 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.sonarqube.tests.source; + +import com.sonar.orchestrator.Orchestrator; +import com.sonar.orchestrator.build.SonarScanner; +import java.io.File; +import java.io.IOException; +import java.text.ParseException; +import java.util.Date; +import java.util.Map; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonarqube.qa.util.Tester; + +import static org.apache.commons.io.FileUtils.copyDirectory; +import static org.apache.commons.io.FileUtils.deleteDirectory; +import static org.apache.commons.io.FileUtils.moveFile; +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonarqube.tests.source.SourceSuite.ORCHESTRATOR; +import static org.sonarqube.tests.source.ZipUtils.unzip; +import static util.ItUtils.projectDir; + +public class ScmThenNoScmTest { + + @ClassRule + public static Orchestrator orchestrator = ORCHESTRATOR; + private SourceScmWS ws = new SourceScmWS(orchestrator); + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Rule + public Tester tester = new Tester(orchestrator); + + @Test + public void with_and_then_without_scm_on_same_file() throws ParseException, IOException { + + File source = disposableWorkspaceFor("xoo-sample-with-then-without-scm"); + unzip(new File(source, "scm-repository.zip"), source.getAbsolutePath()); + + // First run + SonarScanner scanner = SonarScanner.create(source) + .setProperty("sonar.scm.provider", "git") + .setProperty("sonar.scm.disabled", "false"); + + orchestrator.executeBuild(scanner); + + Map scmData = ws.getScmData("sample-with-then-without-scm:src/main/xoo/sample/Sample.xoo"); + assertThat(scmData.size()).isEqualTo(1); + assertThat(scmData.get(1).revision).isEqualTo("036fcddbf771b54d7c5f7c8125a493d7d03a9d9d"); + assertThat(scmData.get(1).author).isEqualTo("guillaume.jambet@sonarsource.com"); + assertThat(scmData.get(1).date).isEqualToIgnoringMillis("2018-01-17T10:35:23"); + + // Drop SCM + deleteDirectory(new File(source, ".git")); + + // 2nd run + scanner = SonarScanner.create(source); + + orchestrator.executeBuild(scanner); + scmData = ws.getScmData("sample-with-then-without-scm:src/main/xoo/sample/Sample.xoo"); + assertThat(scmData.size()).isEqualTo(1); + assertThat(scmData.get(1).revision).isEmpty(); + assertThat(scmData.get(1).author).isEmpty(); + assertThat(scmData.get(1).date).isEqualToIgnoringMillis("2018-01-17T10:35:23"); + + } + + @Test + public void with_and_then_without_scm_on_modified_file() throws ParseException, IOException { + + File source = disposableWorkspaceFor("xoo-sample-with-then-without-scm"); + unzip(new File(source, "scm-repository.zip"), source.getAbsolutePath()); + + // First run + SonarScanner scanner = SonarScanner.create(source) + .setProperty("sonar.scm.provider", "git") + .setProperty("sonar.scm.disabled", "false"); + + orchestrator.executeBuild(scanner); + + Map scmData = ws.getScmData("sample-with-then-without-scm:src/main/xoo/sample/Sample.xoo"); + assertThat(scmData.size()).isEqualTo(1); + assertThat(scmData.get(1).revision).isEqualTo("036fcddbf771b54d7c5f7c8125a493d7d03a9d9d"); + assertThat(scmData.get(1).author).isEqualTo("guillaume.jambet@sonarsource.com"); + assertThat(scmData.get(1).date).isEqualToIgnoringMillis("2018-01-17T10:35:23"); + + // Drop SCM + deleteDirectory(new File(source, ".git")); + + // Swap analysed fo to a modified one + File sample = new File(source, "src/main/xoo/sample/Sample.xoo"); + sample.delete(); + moveFile(new File(source, "src/main/xoo/sample/Sample.xoo.new"), sample); + + // 2nd run + scanner = SonarScanner.create(source); + + orchestrator.executeBuild(scanner); + scmData = ws.getScmData("sample-with-then-without-scm:src/main/xoo/sample/Sample.xoo"); + assertThat(scmData.get(1).revision).isEmpty(); + assertThat(scmData.get(1).author).isEmpty(); + assertThat(scmData.get(1).date).isEqualToIgnoringMillis("2018-01-17T10:35:23"); + + assertThat(scmData.get(5).revision).isEmpty(); + assertThat(scmData.get(5).author).isEmpty(); + assertThat(scmData.get(5).date).isInSameMinuteWindowAs(new Date()); + + } + + private File disposableWorkspaceFor(String project) throws IOException { + File origin = projectDir("scm/" + project); + copyDirectory(origin.getParentFile(), temporaryFolder.getRoot()); + return new File(temporaryFolder.getRoot(), project); + } + +} diff --git a/tests/src/test/java/org/sonarqube/tests/source/SourceSuite.java b/tests/src/test/java/org/sonarqube/tests/source/SourceSuite.java index 23dd36d4966..e658a52d90c 100644 --- a/tests/src/test/java/org/sonarqube/tests/source/SourceSuite.java +++ b/tests/src/test/java/org/sonarqube/tests/source/SourceSuite.java @@ -31,15 +31,19 @@ import static util.ItUtils.xooPlugin; EncodingTest.class, ScmTest.class, NoScmTest.class, + ScmThenNoScmTest.class, SourceViewerTest.class }) public class SourceSuite { + @ClassRule - public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv() - // reduce memory for Elasticsearch + public static final Orchestrator ORCHESTRATOR = Orchestrator + .builderEnv() .setServerProperty("sonar.search.javaOpts", "-Xms128m -Xmx128m") + .setOrchestratorProperty("sonar-scm-git-plugin-version", "1.3.0.869") .addPlugin(xooPlugin()) + .addMavenPlugin("org.sonarsource.scm.git", "sonar-scm-git-plugin", "sonar-scm-git-plugin-version") .build(); } diff --git a/tests/src/test/java/org/sonarqube/tests/source/ZipUtils.java b/tests/src/test/java/org/sonarqube/tests/source/ZipUtils.java new file mode 100644 index 00000000000..258cc38128a --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/source/ZipUtils.java @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.sonarqube.tests.source; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class ZipUtils { + + // I see that we have apache commons compress in the path so it should be possible to reduce the boiler plate + // -- but nothing out of the box : still have to walk the tree and uncompress file by file. + + static void unzip(File archive, String directory) throws IOException { + try (ZipInputStream zis = new ZipInputStream(new FileInputStream(archive))) { + + ZipEntry entry = zis.getNextEntry(); + while (entry != null) { + + File file = new File(directory, entry.getName()); + + if (entry.isDirectory()) { + file.mkdirs(); + } else { + + File parent = file.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + + try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) { + long size = entry.getSize(); + byte[] buffer = new byte[Math.toIntExact(size)]; + if (size > 0) { + int location; + while ((location = zis.read(buffer)) != -1) { + bos.write(buffer, 0, location); + } + } + } + + } + + entry = zis.getNextEntry(); + } + } + } + +} -- 2.39.5