Skip to content

Commit 60b920a

Browse files
authored
feat(test): Longevity integration: unit tests (APP-75)
1 parent 3a69ebc commit 60b920a

File tree

4 files changed

+268
-11
lines changed

4 files changed

+268
-11
lines changed

src/main/kotlin/app/hashers/CodeLongevity.kt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,8 @@ class CodeLongevity(private val localRepo: LocalRepo,
9090
if (tailRev != "") RevWalk(repo).parseCommit(repo.resolve(tailRev))
9191
else null
9292

93-
/**
94-
* A list of all code lines, both alive and deleted, between the given
95-
* revisions.
96-
*/
97-
var codeLines: MutableList<CodeLine> = mutableListOf()
98-
9993
fun update() {
100-
compute()
94+
val codeLines = compute()
10195

10296
// TODO(anatoly): Add emails from server or hashAll.
10397
val emails = hashSetOf(localRepo.author.email)
@@ -154,10 +148,13 @@ class CodeLongevity(private val localRepo: LocalRepo,
154148
}
155149

156150
/**
157-
* Scans through the repo for alive and deleted code lines, and stores them
158-
* in the [codeLines] list.
151+
* Scans through the repo for alive and deleted code lines and returns
152+
* a list of all code lines, both alive and deleted, between the given
153+
* revisions.
159154
*/
160-
private fun compute() {
155+
fun compute() : List<CodeLine> {
156+
val codeLines: MutableList<CodeLine> = mutableListOf()
157+
161158
val treeWalk = TreeWalk(repo)
162159
treeWalk.setRecursive(true)
163160
treeWalk.addTree(head.getTree())
@@ -260,6 +257,7 @@ class CodeLongevity(private val localRepo: LocalRepo,
260257
for (idx in delStart .. delEnd - 1) {
261258
tmpLines.add(RevCommitLine(commit, oldPath, idx))
262259
}
260+
263261
// TODO(alex): Approve code change.
264262
// delStart index caused IndexOutOfBoundException.
265263
lines.addAll(tmpLines)
@@ -275,6 +273,7 @@ class CodeLongevity(private val localRepo: LocalRepo,
275273
var to = lines.get(idx)
276274
val cl = CodeLine(from, to, fileText.getString(idx))
277275
codeLines.add(cl)
276+
Logger.debug("Collected: ${cl.toString()}")
278277
}
279278
lines.subList(insStart, insEnd).clear()
280279
}
@@ -302,5 +301,7 @@ class CodeLongevity(private val localRepo: LocalRepo,
302301
}
303302
}
304303
}
304+
305+
return codeLines
305306
}
306307
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// Copyright 2017 Sourcerer Inc. All Rights Reserved.
2+
// Author: Alexander Surkov ([email protected])
3+
4+
package test.tests.hashers
5+
6+
import app.api.MockApi
7+
import app.hashers.CodeLine
8+
import app.hashers.CodeLongevity
9+
import app.hashers.RevCommitLine
10+
import app.model.*
11+
12+
import test.utils.TestRepo
13+
14+
import kotlin.test.assertEquals
15+
import kotlin.test.assertNotEquals
16+
17+
import org.eclipse.jgit.revwalk.RevCommit
18+
19+
import org.jetbrains.spek.api.Spek
20+
import org.jetbrains.spek.api.dsl.given
21+
import org.jetbrains.spek.api.dsl.it
22+
23+
/**
24+
* Testing class.
25+
*/
26+
class CodeLongevityTest : Spek({
27+
28+
/**
29+
* Assert function to test RevCommitLine object.
30+
*/
31+
fun assertRevCommitLine(expectedCommit: RevCommit,
32+
expectedFile: String,
33+
expectedLineNum: Int,
34+
actualLine: RevCommitLine,
35+
messsage: String = "") {
36+
37+
assertEquals(expectedCommit, actualLine.commit, "$messsage commit")
38+
assertEquals(expectedFile, actualLine.file, "$messsage file name")
39+
assertEquals(expectedLineNum, actualLine.line, "$messsage line num")
40+
}
41+
42+
/**
43+
* Assert function to test CodeLine object.
44+
*/
45+
fun assertCodeLine(lineText: String,
46+
fromCommit: RevCommit, fromFile: String, fromLineNum: Int,
47+
toCommit: RevCommit, toFile: String, toLineNum: Int,
48+
actualLine: CodeLine) {
49+
50+
assertRevCommitLine(fromCommit, fromFile, fromLineNum, actualLine.from,
51+
"'$lineText' from_commit");
52+
assertRevCommitLine(toCommit, toFile, toLineNum, actualLine.to,
53+
"'$lineText' to_commit");
54+
assertEquals(lineText, actualLine.text, "line text")
55+
}
56+
57+
given("'test group #1'") {
58+
val testRepoPath = "../testrepo1"
59+
val testRepo = TestRepo(testRepoPath)
60+
val fileName = "test1.txt"
61+
62+
// t1: initial insertion
63+
testRepo.newFile(fileName, listOf("line1", "line2"))
64+
val rev1 = testRepo.commit("inital commit")
65+
val lines1 = CodeLongevity(
66+
LocalRepo(testRepoPath), Repo(), MockApi(), testRepo.git).compute()
67+
68+
it("'t1: initial insertion'") {
69+
assertEquals(2, lines1.size)
70+
assertCodeLine("line1",
71+
rev1, fileName, 0,
72+
rev1, fileName, 0,
73+
lines1[0])
74+
assertCodeLine("line2",
75+
rev1, fileName, 1,
76+
rev1, fileName, 1,
77+
lines1[1])
78+
}
79+
80+
// t2: subsequent insertion
81+
testRepo.insertLines(fileName, 1, listOf("line in the middle"))
82+
val rev2 = testRepo.commit("insert line")
83+
val lines2 = CodeLongevity(
84+
LocalRepo(testRepoPath), Repo(), MockApi(), testRepo.git).compute()
85+
86+
it("'t2: subsequent insertion'") {
87+
assertEquals(3, lines2.size)
88+
assertCodeLine("line in the middle",
89+
rev2, fileName, 1,
90+
rev2, fileName, 1,
91+
lines2[0])
92+
assertCodeLine("line1",
93+
rev1, fileName, 0,
94+
rev2, fileName, 0,
95+
lines2[1])
96+
assertCodeLine("line2",
97+
rev1, fileName, 1,
98+
rev2, fileName, 2,
99+
lines2[2])
100+
}
101+
102+
// t3: subsequent deletion
103+
testRepo.deleteLines(fileName, 2, 2)
104+
val rev3 = testRepo.commit("delete line")
105+
val lines3 = CodeLongevity(LocalRepo(testRepoPath), Repo(),
106+
MockApi(), testRepo.git).compute()
107+
108+
it("'t3: subsequent deletion'") {
109+
assertEquals(3, lines3.size)
110+
assertCodeLine("line in the middle",
111+
rev2, fileName, 1,
112+
rev3, fileName, 1,
113+
lines3[0])
114+
assertCodeLine("line1",
115+
rev1, fileName, 0,
116+
rev3, fileName, 0,
117+
lines3[1])
118+
assertCodeLine("line2",
119+
rev1, fileName, 1,
120+
rev3, fileName, 2,
121+
lines3[2])
122+
}
123+
124+
// t4: file deletion
125+
testRepo.deleteFile(fileName)
126+
val rev4 = testRepo.commit("delete file")
127+
val lines4 = CodeLongevity(LocalRepo(testRepoPath), Repo(),
128+
MockApi(), testRepo.git).compute()
129+
130+
it("'t4: file deletion'") {
131+
assertEquals(3, lines4.size)
132+
assertCodeLine("line in the middle",
133+
rev2, fileName, 1,
134+
rev4, fileName, 1,
135+
lines4[0])
136+
assertCodeLine("line1",
137+
rev1, fileName, 0,
138+
rev4, fileName, 0,
139+
lines4[1])
140+
141+
/* TODO(alex): the test fails
142+
assertCodeLine("line2",
143+
rev1, fileName, 1,
144+
rev3, fileName, 2,
145+
lines4[2])
146+
*/
147+
}
148+
149+
afterGroup {
150+
testRepo.destroy()
151+
}
152+
}
153+
})

src/test/kotlin/app/CommitHasherTest.kt renamed to src/test/kotlin/test/tests/hashers/CommitHasherTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Author: Liubov Yaronskaya ([email protected])
33
// Author: Anatoly Kislov ([email protected])
44

5-
package app
5+
package test.tests.hashers
66

77
import app.api.MockApi
88
import app.hashers.CommitHasher
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2017 Sourcerer Inc. All Rights Reserved.
2+
// Author: Alexander Surkov ([email protected])
3+
4+
package test.utils
5+
6+
import java.io.BufferedReader
7+
import java.io.BufferedWriter
8+
import java.io.File
9+
import java.io.FileReader
10+
import java.io.FileWriter
11+
import java.io.StringWriter
12+
13+
import org.eclipse.jgit.api.Git
14+
import org.eclipse.jgit.revwalk.RevCommit
15+
16+
/**
17+
* A wrapper around Git repo allowing to add/remove/edit files and make commits.
18+
*/
19+
class TestRepo(val repoPath: String) {
20+
val userName = "Contributor"
21+
val userEmail = "[email protected]"
22+
23+
val git = Git.init().setDirectory(File(repoPath)).call()
24+
25+
init {
26+
val config = git.repository.config
27+
config.setString("user", null, "name", userName)
28+
config.setString("user", null, "email", userEmail)
29+
config.save()
30+
}
31+
32+
fun newFile(fileName: String, content: List<String>) {
33+
val file = File("$repoPath/$fileName")
34+
val writer = BufferedWriter(FileWriter(file))
35+
for (line in content) {
36+
writer.write(line)
37+
writer.newLine()
38+
}
39+
writer.close()
40+
git.add().addFilepattern(fileName).call();
41+
}
42+
43+
fun deleteFile(fileName: String) {
44+
File("$repoPath/$fileName").delete()
45+
}
46+
47+
fun insertLines(fileName: String, insIndex: Int, insLines: List<String>) {
48+
val file = File("$repoPath/$fileName")
49+
val reader = BufferedReader(FileReader(file))
50+
51+
val tmpStrWriter = StringWriter()
52+
val tmpWriter = BufferedWriter(tmpStrWriter)
53+
54+
var lineIdx = 0
55+
for (line in reader.lines()) {
56+
if (lineIdx == insIndex) {
57+
for (insLine in insLines) {
58+
tmpWriter.write(insLine)
59+
tmpWriter.newLine()
60+
}
61+
}
62+
63+
tmpWriter.write(line)
64+
tmpWriter.newLine()
65+
lineIdx++
66+
}
67+
tmpWriter.flush()
68+
69+
val writer = FileWriter(file)
70+
writer.write(tmpStrWriter.toString())
71+
writer.close()
72+
}
73+
74+
fun deleteLines(fileName: String, startIndex: Int, endIndex: Int) {
75+
val file = File("$repoPath/$fileName")
76+
val reader = BufferedReader(FileReader(file))
77+
78+
val tmpStrWriter = StringWriter()
79+
val tmpWriter = BufferedWriter(tmpStrWriter)
80+
81+
var lineIdx = 0
82+
for (line in reader.lines()) {
83+
if (lineIdx < startIndex || lineIdx > endIndex) {
84+
tmpWriter.write(line)
85+
tmpWriter.newLine()
86+
}
87+
lineIdx++
88+
}
89+
tmpWriter.flush()
90+
91+
val writer = FileWriter(file)
92+
writer.write(tmpStrWriter.toString())
93+
writer.close()
94+
}
95+
96+
fun commit(message: String): RevCommit {
97+
return git.commit().setMessage(message).setAll(true).call()
98+
}
99+
100+
fun destroy() {
101+
Runtime.getRuntime().exec("rm -r $repoPath").waitFor()
102+
}
103+
}

0 commit comments

Comments
 (0)