blob_cache_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. package hercules
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "gopkg.in/src-d/go-git.v4"
  6. "gopkg.in/src-d/go-git.v4/plumbing"
  7. "gopkg.in/src-d/go-git.v4/plumbing/object"
  8. )
  9. var testRepository *git.Repository
  10. func fixtureBlobCache() *BlobCache {
  11. cache := &BlobCache{}
  12. cache.Initialize(testRepository)
  13. return cache
  14. }
  15. func TestBlobCacheInitialize(t *testing.T) {
  16. cache := fixtureBlobCache()
  17. assert.Equal(t, testRepository, cache.repository)
  18. }
  19. func TestBlobCacheMetadata(t *testing.T) {
  20. cache := fixtureBlobCache()
  21. assert.Equal(t, cache.Name(), "BlobCache")
  22. assert.Equal(t, len(cache.Provides()), 1)
  23. assert.Equal(t, cache.Provides()[0], "blob_cache")
  24. assert.Equal(t, len(cache.Requires()), 1)
  25. changes := &TreeDiff{}
  26. assert.Equal(t, cache.Requires()[0], changes.Provides()[0])
  27. }
  28. func TestBlobCacheConsumeModification(t *testing.T) {
  29. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  30. "af2d8db70f287b52d2428d9887a69a10bc4d1f46"))
  31. changes := make(object.Changes, 1)
  32. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  33. "80fe25955b8e725feee25c08ea5759d74f8b670d"))
  34. treeTo, _ := testRepository.TreeObject(plumbing.NewHash(
  35. "63076fa0dfd93e94b6d2ef0fc8b1fdf9092f83c4"))
  36. changes[0] = &object.Change{From: object.ChangeEntry{
  37. Name: "labours.py",
  38. Tree: treeFrom,
  39. TreeEntry: object.TreeEntry{
  40. Name: "labours.py",
  41. Mode: 0100644,
  42. Hash: plumbing.NewHash("1cacfc1bf0f048eb2f31973750983ae5d8de647a"),
  43. },
  44. }, To: object.ChangeEntry{
  45. Name: "labours.py",
  46. Tree: treeTo,
  47. TreeEntry: object.TreeEntry{
  48. Name: "labours.py",
  49. Mode: 0100644,
  50. Hash: plumbing.NewHash("c872b8d2291a5224e2c9f6edd7f46039b96b4742"),
  51. },
  52. }}
  53. deps := map[string]interface{}{}
  54. deps["commit"] = commit
  55. deps["changes"] = changes
  56. result, err := fixtureBlobCache().Consume(deps)
  57. assert.Nil(t, err)
  58. assert.Equal(t, len(result), 1)
  59. cacheIface, exists := result["blob_cache"]
  60. assert.True(t, exists)
  61. cache := cacheIface.(map[plumbing.Hash]*object.Blob)
  62. assert.Equal(t, len(cache), 2)
  63. blobFrom, exists := cache[plumbing.NewHash("1cacfc1bf0f048eb2f31973750983ae5d8de647a")]
  64. assert.True(t, exists)
  65. blobTo, exists := cache[plumbing.NewHash("c872b8d2291a5224e2c9f6edd7f46039b96b4742")]
  66. assert.True(t, exists)
  67. assert.Equal(t, blobFrom.Size, int64(8969))
  68. assert.Equal(t, blobTo.Size, int64(9481))
  69. }
  70. func TestBlobCacheConsumeInsertionDeletion(t *testing.T) {
  71. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  72. "2b1ed978194a94edeabbca6de7ff3b5771d4d665"))
  73. changes := make(object.Changes, 2)
  74. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  75. "96c6ece9b2f3c7c51b83516400d278dea5605100"))
  76. treeTo, _ := testRepository.TreeObject(plumbing.NewHash(
  77. "251f2094d7b523d5bcc60e663b6cf38151bf8844"))
  78. changes[0] = &object.Change{From: object.ChangeEntry{
  79. Name: "analyser.go",
  80. Tree: treeFrom,
  81. TreeEntry: object.TreeEntry{
  82. Name: "analyser.go",
  83. Mode: 0100644,
  84. Hash: plumbing.NewHash("baa64828831d174f40140e4b3cfa77d1e917a2c1"),
  85. },
  86. }, To: object.ChangeEntry{},
  87. }
  88. changes[1] = &object.Change{From: object.ChangeEntry{}, To: object.ChangeEntry{
  89. Name: "pipeline.go",
  90. Tree: treeTo,
  91. TreeEntry: object.TreeEntry{
  92. Name: "pipeline.go",
  93. Mode: 0100644,
  94. Hash: plumbing.NewHash("db99e1890f581ad69e1527fe8302978c661eb473"),
  95. },
  96. },
  97. }
  98. deps := map[string]interface{}{}
  99. deps["commit"] = commit
  100. deps["changes"] = changes
  101. result, err := fixtureBlobCache().Consume(deps)
  102. assert.Nil(t, err)
  103. assert.Equal(t, len(result), 1)
  104. cacheIface, exists := result["blob_cache"]
  105. assert.True(t, exists)
  106. cache := cacheIface.(map[plumbing.Hash]*object.Blob)
  107. assert.Equal(t, len(cache), 2)
  108. blobFrom, exists := cache[plumbing.NewHash("baa64828831d174f40140e4b3cfa77d1e917a2c1")]
  109. assert.True(t, exists)
  110. blobTo, exists := cache[plumbing.NewHash("db99e1890f581ad69e1527fe8302978c661eb473")]
  111. assert.True(t, exists)
  112. assert.Equal(t, blobFrom.Size, int64(26446))
  113. assert.Equal(t, blobTo.Size, int64(5576))
  114. }
  115. func TestBlobCacheConsumeNoAction(t *testing.T) {
  116. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  117. "af2d8db70f287b52d2428d9887a69a10bc4d1f46"))
  118. changes := make(object.Changes, 1)
  119. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  120. "80fe25955b8e725feee25c08ea5759d74f8b670d"))
  121. treeTo, _ := testRepository.TreeObject(plumbing.NewHash(
  122. "63076fa0dfd93e94b6d2ef0fc8b1fdf9092f83c4"))
  123. changes[0] = &object.Change{From: object.ChangeEntry{}, To: object.ChangeEntry{}}
  124. deps := map[string]interface{}{}
  125. deps["commit"] = commit
  126. deps["changes"] = changes
  127. result, err := fixtureBlobCache().Consume(deps)
  128. assert.Nil(t, result)
  129. assert.NotNil(t, err)
  130. changes[0] = &object.Change{From: object.ChangeEntry{
  131. Name: "labours.py",
  132. Tree: treeFrom,
  133. TreeEntry: object.TreeEntry{},
  134. }, To: object.ChangeEntry{
  135. Name: "labours.py",
  136. Tree: treeTo,
  137. TreeEntry: object.TreeEntry{},
  138. }}
  139. result, err = fixtureBlobCache().Consume(deps)
  140. assert.Nil(t, result)
  141. assert.NotNil(t, err)
  142. }
  143. func TestBlobCacheConsumeBadHashes(t *testing.T) {
  144. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  145. "af2d8db70f287b52d2428d9887a69a10bc4d1f46"))
  146. changes := make(object.Changes, 1)
  147. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  148. "80fe25955b8e725feee25c08ea5759d74f8b670d"))
  149. treeTo, _ := testRepository.TreeObject(plumbing.NewHash(
  150. "63076fa0dfd93e94b6d2ef0fc8b1fdf9092f83c4"))
  151. changes[0] = &object.Change{From: object.ChangeEntry{
  152. Name: "labours.py",
  153. Tree: treeFrom,
  154. TreeEntry: object.TreeEntry{},
  155. }, To: object.ChangeEntry{
  156. Name: "labours.py",
  157. Tree: treeTo,
  158. TreeEntry: object.TreeEntry{},
  159. }}
  160. deps := map[string]interface{}{}
  161. deps["commit"] = commit
  162. deps["changes"] = changes
  163. result, err := fixtureBlobCache().Consume(deps)
  164. assert.Nil(t, result)
  165. assert.NotNil(t, err)
  166. changes[0] = &object.Change{From: object.ChangeEntry{
  167. Name: "labours.py",
  168. Tree: treeFrom,
  169. TreeEntry: object.TreeEntry{},
  170. }, To: object.ChangeEntry{}}
  171. result, err = fixtureBlobCache().Consume(deps)
  172. // Deleting a missing blob is fine
  173. assert.NotNil(t, result)
  174. assert.Nil(t, err)
  175. changes[0] = &object.Change{From: object.ChangeEntry{},
  176. To: object.ChangeEntry{
  177. Name: "labours.py",
  178. Tree: treeTo,
  179. TreeEntry: object.TreeEntry{},
  180. }}
  181. result, err = fixtureBlobCache().Consume(deps)
  182. assert.Nil(t, result)
  183. assert.NotNil(t, err)
  184. }
  185. func TestBlobCacheConsumeInvalidHash(t *testing.T) {
  186. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  187. "af2d8db70f287b52d2428d9887a69a10bc4d1f46"))
  188. changes := make(object.Changes, 1)
  189. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  190. "80fe25955b8e725feee25c08ea5759d74f8b670d"))
  191. treeTo, _ := testRepository.TreeObject(plumbing.NewHash(
  192. "63076fa0dfd93e94b6d2ef0fc8b1fdf9092f83c4"))
  193. changes[0] = &object.Change{From: object.ChangeEntry{
  194. Name: "labours.py",
  195. Tree: treeFrom,
  196. TreeEntry: object.TreeEntry{
  197. Name: "labours.py",
  198. Mode: 0100644,
  199. Hash: plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff"),
  200. },
  201. }, To: object.ChangeEntry{
  202. Name: "labours.py",
  203. Tree: treeTo,
  204. TreeEntry: object.TreeEntry{},
  205. }}
  206. deps := map[string]interface{}{}
  207. deps["commit"] = commit
  208. deps["changes"] = changes
  209. result, err := fixtureBlobCache().Consume(deps)
  210. assert.Nil(t, result)
  211. assert.NotNil(t, err)
  212. }
  213. func TestBlobCacheFinalize(t *testing.T) {
  214. outcome := fixtureBlobCache().Finalize()
  215. assert.Nil(t, outcome)
  216. }
  217. func TestBlobCacheGetBlob(t *testing.T) {
  218. cache := fixtureBlobCache()
  219. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  220. "80fe25955b8e725feee25c08ea5759d74f8b670d"))
  221. entry := object.ChangeEntry{
  222. Name: "labours.py",
  223. Tree: treeFrom,
  224. TreeEntry: object.TreeEntry{
  225. Name: "labours.py",
  226. Mode: 0100644,
  227. Hash: plumbing.NewHash("80fe25955b8e725feee25c08ea5759d74f8b670d"),
  228. },
  229. }
  230. getter := func(path string) (*object.File, error) {
  231. assert.Equal(t, path, ".gitmodules")
  232. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  233. "13272b66c55e1ba1237a34104f30b84d7f6e4082"))
  234. return commit.File("test_data/gitmodules")
  235. }
  236. blob, err := cache.getBlob(&entry, getter)
  237. assert.Nil(t, blob)
  238. assert.NotNil(t, err)
  239. assert.Equal(t, err.Error(), plumbing.ErrObjectNotFound.Error())
  240. getter = func(path string) (*object.File, error) {
  241. assert.Equal(t, path, ".gitmodules")
  242. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  243. "13272b66c55e1ba1237a34104f30b84d7f6e4082"))
  244. return commit.File("test_data/gitmodules_empty")
  245. }
  246. blob, err = cache.getBlob(&entry, getter)
  247. assert.Nil(t, blob)
  248. assert.NotNil(t, err)
  249. assert.Equal(t, err.Error(), plumbing.ErrObjectNotFound.Error())
  250. }
  251. func TestBlobCacheDeleteInvalidBlob(t *testing.T) {
  252. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  253. "2b1ed978194a94edeabbca6de7ff3b5771d4d665"))
  254. changes := make(object.Changes, 1)
  255. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  256. "96c6ece9b2f3c7c51b83516400d278dea5605100"))
  257. changes[0] = &object.Change{From: object.ChangeEntry{
  258. Name: "analyser.go",
  259. Tree: treeFrom,
  260. TreeEntry: object.TreeEntry{
  261. Name: "analyser.go",
  262. Mode: 0100644,
  263. Hash: plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff"),
  264. },
  265. }, To: object.ChangeEntry{},
  266. }
  267. deps := map[string]interface{}{}
  268. deps["commit"] = commit
  269. deps["changes"] = changes
  270. result, err := fixtureBlobCache().Consume(deps)
  271. assert.Nil(t, err)
  272. assert.Equal(t, len(result), 1)
  273. cacheIface, exists := result["blob_cache"]
  274. assert.True(t, exists)
  275. cache := cacheIface.(map[plumbing.Hash]*object.Blob)
  276. assert.Equal(t, len(cache), 1)
  277. blobFrom, exists := cache[plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff")]
  278. assert.True(t, exists)
  279. assert.Equal(t, blobFrom.Size, int64(0))
  280. }
  281. func TestBlobCacheInsertInvalidBlob(t *testing.T) {
  282. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  283. "2b1ed978194a94edeabbca6de7ff3b5771d4d665"))
  284. changes := make(object.Changes, 1)
  285. treeTo, _ := testRepository.TreeObject(plumbing.NewHash(
  286. "251f2094d7b523d5bcc60e663b6cf38151bf8844"))
  287. changes[0] = &object.Change{From: object.ChangeEntry{}, To: object.ChangeEntry{
  288. Name: "pipeline.go",
  289. Tree: treeTo,
  290. TreeEntry: object.TreeEntry{
  291. Name: "pipeline.go",
  292. Mode: 0100644,
  293. Hash: plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff"),
  294. },
  295. },
  296. }
  297. deps := map[string]interface{}{}
  298. deps["commit"] = commit
  299. deps["changes"] = changes
  300. result, err := fixtureBlobCache().Consume(deps)
  301. assert.NotNil(t, err)
  302. assert.Equal(t, len(result), 0)
  303. }
  304. func TestBlobCacheGetBlobIgnoreMissing(t *testing.T) {
  305. cache := fixtureBlobCache()
  306. cache.IgnoreMissingSubmodules = true
  307. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  308. "80fe25955b8e725feee25c08ea5759d74f8b670d"))
  309. entry := object.ChangeEntry{
  310. Name: "commit",
  311. Tree: treeFrom,
  312. TreeEntry: object.TreeEntry{
  313. Name: "commit",
  314. Mode: 0160000,
  315. Hash: plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff"),
  316. },
  317. }
  318. getter := func(path string) (*object.File, error) {
  319. return nil, plumbing.ErrObjectNotFound
  320. }
  321. blob, err := cache.getBlob(&entry, getter)
  322. assert.NotNil(t, blob)
  323. assert.Nil(t, err)
  324. assert.Equal(t, blob.Size, int64(0))
  325. cache.IgnoreMissingSubmodules = false
  326. getter = func(path string) (*object.File, error) {
  327. assert.Equal(t, path, ".gitmodules")
  328. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  329. "13272b66c55e1ba1237a34104f30b84d7f6e4082"))
  330. return commit.File("test_data/gitmodules")
  331. }
  332. blob, err = cache.getBlob(&entry, getter)
  333. assert.Nil(t, blob)
  334. assert.NotNil(t, err)
  335. }