from atomiclong import AtomicLong, ffi, lib

def test_long_add_and_fetch():
    l = ffi.new('long *', 0)
    assert lib.long_add_and_fetch(l, 1) == 1
    assert lib.long_add_and_fetch(l, 10) == 11

def test_long_sub_and_fetch():
    l = ffi.new('long *', 0)
    assert lib.long_sub_and_fetch(l, 1) == -1
    assert lib.long_sub_and_fetch(l, 10) == -11

def test_long_bool_compare_and_swap():
    l = ffi.new('long *', 0)
    assert lib.long_bool_compare_and_swap(l, 0, 10) == True
    assert lib.long_bool_compare_and_swap(l, 1, 20) == False

def test_atomiclong_repr():
    l = AtomicLong(123456789)
    assert '<AtomicLong at ' in repr(l)
    assert '123456789>' in repr(l)

def test_atomiclong_value():
    l = AtomicLong(0)
    assert l.value == 0
    l.value = 10
    assert l.value == 10

def test_atomiclong_iadd():
    l = AtomicLong(0)
    l += 10
    assert l.value == 10

def test_atomiclong_isub():
    l = AtomicLong(0)
    l -= 10
    assert l.value == -10

def test_atomiclong_eq():
    l1 = AtomicLong(0)
    l2 = AtomicLong(1)
    l3 = AtomicLong(0)
    assert l1 == 0
    assert l1 != 1
    assert not (l2 == 0)
    assert not (l2 != 1)
    assert l1 == l3
    assert not (l1 != l3)
    assert l1 != l2
    assert not (l1 == l2)
    assert l1 == l1

def test_atomiclong_ordering():
    l1 = AtomicLong(0)
    l2 = AtomicLong(1)
    l3 = AtomicLong(0)

    assert l1 < l2
    assert l1 <= l2
    assert l1 <= l3
    assert l2 > l1
    assert l2 >= l3
    assert l2 >= l2

    assert l1 < 1
    assert l1 <= 0
    assert l1 <= 1
    assert l1 > -1
    assert l1 >= -1
    assert l1 >= 0

@@ -1592,12 +1592,823 @@
 ert l1 %3E= 0%0A
+%0Adef test_atomiclong_self_comparison_race():%0A    %22%22%22%0A    When comparing an AtomicLong to itself, it is possible that%0A    self.value and other.value will not be equal because the underlying%0A    long may have been incremented by another thread during the comparison.%0A%0A    Here we simulate this situation by ensuring that AtomicLong.value returns%0A    two different numbers during the comparisons, by swapping out the%0A    underlying storage for an object that pops items off a list.%0A    %22%22%22%0A    class StubStorage(object):%0A        def __init__(self, values):%0A            self._values = values%0A%0A        def __getitem__(self, _idx):%0A            return self._values.pop()%0A%0A    l1 = AtomicLong(0)%0A%0A    l1._storage = StubStorage(%5B0, 1%5D)%0A    assert l1 == l1%0A%0A    l1._storage = StubStorage(%5B0, 1%5D)%0A    assert not (l1 %3C l1)%0A

Add a failing test case for our alex's race condition.