-
Notifications
You must be signed in to change notification settings - Fork 228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spike test only support #1682
Spike test only support #1682
Conversation
Thesed in tests in the economy repository, and is based on prior code, but generally is not yet tested.
NOTE: this is preliminary only to discuss whether it can support what we need for testing.
Usage in a contract is something like:
The test imports the testContext (this should be made easier):
and then the test can refer to e.g., |
I am interested in how
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very promising. Could we see a contract using this, with tests? I could see something like atomicSwap or the secondPriceAuction using this. Does this work under the SwingSet tests? Lastly, I think the name needs to be changed because test.only
has a different meaning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! A few suggestions
- fix types - simplify the zcf-test contract - clean up exports from fakeVatAdmin
Make the testFn default to a no-op function to support the simple case of making zcf available.
Just awaiting @warner 's thoughts on what to do about the argument to |
The pattern I'll recommend is one where each component (ZCF, or the contract) is willing to be vulnerable to (and share internal secrets with) a parent who builds it in an unusual way, which we do during tests. The parent indicates that we're in a special environment by either passing an argument that's outside the usual API, or by accessing an export that's outside the usual API. It should be abundantly clear to an auditor/reviewer which is the normal path and which is not. Vats, like the one created from ZCF, are defined to export a function like For contracts, we should start by renaming the primary export, since We've got the same flexibility with contracts: since ZCF doesn't currently pass any arguments in, we can either define the optional first argument to be this debug/test pathway, or have the contract export a new function for this purpose. Exporting an extra function would be somewhat safer, because if we change ZCF a month from now to pass some new argument in (for functional purposes), and we miss updating a contract, we might leak something important. It's the usual named-vs-positional argument argument. Then the question is what exactly ZCF and the contract want to share with the test harness, and how to pass them through this new pathway. In both cases the testing-relevant internals aren't created until the primary export function is invoked. I'll assume that all of the interesting internals are created by the time that invocation finishes (and we aren't inventing new bits after it returns, or that we find some different way to return them). I can think of four patterns (mutable object or not, times exported function vs argument): 1: export let debugInfo = {};
export function buildRootObject(vatPowers, vatParameters) {
const root = buildstuff();
debugInfo.secret = foo;
return root;
} 2: let debugInfo = {};
export function getDebugInfo() {
return debugInfo;
}
export function buildRootObject(vatPowers, vatParameters) {
const root = buildstuff();
debugInfo.secret = foo;
return root;
} 3: export function buildRootObject(vatPowers, vatParameters, debugInfo={}) {
const root = buildstuff();
debugInfo.secret = foo;
return root;
} 4: export function buildRootObject(vatPowers, vatParameters, giveDebugInfo) {
const root = buildstuff();
let debugInfo = { secret };
if (giveDebugInfo) {
giveDebugInfo(debugInfo);
}
return root;
} The new-export cases (1 and 2) need new top-level mutable state, making the module non-pure. I think we tend to avoid that. The third export function buildRootObject(vatPowers, vatParameters, debugInfo={}) {
const root = buildstuff();
debugInfo.secret = foo;
debugInfo.contractSecrets = {};
const contract = makeContract(otherArgs, debugInfo.contractSecrets);
return root;
} Using So I guess I'd give 3 a try, which I think is how you're approaching the contract. I can't quite understand what files are creating what, so I can't tell how close your patch is to what I described above. When |
This was committed in another PR |
Just a sketch to have something concrete to talk about.