tree_diff_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. package plumbing
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "gopkg.in/src-d/go-git.v4/plumbing"
  6. "gopkg.in/src-d/go-git.v4/plumbing/object"
  7. "gopkg.in/src-d/go-git.v4/utils/merkletrie"
  8. "gopkg.in/src-d/hercules.v10/internal/core"
  9. "gopkg.in/src-d/hercules.v10/internal/test"
  10. )
  11. func fixtureTreeDiff() *TreeDiff {
  12. td := TreeDiff{}
  13. td.Configure(nil)
  14. td.Initialize(test.Repository)
  15. return &td
  16. }
  17. func TestTreeDiffMeta(t *testing.T) {
  18. td := fixtureTreeDiff()
  19. assert.Equal(t, td.Name(), "TreeDiff")
  20. assert.Equal(t, len(td.Requires()), 0)
  21. assert.Equal(t, len(td.Provides()), 1)
  22. assert.Equal(t, td.Provides()[0], DependencyTreeChanges)
  23. opts := td.ListConfigurationOptions()
  24. assert.Len(t, opts, 4)
  25. logger := core.NewLogger()
  26. assert.NoError(t, td.Configure(map[string]interface{}{
  27. core.ConfigLogger: logger,
  28. }))
  29. assert.Equal(t, logger, td.l)
  30. }
  31. func TestTreeDiffConfigure(t *testing.T) {
  32. td := fixtureTreeDiff()
  33. facts := map[string]interface{}{
  34. ConfigTreeDiffEnableBlacklist: true,
  35. ConfigTreeDiffBlacklistedPrefixes: []string{"vendor"},
  36. ConfigTreeDiffLanguages: []string{"go"},
  37. ConfigTreeDiffFilterRegexp: "_.*",
  38. }
  39. assert.Nil(t, td.Configure(facts))
  40. assert.Equal(t, td.Languages, map[string]bool{"go": true})
  41. assert.Equal(t, td.SkipFiles, []string{"vendor"})
  42. assert.Equal(t, td.NameFilter.String(), "_.*")
  43. delete(facts, ConfigTreeDiffLanguages)
  44. td.Languages = nil
  45. assert.Nil(t, td.Configure(facts))
  46. assert.Equal(t, td.Languages, map[string]bool{"all": true})
  47. td.SkipFiles = []string{"test"}
  48. delete(facts, ConfigTreeDiffEnableBlacklist)
  49. assert.Nil(t, td.Configure(facts))
  50. assert.Equal(t, td.SkipFiles, []string{"test"})
  51. }
  52. func TestTreeDiffRegistration(t *testing.T) {
  53. summoned := core.Registry.Summon((&TreeDiff{}).Name())
  54. assert.Len(t, summoned, 1)
  55. assert.Equal(t, summoned[0].Name(), "TreeDiff")
  56. summoned = core.Registry.Summon((&TreeDiff{}).Provides()[0])
  57. assert.True(t, len(summoned) >= 1)
  58. matched := false
  59. for _, tp := range summoned {
  60. matched = matched || tp.Name() == "TreeDiff"
  61. }
  62. assert.True(t, matched)
  63. }
  64. func TestTreeDiffConsume(t *testing.T) {
  65. td := fixtureTreeDiff()
  66. commit, _ := test.Repository.CommitObject(plumbing.NewHash(
  67. "2b1ed978194a94edeabbca6de7ff3b5771d4d665"))
  68. deps := map[string]interface{}{}
  69. deps[core.DependencyCommit] = commit
  70. prevCommit, _ := test.Repository.CommitObject(plumbing.NewHash(
  71. "fbe766ffdc3f87f6affddc051c6f8b419beea6a2"))
  72. td.previousTree, _ = prevCommit.Tree()
  73. res, err := td.Consume(deps)
  74. assert.NoError(t, err)
  75. assert.Equal(t, len(res), 1)
  76. changes := res[DependencyTreeChanges].(object.Changes)
  77. assert.Equal(t, len(changes), 12)
  78. baseline := map[string]merkletrie.Action{
  79. "analyser.go": merkletrie.Delete,
  80. "cmd/hercules/main.go": merkletrie.Modify,
  81. "blob_cache.go": merkletrie.Insert,
  82. "burndown.go": merkletrie.Insert,
  83. "day.go": merkletrie.Insert,
  84. "dummies.go": merkletrie.Insert,
  85. "identity.go": merkletrie.Insert,
  86. "pipeline.go": merkletrie.Insert,
  87. "renames.go": merkletrie.Insert,
  88. "toposort/toposort.go": merkletrie.Insert,
  89. "toposort/toposort_test.go": merkletrie.Insert,
  90. "tree_diff.go": merkletrie.Insert,
  91. }
  92. for _, change := range changes {
  93. action, err := change.Action()
  94. assert.NoError(t, err)
  95. if change.From.Name != "" {
  96. assert.Contains(t, baseline, change.From.Name)
  97. assert.Equal(t, baseline[change.From.Name], action)
  98. } else {
  99. assert.Contains(t, baseline, change.To.Name)
  100. assert.Equal(t, baseline[change.To.Name], action)
  101. }
  102. }
  103. }
  104. func TestTreeDiffConsumeFirst(t *testing.T) {
  105. td := fixtureTreeDiff()
  106. commit, _ := test.Repository.CommitObject(plumbing.NewHash(
  107. "2b1ed978194a94edeabbca6de7ff3b5771d4d665"))
  108. deps := map[string]interface{}{}
  109. deps[core.DependencyCommit] = commit
  110. res, err := td.Consume(deps)
  111. assert.NoError(t, err)
  112. assert.Equal(t, len(res), 1)
  113. changes := res[DependencyTreeChanges].(object.Changes)
  114. assert.Equal(t, len(changes), 21)
  115. for _, change := range changes {
  116. action, err := change.Action()
  117. assert.NoError(t, err)
  118. assert.Equal(t, action, merkletrie.Insert)
  119. }
  120. }
  121. func TestTreeDiffBadCommit(t *testing.T) {
  122. td := fixtureTreeDiff()
  123. commit, _ := test.Repository.CommitObject(plumbing.NewHash(
  124. "2b1ed978194a94edeabbca6de7ff3b5771d4d665"))
  125. commit.TreeHash = plumbing.NewHash("0000000000000000000000000000000000000000")
  126. deps := map[string]interface{}{}
  127. deps[core.DependencyCommit] = commit
  128. res, err := td.Consume(deps)
  129. assert.Nil(t, res)
  130. assert.NotNil(t, err)
  131. }
  132. func TestTreeDiffConsumeSkip(t *testing.T) {
  133. // consume without skipping
  134. td := fixtureTreeDiff()
  135. assert.Contains(t, td.Languages, allLanguages)
  136. commit, _ := test.Repository.CommitObject(plumbing.NewHash(
  137. "aefdedf7cafa6ee110bae9a3910bf5088fdeb5a9"))
  138. deps := map[string]interface{}{}
  139. deps[core.DependencyCommit] = commit
  140. prevCommit, _ := test.Repository.CommitObject(plumbing.NewHash(
  141. "1e076dc56989bc6aa1ef5f55901696e9e01423d4"))
  142. td.previousTree, _ = prevCommit.Tree()
  143. res, err := td.Consume(deps)
  144. assert.NoError(t, err)
  145. assert.Equal(t, len(res), 1)
  146. changes := res[DependencyTreeChanges].(object.Changes)
  147. assert.Equal(t, 37, len(changes))
  148. // consume with skipping
  149. td = fixtureTreeDiff()
  150. td.previousTree, _ = prevCommit.Tree()
  151. td.Configure(map[string]interface{}{
  152. ConfigTreeDiffEnableBlacklist: true,
  153. ConfigTreeDiffBlacklistedPrefixes: []string{"vendor/"},
  154. })
  155. res, err = td.Consume(deps)
  156. assert.NoError(t, err)
  157. assert.Equal(t, len(res), 1)
  158. changes = res[DependencyTreeChanges].(object.Changes)
  159. assert.Equal(t, 31, len(changes))
  160. }
  161. func TestTreeDiffConsumeOnlyFilesThatMatchFilter(t *testing.T) {
  162. // consume without skipping
  163. td := fixtureTreeDiff()
  164. assert.Contains(t, td.Languages, allLanguages)
  165. commit, _ := test.Repository.CommitObject(plumbing.NewHash(
  166. "aefdedf7cafa6ee110bae9a3910bf5088fdeb5a9"))
  167. deps := map[string]interface{}{}
  168. deps[core.DependencyCommit] = commit
  169. prevCommit, _ := test.Repository.CommitObject(plumbing.NewHash(
  170. "1e076dc56989bc6aa1ef5f55901696e9e01423d4"))
  171. td.previousTree, _ = prevCommit.Tree()
  172. res, err := td.Consume(deps)
  173. assert.NoError(t, err)
  174. assert.Equal(t, len(res), 1)
  175. changes := res[DependencyTreeChanges].(object.Changes)
  176. assert.Equal(t, 37, len(changes))
  177. // consume with skipping
  178. td = fixtureTreeDiff()
  179. td.previousTree, _ = prevCommit.Tree()
  180. td.Configure(map[string]interface{}{
  181. ConfigTreeDiffFilterRegexp: ".*go",
  182. })
  183. res, err = td.Consume(deps)
  184. assert.NoError(t, err)
  185. assert.Equal(t, len(res), 1)
  186. changes = res[DependencyTreeChanges].(object.Changes)
  187. assert.Equal(t, 27, len(changes))
  188. }
  189. func TestTreeDiffConsumeLanguageFilterFirst(t *testing.T) {
  190. td := fixtureTreeDiff()
  191. td.Configure(map[string]interface{}{ConfigTreeDiffLanguages: []string{"Go"}})
  192. commit, _ := test.Repository.CommitObject(plumbing.NewHash(
  193. "fbe766ffdc3f87f6affddc051c6f8b419beea6a2"))
  194. deps := map[string]interface{}{}
  195. deps[core.DependencyCommit] = commit
  196. res, err := td.Consume(deps)
  197. assert.NoError(t, err)
  198. assert.Equal(t, len(res), 1)
  199. changes := res[DependencyTreeChanges].(object.Changes)
  200. assert.Equal(t, len(changes), 6)
  201. assert.Equal(t, changes[0].To.Name, "analyser.go")
  202. assert.Equal(t, changes[1].To.Name, "cmd/hercules/main.go")
  203. assert.Equal(t, changes[2].To.Name, "doc.go")
  204. assert.Equal(t, changes[3].To.Name, "file.go")
  205. assert.Equal(t, changes[4].To.Name, "file_test.go")
  206. assert.Equal(t, changes[5].To.Name, "rbtree.go")
  207. }
  208. func TestTreeDiffConsumeLanguageFilter(t *testing.T) {
  209. td := fixtureTreeDiff()
  210. assert.NoError(t, td.Configure(map[string]interface{}{ConfigTreeDiffLanguages: []string{"Python"}}))
  211. commit, _ := test.Repository.CommitObject(plumbing.NewHash(
  212. "e89c1d10fb31e32668ad905eb59dc44d7a4a021e"))
  213. deps := map[string]interface{}{}
  214. deps[core.DependencyCommit] = commit
  215. res, err := td.Consume(deps)
  216. assert.NoError(t, err)
  217. assert.Equal(t, len(res), 1)
  218. commit, _ = test.Repository.CommitObject(plumbing.NewHash(
  219. "fbe766ffdc3f87f6affddc051c6f8b419beea6a2"))
  220. deps[core.DependencyCommit] = commit
  221. res, err = td.Consume(deps)
  222. assert.NoError(t, err)
  223. assert.Equal(t, len(res), 1)
  224. changes := res[DependencyTreeChanges].(object.Changes)
  225. assert.Equal(t, len(changes), 1)
  226. assert.Equal(t, changes[0].To.Name, "labours.py")
  227. // lowercase
  228. assert.NoError(t, td.Configure(map[string]interface{}{ConfigTreeDiffLanguages: []string{"python"}}))
  229. assert.NoError(t, err)
  230. assert.Equal(t, len(res), 1)
  231. changes = res[DependencyTreeChanges].(object.Changes)
  232. assert.Equal(t, len(changes), 1)
  233. assert.Equal(t, changes[0].To.Name, "labours.py")
  234. }
  235. func TestTreeDiffFork(t *testing.T) {
  236. td1 := fixtureTreeDiff()
  237. td1.SkipFiles = append(td1.SkipFiles, "skip")
  238. clones := td1.Fork(1)
  239. assert.Len(t, clones, 1)
  240. td2 := clones[0].(*TreeDiff)
  241. assert.False(t, td1 == td2)
  242. assert.Equal(t, td1.SkipFiles, td2.SkipFiles)
  243. assert.Equal(t, td1.previousTree, td2.previousTree)
  244. td1.Merge([]core.PipelineItem{td2})
  245. }
  246. func TestTreeDiffCheckLanguage(t *testing.T) {
  247. td := fixtureTreeDiff()
  248. lang, err := td.checkLanguage(
  249. "version.go", plumbing.NewHash("975f35a1412b8ae79b5ba2558f71f41e707fd5a9"))
  250. assert.NoError(t, err)
  251. assert.True(t, lang)
  252. td.Languages["go"] = true
  253. delete(td.Languages, allLanguages)
  254. lang, err = td.checkLanguage(
  255. "version.go", plumbing.NewHash("975f35a1412b8ae79b5ba2558f71f41e707fd5a9"))
  256. assert.NoError(t, err)
  257. assert.True(t, lang)
  258. }
  259. func TestTreeDiffConsumeEnryFilter(t *testing.T) {
  260. diffs := object.Changes{&object.Change{
  261. From: object.ChangeEntry{Name: ""},
  262. To: object.ChangeEntry{Name: "vendor/test.go"},
  263. }, &object.Change{
  264. From: object.ChangeEntry{Name: "vendor/test.go"},
  265. To: object.ChangeEntry{Name: ""},
  266. }}
  267. td := fixtureTreeDiff()
  268. newDiffs := td.filterDiffs(diffs)
  269. assert.Len(t, newDiffs, 2)
  270. assert.NoError(t, td.Configure(map[string]interface{}{
  271. ConfigTreeDiffEnableBlacklist: true,
  272. ConfigTreeDiffBlacklistedPrefixes: []string{"whatever"},
  273. }))
  274. newDiffs = td.filterDiffs(diffs)
  275. assert.Len(t, newDiffs, 0)
  276. }
  277. func TestTreeDiffCheckLanguageEmpty(t *testing.T) {
  278. td := fixtureTreeDiff()
  279. td.Languages["python"] = true
  280. delete(td.Languages, allLanguages)
  281. lang, err := td.checkLanguage(
  282. "__init__.py", plumbing.NewHash("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"))
  283. assert.NoError(t, err)
  284. assert.True(t, lang)
  285. }