Use Gerrit repositories for analytics tests Mutate Gerrit bare repositories and use them for the execution of the analytics plugin. This makes the use-case scenarios a lot more similar to the real runtime of the plugin, which runs inside a Gerrit daemon. Remove all references to the copy&paste GitTestCase from Gitective and replace it with a simple pimping of the current Gerrit TestRepository class. Change-Id: Ib6f09a5fbd73aafdb1eefc7a2b521f35df7c23e0
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/BotLikeExtractorImplSpec.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/BotLikeExtractorImplSpec.scala index dedab3b..e9f9c7a 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/BotLikeExtractorImplSpec.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/BotLikeExtractorImplSpec.scala
@@ -15,10 +15,10 @@ package com.googlesource.gerrit.plugins.analytics.common import com.googlesource.gerrit.plugins.analytics.AnalyticsConfig -import com.googlesource.gerrit.plugins.analytics.test.GitTestCase +import com.googlesource.gerrit.plugins.analytics.test.GerritTestDaemon import org.scalatest.{FlatSpec, Matchers} -class BotLikeExtractorImplSpec extends FlatSpec with Matchers with GitTestCase { +class BotLikeExtractorImplSpec extends FlatSpec with Matchers with GerritTestDaemon { behavior of "isBotLike" @@ -29,7 +29,6 @@ "some/path/AFile.xml", "some/path/AnotherFile.xml" )).shouldBe(true) - } it should "return false when at least one file does not match bot-like identifiers" in { @@ -39,18 +38,15 @@ "some/path/AFile.xml", "some/path/AnotherFile.someExtension" )).shouldBe(false) - } it should "return false when no bot-like identifiers have been provided" in { val extractor = newBotLikeExtractorImpl(List.empty) extractor.isBotLike(Set("some/path/anyFile")).shouldBe(false) - } private def newBotLikeExtractorImpl(botLikeRegexps: List[String]) = new BotLikeExtractorImpl(new AnalyticsConfig(null, null) { override lazy val botlikeFilenameRegexps = botLikeRegexps }) - }
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/BranchesExtractorSpec.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/BranchesExtractorSpec.scala index 7a15b22..07909ff 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/BranchesExtractorSpec.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/BranchesExtractorSpec.scala
@@ -1,29 +1,28 @@ package com.googlesource.gerrit.plugins.analytics.common -import com.googlesource.gerrit.plugins.analytics.test.GitTestCase -import org.eclipse.jgit.internal.storage.file.FileRepository +import com.google.gerrit.acceptance.UseLocalDisk +import com.googlesource.gerrit.plugins.analytics.test.GerritTestDaemon import org.scalatest.{FlatSpec, Matchers} -class BranchesExtractorSpec extends FlatSpec with Matchers with GitTestCase { - def commitsBranches = new BranchesExtractor(new FileRepository(testRepo)) +@UseLocalDisk +class BranchesExtractorSpec extends FlatSpec with Matchers with GerritTestDaemon { + def commitsBranches = new BranchesExtractor(testFileRepository.getRepository) behavior of "branchesOfCommit" it should "extract one branch for a commit existing only in one branch" in { - add("file", "content") - branch("feature/branch") - val commit = add("fileOnBranch", "content2") + testFileRepository.commitFile("file", "content") + testFileRepository.branch("feature/branch", "master") + val commit = testFileRepository.commitFile("fileOnBranch", "content2", branch = "feature/branch") - commitsBranches.branchesOfCommit(commit.getId) shouldBe Set("feature/branch") - + commitsBranches.branchesOfCommit(commit) shouldBe Set("feature/branch") } it should "extract two branches for a commit existing in two different branches" in { - val commit = add("file", "content") - branch("feature/branch") - add("fileOnBranch", "content2") + val commit = testFileRepository.commitFile("file", "content") + testFileRepository.branch("feature/branch", "master") + testFileRepository.commitFile("fileOnBranch", "content2", branch = "feature/branch") - commitsBranches.branchesOfCommit(commit.getId) shouldBe Set("feature/branch", "master") - + commitsBranches.branchesOfCommit(commit) shouldBe Set("feature/branch", "master") } }
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/TestUtils.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/TestUtils.scala index cef628e..525d3c3 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/TestUtils.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/TestUtils.scala
@@ -1,14 +1,13 @@ package com.googlesource.gerrit.plugins.analytics.common -import com.googlesource.gerrit.plugins.analytics.test.GitTestCase +import org.eclipse.jgit.internal.storage.file.FileRepository import org.gitective.core.CommitFinder trait TestUtils { - self: GitTestCase => - def aggregateBy(strategy: AggregationStrategy): Array[AggregatedUserCommitActivity] = { + def aggregateBy(strategy: AggregationStrategy)(implicit testRepository: FileRepository): Array[AggregatedUserCommitActivity] = { val filter = new AggregatedHistogramFilterByDates(aggregationStrategy = strategy) - new CommitFinder(testRepo).setFilter(filter).find + new CommitFinder(testRepository).setFilter(filter).find filter.getHistogram.getAggregatedUserActivity }
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/UserActivityHistogramTest.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/UserActivityHistogramSpec.scala similarity index 69% rename from src/test/scala/com/googlesource/gerrit/plugins/analytics/common/UserActivityHistogramTest.scala rename to src/test/scala/com/googlesource/gerrit/plugins/analytics/common/UserActivityHistogramSpec.scala index 282d29f..7dbe121 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/UserActivityHistogramTest.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/common/UserActivityHistogramSpec.scala
@@ -14,24 +14,23 @@ package com.googlesource.gerrit.plugins.analytics.common +import com.google.gerrit.acceptance.UseLocalDisk import com.googlesource.gerrit.plugins.analytics.common.AggregationStrategy.EMAIL_YEAR -import com.googlesource.gerrit.plugins.analytics.test.GitTestCase -import org.eclipse.jgit.internal.storage.file.FileRepository +import com.googlesource.gerrit.plugins.analytics.test.GerritTestDaemon import org.scalatest.{FlatSpec, Matchers} -class UserActivityHistogramTest extends FlatSpec with Matchers with GitTestCase { +@UseLocalDisk +class UserActivityHistogramSpec extends FlatSpec with Matchers with GerritTestDaemon { "UserActivityHistogram" should "return no activities" in { - val repo = new FileRepository(testRepo) val filter = new AggregatedHistogramFilterByDates(aggregationStrategy = EMAIL_YEAR) - new UserActivityHistogram().get(repo, filter) should have size 0 + new UserActivityHistogram().get(testFileRepository.getRepository, filter) should have size 0 } it should "aggregate to one activity" in { - val repo = new FileRepository(testRepo) - add("test.txt", "content") + testFileRepository.commitFile("test.txt", "content") val filter = new AggregatedHistogramFilterByDates(aggregationStrategy = EMAIL_YEAR) - new UserActivityHistogram().get(repo, filter) should have size 1 + new UserActivityHistogram().get(testFileRepository.getRepository, filter) should have size 1 } }
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/AggregatedHistogramFilterByDatesSpec.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/AggregatedHistogramFilterByDatesSpec.scala index 4e0895e..3128b2c 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/AggregatedHistogramFilterByDatesSpec.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/AggregatedHistogramFilterByDatesSpec.scala
@@ -16,22 +16,22 @@ import java.util.Date +import com.google.gerrit.acceptance.UseLocalDisk import com.googlesource.gerrit.plugins.analytics.common.AggregationStrategy.EMAIL import com.googlesource.gerrit.plugins.analytics.common.{AggregatedHistogramFilterByDates, BranchesExtractor} -import org.eclipse.jgit.internal.storage.file.FileRepository import org.eclipse.jgit.lib.PersonIdent import org.gitective.core.CommitFinder import org.scalatest.{BeforeAndAfterEach, FlatSpec, Matchers} -class AggregatedHistogramFilterByDatesSpec extends FlatSpec with GitTestCase with BeforeAndAfterEach with Matchers { - +@UseLocalDisk +class AggregatedHistogramFilterByDatesSpec extends FlatSpec with GerritTestDaemon with BeforeAndAfterEach with Matchers { "Author history filter" should "select one commit without intervals restriction" in { - add("file.txt", "some content") + testFileRepository.commitFile("file.txt", "some content") val filter = new AggregatedHistogramFilterByDates() - new CommitFinder(testRepo).setFilter(filter).find + new CommitFinder(fileRepository).setFilter(filter).find val userActivity = filter.getHistogram.getUserActivity filter.getHistogram.getUserActivity should have size 1 @@ -42,16 +42,16 @@ } it should "select only the second of two commits based on the start timestamp" in { - val firstCommitTs = add("file.txt", "some content") - .getCommitterIdent.getWhen.getTime + val firstCommit = testFileRepository.commitFile("file.txt", "some content") + val firstCommitTs = firstCommit.getCommitterIdent.getWhen.getTime val person = newPersonIdent("Second person", "second@company.com", new Date(firstCommitTs + 1000L)) - val secondCommitTs = add("file.txt", "other content", author = person, committer = person) - .getCommitterIdent.getWhen.getTime + val secondCommit = testFileRepository.commitFile("file.txt", "other content", author = person, committer = person) + val secondCommitTs = secondCommit.getCommitterIdent.getWhen.getTime secondCommitTs should be > firstCommitTs val filter = new AggregatedHistogramFilterByDates(from = Some(secondCommitTs)) - new CommitFinder(testRepo).setFilter(filter).find + new CommitFinder(fileRepository).setFilter(filter).find val userActivity = filter.getHistogram.getUserActivity userActivity should have size 1 @@ -64,15 +64,15 @@ it should "select only the first of two commits based on the end timestamp" in { val person = newPersonIdent("First person", "first@company.com") - val firstCommitTs = add("file.txt", "some content", author = person, committer = person) + val firstCommitTs = testFileRepository.commitFile("file.txt", "some content", author = person, committer = person) .getCommitterIdent.getWhen.getTime - val secondCommitTs = add("file.txt", "other content", committer = new PersonIdent(committer, new Date(firstCommitTs + 1000L))) + val secondCommitTs = testFileRepository.commitFile("file.txt", "other content", committer = new PersonIdent(committer, new Date(firstCommitTs + 1000L))) .getCommitterIdent.getWhen.getTime secondCommitTs should be > firstCommitTs val filter = new AggregatedHistogramFilterByDates(to = Some(secondCommitTs)) - new CommitFinder(testRepo).setFilter(filter).find + new CommitFinder(fileRepository).setFilter(filter).find val userActivity = filter.getHistogram.getUserActivity userActivity should have size 1 @@ -84,19 +84,19 @@ } it should "select only one middle commit out of three based on interval from/to timestamp" in { - val firstCommitTs = add("file.txt", "some content") + val firstCommitTs = testFileRepository.commitFile("file.txt", "some content") .getCommitterIdent.getWhen.getTime val person = newPersonIdent("Middle person", "middle@company.com", new Date(firstCommitTs + 1000L)) - val middleCommitTs = add("file.txt", "other content", author = person, committer = person) + val middleCommitTs = testFileRepository.commitFile("file.txt", "other content", author = person, committer = person) .getCommitterIdent.getWhen.getTime - val lastCommitTs = add("file.text", "yet other content", committer = new PersonIdent(committer, new Date(middleCommitTs + 1000L))) + val lastCommitTs = testFileRepository.commitFile("file.text", "yet other content", committer = new PersonIdent(committer, new Date(middleCommitTs + 1000L))) .getCommitterIdent.getWhen.getTime middleCommitTs should be > firstCommitTs lastCommitTs should be > middleCommitTs val filter = new AggregatedHistogramFilterByDates(from = Some(middleCommitTs), to = Some(lastCommitTs)) - new CommitFinder(testRepo).setFilter(filter).find + new CommitFinder(fileRepository).setFilter(filter).find val userActivity = filter.getHistogram.getUserActivity userActivity should have size 1 @@ -108,16 +108,16 @@ } it should "aggregate commits of the same user separately when they are in different branches and branchesExtractor is set" in { - val repo = new FileRepository(testRepo) - add("file1.txt", "add file1.txt to master branch") - branch("another/branch") - add("file2.txt", "add file2.txt to another/branch") + testFileRepository.commitFile("file1.txt", "add file1.txt to master branch") + testFileRepository.branch("another/branch", "master") + testFileRepository.commitFile("file2.txt", "add file2.txt to another/branch", branch = "another/branch") + val filter = new AggregatedHistogramFilterByDates( aggregationStrategy=EMAIL, - branchesExtractor = Some(new BranchesExtractor(repo)) + branchesExtractor = Some(new BranchesExtractor(fileRepository)) ) - new CommitFinder(testRepo).setFilter(filter).find + new CommitFinder(fileRepository).setFilter(filter).find val userActivity = filter.getHistogram.getUserActivity userActivity should have size 2
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/AggregationSpec.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/AggregationSpec.scala index 6725b7e..c3d2087 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/AggregationSpec.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/AggregationSpec.scala
@@ -16,16 +16,20 @@ import java.util.Date +import com.google.gerrit.acceptance.UseLocalDisk import com.googlesource.gerrit.plugins.analytics.common.AggregationStrategy._ import com.googlesource.gerrit.plugins.analytics.common.DateConversions.isoStringToLongDate import com.googlesource.gerrit.plugins.analytics.common.TestUtils import org.eclipse.jgit.revwalk.RevCommit import org.scalatest.{FlatSpec, Inspectors, Matchers} -class AggregationSpec extends FlatSpec with Matchers with GitTestCase with TestUtils with Inspectors { +@UseLocalDisk +class AggregationSpec extends FlatSpec with Matchers with GerritTestDaemon with TestUtils with Inspectors { - def commitAtDate(committer: String, when: String, content: String): RevCommit = - commit(committer, "afile.txt", content, new Date(isoStringToLongDate(when))) + def commitAtDate(committer: String, when: String, content: String): RevCommit = { + val personIdent = newPersonIdent(committer, committer, new Date(isoStringToLongDate(when))) + testFileRepository.commitFile("somefile", content, committer = personIdent, author = personIdent) + } "AggregatedHistogramFilter by email and year" should "aggregate two commits from the same author the same year" in { commitAtDate("john", "2017-08-01", "first commit")
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsCommentLinkSpec.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsCommentLinkSpec.scala index 2900e69..d263577 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsCommentLinkSpec.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsCommentLinkSpec.scala
@@ -14,13 +14,15 @@ package com.googlesource.gerrit.plugins.analytics.test +import com.google.gerrit.acceptance.UseLocalDisk import com.google.gerrit.extensions.api.projects.CommentLinkInfo import com.googlesource.gerrit.plugins.analytics.IssueInfo import com.googlesource.gerrit.plugins.analytics.common.{CommitsStatistics, Statistics} -import org.eclipse.jgit.internal.storage.file.FileRepository +import org.eclipse.jgit.lib.Repository import org.scalatest.{FlatSpec, Inside, Matchers} -class CommitStatisticsCommentLinkSpec extends FlatSpec with GitTestCase with Matchers with Inside { +@UseLocalDisk +class CommitStatisticsCommentLinkSpec extends FlatSpec with GerritTestDaemon with Matchers with Inside { def createCommentLinkInfo(pattern: String, link: Option[String] = None, html: Option[String] = None) = { val info = new CommentLinkInfo @@ -30,7 +32,7 @@ info } - class TestEnvironment(val repo: FileRepository = new FileRepository(testRepo), + class TestEnvironment(val repo: Repository = fileRepository, val commentLinks: List[CommentLinkInfo] = List( createCommentLinkInfo(pattern = "(bug\\s+#?)(\\d+)", link = Some("http://bugs.example.com/show_bug.cgi?id=$2")), @@ -41,39 +43,37 @@ } it should "collect no commentslink if no matching" in new TestEnvironment { - val nocomments = commit("user", "file1.txt", "content1") + val nocomments = testFileRepository.commitFile("file1.txt", "content1") inside(stats.forCommits(nocomments)) { case List(s: CommitsStatistics) => s.issues should have size 0 } - } it should "collect simple bugzilla comments" in new TestEnvironment { - val simpleComment = commit("user", "file1.txt", "content2", message = - Some("this solves bug #23")) + val simpleComment = testFileRepository.commitFile("file1.txt", "content2", message = + "this solves bug #23") inside(stats.forCommits(simpleComment)) { case List(s: CommitsStatistics) => s.issues should have size 1 s.issues should contain(IssueInfo("bug #23", "http://bugs.example.com/show_bug.cgi?id=23")) } - } it should "collect simple track link" in new TestEnvironment { - val simpleTrackComment = commit("user", "file1.txt", "content3", message - = Some("this solves Bug: 1234")) + val simpleTrackComment = testFileRepository.commitFile("file1.txt", "content3", message + = "this solves Bug: 1234") inside(stats.forCommits(simpleTrackComment)) { case List(s: CommitsStatistics) => s.issues should have size 1 s.issues should contain(IssueInfo("Bug: 1234", "Bug: <a href=\"http://trak.example.com/1234\">1234</a>")) } - } + it should "collect multiple links" in new TestEnvironment { - val multipleComments = commit("user", "file1.txt", "content4", message = - Some("this solves bug 12 and Bug: 23")) + val multipleComments = testFileRepository.commitFile("file1.txt", "content4", message = + "this solves bug 12 and Bug: 23") inside(stats.forCommits(multipleComments)) { case List(s: CommitsStatistics) => @@ -82,7 +82,5 @@ IssueInfo("Bug: 23", "Bug: <a href=\"http://trak.example.com/23\">23</a>") ) } - } - }
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsSpec.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsSpec.scala index 332c724..4b56f7c 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsSpec.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsSpec.scala
@@ -14,21 +14,21 @@ package com.googlesource.gerrit.plugins.analytics.test +import com.google.gerrit.acceptance.UseLocalDisk import com.googlesource.gerrit.plugins.analytics.CommitInfo import com.googlesource.gerrit.plugins.analytics.common.{CommitsStatistics, Statistics} -import org.eclipse.jgit.internal.storage.file.FileRepository import org.scalatest.{FlatSpec, Inside, Matchers} -class CommitStatisticsSpec extends FlatSpec with GitTestCase with Matchers with Inside { - +@UseLocalDisk +class CommitStatisticsSpec extends FlatSpec with GerritTestDaemon with Matchers with Inside { class TestEnvironment { - val repo = new FileRepository(testRepo) + val repo = fileRepository val stats = new Statistics(repo, TestBotLikeExtractor) } "CommitStatistics" should "stats a single file added" in new TestEnvironment { - val change = commit("user", "file1.txt", "line1\nline2") + val change = testFileRepository.commitFile("file1.txt", "line1\nline2") inside(stats.forCommits(change)) { case List(s: CommitsStatistics) => s.numFiles should be(1) @@ -54,12 +54,12 @@ } it should "stats multiple files added" in new TestEnvironment { - val initial = commit("user", "file1.txt", "line1\nline2\n") - val second = add(testRepo, + val initial = testFileRepository.commitFile("file1.txt", "line1\nline2\n") + val second = testFileRepository.commitFiles( List( "file1.txt" -> "line1\n", "file2.txt" -> "line1\nline2\n" - ), "second commit") + ), message = "second commit") inside(stats.forCommits(second)) { case List(s: CommitsStatistics) => s.numFiles should be(2) @@ -69,8 +69,8 @@ } it should "stats lines eliminated" in new TestEnvironment { - val initial = commit("user", "file1.txt", "line1\nline2\nline3") - val second = commit("user", "file1.txt", "line1\n") + val initial = testFileRepository.commitFile( "file1.txt", "line1\nline2\nline3") + val second = testFileRepository.commitFile( "file1.txt", "line1\n") inside(stats.forCommits(second)) { case List(s: CommitsStatistics) => s.numFiles should be(1) s.addedLines should be(0) @@ -79,17 +79,17 @@ } it should "stats a Seq[RevCommit]" in new TestEnvironment { - val initial = add(testRepo, + val initial = testFileRepository.commitFiles( List( "file1.txt" -> "line1\n", "file3.txt" -> "line1\nline2\n"), - "first commit") + message = "first commit") - val second = add(testRepo, + val second = testFileRepository.commitFiles( List( "file1.txt" -> "line1a\n", "file2.txt" -> "line1\nline2\n"), - "second commit") + message = "second commit") inside(stats.forCommits(initial, second)) { case List(nonMergeStats: CommitsStatistics) => nonMergeStats.numFiles should be(4) @@ -100,7 +100,7 @@ } it should "return zero value stats if the commit does not include any file" in new TestEnvironment { - val emptyCommit = add(testRepo, List.empty, "Empty commit") + val emptyCommit = testFileRepository.commitFiles(List.empty, message = "Empty commit") inside(stats.forCommits(emptyCommit)) { case List(stats) => stats.numFiles should be(0) stats.addedLines should be(0) @@ -109,13 +109,15 @@ } it should "split merge commits and non-merge commits" in new TestEnvironment { - val firstNonMerge = commit("user", "file1.txt", "line1\nline2\n") - val merge = mergeCommit("user", "file1.txt", "line1\nline2\nline3") - val nonMerge = add(testRepo, + val clonedRepo = testFileRepository.gitClone + val firstNonMerge = clonedRepo.commitFile("file1.txt", "line1\nline2\n") + val merge = clonedRepo.mergeCommitFile("file1.txt", "line1\nline2\nline3") + val nonMerge = clonedRepo.commitFiles( List( "file1.txt" -> "line1\n", "file2.txt" -> "line1\nline2\n"), - "second commit") + message = "second commit") + clonedRepo.push inside(stats.forCommits(firstNonMerge, merge.getNewHead, nonMerge)) { case List(nonMergeStats, mergeStats) =>
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/GerritTestDaemon.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/GerritTestDaemon.scala new file mode 100644 index 0000000..6e6f457 --- /dev/null +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/GerritTestDaemon.scala
@@ -0,0 +1,146 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.googlesource.gerrit.plugins.analytics.test + +import java.io.File +import java.util.{Date, UUID} + +import com.google.gerrit.acceptance.{AbstractDaemonTest, GitUtil} +import com.google.gerrit.reviewdb.client.Project +import org.eclipse.jgit.api.MergeCommand.FastForwardMode +import org.eclipse.jgit.api.{Git, MergeResult} +import org.eclipse.jgit.internal.storage.file.FileRepository +import org.eclipse.jgit.junit.TestRepository +import org.eclipse.jgit.lib._ +import org.eclipse.jgit.merge.MergeStrategy +import org.eclipse.jgit.revwalk.RevCommit +import org.gitective.core.CommitUtils +import org.junit.runner.Description +import org.junit.runners.model.Statement +import org.scalatest._ + +trait GerritTestDaemon extends BeforeAndAfterEach { + self: Suite => + + type TestFileRepository = TestRepository[FileRepository] + + val daemonTest = GerritTestDaemon + + protected abstract override def runTest(testName: String, args: Args): Status = { + var status: Status = FailedStatus + val runLambda = () => super.runTest(testName, args) + + daemonTest.testRunner.apply(new Statement() { + override def evaluate(): Unit = { + status = runLambda.apply() + } + }, Description.createTestDescription(getClass.getName, testName)).evaluate() + + status + } + + var testFileRepository: TestFileRepository = _ + + implicit var fileRepository: FileRepository = _ + + protected lazy val author = newPersonIdent("Test Author", "author@test.com") + + protected lazy val committer = newPersonIdent("Test Committer", "committer@test.com") + + def newPersonIdent(name: String = "Test Person", email: String = "person@test.com", ts: Date = new Date()) = + new PersonIdent(new PersonIdent(name, email), ts) + + override def beforeEach { + fileRepository = daemonTest.getRepository( + daemonTest.newProject(testSpecificRepositoryName)) + + testFileRepository = GitUtil.newTestRepository(fileRepository) + } + + private def testSpecificRepositoryName = "git-test-case-" + UUID.randomUUID().toString + + implicit class PimpedGitRepository(repo: TestFileRepository) { + + def branch(name: String, startPoint: String): Ref = + repo.git.branchCreate.setName(name).setStartPoint(startPoint).call + + def gitClone: TestFileRepository = { + val TmpDir = System.getProperty("java.io.tmpdir") + val clonedRepository = Git.cloneRepository + .setDirectory(new File(s"$TmpDir/${testSpecificRepositoryName}_clone")) + .setURI(repo.getRepository.getDirectory.toURI.toString) + .call() + .getRepository.asInstanceOf[FileRepository] + + GitUtil.newTestRepository(clonedRepository) + } + + def commitFile(path: String, content: String, author: PersonIdent = author, committer: PersonIdent = committer, branch: String = Constants.MASTER, message: String = ""): RevCommit = + repo.branch(branch).commit() + .add(path, content) + .author(author) + .committer(committer) + .message(message) + .create + + def commitFiles(files: Iterable[(String, String)], author: PersonIdent = author, committer: PersonIdent = committer, branch: String = Constants.MASTER, message: String = ""): RevCommit = { + val commit = repo.branch(branch).commit() + .author(author) + .committer(committer) + .message(message) + + files.foldLeft(commit) { + (commit, fileAndContent) => commit.add(fileAndContent._1, fileAndContent._2) + }.create() + } + + def mergeCommitFile(fileName: String, content: String, author: PersonIdent = author, committer: PersonIdent = committer): MergeResult = { + val currentBranch = repo.getRepository.getFullBranch + val tmpBranch = repo.branch("tmp", currentBranch) + try { + repo.commitFile(fileName, content, branch = tmpBranch.getName, author = author, committer = committer) + repo.mergeBranch(tmpBranch.getName, withCommit = true) + } finally { + repo.git.branchDelete().setBranchNames(tmpBranch.getName).setForce(true).call.get(0) + } + } + + def mergeBranch(branch: String, withCommit: Boolean, message: String = "merging branch"): MergeResult = { + repo.git.merge.setStrategy(MergeStrategy.RESOLVE) + .include(CommitUtils.getRef(repo.getRepository, branch)) + .setCommit(withCommit) + .setFastForward(FastForwardMode.NO_FF) + .setMessage(message) + .call + } + + def push = + repo.git.push.setPushAll.call + } +} + +object GerritTestDaemon extends AbstractDaemonTest { + baseConfig = new Config() + + def newProject(nameSuffix: String) = { + resourcePrefix = "" + super.createProject(nameSuffix, allProjects, false) + } + + def getRepository(projectName: Project.NameKey): FileRepository = + repoManager.openRepository(projectName).asInstanceOf[FileRepository] + + def adminAuthor = admin.getIdent +} \ No newline at end of file
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/GitTestCase.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/GitTestCase.scala deleted file mode 100644 index c7a3850..0000000 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/GitTestCase.scala +++ /dev/null
@@ -1,432 +0,0 @@ -// -// Copyright (c) 2011 Kevin Sawicki <kevinsawicki@gmail.com> -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -// -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.googlesource.gerrit.plugins.analytics.test - -import java.io.{File, PrintWriter} -import java.nio.file.Files -import java.text.MessageFormat -import java.util.Date - -import com.googlesource.gerrit.plugins.analytics.common.DateConversions.isoStringToLongDate -import com.googlesource.gerrit.plugins.analytics.common.ManagedResource.use -import org.eclipse.jgit.api.MergeCommand.FastForwardMode -import org.eclipse.jgit.api.{Git, MergeResult} -import org.eclipse.jgit.api.errors.GitAPIException -import org.eclipse.jgit.lib.{Constants, PersonIdent, Ref} -import org.eclipse.jgit.merge.MergeStrategy -import org.eclipse.jgit.notes.Note -import org.eclipse.jgit.revwalk.RevCommit -import org.gitective.core.CommitUtils -import org.scalatest.{BeforeAndAfterEach, Suite} -import com.googlesource.gerrit.plugins.analytics.common.DateConversions._ - - -/** - * Base test case with utilities for common Git operations performed during - * testing - */ -trait GitTestCase extends BeforeAndAfterEach { - self: Suite => - /** - * Test repository .git directory - */ - protected var testRepo: File = null - - /** - * Author used for commits - */ - protected val author = new PersonIdent("Test Author", "author@test.com") - - def newPersonIdent(name: String = "Test Person", email: String = "person@test.com", ts: Date = new Date()) = - new PersonIdent(new PersonIdent(name, email), ts) - - /** - * Committer used for commits - */ - protected val committer = new PersonIdent("Test Committer", "committer@test.com") - - /** - * Set up method that initializes git repository - * - * - */ - - override def beforeEach = { - testRepo = initRepo - } - - /** - * Initialize a new repo in a new directory - * - * @return created .git folder - * @throws GitAPIException - */ - protected def initRepo: File = { - val dir = Files.createTempDirectory(threadSpecificDirectoryPrefix).toFile - Git.init.setDirectory(dir).setBare(false).call - val repo = new File(dir, Constants.DOT_GIT) - assert(repo.exists) - repo.deleteOnExit() - repo - } - - private def threadSpecificDirectoryPrefix = - "git-test-case-" + Thread.currentThread().getName.replaceAll("~[0-9a-zA-Z]", "_") + System.nanoTime - - /** - * Create branch with name and checkout - * - * @param name - * @return branch ref - * - */ - protected def branch(name: String): Ref = branch(testRepo, name) - - /** - * Delete branch with name - * - * @param name - * @return branch ref - * - */ - protected def deleteBranch(name: String): String = deleteBranch(testRepo, name) - - /** - * Create branch with name and checkout - * - * @param repo - * @param name - * @return branch ref - * - */ - protected def branch(repo: File, name: String): Ref = { - use(Git.open(repo)) { git => - git.branchCreate.setName(name).call - checkout(repo, name) - } - } - - /** - * Delete branch with name - * - * @param repo - * @param name - * @return branch ref - * - */ - protected def deleteBranch(repo: File, name: String): String = { - use(Git.open(repo)) { git => - git.branchDelete().setBranchNames(name).setForce(true).call.get(0) - } - } - - /** - * Checkout branch - * - * @param name - * @return branch ref - * - */ - protected def checkout(name: String): Ref = checkout(testRepo, name) - - /** - * Checkout branch - * - * @param repo - * @param name - * @return branch ref - * - */ - @throws[Exception] - protected def checkout(repo: File, name: String): Ref = { - use(Git.open(repo)) { git => - git.checkout.setName(name).call - } - } ensuring(_ != null, "Unable to checkout result") - - /** - * Create tag with name - * - * @param name - * @return tag ref - * - */ - protected def tag(name: String): Ref = tag(testRepo, name) - - /** - * Create tag with name - * - * @param repo - * @param name - * @return tag ref - * - */ - protected def tag(repo: File, name: String): Ref = { - use(Git.open(repo)) { git => - git.tag.setName(name).setMessage(name).call - git.getRepository.getTags.get(name) - } - } ensuring(_ != null, s"Unable to tag file $name") - - /** - * Add file to test repository - * - * @param path - * @param content - * @return commit - * - */ - protected def add(path: String, content: String, author: PersonIdent = author, committer: PersonIdent = committer): RevCommit = add(testRepo, path, content, author, committer) - - /** - * Add file to test repository - * - * @param repo - * @param path - * @param content - * @return commit - * - */ - protected def add(repo: File, path: String, content: String, author: PersonIdent, committer: PersonIdent): RevCommit = { - val message = MessageFormat.format("Committing {0} at {1}", path, new Date) - add(repo, path, content, message, author, committer) - } - - - /** - * Add file to test repository - * - * @param repo - * @param path - * @param content - * @param message - * @return commit - * - */ - protected def add(repo: File, path: String, content: String, message: String, author: PersonIdent, committer: PersonIdent): RevCommit = { - val file = new File(repo.getParentFile, path) - if (!file.getParentFile.exists) assert(file.getParentFile.mkdirs) - if (!file.exists) assert(file.createNewFile) - - val writer = new PrintWriter(file) - try - writer.print(Option(content).fold("")(identity)) - finally writer.close() - - use(Git.open(repo)) { git => - git.add.addFilepattern(path).call - git.commit.setOnly(path).setMessage(message).setAuthor(author).setCommitter(committer).call - } - } ensuring (_ != null, s"Unable to commit addition of path $path") - - /** - * Move file in test repository - * - * @param from - * @param to - * @return commit - * - */ - protected def mv(from: String, to: String): RevCommit = mv(testRepo, from, to, MessageFormat.format("Moving {0} to {1} at {2}", from, to, new Date)) - - /** - * Move file in test repository - * - * @param from - * @param to - * @param message - * @return commit - * - */ - protected def mv(from: String, to: String, message: String): RevCommit = mv(testRepo, from, to, message) - - /** - * Move file in test repository - * - * @param repo - * @param from - * @param to - * @param message - * @return commit - * - */ - protected def mv(repo: File, from: String, to: String, message: String): RevCommit = { - val file = new File(repo.getParentFile, from) - file.renameTo(new File(repo.getParentFile, to)) - - use(Git.open(testRepo)) { git => - git.rm.addFilepattern(from) - git.add.addFilepattern(to).call - git.commit.setAll(true).setMessage(message).setAuthor(author).setCommitter(committer).call - } - } ensuring (_ != null, "Unable to commit MV operation") - - /** - * Add files to test repository - * - * @param contents iterable of file names and associated content - * @return commit - * - */ - protected def add(contents: Iterable[(String, String)]): RevCommit = add(testRepo, contents, "Committing multiple files") - - /** - * Add files to test repository - * - * @param repo - * @param contents iterable of file names and associated content - * @param message - * @return commit - * - */ - protected def add(repo: File, contents: Iterable[(String, String)], message: String): RevCommit = { - use(Git.open(testRepo)) { git => - var i = 0 - contents.foreach { case (path, content) => - val file = new File(repo.getParentFile, path) - if (!file.getParentFile.exists) require(file.getParentFile.mkdirs, s"Cannot create parent dir '${file.getParent}'") - if (!file.exists) require(file.createNewFile, s"Cannot create file '$file'") - val writer = new PrintWriter(file) - try - writer.print(content) - finally writer.close() - git.add.addFilepattern(path).call - } - - git.commit.setMessage(message).setAuthor(author).setCommitter(committer).call - } - } ensuring (_ != null, "Unable to commit content addition") - - /** - * Merge given branch into current branch - * - * @param branch - * @return result - * - */ - protected def mergeBranch(branch: String, withCommit: Boolean): MergeResult = { - use(Git.open(testRepo)) { git => - git.merge.setStrategy(MergeStrategy.RESOLVE).include(CommitUtils.getRef(git.getRepository, branch)).setCommit(withCommit).setFastForward(FastForwardMode.NO_FF).setMessage(s"merging branch $branch").call - } - } - - /** - * Merge ref into current branch - * - * @param ref - * @return result - * - */ - protected def merge(ref: String): MergeResult = { - use(Git.open(testRepo)) { git => - git.merge.setStrategy(MergeStrategy.RESOLVE).include(CommitUtils.getCommit(git.getRepository, ref)).call - } - } - - /** - * Add note to latest commit with given content - * - * @param content - * @return note - * - */ - protected def note(content: String): Note = note(content, "commits") - - /** - * Add note to latest commit with given content - * - * @param content - * @param ref - * @return note - * - */ - protected def note(content: String, ref: String): Note = { - use(Git.open(testRepo)) { git => - git.notesAdd.setMessage(content).setNotesRef(Constants.R_NOTES + ref).setObjectId(CommitUtils.getHead(git.getRepository)).call - } - } ensuring (_ != null, "Unable to add note") - - /** - * Delete and commit file at path - * - * @param path - * @return commit - * - */ - protected def delete(path: String): RevCommit = { - val message = MessageFormat.format("Committing {0} at {1}", path, new Date) - use(Git.open(testRepo)) { git => - git.rm.addFilepattern(path).call - git.commit.setOnly(path).setMessage(message).setAuthor(author).setCommitter(committer).call - } - } ensuring (_ != null, "Unable to commit delete operation") - - /** - * commit specified content into a file, as committer - * - * @param committer - the author of this commit - * @param fileName - the name of the file - * @param content - the content of the file - * @param when - the date of the commit - * @return RevCommit - * - */ - protected def commit(committer: String, fileName: String, content: String, when: Date = new Date(), message: Option[String] = None): RevCommit = { - val person = newPersonIdent(committer, committer, when) - add(testRepo, fileName, content, author = person, committer = author, message = message.getOrElse("** no message **")) - } - - /** - * commit specified content into a file, as committer and merge into current branch - * - * @param committer - the author of this commit - * @param fileName - the name of the file - * @param content - the content of the file - * @return MergeResult - * - */ - protected def mergeCommit(committer: String, fileName: String, content: String): MergeResult = { - val currentBranch = Git.open(testRepo).getRepository.getBranch - val tmpBranch = branch(testRepo, "tmp") - try { - commit(committer, fileName, content) - checkout(currentBranch) - mergeBranch(tmpBranch.getName, withCommit = true) - } finally { - deleteBranch(testRepo, tmpBranch.getName) - } - } -} \ No newline at end of file
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/UserActivitySummarySpec.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/UserActivitySummarySpec.scala index de4d2f2..a783290 100644 --- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/UserActivitySummarySpec.scala +++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/UserActivitySummarySpec.scala
@@ -1,39 +1,45 @@ package com.googlesource.gerrit.plugins.analytics.test +import com.google.gerrit.acceptance.UseLocalDisk import com.googlesource.gerrit.plugins.analytics.UserActivitySummary import com.googlesource.gerrit.plugins.analytics.common.AggregationStrategy.EMAIL import com.googlesource.gerrit.plugins.analytics.common.{Statistics, TestUtils} -import org.eclipse.jgit.internal.storage.file.FileRepository +import org.eclipse.jgit.lib.Repository import org.scalatest.{FlatSpec, Matchers} -class UserActivitySummarySpec extends FlatSpec with GitTestCase with TestUtils with Matchers { +@UseLocalDisk +class UserActivitySummarySpec extends FlatSpec with GerritTestDaemon with TestUtils with Matchers { "numCommits" should "count only comments filtered by their merge status" in { val personEmail = "aCommitter@aCompany.com" // we want merge and non-merge commits to be authored by same person, so that they can be aggregated together - val repo = getRepoOwnedByPerson(personEmail) + val cloneRepo = testFileRepository.gitClone + getRepoOwnedByPerson(personEmail, repo = cloneRepo) - commit(personEmail, fileName="aFile.txt", content="some content") - mergeCommit(personEmail, fileName = "anotherFile.txt", content="some other content") + val personIdent = newPersonIdent("aPerson", personEmail) + cloneRepo.commitFile("aFile.txt", "some content", committer = personIdent, author = personIdent) + cloneRepo.mergeCommitFile("anotherFile.txt", "some other content", author = personIdent, committer = personIdent) + cloneRepo.push + val aggregatedCommits = aggregateBy(EMAIL) + val summary = UserActivitySummary.apply(new Statistics(fileRepository, TestBotLikeExtractor))(aggregatedCommits.head) - val List(nonMergeSummary, mergeSummary) = UserActivitySummary.apply(new Statistics(repo, TestBotLikeExtractor))(aggregatedCommits.head) + val nonMergeSummary = summary.head + val mergeSummary = summary.drop(1).head nonMergeSummary.numCommits should be(2) mergeSummary.numCommits should be(1) } - def getRepoOwnedByPerson(email: String = author.getEmailAddress): FileRepository = { - val repo = new FileRepository(testRepo) - - val conf = repo.getConfig + def getRepoOwnedByPerson(email: String = author.getEmailAddress, repo: TestFileRepository = testFileRepository): Repository = { + val conf = repo.getRepository.getConfig conf.load() conf.setString("user", null, "name", email) conf.setString("user", null, "email", email) conf.save() - repo + repo.getRepository } }