def test_and(): x = Bits(8)(0b11001100) y = Bits(8)(0b11110000) assert x & y == 0b11000000 assert x & 0b1010 == 0b00001000 assert 0b1010 & x == 0b00001000
def test_or(): x = Bits(8)(0b11001100) y = Bits(8)(0b11110000) assert x | y == 0b11111100 assert x | 0b1010 == 0b11001110 assert 0b1010 | x == 0b11001110
def test_index_array(): data = range(2**4) # Indexing into an array x = Bits(4)(3) assert data[x] == 3 # Note, this converts -2 to unsigned, so 14! y = Bits(4)(-2) assert data[y] == 14 # Larger bitwidths work as long as the list is big enough a = Bits(8)(4) assert data[a] == 4 # If not, regular indexing error b = Bits(8)(20) with pytest.raises(IndexError): data[b] # Same with negative that become out of range when converted to unsigned c = Bits(8)(-1) with pytest.raises(IndexError): data[c]
def test_slice_bounds_checking(): x = Bits(4)(0b1100) with pytest.raises(IndexError): assert x[1:5] == 0b10 with pytest.raises(IndexError): assert x[-1:2] == 0b10 with pytest.raises(IndexError): assert x[2:1] == 0b10 with pytest.raises(IndexError): x[1:5] = 0b10 with pytest.raises(IndexError): x[-1:2] = 0b10 with pytest.raises(IndexError): x[2:1] = 0b10 # FIXED # Bits objects constructed with another Bits object provided as a value # parameter end up having problems when writing to slices. This is # because the mask used when writing to a subslice is often a negative # int in Python, and we don't allow operations on Bits to be performed # with negative values. Current workaround is to force the value param # for the Bits constructor to be an int or a long. #with pytest.raises( AssertionError ): y = Bits(4)(Bits(4)(0)) y[1:3] = 1
def test_invert(): x = Bits(4)(0b0001) assert ~x == 0b1110 x = Bits(4)(0b1001) assert ~x == 0b0110 x = Bits(16)(0b1111000011110000) assert ~x == 0b0000111100001111
def test_neg_assign(): x = Bits(4)(-1) assert x == 0b1111 assert x.uint() == 0b1111 x = Bits(4)(-2) assert x == 0b1110 assert x.uint() == 0b1110
def test_sext(): assert sext(Bits(4)(2), 8) == Bits(8)(0x02) assert sext(Bits(4)(4), 8) == Bits(8)(0x04) assert sext(Bits(4)(15), 8) == Bits(8)(0xff) assert sext(Bits(4)(-2), 8) == Bits(8)(0xfe) assert sext(Bits(4)(-4), 8) == Bits(8)(0xfc)
def test_zext(): assert zext(Bits(4)(2), 8) == Bits(8)(0x02) assert zext(Bits(4)(4), 8) == Bits(8)(0x04) assert zext(Bits(4)(15), 8) == Bits(8)(0x0f) assert zext(Bits(4)(-2), 8) == Bits(8)(0x0e) assert zext(Bits(4)(-4), 8) == Bits(8)(0x0c)
def test_set_single_bit(): x = Bits(4)(0b1100) x[3] = 0 assert x.uint() == 0b0100 x[2] = 1 assert x.uint() == 0b0100 x[1] = 1 assert x.uint() == 0b0110
def test_gt(): x = Bits(4)(0b1100) y = Bits(4)(0b0011) assert x.uint() > y.uint() assert x.uint() > 2 assert x > y.uint() assert x > 2 assert x > y assert 9 > y
def test_lt(): x = Bits(4)(0b1100) y = Bits(4)(0b0011) assert y.uint() < x.uint() assert y.uint() < 10 assert y < x.uint() assert y < 10 assert y < x assert 1 < y
def test_lshift(): x = Bits(8)(0b1100) y = Bits(8)(4) assert x << y == 0b11000000 assert x << 4 == 0b11000000 assert x << 6 == 0b00000000 assert y << x == 0b00000000 assert y << 0 == 0b00000100 assert y << 1 == 0b00001000
def test_set_slice(): x = Bits(4)(0b1100) x[:] = 0b0010 assert x.uint() == 0b0010 x[2:4] = 0b11 assert x.uint() == 0b1110 x[0:1] = 0b1 assert x.uint() == 0b1111 x[1:3] = 0b10 assert x.uint() == 0b1101 # check open ended ranges x[1:] = 0b001 assert x.uint() == 0b0011 x[:3] = 0b110 assert x.uint() == 0b0110 with pytest.raises(ValueError): x[1:3] = 0b110 x[:] = 0b1111 assert x.uint() == 0b1111 with pytest.raises(ValueError): x[:] = 0b10000 with pytest.raises(IndexError): x[::2] = 0b00 assert x == 0b1010
def test_xor(): x = Bits(8)(0b11001100) y = Bits(8)(0b11110000) assert x ^ y == 0b00111100 assert x ^ 0b1010 == 0b11000110 assert 0b1010 ^ x == 0b11000110 a = Bits(1)(1) b = Bits(1)(0) c = Bits(1)(1) assert (a ^ b) ^ c == 0
def test_slice_bits(): data = Bits(8)(0b1101) # Indexing into a bits x = Bits(4)(2) assert data[:] == 0b1101 assert data[x:] == 0b11 assert data[:x] == 0b01 with pytest.raises(IndexError): assert data[x:x] == 0b1
def test_return_type(): x = Bits(8)(0b1100) Bits1 = Bits(1) Bits4 = Bits(4) assert isinstance( x.uint(), int ) assert isinstance( x.int(), int ) assert isinstance( x[1:2], Bits1 ) assert isinstance( x[0:4], Bits4 ) assert isinstance( x[2], Bits1 )
def test_rshift(): x = Bits(8)(0b11000000) y = Bits(8)(4) assert x >> y == 0b00001100 assert x >> 7 == 0b00000001 assert x >> 8 == 0b00000000 assert x >> 10 == 0b00000000 x = Bits(8)(2) assert y >> x == 0b00000001 assert y >> 0 == 0b00000100 assert y >> 2 == 0b00000001 assert y >> 5 == 0b00000000
def test_set_slice(): x = Bits(4)(0b1100) x[:] = 0b0010 assert x.uint() == 0b0010 x[2:4] = 0b11 assert x.uint() == 0b1110 x[0:1] = 0b1 assert x.uint() == 0b1111 x[1:3] = 0b10 assert x.uint() == 0b1101 # check open ended ranges x[1:] = 0b001 assert x.uint() == 0b0011 x[:3] = 0b110 assert x.uint() == 0b0110 with pytest.raises( ValueError ): x[1:3] = 0b110 x[:] = 0b1111 assert x.uint() == 0b1111 with pytest.raises( ValueError ): x[:] = 0b10000 with pytest.raises( IndexError ): x[::2] = 0b00 assert x == 0b1010
def test_ne(): x = Bits(4)(0b1100) y = Bits(4)(0b0011) # TODO: check width? assert x.uint() != y.uint() assert x != y # added for bug z = Bits(1)(0) assert z.uint() != 1L assert z != 1L assert 5 != x assert z != None assert Bits(4)(0) != None
def test_str(): assert Bits(4)(0x2).__str__() == "2" assert Bits(8)(0x1f).__str__() == "1f" assert Bits(32)(0x0000beef).__str__() == "0000beef" # FIXED # Bits objects constructed with another Bits object provided as a value # parameter end up having problems when printed. This is because the # internal ._uint field is expected to be an int/long, but is instead # a Bits object, which cannot be formatted as expected. Current # workaround is to force the value param for the Bits constructor to be # an int or a long. #with pytest.raises( ValueError ): #with pytest.raises( AssertionError ): # assert Bits(4)( Bits(32)(2) ).__str__() == "2" assert Bits(4)(Bits(32)(2)).__str__() == "2"
def test_get_single_bit(): x = Bits(4)(0b1100) assert x[3] == 1 assert x[2] == 1 assert x[1] == 0 assert x[0] == 0
def test_int(): assert Bits(4)(0).int() == 0 assert Bits(4)(2).int() == 2 assert Bits(4)(4).int() == 4 assert Bits(4)(15).int() == -1 assert Bits(4)(-1).int() == -1 assert Bits(4)(-2).int() == -2 assert Bits(4)(-4).int() == -4 assert Bits(4)(-8).int() == -8
def test_mult(): x = Bits(8)(0b00000000) y = Bits(8)(0b00000000) assert x * y == 0b0000000000000000 assert x * 0b1000 == 0b0000000000000000 x = Bits(8)(0b11111111) y = Bits(8)(0b11111111) assert x * y == 0b0000000000000001111111000000001 assert x * 0b11111111 == 0b0000000000000001111111000000001 assert 0b11111111 * x == 0b0000000000000001111111000000001 # TODO: Currently fails as the second operand is larger than the Bits # object x. Should update the test when we define the behaviour #assert x * 0b1111111111 == 0b0000000000000001111111000000001 y = Bits(8)(0b10000000) assert x * y == 0b0000000000000000111111110000000
def test_reduce_or(): assert reduce_or(Bits(2)(0b11)) == 1 assert reduce_or(Bits(2)(0b01)) == 1 assert reduce_or(Bits(2)(0b10)) == 1 assert reduce_or(Bits(2)(0b00)) == 0 assert reduce_or(Bits(4)(0b1111)) == 1 assert reduce_or(Bits(4)(0b1010)) == 1 assert reduce_or(Bits(4)(0b0101)) == 1 assert reduce_or(Bits(4)(0b0000)) == 0
def main(): equivalent([32], alphanum.numbers_to_data, bits.Bits(32)) equivalent(0, alphanum.data_to_numbers, []) equivalent(1, alphanum.data_to_numbers, [1]) equivalent(65, alphanum.data_to_numbers, [1, 1]) equivalent(1000, base16(bits.data_to_numbers), [3, 14, 8]) equivalent(5, washers.data_to_base4, "11") equivalent(18, washers.data_to_base4, "102") equivalent(26, washers.data_to_base4, "122") equivalent("11", washers.base4_to_data, 5) equivalent("102", washers.base4_to_data, 18) equivalent("122", washers.base4_to_data, 26) equivalent(Bits(0b11001100), base16(bits.data_to_numbers), [12, 12]) equivalent("1", washers.base4_to_numbers, [1]) equivalent("000", washers.base4_to_numbers, [0, 0, 0]) def base_64_to_offset(letters): return bip39.numbers_to_offsets(alphanum.base64_to_numbers(letters)) equivalent('AAAAAAAAAA', base_64_to_offset, [0]) equivalent('AAAAAAAAAB', base_64_to_offset, [1]) equivalent('AAAAAAAAABAAAAAAAAA', base_64_to_offset, [1]) equivalent('AAAAAAAAABAAAAAAAAAC', base_64_to_offset, [1, 2]) equivalent('//////////', base_64_to_offset, [2047]) equivalent('///////////////////+', base_64_to_offset, [2047, 2046]) def offset_by_0(word): return bip39.offset_by(word, 0) def offset_by_1(word): return bip39.offset_by(word, 1) def offset_by_2047(word): return bip39.offset_by(word, 2047) equivalent('abandon', offset_by_0, 'abandon') equivalent('abandon', offset_by_1, 'ability') equivalent('abandon', offset_by_2047, 'zoo') equivalent('bread', offset_by_2047, 'brave') mnemonic = [ 'merit', 'average', 'fragile', 'smart', 'end', 'mom', 'knock', 'bid', 'era', 'crisp', 'romance', 'grace' ] bitstream = bip39.mnemonic_to_bitstream(mnemonic) equivalent(deepcopy(bitstream), bip39.bitstream_to_mnemonic, mnemonic) equivalent(mnemonic, bip39.mnemonic_to_bitstream, deepcopy(bitstream))
def test_uint(): assert Bits(4)(0).uint() == 0 assert Bits(4)(2).uint() == 2 assert Bits(4)(4).uint() == 4 assert Bits(4)(15).uint() == 15 assert Bits(4)(-1).uint() == 15 assert Bits(4)(-2).uint() == 14 assert Bits(4)(-4).uint() == 12
def test_bad_constructor(): from bits import BitsN # Correct instantiation of a BitsN object using the Bits factory y = Bits(3) # Incorrect instantiation of a BitsN object using BitsN directly with pytest.raises(TypeError): x = BitsN(5)
def test_constructor(): Bits4 = Bits(4) assert Bits4( 2).uint() == 2 assert Bits4( 4).uint() == 4 assert Bits4(15).uint() == 15 assert Bits4(-2).uint() == 0b1110 assert Bits4(-4).uint() == 0b1100 # Bits(N) returns a class, Bits(N)(value) creates an instance! with pytest.raises( AssertionError ): assert Bits4 == Bits(4)(0) with pytest.raises( AssertionError ): assert Bits(4) == Bits(4)(0) # Bits(N) returns a class, not an instance! # Does not have methods until instantiated! with pytest.raises( TypeError ): assert Bits4.uint() == 0 with pytest.raises( TypeError ): assert Bits(4).uint() == 0 # Sanity checks of subclassing. Note that all types (classes) are # objects, but object instances are objects, but not **not** types! assert isinstance( Bits4, type ) assert isinstance( Bits4, object ) assert not isinstance( Bits4(0), type ) assert isinstance( Bits4(0), object ) assert isinstance( Bits(4), type ) assert isinstance( Bits(4), object ) assert not isinstance( Bits(4)(0), type ) assert isinstance( Bits(4)(0), object )
def test_add(): x, y = [Bits(4)(4)] * 2 # simple (no overflow condition) assert x + y == 8 assert x + Bits(4)(4) == 8 assert x + 4 == 8 # don't extend bitwidth if added to int: overflow! assert (x + 14).nbits == x.nbits assert x + 14 == 2 and (x + 14).nbits == 4 assert 14 + x == 2 and (14 + x).nbits == 4 # infer wider bitwidth if both operands are Bits: no overflow possible! y = Bits(4)(14) assert x + y == 18 and (x + y).nbits == 5 assert y + x == 18 and (x + y).nbits == 5 a = Bits(4)(1) b = Bits(4)(1) c = Bits(1)(1) assert a + b + 1 == 3 assert a + b + c == 3 assert c + b + a == 3
def test_index_bits(): data = Bits(8)(0b11001010) # Indexing into a bits x = Bits(4)(3) assert data[x] == 1 # Note, this converts -8 to unsigned, so 8! Out of range! y = Bits(4)(-8) with pytest.raises(IndexError): data[y] # Larger bitwidths work as long as the list is big enough a = Bits(8)(4) assert data[a] == 0 # If not, regular indexing error b = Bits(8)(20) with pytest.raises(IndexError): data[b] # Same with negative that become out of range when converted to unsigned c = Bits(8)(-1) with pytest.raises(IndexError): data[c]
def test_constructor_bounds_checking(): Bits(4)(15) with pytest.raises(ValueError): Bits(4)(16) Bits(4)(-8) with pytest.raises(ValueError): Bits(4)(-9) with pytest.raises(ValueError): Bits(4)(-16) Bits(1)(0) Bits(1)(1) with pytest.raises(ValueError): Bits(1)(-1) with pytest.raises(ValueError): Bits(1)(-2)
def test_get_slice(): x = Bits(4)(0b1100) assert x[:] == 0b1100 assert x[2:4] == 0b11 assert x[0:1] == 0b0 assert x[1:3] == 0b10 # check open ended ranges assert x[1:] == 0b110 assert x[:3] == 0b100 with pytest.raises(IndexError): assert x[::2] == 0b01
def test_sub(): x, y = [Bits(4)(5), Bits(4)(4)] # simple (no overflow condition) assert x - y == 1 assert x - Bits(4)(4) == 1 assert x - 4 == 1 y = Bits(4)(5) assert x - y == 0 and (x - y).nbits == 5 assert x - 5 == 0 and (x - 5).nbits == 4 # infer wider bitwidth if both operands are Bits: no overflow possible! y = Bits(4)(7) assert x - y == 0b11110 and (x - y).nbits == 5 assert y - x == 0b00010 and (x - y).nbits == 5 # don't extend bitwidth if added to int: overflow! assert x - 7 == 0b1110 and (x - 7).nbits == 4 assert 7 - x == 0b0010 and (7 - x).nbits == 4 assert 9 - x == 0b0100 and (9 - x).nbits == 4
def test_lte(): x = Bits(4)(0b1100) y = Bits(4)(0b0011) z = Bits(4)(0b0011) assert y.uint() <= x.uint() assert y.uint() <= 10 assert y.uint() <= z.uint() assert y.uint() <= 0b0011 assert y <= x.uint() assert y <= 10 assert y <= z.uint() assert y <= 0b0011 assert y <= x assert y <= z assert z <= x assert z <= z assert 1 <= y assert 3 <= y
def test_gte(): x = Bits(4)(0b1100) y = Bits(4)(0b0011) z = Bits(4)(0b1100) assert x.uint() >= y.uint() assert x.uint() >= 2 assert x.uint() >= z.uint() assert x.uint() >= 0b1100 assert x >= y.uint() assert x >= 2 assert x >= z.uint() assert x >= 0b1100 assert x >= y assert x >= z assert z >= y assert z >= x assert x >= x assert 5 >= y assert 3 <= y
def test_eq(): x = Bits(4)(0b1010) assert x.uint() == x.uint() # Compare objects by value, not id assert x == x # Check the value assert x.uint() == 0b1010 assert x.uint() == 0xA assert x.uint() == 10 # Checking the equality operator assert x == 0b1010 assert x == 0xA assert x == 10 # Checking comparison with another bit container y = Bits(4)(0b1010) assert x.uint() == y.uint() assert x == y y = Bits( 8 )(0b1010) assert x.uint() == y.uint() # TODO: How should equality between Bits objects work? # Just same value or same value and width? #assert x == y # Check the negatives x = Bits(4)(-1) assert x.uint() == 0b1111 assert x.uint() == 0xF assert x.uint() == 15 # Checking the equality operator assert x == 0b1111 assert x == 0xF assert x == 15 assert x.uint() == Bits(4)(-1).uint() assert x == Bits(4)(-1).uint() assert 15 == x assert not x == None assert not Bits(4)(0) == None
def test_compare_uint_neg(): x = Bits(4)(2) assert x.uint() != -1 assert x.uint() > -1 assert x.uint() >= -1
def test_compare_int_neg(): x = Bits(4)(-2) assert x.int() == -2 assert x.int() < -1 assert x.int() <= -1