-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1444 from demergent-labs/service_property_test
Service property test
- Loading branch information
Showing
8 changed files
with
1,277 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
property_tests/arbitraries/candid/reference/service_arb.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
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 { CandidTypeArb } from '../candid_type_arb'; | ||
import { UniqueIdentifierArb } from '../../unique_identifier_arb'; | ||
import { JsFunctionNameArb } from '../../js_function_name_arb'; | ||
|
||
// TODO: | ||
// - services that are more than type-definitions, i.e. have functionality | ||
// - async service methods | ||
// - non-query methods | ||
// - actually using the service | ||
|
||
// Example Service: | ||
// const SomeService = Canister({ | ||
// method1: query([], Void), | ||
// method2: query([text, text, nat64], nat64), | ||
// }); | ||
|
||
type ServiceMethod = { | ||
name: string; | ||
imports: Set<string>; | ||
typeDeclarations: string[]; | ||
src: string; | ||
}; | ||
|
||
const ServiceMethodArb = fc | ||
.tuple( | ||
JsFunctionNameArb, | ||
fc.constantFrom('query', 'update'), | ||
fc.array(CandidTypeArb), | ||
fc.oneof(CandidTypeArb, VoidArb) | ||
) | ||
.map(([name, mode, params, returnType]): ServiceMethod => { | ||
const paramThings = params.map((param) => param.src.candidType); | ||
|
||
const typeDeclarations = params.reduce( | ||
(acc, { src: { typeDeclaration } }) => { | ||
return typeDeclaration ? [...acc, typeDeclaration] : acc; | ||
}, | ||
returnType.src.typeDeclaration | ||
? [returnType.src.typeDeclaration] | ||
: new Array<string>() | ||
); | ||
|
||
const src = `${name}: ${mode}([${paramThings}], ${returnType.src.candidType})`; | ||
|
||
const imports = params.reduce( | ||
(acc, param) => { | ||
return new Set([...acc, ...param.src.imports]); | ||
}, | ||
new Set([mode, ...returnType.src.imports]) | ||
); | ||
|
||
return { | ||
name, | ||
imports, | ||
typeDeclarations, | ||
src | ||
}; | ||
}); | ||
|
||
export const ServiceArb = fc | ||
.tuple( | ||
UniqueIdentifierArb('typeDeclaration'), | ||
fc.array(ServiceMethodArb), | ||
PrincipalArb | ||
) | ||
.map(([name, serviceMethods, principal]): CandidMeta<Principal> => { | ||
const imports = new Set([ | ||
...serviceMethods.flatMap((method) => [...method.imports]), | ||
'Canister', | ||
'query' | ||
]); | ||
|
||
const typeDeclaration = generateTypeDeclaration(name, serviceMethods); | ||
|
||
const typeDeclarationAndChildren = [ | ||
...serviceMethods.flatMap((method) => method.typeDeclarations), | ||
typeDeclaration | ||
].join('\n'); | ||
|
||
const valueLiteral = `${name}(${principal.src.valueLiteral})`; | ||
|
||
const value = principal.value; | ||
|
||
return { | ||
src: { | ||
candidType: name, | ||
typeDeclaration: typeDeclarationAndChildren, | ||
imports, | ||
valueLiteral | ||
}, | ||
value | ||
}; | ||
}); | ||
|
||
function generateTypeDeclaration( | ||
name: string, | ||
serviceMethods: ServiceMethod[] | ||
): string { | ||
const methods = serviceMethods | ||
.map((serviceMethod) => serviceMethod.src) | ||
.filter((typeDeclaration) => typeDeclaration) | ||
.join(',\n'); | ||
|
||
// TODO: Is this going to work if serviceMethods.length === 0? | ||
return `const ${name} = Canister({${methods}});`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.