diff --git a/src/keri/core/counting.py b/src/keri/core/counting.py index 579df4253..be60e8d7c 100644 --- a/src/keri/core/counting.py +++ b/src/keri/core/counting.py @@ -5,15 +5,16 @@ Provides versioning support for Counter classes and codes """ -from dataclasses import dataclass, astuple - +from dataclasses import dataclass, astuple, asdict +from collections import namedtuple from ..help import helping from ..help.helping import sceil -from ..help.helping import (intToB64, b64ToInt, codeB64ToB2, codeB2ToB64, +from ..help.helping import (intToB64, b64ToInt, codeB64ToB2, codeB2ToB64, Reb64, nabSextets) from .. import kering +from ..kering import (Versionage, Version, Vrsn_1_0, Vrsn_2_0) from ..core.coring import Sizage @@ -78,7 +79,7 @@ def __delitem__(self, name): @dataclass(frozen=True) -class CounterCodex: +class CounterCodex_1_0(MapCodex): """ CounterCodex is codex hard (stable) part of all counter derivation codes. Only provide defined codes. @@ -104,11 +105,40 @@ class CounterCodex: def __iter__(self): return iter(astuple(self)) # enables value not key inclusion test with "in" -CtrDex = CounterCodex() +CtrDex_1_0 = CounterCodex_1_0() + +@dataclass(frozen=True) +class CounterCodex_2_0(MapCodex): + """ + CounterCodex is codex hard (stable) part of all counter derivation codes. + Only provide defined codes. + Undefined are left out so that inclusion(exclusion) via 'in' operator works. + """ + + ControllerIdxSigs: str = '-A' # Qualified Base64 Indexed Signature. + WitnessIdxSigs: str = '-B' # Qualified Base64 Indexed Signature. + NonTransReceiptCouples: str = '-C' # Composed Base64 Couple, pre+cig. + TransReceiptQuadruples: str = '-D' # Composed Base64 Quadruple, pre+snu+dig+sig. + FirstSeenReplayCouples: str = '-E' # Composed Base64 Couple, fnu+dts. + TransIdxSigGroups: str = '-F' # Composed Base64 Group, pre+snu+dig+ControllerIdxSigs group. + SealSourceCouples: str = '-G' # Composed Base64 couple, snu+dig of given delegator/issuer/transaction event + TransLastIdxSigGroups: str = '-H' # Composed Base64 Group, pre+ControllerIdxSigs group. + SealSourceTriples: str = '-I' # Composed Base64 triple, pre+snu+dig of anchoring source event + SadPathSig: str = '-J' # Composed Base64 Group path+TransIdxSigGroup of SAID of content + SadPathSigGroup: str = '-K' # Composed Base64 Group, root(path)+SaidPathCouples + PathedMaterialQuadlets: str = '-L' # Composed Grouped Pathed Material Quadlet (4 char each) + AttachedMaterialQuadlets: str = '-V' # Composed Grouped Attached Material Quadlet (4 char each) + BigAttachedMaterialQuadlets: str = '-0V' # Composed Grouped Attached Material Quadlet (4 char each) + KERIProtocolStack: str = '--AAA' # KERI ACDC Protocol Stack CESR Version + + def __iter__(self): + return iter(astuple(self)) # enables value not key inclusion test with "in" + +CtrDex_2_0 = CounterCodex_2_0() @dataclass(frozen=True) -class GenusCodex: +class GenusCodex(MapCodex): """GenusCodex is codex of protocol genera for code table. Only provide defined codes. @@ -125,6 +155,19 @@ def __iter__(self): GenDex = GenusCodex() # Make instance +# keys and values as strings of keys +Codict1 = asdict(CtrDex_1_0) +Tagage_1_0 = namedtuple("Tagage_1_0", list(Codict1), defaults=list(Codict1)) +Tags_1_0 = Tagage_1_0() # uses defaults + +Codict2 = asdict(CtrDex_2_0) +Tagage_2_0 = namedtuple("Tagage_2_0", list(Codict2), defaults=list(Codict2)) +Tags_2_0 = Tagage_2_0() # uses defaults + +CodictAll = Codict1 | Codict2 +AllTagage = namedtuple("AllTagage", list(CodictAll), defaults=list(CodictAll)) +AllTags = AllTagage() # uses defaults + """ Design Notes @@ -180,10 +223,21 @@ class Counter: Includes the following attributes and properties: + Class Attributes: + Codes + Tags + Hards + Bards + Sizes + Attributes: + Properties: - .code is str derivation code to indicate cypher suite + .version (Versionage): current CESR code table protocol genus version + .codes (CounterCodex_1_0 | CounterCodex_1_0): version specific codex + .sizes (dict): version specific sizes table + .code (str) derivation code to indicate cypher suite .raw is bytes crypto material only without code .pad is int number of pad chars given raw .count is int count of grouped following material (not part of counter) @@ -192,6 +246,9 @@ class Counter: .qb2 is bytes in binary with derivation code + crypto material Hidden: + ._version (Versionage): value for .version property + ._codes (CounterCodex_1_0 | CounterCodex_1_0): version specific codex + ._sizes (dict): version specific sizes table ._code is str value for .code property ._raw is bytes value for .raw property ._pad is method to compute .pad property @@ -200,6 +257,9 @@ class Counter: ._exfil is method to extract .code and .raw from fully qualified Base64 """ + Codes = {Vrsn_1_0: CtrDex_1_0, Vrsn_2_0: CtrDex_2_0} + Tags = {Vrsn_1_0: Tags_1_0, Vrsn_2_0: Tags_2_0} + # Hards table maps from bytes Base64 first two code chars to int of # hard size, hs,(stable) of code. The soft size, ss, (unstable) for Counter # is always > 0 and hs + ss = fs always @@ -217,6 +277,26 @@ class Counter: # soft size, ss, should always be > 0 and hs+ss=fs for Counter Sizes = \ { + Vrsn_1_0: \ + { + '-A': Sizage(hs=2, ss=2, fs=4, ls=0), + '-B': Sizage(hs=2, ss=2, fs=4, ls=0), + '-C': Sizage(hs=2, ss=2, fs=4, ls=0), + '-D': Sizage(hs=2, ss=2, fs=4, ls=0), + '-E': Sizage(hs=2, ss=2, fs=4, ls=0), + '-F': Sizage(hs=2, ss=2, fs=4, ls=0), + '-G': Sizage(hs=2, ss=2, fs=4, ls=0), + '-H': Sizage(hs=2, ss=2, fs=4, ls=0), + '-I': Sizage(hs=2, ss=2, fs=4, ls=0), + '-J': Sizage(hs=2, ss=2, fs=4, ls=0), + '-K': Sizage(hs=2, ss=2, fs=4, ls=0), + '-L': Sizage(hs=2, ss=2, fs=4, ls=0), + '-V': Sizage(hs=2, ss=2, fs=4, ls=0), + '-0V': Sizage(hs=3, ss=5, fs=8, ls=0), + '--AAA': Sizage(hs=5, ss=3, fs=8, ls=0), + }, + Vrsn_2_0: \ + { '-A': Sizage(hs=2, ss=2, fs=4, ls=0), '-B': Sizage(hs=2, ss=2, fs=4, ls=0), '-C': Sizage(hs=2, ss=2, fs=4, ls=0), @@ -232,17 +312,21 @@ class Counter: '-V': Sizage(hs=2, ss=2, fs=4, ls=0), '-0V': Sizage(hs=3, ss=5, fs=8, ls=0), '--AAA': Sizage(hs=5, ss=3, fs=8, ls=0), + }, } - Codex = CtrDex - - def __init__(self, code=None, count=None, countB64=None, - qb64b=None, qb64=None, qb2=None, strip=False): + def __init__(self, tag=None, *, code = None, count=None, countB64=None, + qb64b=None, qb64=None, qb2=None, strip=False, version=Version): """ Validate as fully qualified Parameters: + tag (str | None): label of stable (hard) part of derivation code + to lookup in codex so it can depend on version. + takes precedence over tag code (str | None): stable (hard) part of derivation code + if tag provided lookup code from tag + else if tag is None and code provided use code count (int | None): count for composition. Count may represent quadlets/triplet, groups, primitives or other numericy @@ -251,11 +335,16 @@ def __init__(self, code=None, count=None, countB64=None, countB64 may represent quadlets/triplet, groups, primitives or other numericy qb64b (bytes | bytearray | None): fully qualified crypto material text domain + if code nor tag is provided qb64 (str | None) fully qualified crypto material text domain + if code nor tag not qb64b is provided qb2 (bytes | bytearray | None) fully qualified crypto material binary domain + if code nor tag not qb64b nor qb54 is provided strip (bool): True means strip counter contents from input stream bytearray after parsing qb64b or qb2. False means do not strip. default False + version (Versionage): instance of version of code tables to use + provides protocol genera version Needs either code or qb64b or qb64 or qb2 @@ -265,11 +354,20 @@ def __init__(self, code=None, count=None, countB64=None, .code and .count """ + self._version = version + self._codes = self.Codes[self._version] + self._sizes = self.Sizes[self._version] + + if tag: + if not hasattr(self._codes, tag): + raise kering.InvalidCodeError(f"Unsupported {tag=}.") + code = self._codes[tag] + if code is not None: # code provided - if code not in self.Sizes: + if code not in self._sizes: raise kering.InvalidCodeError("Unsupported code={}.".format(code)) - hs, ss, fs, ls = self.Sizes[code] # get sizes for code + hs, ss, fs, ls = self._sizes[code] # get sizes for code cs = hs + ss # both hard + soft code size if fs != cs or cs % 4: # fs must be bs and multiple of 4 for count codes raise kering.InvalidCodeSizeError("Whole code size not full size or not " @@ -287,7 +385,7 @@ def __init__(self, code=None, count=None, countB64=None, elif qb64b is not None: self._exfil(qb64b) if strip: # assumes bytearray - del qb64b[:self.Sizes[self.code].fs] + del qb64b[:self._sizes[self.code].fs] elif qb64 is not None: self._exfil(qb64) @@ -295,13 +393,45 @@ def __init__(self, code=None, count=None, countB64=None, elif qb2 is not None: # rewrite to use direct binary exfiltration self._bexfil(qb2) if strip: # assumes bytearray - del qb2[:self.Sizes[self.code].fs * 3 // 4] + del qb2[:self._sizes[self.code].fs * 3 // 4] else: raise kering.EmptyMaterialError("Improper initialization need either " "(code and count) or qb64b or " "qb64 or qb2.") + @property + def version(self): + """ + Returns ._version + Makes .version read only + """ + return self._version + + @property + def codes(self): + """ + Returns ._codes + Makes .codes read only + """ + return self._codes + + @property + def tags(self): + """ + Returns ._tags + Makes .tags read only + """ + return self._tags + + @property + def sizes(self): + """ + Returns ._sizes + Makes .sizes read only + """ + return self._sizes + @property def code(self): """ @@ -357,44 +487,77 @@ def countToB64(self, l=None): """ if l is None: - _, ss, _, _ = self.Sizes[self.code] + _, ss, _, _ = self._sizes[self.code] l = ss return (intToB64(self.count, l=l)) @staticmethod - def semVerToB64(version="", major=0, minor=0, patch=0): - """ Converts semantic version to Base64 representation of countB64 + def verToB64(version=None, *, text="", major=0, minor=0): + """ Converts version to Base64 representation of countB64 suitable for CESR protocol genus and version Returns: countB64 (str): suitable for input to Counter - example: Counter(countB64=semVerToB64(version = "1.0.0")) - Parameters: - version (str | None): dot separated semantic version string of format - "major.minor.patch" - major (int): When version is None or empty then use major,minor, patch - minor (int): When version is None or empty then use major,minor, patch - patch (int): When version is None or empty then use major,minor, patch + Example: + Counter(countB64=Counter.verToB64(verstr = "1.0")) - each of major, minor, patch must be in range [0,63] for represenation as - three Base64 characters + Parameters: + version (Versionage): instange of namedtuple + Versionage(major=major,minor=minor) + text (str): text format of version as dotted decimal "major.minor" + major (int): When version is None and verstr is empty then use major minor + range [0, 63] for one Base64 character + minor (int): When version is None and verstr is empty then use major minor + range [0, 4095] for two Base64 characters """ - parts = [major, minor, patch] if version: - splits = version.split(".", maxsplit=3) + major = version.major + minor = version.minor + + elif text: + splits = text.split(".", maxsplit=2) splits = [(int(s) if s else 0) for s in splits] - for i in range(3-len(splits),0, -1): + parts = [major, minor] + for i in range(2-len(splits),0, -1): # append missing minor and/or major splits.append(parts[-i]) - parts = splits + major = splits[0] + minor = splits[1] + + if major < 0 or major > 63 or minor < 0 or minor > 4095: + raise ValueError(f"Out of bounds version = {major}.{minor}.") + + return (f"{intToB64(major)}{intToB64(minor, l=2)}") + + + @staticmethod + def b64ToVer(b64, *, texted=False): + """ Converts Base64 representation of version to Versionage or + text dotted decimal format + + default is Versionage + + Returns: + version (Versionage | str): + + Example: + Counter(version=Counter.b64ToVer("BAA")) + + Parameters: + b64 (str): base64 string of three characters Mmm for Major minor + texted (bool): return text format dotted decimal string + + + """ + if not Reb64.match(b64.encode("utf-8")): + raise ValueError("Invalid Base64.") + + if texted: + return ".".join([f"{b64ToInt(b64[0])}", f"{b64ToInt(b64[1:3])}"]) - for p in parts: - if p < 0 or p > 63: - raise ValueError(f"Out of bounds semantic version. " - f"Part={p} is < 0 or > 63.") - return ("".join(intToB64(p, l=1) for p in parts)) + return Versionage(major=b64ToInt(b64[0]), minor=b64ToInt(b64[1:3])) def _infil(self): @@ -405,7 +568,7 @@ def _infil(self): code = self.code # codex value chars hard code count = self.count # index value int used for soft - hs, ss, fs, ls = self.Sizes[code] + hs, ss, fs, ls = self._sizes[code] cs = hs + ss # both hard + soft size if fs != cs or cs % 4: # fs must be bs and multiple of 4 for count codes raise kering.InvalidCodeSizeError("Whole code size not full size or not " @@ -433,7 +596,7 @@ def _binfil(self): code = self.code # codex chars hard code count = self.count # index value int used for soft - hs, ss, fs, ls = self.Sizes[code] + hs, ss, fs, ls = self._sizes[code] cs = hs + ss if fs != cs or cs % 4: # fs must be cs and multiple of 4 for count codes raise kering.InvalidCodeSizeError("Whole code size not full size or not " @@ -475,10 +638,10 @@ def _exfil(self, qb64b): hard = qb64b[:hs] # get hard code if hasattr(hard, "decode"): hard = hard.decode("utf-8") # decode converts bytearray/bytes to str - if hard not in self.Sizes: # Sizes needs str not bytes + if hard not in self._sizes: # Sizes needs str not bytes raise kering.UnexpectedCodeError("Unsupported code ={}.".format(hard)) - hs, ss, fs, ls = self.Sizes[hard] # assumes hs consistent in both tables + hs, ss, fs, ls = self._sizes[hard] # assumes hs consistent in both tables cs = hs + ss # both hard + soft code size # assumes that unit tests on Counter and CounterCodex ensure that @@ -518,10 +681,10 @@ def _bexfil(self, qb2): raise kering.ShortageError("Need {} more bytes.".format(bhs - len(qb2))) hard = codeB2ToB64(qb2, hs) # extract and convert hard part of code - if hard not in self.Sizes: + if hard not in self._sizes: raise kering.UnexpectedCodeError("Unsupported code ={}.".format(hard)) - hs, ss, fs, ls = self.Sizes[hard] + hs, ss, fs, ls = self._sizes[hard] cs = hs + ss # both hs and ss # assumes that unit tests on Counter and CounterCodex ensure that # .Codes and .Sizes are well formed. diff --git a/tests/core/test_counting.py b/tests/core/test_counting.py index 51f709595..5547813dc 100644 --- a/tests/core/test_counting.py +++ b/tests/core/test_counting.py @@ -5,14 +5,22 @@ """ from dataclasses import dataclass, astuple, asdict from ordered_set import OrderedSet as oset +from base64 import urlsafe_b64encode as encodeB64 +from base64 import urlsafe_b64decode as decodeB64 import pytest from keri import kering +from keri.help import helping +from keri.help.helping import sceil +from keri.help.helping import (intToB64, b64ToInt, codeB64ToB2, codeB2ToB64, + nabSextets) + from keri.core import counting -from keri.core.counting import MapDom, MapCodex, Counter +from keri.core.counting import Sizage, MapDom, MapCodex, Counter +from keri.core.counting import Versionage, Version, Vrsn_1_0, Vrsn_2_0, AllTags def test_mapdom(): @@ -158,8 +166,862 @@ def __iter__(self): # so value in dataclass not key in dataclass """End Test""" +def test_codexes_tags(): + """ + Test supporting module attributes + """ + assert asdict(counting.CtrDex_1_0) == \ + { + 'ControllerIdxSigs': '-A', + 'WitnessIdxSigs': '-B', + 'NonTransReceiptCouples': '-C', + 'TransReceiptQuadruples': '-D', + 'FirstSeenReplayCouples': '-E', + 'TransIdxSigGroups': '-F', + 'SealSourceCouples': '-G', + 'TransLastIdxSigGroups': '-H', + 'SealSourceTriples': '-I', + 'SadPathSig': '-J', + 'SadPathSigGroup': '-K', + 'PathedMaterialQuadlets': '-L', + 'AttachedMaterialQuadlets': '-V', + 'BigAttachedMaterialQuadlets': '-0V', + 'KERIProtocolStack': '--AAA', + } + + assert asdict(counting.CtrDex_2_0) == \ + { + 'ControllerIdxSigs': '-A', + 'WitnessIdxSigs': '-B', + 'NonTransReceiptCouples': '-C', + 'TransReceiptQuadruples': '-D', + 'FirstSeenReplayCouples': '-E', + 'TransIdxSigGroups': '-F', + 'SealSourceCouples': '-G', + 'TransLastIdxSigGroups': '-H', + 'SealSourceTriples': '-I', + 'SadPathSig': '-J', + 'SadPathSigGroup': '-K', + 'PathedMaterialQuadlets': '-L', + 'AttachedMaterialQuadlets': '-V', + 'BigAttachedMaterialQuadlets': '-0V', + 'KERIProtocolStack': '--AAA', + } + + assert counting.Tags_1_0._asdict() == \ + { + 'ControllerIdxSigs': 'ControllerIdxSigs', + 'WitnessIdxSigs': 'WitnessIdxSigs', + 'NonTransReceiptCouples': 'NonTransReceiptCouples', + 'TransReceiptQuadruples': 'TransReceiptQuadruples', + 'FirstSeenReplayCouples': 'FirstSeenReplayCouples', + 'TransIdxSigGroups': 'TransIdxSigGroups', + 'SealSourceCouples': 'SealSourceCouples', + 'TransLastIdxSigGroups': 'TransLastIdxSigGroups', + 'SealSourceTriples': 'SealSourceTriples', + 'SadPathSig': 'SadPathSig', + 'SadPathSigGroup': 'SadPathSigGroup', + 'PathedMaterialQuadlets': 'PathedMaterialQuadlets', + 'AttachedMaterialQuadlets': 'AttachedMaterialQuadlets', + 'BigAttachedMaterialQuadlets': 'BigAttachedMaterialQuadlets', + 'KERIProtocolStack': 'KERIProtocolStack' + } + + assert counting.Tags_1_0.ControllerIdxSigs == 'ControllerIdxSigs' + + assert counting.Tags_2_0._asdict() == \ + { + 'ControllerIdxSigs': 'ControllerIdxSigs', + 'WitnessIdxSigs': 'WitnessIdxSigs', + 'NonTransReceiptCouples': 'NonTransReceiptCouples', + 'TransReceiptQuadruples': 'TransReceiptQuadruples', + 'FirstSeenReplayCouples': 'FirstSeenReplayCouples', + 'TransIdxSigGroups': 'TransIdxSigGroups', + 'SealSourceCouples': 'SealSourceCouples', + 'TransLastIdxSigGroups': 'TransLastIdxSigGroups', + 'SealSourceTriples': 'SealSourceTriples', + 'SadPathSig': 'SadPathSig', + 'SadPathSigGroup': 'SadPathSigGroup', + 'PathedMaterialQuadlets': 'PathedMaterialQuadlets', + 'AttachedMaterialQuadlets': 'AttachedMaterialQuadlets', + 'BigAttachedMaterialQuadlets': 'BigAttachedMaterialQuadlets', + 'KERIProtocolStack': 'KERIProtocolStack' + } + + assert counting.Tags_2_0.ControllerIdxSigs == 'ControllerIdxSigs' + + assert counting.AllTags._asdict() == \ + { + 'ControllerIdxSigs': 'ControllerIdxSigs', + 'WitnessIdxSigs': 'WitnessIdxSigs', + 'NonTransReceiptCouples': 'NonTransReceiptCouples', + 'TransReceiptQuadruples': 'TransReceiptQuadruples', + 'FirstSeenReplayCouples': 'FirstSeenReplayCouples', + 'TransIdxSigGroups': 'TransIdxSigGroups', + 'SealSourceCouples': 'SealSourceCouples', + 'TransLastIdxSigGroups': 'TransLastIdxSigGroups', + 'SealSourceTriples': 'SealSourceTriples', + 'SadPathSig': 'SadPathSig', + 'SadPathSigGroup': 'SadPathSigGroup', + 'PathedMaterialQuadlets': 'PathedMaterialQuadlets', + 'AttachedMaterialQuadlets': 'AttachedMaterialQuadlets', + 'BigAttachedMaterialQuadlets': 'BigAttachedMaterialQuadlets', + 'KERIProtocolStack': 'KERIProtocolStack' + } + + """End Test""" + + +def test_counter(): + """ + Test Counter class + """ + assert Counter.Codes == \ + { + counting.Vrsn_1_0: counting.CtrDex_1_0, + counting.Vrsn_2_0: counting.CtrDex_2_0, + } + + assert Counter.Tags == \ + { + counting.Vrsn_1_0: counting.Tags_1_0, + counting.Vrsn_2_0: counting.Tags_2_0, + } + + + # first character of code with hard size of code + assert Counter.Hards == \ + { + '-A': 2, '-B': 2, '-C': 2, '-D': 2, '-E': 2, '-F': 2, '-G': 2, '-H': 2, '-I': 2, + '-J': 2, '-K': 2, '-L': 2, '-M': 2, '-N': 2, '-O': 2, '-P': 2, '-Q': 2, '-R': 2, + '-S': 2, '-T': 2, '-U': 2, '-V': 2, '-W': 2, '-X': 2, '-Y': 2, '-Z': 2, + '-a': 2, '-b': 2, '-c': 2, '-d': 2, '-e': 2, '-f': 2, '-g': 2, '-h': 2, '-i': 2, + '-j': 2, '-k': 2, '-l': 2, '-m': 2, '-n': 2, '-o': 2, '-p': 2, '-q': 2, '-r': 2, + '-s': 2, '-t': 2, '-u': 2, '-v': 2, '-w': 2, '-x': 2, '-y': 2, '-z': 2, + '-0': 3, '--': 5, + } + + # Codes table with sizes of code (hard) and full primitive material + assert Counter.Sizes == \ + { + counting.Vrsn_1_0: \ + { + '-A': Sizage(hs=2, ss=2, fs=4, ls=0), + '-B': Sizage(hs=2, ss=2, fs=4, ls=0), + '-C': Sizage(hs=2, ss=2, fs=4, ls=0), + '-D': Sizage(hs=2, ss=2, fs=4, ls=0), + '-E': Sizage(hs=2, ss=2, fs=4, ls=0), + '-F': Sizage(hs=2, ss=2, fs=4, ls=0), + '-G': Sizage(hs=2, ss=2, fs=4, ls=0), + '-H': Sizage(hs=2, ss=2, fs=4, ls=0), + '-I': Sizage(hs=2, ss=2, fs=4, ls=0), + '-J': Sizage(hs=2, ss=2, fs=4, ls=0), + '-K': Sizage(hs=2, ss=2, fs=4, ls=0), + '-L': Sizage(hs=2, ss=2, fs=4, ls=0), + '-V': Sizage(hs=2, ss=2, fs=4, ls=0), + '-0V': Sizage(hs=3, ss=5, fs=8, ls=0), + '--AAA': Sizage(hs=5, ss=3, fs=8, ls=0) + }, + counting.Vrsn_2_0: \ + { + '-A': Sizage(hs=2, ss=2, fs=4, ls=0), + '-B': Sizage(hs=2, ss=2, fs=4, ls=0), + '-C': Sizage(hs=2, ss=2, fs=4, ls=0), + '-D': Sizage(hs=2, ss=2, fs=4, ls=0), + '-E': Sizage(hs=2, ss=2, fs=4, ls=0), + '-F': Sizage(hs=2, ss=2, fs=4, ls=0), + '-G': Sizage(hs=2, ss=2, fs=4, ls=0), + '-H': Sizage(hs=2, ss=2, fs=4, ls=0), + '-I': Sizage(hs=2, ss=2, fs=4, ls=0), + '-J': Sizage(hs=2, ss=2, fs=4, ls=0), + '-K': Sizage(hs=2, ss=2, fs=4, ls=0), + '-L': Sizage(hs=2, ss=2, fs=4, ls=0), + '-V': Sizage(hs=2, ss=2, fs=4, ls=0), + '-0V': Sizage(hs=3, ss=5, fs=8, ls=0), + '--AAA': Sizage(hs=5, ss=3, fs=8, ls=0) + } + } + + assert Counter.Sizes[counting.Vrsn_1_0]['-A'].hs == 2 # hard size + assert Counter.Sizes[counting.Vrsn_1_0]['-A'].ss == 2 # soft size + assert Counter.Sizes[counting.Vrsn_1_0]['-A'].fs == 4 # full size + assert Counter.Sizes[counting.Vrsn_1_0]['-A'].ls == 0 # lead size + + # verify first hs Sizes matches hs in Codes for same first char + for vsize in Counter.Sizes.values(): + for ckey, cval in vsize.items(): + assert Counter.Hards[ckey[:2]] == cval.hs + + # verify all Codes have hs > 0 and ss > 0 and fs = hs + ss and not fs % 4 + for vsize in Counter.Sizes.values(): + for val in vsize.values(): + assert val.hs > 0 and val.ss > 0 and val.hs + val.ss == val.fs and not val.fs % 4 + + # Bizes maps bytes of sextet of decoded first character of code with hard size of code + # verify equivalents of items for Sizes and Bizes + for skey, sval in Counter.Hards.items(): + ckey = codeB64ToB2(skey) + assert Counter.Bards[ckey] == sval + + # test Counter static methods + assert Counter.verToB64() == "AAA" + + assert Counter.b64ToVer('AAA') == Versionage(major=0, minor=0) + assert Counter.b64ToVer('AAA', texted=True) == "0.0" + assert Counter.b64ToVer('BBC', texted=True) == "1.66" + assert Counter.b64ToVer('bbc', texted=True) == '27.1756' + + with pytest.raises(ValueError): + Counter.b64ToVer("!AA") + + with pytest.raises(ValueError): + Counter.b64ToVer("AA#") + + assert Counter.b64ToVer(Counter.verToB64(text='1.1'), texted=True) == "1.1" + assert Counter.verToB64(text=Counter.b64ToVer('BAB', texted=True)) == "BAB" + assert Counter.b64ToVer(Counter.verToB64(text='12.2345'), texted=True) == '12.2345' + assert Counter.verToB64(text='12.2345') == 'Mkp' + assert Counter.verToB64(text=Counter.b64ToVer('Mkp', texted=True)) == 'Mkp' + + assert Counter.verToB64(counting.Vrsn_1_0) == "BAA" + assert Counter.verToB64(counting.Vrsn_2_0) == "CAA" + + assert Counter.verToB64(text="1.2") == "BAC" + + assert Counter.verToB64(major=1) == "BAA" + assert Counter.verToB64(minor=1) == "AAB" + assert Counter.verToB64(major=3, minor=4) == "DAE" + + # test defaults for missing parts in string version + assert Counter.verToB64(text="1.1") == "BAB" + assert Counter.verToB64(text="1.1.") == "BAB" # ignores extra parts + assert Counter.verToB64(text="1.1.0") == "BAB" # ignores extra parts + assert Counter.verToB64(text="1.") == "BAA" + assert Counter.verToB64(text="1") == "BAA" + assert Counter.verToB64(text="1.2") == "BAC" + assert Counter.verToB64(text=".") == "AAA" + assert Counter.verToB64(text="1.3") == "BAD" + assert Counter.verToB64(text="4", major=1, minor=2) == "EAC" + + with pytest.raises(ValueError): + Counter.verToB64(text="64.0") + with pytest.raises(ValueError): + Counter.verToB64(text="63.4096") + with pytest.raises(ValueError): + Counter.verToB64(text="-1.0") + with pytest.raises(ValueError): + Counter.verToB64(text="0.-1") + with pytest.raises(ValueError): + Counter.verToB64(major=64) + with pytest.raises(ValueError): + Counter.verToB64(minor=4096) + with pytest.raises(ValueError): + Counter.verToB64(major=-1) + with pytest.raises(ValueError): + Counter.verToB64(minor=-1) + + + + + + + """ Done Test """ + +def test_counter_v1(): + """ + test Counter instances for verision 1.0 code tables + """ + # test Counter instances + with pytest.raises(kering.EmptyMaterialError): + counter = Counter() + + # create code manually + count = 1 + qsc = counting.CtrDex_1_0.ControllerIdxSigs + intToB64(count, l=2) + assert qsc == '-AAB' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + # version 1_0 tests default version is Version + assert Version == Vrsn_1_0 + CtrDex = Counter.Codes[Version] # set CtrDex to Vrsn_1_0 + + counter = Counter(tag="ControllerIdxSigs", count=count) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(tag=AllTags.ControllerIdxSigs, count=count) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # test tag takes precedence + counter = Counter(tag=AllTags.ControllerIdxSigs, + code=CtrDex.WitnessIdxSigs, + count=count) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(code=CtrDex.ControllerIdxSigs) # default count = 1 + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64b=qscb) # test with bytes not str + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64=qsc) # test with str not bytes + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb2=qscb2) # test with qb2 + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # test truncates extra bytes from qb64 parameter + longqsc64 = qsc + "ABCD" + counter = Counter(qb64=longqsc64) + assert len(counter.qb64) == counter.sizes[counter.code].fs + + # test raises ShortageError if not enough bytes in qb64 parameter + shortqsc64 = qsc[:-1] # too short + with pytest.raises(kering.ShortageError): + counter = Counter(qb64=shortqsc64) + + # test truncates extra bytes from qb2 parameter + longqscb2 = qscb2 + bytearray([1, 2, 3, 4, 5]) # extra bytes in size + counter = Counter(qb2=longqscb2) + assert counter.qb2 == qscb2 + assert len(counter.qb64) == counter.sizes[counter.code].fs + + # test raises ShortageError if not enough bytes in qb2 parameter + shortqscb2 = qscb2[:-4] # too few bytes in size + with pytest.raises(kering.ShortageError): + counter = Counter(qb2=shortqscb2) + + # test with non-zero count=5 + count = 5 + qsc = CtrDex.ControllerIdxSigs + intToB64(count, l=2) + assert qsc == '-AAF' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(code=CtrDex.ControllerIdxSigs, count=count) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64b=qscb) # test with bytes not str + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64=qsc) # test with str not bytes + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb2=qscb2) # test with qb2 + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # test with big codes index=1024 + count = 1024 + qsc = CtrDex.BigAttachedMaterialQuadlets + intToB64(count, l=5) + assert qsc == '-0VAAAQA' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(code=CtrDex.BigAttachedMaterialQuadlets, count=count) + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64b=qscb) # test with bytes not str + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64=qsc) # test with str not bytes + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb2=qscb2) # test with qb2 + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # Test ._bexfil + counter = Counter(qb64=qsc) # + code = counter.code + count = counter.count + qb2 = counter.qb2 + counter._bexfil(qb2) + assert counter.code == code + assert counter.count == count + assert counter.qb64 == qsc + assert counter.qb2 == qb2 + + # Test ._binfil + test = counter._binfil() + assert test == qb2 + + # Test with strip + # create code manually + count = 1 + qsc = CtrDex.ControllerIdxSigs + intToB64(count, l=2) + assert qsc == '-AAB' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + # strip ignored if qb64 + counter = Counter(qb64=qsc, strip=True) # test with str not bytes + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + ims = bytearray(qscb) # test with qb64b + counter = Counter(qb64b=ims, strip=True) # strip + assert not ims # deleted + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + ims = bytearray(qscb2) # test with qb2 + counter = Counter(qb2=ims, strip=True) + assert not ims # deleted + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # test with longer ims for qb64b + extra = b"ABCD" + ims = bytearray(qscb + b"ABCD") + counter = Counter(qb64b=ims, strip=True) + assert counter.qb64b == qscb + assert len(counter.qb64b) == counter.sizes[counter.code].fs + assert ims == extra + + # test with longer ims for qb2 + extra = bytearray([1, 2, 3, 4, 5]) + ims = bytearray(qscb2) + extra + counter = Counter(qb2=ims, strip=True) + assert counter.qb2 == qscb2 + assert len(counter.qb2) == counter.sizes[counter.code].fs * 3 // 4 + assert ims == extra + + # raises error if not bytearray + + ims = bytes(qscb) # test with qb64b + with pytest.raises(TypeError): + counter = Counter(qb64b=ims, strip=True) # strip + + ims = bytes(qscb2) # test with qb2 + with pytest.raises(TypeError): + counter = Counter(qb2=ims, strip=True) + + # test with big codes index=1024 + count = 1024 + qsc = CtrDex.BigAttachedMaterialQuadlets + intToB64(count, l=5) + assert qsc == '-0VAAAQA' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + ims = bytearray(qscb) + counter = Counter(qb64b=ims, strip=True) # test with bytes not str + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + assert not ims + + ims = bytearray(qscb2) + counter = Counter(qb2=ims, strip=True) # test with qb2 + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + assert not ims + + # test protocol genus with CESR protocol genus version + # test with big codes index=1024 + genverint = 0 + genver = intToB64(genverint, l=3) + assert genver == 'AAA' + assert genverint == b64ToInt(genver) + qsc = CtrDex.KERIProtocolStack + genver + assert qsc == '--AAAAAA' # keri Cesr version 0.0.0 + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(code=CtrDex.KERIProtocolStack, count=genverint) + assert counter.code == CtrDex.KERIProtocolStack + assert counter.count == genverint + assert counter.countToB64(l=3) == genver + assert counter.countToB64() == genver # default length + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(code=CtrDex.KERIProtocolStack, countB64=genver) + assert counter.code == CtrDex.KERIProtocolStack + assert counter.count == genverint + assert counter.countToB64(l=3) == genver + assert counter.countToB64() == genver # default length + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + """End Test""" + +def test_counter_v2(): + """ + test Counter instances for verision 2.0 code tables + """ + # test Counter instances + with pytest.raises(kering.EmptyMaterialError): + counter = Counter() + + # create code manually + count = 1 + qsc = counting.CtrDex_1_0.ControllerIdxSigs + intToB64(count, l=2) + assert qsc == '-AAB' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + # version 2_0 tests default version is Version + #assert Version == Vrsn_2_0 + + CtrDex = Counter.Codes[Vrsn_2_0] # set CtrDex to Vrsn_2_0 + + # default count = 1 + counter = Counter(code=CtrDex.ControllerIdxSigs, version=Vrsn_2_0) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64b=qscb, version=Vrsn_2_0) # test with bytes not str + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64=qsc, version=Vrsn_2_0) # test with str not bytes + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb2=qscb2, version=Vrsn_2_0) # test with qb2 + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # test truncates extra bytes from qb64 parameter + longqsc64 = qsc + "ABCD" + counter = Counter(qb64=longqsc64, version=Vrsn_2_0) + assert len(counter.qb64) == counter.sizes[counter.code].fs + + # test raises ShortageError if not enough bytes in qb64 parameter + shortqsc64 = qsc[:-1] # too short + with pytest.raises(kering.ShortageError): + counter = Counter(qb64=shortqsc64, version=Vrsn_2_0) + + # test truncates extra bytes from qb2 parameter + longqscb2 = qscb2 + bytearray([1, 2, 3, 4, 5]) # extra bytes in size + counter = Counter(qb2=longqscb2, version=Vrsn_2_0) + assert counter.qb2 == qscb2 + assert len(counter.qb64) == counter.sizes[counter.code].fs + + # test raises ShortageError if not enough bytes in qb2 parameter + shortqscb2 = qscb2[:-4] # too few bytes in size + with pytest.raises(kering.ShortageError): + counter = Counter(qb2=shortqscb2, version=Vrsn_2_0) + + # test with non-zero count=5 + count = 5 + qsc = CtrDex.ControllerIdxSigs + intToB64(count, l=2) + assert qsc == '-AAF' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(tag="ControllerIdxSigs", count=count, version=Vrsn_2_0) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(tag=AllTags.ControllerIdxSigs, count=count, version=Vrsn_2_0) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # test tag takes precedence + counter = Counter(tag=AllTags.ControllerIdxSigs, + code=CtrDex.WitnessIdxSigs, + count=count, + version=Vrsn_2_0) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(code=CtrDex.ControllerIdxSigs, count=count, version=Vrsn_2_0) + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64b=qscb, version=Vrsn_2_0) # test with bytes not str + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64=qsc, version=Vrsn_2_0) # test with str not bytes + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb2=qscb2, version=Vrsn_2_0) # test with qb2 + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # test with big codes index=1024 + count = 1024 + qsc = CtrDex.BigAttachedMaterialQuadlets + intToB64(count, l=5) + assert qsc == '-0VAAAQA' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(code=CtrDex.BigAttachedMaterialQuadlets, count=count, version=Vrsn_2_0) + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64b=qscb, version=Vrsn_2_0) # test with bytes not str + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64=qsc, version=Vrsn_2_0) # test with str not bytes + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb2=qscb2, version=Vrsn_2_0) # test with qb2 + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # Test ._bexfil + counter = Counter(qb64=qsc, version=Vrsn_2_0) + code = counter.code + count = counter.count + qb2 = counter.qb2 + counter._bexfil(qb2) + assert counter.code == code + assert counter.count == count + assert counter.qb64 == qsc + assert counter.qb2 == qb2 + + # Test ._binfil + test = counter._binfil() + assert test == qb2 + + # Test with strip + # create code manually + count = 1 + qsc = CtrDex.ControllerIdxSigs + intToB64(count, l=2) + assert qsc == '-AAB' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + # strip ignored if qb64 + counter = Counter(qb64=qsc, strip=True, version=Vrsn_2_0) # test with str not bytes + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + ims = bytearray(qscb) # test with qb64b + counter = Counter(qb64b=ims, strip=True, version=Vrsn_2_0) # strip + assert not ims # deleted + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + ims = bytearray(qscb2) # test with qb2 + counter = Counter(qb2=ims, strip=True, version=Vrsn_2_0) + assert not ims # deleted + assert counter.code == CtrDex.ControllerIdxSigs + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # test with longer ims for qb64b + extra = b"ABCD" + ims = bytearray(qscb + b"ABCD") + counter = Counter(qb64b=ims, strip=True, version=Vrsn_2_0) + assert counter.qb64b == qscb + assert len(counter.qb64b) == counter.sizes[counter.code].fs + assert ims == extra + + # test with longer ims for qb2 + extra = bytearray([1, 2, 3, 4, 5]) + ims = bytearray(qscb2) + extra + counter = Counter(qb2=ims, strip=True, version=Vrsn_2_0) + assert counter.qb2 == qscb2 + assert len(counter.qb2) == counter.sizes[counter.code].fs * 3 // 4 + assert ims == extra + + # raises error if not bytearray + + ims = bytes(qscb) # test with qb64b + with pytest.raises(TypeError): + counter = Counter(qb64b=ims, strip=True, version=Vrsn_2_0) # strip + + ims = bytes(qscb2) # test with qb2 + with pytest.raises(TypeError): + counter = Counter(qb2=ims, strip=True, version=Vrsn_2_0) + + # test with big codes index=1024 + count = 1024 + qsc = CtrDex.BigAttachedMaterialQuadlets + intToB64(count, l=5) + assert qsc == '-0VAAAQA' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + ims = bytearray(qscb) + counter = Counter(qb64b=ims, strip=True, version=Vrsn_2_0) # test with bytes not str + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + assert not ims + + ims = bytearray(qscb2) + counter = Counter(qb2=ims, strip=True, version=Vrsn_2_0) # test with qb2 + assert counter.code == CtrDex.BigAttachedMaterialQuadlets + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + assert not ims + + # test protocol genus with CESR version + # test with big codes index=1024 + genverint = 0 + genver = intToB64(genverint, l=3) + assert genver == 'AAA' + assert genverint == b64ToInt(genver) + qsc = CtrDex.KERIProtocolStack + genver + assert qsc == '--AAAAAA' # keri Cesr version 0.0.0 + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(code=CtrDex.KERIProtocolStack, count=genverint, version=Vrsn_2_0) + assert counter.code == CtrDex.KERIProtocolStack + assert counter.count == genverint + assert counter.countToB64(l=3) == genver + assert counter.countToB64() == genver # default length + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(code=CtrDex.KERIProtocolStack, countB64=genver, version=Vrsn_2_0) + assert counter.code == CtrDex.KERIProtocolStack + assert counter.count == genverint + assert counter.countToB64(l=3) == genver + assert counter.countToB64() == genver # default length + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + """End Test""" + + if __name__ == "__main__": test_mapdom() test_mapcodex() + test_codexes_tags() + test_counter() + test_counter_v1() + test_counter_v2()