mirror of
https://github.com/borgbackup/borg.git
synced 2025-01-24 00:09:00 +00:00
Added hashindex test cases and removed unused BandIndex
This commit is contained in:
parent
175f4bb505
commit
a5376ea4fd
2 changed files with 53 additions and 55 deletions
|
@ -1,4 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
cdef extern from "_hashindex.c":
|
cdef extern from "_hashindex.c":
|
||||||
ctypedef struct HashIndex:
|
ctypedef struct HashIndex:
|
||||||
|
@ -22,7 +24,7 @@ cdef class IndexBase:
|
||||||
cdef HashIndex *index
|
cdef HashIndex *index
|
||||||
|
|
||||||
def __cinit__(self, path):
|
def __cinit__(self, path):
|
||||||
self.index = hashindex_open(path)
|
self.index = hashindex_open(<bytes>os.fsencode(path))
|
||||||
if not self.index:
|
if not self.index:
|
||||||
raise Exception('Failed to open %s' % path)
|
raise Exception('Failed to open %s' % path)
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@ cdef class NSIndex(IndexBase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, path, capacity=16):
|
def create(cls, path, capacity=16):
|
||||||
index = hashindex_create(path, capacity, 32, 8)
|
index = hashindex_create(<bytes>os.fsencode(path), capacity, 32, 8)
|
||||||
if not index:
|
if not index:
|
||||||
raise Exception('Failed to create %s' % path)
|
raise Exception('Failed to create %s' % path)
|
||||||
hashindex_close(index)
|
hashindex_close(index)
|
||||||
|
@ -121,7 +123,7 @@ cdef class ChunkIndex(IndexBase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, path, capacity=16):
|
def create(cls, path, capacity=16):
|
||||||
index = hashindex_create(path, capacity, 32, 12)
|
index = hashindex_create(<bytes>os.fsencode(path), capacity, 32, 12)
|
||||||
hashindex_close(index)
|
hashindex_close(index)
|
||||||
return cls(path)
|
return cls(path)
|
||||||
|
|
||||||
|
@ -171,55 +173,3 @@ cdef class ChunkKeyIterator:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
cdef int *value = <int *>(self.key + 32)
|
cdef int *value = <int *>(self.key + 32)
|
||||||
return self.key[:32], (value[0], value[1], value[2])
|
return self.key[:32], (value[0], value[1], value[2])
|
||||||
|
|
||||||
|
|
||||||
cdef class BandIndex(IndexBase):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(cls, path, capacity=16):
|
|
||||||
index = hashindex_create(path, capacity, 4, 4)
|
|
||||||
hashindex_close(index)
|
|
||||||
return cls(path)
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
cdef int k = key
|
|
||||||
data = <int *>hashindex_get(self.index, &k)
|
|
||||||
if not data:
|
|
||||||
raise KeyError
|
|
||||||
return data[0]
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
|
||||||
cdef int k = key
|
|
||||||
hashindex_delete(self.index, &k)
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
cdef int k = key
|
|
||||||
cdef int v = value
|
|
||||||
hashindex_set(self.index, &k, &v)
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
|
||||||
cdef int k = key
|
|
||||||
data = <int *>hashindex_get(self.index, &k)
|
|
||||||
return data != NULL
|
|
||||||
|
|
||||||
def iteritems(self, marker=None, limit=0):
|
|
||||||
iter = BandKeyIterator()
|
|
||||||
iter.index = self.index
|
|
||||||
return iter
|
|
||||||
|
|
||||||
|
|
||||||
cdef class BandKeyIterator:
|
|
||||||
cdef HashIndex *index
|
|
||||||
cdef int *key
|
|
||||||
|
|
||||||
def __cinit__(self):
|
|
||||||
self.key = NULL
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
self.key = <int *>hashindex_next_key(self.index, <char *>self.key)
|
|
||||||
if not self.key:
|
|
||||||
raise StopIteration
|
|
||||||
return self.key[0], self.key[1]
|
|
||||||
|
|
48
darc/testsuite/hashindex.py
Normal file
48
darc/testsuite/hashindex.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import hashlib
|
||||||
|
import tempfile
|
||||||
|
from darc.hashindex import NSIndex, ChunkIndex
|
||||||
|
from darc.testsuite import DarcTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class HashIndexTestCase(DarcTestCase):
|
||||||
|
|
||||||
|
def _generic_test(self, cls, make_value, sha):
|
||||||
|
idx_name = tempfile.NamedTemporaryFile()
|
||||||
|
idx = cls.create(idx_name.name)
|
||||||
|
self.assert_equal(len(idx), 0)
|
||||||
|
# Test set
|
||||||
|
for x in range(100):
|
||||||
|
idx[bytes('%-32d' % x, 'ascii')] = make_value(x)
|
||||||
|
self.assert_equal(len(idx), 100)
|
||||||
|
for x in range(100):
|
||||||
|
self.assert_equal(idx[bytes('%-32d' % x, 'ascii')], make_value(x))
|
||||||
|
# Test update
|
||||||
|
for x in range(100):
|
||||||
|
idx[bytes('%-32d' % x, 'ascii')] = make_value(x * 2)
|
||||||
|
self.assert_equal(len(idx), 100)
|
||||||
|
for x in range(100):
|
||||||
|
self.assert_equal(idx[bytes('%-32d' % x, 'ascii')], make_value(x * 2))
|
||||||
|
# Test delete
|
||||||
|
for x in range(50):
|
||||||
|
del idx[bytes('%-32d' % x, 'ascii')]
|
||||||
|
self.assert_equal(len(idx), 50)
|
||||||
|
del idx
|
||||||
|
# Verify file contents
|
||||||
|
with open(idx_name.name, 'rb') as fd:
|
||||||
|
self.assert_equal(hashlib.sha256(fd.read()).hexdigest(), sha)
|
||||||
|
# Make sure we can open the file
|
||||||
|
idx = cls(idx_name.name)
|
||||||
|
self.assert_equal(len(idx), 50)
|
||||||
|
for x in range(50, 100):
|
||||||
|
self.assert_equal(idx[bytes('%-32d' % x, 'ascii')], make_value(x * 2))
|
||||||
|
idx.clear()
|
||||||
|
self.assert_equal(len(idx), 0)
|
||||||
|
del idx
|
||||||
|
self.assert_equal(len(cls(idx_name.name)), 0)
|
||||||
|
|
||||||
|
def test_nsindex(self):
|
||||||
|
self._generic_test(NSIndex, lambda x: (x, x), '926af057de19a82903fab517e0813e6fa16e4129df5b7062e9b1f24bbe98fb24')
|
||||||
|
|
||||||
|
def test_chunkindex(self):
|
||||||
|
self._generic_test(ChunkIndex, lambda x: (x, x, x), 'cc60ec9265d172b20c33b6c00160abda1a6e881d07088b9d1c5997a82e05f5a7')
|
||||||
|
|
Loading…
Reference in a new issue