From 8b43b22575bb8b9ba0913a35d600ca8692ef38ed Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 10:01:49 +0900 Subject: [PATCH 01/10] Modify arrow function and `var` to `const` --- lib/main.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/main.js b/lib/main.js index 4bbacb9d..1f1d3f71 100644 --- a/lib/main.js +++ b/lib/main.js @@ -46,27 +46,27 @@ Lambda.prototype.setup = function (program) { Lambda.prototype.run = function (program) { this._createSampleFile(program.eventFile, 'event.json') - var splitHandler = program.handler.split('.') - var filename = splitHandler[0] + '.js' - var handlername = splitHandler[1] + const splitHandler = program.handler.split('.') + const filename = splitHandler[0] + '.js' + const handlername = splitHandler[1] // Set custom environment variables if program.configFile is defined if (program.configFile) { this._setRunTimeEnvironmentVars(program) } - var handler = require(path.join(process.cwd(), filename))[handlername] - var event = require(path.join(process.cwd(), program.eventFile)) - var context = require(path.join(process.cwd(), program.contextFile)) + const handler = require(path.join(process.cwd(), filename))[handlername] + const event = require(path.join(process.cwd(), program.eventFile)) + const context = require(path.join(process.cwd(), program.contextFile)) this._runHandler(handler, event, program, context) } -Lambda.prototype._runHandler = function (handler, event, program, context) { - var startTime = new Date() - var timeout = Math.min(program.timeout, 300) * 1000 // convert the timeout into milliseconds +Lambda.prototype._runHandler = (handler, event, program, context) => { + const startTime = new Date() + const timeout = Math.min(program.timeout, 300) * 1000 // convert the timeout into milliseconds - var callback = function (err, result) { + const callback = (err, result) => { if (err) { process.exitCode = 255 console.log('Error: ' + err) @@ -82,8 +82,8 @@ Lambda.prototype._runHandler = function (handler, event, program, context) { } } - context.getRemainingTimeInMillis = function () { - var currentTime = new Date() + context.getRemainingTimeInMillis = () => { + const currentTime = new Date() return timeout - (currentTime - startTime) } From 90f2ccd62f21a9567c244d7c24b3b4506f1649b4 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 10:21:34 +0900 Subject: [PATCH 02/10] Add stderr test to `bin/node-lambda`test --- test/node-lambda.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/node-lambda.js b/test/node-lambda.js index 1800b407..3d296c15 100644 --- a/test/node-lambda.js +++ b/test/node-lambda.js @@ -18,12 +18,21 @@ describe('bin/node-lambda', () => { '--eventFile', 'event.json' ]) var stdoutString = '' + var stderrString = '' run.stdout.on('data', (data) => { stdoutString += data.toString().replace(/\r|\n/g, '') }) + run.stderr.on('data', (data) => { + stderrString += data.toString().replace(/\r|\n/g, '') + }) run.on('exit', (code) => { - assert.match(stdoutString, expectedValues.stdoutRegExp) + if (expectedValues.stdoutRegExp) { + assert.match(stdoutString, expectedValues.stdoutRegExp) + } + if (expectedValues.stderrRegExp) { + assert.match(stderrString, expectedValues.stderrRegExp) + } assert.equal(code, expectedValues.exitCode) done() }) From c61c4a3bbd9de10599fb6dc330835bda81bc27b2 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 10:22:54 +0900 Subject: [PATCH 03/10] Add 'Runtime is not supported' test --- test/node-lambda.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/node-lambda.js b/test/node-lambda.js index 3d296c15..0f3eafba 100644 --- a/test/node-lambda.js +++ b/test/node-lambda.js @@ -145,5 +145,29 @@ describe('bin/node-lambda', () => { }) }) }) + + describe('node-lambda run (Runtime is not supported)', () => { + const eventObj = { + asyncTest: false, + callbackWaitsForEmptyEventLoop: true // True is the default value of Lambda + } + + before(() => { + process.env.AWS_RUNTIME = 'test' + }) + after(() => { + process.env.AWS_RUNTIME = 'nodejs6.10' + }) + + it('`node-lambda run` exitCode is `254` (callback(null))', (done) => { + _generateEventFile(Object.assign(eventObj, { + callbackCode: 'callback(null);' + })) + _testMain({ + stderrRegExp: /^Runtime \[test\] is not supported\.$/, + exitCode: 254 + }, done) + }) + }) }) }) From 19b1f38b3a11c1a9cc19df627a7236c710e496f9 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 10:23:47 +0900 Subject: [PATCH 04/10] Fix timing to check Runtime If it is an unsupported Runtime, it ends with an error. Therefore, I checked it at an early stage --- lib/main.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/main.js b/lib/main.js index 1f1d3f71..03866b0c 100644 --- a/lib/main.js +++ b/lib/main.js @@ -45,6 +45,11 @@ Lambda.prototype.setup = function (program) { } Lambda.prototype.run = function (program) { + if (['nodejs4.3', 'nodejs6.10'].indexOf(program.runtime) === -1) { + console.error(`Runtime [${program.runtime}] is not supported.`) + process.exit(254) + } + this._createSampleFile(program.eventFile, 'event.json') const splitHandler = program.handler.split('.') const filename = splitHandler[0] + '.js' @@ -87,10 +92,6 @@ Lambda.prototype._runHandler = (handler, event, program, context) => { return timeout - (currentTime - startTime) } - if (['nodejs4.3', 'nodejs6.10'].indexOf(program.runtime) === -1) { - console.error(`Runtime [${program.runtime}] is not supported.`) - process.exit(254) - } handler(event, context, callback) } From e324cf330a47f0c730cc7b6ef18787ce6d88bce9 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 19:06:36 +0900 Subject: [PATCH 05/10] Modify from `var` to `let` --- test/node-lambda.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/node-lambda.js b/test/node-lambda.js index 0f3eafba..dfa50674 100644 --- a/test/node-lambda.js +++ b/test/node-lambda.js @@ -17,8 +17,8 @@ describe('bin/node-lambda', () => { '--handler', '__test.handler', '--eventFile', 'event.json' ]) - var stdoutString = '' - var stderrString = '' + let stdoutString = '' + let stderrString = '' run.stdout.on('data', (data) => { stdoutString += data.toString().replace(/\r|\n/g, '') }) From d5fc8686706944f62520adc6774803ee89093f23 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 19:07:50 +0900 Subject: [PATCH 06/10] Add function to execute multiple events --- lib/main.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/main.js b/lib/main.js index 03866b0c..26ffdd94 100644 --- a/lib/main.js +++ b/lib/main.js @@ -95,6 +95,47 @@ Lambda.prototype._runHandler = (handler, event, program, context) => { handler(event, context, callback) } +Lambda.prototype._runMultipleHandlers = (events) => { + console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +The event received by AWS Lambda is basically Object. +For \`node-lambda\`, if event.json is an array, +constit is treated as multiple events and run multiple times. +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +`) + + const _argv = process.argv + const eventFileOptionIndex = (() => { + const index = _argv.indexOf('-j') + if (index >= 0) return index + return _argv.indexOf('--eventFile') + })() + + // In order to reproduce the movement of callbackWaitsForEmptyEventLoop, + // we are going to execute `node-lambda run`. + events.forEach((event, i) => { + const tmpEventFile = `.${i}_tmp_event.json` + const command = () => { + if (eventFileOptionIndex === -1) { + return _argv.concat(['-j', tmpEventFile]).join(' ') + } + _argv[eventFileOptionIndex + 1] = tmpEventFile + return _argv.join(' ') + } + + fs.writeFileSync(tmpEventFile, JSON.stringify(event)) + exec(command(), { + maxBuffer: maxBufferSize, + env: process.env + }, (err, stdout, stderr) => { + console.log('>>> Event:', event, '<<<') + if (err) console.error(err) + console.log(stdout) + console.log(stderr) + fs.unlinkSync(tmpEventFile) + }) + }) +} + Lambda.prototype._params = function (program, buffer) { var params = { FunctionName: program.functionName + From 3a2d77fdbdf36739db3d74f6912c455e05db5791 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 19:08:20 +0900 Subject: [PATCH 07/10] Update to change processing according to event --- lib/main.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/main.js b/lib/main.js index 26ffdd94..4af244c0 100644 --- a/lib/main.js +++ b/lib/main.js @@ -64,7 +64,10 @@ Lambda.prototype.run = function (program) { const event = require(path.join(process.cwd(), program.eventFile)) const context = require(path.join(process.cwd(), program.contextFile)) - this._runHandler(handler, event, program, context) + if (Object.prototype.toString.call(event) !== '[object Array]') { + return this._runHandler(handler, event, program, context) + } + this._runMultipleHandlers(event) } Lambda.prototype._runHandler = (handler, event, program, context) => { From ae3ebdb500eaf20391eccab292c8c1025b54f631 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 19:10:39 +0900 Subject: [PATCH 08/10] Add multiple event test --- test/node-lambda.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/node-lambda.js b/test/node-lambda.js index dfa50674..2b90d9fb 100644 --- a/test/node-lambda.js +++ b/test/node-lambda.js @@ -169,5 +169,32 @@ describe('bin/node-lambda', () => { }, done) }) }) + + describe('node-lambda run (Multiple events))', () => { + const eventObj = [{ + asyncTest: false, + callbackWaitsForEmptyEventLoop: true, + callbackCode: 'callback(null);', + no: 1 + }, { + asyncTest: false, + callbackWaitsForEmptyEventLoop: true, + callbackCode: 'callback(null);', + no: 2 + }, { + asyncTest: false, + callbackWaitsForEmptyEventLoop: true, + callbackCode: 'callback(null);', + no: 3 + }] + + it('`node-lambda run` exitCode is `0`', (done) => { + _generateEventFile(eventObj) + _testMain({ + stdoutRegExp: / no: [123] .+ no: [123] .+ no: [123] .+Success:/, + exitCode: 0 + }, done) + }) + }) }) }) From c0a43cf1a5e75d7c5d3e0258a93b8bbedd3a3a94 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 19:34:48 +0900 Subject: [PATCH 09/10] Modify comment the movement -> the logic --- lib/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.js b/lib/main.js index 4af244c0..39b6632d 100644 --- a/lib/main.js +++ b/lib/main.js @@ -113,7 +113,7 @@ constit is treated as multiple events and run multiple times. return _argv.indexOf('--eventFile') })() - // In order to reproduce the movement of callbackWaitsForEmptyEventLoop, + // In order to reproduce the logic of callbackWaitsForEmptyEventLoop, // we are going to execute `node-lambda run`. events.forEach((event, i) => { const tmpEventFile = `.${i}_tmp_event.json` From 5e9e672821f97e631fc9c9abd7049ea72cf2be90 Mon Sep 17 00:00:00 2001 From: abetomo Date: Thu, 8 Jun 2017 19:38:23 +0900 Subject: [PATCH 10/10] Update message text --- lib/main.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/main.js b/lib/main.js index 39b6632d..748dbfcb 100644 --- a/lib/main.js +++ b/lib/main.js @@ -100,9 +100,9 @@ Lambda.prototype._runHandler = (handler, event, program, context) => { Lambda.prototype._runMultipleHandlers = (events) => { console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -The event received by AWS Lambda is basically Object. -For \`node-lambda\`, if event.json is an array, -constit is treated as multiple events and run multiple times. +Usually you will receive a single Object from AWS Lambda. +We added support for event.json to contain an array, +so you can easily test run multiple events. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! `)