Skip to content

Commit

Permalink
fix(cli): wing test returns 0 exit code upon failure (#3176)
Browse files Browse the repository at this point in the history
Fixes #2916 by returning exit code 0 when tests fail.

## Misc

Tweaks to a bunch of tests.

## Checklist

- [x] Title matches [Winglang's style guide](https://docs.winglang.io/contributing/pull_requests#how-are-pull-request-titles-formatted)
- [x] Description explains motivation and solution
- [x] Tests added (always)
- [x] Docs updated (only required for features)
- [x] Added `pr/e2e-full` label if this feature requires end-to-end testing

*By submitting this pull request, I confirm that my contribution is made under the terms of the [Monada Contribution License](https://docs.winglang.io/terms-and-policies/contribution-license.html)*.
  • Loading branch information
eladb authored Jun 30, 2023
1 parent e6d0f80 commit 6d23520
Show file tree
Hide file tree
Showing 18 changed files with 518 additions and 74 deletions.
12 changes: 9 additions & 3 deletions apps/wing/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ if (!SUPPORTED_NODE_VERSION) {
}

function actionErrorHandler(fn: (...args: any[]) => Promise<any>) {
return (...args: any[]) =>
fn(...args).catch((err: Error) => {
return async (...args: any[]) => {
try {
const exitCode = await fn(...args);
if (exitCode === 1) {
process.exit(1);
}
} catch (err) {
console.error(err);
process.exit(1);
});
}
};
}

async function main() {
Expand Down
19 changes: 14 additions & 5 deletions apps/wing/src/commands/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const generateTestName = (path: string) => path.split(sep).slice(-2).join("/");
*/
export interface TestOptions extends CompileOptions {}

export async function test(entrypoints: string[], options: TestOptions) {
export async function test(entrypoints: string[], options: TestOptions): Promise<number> {
const startTime = Date.now();
const results: { testName: string; results: sdk.cloud.TestResult[] }[] = [];
for (const entrypoint of entrypoints) {
Expand All @@ -44,6 +44,17 @@ export async function test(entrypoints: string[], options: TestOptions) {
}
}
printResults(results, Date.now() - startTime);

// if we have any failures, exit with 1
for (const test of results) {
for (const r of test.results) {
if (r.error) {
return 1;
}
}
}

return 0;
}

function printResults(
Expand Down Expand Up @@ -92,16 +103,14 @@ function printResults(
// prints a summary of how many tests passed and failed
results.push(" ");
results.push(
`${chalk.dim("Tests")}${failingTestsNumber ? chalk.red(` ${failingTestsNumber} failed`) : ""}${
failingTestsNumber && passingTestsNumber ? chalk.dim(" |") : ""
`${chalk.dim("Tests")}${failingTestsNumber ? chalk.red(` ${failingTestsNumber} failed`) : ""}${failingTestsNumber && passingTestsNumber ? chalk.dim(" |") : ""
}${passingTestsNumber ? chalk.green(` ${passingTestsNumber} passed`) : ""} ${chalk.dim(
`(${failingTestsNumber + passingTestsNumber})`
)}`
);
// prints a summary of how many tests files passed and failed
results.push(
`${chalk.dim("Test Files")}${failing.length ? chalk.red(` ${failing.length} failed`) : ""}${
failing.length && passing.length ? chalk.dim(" |") : ""
`${chalk.dim("Test Files")}${failing.length ? chalk.red(` ${failing.length} failed`) : ""}${failing.length && passing.length ? chalk.dim(" |") : ""
}${passing.length ? chalk.green(` ${passing.length} passed`) : ""} ${chalk.dim(
`(${totalSum})`
)}`
Expand Down
31 changes: 0 additions & 31 deletions examples/tests/invalid/inflight_class_capture_mutable.w

This file was deleted.

2 changes: 1 addition & 1 deletion examples/tests/sdk_tests/bucket/events.w
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,4 @@ new std.Test(inflight () => {
assert(wait(checkHitCount(key: "b", type: "UPDATE", source: Source.onEvent, count: 1)));
assert(wait(checkHitCount(key: "c", type: "DELETE", source: Source.onEvent, count: 1)));

}, std.TestProps { timeout: 8m }) as "hitCount is incremented according to the bucket event";
}, timeout: 8m) as "hitCount is incremented according to the bucket event";
3 changes: 1 addition & 2 deletions examples/tests/sdk_tests/bucket/public_url.w
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
bring cloud;

let bucketProps = cloud.BucketProps{public: true};
let publicBucket = new cloud.Bucket(bucketProps) as "publicBucket";
let publicBucket = new cloud.Bucket(public: true) as "publicBucket";
let privateBucket = new cloud.Bucket() as "privateBucket";

test "publicUrl" {
Expand Down
5 changes: 5 additions & 0 deletions examples/tests/valid/enums.w
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ enum SomeEnum {

let one = SomeEnum.ONE;
let two: SomeEnum = SomeEnum.TWO; // Try with explicit type annotation

test "inflight" {
assert(one == SomeEnum.ONE);
assert(two == SomeEnum.TWO);
}
15 changes: 15 additions & 0 deletions examples/tests/valid/resource_call_static.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
bring cloud;

let globalCounter = new cloud.Counter();

class Another {
static inflight myStaticMethod(): num {
return globalCounter.peek();
}
}

test "access cloud resource through static methods only" {
// Call a static method which access a (global) cloud resource
// the capturing should work through the Type binding mechanism
assert(Another.myStaticMethod() == 0);
}
9 changes: 0 additions & 9 deletions tools/hangar/__snapshots__/invalid.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -659,15 +659,6 @@ Test Files 1 failed (1)
Duration <DURATION>"
`;
exports[`inflight_class_capture_mutable.w 1`] = `
"passinflight_class_capture_mutable.wsim (no tests)
Tests 1 passed (1)
Test Files 1 passed (1)
Duration <DURATION>"
`;
exports[`inflight_class_created_in_preflight.w 1`] = `
"error: Cannot create inflight class \\"Foo\\" in preflight phase
--> ../../../examples/tests/invalid/inflight_class_created_in_preflight.w:3:1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1476,9 +1476,7 @@ class $Root extends $stdlib.std.Resource {
(b.onEvent(new $Closure5(this,"$Closure5")));
const wait = new $Closure6(this,"$Closure6");
const checkHitCount = new $Closure7(this,"$Closure7");
this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"hitCount is incremented according to the bucket event",new $Closure8(this,"$Closure8"),{
"timeout": (std.Duration.fromSeconds(480)),}
);
this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"hitCount is incremented according to the bucket event",new $Closure8(this,"$Closure8"),{ timeout: (std.Duration.fromSeconds(480)) });
}
}
class $App extends $AppBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,7 @@ class $Root extends $stdlib.std.Resource {
super._registerBind(host, ops);
}
}
const bucketProps = {
"public": true,}
;
const publicBucket = this.node.root.newAbstract("@winglang/sdk.cloud.Bucket",this,"publicBucket",bucketProps);
const publicBucket = this.node.root.newAbstract("@winglang/sdk.cloud.Bucket",this,"publicBucket",{ public: true });
const privateBucket = this.node.root.newAbstract("@winglang/sdk.cloud.Bucket",this,"privateBucket");
this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:publicUrl",new $Closure1(this,"$Closure1"));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# [enums.w](../../../../../examples/tests/valid/enums.w) | compile | tf-aws

## inflight.$Closure1.js
```js
module.exports = function({ one, two, SomeEnum }) {
class $Closure1 {
constructor({ }) {
const $obj = (...args) => this.handle(...args);
Object.setPrototypeOf($obj, this);
return $obj;
}
async $inflight_init() {
}
async handle() {
{((cond) => {if (!cond) throw new Error("assertion failed: one == SomeEnum.ONE")})((one === SomeEnum.ONE))};
{((cond) => {if (!cond) throw new Error("assertion failed: two == SomeEnum.TWO")})((two === SomeEnum.TWO))};
}
}
return $Closure1;
}

```

## main.tf.json
```json
{
Expand All @@ -21,13 +42,102 @@
},
"output": {
"WING_TEST_RUNNER_FUNCTION_ARNS": {
"value": "[]"
"value": "[[\"root/Default/Default/test:inflight\",\"${aws_lambda_function.root_testinflight_Handler_75584D7C.arn}\"]]"
}
},
"provider": {
"aws": [
{}
]
},
"resource": {
"aws_iam_role": {
"root_testinflight_Handler_IamRole_52AF7859": {
"//": {
"metadata": {
"path": "root/Default/Default/test:inflight/Handler/IamRole",
"uniqueId": "root_testinflight_Handler_IamRole_52AF7859"
}
},
"assume_role_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Effect\":\"Allow\"}]}"
}
},
"aws_iam_role_policy": {
"root_testinflight_Handler_IamRolePolicy_877E2F83": {
"//": {
"metadata": {
"path": "root/Default/Default/test:inflight/Handler/IamRolePolicy",
"uniqueId": "root_testinflight_Handler_IamRolePolicy_877E2F83"
}
},
"policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"none:null\",\"Resource\":\"*\"}]}",
"role": "${aws_iam_role.root_testinflight_Handler_IamRole_52AF7859.name}"
}
},
"aws_iam_role_policy_attachment": {
"root_testinflight_Handler_IamRolePolicyAttachment_C597EE77": {
"//": {
"metadata": {
"path": "root/Default/Default/test:inflight/Handler/IamRolePolicyAttachment",
"uniqueId": "root_testinflight_Handler_IamRolePolicyAttachment_C597EE77"
}
},
"policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
"role": "${aws_iam_role.root_testinflight_Handler_IamRole_52AF7859.name}"
}
},
"aws_lambda_function": {
"root_testinflight_Handler_75584D7C": {
"//": {
"metadata": {
"path": "root/Default/Default/test:inflight/Handler/Default",
"uniqueId": "root_testinflight_Handler_75584D7C"
}
},
"environment": {
"variables": {
"WING_FUNCTION_NAME": "Handler-c85726ab",
"WING_TARGET": "tf-aws"
}
},
"function_name": "Handler-c85726ab",
"handler": "index.handler",
"publish": true,
"role": "${aws_iam_role.root_testinflight_Handler_IamRole_52AF7859.arn}",
"runtime": "nodejs18.x",
"s3_bucket": "${aws_s3_bucket.root_Code_02F3C603.bucket}",
"s3_key": "${aws_s3_object.root_testinflight_Handler_S3Object_62C42629.key}",
"timeout": 30,
"vpc_config": {
"security_group_ids": [],
"subnet_ids": []
}
}
},
"aws_s3_bucket": {
"root_Code_02F3C603": {
"//": {
"metadata": {
"path": "root/Default/Code",
"uniqueId": "root_Code_02F3C603"
}
},
"bucket_prefix": "code-c84a50b1-"
}
},
"aws_s3_object": {
"root_testinflight_Handler_S3Object_62C42629": {
"//": {
"metadata": {
"path": "root/Default/Default/test:inflight/Handler/S3Object",
"uniqueId": "root_testinflight_Handler_S3Object_62C42629"
}
},
"bucket": "${aws_s3_bucket.root_Code_02F3C603.bucket}",
"key": "<ASSET_KEY>",
"source": "<ASSET_SOURCE>"
}
}
}
}
```
Expand All @@ -42,6 +152,55 @@ const $AppBase = $stdlib.core.App.for(process.env.WING_TARGET);
class $Root extends $stdlib.std.Resource {
constructor(scope, id) {
super(scope, id);
class $Closure1 extends $stdlib.std.Resource {
constructor(scope, id, ) {
super(scope, id);
this.display.hidden = true;
this._addInflightOps("handle");
}
static _toInflightType(context) {
const self_client_path = "././inflight.$Closure1.js";
const one_client = context._lift(one);
const two_client = context._lift(two);
const SomeEnumClient = $stdlib.core.NodeJsCode.fromInline(`
Object.freeze((function (tmp) {
tmp[tmp["ONE"] = 0] = "ONE";
tmp[tmp["TWO"] = 1] = "TWO";
tmp[tmp["THREE"] = 2] = "THREE";
return tmp;
})({}))
`);
return $stdlib.core.NodeJsCode.fromInline(`
require("${self_client_path}")({
one: ${one_client},
two: ${two_client},
SomeEnum: ${SomeEnumClient.text},
})
`);
}
_toInflight() {
return $stdlib.core.NodeJsCode.fromInline(`
(await (async () => {
const $Closure1Client = ${$Closure1._toInflightType(this).text};
const client = new $Closure1Client({
});
if (client.$inflight_init) { await client.$inflight_init(); }
return client;
})())
`);
}
_registerBind(host, ops) {
if (ops.includes("$inflight_init")) {
$Closure1._registerBindObject(one, host, []);
$Closure1._registerBindObject(two, host, []);
}
if (ops.includes("handle")) {
$Closure1._registerBindObject(one, host, []);
$Closure1._registerBindObject(two, host, []);
}
super._registerBind(host, ops);
}
}
const SomeEnum =
Object.freeze((function (tmp) {
tmp[tmp["ONE"] = 0] = "ONE";
Expand All @@ -52,6 +211,7 @@ class $Root extends $stdlib.std.Resource {
;
const one = SomeEnum.ONE;
const two = SomeEnum.TWO;
this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:inflight",new $Closure1(this,"$Closure1"));
}
}
class $App extends $AppBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## stdout.log
```log
pass ─ enums.wsim (no tests)
pass ─ enums.wsim » root/env0/test:inflight
Tests 1 passed (1)
Expand Down
Loading

0 comments on commit 6d23520

Please sign in to comment.