Skip to content
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

IH: program-boilerplate: refactor programTrigger Error handling; repl… #139

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions packages/program-boilerplate/__tests__/jsonata.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as jsonata from "jsonata";
import { setLogLevel } from "../src/logger";
import { silenceLogger } from "../src/logger";
import { timeboxExpression, safeJsonata } from "../src/jsonata";

describe("#timeboxExpression", () => {
const infExpr = jsonata("( $inf := function(){$inf()}; $inf())");

test("infinite loops throw error", () => {
timeboxExpression(infExpr);
const infExpr = jsonata("( $inf := function($n){$n+$inf($n-1)}; $inf(5))");
// maxDepth will fail first
timeboxExpression(infExpr, 10000, 5);

let error: any;
expect(() => {
Expand All @@ -17,13 +17,36 @@ describe("#timeboxExpression", () => {
throw e;
}
}).toThrowError();
expect(error!.code === "U1001" || error!.code === "U1002").toBe(true);
}, 7000);
expect(error!.code).toBe("U1001");
expect(error!.message).toBe(
"Stack overflow error: Check for non-terminating recursive function. Consider rewriting as tail-recursive."
);
});

test("timeouts loops throw error", () => {
const infExpr = jsonata("( $inf := function(){$inf()}; $inf())");
// timeout will fail first
timeboxExpression(infExpr, 30, 10000);

let error: any;
expect(() => {
try {
infExpr.evaluate(undefined);
} catch (e) {
error = e;
throw e;
}
}).toThrowError();
expect(error!.code).toBe("U1002");
expect(error!.message).toBe(
"Expression evaluation timeout: Check for infinite loop"
);
});
});

describe("#safeJsonata", () => {
beforeAll(() => {
setLogLevel("error");
silenceLogger();
});

const infExpr = "( $inf := function(){$inf()}; $inf())";
Expand Down
62 changes: 49 additions & 13 deletions packages/program-boilerplate/__tests__/trigger.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { silenceLogger } from "../src/logger";
import Transaction from "../src/transaction";
import { triggerProgram } from "../src/trigger";
import {
Expand All @@ -8,14 +9,10 @@ import {
Program,
} from "../src/types/rpc";

const cachedLogger = console.log;
beforeAll(() => {
console.log = () => {};
});
afterAll(() => {
console.log = cachedLogger;
});
describe("triggerProgram", () => {
beforeAll(() => {
silenceLogger();
});
describe("body has invalid messageType", () => {
const testBody = {
messageType: "NOT_YET_ADDED_TO_BOILERPLATE",
Expand All @@ -30,6 +27,7 @@ describe("triggerProgram", () => {
);
expect(result).toStrictEqual({
json: {
error: "Unrecognized messageType",
message: `Unrecognized messageType NOT_YET_ADDED_TO_BOILERPLATE`,
},
code: 501,
Expand Down Expand Up @@ -92,7 +90,6 @@ describe("triggerProgram", () => {
test("PROGRAM_INTROSPECTION errors", () => {
const spy = jest.fn((...args) => {
const error = new Error();
error.stack = undefined;
throw error;
});
const spyingProgram = {
Expand All @@ -108,7 +105,7 @@ describe("triggerProgram", () => {
expect(result).toStrictEqual({
json: {
error: "An error occurred in a webtask",
message: undefined,
message: "An unspecified error occurred in the program",
},
code: 500,
});
Expand Down Expand Up @@ -152,7 +149,6 @@ describe("triggerProgram", () => {
test("PROGRAM_TRIGGER errors", () => {
const spy = jest.fn((...args) => {
const error = new Error();
error.stack = undefined;
throw error;
});
const spyingProgram = {
Expand All @@ -162,7 +158,7 @@ describe("triggerProgram", () => {
expect(result).toStrictEqual({
json: {
error: "An error occurred in a webtask",
message: undefined,
message: "An unspecified error occurred in the program",
},
code: 500,
});
Expand Down Expand Up @@ -255,7 +251,48 @@ describe("triggerProgram", () => {
});
});

test.skip("PROGRAM_VALIDATION errors - NEEDS IMPLEMENTATION", () => {});
test("PROGRAM_VALIDATION missing validation handler", () => {
const spyingProgram = {
PROGRAM_VALIDATION: {},
};
const result = triggerProgram(testBody, spyingProgram);

expect(result).toStrictEqual({
json: {
error: "An error occurred in a webtask",
message: "Requirement handler for key rule1 not implemented",
},
code: 501,
});
});

test("PROGRAM_VALIDATION validation handler throws error", () => {
const spy1 = (jest.fn(
() => 1
) as unknown) as RequirementValidationHandler;
const spy2 = (jest.fn(() => {
throw new Error();
}) as unknown) as RequirementValidationHandler;
const spy3 = (jest.fn(
() => 3
) as unknown) as RequirementValidationHandler;
const spyingProgram = {
PROGRAM_VALIDATION: {
rule1: spy1,
rule2: spy2,
rule3: spy3,
},
};
const result = triggerProgram(testBody, spyingProgram);

expect(result).toStrictEqual({
json: {
error: "An error occurred in a webtask",
message: "Requirement handler for key rule2 failed",
},
code: 501,
});
});
});

describe("body has messageType PROGRAM_TRIGGER_VARIABLES_SCHEMA_REQUEST", () => {
Expand Down Expand Up @@ -300,7 +337,6 @@ describe("triggerProgram", () => {
test("PROGRAM_TRIGGER_VARIABLES_SCHEMA_REQUEST errors", () => {
const spy = jest.fn((...args) => {
const error = new Error();
error.stack = undefined;
throw error;
});
const spyingProgram = {
Expand Down
15 changes: 5 additions & 10 deletions packages/program-boilerplate/__tests__/webtask.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import * as request from "supertest";
import { webtask } from "../src/index";
import { silenceLogger } from "../src/logger";

describe("webtask express wrapper functionality", () => {
// hopefully can remove this once the console logs are cleaned up in trigger.ts
const cachedLogger = console.log;
beforeAll(() => {
console.log = () => {};
});
afterAll(() => {
console.log = cachedLogger;
silenceLogger();
});

const testSuccessBody = {
messageType: "PROGRAM_INTROSPECTION" as "PROGRAM_INTROSPECTION",
template: { test: "template" },
Expand Down Expand Up @@ -49,9 +46,7 @@ describe("webtask express wrapper functionality", () => {

const successSpy = jest.fn((...args) => newTemplate);
const errorSpy = jest.fn((...args) => {
const error = new Error();
error.stack = "message";
throw error;
throw new Error();
});

const testProgram = {
Expand All @@ -77,7 +72,7 @@ describe("webtask express wrapper functionality", () => {
.send(testErrorBody);
expect(response.body).toStrictEqual({
error: "An error occurred in a webtask",
message: "message",
message: "An unspecified error occurred in the program",
});
expect(response.status).toBe(500);
});
Expand Down
167 changes: 0 additions & 167 deletions packages/program-boilerplate/src/conversion.ts

This file was deleted.

Loading