typos_test.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // +build !disable_babelfish
  2. package research
  3. import (
  4. "bytes"
  5. "testing"
  6. "github.com/gogo/protobuf/proto"
  7. "github.com/stretchr/testify/assert"
  8. "gopkg.in/bblfsh/client-go.v3/tools"
  9. "gopkg.in/bblfsh/sdk.v2/uast"
  10. "gopkg.in/bblfsh/sdk.v2/uast/nodes"
  11. "gopkg.in/src-d/go-git.v4/plumbing"
  12. "gopkg.in/src-d/go-git.v4/plumbing/object"
  13. "gopkg.in/src-d/hercules.v10/internal/core"
  14. "gopkg.in/src-d/hercules.v10/internal/pb"
  15. items "gopkg.in/src-d/hercules.v10/internal/plumbing"
  16. uast_items "gopkg.in/src-d/hercules.v10/internal/plumbing/uast"
  17. "gopkg.in/src-d/hercules.v10/internal/test"
  18. )
  19. func TestTyposDatasetMeta(t *testing.T) {
  20. tdb := TyposDatasetBuilder{}
  21. assert.Equal(t, tdb.Name(), "TyposDataset")
  22. assert.Len(t, tdb.Provides(), 0)
  23. required := [...]string{
  24. uast_items.DependencyUastChanges, items.DependencyFileDiff, items.DependencyBlobCache}
  25. for _, name := range required {
  26. assert.Contains(t, tdb.Requires(), name)
  27. }
  28. opts := tdb.ListConfigurationOptions()
  29. assert.Len(t, opts, 1)
  30. assert.Equal(t, opts[0].Name, ConfigTyposDatasetMaximumAllowedDistance)
  31. assert.Equal(t, opts[0].Type, core.IntConfigurationOption)
  32. assert.Equal(t, tdb.Flag(), "typos-dataset")
  33. }
  34. func TestTyposDatasetRegistration(t *testing.T) {
  35. summoned := core.Registry.Summon((&TyposDatasetBuilder{}).Name())
  36. assert.Len(t, summoned, 1)
  37. assert.Equal(t, summoned[0].Name(), "TyposDataset")
  38. leaves := core.Registry.GetLeaves()
  39. matched := false
  40. for _, tp := range leaves {
  41. if tp.Flag() == (&TyposDatasetBuilder{}).Flag() {
  42. matched = true
  43. break
  44. }
  45. }
  46. assert.True(t, matched)
  47. }
  48. func TestTyposDatasetConfigure(t *testing.T) {
  49. tdb := TyposDatasetBuilder{}
  50. facts := map[string]interface{}{}
  51. facts[ConfigTyposDatasetMaximumAllowedDistance] = 5
  52. assert.Nil(t, tdb.Configure(facts))
  53. assert.Equal(t, tdb.MaximumAllowedDistance, 5)
  54. facts = map[string]interface{}{}
  55. assert.Nil(t, tdb.Configure(facts))
  56. assert.Equal(t, tdb.MaximumAllowedDistance, 5)
  57. }
  58. func AddHash(t *testing.T, cache map[plumbing.Hash]*items.CachedBlob, hash string) {
  59. objhash := plumbing.NewHash(hash)
  60. blob, err := test.Repository.BlobObject(objhash)
  61. assert.Nil(t, err)
  62. cb := &items.CachedBlob{Blob: *blob}
  63. err = cb.Cache()
  64. assert.Nil(t, err)
  65. cache[objhash] = cb
  66. }
  67. func bakeTyposDeps(t *testing.T) map[string]interface{} {
  68. deps := map[string]interface{}{}
  69. cache := map[plumbing.Hash]*items.CachedBlob{}
  70. AddHash(t, cache, "b9a12fd144274c99c7c9a0a32a0268f8b36d2f2c")
  71. AddHash(t, cache, "d5f8e61069136f3578457a3131800ede353527b8")
  72. AddHash(t, cache, "75bb0a09fc01db55d7322f0fae523453edba7846")
  73. deps[items.DependencyBlobCache] = cache
  74. changes := make(object.Changes, 2)
  75. treeFrom, _ := test.Repository.TreeObject(plumbing.NewHash(
  76. "eac25f9126db00e38fa72a59d49773a84580d4ce"))
  77. treeTo, _ := test.Repository.TreeObject(plumbing.NewHash(
  78. "828467b465864b1f757dcec9a034be49030fc8b9"))
  79. changes[0] = &object.Change{From: object.ChangeEntry{
  80. Name: "file_test.go",
  81. Tree: treeFrom,
  82. TreeEntry: object.TreeEntry{
  83. Name: "file_test.go",
  84. Mode: 0100644,
  85. Hash: plumbing.NewHash("75bb0a09fc01db55d7322f0fae523453edba7846"),
  86. },
  87. }, To: object.ChangeEntry{
  88. Name: "file_test.go",
  89. Tree: treeTo,
  90. TreeEntry: object.TreeEntry{
  91. Name: "file_test.go",
  92. Mode: 0100644,
  93. Hash: plumbing.NewHash("75bb0a09fc01db55d7322f0fae523453edba7846"),
  94. },
  95. }}
  96. changes[1] = &object.Change{From: object.ChangeEntry{}, To: object.ChangeEntry{
  97. Name: "blob_cache_test.go",
  98. Tree: treeTo,
  99. TreeEntry: object.TreeEntry{
  100. Name: "blob_cache_test.go",
  101. Mode: 0100644,
  102. Hash: plumbing.NewHash("b9a12fd144274c99c7c9a0a32a0268f8b36d2f2c"),
  103. },
  104. },
  105. }
  106. deps[items.DependencyTreeChanges] = changes
  107. deps[core.DependencyCommit], _ = test.Repository.CommitObject(plumbing.NewHash(
  108. "84165d3b02647fae12cc026c7a580045246e8c98"))
  109. deps[core.DependencyIsMerge] = false
  110. uastItem := &uast_items.Extractor{}
  111. assert.Nil(t, uastItem.Initialize(test.Repository))
  112. uastResult, err := uastItem.Consume(deps)
  113. assert.Nil(t, err)
  114. deps[uast_items.DependencyUasts] = uastResult[uast_items.DependencyUasts]
  115. uastChanges := &uast_items.Changes{}
  116. assert.Nil(t, uastChanges.Initialize(test.Repository))
  117. _, err = uastChanges.Consume(deps)
  118. assert.Nil(t, err)
  119. changes[0].To.TreeEntry.Hash = plumbing.NewHash("d5f8e61069136f3578457a3131800ede353527b8")
  120. uastResult, err = uastItem.Consume(deps)
  121. assert.Nil(t, err)
  122. deps[uast_items.DependencyUasts] = uastResult[uast_items.DependencyUasts]
  123. changesResult, err := uastChanges.Consume(deps)
  124. assert.Nil(t, err)
  125. deps[uast_items.DependencyUastChanges] = changesResult[uast_items.DependencyUastChanges]
  126. fd := &items.FileDiff{}
  127. assert.Nil(t, fd.Initialize(test.Repository))
  128. diffResult, err := fd.Consume(deps)
  129. assert.Nil(t, err)
  130. deps[items.DependencyFileDiff] = diffResult[items.DependencyFileDiff]
  131. return deps
  132. }
  133. func TestTyposDatasetConsume(t *testing.T) {
  134. deps := bakeTyposDeps(t)
  135. tbd := &TyposDatasetBuilder{}
  136. assert.Nil(t, tbd.Initialize(test.Repository))
  137. res, err := tbd.Consume(deps)
  138. assert.Nil(t, res)
  139. assert.Nil(t, err)
  140. assert.Len(t, tbd.typos, 26)
  141. assert.Equal(t, tbd.typos[0].Wrong, "TestInitialize")
  142. assert.Equal(t, tbd.typos[0].Correct, "TestInitializeFile")
  143. assert.Equal(t, tbd.typos[0].Commit, plumbing.NewHash(
  144. "84165d3b02647fae12cc026c7a580045246e8c98"))
  145. assert.Equal(t, tbd.typos[0].File, "file_test.go")
  146. assert.Equal(t, tbd.typos[0].Line, 19)
  147. deps[core.DependencyIsMerge] = true
  148. res, err = tbd.Consume(deps)
  149. assert.Nil(t, res)
  150. assert.Nil(t, err)
  151. assert.Len(t, tbd.typos, 26)
  152. }
  153. func dropPositions(root nodes.Node, target string) {
  154. for element := range tools.Iterate(tools.NewIterator(root, tools.PreOrder)) {
  155. obj, isobj := element.(nodes.Object)
  156. if !isobj {
  157. continue
  158. }
  159. nameval, exists := obj["Name"]
  160. if !exists {
  161. continue
  162. }
  163. if name, isstr := nameval.(nodes.String); !isstr || string(name) != target {
  164. continue
  165. }
  166. posval, exists := obj[uast.KeyPos]
  167. if !exists {
  168. continue
  169. }
  170. posobj, isobj := posval.(nodes.Object)
  171. if !isobj {
  172. continue
  173. }
  174. for k, v := range posobj {
  175. po, _ := v.(nodes.Object)
  176. if uast.AsPosition(po) != nil {
  177. posobj[k] = nil
  178. }
  179. }
  180. }
  181. }
  182. func TestTyposDatasetConsumeMissingPosition(t *testing.T) {
  183. deps := bakeTyposDeps(t)
  184. uastChanges := deps[uast_items.DependencyUastChanges].([]uast_items.Change)
  185. dropPositions(uastChanges[0].Before, "TestZeroInitialize")
  186. dropPositions(uastChanges[0].After, "TestZeroInitializeFile")
  187. tbd := &TyposDatasetBuilder{}
  188. assert.Nil(t, tbd.Initialize(test.Repository))
  189. res, err := tbd.Consume(deps)
  190. assert.Nil(t, res)
  191. assert.Nil(t, err)
  192. assert.Len(t, tbd.typos, 25)
  193. }
  194. func fixtureTyposDataset() *TyposDatasetBuilder {
  195. tdb := TyposDatasetBuilder{}
  196. tdb.Initialize(test.Repository)
  197. tdb.typos = append(tdb.typos, Typo{
  198. Wrong: "Fo",
  199. Correct: "Foo",
  200. Commit: plumbing.ZeroHash,
  201. File: "bar.go",
  202. Line: 7,
  203. })
  204. return &tdb
  205. }
  206. func TestTyposDatasetFinalize(t *testing.T) {
  207. tdb := fixtureTyposDataset()
  208. tdb.typos = append(tdb.typos, tdb.typos[0])
  209. x := tdb.Finalize().(TyposResult)
  210. assert.Len(t, x.Typos, 1)
  211. assert.Equal(t, x.Typos[0], Typo{
  212. Wrong: "Fo",
  213. Correct: "Foo",
  214. Commit: plumbing.ZeroHash,
  215. File: "bar.go",
  216. Line: 7,
  217. })
  218. }
  219. func TestTyposDatasetSerialize(t *testing.T) {
  220. ca := fixtureTyposDataset()
  221. res := ca.Finalize().(TyposResult)
  222. buffer := &bytes.Buffer{}
  223. err := ca.Serialize(res, false, buffer)
  224. assert.Nil(t, err)
  225. assert.Equal(t, ` - wrong: "Fo"
  226. correct: "Foo"
  227. commit: 0000000000000000000000000000000000000000
  228. file: "bar.go"
  229. line: 7
  230. `, buffer.String())
  231. buffer = &bytes.Buffer{}
  232. err = ca.Serialize(res, true, buffer)
  233. assert.Nil(t, err)
  234. msg := pb.TyposDataset{}
  235. assert.Nil(t, proto.Unmarshal(buffer.Bytes(), &msg))
  236. assert.Len(t, msg.Typos, 1)
  237. assert.Equal(t, *msg.Typos[0], pb.Typo{
  238. Wrong: "Fo",
  239. Correct: "Foo",
  240. Commit: "0000000000000000000000000000000000000000",
  241. File: "bar.go",
  242. Line: 7,
  243. })
  244. }