diff --git a/lib/test.d.ts b/lib/test.d.ts index e69de29..cb0ff5c 100644 --- a/lib/test.d.ts +++ b/lib/test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/lib/test.js b/lib/test.js index 4681d88..b222bae 100644 --- a/lib/test.js +++ b/lib/test.js @@ -1,6 +1,349 @@ -// const t = `71 15 01 00 00 01 00 00 00 00 00 00 02 64 63 08 73 65 72 76 69 63 65 73 0c 76 69 73 75 61 6c 73 74 75 64 69 6f 03 63 6f 6d 00 00 01 00 01`.split(" ").join(""); -// // const tp = Buffer.from(t, "hex") -// // // import Parse from "./index"; -// // import * as util from "util"; -// // console.log(util.inspect(Parse(tp), false, 20, true)); +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const chai_1 = require("chai"); +const request_1 = require("./request"); +const types_1 = require("./types"); +function fromHex(data) { + return Buffer.from(data.replace(/\s/g, ""), "hex"); +} +describe("parser", function () { + describe("header", function () { + describe("header parser", function () { + let should_templ = { + ID: 0, + QR: 0, + OPCODE: 0, + AA: 0, + TC: 0, + RD: 0, + RA: 0, + Z: 0, + AD: 0, + CD: 0, + RCODE: 0, + QDCOUNT: 0, + ANCOUNT: 0, + ARCOUNT: 0, + NSCOUNT: 0 + }; + let tests = [ + { + name: "Testing ID field", + data: "0001 0000 0000 0000 0000 0000", + fields: { + ID: 1 + } + }, + { + name: "Testing ID field with max value", + data: "FFFF 0000 0000 0000 0000 0000", + fields: { + ID: 65535 + } + }, + { + name: "Testing QR field", + data: "0000 8000 0000 0000 0000 0000", + fields: { + QR: 1 + } + }, + { + name: "Testing OPCODE field value 2", + data: "0000 1000 0000 0000 0000 0000", + fields: { + OPCODE: 2 + } + }, + { + name: "Testing OPCODE field value 1", + data: "0000 0800 0000 0000 0000 0000", + fields: { + OPCODE: 1 + } + }, + { + name: "Testing AA field", + data: "0000 0400 0000 0000 0000 0000", + fields: { + AA: 1 + } + }, + { + name: "Testing TC field", + data: "0000 0200 0000 0000 0000 0000", + fields: { + TC: 1 + } + }, + { + name: "Testing RD field", + data: "0000 0100 0000 0000 0000 0000", + fields: { + RD: 1 + } + }, + { + name: "Testing RCODE field", + data: "0000 0002 0000 0000 0000 0000", + fields: { + RCODE: 2 + } + }, + { + name: "Testing QDCOUNT field max value", + data: "0000 0000 FFFF 0000 0000 0000", + fields: { + QDCOUNT: 65535 + } + }, + { + name: "Testing ANCOUNT field max value", + data: "0000 0000 0000 FFFF 0000 0000", + fields: { + ANCOUNT: 65535 + } + }, + { + name: "Testing NSCOUNT field max value", + data: "0000 0000 0000 0000 FFFF 0000", + fields: { + NSCOUNT: 65535 + } + }, + { + name: "Testing ARCOUNT field max value", + data: "0000 0000 0000 0000 0000 FFFF", + fields: { + ARCOUNT: 65535 + } + }, + { + name: "Testing all Flags and Values max", + data: "FFFF FFFF FFFF FFFF FFFF FFFF", + fields: { + ID: 65535, + QR: 1, + OPCODE: 15, + AA: 1, + TC: 1, + RD: 1, + RA: 1, + Z: 1, + AD: 1, + CD: 1, + RCODE: 15, + QDCOUNT: 65535, + ANCOUNT: 65535, + NSCOUNT: 65535, + ARCOUNT: 65535 + } + } + ]; + tests.forEach(function (e) { + it(e.name, function () { + let testdata = fromHex(e.data); + let should = Object.assign({}, should_templ, e.fields); // Build in "clone" function + let header = request_1.parseHeader(testdata); + chai_1.assert.hasAllKeys(header, Object.keys(should), "Parsed header is missing some fields"); + chai_1.assert.deepEqual(header, should, "Parsed header has not expected values!"); + }); + }); + }); + describe("header serializer", function () { + let empty_header = { + ID: 0, + QR: 0, + OPCODE: 0, + AA: 0, + TC: 0, + RD: 0, + RA: 0, + Z: 0, + AD: 0, + CD: 0, + RCODE: 0, + QDCOUNT: 0, + ANCOUNT: 0, + ARCOUNT: 0, + NSCOUNT: 0 + }; + let tests = [ + { + name: "Fill header with 0s", + result: "0000 0000 0000 0000 0000 0000", + values: {} + }, + { + name: "Set header id to 5", + result: "0005 0000 0000 0000 0000 0000", + values: { + ID: 5 + } + }, + { + name: "Set QR", + result: "0000 8000 0000 0000 0000 0000", + values: { + QR: 1 + } + }, + { + name: "Set OPCODE", + result: "0000 7800 0000 0000 0000 0000", + values: { + OPCODE: 15 + } + }, + { + name: "Set AA", + result: "0000 0400 0000 0000 0000 0000", + values: { + AA: 1 + } + }, + { + name: "Set TC", + result: "0000 0200 0000 0000 0000 0000", + values: { + TC: 1 + } + }, + { + name: "Set RD", + result: "0000 0100 0000 0000 0000 0000", + values: { + RD: 1 + } + }, + { + name: "Set RA", + result: "0000 0080 0000 0000 0000 0000", + values: { + RA: 1 + } + }, + { + name: "Set Z", + result: "0000 0040 0000 0000 0000 0000", + values: { + Z: 1 + } + }, + { + name: "Set AD", + result: "0000 0020 0000 0000 0000 0000", + values: { + AD: 1 + } + }, + { + name: "Set CD", + result: "0000 0010 0000 0000 0000 0000", + values: { + CD: 1 + } + }, + { + name: "Set RCODE", + result: "0000 000F 0000 0000 0000 0000", + values: { + RCODE: 15 + } + }, + { + name: "Set QDCOUNT", + result: "0000 0000 FFFF 0000 0000 0000", + values: { + QDCOUNT: 65535 + } + }, + { + name: "Set ANCOUNT", + result: "0000 0000 0000 FFFF 0000 0000", + values: { + ANCOUNT: 65535 + } + }, + { + name: "Set NSCOUNT", + result: "0000 0000 0000 0000 FFFF 0000", + values: { + NSCOUNT: 65535 + } + }, + { + name: "Set ARCOUNT", + result: "0000 0000 0000 0000 0000 FFFF", + values: { + ARCOUNT: 65535 + } + }, + ]; + tests.forEach(function (e) { + it(e.name, function () { + let header = Object.assign({}, empty_header, e.values); + let serialized = new request_1.Header(header).serialize(); + chai_1.assert.equal(serialized.toString("hex"), e.result.replace(/\s/g, "").toLowerCase(), "Header serialization failed"); + }); + }); + }); + }); + describe("question", function () { + let questionData = fromHex("0474 6573 7407 6578 616d 706c 6503 636f 6d00 0001 0001"); + let questionObj = { + QNAME: "test.example.com", + QTYPE: types_1.QueryTypes.A, + QCLASS: 1 + }; + it("check question parser with one question", function () { + let res = request_1.parseQuestions(1, questionData); + let should = [questionObj]; + chai_1.assert.deepEqual(res, should, "Question parser does not parse input correctly"); + }); + it("check question serialization", function () { + let res = new request_1.Question(questionObj).serialize(); + chai_1.assert.equal(res.toString("hex"), questionData.toString("hex"), "Query serializer does not serialite correctly"); + }); + }); + it("recource record serialization", function () { + let should = "07 6578616D706C65 03 636f6D 00 0001 0001 00000640 0004 0A000001"; + let rr = new request_1.RecourceRecord(); + rr.CLASS = 1; + rr.NAME = "example.com"; + rr.TTL = 1600; + rr.TYPE = 1; + rr.RDATA = fromHex("0A 00 00 01"); + let res = rr.serialize().toString("hex"); + chai_1.assert.equal(res, should.replace(/\s/g, "").toLowerCase(), "Serialization not working properly"); + }); + it("full response serialization", function () { + let reqData = fromHex("E835 0100 0001 0000 0000 0000 07 6578616D706c65 03636F6D 00 0001 0001"); + let should = "E835 8580 0001000100000000 076578616D706C6503636F6D0000010001 07 6578616D706C65 03 636F6D 00 0001 0001 0000 0640 0004 0A000001"; + let request = new request_1.Request(reqData, () => null); + let rr = new request_1.RecourceRecord(); + rr.CLASS = 1; + rr.NAME = "example.com"; + rr.TTL = 1600; + rr.TYPE = 1; + rr.RDATA = fromHex("0A 00 00 01"); + request.answers.push(rr); + let data = request.serialize(); + chai_1.assert.equal(data.toString("hex"), should.replace(/\s/g, "").toLowerCase(), "Whole packet serialization failed"); + }); + // it("full response serialization benchmark", function () { + // let reqData = fromHex("E835 0100 0001 0000 0000 0000 07 6578616D706c65 03636F6D 00 0001 0001"); + // for (let i = 0; i < 100; i++) { + // let request = new Request(reqData, () => null) + // let rr = new RecourceRecord() + // rr.CLASS = 1 + // rr.NAME = "example.com" + // rr.TTL = 1600 + // rr.TYPE = 1 + // rr.RDATA = fromHex("0A 00 00 01") + // request.answers.push(rr) + // request.serialize() + // } + // }) +}); //# sourceMappingURL=test.js.map \ No newline at end of file diff --git a/lib/test.js.map b/lib/test.js.map index 62c4dee..df4f22a 100644 --- a/lib/test.js.map +++ b/lib/test.js.map @@ -1 +1 @@ -{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"AAAA,6KAA6K;AAC7K,sCAAsC;AACtC,qCAAqC;AACrC,mCAAmC;AACnC,4DAA4D"} \ No newline at end of file +{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/package.json b/package.json index 5b27e7f..1b599e8 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,19 @@ "scripts": { "build": "tsc", "watch": "tsc --watch", - "test": "nodemon lib/test.js" + "test": "mocha src/test.ts --require ts-node/register", + "testwatch": "mocha src/test.ts --require ts-node/register --watch --watch-extensions ts" }, "devDependencies": { "@types/binary-parser": "^1.3.0", + "@types/chai": "^4.1.3", + "@types/mocha": "^5.2.0", "@types/node": "^10.0.8", + "chai": "^4.1.2", + "mocha": "^5.1.1", "nodemon": "^1.17.4", - "typescript": "^2.8.3" + "typescript": "^2.8.3", + "ts-node": "^6.0.3" }, "dependencies": { "binary-parser": "^1.3.2" diff --git a/src/test.ts b/src/test.ts index bab4bfa..4d0a4a3 100644 --- a/src/test.ts +++ b/src/test.ts @@ -1,5 +1,359 @@ -// const t = `71 15 01 00 00 01 00 00 00 00 00 00 02 64 63 08 73 65 72 76 69 63 65 73 0c 76 69 73 75 61 6c 73 74 75 64 69 6f 03 63 6f 6d 00 00 01 00 01`.split(" ").join(""); -// // const tp = Buffer.from(t, "hex") -// // // import Parse from "./index"; -// // import * as util from "util"; -// // console.log(util.inspect(Parse(tp), false, 20, true)); \ No newline at end of file +import { assert, expect } from "chai"; + +import { parseHeader, Header, parseQuestions, Question, RecourceRecord, Request } from "./request" +import { IMessageHeader, IMessageQuestion, QueryTypes } from "./types"; + +function fromHex(data: string) { + return Buffer.from(data.replace(/\s/g, ""), "hex"); +} + +describe("parser", function () { + describe("header", function () { + describe("header parser", function () { + let should_templ: IMessageHeader = { + ID: 0, + QR: 0, + OPCODE: 0, + AA: 0, + TC: 0, + RD: 0, + RA: 0, + Z: 0, + AD: 0, + CD: 0, + RCODE: 0, + QDCOUNT: 0, + ANCOUNT: 0, + ARCOUNT: 0, + NSCOUNT: 0 + } + + let tests: { name: string, data: string, fields: Partial }[] = [ + { + name: "Testing ID field", + data: "0001 0000 0000 0000 0000 0000", + fields: { + ID: 1 + } + }, + { + name: "Testing ID field with max value", + data: "FFFF 0000 0000 0000 0000 0000", + fields: { + ID: 65535 + } + }, + { + name: "Testing QR field", + data: "0000 8000 0000 0000 0000 0000", + fields: { + QR: 1 + } + }, + { + name: "Testing OPCODE field value 2", + data: "0000 1000 0000 0000 0000 0000", + fields: { + OPCODE: 2 + } + }, + { + name: "Testing OPCODE field value 1", + data: "0000 0800 0000 0000 0000 0000", + fields: { + OPCODE: 1 + } + }, + { + name: "Testing AA field", + data: "0000 0400 0000 0000 0000 0000", + fields: { + AA: 1 + } + }, + { + name: "Testing TC field", + data: "0000 0200 0000 0000 0000 0000", + fields: { + TC: 1 + } + }, + { + name: "Testing RD field", + data: "0000 0100 0000 0000 0000 0000", + fields: { + RD: 1 + } + }, + { + name: "Testing RCODE field", + data: "0000 0002 0000 0000 0000 0000", + fields: { + RCODE: 2 + } + }, + { + name: "Testing QDCOUNT field max value", + data: "0000 0000 FFFF 0000 0000 0000", + fields: { + QDCOUNT: 65535 + } + }, + { + name: "Testing ANCOUNT field max value", + data: "0000 0000 0000 FFFF 0000 0000", + fields: { + ANCOUNT: 65535 + } + }, + { + name: "Testing NSCOUNT field max value", + data: "0000 0000 0000 0000 FFFF 0000", + fields: { + NSCOUNT: 65535 + } + }, + { + name: "Testing ARCOUNT field max value", + data: "0000 0000 0000 0000 0000 FFFF", + fields: { + ARCOUNT: 65535 + } + }, + { + name: "Testing all Flags and Values max", + data: "FFFF FFFF FFFF FFFF FFFF FFFF", + fields: { + ID: 65535, + QR: 1, + OPCODE: 15, + AA: 1, + TC: 1, + RD: 1, + RA: 1, + Z: 1, + AD: 1, + CD: 1, + RCODE: 15, + QDCOUNT: 65535, + ANCOUNT: 65535, + NSCOUNT: 65535, + ARCOUNT: 65535 + } + } + ] + tests.forEach(function (e) { + it(e.name, function () { + let testdata = fromHex(e.data) + let should: IMessageHeader = Object.assign({}, should_templ, e.fields) // Build in "clone" function + let header = parseHeader(testdata); + assert.hasAllKeys(header, Object.keys(should), "Parsed header is missing some fields") + assert.deepEqual(header, should, "Parsed header has not expected values!") + }) + }) + }) + + describe("header serializer", function () { + let empty_header: IMessageHeader = { + ID: 0, + QR: 0, + OPCODE: 0, + AA: 0, + TC: 0, + RD: 0, + RA: 0, + Z: 0, + AD: 0, + CD: 0, + RCODE: 0, + QDCOUNT: 0, + ANCOUNT: 0, + ARCOUNT: 0, + NSCOUNT: 0 + } + let tests: { name: string, result: string, values: Partial }[] = [ + { + name: "Fill header with 0s", + result: "0000 0000 0000 0000 0000 0000", + values: {} + }, + { + name: "Set header id to 5", + result: "0005 0000 0000 0000 0000 0000", + values: { + ID: 5 + } + }, + { + name: "Set QR", + result: "0000 8000 0000 0000 0000 0000", + values: { + QR: 1 + } + }, + { + name: "Set OPCODE", + result: "0000 7800 0000 0000 0000 0000", + values: { + OPCODE: 15 + } + }, + { + name: "Set AA", + result: "0000 0400 0000 0000 0000 0000", + values: { + AA: 1 + } + }, + { + name: "Set TC", + result: "0000 0200 0000 0000 0000 0000", + values: { + TC: 1 + } + }, + { + name: "Set RD", + result: "0000 0100 0000 0000 0000 0000", + values: { + RD: 1 + } + }, + { + name: "Set RA", + result: "0000 0080 0000 0000 0000 0000", + values: { + RA: 1 + } + }, + { + name: "Set Z", + result: "0000 0040 0000 0000 0000 0000", + values: { + Z: 1 + } + }, + { + name: "Set AD", + result: "0000 0020 0000 0000 0000 0000", + values: { + AD: 1 + } + }, + { + name: "Set CD", + result: "0000 0010 0000 0000 0000 0000", + values: { + CD: 1 + } + }, + { + name: "Set RCODE", + result: "0000 000F 0000 0000 0000 0000", + values: { + RCODE: 15 + } + }, + { + name: "Set QDCOUNT", + result: "0000 0000 FFFF 0000 0000 0000", + values: { + QDCOUNT: 65535 + } + }, + { + name: "Set ANCOUNT", + result: "0000 0000 0000 FFFF 0000 0000", + values: { + ANCOUNT: 65535 + } + }, + { + name: "Set NSCOUNT", + result: "0000 0000 0000 0000 FFFF 0000", + values: { + NSCOUNT: 65535 + } + }, + { + name: "Set ARCOUNT", + result: "0000 0000 0000 0000 0000 FFFF", + values: { + ARCOUNT: 65535 + } + }, + ] + + tests.forEach(function (e) { + it(e.name, function () { + let header = Object.assign({}, empty_header, e.values) + let serialized = new Header(header).serialize(); + assert.equal(serialized.toString("hex"), e.result.replace(/\s/g, "").toLowerCase(), "Header serialization failed"); + }) + }) + }) + }) + + describe("question", function () { + let questionData = fromHex("0474 6573 7407 6578 616d 706c 6503 636f 6d00 0001 0001") + let questionObj = { + QNAME: "test.example.com", + QTYPE: QueryTypes.A, + QCLASS: 1 + } + it("check question parser with one question", function () { + + let res = parseQuestions(1, questionData) + let should: IMessageQuestion[] = [questionObj] + + assert.deepEqual(res, should, "Question parser does not parse input correctly") + }) + + it("check question serialization", function () { + let res = new Question(questionObj).serialize() + assert.equal(res.toString("hex"), questionData.toString("hex"), "Query serializer does not serialite correctly"); + }) + }) + + it("recource record serialization", function () { + let should = "07 6578616D706C65 03 636f6D 00 0001 0001 00000640 0004 0A000001" + let rr = new RecourceRecord() + rr.CLASS = 1 + rr.NAME = "example.com" + rr.TTL = 1600 + rr.TYPE = 1 + rr.RDATA = fromHex("0A 00 00 01") + let res = rr.serialize().toString("hex") + assert.equal(res, should.replace(/\s/g, "").toLowerCase(), "Serialization not working properly") + }) + + it("full response serialization", function () { + let reqData = fromHex("E835 0100 0001 0000 0000 0000 07 6578616D706c65 03636F6D 00 0001 0001"); + let should = "E835 8580 0001000100000000 076578616D706C6503636F6D0000010001 07 6578616D706C65 03 636F6D 00 0001 0001 0000 0640 0004 0A000001" + let request = new Request(reqData, () => null) + let rr = new RecourceRecord() + rr.CLASS = 1 + rr.NAME = "example.com" + rr.TTL = 1600 + rr.TYPE = 1 + rr.RDATA = fromHex("0A 00 00 01") + request.answers.push(rr) + let data = request.serialize() + assert.equal(data.toString("hex"), should.replace(/\s/g, "").toLowerCase(), "Whole packet serialization failed") + }) + + // it("full response serialization benchmark", function () { + // let reqData = fromHex("E835 0100 0001 0000 0000 0000 07 6578616D706c65 03636F6D 00 0001 0001"); + // for (let i = 0; i < 100; i++) { + // let request = new Request(reqData, () => null) + // let rr = new RecourceRecord() + // rr.CLASS = 1 + // rr.NAME = "example.com" + // rr.TTL = 1600 + // rr.TYPE = 1 + // rr.RDATA = fromHex("0A 00 00 01") + // request.answers.push(rr) + // request.serialize() + // } + // }) +}) \ No newline at end of file