10000 lambda: (close #5) fix to accept all return types · brpapa/recursion-tree-visualizer@ae81754 · GitHub
[go: up one dir, main page]

Skip to content

Commit ae81754

Browse files
committed
lambda: (close #5) fix to accept all return types
1 parent 0f08783 commit ae81754

File tree

10 files changed

+73
-45
lines changed

10 files changed

+73
-45
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ In the `packages/web` directory, run:
2424

2525
```bash
2626
# to install all dependencies
27-
> npm install
27+
$ npm install
2828

2929
# to run the app on http://localhost:3000
30-
> npm run start
30+
$ npm run start
3131
```
3232

3333
### Lambda
@@ -38,13 +38,13 @@ In the `packages/lambda` directory, run:
3838

3939
```bash
4040
# build your local image
41-
> docker build --tag dev-image .
41+
$ docker build --tag dev-image .
4242

4343
# create and run a container using AWS RIE as executable to emulate a server for your lambda function
44-
> docker run --rm -p 8080:8080 dev-image
44+
$ docker run --rm -p 8080:8080 dev-image
4545

4646
# make a http request to your function, passing event with the -d in body field (escaped json)
47-
> curl -XPOST "http://localhost:8080/2015-03-31/functions/function/invocations" -d '{"body":"{}"}'
47+
$ curl -XPOST "http://localhost:8080/2015-03-31/functions/function/invocations" -d '{"body":"{}"}'
4848
```
4949

5050
## Deploy to production

packages/lambda/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"scripts": {
88
"build": "npx tsc",
99
"test": "DEBUG='app:*,test:*' npx jest --config jest.config.js",
10-
"test:cov": "npx jest --config jest.config.js --coverage"
10+
"test:cov": "npx jest --config jest.config.js --coverage",
11+
"typesync": "npx typesync"
1112
},
1213
"dependencies": {
1314
"debug": "^2.6.9",

packages/lambda/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { APIGatewayProxyHandler } from 'aws-lambda'
22
import debug from 'debug'
33
import buildRunner from './runner'
4-
import { TreeViewerData } from './types'
54
import { safeStringify } from './utils/safe-json'
65
import { validateAPIGatewayProxyEvent } from './validations/event'
76

@@ -30,7 +29,7 @@ export const handler: APIGatewayProxyHandler = async (event) => {
3029
}
3130
}
3231

33-
const ok = (body: TreeViewerData) => result(200, body)
32+
const ok = (body: any) => result(200, body)
3433
const badRequest = (reason: string) => result(400, { reason })
3534
const unprocessableEntity = (reason: string) => result(422, { reason })
3635
const internalServerError = (reason: string) => result(500, { reason })

packages/lambda/src/runner/steps/recursion-tree.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ export default async function generateRecursionTree(
4040
const declare = buildDeclare(lang)
4141

4242
try {
43-
const { stdout: rawStdout } = await exec(declare.command(sourceCode), {
44-
timeout: CHILD_PROCESS_TIMEOUT_MS,
45-
})
43+
const { stdout: rawStdout } = await exec(
44+
declare.command(sourceCode),
45+
{ timeout: CHILD_PROCESS_TIMEOUT_MS }
46+
) // throws exceptions if not output a stdout
47+
// log(rawStdout)
48+
4649
const validatedStdout = validateChildProcessStdout(rawStdout)
4750
if (validatedStdout.isError())
48-
throw new Error(`Fail to validate \`rawStdout\`:\n${validatedStdout.value}`)
51+
throw new Error(`Fail to deserialize the \`rawStdout\` object:\n${validatedStdout.value}`)
4952

5053
const stdout = validatedStdout.value
5154
if (stdout.errorValue !== null)

packages/lambda/src/runner/steps/tree-viewer-data.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -121,36 +121,29 @@ const initialEdgesData = (vertices: Vertices): EdgesData => {
121121

122122
const edgeKey = (u: number, v: number) => JSON.stringify([u, v])
123123

124-
const MAX_NUMBER_TO_FIT_ON_SCREEN = 1e5
124+
const MAX_NUMBER_THAT_FIT_ON_SCREEN = 1e5
125125

126-
const labelizeEdgeWeight = (w?: number) => {
127-
if (w === null)
128-
throw new Error(
129-
'The `w` argument can not be null. Probabily there was an error when parsing a function call result to JSON'
130-
)
126+
const labelizeEdgeWeight = (w: any | undefined) => {
131127
if (w === undefined) return undefined
132-
return labelizeNumber(w)
128+
return labelize(w)
133129
}
134130

135-
const labelizeVerticeArgs = (verticeArgs?: any[]) => {
136-
if (verticeArgs === null) throw new Error('`verticeArgs` can not be null')
131+
const labelizeVerticeArgs = (verticeArgs: any[] | undefined) => {
137132
if (verticeArgs === undefined) return undefined
138-
return verticeArgs
139-
.map((arg) =>
140-
JSON.stringify(arg, (_key: string, value: any) => {
141-
if (typeof value === 'number')
142-
return labelizeNumber(value)
143-
return value
144-
}).replace(/"/g, '')
145-
)
146-
.join(',')
133+
return verticeArgs.map(labelize).join(',')
134+
}
135+
136+
const labelize = (value: any) => {
137+
return JSON.stringify(value, (_: string, v: any) =>
138+
typeof v === 'number' ? labelizeNumber(v) : v
139+
).replace(/"/g, '')
147140
}
148141

149142
const labelizeNumber = (n: number) => {
150143
if (n === Infinity) return '∞'
151144
if (n === -Infinity) return '-∞'
152145
if (Number.isNaN(n)) return 'NaN'
153-
return n > MAX_NUMBER_TO_FIT_ON_SCREEN ? n.toExponential(2) : n.toString()
146+
return n > MAX_NUMBER_THAT_FIT_ON_SCREEN ? n.toExponential(2) : n.toString()
154147
}
155148

156149
const TRANSLATED_BY: Point = [50, 50]

packages/lambda/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export type Vertices = Record<
1010
/** vertices[u].argsList: array de params values do vértice u */
1111
argsList: any[]
1212
/** vertices[u].adjList: [{v, w}, ...], sendo u -w-> v, onde w é o resultado de fn(...argsList[u]) */
13-
adjList: { childId: number; weight?: number }[]
13+
adjList: { childId: number; weight?: any }[]
1414
memoized: boolean
1515
}
1616
>

packages/lambda/src/validations/stdout.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ChildProcessStdout } from '../types'
33
import { Either, error, success } from '../utils/either'
44
import { safeParse } from '../utils/safe-json'
55

6+
/** Runtime valition of the stdout received by child process, returning the parsed stdout */
67
export const validateChildProcessStdout = (
78
rawStdout: string
89
): Either<string, ChildProcessStdout> => {
@@ -13,13 +14,13 @@ export const validateChildProcessStdout = (
1314
.pattern(
1415
/^\d+$/,
1516
joi.object({
16-
argsList: joi.array().items(joi.any()).required(),
17+
argsList: joi.array().items(joi.any()).required().not(null),
1718
adjList: joi
1819
.array()
1920
.items(
2021
joi.object({
2122
childId: joi.number().required(),
22-
weight: joi.number().allow(Infinity, -Infinity, NaN),
23+
weight: joi.any().not(null), // if null, probably there was an error when parsing a function call result to JSON
2324
})
2425
)
2526
.required(),

packages/lambda/tests/runner/index.test.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe('Getting tree viewer data from function data', () => {
4848
}
4949
)
5050
})
51-
describe('The full pipeline should run sucessfully', () => {
51+
describe('The full pipeline should run successfully', () => {
5252
test('For `node` language', async () => {
5353
const run = buildRunner('node', { memoize: true })
5454
const treeViewerData = await run({
@@ -72,4 +72,29 @@ describe('Getting tree viewer data from function data', () => {
7272
// log(treeViewerData.value?.logs)
7373
})
7474
})
75+
describe('Should be acceptable a function with different return types', () => {
76+
test('For `python` language', async () => {
77+
const run = buildRunner('python', { memoize: false })
78+
const treeViewerData = await run({
79+
globalVariables: [
80+
{ name: 'steps', value: '3' },
81+
{ name: 'arrLen', value: '2' },
82+
],
83+
params: [
84+
{ name: 'idx', initialValue: '0' },
85+
{ name: 'step', initialValue: 'steps' },
86+
],
87+
body: [
88+
'if idx < 0 or idx >= arrLen:',
89+
' return 0',
90+
'if 0 == step:',
91+
' return 0 == idx',
92+
'return(fn(idx - 1, step - 1) + fn(idx + 1, step - 1) + fn(idx, step - 1)) % 1000000007',
93+
].join('\n')
94+
})
95+
expect(treeViewerData.isSuccess()).toBeTruthy()
96+
// if (treeViewerData.isSuccess())
97+
// log(treeViewerData.value)
98+
})
99+
})
75100
})

packages/lambda/tests/runner/recursion-tree.test.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import translateToPlainCode from '../../src/runner/steps/plain-code'
1111

1212
const log = debug('test:runner:recursion-tree')
1313

14-
const successCases: Record<SupportedLanguages, FunctionData>[] = [
14+
type TestCase = {
15+
[key in SupportedLanguages]: FunctionData
16+
}
17+
18+
const successCases: TestCase[] = [
1519
{
1620
node: {
1721
globalVariables: [{ name: 'arr', value: '[1, 2, 3]' }],
@@ -277,7 +281,7 @@ const successCases: Record<SupportedLanguages, FunctionData>[] = [
277281
},
278282
},
279283
]
280-
const errorCases: Record<SupportedLanguages, FunctionData>[] = [
284+
const errorCases: TestCase[] = [
281285
{
282286
node: {
283287
body: 'return fn()',
@@ -334,18 +338,19 @@ describe('Getting recursion tree from plain code', () => {
334338
[successCases[5], 'Fast Power'],
335339
])(
336340
'Success test case %#: %c%s',
337-
(tc: Record<SupportedLanguages, FunctionData>) => {
341+
(tc: TestCase) => {
338342
test(`Should return success object for 'node' language`, async () => {
339-
const res = await buildRecursionTreeForNode(tc.node)
343+
const res = await buildRecursionTreeForNode(tc.node!)
340344
expect(res.isSuccess()).toBeTruthy()
341345
})
342346
test(`Should return success object for 'python' language`, async () => {
343-
const res = await buildRecursionTreeForPython(tc.python)
347+
const res = await buildRecursionTreeForPython(tc.python!)
344348
expect(res.isSuccess()).toBeTruthy()
345349
})
346350
test('Should return exactly the same object between all supported languages', async () => {
347-
const nodeRes = await buildRecursionTreeForNode(tc.node)
348-
const pythonRes = await buildRecursionTreeForPython(tc.python)
351+
const nodeRes = await buildRecursionTreeForNode(tc.node);
352+
const pythonRes = await buildRecursionTreeForPython(tc.python);
353+
349354
expect(nodeRes.value).toEqual(pythonRes.value)
350355
})
351356
}
@@ -359,16 +364,16 @@ describe('Getting recursion tree from plain code', () => {
359364
])(
360365
'Error test case %#: %c%s',
361366
(
362-
tc: Record<SupportedLanguages, FunctionData>,
367+
tc: TestCase,
363368
expectedError: ChildProcessError | TreeError
364369
) => {
365370
test(`Should return the expected error type for 'node' language`, async () => {
366-
const res = await buildRecursionTreeForNode(tc.node)
371+
const res = await buildRecursionTreeForNode(tc.node!)
367372
expect(res.isError()).toBeTruthy()
368373
if (res.isError()) expect(res.value.type).toEqual(expectedError)
369374
})
370375
test(`Should return the expected error type for 'python' language`, async () => {
371-
const res = await buildRecursionTreeForPython(tc.python)
376+
const res = await buildRecursionTreeForPython(tc.python!)
372377
expect(res.isError()).toBeTruthy()
373378
if (res.isError()) {
374379
log('Error returned: %O', res.value)

packages/web/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SKIP_PREFLIGHT_CHECK=true

0 commit comments

Comments
 (0)
0