chiark / gitweb /
t/: Add a test suite.
[catacomb-python] / t / t-bytes.py
diff --git a/t/t-bytes.py b/t/t-bytes.py
new file mode 100644 (file)
index 0000000..6755e96
--- /dev/null
@@ -0,0 +1,162 @@
+### -*- mode: python, coding: utf-8 -*-
+###
+### Test `ByteString'
+###
+### (c) 2019 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to Catacomb.
+###
+### Catacomb/Python is free software: you can redistribute it and/or
+### modify it under the terms of the GNU General Public License as
+### published by the Free Software Foundation; either version 2 of the
+### License, or (at your option) any later version.
+###
+### Catacomb/Python is distributed in the hope that it will be useful, but
+### WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+### General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with Catacomb/Python.  If not, write to the Free Software
+### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+### USA.
+
+###--------------------------------------------------------------------------
+### Imported modules.
+
+import sys as SYS
+import catacomb as C
+import unittest as U
+import testutils as T
+
+###--------------------------------------------------------------------------
+class TestByteString (U.TestCase):
+
+  def test_create(me):
+
+    ## Create a string and make sure it looks right.
+    x = C.ByteString(T.bin("abcde"))
+    me.assertEqual(x, T.bin("abcde"))
+    me.assertEqual(x, C.bytes("6162636465"))
+    me.assertEqual(len(x), 5)
+
+  def test_index(me):
+
+    x = C.ByteString(T.bin("once upon a time there was a string"))
+
+    ## Check that simple indexing works.
+    me.assertEqual(x[3], 'e')
+    me.assertEqual(x[-5], 't')
+
+    ## Check out-of-range detection.
+    x[34]; me.assertRaises(IndexError, lambda: x[35])
+    x[-35]; me.assertRaises(IndexError, lambda: x[-36])
+
+    ## Check slicing.
+    me.assertEqual(x[7:17], T.bin("on a time "))
+
+    ## Complex slicing is also supported.
+    me.assertEqual(x[5:23:3], C.bytes("756e206d7472"))
+
+  def test_compare(me):
+    """
+    Test byte string comparison.
+
+    This is rather important, since we override it and many of the other
+    tests assume that comparison works.
+    """
+
+    def check(big, small):
+      """Check comparisons between BIG and SMALL strings."""
+
+      ## Equality.
+      me.assertTrue(big == big)
+      me.assertFalse(big == small)
+
+      ## Inequality.
+      me.assertFalse(big != big)
+      me.assertTrue(big != small)
+
+      ## Strict less-than.
+      me.assertFalse(big < big)
+      me.assertFalse(big < small)
+      me.assertTrue(small < big)
+
+      ## Non-strict less-than.
+      me.assertTrue(big <= big)
+      me.assertFalse(big <= small)
+      me.assertTrue(small <= big)
+
+      ## Non-strict greater-than.
+      me.assertTrue(big >= big)
+      me.assertTrue(big >= small)
+      me.assertFalse(small >= big)
+
+      ## Strict greater-than.
+      me.assertFalse(big > big)
+      me.assertTrue(big > small)
+      me.assertFalse(small > big)
+
+    ## Strings with equal length.
+    check(C.ByteString(T.bin("a string which is unlike the second")),
+          C.ByteString(T.bin("a string that is not like the first")))
+
+    ## A string and a prefix of it.
+    check(C.ByteString(T.bin("short strings order before longer ones")),
+          C.ByteString(T.bin("short string")))
+
+    ## The `ctstreq' function.
+    x = T.bin("special test string")
+    y = T.bin("my different string")
+    me.assertTrue(C.ctstreq(x, x))
+    me.assertFalse(C.ctstreq(x, y))
+
+  def test_operators(me):
+
+    ## Some example strings.
+    x = C.bytes("03a5fc")
+    y = C.bytes("5fac30")
+    z = C.bytes("00000000")
+
+    ## Operands of a binary operator must have equal lengths.
+    me.assertRaises(ValueError, lambda: x&z)
+    me.assertRaises(ValueError, lambda: x|z)
+    me.assertRaises(ValueError, lambda: x^z)
+
+    ## Bitwise AND.
+    me.assertEqual(type(x&y), C.ByteString)
+    me.assertEqual(x&y, C.bytes("03a430"))
+
+    ## Bitwise OR.
+    me.assertEqual(type(x | y), C.ByteString)
+    me.assertEqual(x | y, C.bytes("5fadfc"))
+
+    # Bitwise XOR.
+    me.assertEqual(type(x ^ y), C.ByteString)
+    me.assertEqual(x ^ y, C.bytes("5c09cc"))
+
+    # Bitwise NOT.
+    me.assertEqual(type(~x), C.ByteString)
+    me.assertEqual(~x, C.bytes("fc5a03"))
+
+    ## Concatenation.
+    me.assertEqual(x + y, C.bytes("03a5fc5fac30"))
+
+    ## Replication (asymmetric but commutative).
+    me.assertEqual(3*x, C.bytes("03a5fc03a5fc03a5fc"))
+    me.assertEqual(x*3, C.bytes("03a5fc03a5fc03a5fc"))
+
+    ## Replication by zero (regression test).
+    me.assertEqual(0*x, C.ByteString(T.bin("")))
+    me.assertEqual(x*0, C.ByteString(T.bin("")))
+
+  def test_zero(me):
+    me.assertEqual(C.ByteString.zero(7), T.bin(7*"\0"))
+    me.assertEqual(C.ByteString.zero(0), T.bin(""))
+
+###----- That's all, folks --------------------------------------------------
+
+if __name__ == "__main__": U.main()