From df5edc83d3c5cb48baaed9785344453035a22db9 Mon Sep 17 00:00:00 2001 From: hobbyquaker Date: Sun, 26 Aug 2018 11:06:32 +0200 Subject: [PATCH] simple webserver and cam tests --- package-lock.json | 205 +++++++++++++++++++++++++++++++-------------- package.json | 1 + test/test-cam.json | 57 +++++++++++++ test/test.js | 151 +++++++++++++++++++++++++-------- 4 files changed, 313 insertions(+), 101 deletions(-) create mode 100644 test/test-cam.json diff --git a/package-lock.json b/package-lock.json index 1dab801..c2377d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -312,9 +312,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "babel-code-frame": { "version": "6.26.0", @@ -545,8 +545,9 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "bootstrap": { @@ -743,7 +744,7 @@ "dev": true, "requires": { "async": "2.6.0", - "request": "2.83.0", + "request": "2.88.0", "yargs": "7.1.0" }, "dependencies": { @@ -919,17 +920,72 @@ "supports-color": "4.4.0" } }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, "lodash": { "version": "4.17.5", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", "integrity": "sha1-maktZcAnLevoyWtgV7yPv6O+1RE=", "dev": true }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.19", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "1.4.1" + } } } }, @@ -1117,9 +1173,9 @@ "dev": true }, "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { "delayed-stream": "1.0.0" } @@ -1404,6 +1460,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, "requires": { "boom": "5.2.0" }, @@ -1411,9 +1468,10 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } } } @@ -2566,13 +2624,13 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "combined-stream": "1.0.6", + "mime-types": "2.1.19" } }, "forwarded": { @@ -2749,7 +2807,7 @@ "gtoken": "1.2.3", "jws": "3.1.5", "lodash.noop": "3.0.1", - "request": "2.83.0" + "request": "2.88.0" } }, "google-p12-pem": { @@ -2819,7 +2877,7 @@ "google-p12-pem": "0.1.2", "jws": "3.1.5", "mime": "1.4.1", - "request": "2.83.0" + "request": "2.88.0" } }, "hap-client": { @@ -3015,9 +3073,9 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", "requires": { "ajv": "5.5.2", "har-schema": "2.0.0" @@ -3102,11 +3160,12 @@ "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "dev": true, "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", - "hoek": "4.2.0", + "hoek": "4.2.1", "sntp": "2.1.0" } }, @@ -3128,9 +3187,10 @@ } }, "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "dev": true }, "homebridge-camera-ffmpeg": { "version": "0.1.8", @@ -4119,16 +4179,16 @@ "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=" }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", "requires": { - "mime-db": "1.30.0" + "mime-db": "1.35.0" } }, "mimic-fn": { @@ -6529,9 +6589,9 @@ } }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "obj-ease": { "version": "1.0.1", @@ -7028,8 +7088,7 @@ "psl": { "version": "1.1.29", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", - "dev": true + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" }, "pump": { "version": "2.0.1", @@ -7239,32 +7298,47 @@ "dev": true }, "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { "aws-sign2": "0.7.0", - "aws4": "1.6.0", + "aws4": "1.8.0", "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", + "combined-stream": "1.0.6", + "extend": "3.0.2", "forever-agent": "0.6.1", - "form-data": "2.3.1", - "har-validator": "5.0.3", - "hawk": "6.0.2", + "form-data": "2.3.2", + "har-validator": "5.1.0", "http-signature": "1.2.0", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", + "mime-types": "2.1.19", + "oauth-sign": "0.9.0", "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "uuid": "3.3.2" + }, + "dependencies": { + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "require-directory": { @@ -7700,9 +7774,10 @@ "sntp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "sodium": { @@ -7942,9 +8017,10 @@ } }, "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true }, "strip-ansi": { "version": "4.0.0", @@ -8118,10 +8194,11 @@ } }, "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "requires": { + "psl": "1.1.29", "punycode": "1.4.1" } }, @@ -8440,9 +8517,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ=" + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "uuidv5": { "version": "1.0.0", diff --git a/package.json b/package.json index 7055deb..ec86df0 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "hap-client-cli": "latest", "mocha": "latest", "nyc": "latest", + "request": "^2.88.0", "should": "latest", "stream-splitter": "latest", "xo": "latest" diff --git a/test/test-cam.json b/test/test-cam.json new file mode 100644 index 0000000..3209679 --- /dev/null +++ b/test/test-cam.json @@ -0,0 +1,57 @@ +{ + "CamWhz": { + "id": "CamWhz", + "name": "Cam Wohnzimmer", + "payloadIdentify": "", + "services": [ + { + "name": "CamWhz", + "service": "CameraRTSPStreamManagement", + "topic": {}, + "payload": {}, + "config": { + "source": "-rtsp_transport tcp -re -i rtsp://use:pass@cam-whz", + "stillImageSource": "-i https://user:passcam-whz/snap.jpg?JpegSize=M", + "maxStreams": 2, + "maxWidth": 1920, + "maxHeight": 1080, + "maxFPS": 30, + "maxBitrate": 300, + "vcodec": "libx264", + "audio": false, + "packetSize": 1316, + "debug": false, + "videoProcessor": "ffmpeg" + }, + "props": {} + } + ], + "payload": {}, + "config": {} + }, + "Switch": { + "id": "Switch", + "name": "Switch", + "category": 8, + "payloadIdentify": "", + "services": [ + { + "name": "Switch", + "service": "Switch", + "topic": { + "setOn": "test/switch/set", + "statusOn": "test/switch/status" + }, + "json": { + "statusOn": "on" + }, + "payload": { + "onFalse": false, + "onTrue": true + }, + "config": {}, + "props": {} + } + ] + } +} \ No newline at end of file diff --git a/test/test.js b/test/test.js index e4f1a7c..bcf8874 100644 --- a/test/test.js +++ b/test/test.js @@ -6,6 +6,7 @@ require('should'); const cp = require('child_process'); const path = require('path'); +const request = require('request'); const streamSplitter = require('stream-splitter'); const Mqtt = require('mqtt'); @@ -170,7 +171,7 @@ process.on('exit', () => { end(); }); -function initTest(mapFile) { +function initTest(mapFile, cam) { describe('start homekit2mqtt', () => { it('should start without error', function (done) { this.timeout(20000); @@ -273,51 +274,125 @@ function initTest(mapFile) { }); }); - describe('hap-client - homekit2mqtt', function () { - this.retries(5); - it('should be able to dump accessories', function (done) { - this.timeout(36000); + if (!cam) { + describe('hap-client - homekit2mqtt', function () { this.retries(5); + it('should be able to dump accessories', function (done) { + this.timeout(36000); + this.retries(5); - cp.exec(clientCmd + ' dump', {maxBuffer: 1024 * 2048}, (err, stdout, stderr) => { - if (err) { - done(err); - } - let clientAccs; - try { - clientAccs = JSON.parse(stdout).accessories; - } catch (err) { - done(err); - } - aid = {}; - iid = {}; - clientAccs.forEach(acc => { - let name; - const iidTmp = {}; - - acc.services.forEach(service => { - service.characteristics.forEach(ch => { - iidTmp[String(ch.Name).replace(/ /g, '')] = ch.iid; - if (ch.Name === 'Name') { - name = ch.value; - } + cp.exec(clientCmd + ' dump', {maxBuffer: 1024 * 2048}, (err, stdout, stderr) => { + if (err) { + done(err); + } + let clientAccs; + try { + clientAccs = JSON.parse(stdout).accessories; + } catch (err) { + done(err); + } + aid = {}; + iid = {}; + clientAccs.forEach(acc => { + let name; + const iidTmp = {}; + + acc.services.forEach(service => { + service.characteristics.forEach(ch => { + iidTmp[String(ch.Name).replace(/ /g, '')] = ch.iid; + if (ch.Name === 'Name') { + name = ch.value; + } + }); }); + aid[name] = acc.aid; + iid[name] = iidTmp; }); - aid[name] = acc.aid; - iid[name] = iidTmp; - }); - // Add one because the bridge itself is also an accessory - if (clientAccs.length === (Object.keys(config).length + 1)) { - done(); - } else { - done(new Error('wrong clientAccs length')); - } + // Add one because the bridge itself is also an accessory + if (clientAccs.length === (Object.keys(config).length + 1)) { + done(); + } else { + done(new Error('wrong clientAccs length')); + } + }); }); }); - }); + } + } +mqtt.publish('test/retain', '1', {retain: true}); + +initTest(__dirname + '/test-cam.json', true); + +describe('Camera', () => { + it('should publish the camera', function (done) { + subscribe('homekit', /hap publishing camera accessory Cam Wohnzimmer/, () => { + done(); + }); + }); + it('should open listening port for the camera', function (done) { + subscribe('homekit', /hap camera Cam Wohnzimmer listening on port /, () => { + done(); + }); + }); +}); + +describe('http server', () => { + it('should open listening port for the web server', function (done) { + subscribe('homekit', /http server listening on port 51888/, () => { + done(); + }); + }); + + it('should respond http 401 on missing credentials', function (done) { + request.get('http://localhost:51888/quit', (err, res, body) => { + if (res.statusCode === 401) { + done(); + } + }); + }); + + it('should respond on get /config', function (done) { + const conf = require('./test-cam.json'); + request.get({url: 'http://homekit:031-45-154@localhost:51888/config', json: true}, (err, res, body) => { + body.should.containDeep(conf); + done(); + }); + }); + + it('should respond on get /topics', function (done) { + request.get({url: 'http://homekit:031-45-154@localhost:51888/topics', json: true}, (err, res, body) => { + res.statusCode.should.equal(200); + body.should.deepEqual(['test/retain']); + done(); + }); + }); + + it('should respond on get /categories', function (done) { + request.get({url: 'http://homekit:031-45-154@localhost:51888/categories', json: true}, (err, res, body) => { + res.statusCode.should.equal(200); + done(); + }); + }); + + + it('should repsond ok on get /quit', function (done) { + request.get('http://homekit:031-45-154@localhost:51888/quit', (err, res, body) => { + if (res.statusCode === 200 && body.match(/ok/)) { + done(); + } + }); + }); + + it('should quit', function (done) { + subscribe('homekit', /http < quit/, () => { + done(); + }); + }); +}); + initTest(__dirname + '/test-am.json'); describe('AirQualitySensor AirQuality', () => { @@ -3334,6 +3409,8 @@ function testTampered(name, invert) { }); } + + setTimeout(() => { homekit.kill(); process.exit(1);