mercurial/testing/storage.py
changeset 43076 2372284d9457
parent 42813 268662aac075
child 43077 687b865b95ad
equal deleted inserted replaced
43075:57875cf423c9 43076:2372284d9457
    16 )
    16 )
    17 from .. import (
    17 from .. import (
    18     error,
    18     error,
    19     mdiff,
    19     mdiff,
    20 )
    20 )
    21 from ..interfaces import (
    21 from ..interfaces import repository
    22     repository,
    22 from ..utils import storageutil
    23 )
    23 
    24 from ..utils import (
       
    25     storageutil,
       
    26 )
       
    27 
    24 
    28 class basetestcase(unittest.TestCase):
    25 class basetestcase(unittest.TestCase):
    29     if not getattr(unittest.TestCase, r'assertRaisesRegex', False):
    26     if not getattr(unittest.TestCase, r'assertRaisesRegex', False):
    30         assertRaisesRegex = (# camelcase-required
    27         assertRaisesRegex = (  # camelcase-required
    31             unittest.TestCase.assertRaisesRegexp)
    28             unittest.TestCase.assertRaisesRegexp
       
    29         )
       
    30 
    32 
    31 
    33 class ifileindextests(basetestcase):
    32 class ifileindextests(basetestcase):
    34     """Generic tests for the ifileindex interface.
    33     """Generic tests for the ifileindex interface.
    35 
    34 
    36     All file storage backends for index data should conform to the tests in this
    35     All file storage backends for index data should conform to the tests in this
    37     class.
    36     class.
    38 
    37 
    39     Use ``makeifileindextests()`` to create an instance of this type.
    38     Use ``makeifileindextests()`` to create an instance of this type.
    40     """
    39     """
       
    40 
    41     def testempty(self):
    41     def testempty(self):
    42         f = self._makefilefn()
    42         f = self._makefilefn()
    43         self.assertEqual(len(f), 0, 'new file store has 0 length by default')
    43         self.assertEqual(len(f), 0, 'new file store has 0 length by default')
    44         self.assertEqual(list(f), [], 'iter yields nothing by default')
    44         self.assertEqual(list(f), [], 'iter yields nothing by default')
    45 
    45 
   396         self.assertEqual(f.children(node2), [])
   396         self.assertEqual(f.children(node2), [])
   397         self.assertEqual(f.children(node3), [node4])
   397         self.assertEqual(f.children(node3), [node4])
   398         self.assertEqual(f.children(node4), [])
   398         self.assertEqual(f.children(node4), [])
   399         self.assertEqual(f.children(node5), [])
   399         self.assertEqual(f.children(node5), [])
   400 
   400 
       
   401 
   401 class ifiledatatests(basetestcase):
   402 class ifiledatatests(basetestcase):
   402     """Generic tests for the ifiledata interface.
   403     """Generic tests for the ifiledata interface.
   403 
   404 
   404     All file storage backends for data should conform to the tests in this
   405     All file storage backends for data should conform to the tests in this
   405     class.
   406     class.
   406 
   407 
   407     Use ``makeifiledatatests()`` to create an instance of this type.
   408     Use ``makeifiledatatests()`` to create an instance of this type.
   408     """
   409     """
       
   410 
   409     def testempty(self):
   411     def testempty(self):
   410         f = self._makefilefn()
   412         f = self._makefilefn()
   411 
   413 
   412         self.assertEqual(f.storageinfo(), {})
   414         self.assertEqual(f.storageinfo(), {})
   413         self.assertEqual(f.storageinfo(revisionscount=True, trackedsize=True),
   415         self.assertEqual(
   414                          {'revisionscount': 0, 'trackedsize': 0})
   416             f.storageinfo(revisionscount=True, trackedsize=True),
       
   417             {'revisionscount': 0, 'trackedsize': 0},
       
   418         )
   415 
   419 
   416         self.assertEqual(f.size(nullrev), 0)
   420         self.assertEqual(f.size(nullrev), 0)
   417 
   421 
   418         for i in range(-5, 5):
   422         for i in range(-5, 5):
   419             if i == nullrev:
   423             if i == nullrev:
   464         f = self._makefilefn()
   468         f = self._makefilefn()
   465         with self._maketransactionfn() as tr:
   469         with self._maketransactionfn() as tr:
   466             node = f.add(fulltext, None, tr, 0, nullid, nullid)
   470             node = f.add(fulltext, None, tr, 0, nullid, nullid)
   467 
   471 
   468         self.assertEqual(f.storageinfo(), {})
   472         self.assertEqual(f.storageinfo(), {})
   469         self.assertEqual(f.storageinfo(revisionscount=True, trackedsize=True),
   473         self.assertEqual(
   470                          {'revisionscount': 1, 'trackedsize': len(fulltext)})
   474             f.storageinfo(revisionscount=True, trackedsize=True),
       
   475             {'revisionscount': 1, 'trackedsize': len(fulltext)},
       
   476         )
   471 
   477 
   472         self.assertEqual(f.size(0), len(fulltext))
   478         self.assertEqual(f.size(0), len(fulltext))
   473 
   479 
   474         with self.assertRaises(IndexError):
   480         with self.assertRaises(IndexError):
   475             f.size(1)
   481             f.size(1)
   535         self.assertEqual(
   541         self.assertEqual(
   536             f.storageinfo(revisionscount=True, trackedsize=True),
   542             f.storageinfo(revisionscount=True, trackedsize=True),
   537             {
   543             {
   538                 'revisionscount': 3,
   544                 'revisionscount': 3,
   539                 'trackedsize': len(fulltext0) + len(fulltext1) + len(fulltext2),
   545                 'trackedsize': len(fulltext0) + len(fulltext1) + len(fulltext2),
   540             })
   546             },
       
   547         )
   541 
   548 
   542         self.assertEqual(f.size(0), len(fulltext0))
   549         self.assertEqual(f.size(0), len(fulltext0))
   543         self.assertEqual(f.size(1), len(fulltext1))
   550         self.assertEqual(f.size(1), len(fulltext1))
   544         self.assertEqual(f.size(2), len(fulltext2))
   551         self.assertEqual(f.size(2), len(fulltext2))
   545 
   552 
   601         self.assertEqual(rev.p2node, nullid)
   608         self.assertEqual(rev.p2node, nullid)
   602         self.assertIsNone(rev.linknode)
   609         self.assertIsNone(rev.linknode)
   603         self.assertEqual(rev.basenode, node0)
   610         self.assertEqual(rev.basenode, node0)
   604         self.assertIsNone(rev.baserevisionsize)
   611         self.assertIsNone(rev.baserevisionsize)
   605         self.assertIsNone(rev.revision)
   612         self.assertIsNone(rev.revision)
   606         self.assertEqual(rev.delta,
   613         self.assertEqual(
   607                          b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
   614             rev.delta,
   608                          fulltext1)
   615             b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' + fulltext1,
       
   616         )
   609 
   617 
   610         rev = next(gen)
   618         rev = next(gen)
   611 
   619 
   612         self.assertEqual(rev.node, node2)
   620         self.assertEqual(rev.node, node2)
   613         self.assertEqual(rev.p1node, node1)
   621         self.assertEqual(rev.p1node, node1)
   614         self.assertEqual(rev.p2node, nullid)
   622         self.assertEqual(rev.p2node, nullid)
   615         self.assertIsNone(rev.linknode)
   623         self.assertIsNone(rev.linknode)
   616         self.assertEqual(rev.basenode, node1)
   624         self.assertEqual(rev.basenode, node1)
   617         self.assertIsNone(rev.baserevisionsize)
   625         self.assertIsNone(rev.baserevisionsize)
   618         self.assertIsNone(rev.revision)
   626         self.assertIsNone(rev.revision)
   619         self.assertEqual(rev.delta,
   627         self.assertEqual(
   620                          b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
   628             rev.delta,
   621                          fulltext2)
   629             b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' + fulltext2,
       
   630         )
   622 
   631 
   623         with self.assertRaises(StopIteration):
   632         with self.assertRaises(StopIteration):
   624             next(gen)
   633             next(gen)
   625 
   634 
   626         # Request not in DAG order is reordered to be in DAG order.
   635         # Request not in DAG order is reordered to be in DAG order.
   644         self.assertEqual(rev.p2node, nullid)
   653         self.assertEqual(rev.p2node, nullid)
   645         self.assertIsNone(rev.linknode)
   654         self.assertIsNone(rev.linknode)
   646         self.assertEqual(rev.basenode, node0)
   655         self.assertEqual(rev.basenode, node0)
   647         self.assertIsNone(rev.baserevisionsize)
   656         self.assertIsNone(rev.baserevisionsize)
   648         self.assertIsNone(rev.revision)
   657         self.assertIsNone(rev.revision)
   649         self.assertEqual(rev.delta,
   658         self.assertEqual(
   650                          b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
   659             rev.delta,
   651                          fulltext1)
   660             b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' + fulltext1,
       
   661         )
   652 
   662 
   653         rev = next(gen)
   663         rev = next(gen)
   654 
   664 
   655         self.assertEqual(rev.node, node2)
   665         self.assertEqual(rev.node, node2)
   656         self.assertEqual(rev.p1node, node1)
   666         self.assertEqual(rev.p1node, node1)
   657         self.assertEqual(rev.p2node, nullid)
   667         self.assertEqual(rev.p2node, nullid)
   658         self.assertIsNone(rev.linknode)
   668         self.assertIsNone(rev.linknode)
   659         self.assertEqual(rev.basenode, node1)
   669         self.assertEqual(rev.basenode, node1)
   660         self.assertIsNone(rev.baserevisionsize)
   670         self.assertIsNone(rev.baserevisionsize)
   661         self.assertIsNone(rev.revision)
   671         self.assertIsNone(rev.revision)
   662         self.assertEqual(rev.delta,
   672         self.assertEqual(
   663                          b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
   673             rev.delta,
   664                          fulltext2)
   674             b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' + fulltext2,
       
   675         )
   665 
   676 
   666         with self.assertRaises(StopIteration):
   677         with self.assertRaises(StopIteration):
   667             next(gen)
   678             next(gen)
   668 
   679 
   669         # Unrecognized nodesorder value raises ProgrammingError.
   680         # Unrecognized nodesorder value raises ProgrammingError.
   670         with self.assertRaises(error.ProgrammingError):
   681         with self.assertRaises(error.ProgrammingError):
   671             list(f.emitrevisions([], nodesorder='bad'))
   682             list(f.emitrevisions([], nodesorder='bad'))
   672 
   683 
   673         # nodesorder=storage is recognized. But we can't test it thoroughly
   684         # nodesorder=storage is recognized. But we can't test it thoroughly
   674         # because behavior is storage-dependent.
   685         # because behavior is storage-dependent.
   675         res = list(f.emitrevisions([node2, node1, node0],
   686         res = list(f.emitrevisions([node2, node1, node0], nodesorder='storage'))
   676                                          nodesorder='storage'))
       
   677         self.assertEqual(len(res), 3)
   687         self.assertEqual(len(res), 3)
   678         self.assertEqual({o.node for o in res}, {node0, node1, node2})
   688         self.assertEqual({o.node for o in res}, {node0, node1, node2})
   679 
   689 
   680         # nodesorder=nodes forces the order.
   690         # nodesorder=nodes forces the order.
   681         gen = f.emitrevisions([node2, node0], nodesorder='nodes',
   691         gen = f.emitrevisions(
   682                               revisiondata=True)
   692             [node2, node0], nodesorder='nodes', revisiondata=True
       
   693         )
   683 
   694 
   684         rev = next(gen)
   695         rev = next(gen)
   685         self.assertEqual(rev.node, node2)
   696         self.assertEqual(rev.node, node2)
   686         self.assertEqual(rev.p1node, node1)
   697         self.assertEqual(rev.p1node, node1)
   687         self.assertEqual(rev.p2node, nullid)
   698         self.assertEqual(rev.p2node, nullid)
   717         self.assertEqual(rev.p1node, node1)
   728         self.assertEqual(rev.p1node, node1)
   718         self.assertEqual(rev.p2node, nullid)
   729         self.assertEqual(rev.p2node, nullid)
   719         self.assertEqual(rev.basenode, node1)
   730         self.assertEqual(rev.basenode, node1)
   720         self.assertIsNone(rev.baserevisionsize)
   731         self.assertIsNone(rev.baserevisionsize)
   721         self.assertIsNone(rev.revision)
   732         self.assertIsNone(rev.revision)
   722         self.assertEqual(rev.delta,
   733         self.assertEqual(
   723                          b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
   734             rev.delta,
   724                          fulltext2)
   735             b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' + fulltext2,
       
   736         )
   725 
   737 
   726         with self.assertRaises(StopIteration):
   738         with self.assertRaises(StopIteration):
   727             next(gen)
   739             next(gen)
   728 
   740 
   729         # assumehaveparentrevisions=True allows delta against initial revision.
   741         # assumehaveparentrevisions=True allows delta against initial revision.
   730         gen = f.emitrevisions([node2, node1],
   742         gen = f.emitrevisions(
   731                               revisiondata=True, assumehaveparentrevisions=True)
   743             [node2, node1], revisiondata=True, assumehaveparentrevisions=True
       
   744         )
   732 
   745 
   733         rev = next(gen)
   746         rev = next(gen)
   734         self.assertEqual(rev.node, node1)
   747         self.assertEqual(rev.node, node1)
   735         self.assertEqual(rev.p1node, node0)
   748         self.assertEqual(rev.p1node, node0)
   736         self.assertEqual(rev.p2node, nullid)
   749         self.assertEqual(rev.p2node, nullid)
   737         self.assertEqual(rev.basenode, node0)
   750         self.assertEqual(rev.basenode, node0)
   738         self.assertIsNone(rev.baserevisionsize)
   751         self.assertIsNone(rev.baserevisionsize)
   739         self.assertIsNone(rev.revision)
   752         self.assertIsNone(rev.revision)
   740         self.assertEqual(rev.delta,
   753         self.assertEqual(
   741                          b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
   754             rev.delta,
   742                          fulltext1)
   755             b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' + fulltext1,
       
   756         )
   743 
   757 
   744         # forceprevious=True forces a delta against the previous revision.
   758         # forceprevious=True forces a delta against the previous revision.
   745         # Special case for initial revision.
   759         # Special case for initial revision.
   746         gen = f.emitrevisions([node0], revisiondata=True,
   760         gen = f.emitrevisions(
   747                               deltamode=repository.CG_DELTAMODE_PREV)
   761             [node0], revisiondata=True, deltamode=repository.CG_DELTAMODE_PREV
       
   762         )
   748 
   763 
   749         rev = next(gen)
   764         rev = next(gen)
   750         self.assertEqual(rev.node, node0)
   765         self.assertEqual(rev.node, node0)
   751         self.assertEqual(rev.p1node, nullid)
   766         self.assertEqual(rev.p1node, nullid)
   752         self.assertEqual(rev.p2node, nullid)
   767         self.assertEqual(rev.p2node, nullid)
   753         self.assertEqual(rev.basenode, nullid)
   768         self.assertEqual(rev.basenode, nullid)
   754         self.assertIsNone(rev.baserevisionsize)
   769         self.assertIsNone(rev.baserevisionsize)
   755         self.assertIsNone(rev.revision)
   770         self.assertIsNone(rev.revision)
   756         self.assertEqual(rev.delta,
   771         self.assertEqual(
   757                          b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' +
   772             rev.delta,
   758                          fulltext0)
   773             b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' + fulltext0,
       
   774         )
   759 
   775 
   760         with self.assertRaises(StopIteration):
   776         with self.assertRaises(StopIteration):
   761             next(gen)
   777             next(gen)
   762 
   778 
   763         gen = f.emitrevisions([node0, node2], revisiondata=True,
   779         gen = f.emitrevisions(
   764                               deltamode=repository.CG_DELTAMODE_PREV)
   780             [node0, node2],
       
   781             revisiondata=True,
       
   782             deltamode=repository.CG_DELTAMODE_PREV,
       
   783         )
   765 
   784 
   766         rev = next(gen)
   785         rev = next(gen)
   767         self.assertEqual(rev.node, node0)
   786         self.assertEqual(rev.node, node0)
   768         self.assertEqual(rev.p1node, nullid)
   787         self.assertEqual(rev.p1node, nullid)
   769         self.assertEqual(rev.p2node, nullid)
   788         self.assertEqual(rev.p2node, nullid)
   770         self.assertEqual(rev.basenode, nullid)
   789         self.assertEqual(rev.basenode, nullid)
   771         self.assertIsNone(rev.baserevisionsize)
   790         self.assertIsNone(rev.baserevisionsize)
   772         self.assertIsNone(rev.revision)
   791         self.assertIsNone(rev.revision)
   773         self.assertEqual(rev.delta,
   792         self.assertEqual(
   774                          b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' +
   793             rev.delta,
   775                          fulltext0)
   794             b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' + fulltext0,
       
   795         )
   776 
   796 
   777         rev = next(gen)
   797         rev = next(gen)
   778         self.assertEqual(rev.node, node2)
   798         self.assertEqual(rev.node, node2)
   779         self.assertEqual(rev.p1node, node1)
   799         self.assertEqual(rev.p1node, node1)
   780         self.assertEqual(rev.p2node, nullid)
   800         self.assertEqual(rev.p2node, nullid)
   796         meta2 = {
   816         meta2 = {
   797             b'copy': b'source1',
   817             b'copy': b'source1',
   798             b'copyrev': b'b' * 40,
   818             b'copyrev': b'b' * 40,
   799         }
   819         }
   800 
   820 
   801         stored1 = b''.join([
   821         stored1 = b''.join(
   802             b'\x01\ncopy: source0\n',
   822             [
   803             b'copyrev: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\x01\n',
   823                 b'\x01\ncopy: source0\n',
   804             fulltext1,
   824                 b'copyrev: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\x01\n',
   805         ])
   825                 fulltext1,
   806 
   826             ]
   807         stored2 = b''.join([
   827         )
   808             b'\x01\ncopy: source1\n',
   828 
   809             b'copyrev: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n\x01\n',
   829         stored2 = b''.join(
   810             fulltext2,
   830             [
   811         ])
   831                 b'\x01\ncopy: source1\n',
       
   832                 b'copyrev: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n\x01\n',
       
   833                 fulltext2,
       
   834             ]
       
   835         )
   812 
   836 
   813         f = self._makefilefn()
   837         f = self._makefilefn()
   814         with self._maketransactionfn() as tr:
   838         with self._maketransactionfn() as tr:
   815             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   839             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   816             node1 = f.add(fulltext1, meta1, tr, 1, node0, nullid)
   840             node1 = f.add(fulltext1, meta1, tr, 1, node0, nullid)
   845         fulltext1 = b'\x01\nbar'
   869         fulltext1 = b'\x01\nbar'
   846         meta1 = {
   870         meta1 = {
   847             b'copy': b'source0',
   871             b'copy': b'source0',
   848             b'copyrev': b'b' * 40,
   872             b'copyrev': b'b' * 40,
   849         }
   873         }
   850         stored1 = b''.join([
   874         stored1 = b''.join(
   851             b'\x01\ncopy: source0\n',
   875             [
   852             b'copyrev: %s\n' % (b'b' * 40),
   876                 b'\x01\ncopy: source0\n',
   853             b'\x01\n\x01\nbar',
   877                 b'copyrev: %s\n' % (b'b' * 40),
   854         ])
   878                 b'\x01\n\x01\nbar',
       
   879             ]
       
   880         )
   855 
   881 
   856         f = self._makefilefn()
   882         f = self._makefilefn()
   857         with self._maketransactionfn() as tr:
   883         with self._maketransactionfn() as tr:
   858             node0 = f.add(fulltext0, {}, tr, 0, nullid, nullid)
   884             node0 = f.add(fulltext0, {}, tr, 0, nullid, nullid)
   859             node1 = f.add(fulltext1, meta1, tr, 1, nullid, nullid)
   885             node1 = f.add(fulltext1, meta1, tr, 1, nullid, nullid)
   886 
   912 
   887         with self._maketransactionfn() as tr:
   913         with self._maketransactionfn() as tr:
   888             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   914             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   889             node1 = b'\xaa' * 20
   915             node1 = b'\xaa' * 20
   890 
   916 
   891             self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
   917             self._addrawrevisionfn(
   892                                    rawtext=fulltext1)
   918                 f, tr, node1, node0, nullid, 1, rawtext=fulltext1
       
   919             )
   893 
   920 
   894         self.assertEqual(len(f), 2)
   921         self.assertEqual(len(f), 2)
   895         self.assertEqual(f.parents(node1), (node0, nullid))
   922         self.assertEqual(f.parents(node1), (node0, nullid))
   896 
   923 
   897         # revision() raises since it performs hash verification.
   924         # revision() raises since it performs hash verification.
   920 
   947 
   921         with self._maketransactionfn() as tr:
   948         with self._maketransactionfn() as tr:
   922             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   949             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   923             node1 = b'\xaa' * 20
   950             node1 = b'\xaa' * 20
   924 
   951 
   925             self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
   952             self._addrawrevisionfn(
   926                                    rawtext=fulltext1)
   953                 f, tr, node1, node0, nullid, 1, rawtext=fulltext1
       
   954             )
   927 
   955 
   928         with self.assertRaises(error.StorageError):
   956         with self.assertRaises(error.StorageError):
   929             f.rawdata(node1)
   957             f.rawdata(node1)
   930 
   958 
   931         with self.assertRaises(error.StorageError):
   959         with self.assertRaises(error.StorageError):
   941 
   969 
   942         with self._maketransactionfn() as tr:
   970         with self._maketransactionfn() as tr:
   943             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   971             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   944             node1 = b'\xaa' * 20
   972             node1 = b'\xaa' * 20
   945 
   973 
   946             self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
   974             self._addrawrevisionfn(
   947                                    rawtext=fulltext1)
   975                 f, tr, node1, node0, nullid, 1, rawtext=fulltext1
       
   976             )
   948 
   977 
   949         with self.assertRaises(error.StorageError):
   978         with self.assertRaises(error.StorageError):
   950             f.read(node1)
   979             f.read(node1)
   951 
   980 
   952         with self.assertRaises(error.StorageError):
   981         with self.assertRaises(error.StorageError):
   961 
   990 
   962         with self._maketransactionfn() as tr:
   991         with self._maketransactionfn() as tr:
   963             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   992             node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
   964             node1 = b'\xaa' * 20
   993             node1 = b'\xaa' * 20
   965 
   994 
   966             self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
   995             self._addrawrevisionfn(
   967                                    rawtext=fulltext1)
   996                 f, tr, node1, node0, nullid, 1, rawtext=fulltext1
       
   997             )
   968 
   998 
   969         with self.assertRaises(error.StorageError):
   999         with self.assertRaises(error.StorageError):
   970             f.read(node1)
  1000             f.read(node1)
   971 
  1001 
   972         node2 = storageutil.hashrevisionsha1(fulltext2, node1, nullid)
  1002         node2 = storageutil.hashrevisionsha1(fulltext2, node1, nullid)
   973 
  1003 
   974         with self._maketransactionfn() as tr:
  1004         with self._maketransactionfn() as tr:
   975             delta = mdiff.textdiff(fulltext1, fulltext2)
  1005             delta = mdiff.textdiff(fulltext1, fulltext2)
   976             self._addrawrevisionfn(f, tr, node2, node1, nullid,
  1006             self._addrawrevisionfn(
   977                                    2, delta=(1, delta))
  1007                 f, tr, node2, node1, nullid, 2, delta=(1, delta)
       
  1008             )
   978 
  1009 
   979         self.assertEqual(len(f), 3)
  1010         self.assertEqual(len(f), 3)
   980 
  1011 
   981         # Assuming a delta is stored, we shouldn't need to validate node1 in
  1012         # Assuming a delta is stored, we shouldn't need to validate node1 in
   982         # order to retrieve node2.
  1013         # order to retrieve node2.
   983         self.assertEqual(f.read(node2), fulltext2)
  1014         self.assertEqual(f.read(node2), fulltext2)
   984 
  1015 
   985     def testcensored(self):
  1016     def testcensored(self):
   986         f = self._makefilefn()
  1017         f = self._makefilefn()
   987 
  1018 
   988         stored1 = storageutil.packmeta({
  1019         stored1 = storageutil.packmeta({b'censored': b'tombstone',}, b'')
   989             b'censored': b'tombstone',
       
   990         }, b'')
       
   991 
  1020 
   992         with self._maketransactionfn() as tr:
  1021         with self._maketransactionfn() as tr:
   993             node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
  1022             node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
   994 
  1023 
   995             # The node value doesn't matter since we can't verify it.
  1024             # The node value doesn't matter since we can't verify it.
   996             node1 = b'\xbb' * 20
  1025             node1 = b'\xbb' * 20
   997 
  1026 
   998             self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
  1027             self._addrawrevisionfn(
   999                                    censored=True)
  1028                 f, tr, node1, node0, nullid, 1, stored1, censored=True
       
  1029             )
  1000 
  1030 
  1001         self.assertTrue(f.iscensored(1))
  1031         self.assertTrue(f.iscensored(1))
  1002 
  1032 
  1003         with self.assertRaises(error.CensoredNodeError):
  1033         with self.assertRaises(error.CensoredNodeError):
  1004             f.revision(1)
  1034             f.revision(1)
  1013         # Like above, except we do the rawdata() request first to
  1043         # Like above, except we do the rawdata() request first to
  1014         # isolate revision caching behavior.
  1044         # isolate revision caching behavior.
  1015 
  1045 
  1016         f = self._makefilefn()
  1046         f = self._makefilefn()
  1017 
  1047 
  1018         stored1 = storageutil.packmeta({
  1048         stored1 = storageutil.packmeta({b'censored': b'tombstone',}, b'')
  1019             b'censored': b'tombstone',
       
  1020         }, b'')
       
  1021 
  1049 
  1022         with self._maketransactionfn() as tr:
  1050         with self._maketransactionfn() as tr:
  1023             node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
  1051             node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
  1024 
  1052 
  1025             # The node value doesn't matter since we can't verify it.
  1053             # The node value doesn't matter since we can't verify it.
  1026             node1 = b'\xbb' * 20
  1054             node1 = b'\xbb' * 20
  1027 
  1055 
  1028             self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
  1056             self._addrawrevisionfn(
  1029                                    censored=True)
  1057                 f, tr, node1, node0, nullid, 1, stored1, censored=True
       
  1058             )
  1030 
  1059 
  1031         with self.assertRaises(error.CensoredNodeError):
  1060         with self.assertRaises(error.CensoredNodeError):
  1032             f.rawdata(1)
  1061             f.rawdata(1)
  1033 
  1062 
       
  1063 
  1034 class ifilemutationtests(basetestcase):
  1064 class ifilemutationtests(basetestcase):
  1035     """Generic tests for the ifilemutation interface.
  1065     """Generic tests for the ifilemutation interface.
  1036 
  1066 
  1037     All file storage backends that support writing should conform to this
  1067     All file storage backends that support writing should conform to this
  1038     interface.
  1068     interface.
  1039 
  1069 
  1040     Use ``makeifilemutationtests()`` to create an instance of this type.
  1070     Use ``makeifilemutationtests()`` to create an instance of this type.
  1041     """
  1071     """
       
  1072 
  1042     def testaddnoop(self):
  1073     def testaddnoop(self):
  1043         f = self._makefilefn()
  1074         f = self._makefilefn()
  1044         with self._maketransactionfn() as tr:
  1075         with self._maketransactionfn() as tr:
  1045             node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
  1076             node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
  1046             node1 = f.add(b'foo', None, tr, 0, nullid, nullid)
  1077             node1 = f.add(b'foo', None, tr, 0, nullid, nullid)
  1071 
  1102 
  1072     def testaddgroupsimple(self):
  1103     def testaddgroupsimple(self):
  1073         f = self._makefilefn()
  1104         f = self._makefilefn()
  1074 
  1105 
  1075         callbackargs = []
  1106         callbackargs = []
       
  1107 
  1076         def cb(*args, **kwargs):
  1108         def cb(*args, **kwargs):
  1077             callbackargs.append((args, kwargs))
  1109             callbackargs.append((args, kwargs))
  1078 
  1110 
  1079         def linkmapper(node):
  1111         def linkmapper(node):
  1080             return 0
  1112             return 0
  1099         ]
  1131         ]
  1100 
  1132 
  1101         with self._maketransactionfn() as tr:
  1133         with self._maketransactionfn() as tr:
  1102             nodes = f.addgroup(deltas, linkmapper, tr, addrevisioncb=cb)
  1134             nodes = f.addgroup(deltas, linkmapper, tr, addrevisioncb=cb)
  1103 
  1135 
  1104         self.assertEqual(nodes, [
  1136         self.assertEqual(
  1105             b'\x49\xd8\xcb\xb1\x5c\xe2\x57\x92\x04\x47'
  1137             nodes,
  1106             b'\x00\x6b\x46\x97\x8b\x7a\xf9\x80\xa9\x79'])
  1138             [
       
  1139                 b'\x49\xd8\xcb\xb1\x5c\xe2\x57\x92\x04\x47'
       
  1140                 b'\x00\x6b\x46\x97\x8b\x7a\xf9\x80\xa9\x79'
       
  1141             ],
       
  1142         )
  1107 
  1143 
  1108         self.assertEqual(len(callbackargs), 1)
  1144         self.assertEqual(len(callbackargs), 1)
  1109         self.assertEqual(callbackargs[0][0][1], nodes[0])
  1145         self.assertEqual(callbackargs[0][0][1], nodes[0])
  1110 
  1146 
  1111         self.assertEqual(list(f.revs()), [0])
  1147         self.assertEqual(list(f.revs()), [0])
  1147 
  1183 
  1148     def testdeltaagainstcensored(self):
  1184     def testdeltaagainstcensored(self):
  1149         # Attempt to apply a delta made against a censored revision.
  1185         # Attempt to apply a delta made against a censored revision.
  1150         f = self._makefilefn()
  1186         f = self._makefilefn()
  1151 
  1187 
  1152         stored1 = storageutil.packmeta({
  1188         stored1 = storageutil.packmeta({b'censored': b'tombstone',}, b'')
  1153             b'censored': b'tombstone',
       
  1154         }, b'')
       
  1155 
  1189 
  1156         with self._maketransactionfn() as tr:
  1190         with self._maketransactionfn() as tr:
  1157             node0 = f.add(b'foo\n' * 30, None, tr, 0, nullid, nullid)
  1191             node0 = f.add(b'foo\n' * 30, None, tr, 0, nullid, nullid)
  1158 
  1192 
  1159             # The node value doesn't matter since we can't verify it.
  1193             # The node value doesn't matter since we can't verify it.
  1160             node1 = b'\xbb' * 20
  1194             node1 = b'\xbb' * 20
  1161 
  1195 
  1162             self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
  1196             self._addrawrevisionfn(
  1163                                    censored=True)
  1197                 f, tr, node1, node0, nullid, 1, stored1, censored=True
       
  1198             )
  1164 
  1199 
  1165         delta = mdiff.textdiff(b'bar\n' * 30, (b'bar\n' * 30) + b'baz\n')
  1200         delta = mdiff.textdiff(b'bar\n' * 30, (b'bar\n' * 30) + b'baz\n')
  1166         deltas = [(b'\xcc' * 20, node1, nullid, b'\x01' * 20, node1, delta, 0)]
  1201         deltas = [(b'\xcc' * 20, node1, nullid, b'\x01' * 20, node1, delta, 0)]
  1167 
  1202 
  1168         with self._maketransactionfn() as tr:
  1203         with self._maketransactionfn() as tr:
  1304         self.assertEqual(len(f), 1)
  1339         self.assertEqual(len(f), 1)
  1305 
  1340 
  1306         with self.assertRaises(error.LookupError):
  1341         with self.assertRaises(error.LookupError):
  1307             f.rev(node1)
  1342             f.rev(node1)
  1308 
  1343 
       
  1344 
  1309 def makeifileindextests(makefilefn, maketransactionfn, addrawrevisionfn):
  1345 def makeifileindextests(makefilefn, maketransactionfn, addrawrevisionfn):
  1310     """Create a unittest.TestCase class suitable for testing file storage.
  1346     """Create a unittest.TestCase class suitable for testing file storage.
  1311 
  1347 
  1312     ``makefilefn`` is a callable which receives the test case as an
  1348     ``makefilefn`` is a callable which receives the test case as an
  1313     argument and returns an object implementing the ``ifilestorage`` interface.
  1349     argument and returns an object implementing the ``ifilestorage`` interface.
  1329         r'_maketransactionfn': maketransactionfn,
  1365         r'_maketransactionfn': maketransactionfn,
  1330         r'_addrawrevisionfn': addrawrevisionfn,
  1366         r'_addrawrevisionfn': addrawrevisionfn,
  1331     }
  1367     }
  1332     return type(r'ifileindextests', (ifileindextests,), d)
  1368     return type(r'ifileindextests', (ifileindextests,), d)
  1333 
  1369 
       
  1370 
  1334 def makeifiledatatests(makefilefn, maketransactionfn, addrawrevisionfn):
  1371 def makeifiledatatests(makefilefn, maketransactionfn, addrawrevisionfn):
  1335     d = {
  1372     d = {
  1336         r'_makefilefn': makefilefn,
  1373         r'_makefilefn': makefilefn,
  1337         r'_maketransactionfn': maketransactionfn,
  1374         r'_maketransactionfn': maketransactionfn,
  1338         r'_addrawrevisionfn': addrawrevisionfn,
  1375         r'_addrawrevisionfn': addrawrevisionfn,
  1339     }
  1376     }
  1340     return type(r'ifiledatatests', (ifiledatatests,), d)
  1377     return type(r'ifiledatatests', (ifiledatatests,), d)
  1341 
  1378 
       
  1379 
  1342 def makeifilemutationtests(makefilefn, maketransactionfn, addrawrevisionfn):
  1380 def makeifilemutationtests(makefilefn, maketransactionfn, addrawrevisionfn):
  1343     d = {
  1381     d = {
  1344         r'_makefilefn': makefilefn,
  1382         r'_makefilefn': makefilefn,
  1345         r'_maketransactionfn': maketransactionfn,
  1383         r'_maketransactionfn': maketransactionfn,
  1346         r'_addrawrevisionfn': addrawrevisionfn,
  1384         r'_addrawrevisionfn': addrawrevisionfn,