Skip to content

Commit

Permalink
simplify opts
Browse files Browse the repository at this point in the history
  • Loading branch information
bdemann committed Nov 2, 2023
1 parent 002b48f commit 046b3ab
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 93 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -223,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 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 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 npm test

check-basic-integration-tests-success:
needs: basic-integration-tests
Expand Down
111 changes: 23 additions & 88 deletions property_tests/arbitraries/candid/constructed/opt_arb.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,31 @@
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 { Float32Arb } from '../primitive/floats/float32_arb';
import { Float64Arb } from '../primitive/floats/float64_arb';
import { TextArb } from '../primitive/text';
import { NullArb } from '../primitive/null';
import { BoolArb } from '../primitive/bool';
import { Candid } from '../../candid';
import { PrincipalArb } from '../reference/principal_arb';
import { Principal } from '@dfinity/principal';

type InnerOpt = number | bigint | null | string | boolean | Opt | Principal;
type InnerOptArb = Candid<{ Some?: Candid<InnerOpt>; None?: null }>;
import { Candid, CandidType, CandidTypeArb } from '../../candid';

type InnerOptArb = ['Some' | 'None', Candid<CandidType>];

// This gives us a random Some or None, which means the default depth of all Opts is at least one
const InnerOptArb = (arb: fc.Arbitrary<Candid<InnerOpt>>) => {
const InnerOptArb = (arb: fc.Arbitrary<Candid<CandidType>>) => {
return fc.constantFrom('Some', 'None').chain((keySample) => {
return arb.map((innerValueSample): InnerOptArb => {
if (keySample === 'Some') {
return {
value: { Some: innerValueSample },
src: {
candidType: `Opt(${innerValueSample.src.candidType})`,
imports: new Set([
...innerValueSample.src.imports,
'Opt'
]),
valueLiteral: `{Some: ${innerValueSample.src.valueLiteral}}`
},
equals: (a, b) => {
if (a.Some === undefined || b.Some === undefined) {
return false;
}
return innerValueSample.equals(
a.Some.value,
b.Some.value
);
}
};
return ['Some', innerValueSample];
} else {
return {
value: { None: null },
src: {
candidType: `Opt(${innerValueSample.src.candidType})`,
imports: new Set([
...innerValueSample.src.imports,
'Opt'
]),
valueLiteral: '{None: null}'
},
equals: (a, b) => {
if (a.None === undefined || b.None === undefined) {
return false;
}
return a.None === b.None;
}
};
return ['None', innerValueSample];
}
});
});
};

// TODO look into making this recursive
// TODO we need to add all constructed and reference types
export const PrimitiveOptArb = fc.oneof(
InnerOptArb(Float32Arb),
InnerOptArb(Float64Arb),
InnerOptArb(IntArb),
InnerOptArb(Int8Arb),
InnerOptArb(Int16Arb),
InnerOptArb(Int32Arb),
InnerOptArb(Int64Arb),
InnerOptArb(NatArb),
InnerOptArb(Nat8Arb),
InnerOptArb(Nat16Arb),
InnerOptArb(Nat32Arb),
InnerOptArb(Nat64Arb),
InnerOptArb(BoolArb),
InnerOptArb(TextArb),
InnerOptArb(NullArb),
InnerOptArb(PrincipalArb)
);
export const PrimitiveOptArb = InnerOptArb(CandidTypeArb);

type RecursiveOpt<T> = {
base: T;
nextLayer: RecursiveOpt<T> | null;
};

export type Opt = [InnerOpt] | never[];
export type Opt = [CandidType | Opt] | never[];

export const OptArb = fc
.letrec((tie) => ({
Expand All @@ -121,7 +51,7 @@ export const OptArb = fc
function generateCandidType(recursiveOpt: RecursiveOpt<InnerOptArb>): string {
if (recursiveOpt.nextLayer === null) {
// base case
return recursiveOpt.base.src.candidType;
return `Opt(${recursiveOpt.base[1].src.candidType})`;
} else {
return `Opt(${generateCandidType(recursiveOpt.nextLayer)})`;
}
Expand All @@ -130,7 +60,7 @@ function generateCandidType(recursiveOpt: RecursiveOpt<InnerOptArb>): string {
function generateImports(recursiveOpt: RecursiveOpt<InnerOptArb>): Set<string> {
if (recursiveOpt.nextLayer === null) {
// base case
return recursiveOpt.base.src.imports;
return new Set([...recursiveOpt.base[1].src.imports, 'Opt']);
} else {
return generateImports(recursiveOpt.nextLayer);
}
Expand All @@ -139,8 +69,8 @@ function generateImports(recursiveOpt: RecursiveOpt<InnerOptArb>): Set<string> {
function generateValue(recursiveOpt: RecursiveOpt<InnerOptArb>): Opt {
if (recursiveOpt.nextLayer === null) {
// base case
if (recursiveOpt.base.value.Some !== undefined) {
return [recursiveOpt.base.value.Some.value];
if (recursiveOpt.base[0] === 'Some') {
return [recursiveOpt.base[1].value];
} else {
return [];
}
Expand All @@ -152,7 +82,11 @@ function generateValue(recursiveOpt: RecursiveOpt<InnerOptArb>): Opt {
function generateValueLiteral(recursiveOpt: RecursiveOpt<InnerOptArb>): string {
if (recursiveOpt.nextLayer === null) {
// base case
return recursiveOpt.base.src.valueLiteral;
if (recursiveOpt.base[0] === 'Some') {
return `{Some: ${recursiveOpt.base[1].src.valueLiteral}}`;
} else {
return `{None: null}`;
}
} else {
return `{
Some: ${generateValueLiteral(recursiveOpt.nextLayer)}
Expand Down Expand Up @@ -188,8 +122,8 @@ function getBaseEquals(
): (a: any, b: any) => boolean {
if (recursiveOpt.nextLayer === null) {
// base case
if (recursiveOpt.base.value.Some !== undefined) {
return recursiveOpt.base.value.Some.equals;
if (recursiveOpt.base[0] === 'Some') {
return recursiveOpt.base[1].equals;
} else {
return (a: null, b: null) => a === b;
}
Expand All @@ -210,12 +144,13 @@ function areOptsEqual(
return false;
}

function isNone(value: any | []) {
return Array.isArray(value) && value.length === 0;
}
if (isNone(value1) && isNone(value2)) {
return true;
}

return equals(value1, value2);
}

function isNone(value: any | []) {
return Array.isArray(value) && value.length === 0;
}
4 changes: 3 additions & 1 deletion property_tests/arbitraries/candid/constructed/vec_arb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ 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';

const VecInnerArb = <T>(arb: fc.Arbitrary<Candid<T>>) => {
return fc.tuple(fc.array(arb), arb).map(([sample, src]): Candid<T[]> => {
Expand Down Expand Up @@ -62,7 +63,8 @@ export const VecArb = fc.oneof(
VecInnerArb(Nat64Arb),
VecInnerArb(BoolArb),
VecInnerArb(TextArb),
VecInnerArb(PrincipalArb)
VecInnerArb(PrincipalArb),
VecInnerArb(BlobArb)
// VecInnerArb(NullArb)
);

Expand Down
2 changes: 1 addition & 1 deletion property_tests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function runPropTests(testArb: fc.Arbitrary<TestSample>) {
);
}),
{
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
}
);
Expand Down

0 comments on commit 046b3ab

Please sign in to comment.