Skip to content

Commit

Permalink
fix(amplify-nodejs-function-runtime-provider): fix lambda error format (
Browse files Browse the repository at this point in the history
#6350)

return proper error message and stack if a string error is provided return string error as is

fix #5553
  • Loading branch information
SwaySway committed Jan 14, 2021
1 parent b2e2dd0 commit 0cf5282
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 21 deletions.
Expand Up @@ -33,3 +33,11 @@ module.exports.callbackHandler = async (event, context, callback) => {
module.exports.nonAsyncHandler = () => {
return 'foo';
};

module.exports.undefinedVariableHandler = (event, context, callback) => {
console.log(undedvar);
};

module.exports.stringErrorHandler = (event, context, callback) => {
throw 'string';
};
@@ -1,10 +1,9 @@
import * as execa from 'execa';
import { invoke } from '../../utils/invoke';
import { InvokeOptions } from '../../utils/invokeOptions';
import { InvokeOptions } from '../../utils/invokeUtils';

jest.mock('execa');
const execa_mock = execa as jest.Mocked<typeof execa>;

class ExecaChildProcessMock {
public stdout = {
on: jest.fn(),
Expand Down Expand Up @@ -213,4 +212,4 @@ describe('invoke', () => {
await expect(promise).rejects.toEqual(error);
});
});
});
});
@@ -0,0 +1,40 @@
import * as execa from 'execa';
import path from 'path';
import { invoke } from '../../utils/invoke';

jest.setTimeout(60000);
jest.mock('../../utils/invokeUtils', () => ({
...(jest.requireActual('../../utils/invokeUtils') as any),
getLambdaChildProcess: jest.fn().mockImplementation((environment: any, functionName: string = 'execute.js') => {
return execa.node(path.join(__dirname, '..', '..', '..', 'lib', 'utils', functionName), [], {
env: environment || {},
});
})
}));

describe('test invoke with execute', () => {
it('should fail with proper error', async () => {
await expect(invoke({
packageFolder: __dirname,
handler: 'handlers.undefinedVariableHandler',
event: '{}',
environment: {}
})).rejects.toMatchObject({
message: 'undedvar is not defined',
stack: expect.stringContaining('ReferenceError: undedvar is not defined'),
type: 'Lambda:Unhandled'
})
});

it('should fail with string error', async () => {
await expect(invoke({
packageFolder: __dirname,
handler: 'handlers.stringErrorHandler',
event: '{}',
environment: {}
})).rejects.toMatchObject({
type: 'Lambda:Unhandled',
message: 'Unknown Error'
});
});
});
@@ -1,5 +1,5 @@
import { existsSync } from 'fs-extra';
import { InvokeOptions } from './invokeOptions';
import { InvokeOptions } from './invokeUtils';
import path from 'path';
import _ from 'lodash';
import exit from 'exit';
Expand Down Expand Up @@ -95,14 +95,12 @@ process.on('message', async options => {
process.stdout.write('\n');
process.stdout.write(JSON.stringify({ result, error: null }));
} catch (error) {
let lambdaError = typeof error === 'string' ? { message: 'Unknown Error' } : { message: error.message, stack: error.stack };
process.stdout.write('\n');
process.stdout.write(
JSON.stringify({
result: null,
error: {
type: 'Lambda:Unhandled',
message: error.message || typeof error === 'string' ? error : 'Unknown error', // In case of callback('error'), it is only a string
},
error: { type: 'Lambda:Unhandled', ...lambdaError },
}),
);
}
Expand Down
@@ -1,15 +1,11 @@
import { InvokeOptions } from './invokeOptions';
import path from 'path';
import * as execa from 'execa';
import { InvokeOptions, getLambdaChildProcess } from './invokeUtils';

// copied from amplify-util-mock with slight modifications
export function invoke(options: InvokeOptions): Promise<any> {
return new Promise((resolve, reject) => {
try {
let data: string = '';
const lambdaFn = execa.node(path.join(__dirname, 'execute.js'), [], {
env: options.environment || {},
});
const lambdaFn = getLambdaChildProcess(options.environment);
lambdaFn.stdout.on('data', msg => {
data += msg;
});
Expand Down

This file was deleted.

@@ -0,0 +1,16 @@
import path from 'path';
import * as execa from 'execa';

export type InvokeOptions = {
packageFolder: string;
handler: string;
event: string;
context?: object;
environment?: { [key: string]: string };
};

export const getLambdaChildProcess = (environment: any, functionName: string = 'execute.js'): execa.ExecaChildProcess => {
return execa.node(path.join(__dirname, functionName), [], {
env: environment || {},
});
}

0 comments on commit 0cf5282

Please sign in to comment.