[esnacc-dev] [RFC] python: Introduce Python library

Aaron Conole aconole at bytheb.org
Tue Dec 13 21:11:39 UTC 2016


This commit introduces ASN.1 primitive types for ASN.1 Integer,
Enumerated, Octet-String, RelativeOID, OID, Bit-String, and the various
collected string types.

Additionally, a tiny buffer system is added.

Signed-off-by: Aaron Conole <aconole at bytheb.org>
---
This is an early feedback release.  There is still quite a bit to do, but it
should be usable for decoding integers, enums, and octet strings.

 py-lib/.gitignore                   |   1 +
 py-lib/esnacc/__init__.py           |   7 ++
 py-lib/esnacc/asn_base.py           | 103 +++++++++++++++++++
 py-lib/esnacc/asn_buffer.py         | 119 ++++++++++++++++++++++
 py-lib/esnacc/asn_ints.py           | 188 +++++++++++++++++++++++++++++++++++
 py-lib/esnacc/asn_octs.py           |  93 +++++++++++++++++
 py-lib/esnacctests/__init__.py      |   7 ++
 py-lib/esnacctests/asn_ints_test.py | 192 ++++++++++++++++++++++++++++++++++++
 8 files changed, 710 insertions(+)
 create mode 100644 py-lib/.gitignore
 create mode 100644 py-lib/esnacc/__init__.py
 create mode 100644 py-lib/esnacc/asn_base.py
 create mode 100644 py-lib/esnacc/asn_buffer.py
 create mode 100644 py-lib/esnacc/asn_ints.py
 create mode 100644 py-lib/esnacc/asn_octs.py
 create mode 100644 py-lib/esnacctests/__init__.py
 create mode 100755 py-lib/esnacctests/asn_ints_test.py

