Skip to content

Commit

Permalink
tests: add versify and deversify tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kentbull committed Aug 18, 2024
1 parent 07872af commit bbe4729
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 19 deletions.
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export { Codex } from './lib/digests.js'
export { versify } from './lib/versions.js'
export { deversify } from './lib/versions.js'
export { rematch } from './lib/versions.js'
export { Rever } from './lib/versions.js'
export { ReverV1, ReverV2, VER1FULLSPAN, VER2FULLSPAN } from './lib/versions.js'
export { Vrsn_2_0 } from './lib/versions.js'
export { Vrsn_1_0 } from './lib/versions.js'
export { Vrsn_1_0, Vrsn_1_1 } from './lib/versions.js'
export { Version } from './lib/versions.js'
2 changes: 1 addition & 1 deletion src/lib/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export function serialize(data: Dict<any>, kind?: Serials): Uint8Array {
* }
* const label = 'd';
* const said = deriveSAIDBytes(myData, label);
* console.log(said); // ELOaxFqMsS9NFeJiDpKTb3X-xJahjNbh13QoBPnSxMWV TODO update this with the correct SAID
* // you can now use this SAID Uint8Array to create a fully qualified Base64 SAID
* ```
*
* @param data - data to derive self-addressing data from and to add to as a prop labeled by `label`
Expand Down
133 changes: 133 additions & 0 deletions src/lib/versions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { describe, expect, it } from 'vitest'
import * as Lib from '../index.js'
import { Protocols } from '../index.js'

describe('versify CESR v1 serialize and deserialize version string', () => {
it(`produces correct default version string with no args`, () => {
let vs = Lib.versify()
expect(vs).toEqual('KERI10JSON000000_')
expect(vs.length).toEqual(Lib.VER1FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.KERI)
expect(vrsn).toEqual(Lib.Vrsn_1_0)
expect(kind).toEqual(Lib.Serials.JSON)
expect(size).toEqual(0)
})

it(`produces a correct version string with JSON and size 65 (hex 41)`, () => {
const vs = Lib.versify(Protocols.KERI, Lib.Vrsn_1_0, Lib.Serials.JSON, 65)
expect(vs).toEqual('KERI10JSON000041_')
expect(vs.length).toEqual(Lib.VER1FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.KERI)
expect(vrsn).toEqual(Lib.Vrsn_1_0)
expect(kind).toEqual(Lib.Serials.JSON)
expect(size).toEqual(65)
})

it(`produces a correct ACDC version string with JSON and size 86`, () => {
const vs = Lib.versify(Protocols.ACDC, Lib.Vrsn_1_0, Lib.Serials.JSON, 86)
expect(vs).toEqual('ACDC10JSON000056_')
expect(vs.length).toEqual(Lib.VER1FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.ACDC)
expect(vrsn).toEqual(Lib.Vrsn_1_0)
expect(kind).toEqual(Lib.Serials.JSON)
expect(size).toEqual(86)
})

it(`produces a correct version string with CBOR and size 255 (hex FF)`, () => {
const vs = Lib.versify(Protocols.KERI, Lib.Vrsn_1_0, Lib.Serials.CBOR, 255)
expect(vs).toEqual('KERI10CBOR0000ff_')
expect(vs.length).toEqual(Lib.VER1FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.KERI)
expect(vrsn).toEqual(Lib.Vrsn_1_0)
expect(kind).toEqual(Lib.Serials.CBOR)
expect(size).toEqual(255)
})

it(`produces a correct version string with MGPK and size 256 (hex 100)`, () => {
const vs = Lib.versify(Protocols.KERI, Lib.Vrsn_1_0, Lib.Serials.MGPK, 256)
expect(vs).toEqual('KERI10MGPK000100_')
expect(vs.length).toEqual(Lib.VER1FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.KERI)
expect(vrsn).toEqual(Lib.Vrsn_1_0)
expect(kind).toEqual(Lib.Serials.MGPK)
expect(size).toEqual(256)
})

it(`produces a correct version string for KERI 1.1 with JSON and size 4095 (hex fff)`, () => {
const vs = Lib.versify(Protocols.KERI, Lib.Vrsn_1_1, Lib.Serials.JSON, 4095)
expect(vs).toEqual('KERI11JSON000fff_')
expect(vs.length).toEqual(Lib.VER1FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.KERI)
expect(vrsn).toEqual(Lib.Vrsn_1_1)
expect(kind).toEqual(Lib.Serials.JSON)
expect(size).toEqual(4095)
})
})

describe(`versify CESR v2 serialize and deserialize version string`, () => {
it(`produces a correct version string for KERI 2.0 (Base64URLSafe C = 2 AA == 0) with JSON and size 0 (Base64URLSafe AAAA)`, () => {
const vs = Lib.versify(Protocols.KERI, Lib.Vrsn_2_0, Lib.Serials.JSON, 0)
// KERI = protocol
// C = 2 in Base64
// AA = 0 in Base64 (padded to two chars)
// JSON = serialization type
// AAAA = primitive size 0 in Base64 (padded to four chars)
expect(vs).toEqual('KERICAAJSONAAAA.')
expect(vs.length).toEqual(Lib.VER2FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.KERI)
expect(vrsn).toEqual(Lib.Vrsn_2_0)
expect(kind).toEqual(Lib.Serials.JSON)
expect(size).toEqual(0)
})

it(`produces a correct version string for KERI 2.0 with JSON and size 65 (Base64URLSafe AABB)`, () => {
const vs = Lib.versify(Protocols.KERI, Lib.Vrsn_2_0, Lib.Serials.JSON, 65)
expect(vs).toEqual('KERICAAJSONAABB.')
expect(vs.length).toEqual(Lib.VER2FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.KERI)
expect(vrsn).toEqual(Lib.Vrsn_2_0)
expect(kind).toEqual(Lib.Serials.JSON)
expect(size).toEqual(65)
})

it(`produces a correct version string for ACDC 2.0 with CBOR and size 86 (Base64URLSafe AABW)`, () => {
const vs = Lib.versify(Protocols.ACDC, Lib.Vrsn_2_0, Lib.Serials.CBOR, 86)
expect(vs).toEqual('ACDCCAACBORAABW.')
expect(vs.length).toEqual(Lib.VER2FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.ACDC)
expect(vrsn).toEqual(Lib.Vrsn_2_0)
expect(kind).toEqual(Lib.Serials.CBOR)
expect(size).toEqual(86)
})

// generate a test with mgpk and size 65
it(`produces a correct version string for KERI 2.0 with MGPK and size 65 (Base64URLSafe AABB)`, () => {
const vs = Lib.versify(Protocols.KERI, Lib.Vrsn_2_0, Lib.Serials.MGPK, 65)
expect(vs).toEqual('KERICAAMGPKAABB.')
expect(vs.length).toEqual(Lib.VER2FULLSPAN)

let [proto, vrsn, kind, size] = Lib.deversify(vs)
expect(proto).toEqual(Lib.Protocols.KERI)
expect(vrsn).toEqual(Lib.Vrsn_2_0)
expect(kind).toEqual(Lib.Serials.MGPK)
expect(size).toEqual(65)
})
})
49 changes: 33 additions & 16 deletions src/lib/versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class Version implements Versionage {
}

export const Vrsn_1_0 = new Version(1, 0)
export const Vrsn_1_1 = new Version(1, 1)
export const Vrsn_2_0 = new Version(2, 0)
// Version string in JSON, CBOR, or MGPK field map serialization version 1
export const VER1FULLSPAN = 17 // number of characters in full version string
Expand All @@ -28,9 +29,22 @@ export const VEREX1 = /([A-Z]{4})([0-9a-f])([0-9a-f])([A-Z]{4})([0-9a-f]{6})_/
export const VER2FULLSPAN = 16 // number of characters in full version string
export const VER2TERM = `.`
export const VEREX2 = /([A-Z]{4})([0-9A-Za-z_-])([0-9A-Za-z_-]{2})([A-Z]{4})([0-9A-Za-z_-]{4})\./

// Combined regular expression
export const VEREX = new RegExp(VEREX2.source + '|' + VEREX1.source)
export const Rever = new RegExp(VEREX)
// WARNING: cannot use this (from KERIpy) because JavaScript regex does not combine regexes like Python does to be tried repeatedly
// and only return one capture group. Instead JavaScript regexes return all capture groups for all regexes in the combined regex.
// export const VEREX = new RegExp(VEREX2.source + '|' + VEREX1.source);
// export const Rever = new RegExp(VEREX);

/**
* regular expression for CESR v1 version string
*/
export const ReverV1 = new RegExp(VEREX1)
/**
* regular expression for CESR v2 version string
*/
export const ReverV2 = new RegExp(VEREX2)

/**
* the result of smelling a version string
* proto (Protocols): protocol type value of Protocol. Examples: 'KERI', 'ACDC'
Expand Down Expand Up @@ -63,15 +77,15 @@ function parseVersion1Matches(match: RegExpMatchArray): Smellage {
throw new Error(`Invalid protocol ${kind} in string = ${full}`)
}
try {
major = b64ToInt(major)
major = parseInt(major, 16)
} catch (e) {
throw new Error(`Invalid major version ${major} in string = ${full}: ${e}`)
}
if (major < 2) {
if (major > 1) {
throw new Error(`Incompatible major version ${major} with string = ${full}`)
}
try {
minor = b64ToInt(minor)
minor = parseInt(minor, 16)
} catch (e) {
throw new Error(`Invalid minor version = ${minor}: ${e}`)
}
Expand All @@ -82,7 +96,7 @@ function parseVersion1Matches(match: RegExpMatchArray): Smellage {
throw new Error(`Invalid serialization kind ${kind} in string = ${full}`)
}
try {
size = b64ToInt(size)
size = parseInt(size, 16)
} catch (e) {
throw new Error(`Invalid size = ${size}: ${e}`)
}
Expand Down Expand Up @@ -112,15 +126,15 @@ function parseVersion2Matches(match: RegExpMatchArray): Smellage {
throw new Error(`Invalid protocol ${kind} in string = ${full}`)
}
try {
major = parseInt(major, 16)
major = b64ToInt(major)
} catch (e) {
throw new Error(`Invalid major version ${major} in string = ${full}: ${e}`)
}
if (major < 2) {
throw new Error(`Incompatible major version ${major} with string = ${full}`)
}
try {
minor = parseInt(minor, 16)
minor = b64ToInt(minor)
} catch (e) {
throw new Error(`Invalid minor version = ${minor}: ${e}`)
}
Expand All @@ -131,7 +145,7 @@ function parseVersion2Matches(match: RegExpMatchArray): Smellage {
throw new Error(`Invalid serialization kind ${kind} in string = ${full}`)
}
try {
size = parseInt(size, 16)
size = b64ToInt(size)
} catch (e) {
throw new Error(`Invalid size = ${size}: ${e}`)
}
Expand Down Expand Up @@ -159,11 +173,14 @@ export function rematch(match: RegExpMatchArray): Smellage {
* returns Smellage a tuple of protocol, version, serialization, and size
*/
export function deversify(versionString: string): Smellage {
const match = Rever.exec(versionString)
if (!match) {
throw new Error(`Invalid version string = ${versionString}`)
}
return rematch(match)
const matchV2 = ReverV2.exec(versionString)
const matchV1 = ReverV1.exec(versionString)
if (matchV2) {
return rematch(matchV2)
} else if (matchV1) {
return rematch(matchV1)
}
throw new Error(`Invalid version string = ${versionString}`)
}

const VERRAWSIZE = 6
Expand All @@ -188,8 +205,8 @@ export function versify(
return `${protocol}${major}${minor}${kind}${formattedSize}${VER1TERM}`
} else {
const major = intToB64(version.major)
const minor = intToB64(version.minor)
const formattedSize = intToB64(size, VERRAWSIZE)
const minor = intToB64(version.minor, 2)
const formattedSize = intToB64(size, 4)
return `${protocol}${major}${minor}${kind}${formattedSize}${VER2TERM}`
}
}

0 comments on commit bbe4729

Please sign in to comment.