2
0

test_object_store.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. # test_object_store.py -- tests for object_store.py
  2. # Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU General Public License
  6. # as published by the Free Software Foundation; version 2
  7. # or (at your option) any later version of the License.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  17. # MA 02110-1301, USA.
  18. """Tests for the object store interface."""
  19. import os
  20. import shutil
  21. import tempfile
  22. from dulwich.index import (
  23. commit_tree,
  24. )
  25. from dulwich.errors import (
  26. NotTreeError,
  27. )
  28. from dulwich.objects import (
  29. object_class,
  30. Blob,
  31. ShaFile,
  32. Tag,
  33. Tree,
  34. TreeEntry,
  35. )
  36. from dulwich.object_store import (
  37. DiskObjectStore,
  38. MemoryObjectStore,
  39. tree_lookup_path,
  40. )
  41. from dulwich.pack import (
  42. write_pack_data,
  43. )
  44. from dulwich.tests import (
  45. TestCase,
  46. )
  47. from utils import (
  48. make_object,
  49. )
  50. testobject = make_object(Blob, data="yummy data")
  51. class ObjectStoreTests(object):
  52. def test_iter(self):
  53. self.assertEquals([], list(self.store))
  54. def test_get_nonexistant(self):
  55. self.assertRaises(KeyError, lambda: self.store["a" * 40])
  56. def test_contains_nonexistant(self):
  57. self.assertFalse(("a" * 40) in self.store)
  58. def test_add_objects_empty(self):
  59. self.store.add_objects([])
  60. def test_add_commit(self):
  61. # TODO: Argh, no way to construct Git commit objects without
  62. # access to a serialized form.
  63. self.store.add_objects([])
  64. def test_add_object(self):
  65. self.store.add_object(testobject)
  66. self.assertEquals(set([testobject.id]), set(self.store))
  67. self.assertTrue(testobject.id in self.store)
  68. r = self.store[testobject.id]
  69. self.assertEquals(r, testobject)
  70. def test_add_objects(self):
  71. data = [(testobject, "mypath")]
  72. self.store.add_objects(data)
  73. self.assertEquals(set([testobject.id]), set(self.store))
  74. self.assertTrue(testobject.id in self.store)
  75. r = self.store[testobject.id]
  76. self.assertEquals(r, testobject)
  77. def test_tree_changes(self):
  78. blob_a1 = make_object(Blob, data='a1')
  79. blob_a2 = make_object(Blob, data='a2')
  80. blob_b = make_object(Blob, data='b')
  81. for blob in [blob_a1, blob_a2, blob_b]:
  82. self.store.add_object(blob)
  83. blobs_1 = [('a', blob_a1.id, 0100644), ('b', blob_b.id, 0100644)]
  84. tree1_id = commit_tree(self.store, blobs_1)
  85. blobs_2 = [('a', blob_a2.id, 0100644), ('b', blob_b.id, 0100644)]
  86. tree2_id = commit_tree(self.store, blobs_2)
  87. change_a = (('a', 'a'), (0100644, 0100644), (blob_a1.id, blob_a2.id))
  88. self.assertEquals([change_a],
  89. list(self.store.tree_changes(tree1_id, tree2_id)))
  90. self.assertEquals(
  91. [change_a, (('b', 'b'), (0100644, 0100644), (blob_b.id, blob_b.id))],
  92. list(self.store.tree_changes(tree1_id, tree2_id,
  93. want_unchanged=True)))
  94. def test_iter_tree_contents(self):
  95. blob_a = make_object(Blob, data='a')
  96. blob_b = make_object(Blob, data='b')
  97. blob_c = make_object(Blob, data='c')
  98. for blob in [blob_a, blob_b, blob_c]:
  99. self.store.add_object(blob)
  100. blobs = [
  101. ('a', blob_a.id, 0100644),
  102. ('ad/b', blob_b.id, 0100644),
  103. ('ad/bd/c', blob_c.id, 0100755),
  104. ('ad/c', blob_c.id, 0100644),
  105. ('c', blob_c.id, 0100644),
  106. ]
  107. tree_id = commit_tree(self.store, blobs)
  108. self.assertEquals([TreeEntry(p, m, h) for (p, h, m) in blobs],
  109. list(self.store.iter_tree_contents(tree_id)))
  110. def test_iter_tree_contents_include_trees(self):
  111. blob_a = make_object(Blob, data='a')
  112. blob_b = make_object(Blob, data='b')
  113. blob_c = make_object(Blob, data='c')
  114. for blob in [blob_a, blob_b, blob_c]:
  115. self.store.add_object(blob)
  116. blobs = [
  117. ('a', blob_a.id, 0100644),
  118. ('ad/b', blob_b.id, 0100644),
  119. ('ad/bd/c', blob_c.id, 0100755),
  120. ]
  121. tree_id = commit_tree(self.store, blobs)
  122. tree = self.store[tree_id]
  123. tree_ad = self.store[tree['ad'][1]]
  124. tree_bd = self.store[tree_ad['bd'][1]]
  125. expected = [
  126. TreeEntry('', 0040000, tree_id),
  127. TreeEntry('a', 0100644, blob_a.id),
  128. TreeEntry('ad', 0040000, tree_ad.id),
  129. TreeEntry('ad/b', 0100644, blob_b.id),
  130. TreeEntry('ad/bd', 0040000, tree_bd.id),
  131. TreeEntry('ad/bd/c', 0100755, blob_c.id),
  132. ]
  133. actual = self.store.iter_tree_contents(tree_id, include_trees=True)
  134. self.assertEquals(expected, list(actual))
  135. def make_tag(self, name, obj):
  136. tag = make_object(Tag, name=name, message='',
  137. tag_time=12345, tag_timezone=0,
  138. tagger='Test Tagger <test@example.com>',
  139. object=(object_class(obj.type_name), obj.id))
  140. self.store.add_object(tag)
  141. return tag
  142. def test_peel_sha(self):
  143. self.store.add_object(testobject)
  144. tag1 = self.make_tag('1', testobject)
  145. tag2 = self.make_tag('2', testobject)
  146. tag3 = self.make_tag('3', testobject)
  147. for obj in [testobject, tag1, tag2, tag3]:
  148. self.assertEqual(testobject, self.store.peel_sha(obj.id))
  149. class MemoryObjectStoreTests(ObjectStoreTests, TestCase):
  150. def setUp(self):
  151. TestCase.setUp(self)
  152. self.store = MemoryObjectStore()
  153. class PackBasedObjectStoreTests(ObjectStoreTests):
  154. def tearDown(self):
  155. for pack in self.store.packs:
  156. pack.close()
  157. def test_empty_packs(self):
  158. self.assertEquals([], self.store.packs)
  159. def test_pack_loose_objects(self):
  160. b1 = make_object(Blob, data="yummy data")
  161. self.store.add_object(b1)
  162. b2 = make_object(Blob, data="more yummy data")
  163. self.store.add_object(b2)
  164. self.assertEquals([], self.store.packs)
  165. self.assertEquals(2, self.store.pack_loose_objects())
  166. self.assertNotEquals([], self.store.packs)
  167. self.assertEquals(0, self.store.pack_loose_objects())
  168. class DiskObjectStoreTests(PackBasedObjectStoreTests, TestCase):
  169. def setUp(self):
  170. TestCase.setUp(self)
  171. self.store_dir = tempfile.mkdtemp()
  172. self.store = DiskObjectStore.init(self.store_dir)
  173. def tearDown(self):
  174. TestCase.tearDown(self)
  175. PackBasedObjectStoreTests.tearDown(self)
  176. shutil.rmtree(self.store_dir)
  177. def test_pack_dir(self):
  178. o = DiskObjectStore(self.store_dir)
  179. self.assertEquals(os.path.join(self.store_dir, "pack"), o.pack_dir)
  180. def test_add_pack(self):
  181. o = DiskObjectStore(self.store_dir)
  182. f, commit = o.add_pack()
  183. b = make_object(Blob, data="more yummy data")
  184. write_pack_data(f, [(b, None)], 1)
  185. commit()
  186. def test_add_thin_pack(self):
  187. o = DiskObjectStore(self.store_dir)
  188. f, commit = o.add_thin_pack()
  189. b = make_object(Blob, data="more yummy data")
  190. write_pack_data(f, [(b, None)], 1)
  191. commit()
  192. class TreeLookupPathTests(TestCase):
  193. def setUp(self):
  194. TestCase.setUp(self)
  195. self.store = MemoryObjectStore()
  196. blob_a = make_object(Blob, data='a')
  197. blob_b = make_object(Blob, data='b')
  198. blob_c = make_object(Blob, data='c')
  199. for blob in [blob_a, blob_b, blob_c]:
  200. self.store.add_object(blob)
  201. blobs = [
  202. ('a', blob_a.id, 0100644),
  203. ('ad/b', blob_b.id, 0100644),
  204. ('ad/bd/c', blob_c.id, 0100755),
  205. ('ad/c', blob_c.id, 0100644),
  206. ('c', blob_c.id, 0100644),
  207. ]
  208. self.tree_id = commit_tree(self.store, blobs)
  209. def get_object(self, sha):
  210. return self.store[sha]
  211. def test_lookup_blob(self):
  212. o_id = tree_lookup_path(self.get_object, self.tree_id, 'a')[1]
  213. self.assertTrue(isinstance(self.store[o_id], Blob))
  214. def test_lookup_tree(self):
  215. o_id = tree_lookup_path(self.get_object, self.tree_id, 'ad')[1]
  216. self.assertTrue(isinstance(self.store[o_id], Tree))
  217. o_id = tree_lookup_path(self.get_object, self.tree_id, 'ad/bd')[1]
  218. self.assertTrue(isinstance(self.store[o_id], Tree))
  219. o_id = tree_lookup_path(self.get_object, self.tree_id, 'ad/bd/')[1]
  220. self.assertTrue(isinstance(self.store[o_id], Tree))
  221. def test_lookup_nonexistent(self):
  222. self.assertRaises(KeyError, tree_lookup_path, self.get_object, self.tree_id, 'j')
  223. def test_lookup_not_tree(self):
  224. self.assertRaises(NotTreeError, tree_lookup_path, self.get_object, self.tree_id, 'ad/b/j')
  225. # TODO: MissingObjectFinderTests