diff options
| author | Floris Bruynooghe <flub@google.com> | 2019-10-08 23:03:12 +0200 |
|---|---|---|
| committer | David Bremner <david@tethera.net> | 2019-12-03 08:12:30 -0400 |
| commit | 83c2d158983875bf77a9b7662894df585b61741c (patch) | |
| tree | 8443e3ab530a9cbf00b17c395f03e19138d3bae0 /bindings/python-cffi/tests/test_base.py | |
| parent | 5f9ea4d2908a597acaf0b809b6f27fa74b70520b (diff) | |
Introduce CFFI-based python bindings
This introduces CFFI-based Python3-only bindings.
The bindings aim at:
- Better performance on pypy
- Easier to use Python-C interface
- More "pythonic"
- The API should not allow invalid operations
- Use native object protocol where possible
- Memory safety; whatever you do from python, it should not coredump.
Diffstat (limited to 'bindings/python-cffi/tests/test_base.py')
| -rw-r--r-- | bindings/python-cffi/tests/test_base.py | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/bindings/python-cffi/tests/test_base.py b/bindings/python-cffi/tests/test_base.py new file mode 100644 index 00000000..b6d3d62c --- /dev/null +++ b/bindings/python-cffi/tests/test_base.py @@ -0,0 +1,116 @@ +import pytest + +from notdb import _base as base +from notdb import _errors as errors + + +class TestNotmuchObject: + + def test_no_impl_methods(self): + class Object(base.NotmuchObject): + pass + with pytest.raises(TypeError): + Object() + + def test_impl_methods(self): + + class Object(base.NotmuchObject): + + def __init__(self): + pass + + @property + def alive(self): + pass + + def _destroy(self, parent=False): + pass + + Object() + + def test_del(self): + destroyed = False + + class Object(base.NotmuchObject): + + def __init__(self): + pass + + @property + def alive(self): + pass + + def _destroy(self, parent=False): + nonlocal destroyed + destroyed = True + + o = Object() + o.__del__() + assert destroyed + + +class TestMemoryPointer: + + @pytest.fixture + def obj(self): + class Cls: + ptr = base.MemoryPointer() + return Cls() + + def test_unset(self, obj): + with pytest.raises(errors.ObjectDestroyedError): + obj.ptr + + def test_set(self, obj): + obj.ptr = 'some' + assert obj.ptr == 'some' + + def test_cleared(self, obj): + obj.ptr = 'some' + obj.ptr + obj.ptr = None + with pytest.raises(errors.ObjectDestroyedError): + obj.ptr + + def test_two_instances(self, obj): + obj2 = obj.__class__() + obj.ptr = 'foo' + obj2.ptr = 'bar' + assert obj.ptr != obj2.ptr + + +class TestBinString: + + def test_type(self): + s = base.BinString(b'foo') + assert isinstance(s, str) + + def test_init_bytes(self): + s = base.BinString(b'foo') + assert s == 'foo' + + def test_init_str(self): + s = base.BinString('foo') + assert s == 'foo' + + def test_bytes(self): + s = base.BinString(b'foo') + assert bytes(s) == b'foo' + + def test_invalid_utf8(self): + s = base.BinString(b'\x80foo') + assert s == 'foo' + assert bytes(s) == b'\x80foo' + + def test_errors(self): + s = base.BinString(b'\x80foo', errors='replace') + assert s == '�foo' + assert bytes(s) == b'\x80foo' + + def test_encoding(self): + # pound sign: '£' == '\u00a3' latin-1: b'\xa3', utf-8: b'\xc2\xa3' + with pytest.raises(UnicodeDecodeError): + base.BinString(b'\xa3', errors='strict') + s = base.BinString(b'\xa3', encoding='latin-1', errors='strict') + assert s == '£' + assert bytes(s) == b'\xa3' |
