blob_cache_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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 TestBlobCacheGetBlob(t *testing.T) {
  214. cache := fixtureBlobCache()
  215. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  216. "80fe25955b8e725feee25c08ea5759d74f8b670d"))
  217. entry := object.ChangeEntry{
  218. Name: "labours.py",
  219. Tree: treeFrom,
  220. TreeEntry: object.TreeEntry{
  221. Name: "labours.py",
  222. Mode: 0100644,
  223. Hash: plumbing.NewHash("80fe25955b8e725feee25c08ea5759d74f8b670d"),
  224. },
  225. }
  226. getter := func(path string) (*object.File, error) {
  227. assert.Equal(t, path, ".gitmodules")
  228. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  229. "13272b66c55e1ba1237a34104f30b84d7f6e4082"))
  230. return commit.File("test_data/gitmodules")
  231. }
  232. blob, err := cache.getBlob(&entry, getter)
  233. assert.Nil(t, blob)
  234. assert.NotNil(t, err)
  235. assert.Equal(t, err.Error(), plumbing.ErrObjectNotFound.Error())
  236. getter = func(path string) (*object.File, error) {
  237. assert.Equal(t, path, ".gitmodules")
  238. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  239. "13272b66c55e1ba1237a34104f30b84d7f6e4082"))
  240. return commit.File("test_data/gitmodules_empty")
  241. }
  242. blob, err = cache.getBlob(&entry, getter)
  243. assert.Nil(t, blob)
  244. assert.NotNil(t, err)
  245. assert.Equal(t, err.Error(), plumbing.ErrObjectNotFound.Error())
  246. }
  247. func TestBlobCacheDeleteInvalidBlob(t *testing.T) {
  248. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  249. "2b1ed978194a94edeabbca6de7ff3b5771d4d665"))
  250. changes := make(object.Changes, 1)
  251. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  252. "96c6ece9b2f3c7c51b83516400d278dea5605100"))
  253. changes[0] = &object.Change{From: object.ChangeEntry{
  254. Name: "analyser.go",
  255. Tree: treeFrom,
  256. TreeEntry: object.TreeEntry{
  257. Name: "analyser.go",
  258. Mode: 0100644,
  259. Hash: plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff"),
  260. },
  261. }, To: object.ChangeEntry{},
  262. }
  263. deps := map[string]interface{}{}
  264. deps["commit"] = commit
  265. deps["changes"] = changes
  266. result, err := fixtureBlobCache().Consume(deps)
  267. assert.Nil(t, err)
  268. assert.Equal(t, len(result), 1)
  269. cacheIface, exists := result["blob_cache"]
  270. assert.True(t, exists)
  271. cache := cacheIface.(map[plumbing.Hash]*object.Blob)
  272. assert.Equal(t, len(cache), 1)
  273. blobFrom, exists := cache[plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff")]
  274. assert.True(t, exists)
  275. assert.Equal(t, blobFrom.Size, int64(0))
  276. }
  277. func TestBlobCacheInsertInvalidBlob(t *testing.T) {
  278. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  279. "2b1ed978194a94edeabbca6de7ff3b5771d4d665"))
  280. changes := make(object.Changes, 1)
  281. treeTo, _ := testRepository.TreeObject(plumbing.NewHash(
  282. "251f2094d7b523d5bcc60e663b6cf38151bf8844"))
  283. changes[0] = &object.Change{From: object.ChangeEntry{}, To: object.ChangeEntry{
  284. Name: "pipeline.go",
  285. Tree: treeTo,
  286. TreeEntry: object.TreeEntry{
  287. Name: "pipeline.go",
  288. Mode: 0100644,
  289. Hash: plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff"),
  290. },
  291. },
  292. }
  293. deps := map[string]interface{}{}
  294. deps["commit"] = commit
  295. deps["changes"] = changes
  296. result, err := fixtureBlobCache().Consume(deps)
  297. assert.NotNil(t, err)
  298. assert.Equal(t, len(result), 0)
  299. }
  300. func TestBlobCacheGetBlobIgnoreMissing(t *testing.T) {
  301. cache := fixtureBlobCache()
  302. cache.IgnoreMissingSubmodules = true
  303. treeFrom, _ := testRepository.TreeObject(plumbing.NewHash(
  304. "80fe25955b8e725feee25c08ea5759d74f8b670d"))
  305. entry := object.ChangeEntry{
  306. Name: "commit",
  307. Tree: treeFrom,
  308. TreeEntry: object.TreeEntry{
  309. Name: "commit",
  310. Mode: 0160000,
  311. Hash: plumbing.NewHash("ffffffffffffffffffffffffffffffffffffffff"),
  312. },
  313. }
  314. getter := func(path string) (*object.File, error) {
  315. return nil, plumbing.ErrObjectNotFound
  316. }
  317. blob, err := cache.getBlob(&entry, getter)
  318. assert.NotNil(t, blob)
  319. assert.Nil(t, err)
  320. assert.Equal(t, blob.Size, int64(0))
  321. cache.IgnoreMissingSubmodules = false
  322. getter = func(path string) (*object.File, error) {
  323. assert.Equal(t, path, ".gitmodules")
  324. commit, _ := testRepository.CommitObject(plumbing.NewHash(
  325. "13272b66c55e1ba1237a34104f30b84d7f6e4082"))
  326. return commit.File("test_data/gitmodules")
  327. }
  328. blob, err = cache.getBlob(&entry, getter)
  329. assert.Nil(t, blob)
  330. assert.NotNil(t, err)
  331. }