def test_ordered_insert(cls): sl = orderedstructs.SkipList(object) for i in range(8): assert sl.lacks_integrity() == 0 obj = cls(i) sl.insert(obj) assert sl.lacks_integrity() == 0
def test_hypothesis_insert_remove_integers(lst): sl = orderedstructs.SkipList(int_type) for v in lst: sl.insert(int_type(v)) for v in lst: sl.remove(int_type(v)) assert sl.size() == 0
def _setup_skiplist_with_class(cls: typing.Type, n: int) -> orderedstructs.SkipList: """Returns a skiplist with a particular class of length n.""" sl = orderedstructs.SkipList(object) for v in range(n): sl.insert(cls(v)) return sl
def test_memory_management_python_objects(cls, size, rounds, expected_getsizeof, maximum_increase_at_empty): """Check for memory usage and recovery (no leaks).""" print() # SIZE = 1024 * 100 # ROUNDS = 1 proc = psutil.Process() rss_start = proc.memory_info().rss print(f'RSS: {rss_start:12,d} at start of test.') for round in range(rounds): sl = orderedstructs.SkipList(object) for i in range(size): sl.insert(cls(i)) assert sl.size() == size rss_peak = proc.memory_info().rss print( f'RSS: {rss_peak:12,d}' f' Change {rss_peak - rss_start:+12,d} skip list loaded' f' round {round:4d} sys.getsizeof(sl) {sys.getsizeof(sl):+12,d}.') # Should be within 10% say assert abs(sys.getsizeof(sl) - expected_getsizeof) < 0.1 * expected_getsizeof for i in range(size): sl.remove(cls(i)) assert sl.size() == 0 del sl rss_end = proc.memory_info().rss print( f'RSS: {rss_end:12,d} Change {rss_end - rss_start:+12,d} skip list empty.' ) assert rss_end - rss_start < maximum_increase_at_empty
def test_ordered_cmp_not_a_function(cls): """Test of passing in a non-callable. This can be detected at instantiation time.""" with pytest.raises(ValueError) as err: orderedstructs.SkipList(object, 14) assert err.value.args[0] == \ 'Argument "cmp_func" to __init__ must be a callable object not an "int" object.'
def test_ordered_refcount_insert(cls): """Reference count is incremented on insert.""" sl = orderedstructs.SkipList(object) obj = cls(0) rc = sys.getrefcount(obj) sl.insert(obj) assert sys.getrefcount(obj) == rc + 1
def test_given_cmp_function_bytes_fails(cls): """Test of passing in a non-callable. This can be detected at instantiation time.""" with pytest.raises(ValueError) as err: orderedstructs.SkipList(bytes, lambda x, y: x < y) assert err.value.args[0] == \ 'Can not specify comparison function with type "bytes".'
def test_insert_node_width(typ, value): """See: skiplist/doc/dot/doc_insert_remove.svg to node 3""" num_nodes = 4 seq = ( 1, 1, 0, # Node value 0 1, 0, # Node value 1 1, 1, 0, # Node value 2 0, # Node value 3 ) assert len(seq) <= SEEDTREE_DEPTH orderedstructs.seed_rand(SEED_DICT[seq]) sl = orderedstructs.SkipList(typ) for i in range(num_nodes): assert sl.lacks_integrity() == 0 sl.insert(value * i) assert sl.lacks_integrity() == 0 # Now test expected = { 0: (1, 1, 2), 1: (1, 1), 2: (1, 2, 2), 3: (1, ), } for i in range(num_nodes): assert sl.lacks_integrity() == 0 assert sl.node_height(i) == len(expected[i]) for level in range(sl.node_height(i)): assert sl.node_width(i, level) == expected[i][level] assert sl.lacks_integrity() == 0
def test_hypothesis_insert_remove_floats_no_nan_with_infinity(lst): sl = orderedstructs.SkipList(float) for v in lst: sl.insert(v) for v in lst: sl.remove(v) assert sl.size() == 0
def test_hypothesis_index_integers(lst): sl = orderedstructs.SkipList(int_type) for v in lst: sl.insert(int_type(v)) reference = sorted(lst) for v in lst: assert reference.index(v) == sl.index(int_type(v))
def test_ordered_insert_remove_id_is_same(cls): """Check that an insert followed by a remove refers to the same Python object.""" sl = orderedstructs.SkipList(object) obj_insert = cls(0) sl.insert(obj_insert) obj_remove = sl.remove(obj_insert) assert id(obj_remove) == id(obj_insert)
def test_hypothesis_insert_remove_bytes(lst): sl = orderedstructs.SkipList(bytes) for v in lst: sl.insert(v) for v in lst: sl.remove(v) assert sl.size() == 0
def test_hypothesis_index_bytes(lst): sl = orderedstructs.SkipList(bytes) for v in lst: sl.insert(v) reference = sorted(lst) for v in lst: assert reference.index(v) == sl.index(v)
def test_ordered_person(): sl = orderedstructs.SkipList(object) sl.insert(Person('Peter', 'Pan')) sl.insert(Person('Alan', 'Pan')) assert sl.size() == 2 assert str(sl.at(0)) == 'Pan, Alan' assert str(sl.at(1)) == 'Pan, Peter'
def test_integer___len__(): SIZE = 8 sl = orderedstructs.SkipList(int_type) for i in range(SIZE): assert sl.size() == i assert len(sl) == i sl.insert(i)
def test_index(typ, value): sl = orderedstructs.SkipList(typ) assert sl.lacks_integrity() == 0 sl.insert(value) assert sl.lacks_integrity() == 0 assert sl.index(value) == 0 assert sl.lacks_integrity() == 0
def test_single_at(typ, value): sl = orderedstructs.SkipList(typ) assert sl.lacks_integrity() == 0 sl.insert(value) assert sl.lacks_integrity() == 0 assert sl.at(0) == value assert sl.lacks_integrity() == 0
def test_has_float_NaN_raises(): sl = orderedstructs.SkipList(float) assert sl.lacks_integrity() == 0 with pytest.raises(ValueError) as err: sl.has(math_nan) assert err.value.args[0] == \ 'Can not work with something that does not compare equal to itself.' assert sl.lacks_integrity() == 0
def test_ordered_refcount_after_del(cls): """Reference count is maintained after insert and then dealloc.""" obj = cls(0) rc = sys.getrefcount(obj) sl = orderedstructs.SkipList(object) sl.insert(obj) del sl assert sys.getrefcount(obj) == rc
def test_ordered_refcount_remove(cls): """Reference count is maintained on insert+remove.""" sl = orderedstructs.SkipList(object) obj = cls(0) rc = sys.getrefcount(obj) sl.insert(obj) sl.remove(obj) assert sys.getrefcount(obj) == rc
def test_node_width_raises(typ): sl = orderedstructs.SkipList(typ) with pytest.raises(TypeError): sl.node_width(1) with pytest.raises(TypeError): sl.node_width('1', 2) with pytest.raises(TypeError): sl.node_width(1, '2')
def test_index_raises_out_of_range(typ, value): sl = orderedstructs.SkipList(typ) assert sl.lacks_integrity() == 0 with pytest.raises(ValueError) as err: assert sl.index(value) == 0 assert err.value.args[0].startswith('Value ') assert err.value.args[0].endswith(' not found.') assert sl.lacks_integrity() == 0
def test_ordered_has_same_value_diff_id(cls): """Insert an object and check that an equivalent object is there.""" sl = orderedstructs.SkipList(object) obj_a = cls(0) sl.insert(obj_a) assert sl.has(obj_a) obj_b = cls(0) assert id(obj_a) != id(obj_b) assert sl.has(obj_b)
def test_index_sequence_reversed(typ, seq): sl = orderedstructs.SkipList(typ) assert sl.lacks_integrity() == 0 for value in seq: sl.insert(value) assert sl.lacks_integrity() == 0 reference = sorted(seq) for v in seq: assert reference.index(v) == sl.index(v)
def test_ctor_raises_no_type(): with pytest.raises(TypeError) as err: orderedstructs.SkipList() if sys.version_info.major == 3 and sys.version_info.minor >= 7: assert err.value.args[ 0] == "__init__() missing required argument 'value_type' (pos 1)" else: assert err.value.args[ 0] == "Required argument 'value_type' (pos 1) not found"
def test_at_seq_empty_fails(typ): sl = orderedstructs.SkipList(typ) assert sl.lacks_integrity() == 0 with pytest.raises(IndexError) as err: sl.at_seq(0, 0) assert err.value.args[0] == 'Index 0 out of range -1 < index <= -1' with pytest.raises(IndexError) as err: sl.at_seq(-1, 0) assert err.value.args[0] == 'Index -1 out of range -1 < index <= -1'
def test_at_seq(typ, seq): sl = orderedstructs.SkipList(typ) assert sl.lacks_integrity() == 0 for value in seq: sl.insert(value) assert sl.lacks_integrity() == 0 assert sl.at_seq(0, 0) == tuple() assert sl.at_seq(0, 2) == seq[:2] assert sl.at_seq(2, 2) == seq[2:4]
def test_single_remove(typ, value): sl = orderedstructs.SkipList(typ) assert sl.size() == 0 assert sl.lacks_integrity() == 0 assert sl.insert(value) is None assert sl.size() == 1 assert sl.remove(value) == value assert sl.lacks_integrity() == 0 assert sl.size() == 0
def test_single_insert_same_and_size(typ, value): sl = orderedstructs.SkipList(typ) for i in range(16): assert sl.lacks_integrity() == 0 assert sl.size() == i sl.insert(value) assert sl.has(value) assert sl.lacks_integrity() == 0 assert sl.size() == i + 1
def test_ordered_refcount_at(cls): """Reference count is incremented when at() is assigned.""" sl = orderedstructs.SkipList(object) obj = cls(0) rc = sys.getrefcount(obj) sl.insert(obj) assert sys.getrefcount(obj) == rc + 1 obj_at = sl.at(0) assert id(obj_at) == id(obj) assert sys.getrefcount(obj) == rc + 2