diff --git a/py-lib/.gitignore b/py-lib/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/py-lib/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/py-lib/esnacc/__init__.py b/py-lib/esnacc/__init__.py
new file mode 100644
index 0000000..c274353
--- /dev/null
+++ b/py-lib/esnacc/__init__.py
@@ -0,0 +1,7 @@
+# Copyright (C) 2016, Aaron Conole <aconole at bytheb.org>
+#
+# Licensed under the terms of the GNU General Public License
+# agreement (version 2 or greater).  Alternately, may be licensed
+# under the terms of the ESNACC Public License.
+#
+# This file intentionally blank...
diff --git a/py-lib/esnacc/asn_base.py b/py-lib/esnacc/asn_base.py
new file mode 100644
index 0000000..148a438
--- /dev/null
+++ b/py-lib/esnacc/asn_base.py
@@ -0,0 +1,103 @@
+# Copyright (C) 2016, Aaron Conole <aconole at bytheb.org>
+#
+# Licensed under the terms of the GNU General Public License
+# agreement (version 2 or greater).  Alternately, may be licensed
+# under the terms of the ESNACC Public License.
+#
+# ASN.1 Base type for eSNACC
+
+from asn_buffer import BDecDefLen
+from asn_buffer import BEncDefLen
+
+
+class Constraint(object):
+    def __init__(self):
+        pass
+
+    def withinConstraint(self, value):
+        raise NotImplementedError
+
+
+class BERConsts(object):
+    BER_ANY_CLASS = -2
+    BER_NULL_CLASS = -1
+    BER_UNIVERSAL_CLASS = 0
+    BER_APPLICATION_CLASS = 1
+    BER_CONTEXTUAL_CLASS = 2
+    BER_PRIVATE_CLASS = 3
+
+    BER_ANY_FORM = -2
+    BER_NULL_FORM = -1
+    BER_PRIMITIVE_FORM = 0
+    BER_CONSTRUCTED_FORM = 1
+
+
+class AsnBase(object):
+    def __init__(self):
+        pass
+
+    def typename(self):
+        raise NotImplementedError
+
+    def passesAllConstraints(self, constraints):
+        return True
+
+    def addConstraint(self, constraint):
+        if not self.constraints:
+            self.constraints = []
+        self.constraints.append(constraint)
+
+    def BEncContent(self, asnbuf):
+        raise NotImplementedError
+
+    def BDecContent(self, asnbuf, contentlen):
+        raise NotImplementedError
+
+    def BEnc(self, asnbuf):
+        if self.constraints is not None and \
+           not self.passesAllConstraints(self.constraints):
+            raise ValueError("Not all constraints passed")
+
+        asnlen = self.BEncContent(asnbuf)
+        asnlen += BEncDefLen(asnbuf, asnlen)
+        TAG_CODE = BERConsts.BER_UNIVERSAL_CLASS & 0xff | \
+            BERConsts.BER_PRIMITIVE_FORM & 0xff | \
+            self.BER_TAG & 0xff
+        asnlen += asnbuf.PutBufReverse(chr(TAG_CODE))
+        return asnlen
+
+    def BDec(self, asnbuf, asnlen):
+        bufTag = ord(asnbuf.Buffer()[0])
+
+        PRIM_TAG = BERConsts.BER_UNIVERSAL_CLASS & 0xff | \
+            BERConsts.BER_PRIMITIVE_FORM & 0xff | \
+            self.BER_TAG & 0xff
+        CONS_TAG = BERConsts.BER_UNIVERSAL_CLASS & 0xff | \
+            BERConsts.BER_CONSTRUCTED_FORM & 0xff | \
+            self.BER_TAG & 0xff
+
+        if bufTag != PRIM_TAG and bufTag != CONS_TAG:
+            raise IOError("Invalid bytes 0x%02x expected [0x%02x|0x%02x]" %
+                          (ord(bufTag), ord(PRIM_TAG), ord(CONS_TAG)))
+
+        asnbuf.swallow(1)
+        asnlen += 1
+        tag_total_len, totalBytesLength = BDecDefLen(asnbuf)
+        asnlen += tag_total_len
+        asnlen += totalBytesLength
+        self.BDecContent(asnbuf, totalBytesLength)
+        return asnlen
+
+    def BEncPdu(self, asnbuf, asnlen):
+        try:
+            asnlen = self.BEnc(asnbuf)
+        except Exception:
+            return False
+        return True, asnlen
+
+    def BDecPdu(self, asnbuf, asnlen):
+        try:
+            asnlen = self.BDec(asnbuf, asnlen)
+        except Exception:
+            return False
+        return True, asnlen
diff --git a/py-lib/esnacc/asn_buffer.py b/py-lib/esnacc/asn_buffer.py
new file mode 100644
index 0000000..c9a368c
--- /dev/null
+++ b/py-lib/esnacc/asn_buffer.py
@@ -0,0 +1,119 @@
+# Copyright (C) 2016, Aaron Conole <aconole at bytheb.org>
+#
+# Licensed under the terms of the GNU General Public License
+# agreement (version 2 or greater).  Alternately, may be licensed
+# under the terms of the ESNACC Public License.
+#
+# ASN.1 Buffer library for eSNACC
+
+
+def ints2octs(listOfInts):
+    return [chr(int(x)) for x in listOfInts]
+
+
+def BEncDefLen(asnbuf, length):
+    if length < 128:
+        asnbuf.PutBufReverse(chr(length & 0xff))
+        return 1
+    elif length < 256:
+        asnbuf.PutBufReverse(chr(length & 0xff))
+        asnbuf.PutBufReverse(chr(0x81))
+        return 2
+    elif length < 65536:
+        asnbuf.PutBufReverse(chr(length & 0xff))
+        asnbuf.PutBufReverse(chr((length & 0xff00) >> 8))
+        asnbuf.PutBufReverse(chr(0x82))
+        return 3
+    elif length < 16777126:
+        asnbuf.PutBufReverse(chr(length & 0xff))
+        asnbuf.PutBufReverse(chr((length & 0xff00) >> 8))
+        asnbuf.PutBufReverse(chr((length & 0xff0000) >> 16))
+        asnbuf.PutBufReverse(chr(0x83))
+        return 4
+    else:
+        asnbuf.PutBufReverse(chr(length & 0xff))
+        asnbuf.PutBufReverse(chr((length & 0xff00) >> 8))
+        asnbuf.PutBufReverse(chr((length & 0xff0000) >> 16))
+        asnbuf.PutBufReverse(chr((length & 0xff000000) >> 24))
+        asnbuf.PutBufReverse(chr(0x84))
+        return 5
+
+
+def BDecDefLen(asnbuf):
+    lenByte = ord(asnbuf.GetByte())
+    if lenByte < 128:
+        return 1, lenByte
+    elif lenByte == 0x80:
+        raise IOError("INDEFINITE length not supported")
+
+    bytesTotal = lenByte & 0x7f
+    lenByte = 0
+    for b in range(bytesTotal):
+        lenByte = lenByte << 8
+        lenByte += asnbuf.GetByte()
+    return bytesTotal, lenByte
+
+
+class AsnBuf(object):
+
+    def __init__(self, bufbytes=None):
+        if bufbytes is None:
+            self.buf = []
+        else:
+            self.buf = bufbytes
+
+    def __len__(self):
+        return len(self.buf)
+
+    def PutBufReverse(self, listOf):
+        length = 0
+        if isinstance(listOf, list):
+            for x in reversed(listOf):
+                length += self.PutBufReverse(x)
+        else:
+            self.buf.insert(0, listOf)
+            length = 1
+        return length
+
+    def PutBufIntsReverse(self, listOfInts):
+        return self.PutBufReverse(ints2octs(listOfInts))
+
+    def PutBuf(self, listOf):
+        length = 0
+        if isinstance(listOf, list):
+            for x in listOf:
+                length += self.PutBuf(x)
+        else:
+            self.buf.append(listOf)
+            length = 1
+        return length
+
+    def PutBufInts(self, listOfInts):
+        return self.PutBuf(ints2octs(listOfInts))
+
+    def Buffer(self):
+        return self.buf
+
+    def swallow(self, num):
+        if len(self.buf) < num:
+            raise ValueError("Too many bytes to swallow")
+
+        for x in range(num):
+            del self.buf[0]
+
+    def GetByte(self):
+        ret = self.buf[0]
+        self.swallow(1)
+        return ret
+
+    def GetSeg(self, length):
+        ret = []
+
+        if len(self.buf) < length:
+            raise ValueError("Too many bytes specified")
+
+        for x in range(length):
+            ret.append(self.buf[0])
+            del self.buf[0]
+
+        return ret
diff --git a/py-lib/esnacc/asn_ints.py b/py-lib/esnacc/asn_ints.py
new file mode 100644
index 0000000..85a6b96
--- /dev/null
+++ b/py-lib/esnacc/asn_ints.py
@@ -0,0 +1,188 @@
+# Copyright (C) 2016, Aaron Conole <aconole at bytheb.org>
+#
+# Licensed under the terms of the GNU General Public License
+# agreement (version 2 or greater).  Alternately, may be licensed
+# under the terms of the ESNACC Public License.
+#
+# ASN.1 Integer Types for eSNACC
+
+from asn_base import AsnBase
+from asn_base import Constraint
+from asn_buffer import AsnBuf
+
+
+class IntegerConstraint(Constraint):
+    def __init__(self, lowerBound=None, upperBound=None):
+        self.lower = lowerBound
+        self.upper = upperBound
+
+    def withinConstraint(self, value):
+        if self.lower is not None and value is not None and value < self.lower:
+            return False
+        if self.upper is not None and value is not None and value > self.upper:
+            return False
+        return True
+
+
+def isfundamental_int_type(value):
+    if isinstance(value, int) or isinstance(value, float) or \
+       isinstance(value, basestring):
+        return True
+    return False
+
+
+class AsnInt(AsnBase):
+
+    BER_TAG = 0x2
+
+    def __init__(self, value=None):
+        self.constraints = None
+        if value is None:
+            self.intVal = 0
+        elif isfundamental_int_type(value):
+            self.intVal = int(value)
+        elif isinstance(value, AsnInt):
+            self.intVal = value.intVal
+        else:
+            raise ValueError("AsnInt - bad value")
+
+    def __cmp__(self, obj):
+        cmpValA = self.intVal
+        if isinstance(obj, int):
+            cmpValB = obj
+        elif isinstance(obj, AsnInt):
+            cmpValB = obj.intVal
+        elif isinstance(obj, basestring) or isinstance(obj, float):
+            cmpValB = int(obj)
+        else:
+            raise TypeError("Compare with int, or AsnInt")
+        return cmp(cmpValA, cmpValB)
+
+    def value(self, newval=None):
+        if newval is not None:
+            if isinstance(newval, int) or isinstance(newval, float) or \
+               isinstance(newval, basestring):
+                self.intVal = int(newval)
+            elif isinstance(newval, AsnInt):
+                self.intVal = newval.intVal
+        return self.intVal
+
+    def __int__(self):
+        return self.value()
+
+    def __float__(self):
+        return float(self.intVal)
+
+    def __add__(self, obj):
+        if isinstance(obj, AsnInt):
+            return self.intVal + obj.intVal
+        return self.intVal + int(obj)
+
+    def __iadd__(self, obj):
+        if isinstance(obj, AsnInt):
+            self.intVal += obj.intVal
+        else:
+            self.intVal += int(obj)
+        return self
+
+    def __sub__(self, obj):
+        if isinstance(obj, AsnInt):
+            return self.intVal - obj.intVal
+        return self.intVal - int(obj)
+
+    def __isub__(self, obj):
+        if isinstance(obj, AsnInt):
+            self.intVal -= obj.intVal
+        else:
+            self.intVal -= int(obj)
+        return self
+
+    def __mul__(self, obj):
+        if isinstance(obj, AsnInt):
+            return self.intVal * obj.intVal
+        return self.intVal * obj
+
+    def __imul__(self, obj):
+        if isinstance(obj, AsnInt):
+            self.intVal *= obj.intVal
+        else:
+            self.intVal *= obj
+        return self
+
+    def typename(self):
+        return "AsnInt"
+
+    def passesAllConstraints(self, constraints):
+        if constraints is None:
+            return True
+        if isinstance(constraints, IntegerConstraint):
+            return constraints.withinConstraint(self.intVal)
+        elif isinstance(constraints, list):
+            for x in constraints:
+                if not self.passesAllConstraints(x):
+                    return False
+        return True
+
+    def BEncContent(self, asnbuf):
+        if not isinstance(asnbuf, AsnBuf):
+            raise ValueError("Buffer must be esnacc.asn_buf.AsnBuf")
+
+        octets = []
+        value = self.intVal
+        while 1:
+            octets.insert(0, value & 0xff)
+            if value == 0 or value == -1:
+                break
+            value = value >> 8
+        if value == 0 and octets[0] & 0x80:
+            octets.insert(0, 0)
+        while len(octets) > 1 and \
+            (octets[0] == 0 and octets[1] & 0x80 == 0 or
+             octets[0] == 0xff and octets[1] & 0x80 != 0):
+            del octets[0]
+
+        asnbuf.PutBufIntsReverse(octets)
+        return len(octets)
+
+    def BDecContent(self, asnbuf, intlen):
+        buf = ord(asnbuf.Buffer()[0])
+        result = 0
+        if buf & 0x80:
+            result = -1
+
+        for x in range(intlen):
+            result <<= 8
+            result |= ord(asnbuf.GetByte())
+        self.intVal = result
+        return intlen
+
+
+class EnumeratedConstraint(Constraint):
+    def __init__(self, listOfEnumerations):
+        self.enums = listOfEnumerations
+
+    def withinConstraint(self, value):
+        if value not in self.enums:
+            return False
+        return True
+
+
+class AsnEnum(AsnInt):
+    BER_TAG = 0xa
+
+    def __init__(self, val=None):
+        self.constraints = None
+        if val is not None:
+            self.intVal = val
+
+    def passesAllConstraints(self, constraints):
+        if constraints is None:
+            return True
+        if isinstance(constraints, IntegerConstraint) \
+           or isinstance(constraints, EnumeratedConstraint):
+            return constraints.withinConstraint(self.intVal)
+        elif isinstance(constraints, list):
+            for x in constraints:
+                if not self.passesAllConstraints(x):
+                    return False
+        return True
diff --git a/py-lib/esnacc/asn_octs.py b/py-lib/esnacc/asn_octs.py
new file mode 100644
index 0000000..b3682e7
--- /dev/null
+++ b/py-lib/esnacc/asn_octs.py
@@ -0,0 +1,93 @@
+# Copyright (C) 2016, Aaron Conole <aconole at bytheb.org>
+#
+# Licensed under the terms of the GNU General Public License
+# agreement (version 2 or greater).  Alternately, may be licensed
+# under the terms of the ESNACC Public License.
+#
+# ASN.1 Integer Types for eSNACC
+
+from asn_base import AsnBase
+from asn_base import Constraint
+
+
+class CharacterValueConstraint(Constraint):
+    def __init__(self, lowerBound=None, upperBound=None, charList=None):
+        self.lower = lowerBound
+        self.upper = upperBound
+        self.chars = charList
+
+    def withinConstraint(self, value):
+        if isinstance(value, list) or isinstance(value, basestring):
+            for x in value:
+                if self.withinConstraint(x):
+                    return False
+        if self.lower is not None and value is not None and \
+           value < self.lower:
+            return False
+        if self.upper is not None and value is not None and \
+           value > self.upper:
+            return False
+        if self.chars is not None and value is not None and \
+           value not in self.chars:
+            return False
+        return True
+
+
+class OctetLengthConstraint(Constraint):
+    def __init__(self, length=None):
+        self.length = length
+
+    def withinConstraint(self, value):
+        if isinstance(value, list) or isinstance(value, basestring):
+            if len(value) <= self.length:
+                return True
+        return False
+
+
+class AsnOcts(AsnBase):
+    BER_TAG = 4
+
+    def __init__(self, octets=None):
+        self.constraints = None
+        self.octs = None
+        if octets is not None:
+            self.setData(octets)
+
+    def __getitem__(self, idx):
+        if self.octs is None or idx > len(self.octs):
+            raise IndexError("Octet value out of range")
+        return self.octs[idx]
+
+    def __contains__(self, a):
+        if self.octs is not None:
+            return a in self.octs
+        return None
+
+    def __len__(self):
+        if self.octs is not None:
+            return len(self.octs)
+        return 0
+
+    def __delitem__(self, idx):
+        if self.octs is not None:
+            del self.octs[idx]
+        raise IndexError("Out of range")
+
+    def octs(self):
+        return self.octs
+
+    def setData(self, octets):
+        if isinstance(octets, list):
+            self.octs = octets
+        elif isinstance(octets, basestring):
+            self.octs = []
+            for x in octets:
+                self.octs.append(chr(ord(x)))
+
+    def BEncContent(self, asnbuf):
+        asnbuf.PutBufReverse(self.octs)
+        return len(self.octs)
+
+    def BDecContent(self, asnbuf, contentlen):
+        self.octs = asnbuf.GetSeg(contentlen)
+        return len(self.octs)
diff --git a/py-lib/esnacctests/__init__.py b/py-lib/esnacctests/__init__.py
new file mode 100644
index 0000000..c274353
--- /dev/null
+++ b/py-lib/esnacctests/__init__.py
@@ -0,0 +1,7 @@
+# Copyright (C) 2016, Aaron Conole <aconole at bytheb.org>
+#
+# Licensed under the terms of the GNU General Public License
+# agreement (version 2 or greater).  Alternately, may be licensed
+# under the terms of the ESNACC Public License.
+#
+# This file intentionally blank...
diff --git a/py-lib/esnacctests/asn_ints_test.py b/py-lib/esnacctests/asn_ints_test.py
new file mode 100755
index 0000000..4258940
--- /dev/null
+++ b/py-lib/esnacctests/asn_ints_test.py
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+# Copyright (C) 2016, Aaron Conole <aconole at bytheb.org>
+#
+# Licensed under the terms of the GNU General Public License
+# agreement (version 2 or greater).  Alternately, may be licensed
+# under the terms of the ESNACC Public License.
+#
+# ESNACC ASN.1 integer tests
+
+import unittest
+if __package__ is None:
+    import sys
+    from os import path
+    sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
+    from esnacc import asn_ints
+    from esnacc import asn_buffer
+else:
+    from ..esnacc import asn_ints
+    from ..esnacc import asn_buffer
+
+class TestAsnInts(unittest.TestCase):
+    def test_operations_default(self):
+        asninteger = asn_ints.AsnInt(1)
+
+        self.assertTrue(asninteger == 1)
+        self.assertTrue(asninteger > 0)
+        self.assertTrue(asninteger < 2)
+
+        asninteger += 1
+
+        self.assertTrue(asninteger == 2)
+        self.assertTrue((asninteger * 1) == 2)
+        self.assertTrue((asninteger - 1) == 1)
+
+    def test_ber_encoder_simple(self):
+        class testVec(unittest.TestCase):
+            def __init__(self, number, length, byteCodes):
+                self.nm = number
+                self.ln = length
+                self.bc = byteCodes
+
+            def run(self):
+                asninteger = asn_ints.AsnInt(self.nm)
+                asnbuf = asn_buffer.AsnBuf()
+
+                self.assertTrue(asninteger.BEnc(asnbuf) == self.ln)
+                byteCodes = asnbuf.Buffer()
+                self.assertTrue(len(byteCodes) == len(self.bc))
+                for x in range(len(byteCodes)):
+                    self.assertTrue(self.bc[x] == byteCodes[x])
+                return True
+
+        tests = []
+        tvn65535codes = [chr(0x2), chr(0x3), chr(0xff), chr(0x0), chr(0x1)]
+        tests.append(testVec(-65535, 5, tvn65535codes))
+
+        tvn10codes = [chr(0x2), chr(0x1), chr(0xf6)]
+        tests.append(testVec(-10, 3, tvn10codes))
+
+        tv0codes = [chr(0x2), chr(0x1), chr(0x0)]
+        tests.append(testVec(0, 3, tv0codes))
+
+        tv1codes = [chr(0x2), chr(0x1), chr(0x1)]
+        tests.append(testVec(1, 3, tv1codes))
+
+        tv2codes = [chr(0x2), chr(0x2), chr(0x3f), chr(0xc3)]
+        tests.append(testVec(16323, 4, tv2codes))
+
+        tv3codes = [chr(0x2), chr(02), chr(0x7f), chr(0xff)]
+        tests.append(testVec(32767, 4, tv3codes))
+
+        tv4codes = [chr(0x2), chr(0x3), chr(0x00), chr(0x80), chr(0x00)]
+        tests.append(testVec(32768, 5, tv4codes))
+
+        tv5codes = [chr(0x2), chr(0x3), chr(0x20), chr(0x00), chr(0x00)]
+        tests.append(testVec(2097152, 5, tv5codes))
+
+        tv6codes = [chr(0x2), chr(0x4), chr(0x1), chr(0x0), chr(0x0), chr(0x0)]
+        tests.append(testVec(16777216, 6, tv6codes))
+
+        for x in tests:
+            self.assertTrue(x.run())
+
+    def test_ber_decoder_simple(self):
+        class testVec(unittest.TestCase):
+            def __init__(self, number, length, byteCodes):
+                self.nm = number
+                self.ln = length
+                self.bc = byteCodes
+
+            def run(self):
+                asnbuf = asn_buffer.AsnBuf(self.bc)
+                asninteger = asn_ints.AsnInt()
+                self.assertTrue(asninteger.BDec(asnbuf, 0) == self.ln)
+                self.assertTrue(self.nm == int(asninteger))
+                return True
+
+        tests = []
+        tvn65535codes = [chr(0x2), chr(0x3), chr(0xff), chr(0x0), chr(0x1)]
+        tests.append(testVec(-65535, 5, tvn65535codes))
+
+        tvn10codes = [chr(0x2), chr(0x1), chr(0xf6)]
+        tests.append(testVec(-10, 3, tvn10codes))
+
+        tv0codes = [chr(0x2), chr(0x1), chr(0x0)]
+        tests.append(testVec(0, 3, tv0codes))
+
+        tv1codes = [chr(0x2), chr(0x1), chr(0x1)]
+        tests.append(testVec(1, 3, tv1codes))
+
+        tv2codes = [chr(0x2), chr(0x2), chr(0x3f), chr(0xc3)]
+        tests.append(testVec(16323, 4, tv2codes))
+
+        tv3codes = [chr(0x2), chr(02), chr(0x7f), chr(0xff)]
+        tests.append(testVec(32767, 4, tv3codes))
+
+        tv4codes = [chr(0x2), chr(0x3), chr(0x00), chr(0x80), chr(0x00)]
+        tests.append(testVec(32768, 5, tv4codes))
+
+        tv5codes = [chr(0x2), chr(0x3), chr(0x20), chr(0x00), chr(0x00)]
+        tests.append(testVec(2097152, 5, tv5codes))
+
+        tv6codes = [chr(0x2), chr(0x4), chr(0x1), chr(0x0), chr(0x0), chr(0x0)]
+        tests.append(testVec(16777216, 6, tv6codes))
+
+        for x in tests:
+            self.assertTrue(x.run())
+        
+
+    def test_constraints(self):
+        class testVec(unittest.TestCase):
+            def __init__(self, number):
+                self.nm = number
+
+            def run(self):
+                cnstraint_good = asn_ints.IntegerConstraint(self.nm-1, self.nm+1)
+                asninteger = asn_ints.AsnInt(self.nm)
+                asninteger.addConstraint(cnstraint_good)
+
+                buf = asn_buffer.AsnBuf()
+                self.assertTrue(asninteger.BEnc(buf) != 0)
+
+                cnstraint_bad = asn_ints.IntegerConstraint(self.nm+1, self.nm+2)
+                asninteger.addConstraint(cnstraint_bad)
+                with self.assertRaises(ValueError):
+                    asninteger.BEnc(buf)
+                return True
+
+        tests = []
+        tests.append(testVec(-65535))
+        tests.append(testVec(-10))
+        tests.append(testVec(0))
+        tests.append(testVec(1))
+        tests.append(testVec(16323))
+        tests.append(testVec(32767))
+        tests.append(testVec(32768))
+        tests.append(testVec(2097152))
+        tests.append(testVec(16777216))
+
+        for x in tests:
+            self.assertTrue(x.run())
+
+class TestAsnEnums(unittest.TestCase):
+    def test_enumeration_encoding(self):
+        class testVec(unittest.TestCase):
+            def __init__(self, number, length, byteCodes):
+                self.nm = number
+                self.ln = length
+                self.bc = byteCodes
+
+            def run(self):
+                asnenum = asn_ints.AsnEnum(self.nm)
+                asnbuf = asn_buffer.AsnBuf()
+
+                self.assertTrue(asnenum.BEnc(asnbuf) == self.ln)
+                byteCodes = asnbuf.Buffer()
+                self.assertTrue(len(byteCodes) == len(self.bc))
+                for x in range(len(byteCodes)):
+                    self.assertTrue(self.bc[x] == byteCodes[x])
+                return True
+
+        tests = []
+        tv0codes = [chr(0xa), chr(0x1), chr(0x0)]
+        tests.append(testVec(0, 3, tv0codes))
+
+        for x in tests:
+            self.assertTrue(x.run())
+
+
+if __name__ == '__main__':
+
+    unittest.main()
-- 
2.7.4



More information about the dev mailing list