diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 496aa0a758..688bc7a65a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -134,6 +134,7 @@ jobs: "property_tests/tests/bool", "property_tests/tests/float32", "property_tests/tests/float64", + "property_tests/tests/func", "property_tests/tests/int", "property_tests/tests/int8", "property_tests/tests/int16", @@ -146,7 +147,10 @@ jobs: "property_tests/tests/nat64", "property_tests/tests/null", "property_tests/tests/principal", + "property_tests/tests/record", "property_tests/tests/text", + "property_tests/tests/tuple", + "property_tests/tests/variant", "property_tests/tests/vec" ] END @@ -219,15 +223,15 @@ jobs: - if: ${{ needs.release-candidate-deploy.outputs.should_run_tests }} shell: bash -l {0} working-directory: ${{ matrix.example_directories }} - run: AZLE_NUM_PROPTEST_RUNS=10 npm test + run: AZLE_PROPTEST_NUM_RUNS=10 AZLE_PROPTEST_VERBOSE=true npm test - if: ${{ needs.release-candidate-deploy.outputs.should_run_tests && contains(github.head_ref, 'release--') }} shell: bash -l {0} working-directory: ${{ matrix.example_directories }} - run: AZLE_NUM_PROPTEST_RUNS=100 npm test + run: AZLE_PROPTEST_NUM_RUNS=100 AZLE_PROPTEST_VERBOSE=true npm test - if: ${{ needs.release-candidate-deploy.outputs.should_run_tests && (github.ref == 'refs/heads/main' && contains(github.event.head_commit.message, 'Merge pull request') && contains(github.event.head_commit.message, 'demergent-labs/release--')) }} shell: bash -l {0} working-directory: ${{ matrix.example_directories }} - run: AZLE_NUM_PROPTEST_RUNS=100 npm test + run: AZLE_PROPTEST_NUM_RUNS=100 AZLE_PROPTEST_VERBOSE=true npm test check-basic-integration-tests-success: needs: basic-integration-tests diff --git a/package-lock.json b/package-lock.json index 8a52026c81..9effead501 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "eslint": "8.11.0", "eslint-config-prettier": "8.5.0", "fast-check": "^3.13.1", + "fast-equals": "5.0.1", "husky": "7.0.4", "lint-staged": "12.3.7", "prettier": "^3.0.3" @@ -1352,6 +1353,15 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", diff --git a/package.json b/package.json index ea4f5eae41..65a1a3b246 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "eslint": "8.11.0", "eslint-config-prettier": "8.5.0", "fast-check": "^3.13.1", + "fast-equals": "5.0.1", "husky": "7.0.4", "lint-staged": "12.3.7", "prettier": "^3.0.3" diff --git a/property_tests/arbitraries/candid/candid_arb.ts b/property_tests/arbitraries/candid/candid_arb.ts new file mode 100644 index 0000000000..414dd32838 --- /dev/null +++ b/property_tests/arbitraries/candid/candid_arb.ts @@ -0,0 +1,34 @@ +import fc from 'fast-check'; +import { deepEqual } from 'fast-equals'; +import { CandidType } from './candid_type_arb'; + +// TODO we're thinking that Candid is not the best name for this. What is better? +export type CandidMeta = { + value: T; + src: { + candidType: string; + typeDeclaration?: string; + imports: Set; + valueLiteral: string; + }; + equals(a: T, b: T): boolean; +}; + +export const CandidMetaArb = ( + arb: fc.Arbitrary, + candidType: string, + toLiteral: (value: T) => string, + equals: (a: T, b: T) => boolean = (a: T, b: T) => deepEqual(a, b) +) => { + return arb.map( + (value): CandidMeta => ({ + src: { + candidType, + imports: new Set([candidType]), + valueLiteral: toLiteral(value) + }, + value, + equals + }) + ); +}; diff --git a/property_tests/arbitraries/candid/candid_type_arb.ts b/property_tests/arbitraries/candid/candid_type_arb.ts new file mode 100644 index 0000000000..ffdd5482b7 --- /dev/null +++ b/property_tests/arbitraries/candid/candid_type_arb.ts @@ -0,0 +1,66 @@ +import fc from 'fast-check'; +import { IntArb } from './primitive/ints/int_arb'; +import { Int8Arb } from './primitive/ints/int8_arb'; +import { Int16Arb } from './primitive/ints/int16_arb'; +import { Int32Arb } from './primitive/ints/int32_arb'; +import { Int64Arb } from './primitive/ints/int64_arb'; +import { NatArb } from './primitive/nats/nat_arb'; +import { Nat8Arb } from './primitive/nats/nat8_arb'; +import { Nat16Arb } from './primitive/nats/nat16_arb'; +import { Nat32Arb } from './primitive/nats/nat32_arb'; +import { Nat64Arb } from './primitive/nats/nat64_arb'; +import { NullArb } from './primitive/null'; +import { BoolArb } from './primitive/bool'; +import { Principal } from '@dfinity/principal'; +import { PrincipalArb } from './reference/principal_arb'; +import { Float32Arb } from './primitive/floats/float32_arb'; +import { Float64Arb } from './primitive/floats/float64_arb'; +import { TextArb } from './primitive/text'; +import { BlobArb } from './constructed/blob_arb'; +import { CandidMeta } from './candid_arb'; +import { Func } from './reference/func_arb'; +import { Opt } from './constructed/opt_arb'; +import { Variant } from './constructed/variant_arb'; +import { Record } from './constructed/record_arb'; +import { Tuple } from './constructed/tuple_arb'; + +export type CandidType = + | number + | bigint + | null + | boolean + | Principal + | Uint8Array + | string + | Func + | Opt + | Variant + | Record + | Tuple + | undefined; + +/** + * An arbitrary representing all possible Candid types. + * + * **Note:** This currently only supports ints, nats, and null arbitraries + */ +export const CandidTypeArb: fc.Arbitrary> = fc.oneof( + Float32Arb, + Float64Arb, + IntArb, + Int8Arb, + Int16Arb, + Int32Arb, + Int64Arb, + NatArb, + Nat8Arb, + Nat16Arb, + Nat32Arb, + Nat64Arb, + BoolArb, + NullArb, + TextArb, + PrincipalArb, + BlobArb +); +// TODO: This needs to support ALL valid candid types, including records, variants, etc. diff --git a/property_tests/arbitraries/candid/constructed/blob_arb.ts b/property_tests/arbitraries/candid/constructed/blob_arb.ts index 76d444f610..6090071e99 100644 --- a/property_tests/arbitraries/candid/constructed/blob_arb.ts +++ b/property_tests/arbitraries/candid/constructed/blob_arb.ts @@ -1,6 +1,13 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../candid_arb'; +import { blobToSrcLiteral } from '../to_src_literal/blob'; -export const BlobArb = fc.tuple( - fc.uint8Array(), - fc.oneof(fc.constant('blob'), fc.constant('Vec(nat8)')) -); +export const BlobArb = fc + .oneof( + CandidMetaArb(fc.uint8Array(), 'Vec(nat8)', blobToSrcLiteral), + CandidMetaArb(fc.uint8Array(), 'blob', blobToSrcLiteral) + ) + .map((sample) => ({ + ...sample, + src: { ...sample.src, imports: new Set(['blob', 'nat8', 'Vec']) } + })); diff --git a/property_tests/arbitraries/candid/constructed/opt_arb.ts b/property_tests/arbitraries/candid/constructed/opt_arb.ts index 656606b9fd..1ccdc63e1e 100644 --- a/property_tests/arbitraries/candid/constructed/opt_arb.ts +++ b/property_tests/arbitraries/candid/constructed/opt_arb.ts @@ -1,73 +1,157 @@ import fc from 'fast-check'; -import { IntArb } from '../primitive/ints/int_arb'; -import { Int8Arb } from '../primitive/ints/int8_arb'; -import { Int16Arb } from '../primitive/ints/int16_arb'; -import { Int32Arb } from '../primitive/ints/int32_arb'; -import { Int64Arb } from '../primitive/ints/int64_arb'; -import { NatArb } from '../primitive/nats/nat_arb'; -import { Nat8Arb } from '../primitive/nats/nat8_arb'; -import { Nat16Arb } from '../primitive/nats/nat16_arb'; -import { Nat32Arb } from '../primitive/nats/nat32_arb'; -import { Nat64Arb } from '../primitive/nats/nat64_arb'; - -const InnerOptArb = (arb: fc.Arbitrary) => { - return fc - .oneof(fc.constant('Some'), fc.constant('None')) - .chain((keySample) => { - return arb.map((innerValueSample) => { - if (keySample === 'Some') { - return { - Some: innerValueSample - }; - } else { - return { - None: null - }; - } - }); - }); +import { CandidType, CandidTypeArb } from '../candid_type_arb'; +import { CandidMeta } from '../candid_arb'; + +type SomeOrNone = 'Some' | 'None'; +type Base = { + someOrNone: SomeOrNone; + candid: CandidMeta; }; +type RecursiveOpt = { base: T } | { nextLayer: RecursiveOpt }; + +export type Opt = [CandidType] | never[]; + // TODO look into making this recursive -// TODO we want to be able to have opts of opts -// TODO we also need to add vecs in here // TODO we need to add all constructed and reference types -export const OptArb = fc.oneof( - InnerOptArb(IntArb).map((sample) => - createOptArbWrapper(sample, 'Opt(int)') - ), - InnerOptArb(Int8Arb).map((sample) => - createOptArbWrapper(sample, 'Opt(int8)') - ), - InnerOptArb(Int16Arb).map((sample) => - createOptArbWrapper(sample, 'Opt(int16)') - ), - InnerOptArb(Int32Arb).map((sample) => - createOptArbWrapper(sample, 'Opt(int32)') - ), - InnerOptArb(Int64Arb).map((sample) => - createOptArbWrapper(sample, 'Opt(int64)') - ), - InnerOptArb(NatArb).map((sample) => - createOptArbWrapper(sample, 'Opt(nat)') - ), - InnerOptArb(Nat8Arb).map((sample) => - createOptArbWrapper(sample, 'Opt(nat8)') - ), - InnerOptArb(Nat16Arb).map((sample) => - createOptArbWrapper(sample, 'Opt(nat16)') - ), - InnerOptArb(Nat32Arb).map((sample) => - createOptArbWrapper(sample, 'Opt(nat32)') - ), - InnerOptArb(Nat64Arb).map((sample) => - createOptArbWrapper(sample, 'Opt(nat64)') +const BaseArb = fc + .tuple( + fc.constantFrom('Some', 'None') as fc.Arbitrary, + CandidTypeArb ) -); + .map(([someOrNone, candid]) => ({ someOrNone, candid }) as Base); + +export const OptArb = fc + .letrec((tie) => ({ + RecursiveOptArb: fc.oneof( + fc.record({ + base: BaseArb + }), + fc.record({ + nextLayer: tie('RecursiveOptArb').map( + (sample) => sample as RecursiveOpt + ) + }) + ) + })) + .RecursiveOptArb.map((recursiveOptArb): CandidMeta => { + return { + src: { + candidType: generateCandidType(recursiveOptArb), + imports: generateImports(recursiveOptArb), + valueLiteral: generateValueLiteral(recursiveOptArb) + }, + value: generateValue(recursiveOptArb), + equals: (a, b) => areOptsEqual(getBaseEquals(recursiveOptArb), a, b) + }; + }); + +function generateCandidType(recursiveOpt: RecursiveOpt): string { + if ('base' in recursiveOpt) { + // base case + return `Opt(${recursiveOpt.base.candid.src.candidType})`; + } else { + return `Opt(${generateCandidType(recursiveOpt.nextLayer)})`; + } +} + +function generateImports(recursiveOpt: RecursiveOpt): Set { + if ('base' in recursiveOpt) { + // base case + return new Set([ + ...recursiveOpt.base.candid.src.imports, + 'Opt', + 'Some', + 'None' + ]); + } else { + return generateImports(recursiveOpt.nextLayer); + } +} + +function generateValue(recursiveOpt: RecursiveOpt): Opt { + if ('base' in recursiveOpt) { + // base case + if (recursiveOpt.base.someOrNone === 'Some') { + return [recursiveOpt.base.candid.value]; + } else { + return []; + } + } else { + return [generateValue(recursiveOpt.nextLayer)]; + } +} + +function generateValueLiteral(recursiveOpt: RecursiveOpt): string { + if ('base' in recursiveOpt) { + // base case + if (recursiveOpt.base.someOrNone === 'Some') { + return `Some(${recursiveOpt.base.candid.src.valueLiteral})`; + } else { + return `None`; + } + } else { + return `Some(${generateValueLiteral(recursiveOpt.nextLayer)})`; + } +} + +function calculateDepthAndValues(value: [any] | []): { + depth: number; + value: any; +} { + if (value.length === 0) { + // None + return { depth: 1, value }; + } + const isOpt = + Array.isArray(value[0]) && + (value[0].length === 1 || value[0].length === 0); + if (!isOpt) { + // The value.Some is not an opt. return value.Some + return { + depth: 1, + value: value[0] + }; + } + + const result = calculateDepthAndValues(value[0]); + return { ...result, depth: result.depth + 1 }; +} + +function getBaseEquals( + recursiveOpt: RecursiveOpt +): (a: any, b: any) => boolean { + if ('base' in recursiveOpt) { + // base case + if (recursiveOpt.base.someOrNone === 'Some') { + return recursiveOpt.base.candid.equals; + } else { + return (a: null, b: null) => a === b; + } + } else { + return getBaseEquals(recursiveOpt.nextLayer); + } +} + +function areOptsEqual( + equals: (a: any, b: any) => boolean, + opt1: any, + opt2: any +) { + const { depth: depth1, value: value1 } = calculateDepthAndValues(opt1); + const { depth: depth2, value: value2 } = calculateDepthAndValues(opt2); + + if (depth1 !== depth2) { + return false; + } + + if (isNone(value1) && isNone(value2)) { + return true; + } + + return equals(value1, value2); +} -function createOptArbWrapper(sample: any, candidType: string) { - return { - opt: sample, - candidType - }; +function isNone(value: any | []) { + return Array.isArray(value) && value.length === 0; } diff --git a/property_tests/arbitraries/candid/constructed/record_arb.ts b/property_tests/arbitraries/candid/constructed/record_arb.ts new file mode 100644 index 0000000000..d3796737fb --- /dev/null +++ b/property_tests/arbitraries/candid/constructed/record_arb.ts @@ -0,0 +1,121 @@ +import fc from 'fast-check'; + +import { CandidMeta } from '../candid_arb'; +import { CandidType, CandidTypeArb } from '../candid_type_arb'; +import { UniqueIdentifierArb } from '../../unique_identifier_arb'; +import { JsFunctionNameArb } from '../../js_function_name_arb'; + +export type Record = { + [x: string]: CandidType; +}; + +type Field = [string, CandidMeta]; + +export const RecordArb = fc + .tuple( + UniqueIdentifierArb('typeDeclaration'), + fc.uniqueArray(fc.tuple(JsFunctionNameArb, CandidTypeArb), { + selector: (entry) => entry[0] + }) + ) + .map(([name, fields]): CandidMeta => { + const typeDeclaration = generateTypeDeclaration(name, fields); + + const imports = generateImports(fields); + + const valueLiteral = generateValueLiteral(fields); + + const value = generateValue(fields); + + const equals = generateEqualsMethod(fields); + + return { + src: { + candidType: name, + typeDeclaration, + imports, + valueLiteral + }, + value, + equals + }; + }); + +function generateImports(fields: Field[]): Set { + const fieldImports = fields.flatMap((field) => [...field[1].src.imports]); + return new Set([...fieldImports, 'Record']); +} + +function generateTypeDeclaration(name: string, fields: Field[]): string { + return `const ${name} = Record({\n ${fields + .map( + ([fieldName, fieldDataType]) => + `${fieldName}: ${fieldDataType.src.candidType}` + ) + .join(',\n ')}\n});`; +} + +function generateValue(fields: Field[]): Record { + return fields.length === 0 + ? {} + : fields.reduce((record, [fieldName, fieldDataType]) => { + return { + ...record, + [fieldName]: fieldDataType.value + }; + }, {}); +} + +function generateValueLiteral(fields: Field[]): string { + if (fields.length === 0) { + return '{}'; + } + + const fieldLiterals = fields + .map( + ([fieldName, fieldValue]) => + `${fieldName}: ${fieldValue.src.valueLiteral}` + ) + .join(',\n'); + + return `{ + ${fieldLiterals} + }`; +} + +function generateEqualsMethod( + fields: Field[] +): (a: Record, b: Record) => boolean { + return (a: Record, b: Record): boolean => { + if (typeof a !== typeof b) { + return false; + } + + const aFieldNames = Object.keys(a).sort(); + const bFieldNames = Object.keys(b).sort(); + if (aFieldNames.length !== bFieldNames.length) { + return false; + } + + const areFieldNamesTheSame = aFieldNames.reduce( + (acc, aFieldName, index) => + acc && aFieldName === bFieldNames[index], + true + ); + + if (!areFieldNamesTheSame) { + return false; + } + + const areFieldValuesTheSame = fields.reduce( + (acc, [fieldName, fieldCandidType]) => { + return ( + acc && fieldCandidType.equals(a[fieldName], b[fieldName]) + ); + }, + true + ); + + return areFieldValuesTheSame; + }; +} diff --git a/property_tests/arbitraries/candid/constructed/tuple_arb.ts b/property_tests/arbitraries/candid/constructed/tuple_arb.ts new file mode 100644 index 0000000000..e2ca939493 --- /dev/null +++ b/property_tests/arbitraries/candid/constructed/tuple_arb.ts @@ -0,0 +1,83 @@ +import fc from 'fast-check'; + +import { CandidMeta } from '../candid_arb'; +import { CandidType, CandidTypeArb } from '../candid_type_arb'; +import { UniqueIdentifierArb } from '../../unique_identifier_arb'; + +export type Tuple = CandidType[]; + +export const TupleArb = fc + .tuple(UniqueIdentifierArb('typeDeclaration'), fc.array(CandidTypeArb)) + .map(([name, fields]): CandidMeta => { + const innerTypes = fields.map((field) => field.src.candidType); + + const typeDeclaration = `const ${name} = Tuple(${innerTypes.join( + ', ' + )});`; + + const imports = generateImports(fields); + + const valueLiteral = generateValueLiteral(fields); + + const value = fields.map((field) => field.value); + + const equals = generateEqualsMethod(fields); + + return { + src: { + candidType: name, + typeDeclaration, + imports, + valueLiteral + }, + value, + equals + }; + }); + +function generateImports(fields: CandidMeta[]): Set { + const fieldImports = fields.flatMap((field) => [...field.src.imports]); + return new Set([...fieldImports, 'Tuple']); +} + +function generateValueLiteral(fields: CandidMeta[]) { + const fieldLiterals = fields + .map((field) => field.src.valueLiteral) + .join(',\n'); + + return `[ + ${fieldLiterals} + ]`; +} + +function generateEqualsMethod( + fields: CandidMeta[] +): (a: Tuple, b: Tuple) => boolean { + return (a: Tuple, b: Tuple): boolean => { + if (typeof a !== typeof b) { + return false; + } + + const aFieldNames = Object.keys(a); + const bFieldNames = Object.keys(b); + if (aFieldNames.length !== bFieldNames.length) { + return false; + } + + const areFieldNamesTheSame = aFieldNames.reduce( + (acc, aFieldName, index) => + acc && aFieldName === bFieldNames[index], + true + ); + + if (!areFieldNamesTheSame) { + return false; + } + + const areFieldValuesTheSame = fields.reduce((acc, field, index) => { + return acc && field.equals(a[index], b[index]); + }, true); + + return areFieldValuesTheSame; + }; +} diff --git a/property_tests/arbitraries/candid/constructed/variant_arb.ts b/property_tests/arbitraries/candid/constructed/variant_arb.ts new file mode 100644 index 0000000000..6a5bc92cf3 --- /dev/null +++ b/property_tests/arbitraries/candid/constructed/variant_arb.ts @@ -0,0 +1,111 @@ +import fc from 'fast-check'; +import { CandidMeta } from '../candid_arb'; +import { CandidType, CandidTypeArb } from '../candid_type_arb'; +import { UniqueIdentifierArb } from '../../unique_identifier_arb'; +import { JsFunctionNameArb } from '../../js_function_name_arb'; + +export type Variant = { + [x: string]: CandidType; +}; +type Field = [string, CandidMeta]; + +export const VariantArb = fc + .tuple( + UniqueIdentifierArb('typeDeclaration'), + fc.uniqueArray(fc.tuple(JsFunctionNameArb, CandidTypeArb), { + selector: (entry) => entry[0], + minLength: 1 + // Although no minLength is technically required (according to the + // spec), the DFX CLI itself currently errors out trying to pass + // an empty object. + }) + ) + .map(([name, fields]): CandidMeta => { + const randomIndex = Math.floor(Math.random() * fields.length); + + const typeDeclaration = generateTypeDeclaration(name, fields); + + const imports = generateImports(fields); + + const valueLiteral = generateValueLiteral(randomIndex, fields); + + const value = generateValue(randomIndex, fields); + + const equals = generateEqualsMethod(fields); + + return { + src: { + candidType: name, + typeDeclaration, + imports, + valueLiteral + }, + value, + equals + }; + }); + +function generateImports(fields: Field[]): Set { + const fieldImports = fields.flatMap((field) => [...field[1].src.imports]); + return new Set([...fieldImports, 'Variant']); +} + +function generateTypeDeclaration(name: string, fields: Field[]): string { + return `const ${name} = Variant({\n ${fields + .map( + ([fieldName, fieldDataType]) => + `${fieldName}: ${fieldDataType.src.candidType}` + ) + .join(',\n ')}\n});`; +} + +function generateValue(index: number, fields: Field[]): Variant { + if (fields.length === 0) { + return {}; + } + const [randomFieldName, { value: randomFieldDataType }] = fields[index]; + + return { + [randomFieldName]: randomFieldDataType + }; +} + +function generateValueLiteral(index: number, fields: Field[]): string { + if (fields.length === 0) { + return '{}'; + } + + const [fieldName, fieldValue] = fields[index]; + + return `{ + ${fieldName}: ${fieldValue.src.valueLiteral} + }`; +} + +function generateEqualsMethod( + fields: Field[] +): (a: Variant, b: Variant) => boolean { + return (a: Variant, b: Variant): boolean => { + if (typeof a !== typeof b) { + return false; + } + + const aKeys = Object.keys(a); + const bKeys = Object.keys(b); + if (aKeys.length !== bKeys.length && aKeys.length !== 1) { + return false; + } + const aFieldName = aKeys[0]; + const bFieldName = bKeys[0]; + if (aFieldName !== bFieldName) { + return false; + } + + return fields.reduce((acc, [fieldName, fieldCandidType]) => { + if (fieldName !== aFieldName) { + return acc || false; + } + return fieldCandidType.equals(a[fieldName], b[fieldName]); + }, false); + }; +} diff --git a/property_tests/arbitraries/candid/constructed/vec_arb.ts b/property_tests/arbitraries/candid/constructed/vec_arb.ts index ac3f21ece1..a90afaa271 100644 --- a/property_tests/arbitraries/candid/constructed/vec_arb.ts +++ b/property_tests/arbitraries/candid/constructed/vec_arb.ts @@ -1,4 +1,3 @@ -import { Principal } from '@dfinity/principal'; import fc from 'fast-check'; import { IntArb } from '../primitive/ints/int_arb'; import { Int8Arb } from '../primitive/ints/int8_arb'; @@ -11,52 +10,85 @@ import { Nat16Arb } from '../primitive/nats/nat16_arb'; import { Nat32Arb } from '../primitive/nats/nat32_arb'; import { Nat64Arb } from '../primitive/nats/nat64_arb'; import { PrincipalArb } from '../reference/principal_arb'; +import { CandidMeta } from '../candid_arb'; +import { BoolArb } from '../primitive/bool'; +import { Float32Arb } from '../primitive/floats/float32_arb'; +import { Float64Arb } from '../primitive/floats/float64_arb'; +import { NullArb } from '../primitive/null'; +import { TextArb } from '../primitive/text'; +import { deepEqual } from 'fast-equals'; +import { BlobArb } from './blob_arb'; +import { CandidType } from '../candid_type_arb'; + +const VecInnerArb = ( + arb: fc.Arbitrary> +) => { + return fc + .tuple(fc.array(arb), arb) + .map(([sample, src]): CandidMeta => { + const equals = generateEquals(sample); + const valueLiteral = generateValueLiteral(sample); + + return { + value: sample.map((sample) => sample.value), + src: { + candidType: `Vec(${src.src.candidType})`, + imports: new Set([...src.src.imports, 'Vec']), + valueLiteral + }, + equals + }; + }); +}; + +function generateValueLiteral(sample: CandidMeta[]) { + const valueLiterals = sample + .map((sample) => sample.src.valueLiteral) + .join(','); + return `[${valueLiterals}]`; +} + +function generateEquals(sample: CandidMeta[]) { + return (a: T[], b: T[]) => + arraysAreEqual(a, b, sample[0]?.equals ?? deepEqual); +} -// TODO look into making this recursive -// TODO we want to be able to have vecs of vecs -// TODO we need to add all constructed and reference types export const VecArb = fc.oneof( - fc.array(IntArb).map((sample) => createVecArbWrapper(sample, 'Vec(int)')), - fc.array(Int8Arb).map((sample) => createVecArbWrapper(sample, 'Vec(int8)')), - fc - .array(Int16Arb) - .map((sample) => createVecArbWrapper(sample, 'Vec(int16)')), - fc - .array(Int32Arb) - .map((sample) => createVecArbWrapper(sample, 'Vec(int32)')), - fc - .array(Int64Arb) - .map((sample) => createVecArbWrapper(sample, 'Vec(int64)')), - fc.array(NatArb).map((sample) => createVecArbWrapper(sample, 'Vec(nat)')), - fc.array(Nat8Arb).map((sample) => createVecArbWrapper(sample, 'Vec(nat8)')), - fc - .array(Nat16Arb) - .map((sample) => createVecArbWrapper(sample, 'Vec(nat16)')), - fc - .array(Nat32Arb) - .map((sample) => createVecArbWrapper(sample, 'Vec(nat32)')), - fc - .array(Nat64Arb) - .map((sample) => createVecArbWrapper(sample, 'Vec(nat64)')), - fc - .array(PrincipalArb) - .map((sample) => - createVecArbWrapper( - sample, - 'Vec(Principal)', - (a: Principal, b: Principal) => a.toText() === b.toText() - ) - ) + VecInnerArb(Float32Arb), + VecInnerArb(Float64Arb), + VecInnerArb(IntArb), + VecInnerArb(Int8Arb), + VecInnerArb(Int16Arb), + VecInnerArb(Int32Arb), + VecInnerArb(Int64Arb), + VecInnerArb(NatArb), + VecInnerArb(Nat8Arb), + VecInnerArb(Nat16Arb), + VecInnerArb(Nat32Arb), + VecInnerArb(Nat64Arb), + VecInnerArb(BoolArb), + VecInnerArb(TextArb), + VecInnerArb(PrincipalArb), + VecInnerArb(BlobArb) + // VecInnerArb(NullArb) ); -function createVecArbWrapper( - sample: any[], - candidType: string, - equalityCheck: (a: any, b: any) => boolean = (a, b) => a === b +function arraysAreEqual( + arr1: T[], + arr2: T[], + equals: (a: T, b: T) => boolean ) { - return { - vec: sample, - candidType, - equalityCheck - }; + // Check if both arrays have the same length + if (arr1.length !== arr2.length) { + return false; + } + + // Loop through each element to check for equality + for (let i = 0; i < arr1.length; i++) { + if (!equals(arr1[i], arr2[i])) { + return false; + } + } + + return true; } diff --git a/property_tests/arbitraries/candid/primitive/bool.ts b/property_tests/arbitraries/candid/primitive/bool.ts index d071b720c3..b2c914b567 100644 --- a/property_tests/arbitraries/candid/primitive/bool.ts +++ b/property_tests/arbitraries/candid/primitive/bool.ts @@ -1,3 +1,5 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../candid_arb'; +import { booleanToSrcLiteral } from '../to_src_literal/boolean'; -export const BoolArb = fc.boolean(); +export const BoolArb = CandidMetaArb(fc.boolean(), 'bool', booleanToSrcLiteral); diff --git a/property_tests/arbitraries/candid/primitive/floats/float32_arb.ts b/property_tests/arbitraries/candid/primitive/floats/float32_arb.ts index 348effebc4..5fe72a91fa 100644 --- a/property_tests/arbitraries/candid/primitive/floats/float32_arb.ts +++ b/property_tests/arbitraries/candid/primitive/floats/float32_arb.ts @@ -1,3 +1,9 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../../candid_arb'; +import { floatToSrcLiteral } from '../../to_src_literal/float'; -export const Float32Arb = fc.float(); +export const Float32Arb = CandidMetaArb( + fc.float(), + 'float32', + floatToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/floats/float64_arb.ts b/property_tests/arbitraries/candid/primitive/floats/float64_arb.ts index c3169fa933..4f4078c972 100644 --- a/property_tests/arbitraries/candid/primitive/floats/float64_arb.ts +++ b/property_tests/arbitraries/candid/primitive/floats/float64_arb.ts @@ -1,3 +1,9 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../../candid_arb'; +import { floatToSrcLiteral } from '../../to_src_literal/float'; -export const Float64ArrayArb = fc.float64Array(); +export const Float64Arb = CandidMetaArb( + fc.float64Array({ maxLength: 1, minLength: 1 }).map((sample) => sample[0]), + 'float64', + floatToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/ints/index.ts b/property_tests/arbitraries/candid/primitive/ints/index.ts new file mode 100644 index 0000000000..b84f8644c0 --- /dev/null +++ b/property_tests/arbitraries/candid/primitive/ints/index.ts @@ -0,0 +1,4 @@ +import fc from 'fast-check'; + +export const NumberArb = (n: number) => + fc.bigIntN(n).map((value) => Number(value)); diff --git a/property_tests/arbitraries/candid/primitive/ints/int16_arb.ts b/property_tests/arbitraries/candid/primitive/ints/int16_arb.ts index f8a21a84f0..6c7a54032a 100644 --- a/property_tests/arbitraries/candid/primitive/ints/int16_arb.ts +++ b/property_tests/arbitraries/candid/primitive/ints/int16_arb.ts @@ -1,3 +1,9 @@ -import fc from 'fast-check'; +import { numberToSrcLiteral } from '../../to_src_literal/number'; +import { CandidMetaArb } from '../../candid_arb'; +import { NumberArb } from './'; -export const Int16Arb = fc.bigIntN(16).map((sample) => Number(sample)); +export const Int16Arb = CandidMetaArb( + NumberArb(16), + 'int16', + numberToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/ints/int32_arb.ts b/property_tests/arbitraries/candid/primitive/ints/int32_arb.ts index 6da3e669f7..6396827d36 100644 --- a/property_tests/arbitraries/candid/primitive/ints/int32_arb.ts +++ b/property_tests/arbitraries/candid/primitive/ints/int32_arb.ts @@ -1,3 +1,9 @@ -import fc from 'fast-check'; +import { numberToSrcLiteral } from '../../to_src_literal/number'; +import { CandidMetaArb } from '../../candid_arb'; +import { NumberArb } from './'; -export const Int32Arb = fc.bigIntN(32).map((sample) => Number(sample)); +export const Int32Arb = CandidMetaArb( + NumberArb(32), + 'int32', + numberToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/ints/int64_arb.ts b/property_tests/arbitraries/candid/primitive/ints/int64_arb.ts index 7bac76edec..88b269430c 100644 --- a/property_tests/arbitraries/candid/primitive/ints/int64_arb.ts +++ b/property_tests/arbitraries/candid/primitive/ints/int64_arb.ts @@ -1,3 +1,9 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../../candid_arb'; +import { bigintToSrcLiteral } from '../../to_src_literal/bigint'; -export const Int64Arb = fc.bigIntN(64); +export const Int64Arb = CandidMetaArb( + fc.bigIntN(64), + 'int64', + bigintToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/ints/int8_arb.ts b/property_tests/arbitraries/candid/primitive/ints/int8_arb.ts index ad691ed1b5..d2506756ac 100644 --- a/property_tests/arbitraries/candid/primitive/ints/int8_arb.ts +++ b/property_tests/arbitraries/candid/primitive/ints/int8_arb.ts @@ -1,3 +1,5 @@ -import fc from 'fast-check'; +import { numberToSrcLiteral } from '../../to_src_literal/number'; +import { CandidMetaArb } from '../../candid_arb'; +import { NumberArb } from './'; -export const Int8Arb = fc.bigIntN(8).map((sample) => Number(sample)); +export const Int8Arb = CandidMetaArb(NumberArb(8), 'int8', numberToSrcLiteral); diff --git a/property_tests/arbitraries/candid/primitive/ints/int_arb.ts b/property_tests/arbitraries/candid/primitive/ints/int_arb.ts index e7c18bf182..92a310ce64 100644 --- a/property_tests/arbitraries/candid/primitive/ints/int_arb.ts +++ b/property_tests/arbitraries/candid/primitive/ints/int_arb.ts @@ -1,3 +1,5 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../../candid_arb'; +import { bigintToSrcLiteral } from '../../to_src_literal/bigint'; -export const IntArb = fc.bigInt(); +export const IntArb = CandidMetaArb(fc.bigInt(), 'int', bigintToSrcLiteral); diff --git a/property_tests/arbitraries/candid/primitive/nats/index.ts b/property_tests/arbitraries/candid/primitive/nats/index.ts new file mode 100644 index 0000000000..da6390e7df --- /dev/null +++ b/property_tests/arbitraries/candid/primitive/nats/index.ts @@ -0,0 +1,4 @@ +import fc from 'fast-check'; + +export const UNumberArb = (n: number) => + fc.bigUintN(n).map((value) => Number(value)); diff --git a/property_tests/arbitraries/candid/primitive/nats/nat16_arb.ts b/property_tests/arbitraries/candid/primitive/nats/nat16_arb.ts index 1233c41ba2..9e108e1380 100644 --- a/property_tests/arbitraries/candid/primitive/nats/nat16_arb.ts +++ b/property_tests/arbitraries/candid/primitive/nats/nat16_arb.ts @@ -1,3 +1,9 @@ -import fc from 'fast-check'; +import { numberToSrcLiteral } from '../../to_src_literal/number'; +import { CandidMetaArb } from '../../candid_arb'; +import { UNumberArb } from './index'; -export const Nat16Arb = fc.bigUintN(16).map((sample) => Number(sample)); +export const Nat16Arb = CandidMetaArb( + UNumberArb(16), + 'nat16', + numberToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/nats/nat32_arb.ts b/property_tests/arbitraries/candid/primitive/nats/nat32_arb.ts index a156db00a5..83671ce36f 100644 --- a/property_tests/arbitraries/candid/primitive/nats/nat32_arb.ts +++ b/property_tests/arbitraries/candid/primitive/nats/nat32_arb.ts @@ -1,3 +1,9 @@ -import fc from 'fast-check'; +import { numberToSrcLiteral } from '../../to_src_literal/number'; +import { CandidMetaArb } from '../../candid_arb'; +import { UNumberArb } from './index'; -export const Nat32Arb = fc.bigUintN(32).map((sample) => Number(sample)); +export const Nat32Arb = CandidMetaArb( + UNumberArb(32), + 'nat32', + numberToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/nats/nat64_arb.ts b/property_tests/arbitraries/candid/primitive/nats/nat64_arb.ts index ecd5feb951..e616bfec8a 100644 --- a/property_tests/arbitraries/candid/primitive/nats/nat64_arb.ts +++ b/property_tests/arbitraries/candid/primitive/nats/nat64_arb.ts @@ -1,3 +1,9 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../../candid_arb'; +import { bigintToSrcLiteral } from '../../to_src_literal/bigint'; -export const Nat64Arb = fc.bigUintN(64); +export const Nat64Arb = CandidMetaArb( + fc.bigUintN(64), + 'nat64', + bigintToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/nats/nat8_arb.ts b/property_tests/arbitraries/candid/primitive/nats/nat8_arb.ts index 17200e6fd9..7ca00e794b 100644 --- a/property_tests/arbitraries/candid/primitive/nats/nat8_arb.ts +++ b/property_tests/arbitraries/candid/primitive/nats/nat8_arb.ts @@ -1,3 +1,5 @@ -import fc from 'fast-check'; +import { numberToSrcLiteral } from '../../to_src_literal/number'; +import { CandidMetaArb } from '../../candid_arb'; +import { UNumberArb } from './index'; -export const Nat8Arb = fc.bigUintN(8).map((sample) => Number(sample)); +export const Nat8Arb = CandidMetaArb(UNumberArb(8), 'nat8', numberToSrcLiteral); diff --git a/property_tests/arbitraries/candid/primitive/nats/nat_arb.ts b/property_tests/arbitraries/candid/primitive/nats/nat_arb.ts index da6b849f6d..e1592dc47b 100644 --- a/property_tests/arbitraries/candid/primitive/nats/nat_arb.ts +++ b/property_tests/arbitraries/candid/primitive/nats/nat_arb.ts @@ -1,3 +1,5 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../../candid_arb'; +import { bigintToSrcLiteral } from '../../to_src_literal/bigint'; -export const NatArb = fc.bigUint(); +export const NatArb = CandidMetaArb(fc.bigUint(), 'nat', bigintToSrcLiteral); diff --git a/property_tests/arbitraries/candid/primitive/null.ts b/property_tests/arbitraries/candid/primitive/null.ts index fa6dd45cd4..c98466cd17 100644 --- a/property_tests/arbitraries/candid/primitive/null.ts +++ b/property_tests/arbitraries/candid/primitive/null.ts @@ -1,3 +1,9 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../candid_arb'; +import { nullToSrcLiteral } from '../to_src_literal/null'; -export const NullArb = fc.constant(null); +export const NullArb = CandidMetaArb( + fc.constant(null), + 'Null', + nullToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/primitive/text.ts b/property_tests/arbitraries/candid/primitive/text.ts index b401096214..b68a28d6a8 100644 --- a/property_tests/arbitraries/candid/primitive/text.ts +++ b/property_tests/arbitraries/candid/primitive/text.ts @@ -1,3 +1,5 @@ import fc from 'fast-check'; +import { CandidMetaArb } from '../candid_arb'; +import { stringToSrcLiteral } from '../to_src_literal/string'; -export const TextArb = fc.string(); +export const TextArb = CandidMetaArb(fc.string(), 'text', stringToSrcLiteral); diff --git a/property_tests/arbitraries/candid/primitive/void.ts b/property_tests/arbitraries/candid/primitive/void.ts new file mode 100644 index 0000000000..d39c1339d2 --- /dev/null +++ b/property_tests/arbitraries/candid/primitive/void.ts @@ -0,0 +1,9 @@ +import fc from 'fast-check'; +import { CandidMetaArb } from '../candid_arb'; +import { voidToSrcLiteral } from '../to_src_literal/void'; + +export const VoidArb = CandidMetaArb( + fc.constant(undefined), + 'Void', + voidToSrcLiteral +); diff --git a/property_tests/arbitraries/candid/reference/func_arb.ts b/property_tests/arbitraries/candid/reference/func_arb.ts new file mode 100644 index 0000000000..28563251a9 --- /dev/null +++ b/property_tests/arbitraries/candid/reference/func_arb.ts @@ -0,0 +1,78 @@ +import fc from 'fast-check'; +import { Principal } from '@dfinity/principal'; + +import { PrincipalArb } from './principal_arb'; +import { VoidArb } from '../primitive/void'; +import { CandidMeta } from '../candid_arb'; +import { CandidType, CandidTypeArb } from '../candid_type_arb'; +import { UniqueIdentifierArb } from '../../unique_identifier_arb'; + +export type Func = [Principal, string]; +type Mode = 'query' | 'update' | 'oneway'; + +export const FuncArb = ( + fc.constantFrom('query', 'update', 'oneway') as fc.Arbitrary +) + .chain((mode) => { + const returnType = mode === 'oneway' ? VoidArb : CandidTypeArb; + + return fc.tuple( + UniqueIdentifierArb('typeDeclaration'), + fc.array(CandidTypeArb), + returnType, + fc.constant(mode), + PrincipalArb + ); + }) + .map(([name, params, returnFunc, mode, principal]): CandidMeta => { + const typeDeclaration = generateTypeDeclaration( + name, + params, + returnFunc.src.candidType, + mode + ); + + const imports = new Set([ + ...params.flatMap((param) => [...param.src.imports]), + ...returnFunc.src.imports, + 'Func' + ]); + + const value: Func = [principal.value, name]; + + const valueLiteral = `[${principal.src.valueLiteral}, '${name}']`; + + return { + src: { + candidType: name, + typeDeclaration, + imports, + valueLiteral + }, + value, + equals: funcsAreEqual + }; + }); + +function generateTypeDeclaration( + name: string, + paramCandids: CandidMeta[], + returnType: string, + mode: Mode +): string { + const params = paramCandids.map((param) => param.src.candidType).join(', '); + + return `const ${name} = Func([${params}], ${returnType}, '${mode}')`; +} + +function funcsAreEqual(result: Func, expectedResult: Func): boolean { + if (result[0].toText() !== expectedResult[0].toText()) { + return false; + } + + if (result[1] !== expectedResult[1]) { + return false; + } + + return true; +} diff --git a/property_tests/arbitraries/candid/reference/principal_arb.ts b/property_tests/arbitraries/candid/reference/principal_arb.ts index f21a6c30f8..2807ac105b 100644 --- a/property_tests/arbitraries/candid/reference/principal_arb.ts +++ b/property_tests/arbitraries/candid/reference/principal_arb.ts @@ -1,9 +1,16 @@ import fc from 'fast-check'; import { Principal } from '@dfinity/principal'; +import { CandidMetaArb } from '../candid_arb'; +import { principalToSrcLiteral } from '../to_src_literal/principal'; -export const PrincipalArb = fc - .uint8Array({ - minLength: 29, - maxLength: 29 - }) - .map((sample) => Principal.fromUint8Array(sample)); +export const PrincipalArb = CandidMetaArb( + fc + .uint8Array({ + minLength: 29, + maxLength: 29 + }) + .map((sample) => Principal.fromUint8Array(sample)), + 'Principal', + principalToSrcLiteral, + (a, b) => a.toText() === b.toText() +); diff --git a/property_tests/arbitraries/candid/to_src_literal/bigint.ts b/property_tests/arbitraries/candid/to_src_literal/bigint.ts new file mode 100644 index 0000000000..6282daafd1 --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/bigint.ts @@ -0,0 +1,3 @@ +export function bigintToSrcLiteral(value: bigint): string { + return `${value.toString()}n`; +} diff --git a/property_tests/arbitraries/candid/to_src_literal/blob.ts b/property_tests/arbitraries/candid/to_src_literal/blob.ts new file mode 100644 index 0000000000..501d4e83fd --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/blob.ts @@ -0,0 +1,3 @@ +export function blobToSrcLiteral(value: Uint8Array): string { + return `new Uint8Array([${[...value].join(', ')}])`; +} diff --git a/property_tests/arbitraries/candid/to_src_literal/boolean.ts b/property_tests/arbitraries/candid/to_src_literal/boolean.ts new file mode 100644 index 0000000000..43e8543964 --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/boolean.ts @@ -0,0 +1,3 @@ +export function booleanToSrcLiteral(value: boolean): string { + return value.toString(); +} diff --git a/property_tests/arbitraries/candid/to_src_literal/float.ts b/property_tests/arbitraries/candid/to_src_literal/float.ts new file mode 100644 index 0000000000..f789e3cb4d --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/float.ts @@ -0,0 +1,12 @@ +export function floatToSrcLiteral(value: number): string { + if (Number.isNaN(value)) { + return 'Number.NaN'; + } + if (Number.isFinite(value)) { + return value.toString(); + } + if (value > 0) { + return 'Number.POSITIVE_INFINITY'; + } + return 'Number.NEGATIVE_INFINITY'; +} diff --git a/property_tests/arbitraries/candid/to_src_literal/null.ts b/property_tests/arbitraries/candid/to_src_literal/null.ts new file mode 100644 index 0000000000..5bc6d4def1 --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/null.ts @@ -0,0 +1,3 @@ +export function nullToSrcLiteral(_value: null): string { + return 'null'; +} diff --git a/property_tests/arbitraries/candid/to_src_literal/number.ts b/property_tests/arbitraries/candid/to_src_literal/number.ts new file mode 100644 index 0000000000..04aa0c8bac --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/number.ts @@ -0,0 +1,3 @@ +export function numberToSrcLiteral(value: number): string { + return value.toString(); +} diff --git a/property_tests/arbitraries/candid/to_src_literal/principal.ts b/property_tests/arbitraries/candid/to_src_literal/principal.ts new file mode 100644 index 0000000000..2cc2cc61b4 --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/principal.ts @@ -0,0 +1,5 @@ +import { Principal } from '@dfinity/principal'; + +export function principalToSrcLiteral(value: Principal): string { + return `Principal.fromText('${value.toText()}')`; +} diff --git a/property_tests/arbitraries/candid/to_src_literal/string.ts b/property_tests/arbitraries/candid/to_src_literal/string.ts new file mode 100644 index 0000000000..54f4682739 --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/string.ts @@ -0,0 +1,10 @@ +function escapeStringForJavaScript(input: string) { + return input + .replace(/\\/g, '\\\\') // Escape backslashes + .replace(/'/g, "\\'") // Escape single quotes + .replace(/"/g, '\\"'); // Escape double quotes +} + +export function stringToSrcLiteral(value: string): string { + return `'${escapeStringForJavaScript(value)}'`; +} diff --git a/property_tests/arbitraries/candid/to_src_literal/void.ts b/property_tests/arbitraries/candid/to_src_literal/void.ts new file mode 100644 index 0000000000..c04cfbf647 --- /dev/null +++ b/property_tests/arbitraries/candid/to_src_literal/void.ts @@ -0,0 +1,3 @@ +export function voidToSrcLiteral(value: undefined): string { + return 'undefined'; +} diff --git a/property_tests/arbitraries/canister_arb.ts b/property_tests/arbitraries/canister_arb.ts index 581240103e..0753177340 100644 --- a/property_tests/arbitraries/canister_arb.ts +++ b/property_tests/arbitraries/canister_arb.ts @@ -1,20 +1,11 @@ import fc from 'fast-check'; -import { createQueryMethodArb } from './query_method_arb'; +import { QueryMethodArb } from './query_method_arb'; import { Test } from '../../test'; +import { TestSample } from './test_sample_arb'; -export type TestSample = { - functionName: string; - imports: string[]; - paramCandidTypes: string; - returnCandidType: string; - paramNames: string[]; - body: string; - test: any; -}; - -export function createCanisterArb(testArb: fc.Arbitrary) { +export function CanisterArb(testArb: fc.Arbitrary) { return fc - .array(createQueryMethodArb(testArb), { + .array(QueryMethodArb(testArb), { minLength: 20, // TODO work on these maxLength: 100 }) @@ -23,6 +14,13 @@ export function createCanisterArb(testArb: fc.Arbitrary) { (queryMethod) => queryMethod.sourceCode ); + const candidTypeDeclarations = queryMethods + .map( + (queryMethod) => + queryMethod.candidTypeDeclarations?.join('\n') ?? '' + ) + .join('\n'); + const imports = [ ...new Set( queryMethods.reduce((acc, queryMethod) => { @@ -38,7 +36,9 @@ export function createCanisterArb(testArb: fc.Arbitrary) { return { sourceCode: ` import { Canister, query, ${imports.join(', ')} } from 'azle'; - + + ${candidTypeDeclarations} + export default Canister({ ${queryMethodSourceCodes.join(',\n ')} });`, diff --git a/property_tests/arbitraries/query_method_arb.ts b/property_tests/arbitraries/query_method_arb.ts index 8495a878d5..293a9978d3 100644 --- a/property_tests/arbitraries/query_method_arb.ts +++ b/property_tests/arbitraries/query_method_arb.ts @@ -1,23 +1,36 @@ import fc from 'fast-check'; -import { TestSample } from './canister_arb'; +import { TestSample } from './test_sample_arb'; +import { Test } from '../../test'; -export function createQueryMethodArb(testArb: fc.Arbitrary) { - return testArb.map((testSample) => { - const paramNames = testSample.paramNames; - const paramCandidTypes = testSample.paramCandidTypes; - const returnCandidType = testSample.returnCandidType; - const body = testSample.body; - const functionName = testSample.functionName; +type QueryMethod = { + sourceCode: string; + test: Test; + imports: Set; + candidTypeDeclarations: string[] | undefined; +}; + +export function QueryMethodArb(testArb: fc.Arbitrary) { + return testArb.map((testSample): QueryMethod => { + const { + paramNames, + paramCandidTypes, + returnCandidType, + body, + functionName, + test, + imports, + candidTypeDeclarations + } = testSample; return { - name: functionName, sourceCode: `${functionName}: query([${paramCandidTypes}], ${returnCandidType}, (${paramNames.join( ', ' )}) => { ${body} })`, - test: testSample.test, - imports: testSample.imports + test, + imports, + candidTypeDeclarations }; }); } diff --git a/property_tests/arbitraries/test_sample_arb.ts b/property_tests/arbitraries/test_sample_arb.ts new file mode 100644 index 0000000000..67af515953 --- /dev/null +++ b/property_tests/arbitraries/test_sample_arb.ts @@ -0,0 +1,12 @@ +import { Test } from '../../test'; + +export type TestSample = { + imports: Set; + candidTypeDeclarations?: string[]; + functionName: string; + paramNames: string[]; + paramCandidTypes: string; + returnCandidType: string; + body: string; + test: Test; +}; diff --git a/property_tests/arbitraries/unique_identifier_arb.ts b/property_tests/arbitraries/unique_identifier_arb.ts new file mode 100644 index 0000000000..49e261bc0a --- /dev/null +++ b/property_tests/arbitraries/unique_identifier_arb.ts @@ -0,0 +1,27 @@ +import { JsFunctionNameArb } from './js_function_name_arb'; + +type IdentifiersMap = { + [key: string]: Set; +}; + +let identifiers: IdentifiersMap = {}; + +/** + * An arbitrary for creating unique Rust-keyword-avoidant identifiers. Generated + * identifiers are checked for uniqueness based on the provided key. Duplicates + * may occur across groupings, but never within. + * @param key the grouping in which to keep this identifier unique + * @returns an arbitrary identifier string + */ +export function UniqueIdentifierArb(key: string) { + if (!(key in identifiers)) { + identifiers[key] = new Set(); + } + + return JsFunctionNameArb.filter( + (sample) => !identifiers[key].has(sample) + ).map((sample) => { + identifiers[key].add(sample); + return sample; + }); +} diff --git a/property_tests/arbitraries/unique_primitive_arb.ts b/property_tests/arbitraries/unique_primitive_arb.ts index 612cf1b05b..428f29657a 100644 --- a/property_tests/arbitraries/unique_primitive_arb.ts +++ b/property_tests/arbitraries/unique_primitive_arb.ts @@ -2,7 +2,7 @@ import fc from 'fast-check'; let samples = new Set(); -export function createUniquePrimitiveArb(arb: fc.Arbitrary) { +export function createUniquePrimitiveArb(arb: fc.Arbitrary) { return arb .filter((primitiveSample) => !samples.has(primitiveSample)) .map((primitiveSample) => { diff --git a/property_tests/are_equal/float.ts b/property_tests/are_equal/float.ts index 40f8791a3d..9223b22145 100644 --- a/property_tests/are_equal/float.ts +++ b/property_tests/are_equal/float.ts @@ -1,7 +1,3 @@ -export function areFloatsEqual(paramName: string, paramValue: number) { - if (Number.isNaN(paramValue)) { - return `(Number.isNaN(${paramName}) && Number.isNaN(${paramValue}))`; - } else { - return `${paramName} === ${paramValue}`; - } +export function areFloatsEqual(paramName: string, paramLiteral: string) { + return `((Number.isNaN(${paramName}) && Number.isNaN(${paramLiteral})) || ${paramName} === ${paramLiteral})`; } diff --git a/property_tests/are_equal/index.ts b/property_tests/are_equal/index.ts deleted file mode 100644 index 629e47b77f..0000000000 --- a/property_tests/are_equal/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './float'; -export * from './principal'; diff --git a/property_tests/are_equal/opt.ts b/property_tests/are_equal/opt.ts new file mode 100644 index 0000000000..c372647c56 --- /dev/null +++ b/property_tests/are_equal/opt.ts @@ -0,0 +1,36 @@ +export function createAreOptsEqualCodeDeclaration(): string { + return ` + function calculateDepthAndValues(value: any): { + depth: number; + value: any; + } { + if (value.None === null) { + return { depth: 0, value: null }; + } + if (value.Some === null || (value.Some.Some === undefined && value.Some.None === undefined)) { + // The value.Some is not an opt. return value.Some + return {depth: 0, value: JSON.stringify(value.Some, (key, value) => typeof value === 'bigint' ? value.toString() + "n" : value)} + } + + const result = calculateDepthAndValues(value.Some); + return { ...result, depth: result.depth + 1 }; + } + + function areOptsEqual(opt1: any, opt2: any) { + const { depth: depth1, value: value1 } = + calculateDepthAndValues(opt1); + const { depth: depth2, value: value2 } = + calculateDepthAndValues(opt2); + + return depth1 === depth2 && value1 === value2; + } + `; +} + +export function createAreOptsEqualCodeUsage( + paramName: string, + paramLiteral: string +): string { + // TODO this only works because right now both a and b are strings when they are bigints. Try changing the areOptsEqual with deepEqual and you will see + return `areOptsEqual(${paramName}, ${paramLiteral})`; +} diff --git a/property_tests/are_equal/principal.ts b/property_tests/are_equal/principal.ts index 58affcf2ec..028ecc6b23 100644 --- a/property_tests/are_equal/principal.ts +++ b/property_tests/are_equal/principal.ts @@ -1,5 +1,3 @@ -import { Principal } from '@dfinity/principal'; - -export function arePrincipalsEqual(paramName: string, paramValue: Principal) { - return `(${paramName}.toText() === "${paramValue.toText()}")`; +export function arePrincipalsEqual(paramName: string, paramLiteral: string) { + return `(${paramName}.toText() === ${paramLiteral}.toText())`; } diff --git a/property_tests/index.ts b/property_tests/index.ts index 87dfbe6ef0..cbbc45deb8 100644 --- a/property_tests/index.ts +++ b/property_tests/index.ts @@ -1,18 +1,25 @@ import fc from 'fast-check'; -import { TestSample, createCanisterArb } from './arbitraries/canister_arb'; +import { CanisterArb } from './arbitraries/canister_arb'; +import { TestSample } from './arbitraries/test_sample_arb'; import { existsSync, mkdirSync, writeFileSync } from 'fs'; import { execSync } from 'child_process'; import { runTests } from '../test'; +export { getActor } from './get_actor'; + export function runPropTests(testArb: fc.Arbitrary) { fc.assert( - fc.asyncProperty(createCanisterArb(testArb), async (canister) => { + fc.asyncProperty(CanisterArb(testArb), async (canister) => { if (!existsSync('src')) { mkdirSync('src'); } writeFileSync('src/index.ts', canister.sourceCode); + execSync(`npx prettier --write src`, { + stdio: 'inherit' + }); + execSync(`dfx canister uninstall-code canister || true`, { stdio: 'inherit' }); @@ -25,10 +32,13 @@ export function runPropTests(testArb: fc.Arbitrary) { stdio: 'inherit' }); - return await runTests(canister.tests, false); + return await runTests( + canister.tests, + process.env.AZLE_PROPTEST_VERBOSE !== 'true' + ); }), { - numRuns: Number(process.env.AZLE_NUM_PROPTEST_RUNS ?? 1), + numRuns: Number(process.env.AZLE_PROPTEST_NUM_RUNS ?? 1), endOnFailure: true // TODO This essentially disables shrinking. We don't know how to do shrinking well yet } ); diff --git a/property_tests/tests/blob/package-lock.json b/property_tests/tests/blob/package-lock.json index a8e19d7558..e43ae16581 100644 --- a/property_tests/tests/blob/package-lock.json +++ b/property_tests/tests/blob/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "blob", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/blob/src/.gitkeep b/property_tests/tests/blob/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/blob/test/test.ts b/property_tests/tests/blob/test/test.ts index 0b96647177..9d40974a7f 100644 --- a/property_tests/tests/blob/test/test.ts +++ b/property_tests/tests/blob/test/test.ts @@ -1,90 +1,103 @@ import fc from 'fast-check'; + import { BlobArb } from '../../../arbitraries/candid/constructed/blob_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const BlobTestArb = fc .tuple( createUniquePrimitiveArb(JsFunctionNameArb), fc.array(BlobArb), - fc.oneof(fc.constant('blob'), fc.constant('Vec(nat8)')) + BlobArb ) - .map(([functionName, blobTuples, returnCandidType]) => { - const paramCandidTypes = blobTuples.map((blobTuple) => blobTuple[1]); - const paramNames = blobTuples.map((_, index) => `param${index}`); - - // TODO this ordering check is not perfect - // TODO but turning the vec into a string seems a bit difficult...we need to figure out how to check perfecly for the values that we want - // TODO maybe a global variable that we can write into and call would work - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName}.length !== ${blobTuples[index][0].length}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); - - // TODO these checks should be much more precise probably, imagine checking the elements inside of the arrays - const paramsAreUint8Arrays = paramNames - .map((paramName) => { - return `if (!(${paramName} instanceof Uint8Array)) throw new Error('${paramName} must be a Uint8Array');`; - }) - .join('\n'); - - const returnStatement = `Uint8Array.from([${paramNames - .map((paramName) => `...${paramName}`) - .join(', ')}])`; - - const expectedResult = Uint8Array.from( - blobTuples - .map((blobTuple) => blobTuple[0]) - .reduce((acc, blob) => [...acc, ...blob], [] as number[]) - ); + .map(([functionName, paramBlobs, defaultReturnBlob]): TestSample => { + const imports = defaultReturnBlob.src.imports; + const paramNames = paramBlobs.map((_, index) => `param${index}`); + const paramCandidTypes = paramBlobs + .map((blob) => blob.src.candidType) + .join(', '); + const returnCandidType = defaultReturnBlob.src.candidType; + const body = generateBody(paramNames, paramBlobs, defaultReturnBlob); + const test = generateTest(functionName, paramBlobs, defaultReturnBlob); return { + imports, functionName, - imports: ['blob', 'nat8', 'Vec'], - paramCandidTypes: paramCandidTypes.join(', '), - returnCandidType, paramNames, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreUint8Arrays} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/blob/test'); - - const result = await actor[functionName]( - ...blobTuples.map((blobTuple) => blobTuple[0]) - ); - - return { - Ok: primitiveArraysAreEqual(result, expectedResult) - }; - } - } + paramCandidTypes, + returnCandidType, + body, + test }; }); runPropTests(BlobTestArb); -function primitiveArraysAreEqual(arr1: any, arr2: any) { - // Check if both arrays have the same length - if (arr1.length !== arr2.length) { - return false; - } +function generateBody( + paramNames: string[], + paramBlobs: CandidMeta[], + returnBlob: CandidMeta +): string { + // TODO these checks should be much more precise probably, imagine checking the elements inside of the arrays + const paramsAreUint8Arrays = paramNames + .map((paramName) => { + return `if (!(${paramName} instanceof Uint8Array)) throw new Error('${paramName} must be a Uint8Array');`; + }) + .join('\n'); - // Loop through each element to check for equality - for (let i = 0; i < arr1.length; i++) { - if (arr1[i] !== arr2[i]) { - return false; - } - } + // TODO this ordering check is not perfect + // TODO but turning the vec into a string seems a bit difficult...we need to figure out how to check perfecly for the values that we want + // TODO maybe a global variable that we can write into and call would work + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + const paramIsCorrectLength = `${paramName}.length === ${paramBlobs[index].value.length}`; + + const throwError = `throw new Error('${paramName} is incorrectly ordered')`; + + return `if (!(${paramIsCorrectLength})) ${throwError};`; + }) + .join('\n'); + + const returnStatement = `Uint8Array.from([${[...returnBlob.value]} ${ + returnBlob.value.length > 0 ? ',' : '' + } ${paramNames.map((paramName) => `...${paramName}`).join(', ')}])`; - return true; + return ` + ${paramsAreUint8Arrays} + + ${paramsCorrectlyOrdered} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramBlobs: CandidMeta[], + returnBlob: CandidMeta +): Test { + const expectedResult = Uint8Array.from( + paramBlobs + .map((blob) => blob.value) + .reduce((acc, blob) => [...acc, ...blob], [...returnBlob.value]) + ); + + return { + name: `blob ${functionName}`, + test: async () => { + const actor = getActor('./tests/blob/test'); + + const result = await actor[functionName]( + ...paramBlobs.map((blob) => blob.value) + ); + + return { + Ok: returnBlob.equals(result, expectedResult) + }; + } + }; } diff --git a/property_tests/tests/bool/test/test.ts b/property_tests/tests/bool/test/test.ts index 0415dafedf..236785d67b 100644 --- a/property_tests/tests/bool/test/test.ts +++ b/property_tests/tests/bool/test/test.ts @@ -1,64 +1,100 @@ import fc from 'fast-check'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; -import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; + import { BoolArb } from '../../../arbitraries/candid/primitive/bool'; +import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const BoolTestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(BoolArb)) - .map(([functionName, bools]) => { - const paramCandidTypes = bools.map(() => 'bool').join(', '); - const returnCandidType = 'bool'; - const paramNames = bools.map((_, index) => `param${index}`); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(BoolArb), + BoolArb + ) + .map(([functionName, paramBools, defaultReturnBool]): TestSample => { + const imports = defaultReturnBool.src.imports; - const paramsAreBooleans = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'boolean') throw new Error('${paramName} must be a boolean');`; - }) - .join('\n'); + const paramNames = paramBools.map((_, index) => `param${index}`); + const paramCandidTypes = paramBools + .map((bool) => bool.src.candidType) + .join(', '); - const returnStatement = paramNames.reduce((acc, paramName) => { - return `${acc} && ${paramName}`; - }, 'true'); + const returnCandidType = defaultReturnBool.src.candidType; - const expectedResult = bools.reduce((acc, bool) => acc && bool, true); + const body = generateBody(paramNames, paramBools, defaultReturnBool); - const paramSamples = bools; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const test = generateTest(functionName, paramBools, defaultReturnBool); return { + imports, functionName, - imports: ['bool'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreBooleans} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/bool/test'); - - const result = await actor[functionName](...bools); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(BoolTestArb); + +function generateBody( + paramNames: string[], + paramBools: CandidMeta[], + returnBool: CandidMeta +): string { + // TODO do we want to encapsulate 'boolean' in the CandidArb? Like an agentType instead of a candidType, like azleValue and agentValue? + // TODO or will this not matter anymore once we start using a deep equal library + const paramsAreBooleans = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'boolean') throw new Error('${paramName} must be a boolean');`; + }) + .join('\n'); + + const paramLiterals = paramBools.map((bool) => bool.src.valueLiteral); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + const returnStatement = paramNames.reduce((acc, paramName) => { + return `${acc} && ${paramName}`; + }, returnBool.src.valueLiteral); + + return ` + ${paramsAreBooleans} + + ${paramsCorrectlyOrdered} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramBools: CandidMeta[], + returnBool: CandidMeta +): Test { + const expectedResult = paramBools.reduce( + (acc, bool) => acc && bool.value, + returnBool.value + ); + const paramValues = paramBools.map((bool) => bool.value); + + return { + name: `bool ${functionName}`, + test: async () => { + const actor = getActor('./tests/bool/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnBool.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/float32/test/test.ts b/property_tests/tests/float32/test/test.ts index f0f7ac1420..7b73a530b1 100644 --- a/property_tests/tests/float32/test/test.ts +++ b/property_tests/tests/float32/test/test.ts @@ -1,72 +1,113 @@ import fc from 'fast-check'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; -import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; + +import { areFloatsEqual } from '../../../are_equal/float'; import { Float32Arb } from '../../../arbitraries/candid/primitive/floats/float32_arb'; -import { areFloatsEqual } from '../../../are_equal'; +import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Float32TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Float32Arb)) - .map(([functionName, float32s]) => { - const paramCandidTypes = float32s.map(() => 'float32').join(', '); - const returnCandidType = 'float32'; - const paramNames = float32s.map((_, index) => `param${index}`); - - const paramsAreNumbers = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; - }) - .join('\n'); - - const returnStatement = float32s.length === 0 ? '0' : `param0`; - - const paramSamples = float32s; - const expectedResult = float32s.length === 0 ? 0 : float32s[0]; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - const areFloat32sEqual = areFloatsEqual( - paramName, - paramSamples[index] - ); - return `if (!${areFloat32sEqual}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Float32Arb), + Float32Arb + ) + .map(([functionName, paramFloat32s, defaultReturnFloat32]): TestSample => { + const imports = defaultReturnFloat32.src.imports; + + const paramNames = paramFloat32s.map((_, index) => `param${index}`); + const paramCandidTypes = paramFloat32s + .map((float32) => float32.src.candidType) + .join(', '); + + const returnCandidType = defaultReturnFloat32.src.candidType; + + const body = generateBody( + paramNames, + paramFloat32s, + defaultReturnFloat32 + ); + + const test = generateTest( + functionName, + paramFloat32s, + defaultReturnFloat32 + ); return { + imports, functionName, - imports: ['float32'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreNumbers} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/float32/test'); - - const result = await actor[functionName](...float32s); - - if (Number.isNaN(expectedResult)) { - return { - Ok: Number.isNaN(result) - }; - } - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Float32TestArb); + +function generateBody( + paramNames: string[], + paramFloat32s: CandidMeta[], + returnFloat32: CandidMeta +): string { + const paramsAreNumbers = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; + }) + .join('\n'); + + const paramLiterals = paramFloat32s.map( + (float32s) => float32s.src.valueLiteral + ); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + const areFloat32sEqual = areFloatsEqual( + paramName, + paramLiterals[index] + ); + return `if (!(${areFloat32sEqual})) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + const returnStatement = + paramFloat32s.length === 0 + ? returnFloat32.src.valueLiteral + : paramNames[0]; + + return ` + ${paramsCorrectlyOrdered} + + ${paramsAreNumbers} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramFloat32s: CandidMeta[], + returnFloat32: CandidMeta +): Test { + const expectedResult = + paramFloat32s.length === 0 + ? returnFloat32.value + : paramFloat32s[0].value; + const paramValues = paramFloat32s.map((paramFloats) => paramFloats.value); + return { + name: `float32 ${functionName}`, + test: async () => { + const actor = getActor('./tests/float32/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnFloat32.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/float64/package-lock.json b/property_tests/tests/float64/package-lock.json index 46bdfdeb88..f3fb782515 100644 --- a/property_tests/tests/float64/package-lock.json +++ b/property_tests/tests/float64/package-lock.json @@ -1,5 +1,5 @@ { - "name": "float32", + "name": "float64", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/float64/test/test.ts b/property_tests/tests/float64/test/test.ts index 0a7d4af7e4..c178659fa3 100644 --- a/property_tests/tests/float64/test/test.ts +++ b/property_tests/tests/float64/test/test.ts @@ -1,80 +1,118 @@ import fc from 'fast-check'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; + +import { areFloatsEqual } from '../../../are_equal/float'; +import { Float64Arb } from '../../../arbitraries/candid/primitive/floats/float64_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; -import { Float64ArrayArb } from '../../../arbitraries/candid/primitive/floats/float64_arb'; -import { areFloatsEqual } from '../../../are_equal'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Float64TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), Float64ArrayArb) - .map(([functionName, float64Array]) => { - const float64s = [...float64Array.values()]; - const paramCandidTypes = float64s.map(() => 'float64').join(', '); - const returnCandidType = 'float64'; - const paramNames = float64s.map((_, index) => `param${index}`); - - const paramsAreNumbers = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; - }) - .join('\n'); - - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0'); - - const length = float64s.length === 0 ? 1 : float64s.length; - - const returnStatement = `(${paramsSum}) / ${length}`; - - const expectedResult = - float64s.reduce((acc, float64) => acc + float64, 0) / length; - const paramSamples = float64s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - const areFloat64sEqual = areFloatsEqual( - paramName, - paramSamples[index] - ); - return `if (!${areFloat64sEqual}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Float64Arb), + Float64Arb + ) + .map(([functionName, paramFloat64s, defaultReturnFloat64]): TestSample => { + const imports = defaultReturnFloat64.src.imports; + + const paramNames = paramFloat64s.map((_, index) => `param${index}`); + const paramCandidTypes = paramFloat64s + .map((float64) => float64.src.candidType) + .join(', '); + + const returnCandidType = defaultReturnFloat64.src.candidType; + + const body = generateBody( + paramNames, + paramFloat64s, + defaultReturnFloat64 + ); + + const test = generateTest( + functionName, + paramFloat64s, + defaultReturnFloat64 + ); return { + imports, functionName, - imports: ['float64'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreNumbers} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/float64/test'); - - const result = await actor[functionName](...float64s); - - if (Number.isNaN(expectedResult)) { - return { - Ok: Number.isNaN(result) - }; - } - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Float64TestArb); + +function generateBody( + paramNames: string[], + paramFloat64s: CandidMeta[], + returnFloat64: CandidMeta +): string { + const paramsAreNumbers = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; + }) + .join('\n'); + + const paramLiterals = paramFloat64s.map( + (float64) => float64.src.valueLiteral + ); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + const areFloat64sEqual = areFloatsEqual( + paramName, + paramLiterals[index] + ); + return `if (!(${areFloat64sEqual})) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnFloat64.src.valueLiteral); + const count = paramFloat64s.length + 1; + const average = `(${sum}) / ${count}`; + + return ` + ${paramsCorrectlyOrdered} + + ${paramsAreNumbers} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramFloat64s: CandidMeta[], + returnFloat64: CandidMeta +): Test { + const count = paramFloat64s.length + 1; + const expectedResult = + paramFloat64s.reduce( + (acc, float64) => acc + float64.value, + returnFloat64.value + ) / count; + + const paramValues = paramFloat64s.map((float64) => float64.value); + + return { + name: `float64 ${functionName}`, + test: async () => { + const actor = getActor('./tests/float64/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnFloat64.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/func/dfx.json b/property_tests/tests/func/dfx.json new file mode 100644 index 0000000000..6ab9fbd7e4 --- /dev/null +++ b/property_tests/tests/func/dfx.json @@ -0,0 +1,16 @@ +{ + "canisters": { + "canister": { + "type": "custom", + "main": "src/index.ts", + "candid": "src/index.did", + "build": "npx azle canister", + "wasm": ".azle/canister/canister.wasm", + "gzip": true, + "declarations": { + "output": "test/dfx_generated/canister", + "node_compatibility": true + } + } + } +} diff --git a/property_tests/tests/func/package-lock.json b/property_tests/tests/func/package-lock.json new file mode 100644 index 0000000000..035546be3f --- /dev/null +++ b/property_tests/tests/func/package-lock.json @@ -0,0 +1,1174 @@ +{ + "name": "func", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "azle": "^0.18.5" + }, + "devDependencies": { + "@dfinity/agent": "^0.19.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } + }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@dfinity/agent": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-0.19.3.tgz", + "integrity": "sha512-q410aNLoOA1ZkwdAMgSo6t++pjISn9TfSybRXhPRI5Ume7eG6+6qYr/rlvcXy7Nb2+Ar7LTsHNn34IULfjni7w==", + "dev": true, + "dependencies": { + "@noble/hashes": "^1.3.1", + "base64-arraybuffer": "^0.2.0", + "borc": "^2.1.1", + "simple-cbor": "^0.4.1" + }, + "peerDependencies": { + "@dfinity/candid": "^0.19.3", + "@dfinity/principal": "^0.19.3" + } + }, + "node_modules/@dfinity/candid": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-0.19.3.tgz", + "integrity": "sha512-yXfbLSWTeRd4G0bLLxYoDqpXH3Jim0P+1PPZOoktXNC1X1hB+ea3yrZebX75t4GVoQK7123F7mxWHiPjuV2tQQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "@dfinity/principal": "^0.19.3" + } + }, + "node_modules/@dfinity/principal": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-0.19.3.tgz", + "integrity": "sha512-+nixVvdGt7ECxRvLXDXsvU9q9sSPssBtDQ4bXa149SK6gcYcmZ6lfWIi3DJNqj3tGROxILVBsguel9tECappsA==", + "dependencies": { + "@noble/hashes": "^1.3.1" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", + "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", + "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", + "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", + "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", + "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", + "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", + "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", + "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", + "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", + "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", + "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", + "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", + "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", + "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", + "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", + "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", + "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", + "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", + "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", + "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", + "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", + "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@swc/core": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.93.tgz", + "integrity": "sha512-690GRr1wUGmGYZHk7fUduX/JUwViMF2o74mnZYIWEcJaCcd9MQfkhsxPBtjeg6tF+h266/Cf3RPYhsFBzzxXcA==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.1", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.3.93", + "@swc/core-darwin-x64": "1.3.93", + "@swc/core-linux-arm-gnueabihf": "1.3.93", + "@swc/core-linux-arm64-gnu": "1.3.93", + "@swc/core-linux-arm64-musl": "1.3.93", + "@swc/core-linux-x64-gnu": "1.3.93", + "@swc/core-linux-x64-musl": "1.3.93", + "@swc/core-win32-arm64-msvc": "1.3.93", + "@swc/core-win32-ia32-msvc": "1.3.93", + "@swc/core-win32-x64-msvc": "1.3.93" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.93.tgz", + "integrity": "sha512-gEKgk7FVIgltnIfDO6GntyuQBBlAYg5imHpRgLxB1zSI27ijVVkksc6QwISzFZAhKYaBWIsFSVeL9AYSziAF7A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.93.tgz", + "integrity": "sha512-ZQPxm/fXdDQtn3yrYSL/gFfA8OfZ5jTi33yFQq6vcg/Y8talpZ+MgdSlYM0FkLrZdMTYYTNFiuBQuuvkA+av+Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.93.tgz", + "integrity": "sha512-OYFMMI2yV+aNe3wMgYhODxHdqUB/jrK0SEMHHS44GZpk8MuBXEF+Mcz4qjkY5Q1EH7KVQqXb/gVWwdgTHpjM2A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.93.tgz", + "integrity": "sha512-BT4dT78odKnJMNiq5HdjBsv29CiIdcCcImAPxeFqAeFw1LL6gh9nzI8E96oWc+0lVT5lfhoesCk4Qm7J6bty8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.93.tgz", + "integrity": "sha512-yH5fWEl1bktouC0mhh0Chuxp7HEO4uCtS/ly1Vmf18gs6wZ8DOOkgAEVv2dNKIryy+Na++ljx4Ym7C8tSJTrLw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.93.tgz", + "integrity": "sha512-OFUdx64qvrGJhXKEyxosHxgoUVgba2ztYh7BnMiU5hP8lbI8G13W40J0SN3CmFQwPP30+3oEbW7LWzhKEaYjlg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.93.tgz", + "integrity": "sha512-4B8lSRwEq1XYm6xhxHhvHmKAS7pUp1Q7E33NQ2TlmFhfKvCOh86qvThcjAOo57x8DRwmpvEVrqvpXtYagMN6Ig==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.93.tgz", + "integrity": "sha512-BHShlxtkven8ZjjvZ5QR6sC5fZCJ9bMujEkiha6W4cBUTY7ce7qGFyHmQd+iPC85d9kD/0cCiX/Xez8u0BhO7w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.93.tgz", + "integrity": "sha512-nEwNWnz4JzYAK6asVvb92yeylfxMYih7eMQOnT7ZVlZN5ba9WF29xJ6kcQKs9HRH6MvWhz9+wRgv3FcjlU6HYA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.93.tgz", + "integrity": "sha512-jibQ0zUr4kwJaQVwgmH+svS04bYTPnPw/ZkNInzxS+wFAtzINBYcU8s2PMWbDb2NGYiRSEeoSGyAvS9H+24JFA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", + "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==" + }, + "node_modules/@swc/types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, + "node_modules/@types/node": { + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "peer": true, + "dependencies": { + "undici-types": "~5.25.1" + } + }, + "node_modules/@types/uuid": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", + "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==" + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/azle": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/azle/-/azle-0.18.5.tgz", + "integrity": "sha512-9lLhVKwexVCd8OOYMXgjk06L+Mu0q29Rpchmz07HYV6idwF5kg+8QCxzytpU9GpnUeoADTQNkEkyLABtkd2hCA==", + "dependencies": { + "@dfinity/candid": "github:demergent-labs/candid#minimum_viable", + "@dfinity/principal": "^0.19.0", + "@swc/core": "^1.3.86", + "@types/uuid": "^9.0.4", + "buffer": "^6.0.3", + "esbuild": "^0.19.3", + "fs-extra": "10.0.1", + "js-sha256": "0.9.0", + "text-encoding": "0.7.0", + "ts-node": "10.3.1", + "typescript": "^5.2.2", + "uuid": "^9.0.1" + }, + "bin": { + "azle": "bin.js" + } + }, + "node_modules/azle/node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/azle/node_modules/@dfinity/candid": { + "version": "0.19.2", + "resolved": "git+ssh://git@github.com/demergent-labs/candid.git#5797fa906b1a7cc30c161dbb0eb919283ce2f80d", + "license": "Apache-2.0", + "peerDependencies": { + "@dfinity/principal": "^0.19.2" + } + }, + "node_modules/azle/node_modules/ts-node": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.1.tgz", + "integrity": "sha512-Yw3W2mYzhHfCHOICGNJqa0i+rbL0rAyg7ZIHxU+K4pgY8gd2Lh1j+XbHCusJMykbj6RZMJVOY0MlHVd+GOivcw==", + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/base64-arraybuffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", + "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/borc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", + "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", + "dev": true, + "dependencies": { + "bignumber.js": "^9.0.0", + "buffer": "^5.5.0", + "commander": "^2.15.0", + "ieee754": "^1.1.13", + "iso-url": "~0.4.7", + "json-text-sequence": "~0.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/borc/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/delimit-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", + "integrity": "sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/esbuild": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", + "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.5", + "@esbuild/android-arm64": "0.19.5", + "@esbuild/android-x64": "0.19.5", + "@esbuild/darwin-arm64": "0.19.5", + "@esbuild/darwin-x64": "0.19.5", + "@esbuild/freebsd-arm64": "0.19.5", + "@esbuild/freebsd-x64": "0.19.5", + "@esbuild/linux-arm": "0.19.5", + "@esbuild/linux-arm64": "0.19.5", + "@esbuild/linux-ia32": "0.19.5", + "@esbuild/linux-loong64": "0.19.5", + "@esbuild/linux-mips64el": "0.19.5", + "@esbuild/linux-ppc64": "0.19.5", + "@esbuild/linux-riscv64": "0.19.5", + "@esbuild/linux-s390x": "0.19.5", + "@esbuild/linux-x64": "0.19.5", + "@esbuild/netbsd-x64": "0.19.5", + "@esbuild/openbsd-x64": "0.19.5", + "@esbuild/sunos-x64": "0.19.5", + "@esbuild/win32-arm64": "0.19.5", + "@esbuild/win32-ia32": "0.19.5", + "@esbuild/win32-x64": "0.19.5" + } + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/iso-url": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", + "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "node_modules/json-text-sequence": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz", + "integrity": "sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w==", + "dev": true, + "dependencies": { + "delimit-stream": "0.1.0" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-cbor": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/simple-cbor/-/simple-cbor-0.4.1.tgz", + "integrity": "sha512-rijcxtwx2b4Bje3sqeIqw5EeW7UlOIC4YfOdwqIKacpvRQ/D78bWg/4/0m5e0U91oKvlGh7LlJuZCu07ISCC7w==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", + "deprecated": "no longer maintained" + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/property_tests/tests/func/package.json b/property_tests/tests/func/package.json new file mode 100644 index 0000000000..fd5d123560 --- /dev/null +++ b/property_tests/tests/func/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "test": "ts-node --transpile-only --ignore=false test/test.ts" + }, + "dependencies": { + "azle": "^0.18.5" + }, + "devDependencies": { + "@dfinity/agent": "^0.19.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } +} diff --git a/property_tests/tests/func/test/test.ts b/property_tests/tests/func/test/test.ts new file mode 100644 index 0000000000..17aa0d22d3 --- /dev/null +++ b/property_tests/tests/func/test/test.ts @@ -0,0 +1,135 @@ +import fc from 'fast-check'; + +import { getActor, runPropTests } from '../../..'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { FuncArb, Func } from '../../../arbitraries/candid/reference/func_arb'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { UniqueIdentifierArb } from '../../../arbitraries/unique_identifier_arb'; +import { Test } from '../../../../test'; + +const FuncTestArb = fc + .tuple( + UniqueIdentifierArb('canisterMethod'), + // TODO: Consider making this not a unique array and then dealing with + // duplicates when making the type declarations + fc.uniqueArray(FuncArb, { + selector: (entry) => entry.src.candidType + }), + FuncArb + ) + .map(([functionName, paramFuncs, defaultReturnFunc]): TestSample => { + const imports = new Set([ + 'Principal', + 'Void', + ...paramFuncs.flatMap((func) => [...func.src.imports]), + ...defaultReturnFunc.src.imports + ]); + + const candidTypeDeclarations = [ + ...paramFuncs.map((func) => func.src.typeDeclaration ?? ''), + paramFuncs.length === 0 + ? defaultReturnFunc.src.typeDeclaration ?? '' + : '' + ]; + + const paramNames = paramFuncs.map((_, index) => `param${index}`); + + const paramCandidTypes = paramFuncs + .map((func) => func.src.candidType) + .join(', '); + + const returnFunc = + paramFuncs.length === 0 ? defaultReturnFunc : paramFuncs[0]; + + const returnCandidType = returnFunc.src.candidType; + + const body = generateBody(paramFuncs, returnFunc); + + const test = generateTest(functionName, paramFuncs, returnFunc); + + return { + functionName, + imports, + candidTypeDeclarations, + paramNames, + paramCandidTypes, + returnCandidType, + body, + test + }; + }); + +runPropTests(FuncTestArb); + +function generateBody( + funcs: CandidMeta[], + returnFunc: CandidMeta +): string { + const paramsAreFuncs = funcs + .map((_, index) => { + const paramName = `param${index}`; + + const paramIsArray = `Array.isArray(${paramName})`; + const paramHas2Fields = `${paramName}.length === 2`; + const field0IsAPrincipal = `${paramName}[0]._isPrincipal === true`; + const field1IsAString = `typeof ${paramName}[1] === 'string'`; + + const paramIsAFunc = [ + paramIsArray, + paramHas2Fields, + field0IsAPrincipal, + field1IsAString + ].join(' && '); + + const throwError = `throw new Error('${paramName} must be a Func');`; + + return `if (!(${paramIsAFunc})) ${throwError}`; + }) + .join('\n'); + + const paramsCorrectlyOrdered = funcs + .map((func, paramIndex): string => { + const paramName = `param${paramIndex}`; + + const [principal, methodName] = func.value; + + const principalValueIsCorrect = `${paramName}[0].toText() === '${principal.toText()}'`; + const methodNameIsCorrect = `${paramName}[1] === '${methodName}'`; + const throwError = `throw new Error('${paramName} is incorrectly ordered')`; + + return `if (!(${principalValueIsCorrect} && ${methodNameIsCorrect})) ${throwError}`; + }) + .join('\n'); + + const returnStatement = + funcs.length === 0 ? returnFunc.src.valueLiteral : `param0`; + + return ` + ${paramsAreFuncs} + + ${paramsCorrectlyOrdered} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + funcs: CandidMeta[], + returnFunc: CandidMeta +): Test { + return { + name: `func ${functionName}`, + test: async () => { + const actor = getActor('./tests/func/test'); + + const result = await actor[functionName]( + ...funcs.map((func) => func.value) + ); + + return { + Ok: returnFunc.equals(result, returnFunc.value) + }; + } + }; +} diff --git a/property_tests/tests/func/tsconfig.json b/property_tests/tests/func/tsconfig.json new file mode 100644 index 0000000000..2638f0d8bc --- /dev/null +++ b/property_tests/tests/func/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ES2020", + "moduleResolution": "node", + "allowJs": true, + "outDir": "HACK_BECAUSE_OF_ALLOW_JS" + } +} diff --git a/property_tests/tests/int/package-lock.json b/property_tests/tests/int/package-lock.json index a8e19d7558..62324090c9 100644 --- a/property_tests/tests/int/package-lock.json +++ b/property_tests/tests/int/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "int", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/int/src/.gitkeep b/property_tests/tests/int/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/int/test/test.ts b/property_tests/tests/int/test/test.ts index caf9758706..e56811b83e 100644 --- a/property_tests/tests/int/test/test.ts +++ b/property_tests/tests/int/test/test.ts @@ -1,66 +1,98 @@ import fc from 'fast-check'; + import { IntArb } from '../../../arbitraries/candid/primitive/ints/int_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const IntTestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(IntArb)) - .map(([functionName, ints]) => { - const paramCandidTypes = ints.map(() => 'int').join(', '); - const returnCandidType = 'int'; - const paramNames = ints.map((_, index) => `param${index}`); - - const paramsAreBigInts = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'bigint') throw new Error('${paramName} must be a bigint');`; - }) - .join('\n'); - - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0n'); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(IntArb), + IntArb + ) + .map(([functionName, paramInts, defaultReturnInt]): TestSample => { + const imports = defaultReturnInt.src.imports; - const returnStatement = `${paramsSum}`; + const paramNames = paramInts.map((_, index) => `param${index}`); + const paramCandidTypes = paramInts + .map((int) => int.src.candidType) + .join(', '); - const expectedResult = ints.reduce((acc, int) => acc + int, 0n); + const returnCandidType = defaultReturnInt.src.candidType; - const paramSamples = ints; + const body = generateBody(paramNames, paramInts, defaultReturnInt); - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}n) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const test = generateTest(functionName, paramInts, defaultReturnInt); return { + imports, functionName, - imports: ['int'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreBigInts} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/int/test'); - - const result = await actor[functionName](...ints); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(IntTestArb); + +function generateBody( + paramNames: string[], + paramInts: CandidMeta[], + returnInt: CandidMeta +): string { + const paramsAreBigInts = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'bigint') throw new Error('${paramName} must be a bigint');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnInt.src.valueLiteral); + + const paramLiterals = paramInts.map((sample) => sample.src.valueLiteral); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreBigInts} + + ${paramsCorrectlyOrdered} + + return ${sum}; + `; +} + +function generateTest( + functionName: string, + paramInts: CandidMeta[], + returnInt: CandidMeta +): Test { + const expectedResult = paramInts.reduce( + (acc, int) => acc + int.value, + returnInt.value + ); + const paramValues = paramInts.map((sample) => sample.value); + + return { + name: `int ${functionName}`, + test: async () => { + const actor = getActor('./tests/int/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnInt.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/int16/package-lock.json b/property_tests/tests/int16/package-lock.json index a8e19d7558..0d9c69cf61 100644 --- a/property_tests/tests/int16/package-lock.json +++ b/property_tests/tests/int16/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "int16", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/int16/src/.gitkeep b/property_tests/tests/int16/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/int16/test/test.ts b/property_tests/tests/int16/test/test.ts index 3b3dcd472d..6048748e77 100644 --- a/property_tests/tests/int16/test/test.ts +++ b/property_tests/tests/int16/test/test.ts @@ -1,70 +1,109 @@ import fc from 'fast-check'; + import { Int16Arb } from '../../../arbitraries/candid/primitive/ints/int16_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Int16TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Int16Arb)) - .map(([functionName, int16s]) => { - const paramCandidTypes = int16s.map(() => 'int16').join(', '); - const returnCandidType = 'int16'; - const paramNames = int16s.map((_, index) => `param${index}`); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Int16Arb), + Int16Arb + ) + .map(([functionName, paramInt16s, defaultReturnInt16]): TestSample => { + const imports = defaultReturnInt16.src.imports; - const paramsAreNumbers = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; - }) - .join('\n'); + const paramNames = paramInt16s.map((_, index) => `param${index}`); + const paramCandidTypes = paramInt16s + .map((int16) => int16.src.candidType) + .join(', '); - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0'); + const returnCandidType = defaultReturnInt16.src.candidType; - const length = int16s.length === 0 ? 1 : int16s.length; + const body = generateBody(paramNames, paramInt16s, defaultReturnInt16); - const returnStatement = `Math.floor((${paramsSum}) / ${length})`; - - const expectedResult = Math.floor( - int16s.reduce((acc, int16) => acc + int16, 0) / length + const test = generateTest( + functionName, + paramInt16s, + defaultReturnInt16 ); - const paramSamples = int16s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); - return { + imports, functionName, - imports: ['int16'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreNumbers} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/int16/test'); - - const result = await actor[functionName](...int16s); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Int16TestArb); + +function generateBody( + paramNames: string[], + paramInt16s: CandidMeta[], + returnInt16: CandidMeta +): string { + const paramsAreNumbers = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; + }) + .join('\n'); + + const paramValueLiterals = paramInt16s.map( + (sample) => sample.src.valueLiteral + ); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramValueLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnInt16.src.valueLiteral); + const count = paramInt16s.length + 1; + const average = `Math.floor((${sum}) / ${count})`; + + return ` + ${paramsAreNumbers} + + ${paramsCorrectlyOrdered} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramInt16s: CandidMeta[], + returnInt16: CandidMeta +): Test { + const count = paramInt16s.length + 1; + const expectedResult = Math.floor( + paramInt16s.reduce( + (acc, int16) => acc + int16.value, + returnInt16.value + ) / count + ); + const paramValues = paramInt16s.map((sample) => sample.value); + + return { + name: `int16 ${functionName}`, + test: async () => { + const actor = getActor('./tests/int16/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnInt16.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/int32/package-lock.json b/property_tests/tests/int32/package-lock.json index a8e19d7558..5135c2e33d 100644 --- a/property_tests/tests/int32/package-lock.json +++ b/property_tests/tests/int32/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "int32", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/int32/src/.gitkeep b/property_tests/tests/int32/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/int32/test/test.ts b/property_tests/tests/int32/test/test.ts index ccd7c83fca..11c736d144 100644 --- a/property_tests/tests/int32/test/test.ts +++ b/property_tests/tests/int32/test/test.ts @@ -1,70 +1,107 @@ import fc from 'fast-check'; + import { Int32Arb } from '../../../arbitraries/candid/primitive/ints/int32_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Int32TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Int32Arb)) - .map(([functionName, int32s]) => { - const paramCandidTypes = int32s.map(() => 'int32').join(', '); - const returnCandidType = 'int32'; - const paramNames = int32s.map((_, index) => `param${index}`); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Int32Arb), + Int32Arb + ) + .map(([functionName, paramInt32s, defaultReturnInt32]): TestSample => { + const imports = defaultReturnInt32.src.imports; - const paramsAreNumbers = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; - }) - .join('\n'); + const paramNames = paramInt32s.map((_, index) => `param${index}`); + const paramCandidTypes = paramInt32s + .map((int32) => int32.src.candidType) + .join(', '); - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0'); + const returnCandidType = defaultReturnInt32.src.candidType; - const length = int32s.length === 0 ? 1 : int32s.length; + const body = generateBody(paramNames, paramInt32s, defaultReturnInt32); - const returnStatement = `Math.floor((${paramsSum}) / ${length})`; - - const expectedResult = Math.floor( - int32s.reduce((acc, int32) => acc + int32, 0) / length + const test = generateTest( + functionName, + paramInt32s, + defaultReturnInt32 ); - const paramSamples = int32s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); - return { + imports, functionName, - imports: ['int32'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreNumbers} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/int32/test'); - - const result = await actor[functionName](...int32s); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Int32TestArb); + +function generateBody( + paramNames: string[], + paramInt32s: CandidMeta[], + returnInt32: CandidMeta +): string { + const paramsAreNumbers = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnInt32.src.valueLiteral); + const count = paramInt32s.length + 1; + const average = `Math.floor((${sum}) / ${count})`; + + const paramLiterals = paramInt32s.map((sample) => sample.src.valueLiteral); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreNumbers} + + ${paramsCorrectlyOrdered} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramInt32s: CandidMeta[], + returnInt32: CandidMeta +): Test { + const count = paramInt32s.length + 1; + const expectedResult = Math.floor( + paramInt32s.reduce( + (acc, int32) => acc + int32.value, + returnInt32.value + ) / count + ); + const paramValues = paramInt32s.map((sample) => sample.value); + + return { + name: `int32 ${functionName}`, + test: async () => { + const actor = getActor('./tests/int32/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnInt32.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/int64/package-lock.json b/property_tests/tests/int64/package-lock.json index a8e19d7558..af549dcc6b 100644 --- a/property_tests/tests/int64/package-lock.json +++ b/property_tests/tests/int64/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "int64", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/int64/src/.gitkeep b/property_tests/tests/int64/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/int64/test/test.ts b/property_tests/tests/int64/test/test.ts index 52090b3b52..0c432809b9 100644 --- a/property_tests/tests/int64/test/test.ts +++ b/property_tests/tests/int64/test/test.ts @@ -1,69 +1,107 @@ import fc from 'fast-check'; + import { Int64Arb } from '../../../arbitraries/candid/primitive/ints/int64_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Int64TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Int64Arb)) - .map(([functionName, int64s]) => { - const paramCandidTypes = int64s.map(() => 'int64').join(', '); - const returnCandidType = 'int64'; - const paramNames = int64s.map((_, index) => `param${index}`); - - const paramsAreBigInts = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'bigint') throw new Error('${paramName} must be a bigint');`; - }) - .join('\n'); - - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0n'); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Int64Arb), + Int64Arb + ) + .map(([functionName, paramInt64s, defaultReturnInt64]): TestSample => { + const imports = defaultReturnInt64.src.imports; - const length = int64s.length === 0 ? 1 : int64s.length; + const paramNames = paramInt64s.map((_, index) => `param${index}`); + const paramCandidTypes = paramInt64s + .map((int64) => int64.src.candidType) + .join(', '); - const returnStatement = `(${paramsSum}) / ${length}n`; + const returnCandidType = defaultReturnInt64.src.candidType; - const expectedResult = - int64s.reduce((acc, int64) => acc + int64, 0n) / BigInt(length); + const body = generateBody(paramNames, paramInt64s, defaultReturnInt64); - const paramSamples = int64s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}n) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const test = generateTest( + functionName, + paramInt64s, + defaultReturnInt64 + ); return { + imports, functionName, - imports: ['int64'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreBigInts} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/int64/test'); - - const result = await actor[functionName](...int64s); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Int64TestArb); + +function generateBody( + paramNames: string[], + paramInt64s: CandidMeta[], + returnInt64: CandidMeta +): string { + const paramsAreBigInts = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'bigint') throw new Error('${paramName} must be a bigint');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnInt64.src.valueLiteral); + const count = paramInt64s.length + 1; + const average = `(${sum}) / ${count}n`; + + const paramLiterals = paramInt64s.map((sample) => sample.src.valueLiteral); + + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreBigInts} + + ${paramsCorrectlyOrdered} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramInt64s: CandidMeta[], + returnInt64: CandidMeta +): Test { + const count = paramInt64s.length + 1; + const expectedResult = + paramInt64s.reduce( + (acc, int64) => acc + int64.value, + returnInt64.value + ) / BigInt(count); + + const paramValues = paramInt64s.map((sample) => sample.value); + return { + name: `int64 ${functionName}`, + test: async () => { + const actor = getActor('./tests/int64/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: result === expectedResult + }; + } + }; +} diff --git a/property_tests/tests/int8/package-lock.json b/property_tests/tests/int8/package-lock.json index a8e19d7558..8fdd08fd9c 100644 --- a/property_tests/tests/int8/package-lock.json +++ b/property_tests/tests/int8/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "int8", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/int8/src/.gitkeep b/property_tests/tests/int8/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/int8/test/test.ts b/property_tests/tests/int8/test/test.ts index 685464ad2f..735652cc50 100644 --- a/property_tests/tests/int8/test/test.ts +++ b/property_tests/tests/int8/test/test.ts @@ -1,70 +1,101 @@ import fc from 'fast-check'; + import { Int8Arb } from '../../../arbitraries/candid/primitive/ints/int8_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Int8TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Int8Arb)) - .map(([functionName, int8s]) => { - const paramCandidTypes = int8s.map(() => 'int8').join(', '); - const returnCandidType = 'int8'; - const paramNames = int8s.map((_, index) => `param${index}`); - - const paramsAreNumbers = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; - }) - .join('\n'); - - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0'); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Int8Arb), + Int8Arb + ) + .map(([functionName, paramInt8s, defaultReturnInt8]): TestSample => { + const imports = defaultReturnInt8.src.imports; - const length = int8s.length === 0 ? 1 : int8s.length; + const paramNames = paramInt8s.map((_, index) => `param${index}`); + const paramCandidTypes = paramInt8s + .map((int8) => int8.src.candidType) + .join(', '); - const returnStatement = `Math.floor((${paramsSum}) / ${length})`; + const returnCandidType = defaultReturnInt8.src.candidType; - const expectedResult = Math.floor( - int8s.reduce((acc, int8) => acc + int8, 0) / length - ); + const body = generateBody(paramNames, paramInt8s, defaultReturnInt8); - const paramSamples = int8s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const test = generateTest(functionName, paramInt8s, defaultReturnInt8); return { + imports, functionName, - imports: ['int8'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreNumbers} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/int8/test'); - - const result = await actor[functionName](...int8s); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Int8TestArb); + +function generateBody( + paramNames: string[], + paramInt8s: CandidMeta[], + returnInt8: CandidMeta +): string { + const paramsAreNumbers = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnInt8.src.valueLiteral); + const count = paramInt8s.length + 1; + const average = `Math.floor((${sum}) / ${count})`; + + const paramLiterals = paramInt8s.map((sample) => sample.src.valueLiteral); + + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreNumbers} + + ${paramsCorrectlyOrdered} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramInt8s: CandidMeta[], + returnInt8: CandidMeta +): Test { + const count = paramInt8s.length + 1; + const expectedResult = Math.floor( + paramInt8s.reduce((acc, int8) => acc + int8.value, returnInt8.value) / + count + ); + const paramValues = paramInt8s.map((sample) => sample.value); + return { + name: `test ${functionName}`, + test: async () => { + const actor = getActor('./tests/int8/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: result === expectedResult + }; + } + }; +} diff --git a/property_tests/tests/nat/src/.gitkeep b/property_tests/tests/nat/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/nat/test/test.ts b/property_tests/tests/nat/test/test.ts index ee5be1f3d1..5466e9bfbc 100644 --- a/property_tests/tests/nat/test/test.ts +++ b/property_tests/tests/nat/test/test.ts @@ -1,66 +1,98 @@ import fc from 'fast-check'; + import { NatArb } from '../../../arbitraries/candid/primitive/nats/nat_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../../'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const NatTestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(NatArb)) - .map(([functionName, nats]) => { - const paramCandidTypes = nats.map(() => 'nat').join(', '); - const returnCandidType = 'nat'; - const paramNames = nats.map((_, index) => `param${index}`); - - const paramsAreBigInts = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'bigint') throw new Error('${paramName} must be a bigint');`; - }) - .join('\n'); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(NatArb), + NatArb + ) + .map(([functionName, paramNats, defaultReturnNat]): TestSample => { + const imports = defaultReturnNat.src.imports; - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0n'); + const paramNames = paramNats.map((_, index) => `param${index}`); + const paramCandidTypes = paramNats + .map((nat) => nat.src.candidType) + .join(', '); - const returnStatement = `${paramsSum}`; + const returnCandidType = defaultReturnNat.src.candidType; - const expectedResult = nats.reduce((acc, nat) => acc + nat, 0n); + const body = generateBody(paramNames, paramNats, defaultReturnNat); - const paramSamples = nats; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}n) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const test = generateTest(functionName, paramNats, defaultReturnNat); return { + imports, functionName, - imports: ['nat'], paramCandidTypes, returnCandidType, paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreBigInts} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/nat/test'); - - const result = await actor[functionName](...nats); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(NatTestArb); + +function generateBody( + paramNames: string[], + paramNats: CandidMeta[], + returnNat: CandidMeta +): string { + const paramsAreBigInts = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'bigint') throw new Error('${paramName} must be a bigint');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnNat.src.valueLiteral); + + const paramLiterals = paramNats.map((sample) => sample.src.valueLiteral); + + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + return ` + ${paramsCorrectlyOrdered} + + ${paramsAreBigInts} + + return ${sum}; + `; +} + +function generateTest( + functionName: string, + paramNats: CandidMeta[], + returnNat: CandidMeta +): Test { + const expectedResult = paramNats.reduce( + (acc, nat) => acc + nat.value, + returnNat.value + ); + const paramValues = paramNats.map((sample) => sample.value); + + return { + name: `nat ${functionName}`, + test: async () => { + const actor = getActor('./tests/nat/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: result === expectedResult + }; + } + }; +} diff --git a/property_tests/tests/nat16/package-lock.json b/property_tests/tests/nat16/package-lock.json index a8e19d7558..b05f4fc63b 100644 --- a/property_tests/tests/nat16/package-lock.json +++ b/property_tests/tests/nat16/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "nat16", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/nat16/src/.gitkeep b/property_tests/tests/nat16/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/nat16/test/test.ts b/property_tests/tests/nat16/test/test.ts index 3d1ad24b7f..585209e7be 100644 --- a/property_tests/tests/nat16/test/test.ts +++ b/property_tests/tests/nat16/test/test.ts @@ -1,70 +1,107 @@ import fc from 'fast-check'; + import { Nat16Arb } from '../../../arbitraries/candid/primitive/nats/nat16_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Nat16TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Nat16Arb)) - .map(([functionName, nat16s]) => { - const paramCandidTypes = nat16s.map(() => 'nat16').join(', '); - const returnCandidType = 'nat16'; - const paramNames = nat16s.map((_, index) => `param${index}`); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Nat16Arb), + Nat16Arb + ) + .map(([functionName, paramNat16s, defaultReturnNat16]): TestSample => { + const imports = defaultReturnNat16.src.imports; - const paramsAreNumbers = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; - }) - .join('\n'); + const paramNames = paramNat16s.map((_, index) => `param${index}`); + const paramCandidTypes = paramNat16s + .map((nat16) => nat16.src.candidType) + .join(', '); - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0'); + const returnCandidType = defaultReturnNat16.src.candidType; - const length = nat16s.length === 0 ? 1 : nat16s.length; + const body = generateBody(paramNames, paramNat16s, defaultReturnNat16); - const returnStatement = `Math.floor((${paramsSum}) / ${length})`; - - const expectedResult = Math.floor( - nat16s.reduce((acc, nat16) => acc + nat16, 0) / length + const test = generateTest( + functionName, + paramNat16s, + defaultReturnNat16 ); - const paramSamples = nat16s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); - return { + imports, functionName, - imports: ['nat16'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreNumbers} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/nat16/test'); - - const result = await actor[functionName](...nat16s); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Nat16TestArb); + +function generateBody( + paramNames: string[], + paramNat16s: CandidMeta[], + returnNat16: CandidMeta +): string { + const paramsAreNumbers = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnNat16.src.valueLiteral); + const count = paramNat16s.length + 1; + const average = `Math.floor((${sum}) / ${count})`; + + const paramLiterals = paramNat16s.map((sample) => sample.src.valueLiteral); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreNumbers} + + ${paramsCorrectlyOrdered} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramNat16s: CandidMeta[], + returnNat16: CandidMeta +): Test { + const count = paramNat16s.length + 1; + const expectedResult = Math.floor( + paramNat16s.reduce( + (acc, nat16) => acc + nat16.value, + returnNat16.value + ) / count + ); + const paramValues = paramNat16s.map((sample) => sample.value); + + return { + name: `nat16 ${functionName}`, + test: async () => { + const actor = getActor('./tests/nat16/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnNat16.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/nat32/package-lock.json b/property_tests/tests/nat32/package-lock.json index a8e19d7558..36553cfa29 100644 --- a/property_tests/tests/nat32/package-lock.json +++ b/property_tests/tests/nat32/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "nat32", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/nat32/src/.gitkeep b/property_tests/tests/nat32/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/nat32/test/test.ts b/property_tests/tests/nat32/test/test.ts index a7bb6d90da..3fd3bd2c0b 100644 --- a/property_tests/tests/nat32/test/test.ts +++ b/property_tests/tests/nat32/test/test.ts @@ -1,70 +1,108 @@ import fc from 'fast-check'; + import { Nat32Arb } from '../../../arbitraries/candid/primitive/nats/nat32_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../..'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Nat32TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Nat32Arb)) - .map(([functionName, nat32s]) => { - const paramCandidTypes = nat32s.map(() => 'nat32').join(', '); - const returnCandidType = 'nat32'; - const paramNames = nat32s.map((_, index) => `param${index}`); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Nat32Arb), + Nat32Arb + ) + .map(([functionName, paramNat32s, defaultReturnNat32]): TestSample => { + const imports = defaultReturnNat32.src.imports; - const paramsAreNumbers = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; - }) - .join('\n'); + const paramNames = paramNat32s.map((_, index) => `param${index}`); + const paramCandidTypes = paramNat32s + .map((nat32) => nat32.src.candidType) + .join(', '); - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0'); + const returnCandidType = defaultReturnNat32.src.candidType; - const length = nat32s.length === 0 ? 1 : nat32s.length; + const body = generateBody(paramNames, paramNat32s, defaultReturnNat32); - const returnStatement = `Math.floor((${paramsSum}) / ${length})`; - - const expectedResult = Math.floor( - nat32s.reduce((acc, nat32) => acc + nat32, 0) / length + const test = generateTest( + functionName, + paramNat32s, + defaultReturnNat32 ); - const paramSamples = nat32s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); - return { + imports, functionName, - imports: ['nat32'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreNumbers} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/nat32/test'); - - const result = await actor[functionName](...nat32s); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Nat32TestArb); + +function generateBody( + paramNames: string[], + paramNat32s: CandidMeta[], + returnNat32: CandidMeta +): string { + const paramsAreNumbers = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnNat32.src.valueLiteral); + const count = paramNat32s.length + 1; + const average = `Math.floor((${sum}) / ${count})`; + + const paramLiterals = paramNat32s.map((sample) => sample.src.valueLiteral); + + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreNumbers} + + ${paramsCorrectlyOrdered} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramNat32s: CandidMeta[], + returnNat32: CandidMeta +): Test { + const count = paramNat32s.length + 1; + const expectedResult = Math.floor( + paramNat32s.reduce( + (acc, nat32) => acc + nat32.value, + returnNat32.value + ) / count + ); + const paramValues = paramNat32s.map((sample) => sample.value); + + return { + name: `nat32 ${functionName}`, + test: async () => { + const actor = getActor('./tests/nat32/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnNat32.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/nat64/package-lock.json b/property_tests/tests/nat64/package-lock.json index a8e19d7558..a61a5dab26 100644 --- a/property_tests/tests/nat64/package-lock.json +++ b/property_tests/tests/nat64/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "nat64", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/nat64/src/.gitkeep b/property_tests/tests/nat64/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/nat64/test/test.ts b/property_tests/tests/nat64/test/test.ts index df23279919..3b443ba58a 100644 --- a/property_tests/tests/nat64/test/test.ts +++ b/property_tests/tests/nat64/test/test.ts @@ -1,69 +1,106 @@ import fc from 'fast-check'; + import { Nat64Arb } from '../../../arbitraries/candid/primitive/nats/nat64_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../../'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Nat64TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Nat64Arb)) - .map(([functionName, nat64s]) => { - const paramCandidTypes = nat64s.map(() => 'nat64').join(', '); - const returnCandidType = 'nat64'; - const paramNames = nat64s.map((_, index) => `param${index}`); - - const paramsAreBigInts = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'bigint') throw new Error('${paramName} must be a bigint');`; - }) - .join('\n'); - - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0n'); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Nat64Arb), + Nat64Arb + ) + .map(([functionName, paramNat64s, defaultReturnNat64]): TestSample => { + const imports = defaultReturnNat64.src.imports; - const length = nat64s.length === 0 ? 1 : nat64s.length; + const paramNames = paramNat64s.map((_, index) => `param${index}`); + const paramCandidTypes = paramNat64s + .map((nat64) => nat64.src.candidType) + .join(', '); - const returnStatement = `(${paramsSum}) / ${length}n`; + const returnCandidType = defaultReturnNat64.src.candidType; - const expectedResult = - nat64s.reduce((acc, nat64) => acc + nat64, 0n) / BigInt(length); + const body = generateBody(paramNames, paramNat64s, defaultReturnNat64); - const paramSamples = nat64s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}n) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const test = generateTest( + functionName, + paramNat64s, + defaultReturnNat64 + ); return { + imports, functionName, - imports: ['nat64'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreBigInts} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/nat64/test'); - - const result = await actor[functionName](...nat64s); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Nat64TestArb); + +function generateBody( + paramNames: string[], + paramNat64s: CandidMeta[], + returnNat64: CandidMeta +): string { + const paramsAreBigInts = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'bigint') throw new Error('${paramName} must be a bigint');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnNat64.src.valueLiteral); + const count = paramNat64s.length + 1; + const average = `(${sum}) / ${count}n`; + + const paramLiterals = paramNat64s.map((sample) => sample.src.valueLiteral); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiterals[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreBigInts} + + ${paramsCorrectlyOrdered} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramNat64s: CandidMeta[], + returnNat64: CandidMeta +): Test { + const count = paramNat64s.length + 1; + const expectedResult = + paramNat64s.reduce( + (acc, nat64) => acc + nat64.value, + returnNat64.value + ) / BigInt(count); + const paramValues = paramNat64s.map((sample) => sample.value); + + return { + name: `nat64 ${functionName}`, + test: async () => { + const actor = getActor('./tests/nat64/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnNat64.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/nat8/package-lock.json b/property_tests/tests/nat8/package-lock.json index a8e19d7558..96b6e70bf7 100644 --- a/property_tests/tests/nat8/package-lock.json +++ b/property_tests/tests/nat8/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "nat8", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/nat8/src/.gitkeep b/property_tests/tests/nat8/src/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/property_tests/tests/nat8/test/test.ts b/property_tests/tests/nat8/test/test.ts index e1405c6a5b..1c337c78e2 100644 --- a/property_tests/tests/nat8/test/test.ts +++ b/property_tests/tests/nat8/test/test.ts @@ -1,70 +1,101 @@ import fc from 'fast-check'; + import { Nat8Arb } from '../../../arbitraries/candid/primitive/nats/nat8_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const Nat8TestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(Nat8Arb)) - .map(([functionName, nat8s]) => { - const paramCandidTypes = nat8s.map(() => 'nat8').join(', '); - const returnCandidType = 'nat8'; - const paramNames = nat8s.map((_, index) => `param${index}`); - - const paramsAreNumbers = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; - }) - .join('\n'); - - const paramsSum = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '0'); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(Nat8Arb), + Nat8Arb + ) + .map(([functionName, paramNat8s, defaultReturnNat8]): TestSample => { + const imports = defaultReturnNat8.src.imports; - const length = nat8s.length === 0 ? 1 : nat8s.length; + const paramNames = paramNat8s.map((_, index) => `param${index}`); + const paramCandidTypes = paramNat8s + .map((nat8) => nat8.src.candidType) + .join(', '); - const returnStatement = `Math.floor((${paramsSum}) / ${length})`; + const returnCandidType = defaultReturnNat8.src.candidType; - const expectedResult = Math.floor( - nat8s.reduce((acc, nat8) => acc + nat8, 0) / length - ); + const body = generateBody(paramNames, paramNat8s, defaultReturnNat8); - const paramSamples = nat8s; - - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== ${paramSamples[index]}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const test = generateTest(functionName, paramNat8s, defaultReturnNat8); return { + imports, functionName, - imports: ['nat8'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreNumbers} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/nat8/test'); - - const result = await actor[functionName](...nat8s); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(Nat8TestArb); + +function generateBody( + paramNames: string[], + paramNat8s: CandidMeta[], + returnNat8: CandidMeta +): string { + const paramsAreNumbers = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'number') throw new Error('${paramName} must be a number');`; + }) + .join('\n'); + + const sum = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnNat8.src.valueLiteral); + const count = paramNat8s.length + 1; + const average = `Math.floor((${sum}) / ${count})`; + + const paramLiteral = paramNat8s.map((sample) => sample.src.valueLiteral); + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramLiteral[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreNumbers} + + ${paramsCorrectlyOrdered} + + return ${average}; + `; +} + +function generateTest( + functionName: string, + paramNat8s: CandidMeta[], + returnNat8: CandidMeta +): Test { + const count = paramNat8s.length + 1; + const expectedResult = Math.floor( + paramNat8s.reduce((acc, nat8) => acc + nat8.value, returnNat8.value) / + count + ); + const paramValues = paramNat8s.map((sample) => sample.value); + + return { + name: `nat8 ${functionName}`, + test: async () => { + const actor = getActor('./tests/nat8/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnNat8.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/null/test/test.ts b/property_tests/tests/null/test/test.ts index 9205956e1f..c39527a259 100644 --- a/property_tests/tests/null/test/test.ts +++ b/property_tests/tests/null/test/test.ts @@ -1,48 +1,80 @@ import fc from 'fast-check'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; -import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; + import { NullArb } from '../../../arbitraries/candid/primitive/null'; +import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const NullTestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(NullArb)) - .map(([functionName, nulls]) => { - const paramCandidTypes = nulls.map(() => 'Null').join(', '); - const returnCandidType = 'Null'; - const paramNames = nulls.map((_, index) => `param${index}`); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(NullArb), + NullArb + ) + .map(([functionName, paramNulls, returnNull]): TestSample => { + const imports = returnNull.src.imports; + + const paramNames = paramNulls.map((_, index) => `param${index}`); + const paramCandidTypes = paramNulls + .map((Null) => Null.src.candidType) + .join(', '); + + const returnCandidType = returnNull.src.candidType; - const areAllNull = paramNames.reduce((acc, paramName) => { - return `${acc} && ${paramName} === null`; - }, 'true'); + const body = generateBody(paramNames, returnNull); - const allNullCheck = `if (!(${areAllNull})) throw new Error("Not all of the values were null")`; + const test = generateTest(functionName, paramNulls, returnNull); return { functionName, - imports: ['Null'], + imports, paramCandidTypes, returnCandidType, paramNames, - paramSamples: nulls, - body: ` - ${allNullCheck} - - return null; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/null/test'); - - const result = await actor[functionName](...nulls); - - return { - Ok: result === null - }; - } - } + body, + test }; }); runPropTests(NullTestArb); + +function generateBody( + paramNames: string[], + returnNull: CandidMeta +): string { + const areAllNull = paramNames.reduce((acc, paramName) => { + return `${acc} && ${paramName} === null`; + }, 'true'); + + const allNullCheck = `if (!(${areAllNull})) throw new Error("Not all of the values were null")`; + + return ` + ${allNullCheck} + + return ${returnNull.src.valueLiteral}; + `; +} + +function generateTest( + functionName: string, + paramNulls: CandidMeta[], + returnNull: CandidMeta +): Test { + return { + name: `test ${functionName}`, + test: async () => { + const actor = getActor('./tests/null/test'); + + const result = await actor[functionName]( + ...paramNulls.map((sample) => sample.value) + ); + + return { + Ok: returnNull.equals(result, null) + }; + } + }; +} diff --git a/property_tests/tests/opt/package-lock.json b/property_tests/tests/opt/package-lock.json index a8e19d7558..329cba2c5d 100644 --- a/property_tests/tests/opt/package-lock.json +++ b/property_tests/tests/opt/package-lock.json @@ -1,5 +1,5 @@ { - "name": "nat", + "name": "opt", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/property_tests/tests/opt/test/test.ts b/property_tests/tests/opt/test/test.ts index 77783411fa..1cdeb0524a 100644 --- a/property_tests/tests/opt/test/test.ts +++ b/property_tests/tests/opt/test/test.ts @@ -1,92 +1,118 @@ import fc from 'fast-check'; -import { OptArb } from '../../../arbitraries/candid/constructed/opt_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; + +import { + createAreOptsEqualCodeDeclaration, + createAreOptsEqualCodeUsage +} from '../../../are_equal/opt'; +import { Opt, OptArb } from '../../../arbitraries/candid/constructed/opt_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const OptTestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(OptArb)) - .map(([functionName, optWrappers]) => { - const paramCandidTypes = optWrappers.map( - (vecWrapper) => vecWrapper.candidType - ); - const returnCandidType = optWrappers[0]?.candidType ?? 'Opt(int8)'; - const paramNames = optWrappers.map((_, index) => `param${index}`); - - // TODO this ordering check is not perfect - // TODO but turning the vec into a string seems a bit difficult...we need to figure out how to check perfecly for the values that we want - // TODO maybe a global variable that we can write into and call would work - // TODO we really need to create some kind of universal equality checking solution - // const paramsCorrectlyOrdered = paramNames - // .map((paramName, index) => { - // return `if (${paramName}.Some === undefined && ${optWrappers[index].opt.Some} === undefined && ${paramName}.None !== ${optWrappers[index].opt.None}) throw new Error('${paramName} is incorrectly ordered')`; - // }) - // .join('\n'); - - // TODO these checks should be much more precise probably, imagine checking the values inside of the opts - const paramsOpts = paramNames - .map((paramName) => { - return `if (${paramName}.Some === undefined && ${paramName}.None === undefined) throw new Error('${paramName} must be an Opt');`; - }) - .join('\n'); - - const returnStatement = paramNames[0] ?? `None`; - - const expectedResult = - optWrappers[0]?.opt.Some !== undefined - ? [optWrappers[0]?.opt.Some] - : []; + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(OptArb), + OptArb + ) + .map(([functionName, paramOpts, defaultReturnOpt]): TestSample => { + const imports = new Set([ + 'None', + ...paramOpts.flatMap((opt) => [...opt.src.imports]), + ...defaultReturnOpt.src.imports + ]); + + const paramNames = paramOpts.map((_, index) => `param${index}`); + const paramCandidTypes = paramOpts + .map((opt) => opt.src.candidType) + .join(', '); + + const returnCandidType = + paramOpts.length === 0 + ? defaultReturnOpt.src.candidType + : paramOpts[0].src.candidType; + + const body = generateBody(paramNames, paramOpts, defaultReturnOpt); + + const test = generateTest(functionName, paramOpts, defaultReturnOpt); return { + imports, functionName, - imports: [ - 'int', - 'int8', - 'int16', - 'int32', - 'int64', - 'nat', - 'nat8', - 'nat16', - 'nat32', - 'nat64', - 'None', - 'Opt' - ], - paramCandidTypes: paramCandidTypes.join(', '), - returnCandidType, paramNames, - body: ` - ${paramsOpts} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/opt/test'); - - const result = await actor[functionName]( - ...optWrappers.map((optWrapper) => { - if (optWrapper.opt.Some !== undefined) { - return [optWrapper.opt.Some]; - } else { - return []; - } - }) - ); - - // TODO be careful on equality checks when we go beyond primitives - // TODO a universal equality checker is going to be very useful - return { - Ok: - result.length === expectedResult.length && - result[0] === expectedResult[0] - }; - } - } + paramCandidTypes, + returnCandidType, + body, + test }; }); runPropTests(OptTestArb); + +function isParamOpt(paramName: string): string { + return `(${paramName}.Some !== undefined || ${paramName}.None !== undefined)`; +} + +function generateBody( + paramNames: string[], + paramOpts: CandidMeta[], + returnOpt: CandidMeta +): string { + const areParamsOpts = paramNames + .map((paramName) => { + return `if (!${isParamOpt( + paramName + )}) throw new Error('${paramName} must be an Opt');`; + }) + .join('\n'); + + const paramLiterals = paramOpts.map((opt) => opt.src.valueLiteral); + + const areParamsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (!${createAreOptsEqualCodeUsage( + paramName, + paramLiterals[index] + )}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + const returnStatement = paramNames[0] ?? returnOpt.src.valueLiteral; + + return ` + ${areParamsOpts} + ${createAreOptsEqualCodeDeclaration()} + ${areParamsCorrectlyOrdered} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramOpts: CandidMeta[], + returnOpt: CandidMeta +): Test { + const expectedResult = + paramOpts.length === 0 ? returnOpt.value : paramOpts[0].value; + return { + name: `opt ${functionName}`, + test: async () => { + const actor = getActor('./tests/opt/test'); + + const params = paramOpts.map((opt) => opt.value); + + const result = await actor[functionName](...params); + + const equals = + paramOpts.length > 0 ? paramOpts[0].equals : returnOpt.equals; + + return { + Ok: equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/principal/test/test.ts b/property_tests/tests/principal/test/test.ts index a4119a411f..e5349d8a92 100644 --- a/property_tests/tests/principal/test/test.ts +++ b/property_tests/tests/principal/test/test.ts @@ -1,66 +1,120 @@ import fc from 'fast-check'; -import { getActor } from '../../../get_actor'; +import { deepEqual, shallowEqual } from 'fast-equals'; + +import { arePrincipalsEqual } from '../../../are_equal/principal'; import { PrincipalArb } from '../../../arbitraries/candid/reference/principal_arb'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; -import { arePrincipalsEqual } from '../../../are_equal'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { Principal } from '@dfinity/principal'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const PrincipalTestArb = fc .tuple( createUniquePrimitiveArb(JsFunctionNameArb), - fc.array(PrincipalArb, { minLength: 1 }) + fc.array(PrincipalArb), + PrincipalArb ) - .map(([functionName, principals]) => { - const paramCandidTypes = principals.map(() => 'Principal').join(', '); - const returnCandidType = 'Principal'; - const paramNames = principals.map((_, index) => `param${index}`); - - const paramsArePrincipals = paramNames - .map((paramName) => { - return `if (${paramName}._isPrincipal !== true) throw new Error('${paramName} must be a Principal');`; - }) - .join('\n'); + .map( + ([ + functionName, + paramPrincipals, + defaultReturnPrincipal + ]): TestSample => { + const imports = defaultReturnPrincipal.src.imports; - const returnStatement = `param0`; + const paramNames = paramPrincipals.map( + (_, index) => `param${index}` + ); + const paramCandidTypes = paramPrincipals + .map((principal) => principal.src.candidType) + .join(', '); - const expectedResult = principals[0].toText(); + const returnCandidType = defaultReturnPrincipal.src.candidType; - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - const areEqual = arePrincipalsEqual( - paramName, - principals[index] - ); + const body = generateBody( + paramNames, + paramPrincipals, + defaultReturnPrincipal + ); - return `if (!${areEqual}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const test = generateTest( + functionName, + paramPrincipals, + defaultReturnPrincipal + ); - return { - functionName, - imports: ['Principal'], - paramCandidTypes, - returnCandidType, - paramNames, - principals, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsArePrincipals} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/principal/test'); - const result = await actor[functionName](...principals); - - return { Ok: result.toText() === expectedResult }; - } - } - }; - }); + return { + imports, + functionName, + paramNames, + paramCandidTypes, + returnCandidType, + body, + test + }; + } + ); runPropTests(PrincipalTestArb); + +function generateBody( + paramNames: string[], + paramPrincipals: CandidMeta[], + returnPrincipal: CandidMeta +): string { + const paramsArePrincipals = paramNames + .map((paramName) => { + return `if (${paramName}._isPrincipal !== true) throw new Error('${paramName} must be a Principal');`; + }) + .join('\n'); + + const returnStatement = + paramPrincipals.length > 0 + ? `param0` + : returnPrincipal.src.valueLiteral; + + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + const areEqual = arePrincipalsEqual( + paramName, + paramPrincipals[index].src.valueLiteral + ); + + return `if (!${areEqual}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsArePrincipals} + + ${paramsCorrectlyOrdered} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramPrincipals: CandidMeta[], + returnPrincipal: CandidMeta +): Test { + const expectedResult = + paramPrincipals.length > 0 + ? paramPrincipals[0].value + : returnPrincipal.value; + + return { + name: `principal ${functionName}`, + test: async () => { + const actor = getActor('./tests/principal/test'); + const result = await actor[functionName]( + ...paramPrincipals.map((sample) => sample.value) + ); + + return { Ok: returnPrincipal.equals(result, expectedResult) }; + } + }; +} diff --git a/property_tests/tests/query_methods/test/test.ts b/property_tests/tests/query_methods/test/test.ts index 774049202f..e28dec58eb 100644 --- a/property_tests/tests/query_methods/test/test.ts +++ b/property_tests/tests/query_methods/test/test.ts @@ -1,8 +1,9 @@ +import { execSync } from 'child_process'; import fc from 'fast-check'; +import { writeFileSync } from 'fs'; + import { getActor } from '../../../get_actor'; import { Test, getCanisterId, runTests } from 'azle/test'; -import { writeFileSync } from 'fs'; -import { execSync } from 'child_process'; // TODO Canister // TODO Record diff --git a/property_tests/tests/record/dfx.json b/property_tests/tests/record/dfx.json new file mode 100644 index 0000000000..6ab9fbd7e4 --- /dev/null +++ b/property_tests/tests/record/dfx.json @@ -0,0 +1,16 @@ +{ + "canisters": { + "canister": { + "type": "custom", + "main": "src/index.ts", + "candid": "src/index.did", + "build": "npx azle canister", + "wasm": ".azle/canister/canister.wasm", + "gzip": true, + "declarations": { + "output": "test/dfx_generated/canister", + "node_compatibility": true + } + } + } +} diff --git a/property_tests/tests/record/package-lock.json b/property_tests/tests/record/package-lock.json new file mode 100644 index 0000000000..59d1aae0b8 --- /dev/null +++ b/property_tests/tests/record/package-lock.json @@ -0,0 +1,1174 @@ +{ + "name": "record", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "azle": "^0.18.5" + }, + "devDependencies": { + "@dfinity/agent": "^0.19.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } + }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@dfinity/agent": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-0.19.3.tgz", + "integrity": "sha512-q410aNLoOA1ZkwdAMgSo6t++pjISn9TfSybRXhPRI5Ume7eG6+6qYr/rlvcXy7Nb2+Ar7LTsHNn34IULfjni7w==", + "dev": true, + "dependencies": { + "@noble/hashes": "^1.3.1", + "base64-arraybuffer": "^0.2.0", + "borc": "^2.1.1", + "simple-cbor": "^0.4.1" + }, + "peerDependencies": { + "@dfinity/candid": "^0.19.3", + "@dfinity/principal": "^0.19.3" + } + }, + "node_modules/@dfinity/candid": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-0.19.3.tgz", + "integrity": "sha512-yXfbLSWTeRd4G0bLLxYoDqpXH3Jim0P+1PPZOoktXNC1X1hB+ea3yrZebX75t4GVoQK7123F7mxWHiPjuV2tQQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "@dfinity/principal": "^0.19.3" + } + }, + "node_modules/@dfinity/principal": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-0.19.3.tgz", + "integrity": "sha512-+nixVvdGt7ECxRvLXDXsvU9q9sSPssBtDQ4bXa149SK6gcYcmZ6lfWIi3DJNqj3tGROxILVBsguel9tECappsA==", + "dependencies": { + "@noble/hashes": "^1.3.1" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", + "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", + "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", + "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", + "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", + "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", + "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", + "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", + "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", + "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", + "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", + "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", + "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", + "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", + "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", + "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", + "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", + "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", + "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", + "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", + "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", + "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", + "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@swc/core": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.93.tgz", + "integrity": "sha512-690GRr1wUGmGYZHk7fUduX/JUwViMF2o74mnZYIWEcJaCcd9MQfkhsxPBtjeg6tF+h266/Cf3RPYhsFBzzxXcA==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.1", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.3.93", + "@swc/core-darwin-x64": "1.3.93", + "@swc/core-linux-arm-gnueabihf": "1.3.93", + "@swc/core-linux-arm64-gnu": "1.3.93", + "@swc/core-linux-arm64-musl": "1.3.93", + "@swc/core-linux-x64-gnu": "1.3.93", + "@swc/core-linux-x64-musl": "1.3.93", + "@swc/core-win32-arm64-msvc": "1.3.93", + "@swc/core-win32-ia32-msvc": "1.3.93", + "@swc/core-win32-x64-msvc": "1.3.93" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.93.tgz", + "integrity": "sha512-gEKgk7FVIgltnIfDO6GntyuQBBlAYg5imHpRgLxB1zSI27ijVVkksc6QwISzFZAhKYaBWIsFSVeL9AYSziAF7A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.93.tgz", + "integrity": "sha512-ZQPxm/fXdDQtn3yrYSL/gFfA8OfZ5jTi33yFQq6vcg/Y8talpZ+MgdSlYM0FkLrZdMTYYTNFiuBQuuvkA+av+Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.93.tgz", + "integrity": "sha512-OYFMMI2yV+aNe3wMgYhODxHdqUB/jrK0SEMHHS44GZpk8MuBXEF+Mcz4qjkY5Q1EH7KVQqXb/gVWwdgTHpjM2A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.93.tgz", + "integrity": "sha512-BT4dT78odKnJMNiq5HdjBsv29CiIdcCcImAPxeFqAeFw1LL6gh9nzI8E96oWc+0lVT5lfhoesCk4Qm7J6bty8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.93.tgz", + "integrity": "sha512-yH5fWEl1bktouC0mhh0Chuxp7HEO4uCtS/ly1Vmf18gs6wZ8DOOkgAEVv2dNKIryy+Na++ljx4Ym7C8tSJTrLw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.93.tgz", + "integrity": "sha512-OFUdx64qvrGJhXKEyxosHxgoUVgba2ztYh7BnMiU5hP8lbI8G13W40J0SN3CmFQwPP30+3oEbW7LWzhKEaYjlg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.93.tgz", + "integrity": "sha512-4B8lSRwEq1XYm6xhxHhvHmKAS7pUp1Q7E33NQ2TlmFhfKvCOh86qvThcjAOo57x8DRwmpvEVrqvpXtYagMN6Ig==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.93.tgz", + "integrity": "sha512-BHShlxtkven8ZjjvZ5QR6sC5fZCJ9bMujEkiha6W4cBUTY7ce7qGFyHmQd+iPC85d9kD/0cCiX/Xez8u0BhO7w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.93.tgz", + "integrity": "sha512-nEwNWnz4JzYAK6asVvb92yeylfxMYih7eMQOnT7ZVlZN5ba9WF29xJ6kcQKs9HRH6MvWhz9+wRgv3FcjlU6HYA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.93.tgz", + "integrity": "sha512-jibQ0zUr4kwJaQVwgmH+svS04bYTPnPw/ZkNInzxS+wFAtzINBYcU8s2PMWbDb2NGYiRSEeoSGyAvS9H+24JFA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", + "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==" + }, + "node_modules/@swc/types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, + "node_modules/@types/node": { + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "peer": true, + "dependencies": { + "undici-types": "~5.25.1" + } + }, + "node_modules/@types/uuid": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", + "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==" + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/azle": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/azle/-/azle-0.18.5.tgz", + "integrity": "sha512-9lLhVKwexVCd8OOYMXgjk06L+Mu0q29Rpchmz07HYV6idwF5kg+8QCxzytpU9GpnUeoADTQNkEkyLABtkd2hCA==", + "dependencies": { + "@dfinity/candid": "github:demergent-labs/candid#minimum_viable", + "@dfinity/principal": "^0.19.0", + "@swc/core": "^1.3.86", + "@types/uuid": "^9.0.4", + "buffer": "^6.0.3", + "esbuild": "^0.19.3", + "fs-extra": "10.0.1", + "js-sha256": "0.9.0", + "text-encoding": "0.7.0", + "ts-node": "10.3.1", + "typescript": "^5.2.2", + "uuid": "^9.0.1" + }, + "bin": { + "azle": "bin.js" + } + }, + "node_modules/azle/node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/azle/node_modules/@dfinity/candid": { + "version": "0.19.2", + "resolved": "git+ssh://git@github.com/demergent-labs/candid.git#5797fa906b1a7cc30c161dbb0eb919283ce2f80d", + "license": "Apache-2.0", + "peerDependencies": { + "@dfinity/principal": "^0.19.2" + } + }, + "node_modules/azle/node_modules/ts-node": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.1.tgz", + "integrity": "sha512-Yw3W2mYzhHfCHOICGNJqa0i+rbL0rAyg7ZIHxU+K4pgY8gd2Lh1j+XbHCusJMykbj6RZMJVOY0MlHVd+GOivcw==", + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/base64-arraybuffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", + "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/borc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", + "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", + "dev": true, + "dependencies": { + "bignumber.js": "^9.0.0", + "buffer": "^5.5.0", + "commander": "^2.15.0", + "ieee754": "^1.1.13", + "iso-url": "~0.4.7", + "json-text-sequence": "~0.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/borc/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/delimit-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", + "integrity": "sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/esbuild": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", + "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.5", + "@esbuild/android-arm64": "0.19.5", + "@esbuild/android-x64": "0.19.5", + "@esbuild/darwin-arm64": "0.19.5", + "@esbuild/darwin-x64": "0.19.5", + "@esbuild/freebsd-arm64": "0.19.5", + "@esbuild/freebsd-x64": "0.19.5", + "@esbuild/linux-arm": "0.19.5", + "@esbuild/linux-arm64": "0.19.5", + "@esbuild/linux-ia32": "0.19.5", + "@esbuild/linux-loong64": "0.19.5", + "@esbuild/linux-mips64el": "0.19.5", + "@esbuild/linux-ppc64": "0.19.5", + "@esbuild/linux-riscv64": "0.19.5", + "@esbuild/linux-s390x": "0.19.5", + "@esbuild/linux-x64": "0.19.5", + "@esbuild/netbsd-x64": "0.19.5", + "@esbuild/openbsd-x64": "0.19.5", + "@esbuild/sunos-x64": "0.19.5", + "@esbuild/win32-arm64": "0.19.5", + "@esbuild/win32-ia32": "0.19.5", + "@esbuild/win32-x64": "0.19.5" + } + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/iso-url": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", + "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "node_modules/json-text-sequence": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz", + "integrity": "sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w==", + "dev": true, + "dependencies": { + "delimit-stream": "0.1.0" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-cbor": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/simple-cbor/-/simple-cbor-0.4.1.tgz", + "integrity": "sha512-rijcxtwx2b4Bje3sqeIqw5EeW7UlOIC4YfOdwqIKacpvRQ/D78bWg/4/0m5e0U91oKvlGh7LlJuZCu07ISCC7w==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", + "deprecated": "no longer maintained" + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/property_tests/tests/record/package.json b/property_tests/tests/record/package.json new file mode 100644 index 0000000000..fd5d123560 --- /dev/null +++ b/property_tests/tests/record/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "test": "ts-node --transpile-only --ignore=false test/test.ts" + }, + "dependencies": { + "azle": "^0.18.5" + }, + "devDependencies": { + "@dfinity/agent": "^0.19.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } +} diff --git a/property_tests/tests/record/test/test.ts b/property_tests/tests/record/test/test.ts new file mode 100644 index 0000000000..30d5d04442 --- /dev/null +++ b/property_tests/tests/record/test/test.ts @@ -0,0 +1,177 @@ +import fc from 'fast-check'; + +import { + RecordArb, + Record +} from '../../../arbitraries/candid/constructed/record_arb'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { UniqueIdentifierArb } from '../../../arbitraries/unique_identifier_arb'; +import { getActor, runPropTests } from '../../..'; +import { AzleResult, Test } from '../../../../test'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; + +const RecordTestArb = fc + .tuple( + UniqueIdentifierArb('canisterMethod'), + fc.uniqueArray(RecordArb, { + selector: (entry) => entry.src.candidType + }), + RecordArb + ) + .map(([functionName, paramRecords, defaultReturnRecord]): TestSample => { + const imports = new Set([ + ...paramRecords.flatMap((record) => [...record.src.imports]), + ...defaultReturnRecord.src.imports + ]); + + const candidTypeDeclarations = [ + ...paramRecords.map((record) => record.src.typeDeclaration ?? ''), + defaultReturnRecord.src.typeDeclaration ?? '' + ]; + + const paramNames = paramRecords.map((_, index) => `param${index}`); + + const paramCandidTypes = paramRecords + .map((record) => record.src.candidType) + .join(', '); + + const returnRecord = + paramRecords.length === 0 ? defaultReturnRecord : paramRecords[0]; + const returnCandidType = returnRecord.src.candidType; + + const body = generateBody(paramRecords, returnRecord); + + const test = generateTest(functionName, paramRecords, returnRecord); + + return { + imports, + candidTypeDeclarations, + functionName, + paramNames, + paramCandidTypes, + returnCandidType, + body, + test + }; + }); + +runPropTests(RecordTestArb); + +function generateBody( + paramRecords: CandidMeta[], + returnRecord: CandidMeta +): string { + const paramsAreRecords = paramRecords + .map((record, index) => { + const paramName = `param${index}`; + const fieldsCount = Object.keys(record.value).length; + + const paramIsObject = `typeof ${paramName} === 'object'`; + const paramHasCorrectNumberOfFields = `Object.keys(${paramName}).length === ${fieldsCount}`; + const throwError = `throw new Error('${paramName} must be a Record');`; + + return `if (!(${paramIsObject} && ${paramHasCorrectNumberOfFields})) ${throwError}`; + }) + .join('\n'); + + const paramsCorrectlyOrdered = paramRecords + .map((record, index) => { + const paramName = `param${index}`; + + const fieldNamesMatch = Object.entries(record.value) + .map(([fieldName, _]) => { + return `Object.keys(${paramName}).includes('${fieldName}')`; + }) + .join(' && '); + + const throwError = `throw new Error('${paramName} is incorrectly ordered')`; + + if (Object.entries(record.value).length === 0) { + return `if (Object.keys(${paramName}).length !== 0) ${throwError}`; + } + + return `if (!(${fieldNamesMatch})) ${throwError}`; + }) + .join('\n'); + + const returnStatement = + paramRecords.length === 0 ? returnRecord.src.valueLiteral : `param0`; + + return ` + ${paramsAreRecords} + + ${paramsCorrectlyOrdered} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramRecords: CandidMeta[], + returnRecord: CandidMeta +): Test { + return { + name: `record ${functionName}`, + test: async () => { + const actor = getActor('./tests/record/test'); + + const result = await actor[functionName]( + ...paramRecords.map((record) => record.value) + ); + + // Start by using the equals method defined by the return arbitrary + // This method works in all cases and if it should return true it + // will. It's weakness is that we don't always know why it returns + // false, so if that equals method returns false, then instead of + // just returning {Ok: false} we will use the equals function that + // has better reporting of why the test failed but isn't as robust + if (returnRecord.equals(result, returnRecord.value)) { + return { Ok: true }; + } + return recordsAreEqual(result, returnRecord.value); + } + }; +} + +function recordsAreEqual( + result: Record, + expectedResult: Record +): AzleResult { + if (typeof result !== 'object') { + return { Err: 'Result is not an object' }; + } + + if (typeof expectedResult !== 'object') { + return { Err: 'Expected Result is not an object' }; + } + + const resultKeys = Object.keys(result); + const resultEntries = Object.entries(result); + const expectedResultEntries = Object.entries(expectedResult); + + if (resultEntries.length !== expectedResultEntries.length) { + return { + Err: `The entries of result and expectedResult differ in length: ${resultEntries.length} & ${expectedResultEntries.length} respectively` + }; + } + + for (let i = 0; i < expectedResultEntries.length; i++) { + const [expectedResultKey, expectedResultValue] = + expectedResultEntries[i]; + + if (!resultKeys.includes(expectedResultKey)) { + return { + Err: `Result is missing key "${expectedResultKey}"` + }; + } + + if (result[expectedResultKey] !== expectedResultValue) { + return { + Err: `Expected result.${expectedResultKey} to be ${expectedResultValue} but got ${result[expectedResultKey]} instead` + }; + } + } + + return { Ok: true }; +} diff --git a/property_tests/tests/record/tsconfig.json b/property_tests/tests/record/tsconfig.json new file mode 100644 index 0000000000..2638f0d8bc --- /dev/null +++ b/property_tests/tests/record/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ES2020", + "moduleResolution": "node", + "allowJs": true, + "outDir": "HACK_BECAUSE_OF_ALLOW_JS" + } +} diff --git a/property_tests/tests/text/test/test.ts b/property_tests/tests/text/test/test.ts index 08dca6ef1a..291a16f7d7 100644 --- a/property_tests/tests/text/test/test.ts +++ b/property_tests/tests/text/test/test.ts @@ -1,72 +1,99 @@ import fc from 'fast-check'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; -import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; + import { TextArb } from '../../../arbitraries/candid/primitive/text'; +import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const TextTestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(TextArb)) - .map(([functionName, texts]) => { - const paramCandidTypes = texts.map(() => 'text').join(', '); - const returnCandidType = 'text'; - const paramNames = texts.map((_, index) => `param${index}`); - - const paramsAreStrings = paramNames - .map((paramName) => { - return `if (typeof ${paramName} !== 'string') throw new Error('${paramName} must be a string');`; - }) - .join('\n'); - - const returnStatement = paramNames.reduce((acc, paramName) => { - return `${acc} + ${paramName}`; - }, '""'); - - const expectedResult = texts.reduce((acc, text) => acc + text, ''); - const paramSamples = texts; - - function escapeStringForJavaScript(input: string) { - return input - .replace(/\\/g, '\\\\') // Escape backslashes - .replace(/'/g, "\\'") // Escape single quotes - .replace(/"/g, '\\"'); // Escape double quotes - } + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(TextArb), + TextArb + ) + .map(([functionName, paramTexts, defaultReturnText]): TestSample => { + const imports = defaultReturnText.src.imports; - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName} !== '${escapeStringForJavaScript( - paramSamples[index] - )}') throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); + const paramNames = paramTexts.map((_, index) => `param${index}`); + const paramCandidTypes = paramTexts + .map((text) => text.src.candidType) + .join(', '); + + const returnCandidType = defaultReturnText.src.candidType; + + const body = generateBody(paramNames, paramTexts, defaultReturnText); + + const test = generateTest(functionName, paramTexts, defaultReturnText); return { + imports, functionName, - imports: ['text'], + paramNames, paramCandidTypes, returnCandidType, - paramNames, - paramSamples, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreStrings} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/text/test'); - - const result = await actor[functionName](...texts); - - return { - Ok: result === expectedResult - }; - } - } + body, + test }; }); runPropTests(TextTestArb); + +function generateBody( + paramNames: string[], + paramTexts: CandidMeta[], + returnText: CandidMeta +): string { + const paramsAreStrings = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'string') throw new Error('${paramName} must be a string');`; + }) + .join('\n'); + + const returnStatement = paramNames.reduce((acc, paramName) => { + return `${acc} + ${paramName}`; + }, returnText.src.valueLiteral); + + const paramValues = paramTexts.map((text) => text.src.valueLiteral); + + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName} !== ${paramValues[index]}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + return ` + ${paramsAreStrings} + + ${paramsCorrectlyOrdered} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramTexts: CandidMeta[], + returnTexts: CandidMeta +): Test { + const expectedResult = paramTexts.reduce( + (acc, text) => acc + text.value, + returnTexts.value + ); + const paramValues = paramTexts.map((text) => text.value); + + return { + name: `text ${functionName}`, + test: async () => { + const actor = getActor('./tests/text/test'); + + const result = await actor[functionName](...paramValues); + + return { + Ok: returnTexts.equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/tuple/dfx.json b/property_tests/tests/tuple/dfx.json new file mode 100644 index 0000000000..6ab9fbd7e4 --- /dev/null +++ b/property_tests/tests/tuple/dfx.json @@ -0,0 +1,16 @@ +{ + "canisters": { + "canister": { + "type": "custom", + "main": "src/index.ts", + "candid": "src/index.did", + "build": "npx azle canister", + "wasm": ".azle/canister/canister.wasm", + "gzip": true, + "declarations": { + "output": "test/dfx_generated/canister", + "node_compatibility": true + } + } + } +} diff --git a/property_tests/tests/tuple/package-lock.json b/property_tests/tests/tuple/package-lock.json new file mode 100644 index 0000000000..2972b1444e --- /dev/null +++ b/property_tests/tests/tuple/package-lock.json @@ -0,0 +1,1174 @@ +{ + "name": "tuple", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "azle": "^0.18.5" + }, + "devDependencies": { + "@dfinity/agent": "^0.19.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } + }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@dfinity/agent": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-0.19.3.tgz", + "integrity": "sha512-q410aNLoOA1ZkwdAMgSo6t++pjISn9TfSybRXhPRI5Ume7eG6+6qYr/rlvcXy7Nb2+Ar7LTsHNn34IULfjni7w==", + "dev": true, + "dependencies": { + "@noble/hashes": "^1.3.1", + "base64-arraybuffer": "^0.2.0", + "borc": "^2.1.1", + "simple-cbor": "^0.4.1" + }, + "peerDependencies": { + "@dfinity/candid": "^0.19.3", + "@dfinity/principal": "^0.19.3" + } + }, + "node_modules/@dfinity/candid": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-0.19.3.tgz", + "integrity": "sha512-yXfbLSWTeRd4G0bLLxYoDqpXH3Jim0P+1PPZOoktXNC1X1hB+ea3yrZebX75t4GVoQK7123F7mxWHiPjuV2tQQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "@dfinity/principal": "^0.19.3" + } + }, + "node_modules/@dfinity/principal": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-0.19.3.tgz", + "integrity": "sha512-+nixVvdGt7ECxRvLXDXsvU9q9sSPssBtDQ4bXa149SK6gcYcmZ6lfWIi3DJNqj3tGROxILVBsguel9tECappsA==", + "dependencies": { + "@noble/hashes": "^1.3.1" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", + "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", + "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", + "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", + "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", + "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", + "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", + "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", + "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", + "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", + "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", + "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", + "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", + "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", + "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", + "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", + "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", + "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", + "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", + "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", + "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", + "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", + "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@swc/core": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.93.tgz", + "integrity": "sha512-690GRr1wUGmGYZHk7fUduX/JUwViMF2o74mnZYIWEcJaCcd9MQfkhsxPBtjeg6tF+h266/Cf3RPYhsFBzzxXcA==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.1", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.3.93", + "@swc/core-darwin-x64": "1.3.93", + "@swc/core-linux-arm-gnueabihf": "1.3.93", + "@swc/core-linux-arm64-gnu": "1.3.93", + "@swc/core-linux-arm64-musl": "1.3.93", + "@swc/core-linux-x64-gnu": "1.3.93", + "@swc/core-linux-x64-musl": "1.3.93", + "@swc/core-win32-arm64-msvc": "1.3.93", + "@swc/core-win32-ia32-msvc": "1.3.93", + "@swc/core-win32-x64-msvc": "1.3.93" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.93.tgz", + "integrity": "sha512-gEKgk7FVIgltnIfDO6GntyuQBBlAYg5imHpRgLxB1zSI27ijVVkksc6QwISzFZAhKYaBWIsFSVeL9AYSziAF7A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.93.tgz", + "integrity": "sha512-ZQPxm/fXdDQtn3yrYSL/gFfA8OfZ5jTi33yFQq6vcg/Y8talpZ+MgdSlYM0FkLrZdMTYYTNFiuBQuuvkA+av+Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.93.tgz", + "integrity": "sha512-OYFMMI2yV+aNe3wMgYhODxHdqUB/jrK0SEMHHS44GZpk8MuBXEF+Mcz4qjkY5Q1EH7KVQqXb/gVWwdgTHpjM2A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.93.tgz", + "integrity": "sha512-BT4dT78odKnJMNiq5HdjBsv29CiIdcCcImAPxeFqAeFw1LL6gh9nzI8E96oWc+0lVT5lfhoesCk4Qm7J6bty8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.93.tgz", + "integrity": "sha512-yH5fWEl1bktouC0mhh0Chuxp7HEO4uCtS/ly1Vmf18gs6wZ8DOOkgAEVv2dNKIryy+Na++ljx4Ym7C8tSJTrLw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.93.tgz", + "integrity": "sha512-OFUdx64qvrGJhXKEyxosHxgoUVgba2ztYh7BnMiU5hP8lbI8G13W40J0SN3CmFQwPP30+3oEbW7LWzhKEaYjlg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.93.tgz", + "integrity": "sha512-4B8lSRwEq1XYm6xhxHhvHmKAS7pUp1Q7E33NQ2TlmFhfKvCOh86qvThcjAOo57x8DRwmpvEVrqvpXtYagMN6Ig==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.93.tgz", + "integrity": "sha512-BHShlxtkven8ZjjvZ5QR6sC5fZCJ9bMujEkiha6W4cBUTY7ce7qGFyHmQd+iPC85d9kD/0cCiX/Xez8u0BhO7w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.93.tgz", + "integrity": "sha512-nEwNWnz4JzYAK6asVvb92yeylfxMYih7eMQOnT7ZVlZN5ba9WF29xJ6kcQKs9HRH6MvWhz9+wRgv3FcjlU6HYA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.93.tgz", + "integrity": "sha512-jibQ0zUr4kwJaQVwgmH+svS04bYTPnPw/ZkNInzxS+wFAtzINBYcU8s2PMWbDb2NGYiRSEeoSGyAvS9H+24JFA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", + "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==" + }, + "node_modules/@swc/types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, + "node_modules/@types/node": { + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "peer": true, + "dependencies": { + "undici-types": "~5.25.1" + } + }, + "node_modules/@types/uuid": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", + "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==" + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/azle": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/azle/-/azle-0.18.5.tgz", + "integrity": "sha512-9lLhVKwexVCd8OOYMXgjk06L+Mu0q29Rpchmz07HYV6idwF5kg+8QCxzytpU9GpnUeoADTQNkEkyLABtkd2hCA==", + "dependencies": { + "@dfinity/candid": "github:demergent-labs/candid#minimum_viable", + "@dfinity/principal": "^0.19.0", + "@swc/core": "^1.3.86", + "@types/uuid": "^9.0.4", + "buffer": "^6.0.3", + "esbuild": "^0.19.3", + "fs-extra": "10.0.1", + "js-sha256": "0.9.0", + "text-encoding": "0.7.0", + "ts-node": "10.3.1", + "typescript": "^5.2.2", + "uuid": "^9.0.1" + }, + "bin": { + "azle": "bin.js" + } + }, + "node_modules/azle/node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/azle/node_modules/@dfinity/candid": { + "version": "0.19.2", + "resolved": "git+ssh://git@github.com/demergent-labs/candid.git#5797fa906b1a7cc30c161dbb0eb919283ce2f80d", + "license": "Apache-2.0", + "peerDependencies": { + "@dfinity/principal": "^0.19.2" + } + }, + "node_modules/azle/node_modules/ts-node": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.1.tgz", + "integrity": "sha512-Yw3W2mYzhHfCHOICGNJqa0i+rbL0rAyg7ZIHxU+K4pgY8gd2Lh1j+XbHCusJMykbj6RZMJVOY0MlHVd+GOivcw==", + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/base64-arraybuffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", + "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/borc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", + "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", + "dev": true, + "dependencies": { + "bignumber.js": "^9.0.0", + "buffer": "^5.5.0", + "commander": "^2.15.0", + "ieee754": "^1.1.13", + "iso-url": "~0.4.7", + "json-text-sequence": "~0.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/borc/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/delimit-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", + "integrity": "sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/esbuild": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", + "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.5", + "@esbuild/android-arm64": "0.19.5", + "@esbuild/android-x64": "0.19.5", + "@esbuild/darwin-arm64": "0.19.5", + "@esbuild/darwin-x64": "0.19.5", + "@esbuild/freebsd-arm64": "0.19.5", + "@esbuild/freebsd-x64": "0.19.5", + "@esbuild/linux-arm": "0.19.5", + "@esbuild/linux-arm64": "0.19.5", + "@esbuild/linux-ia32": "0.19.5", + "@esbuild/linux-loong64": "0.19.5", + "@esbuild/linux-mips64el": "0.19.5", + "@esbuild/linux-ppc64": "0.19.5", + "@esbuild/linux-riscv64": "0.19.5", + "@esbuild/linux-s390x": "0.19.5", + "@esbuild/linux-x64": "0.19.5", + "@esbuild/netbsd-x64": "0.19.5", + "@esbuild/openbsd-x64": "0.19.5", + "@esbuild/sunos-x64": "0.19.5", + "@esbuild/win32-arm64": "0.19.5", + "@esbuild/win32-ia32": "0.19.5", + "@esbuild/win32-x64": "0.19.5" + } + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/iso-url": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", + "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "node_modules/json-text-sequence": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz", + "integrity": "sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w==", + "dev": true, + "dependencies": { + "delimit-stream": "0.1.0" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-cbor": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/simple-cbor/-/simple-cbor-0.4.1.tgz", + "integrity": "sha512-rijcxtwx2b4Bje3sqeIqw5EeW7UlOIC4YfOdwqIKacpvRQ/D78bWg/4/0m5e0U91oKvlGh7LlJuZCu07ISCC7w==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", + "deprecated": "no longer maintained" + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/property_tests/tests/tuple/package.json b/property_tests/tests/tuple/package.json new file mode 100644 index 0000000000..fd5d123560 --- /dev/null +++ b/property_tests/tests/tuple/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "test": "ts-node --transpile-only --ignore=false test/test.ts" + }, + "dependencies": { + "azle": "^0.18.5" + }, + "devDependencies": { + "@dfinity/agent": "^0.19.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } +} diff --git a/property_tests/tests/tuple/test/test.ts b/property_tests/tests/tuple/test/test.ts new file mode 100644 index 0000000000..b869abf765 --- /dev/null +++ b/property_tests/tests/tuple/test/test.ts @@ -0,0 +1,165 @@ +import fc from 'fast-check'; + +import { + TupleArb, + Tuple +} from '../../../arbitraries/candid/constructed/tuple_arb'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { UniqueIdentifierArb } from '../../../arbitraries/unique_identifier_arb'; +import { getActor, runPropTests } from '../../..'; +import { AzleResult, Test } from '../../../../test'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; + +const TupleTestArb = fc + .tuple( + UniqueIdentifierArb('canisterMethod'), + fc.uniqueArray(TupleArb, { + selector: (entry) => entry.src.candidType + }), + TupleArb + ) + .map(([functionName, paramTuples, defaultReturnTuple]): TestSample => { + const imports = new Set([ + ...paramTuples.flatMap((tuple) => [...tuple.src.imports]), + ...defaultReturnTuple.src.imports + ]); + + const candidTypeDeclarations = [ + ...paramTuples.map((tuple) => tuple.src.typeDeclaration ?? ''), + defaultReturnTuple.src.typeDeclaration ?? '' + ]; + + const paramNames = paramTuples.map((_, index) => `param${index}`); + + const paramCandidTypes = paramTuples + .map((tuple) => tuple.src.candidType) + .join(', '); + + const returnTuple = + paramTuples.length === 0 ? defaultReturnTuple : paramTuples[0]; + const returnCandidType = returnTuple.src.candidType; + + const body = generateBody(paramTuples, returnTuple); + + const test = generateTest(functionName, paramTuples, returnTuple); + + return { + functionName, + imports, + candidTypeDeclarations, + paramNames, + paramCandidTypes, + returnCandidType, + body, + test + }; + }); + +runPropTests(TupleTestArb); + +function generateBody( + paramTuples: CandidMeta[], + returnTuple: CandidMeta +): string { + const paramsAreTuples = paramTuples + .map((tuple, index) => { + const paramName = `param${index}`; + const fieldsCount = tuple.value.length; + + const paramIsArray = `Array.isArray(${paramName})`; + const paramHasCorrectNumberOfFields = `${paramName}.length === ${fieldsCount}`; + const throwError = `throw new Error('${paramName} must be a Tuple');`; + + return `if (!(${paramIsArray} && ${paramHasCorrectNumberOfFields})) ${throwError}`; + }) + .join('\n'); + + const paramsCorrectlyOrdered = paramTuples + .map((tuple, paramIndex): string => { + const paramName = `param${paramIndex}`; + + const paramIsCorrectValue = `${paramName}.toString() === ${tuple.src.valueLiteral}.toString()`; + + const throwError = `throw new Error('${paramName} is incorrectly ordered.')`; + + return `if (!(${paramIsCorrectValue})) ${throwError}`; + }) + .join('\n'); + + const returnStatement = + paramTuples.length === 0 ? returnTuple.src.valueLiteral : `param0`; + + return ` + ${paramsAreTuples} + + ${paramsCorrectlyOrdered} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramTuples: CandidMeta[], + returnTuple: CandidMeta +): Test { + const expectedResult = returnTuple.value; + + return { + name: `tuple ${functionName}`, + test: async () => { + const actor = getActor('./tests/tuple/test'); + + const result = await actor[functionName]( + ...paramTuples.map((tuple) => tuple.value) + ); + + // Start by using the equals method defined by the return arbitrary + // This method works in all cases and if it should return true it + // will. It's weakness is that we don't always know why it returns + // false, so if that equals method returns false, then instead of + // just returning {Ok: false} we will use the equals function that + // has better reporting of why the test failed but isn't as robust + if (returnTuple.equals(result, expectedResult)) { + return { Ok: true }; + } + + return tuplesAreEqual(result, expectedResult); + } + }; +} + +function tuplesAreEqual( + result: Tuple, + expectedResult: Tuple +): AzleResult { + if (typeof result !== 'object') { + return { Err: 'Result is not an object' }; + } + + if (typeof expectedResult !== 'object') { + return { Err: 'Expected result is not an object' }; + } + + const resultFieldsCount = Object.entries(result).length; + const expectedResultFieldsCount = Object.entries(expectedResult).length; + + if (resultFieldsCount !== expectedResultFieldsCount) { + return { + Err: `Result is not of the correct length: expected ${expectedResultFieldsCount}, received ${resultFieldsCount}` + }; + } + + for (let i = 0; i < expectedResultFieldsCount; i++) { + const expectedFieldValue = expectedResult[i]; + const actualFieldValue = result[i]; + + if (actualFieldValue !== expectedFieldValue) { + return { + Err: `Expected result[${i}] to be ${expectedFieldValue} but got ${actualFieldValue} instead` + }; + } + } + + return { Ok: true }; +} diff --git a/property_tests/tests/tuple/tsconfig.json b/property_tests/tests/tuple/tsconfig.json new file mode 100644 index 0000000000..2638f0d8bc --- /dev/null +++ b/property_tests/tests/tuple/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ES2020", + "moduleResolution": "node", + "allowJs": true, + "outDir": "HACK_BECAUSE_OF_ALLOW_JS" + } +} diff --git a/property_tests/tests/variant/dfx.json b/property_tests/tests/variant/dfx.json new file mode 100644 index 0000000000..6ab9fbd7e4 --- /dev/null +++ b/property_tests/tests/variant/dfx.json @@ -0,0 +1,16 @@ +{ + "canisters": { + "canister": { + "type": "custom", + "main": "src/index.ts", + "candid": "src/index.did", + "build": "npx azle canister", + "wasm": ".azle/canister/canister.wasm", + "gzip": true, + "declarations": { + "output": "test/dfx_generated/canister", + "node_compatibility": true + } + } + } +} diff --git a/property_tests/tests/variant/package-lock.json b/property_tests/tests/variant/package-lock.json new file mode 100644 index 0000000000..0467a176f5 --- /dev/null +++ b/property_tests/tests/variant/package-lock.json @@ -0,0 +1,1174 @@ +{ + "name": "variant", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "azle": "^0.18.5" + }, + "devDependencies": { + "@dfinity/agent": "^0.19.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } + }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@dfinity/agent": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-0.19.3.tgz", + "integrity": "sha512-q410aNLoOA1ZkwdAMgSo6t++pjISn9TfSybRXhPRI5Ume7eG6+6qYr/rlvcXy7Nb2+Ar7LTsHNn34IULfjni7w==", + "dev": true, + "dependencies": { + "@noble/hashes": "^1.3.1", + "base64-arraybuffer": "^0.2.0", + "borc": "^2.1.1", + "simple-cbor": "^0.4.1" + }, + "peerDependencies": { + "@dfinity/candid": "^0.19.3", + "@dfinity/principal": "^0.19.3" + } + }, + "node_modules/@dfinity/candid": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-0.19.3.tgz", + "integrity": "sha512-yXfbLSWTeRd4G0bLLxYoDqpXH3Jim0P+1PPZOoktXNC1X1hB+ea3yrZebX75t4GVoQK7123F7mxWHiPjuV2tQQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "@dfinity/principal": "^0.19.3" + } + }, + "node_modules/@dfinity/principal": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-0.19.3.tgz", + "integrity": "sha512-+nixVvdGt7ECxRvLXDXsvU9q9sSPssBtDQ4bXa149SK6gcYcmZ6lfWIi3DJNqj3tGROxILVBsguel9tECappsA==", + "dependencies": { + "@noble/hashes": "^1.3.1" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", + "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", + "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", + "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", + "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", + "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", + "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", + "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", + "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", + "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", + "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", + "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", + "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", + "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", + "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", + "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", + "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", + "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", + "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", + "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", + "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", + "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", + "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@swc/core": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.93.tgz", + "integrity": "sha512-690GRr1wUGmGYZHk7fUduX/JUwViMF2o74mnZYIWEcJaCcd9MQfkhsxPBtjeg6tF+h266/Cf3RPYhsFBzzxXcA==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.1", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.3.93", + "@swc/core-darwin-x64": "1.3.93", + "@swc/core-linux-arm-gnueabihf": "1.3.93", + "@swc/core-linux-arm64-gnu": "1.3.93", + "@swc/core-linux-arm64-musl": "1.3.93", + "@swc/core-linux-x64-gnu": "1.3.93", + "@swc/core-linux-x64-musl": "1.3.93", + "@swc/core-win32-arm64-msvc": "1.3.93", + "@swc/core-win32-ia32-msvc": "1.3.93", + "@swc/core-win32-x64-msvc": "1.3.93" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.93.tgz", + "integrity": "sha512-gEKgk7FVIgltnIfDO6GntyuQBBlAYg5imHpRgLxB1zSI27ijVVkksc6QwISzFZAhKYaBWIsFSVeL9AYSziAF7A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.93.tgz", + "integrity": "sha512-ZQPxm/fXdDQtn3yrYSL/gFfA8OfZ5jTi33yFQq6vcg/Y8talpZ+MgdSlYM0FkLrZdMTYYTNFiuBQuuvkA+av+Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.93.tgz", + "integrity": "sha512-OYFMMI2yV+aNe3wMgYhODxHdqUB/jrK0SEMHHS44GZpk8MuBXEF+Mcz4qjkY5Q1EH7KVQqXb/gVWwdgTHpjM2A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.93.tgz", + "integrity": "sha512-BT4dT78odKnJMNiq5HdjBsv29CiIdcCcImAPxeFqAeFw1LL6gh9nzI8E96oWc+0lVT5lfhoesCk4Qm7J6bty8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.93.tgz", + "integrity": "sha512-yH5fWEl1bktouC0mhh0Chuxp7HEO4uCtS/ly1Vmf18gs6wZ8DOOkgAEVv2dNKIryy+Na++ljx4Ym7C8tSJTrLw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.93.tgz", + "integrity": "sha512-OFUdx64qvrGJhXKEyxosHxgoUVgba2ztYh7BnMiU5hP8lbI8G13W40J0SN3CmFQwPP30+3oEbW7LWzhKEaYjlg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.93.tgz", + "integrity": "sha512-4B8lSRwEq1XYm6xhxHhvHmKAS7pUp1Q7E33NQ2TlmFhfKvCOh86qvThcjAOo57x8DRwmpvEVrqvpXtYagMN6Ig==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.93.tgz", + "integrity": "sha512-BHShlxtkven8ZjjvZ5QR6sC5fZCJ9bMujEkiha6W4cBUTY7ce7qGFyHmQd+iPC85d9kD/0cCiX/Xez8u0BhO7w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.93.tgz", + "integrity": "sha512-nEwNWnz4JzYAK6asVvb92yeylfxMYih7eMQOnT7ZVlZN5ba9WF29xJ6kcQKs9HRH6MvWhz9+wRgv3FcjlU6HYA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.93", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.93.tgz", + "integrity": "sha512-jibQ0zUr4kwJaQVwgmH+svS04bYTPnPw/ZkNInzxS+wFAtzINBYcU8s2PMWbDb2NGYiRSEeoSGyAvS9H+24JFA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", + "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==" + }, + "node_modules/@swc/types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, + "node_modules/@types/node": { + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "peer": true, + "dependencies": { + "undici-types": "~5.25.1" + } + }, + "node_modules/@types/uuid": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", + "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==" + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/azle": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/azle/-/azle-0.18.5.tgz", + "integrity": "sha512-9lLhVKwexVCd8OOYMXgjk06L+Mu0q29Rpchmz07HYV6idwF5kg+8QCxzytpU9GpnUeoADTQNkEkyLABtkd2hCA==", + "dependencies": { + "@dfinity/candid": "github:demergent-labs/candid#minimum_viable", + "@dfinity/principal": "^0.19.0", + "@swc/core": "^1.3.86", + "@types/uuid": "^9.0.4", + "buffer": "^6.0.3", + "esbuild": "^0.19.3", + "fs-extra": "10.0.1", + "js-sha256": "0.9.0", + "text-encoding": "0.7.0", + "ts-node": "10.3.1", + "typescript": "^5.2.2", + "uuid": "^9.0.1" + }, + "bin": { + "azle": "bin.js" + } + }, + "node_modules/azle/node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/azle/node_modules/@dfinity/candid": { + "version": "0.19.2", + "resolved": "git+ssh://git@github.com/demergent-labs/candid.git#5797fa906b1a7cc30c161dbb0eb919283ce2f80d", + "license": "Apache-2.0", + "peerDependencies": { + "@dfinity/principal": "^0.19.2" + } + }, + "node_modules/azle/node_modules/ts-node": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.1.tgz", + "integrity": "sha512-Yw3W2mYzhHfCHOICGNJqa0i+rbL0rAyg7ZIHxU+K4pgY8gd2Lh1j+XbHCusJMykbj6RZMJVOY0MlHVd+GOivcw==", + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/base64-arraybuffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", + "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/borc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", + "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", + "dev": true, + "dependencies": { + "bignumber.js": "^9.0.0", + "buffer": "^5.5.0", + "commander": "^2.15.0", + "ieee754": "^1.1.13", + "iso-url": "~0.4.7", + "json-text-sequence": "~0.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/borc/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/delimit-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", + "integrity": "sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/esbuild": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", + "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.5", + "@esbuild/android-arm64": "0.19.5", + "@esbuild/android-x64": "0.19.5", + "@esbuild/darwin-arm64": "0.19.5", + "@esbuild/darwin-x64": "0.19.5", + "@esbuild/freebsd-arm64": "0.19.5", + "@esbuild/freebsd-x64": "0.19.5", + "@esbuild/linux-arm": "0.19.5", + "@esbuild/linux-arm64": "0.19.5", + "@esbuild/linux-ia32": "0.19.5", + "@esbuild/linux-loong64": "0.19.5", + "@esbuild/linux-mips64el": "0.19.5", + "@esbuild/linux-ppc64": "0.19.5", + "@esbuild/linux-riscv64": "0.19.5", + "@esbuild/linux-s390x": "0.19.5", + "@esbuild/linux-x64": "0.19.5", + "@esbuild/netbsd-x64": "0.19.5", + "@esbuild/openbsd-x64": "0.19.5", + "@esbuild/sunos-x64": "0.19.5", + "@esbuild/win32-arm64": "0.19.5", + "@esbuild/win32-ia32": "0.19.5", + "@esbuild/win32-x64": "0.19.5" + } + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/iso-url": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", + "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "node_modules/json-text-sequence": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz", + "integrity": "sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w==", + "dev": true, + "dependencies": { + "delimit-stream": "0.1.0" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-cbor": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/simple-cbor/-/simple-cbor-0.4.1.tgz", + "integrity": "sha512-rijcxtwx2b4Bje3sqeIqw5EeW7UlOIC4YfOdwqIKacpvRQ/D78bWg/4/0m5e0U91oKvlGh7LlJuZCu07ISCC7w==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", + "deprecated": "no longer maintained" + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/property_tests/tests/variant/package.json b/property_tests/tests/variant/package.json new file mode 100644 index 0000000000..fd5d123560 --- /dev/null +++ b/property_tests/tests/variant/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "test": "ts-node --transpile-only --ignore=false test/test.ts" + }, + "dependencies": { + "azle": "^0.18.5" + }, + "devDependencies": { + "@dfinity/agent": "^0.19.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } +} diff --git a/property_tests/tests/variant/test/test.ts b/property_tests/tests/variant/test/test.ts new file mode 100644 index 0000000000..716edf272c --- /dev/null +++ b/property_tests/tests/variant/test/test.ts @@ -0,0 +1,125 @@ +import fc from 'fast-check'; + +import { + Variant, + VariantArb +} from '../../../arbitraries/candid/constructed/variant_arb'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { UniqueIdentifierArb } from '../../../arbitraries/unique_identifier_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; + +const VariantTestArb = fc + .tuple( + UniqueIdentifierArb('canisterMethod'), + fc.uniqueArray(VariantArb, { + selector: (entry) => entry.src.candidType + }), + VariantArb + ) + .map(([functionName, paramVariants, defaultReturnVariant]): TestSample => { + const imports = new Set([ + ...paramVariants.flatMap((variant) => [...variant.src.imports]), + ...defaultReturnVariant.src.imports + ]); + + const candidTypeDeclarations = [ + ...paramVariants.map( + (variant) => variant.src.typeDeclaration ?? '' + ), + defaultReturnVariant.src.typeDeclaration ?? '' + ]; + + const paramNames = paramVariants.map((_, index) => `param${index}`); + const paramCandidTypes = paramVariants + .map((variant) => variant.src.candidType) + .join(', '); + + const returnCandidType = + paramVariants[0]?.src?.candidType ?? + defaultReturnVariant.src.candidType; + + const body = generateBody( + paramNames, + paramVariants, + defaultReturnVariant + ); + + const test = generateTest( + functionName, + paramVariants, + defaultReturnVariant + ); + + return { + imports, + functionName, + candidTypeDeclarations, + paramCandidTypes, + returnCandidType, + paramNames, + body, + test + }; + }); + +runPropTests(VariantTestArb); + +function generateBody( + paramNames: string[], + paramVariants: CandidMeta[], + returnVariant: CandidMeta +): string { + const paramsAreVariants = paramNames + .map((paramName) => { + return `if (typeof ${paramName} !== 'object' || Object.keys(${paramName}).length !== 1) throw new Error('${paramName} must be a Variant');`; + }) + .join('\n'); + + const paramsCorrectlyOrdered = paramVariants + .map((variant, index) => { + const paramName = `param${index}`; + + return `if (Object.keys(${paramName})[0] !== "${ + Object.keys(variant.value)[0] + }") throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + const returnStatement = paramNames[0] + ? `${paramNames[0]}` + : returnVariant.src.valueLiteral; + + return ` + ${paramsCorrectlyOrdered} + + ${paramsAreVariants} + + return ${returnStatement}; + `; +} + +function generateTest( + functionName: string, + paramVariants: CandidMeta[], + returnVariant: CandidMeta +): Test { + const expectedResult = paramVariants[0]?.value ?? returnVariant.value; + const equals = + paramVariants[0]?.equals ?? ((a: any, b: any) => a.None === b.None); + return { + name: `variant ${functionName}`, + test: async () => { + const actor = getActor('./tests/variant/test'); + + const result = await actor[functionName]( + ...paramVariants.map((variant) => variant.value) + ); + + return { + Ok: equals(result, expectedResult) + }; + } + }; +} diff --git a/property_tests/tests/variant/tsconfig.json b/property_tests/tests/variant/tsconfig.json new file mode 100644 index 0000000000..2638f0d8bc --- /dev/null +++ b/property_tests/tests/variant/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ES2020", + "moduleResolution": "node", + "allowJs": true, + "outDir": "HACK_BECAUSE_OF_ALLOW_JS" + } +} diff --git a/property_tests/tests/vec/test/test.ts b/property_tests/tests/vec/test/test.ts index 54a255e883..231de60fcf 100644 --- a/property_tests/tests/vec/test/test.ts +++ b/property_tests/tests/vec/test/test.ts @@ -1,96 +1,50 @@ import fc from 'fast-check'; + import { VecArb } from '../../../arbitraries/candid/constructed/vec_arb'; -import { getActor } from '../../../get_actor'; -import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; import { JsFunctionNameArb } from '../../../arbitraries/js_function_name_arb'; -import { runPropTests } from '../../..'; +import { TestSample } from '../../../arbitraries/test_sample_arb'; +import { createUniquePrimitiveArb } from '../../../arbitraries/unique_primitive_arb'; +import { getActor, runPropTests } from '../../../../property_tests'; +import { deepEqual } from 'fast-equals'; +import { CandidMeta } from '../../../arbitraries/candid/candid_arb'; +import { Test } from '../../../../test'; const VecTestArb = fc - .tuple(createUniquePrimitiveArb(JsFunctionNameArb), fc.array(VecArb)) - .map(([functionName, vecWrappers]) => { - const paramCandidTypes = vecWrappers.map( - (vecWrapper) => vecWrapper.candidType - ); - const returnCandidType = vecWrappers[0]?.candidType ?? 'Vec(int8)'; - const paramNames = vecWrappers.map((_, index) => `param${index}`); - - // TODO these checks should be much more precise probably, imagine checking the elements inside of the arrays - const paramsAreArrays = paramNames - .map((paramName) => { - return `if (!Array.isArray(${paramName}) && !ArrayBuffer.isView(${paramName})) throw new Error('${paramName} must be an array');`; - }) - .join('\n'); - - // TODO this ordering check is not perfect - // TODO but turning the vec into a string seems a bit difficult...we need to figure out how to check perfecly for the values that we want - // TODO maybe a global variable that we can write into and call would work - const paramsCorrectlyOrdered = paramNames - .map((paramName, index) => { - return `if (${paramName}.length !== ${vecWrappers[index].vec.length}) throw new Error('${paramName} is incorrectly ordered')`; - }) - .join('\n'); - - const returnStatement = paramNames[0] ?? `[]`; - - const expectedResult = vecWrappers[0]?.vec ?? []; - - const equalityCheck = - vecWrappers[0]?.equalityCheck ?? ((a, b) => a === b); + .tuple( + createUniquePrimitiveArb(JsFunctionNameArb), + fc.array(VecArb), + VecArb + ) + .map(([functionName, paramVecs, defaultReturnVec]): TestSample => { + const imports = new Set([ + ...paramVecs.flatMap((vec) => [...vec.src.imports]), + ...defaultReturnVec.src.imports + ]); + + const paramNames = paramVecs.map((_, index) => `param${index}`); + const paramCandidTypes = paramVecs.map((vec) => vec.src.candidType); + + const returnCandidType = + paramVecs[0]?.src?.candidType ?? defaultReturnVec.src.candidType; + + const body = generateBody(paramNames, paramVecs, defaultReturnVec); + + const test = generateTest(functionName, paramVecs, defaultReturnVec); return { functionName, - imports: [ - 'int', - 'int8', - 'int16', - 'int32', - 'int64', - 'nat', - 'nat8', - 'nat16', - 'nat32', - 'nat64', - 'Principal', - 'Vec' - ], + imports, paramCandidTypes: paramCandidTypes.join(', '), returnCandidType, paramNames, - body: ` - ${paramsCorrectlyOrdered} - - ${paramsAreArrays} - - return ${returnStatement}; - `, - test: { - name: `test ${functionName}`, - test: async () => { - const actor = getActor('./tests/vec/test'); - - const result = await actor[functionName]( - ...vecWrappers.map((vecWrapper) => vecWrapper.vec) - ); - - return { - Ok: primitiveArraysAreEqual( - result, - expectedResult, - equalityCheck - ) - }; - } - } + body, + test }; }); runPropTests(VecTestArb); -function primitiveArraysAreEqual( - arr1: any, - arr2: any, - equalityCheck: (a: any, b: any) => boolean -) { +function blobsAreEqual(arr1: Uint8Array, arr2: Uint8Array) { // Check if both arrays have the same length if (arr1.length !== arr2.length) { return false; @@ -98,10 +52,65 @@ function primitiveArraysAreEqual( // Loop through each element to check for equality for (let i = 0; i < arr1.length; i++) { - if (!equalityCheck(arr1[i], arr2[i])) { + if (!deepEqual(arr1[i], arr2[i])) { return false; } } return true; } + +function generateBody( + paramNames: string[], + paramVecs: CandidMeta[], + returnVec: CandidMeta +): string { + // TODO these checks should be much more precise probably, imagine checking the elements inside of the arrays + const paramsAreArrays = paramNames + .map((paramName) => { + return `if (!Array.isArray(${paramName}) && !ArrayBuffer.isView(${paramName})) throw new Error('${paramName} must be an array');`; + }) + .join('\n'); + + // TODO this ordering check is not perfect + // TODO but turning the vec into a string seems a bit difficult...we need to figure out how to check perfectly for the values that we want + // TODO maybe a global variable that we can write into and call would work + const paramsCorrectlyOrdered = paramNames + .map((paramName, index) => { + return `if (${paramName}.length !== ${paramVecs[index].value.length}) throw new Error('${paramName} is incorrectly ordered')`; + }) + .join('\n'); + + const returnValue = paramNames[0] ?? returnVec.src.valueLiteral; + + return ` + ${paramsAreArrays} + + ${paramsCorrectlyOrdered} + + return ${returnValue}; + `; +} + +function generateTest( + functionName: string, + paramVecs: CandidMeta[], + returnVec: CandidMeta +): Test { + const expectedResult = paramVecs[0]?.value ?? returnVec.value; + const equals = paramVecs[0]?.equals ?? returnVec.equals; + + return { + name: `vec ${functionName}`, + test: async () => { + const actor = getActor('./tests/vec/test'); + + const params = paramVecs.map((vec) => vec.value); + const result = await actor[functionName](...params); + + return { + Ok: equals(result, expectedResult) + }; + } + }; +}