test: add addon tests for RegisterSignalHandler()

Ensure coverage for the different combinations of arguments.

PR-URL: https://github.com/nodejs/node/pull/27775
Refs: https://github.com/nodejs/node/pull/27246
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
Anna Henningsen 2019-05-20 02:05:20 +02:00
parent 89b32378c8
commit 039cfdc838
No known key found for this signature in database
GPG Key ID: 9C63F3A6CD2AD8F9
4 changed files with 108 additions and 0 deletions

View File

@ -0,0 +1,7 @@
'use strict';
require('../common');
// This is a sibling test to test/addons/register-signal-handler/
process.env.ALLOW_CRASHES = true;
require('../addons/register-signal-handler/test');

View File

@ -0,0 +1,36 @@
#ifndef _WIN32
#include <node.h>
#include <v8.h>
#include <uv.h>
#include <assert.h>
#include <unistd.h>
using v8::Boolean;
using v8::FunctionCallbackInfo;
using v8::Int32;
using v8::Value;
void Handler(int signo, siginfo_t* siginfo, void* ucontext) {
char signo_char = signo;
int written;
do {
written = write(1, &signo_char, 1); // write() is signal-safe.
} while (written == -1 && errno == EINTR);
assert(written == 1);
}
void RegisterSignalHandler(const FunctionCallbackInfo<Value>& args) {
assert(args[0]->IsInt32());
assert(args[1]->IsBoolean());
int32_t signo = args[0].As<Int32>()->Value();
bool reset_handler = args[1].As<Boolean>()->Value();
node::RegisterSignalHandler(signo, Handler, reset_handler);
}
NODE_MODULE_INIT() {
NODE_SET_METHOD(exports, "registerSignalHandler", RegisterSignalHandler);
}
#endif // _WIN32

View File

@ -0,0 +1,9 @@
{
'targets': [
{
'target_name': 'binding',
'sources': [ 'binding.cc' ],
'includes': ['../common.gypi'],
}
]
}

View File

@ -0,0 +1,56 @@
'use strict';
const common = require('../../common');
if (common.isWindows)
common.skip('No RegisterSignalHandler() on Windows');
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const { signals } = require('os').constants;
const { spawnSync } = require('child_process');
const bindingPath = path.resolve(
__dirname, 'build', common.buildType, 'binding.node');
if (!fs.existsSync(bindingPath))
common.skip('binding not built yet');
const binding = require(bindingPath);
if (process.argv[2] === 'child') {
const signo = +process.argv[3];
const reset = process.argv[4] === 'reset';
const count = +process.argv[5];
binding.registerSignalHandler(signo, reset);
for (let i = 0; i < count; i++)
process.kill(process.pid, signo);
return;
}
for (const raiseSignal of [ 'SIGABRT', 'SIGSEGV' ]) {
const signo = signals[raiseSignal];
for (const { reset, count, stderr, code, signal } of [
{ reset: true, count: 1, stderr: [signo], code: 0, signal: null },
{ reset: true, count: 2, stderr: [signo], code: null, signal: raiseSignal },
{ reset: false, count: 1, stderr: [signo], code: 0, signal: null },
{ reset: false, count: 2, stderr: [signo, signo], code: 0, signal: null }
]) {
// We do not want to generate core files when running this test as an
// addon test. We require this file as an abort test as well, though,
// with ALLOW_CRASHES set.
if (signal !== null && !process.env.ALLOW_CRASHES)
continue;
// reset_handler does not work with SIGSEGV.
if (reset && signo === signals.SIGSEGV)
continue;
const args = [__filename, 'child', signo, reset ? 'reset' : '', count];
console.log(`Running: node ${args.join(' ')}`);
const result = spawnSync(
process.execPath, args, { stdio: ['inherit', 'pipe', 'inherit'] });
assert.strictEqual(result.status, code);
assert.strictEqual(result.signal, signal);
assert.deepStrictEqual([...result.stdout], stderr);
}
}