UNPKG

struffer

Version:
451 lines 17.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const alsatian_1 = require("alsatian"); const base_1 = require("../src/base"); const os_1 = require("os"); const common_1 = require("../src/common"); const util_1 = require("util"); // tslint:disable-next-line:max-line-length exports.CommonAPITestCase = alsatian_1.TestCase('foobar', 'bar', 'foo', 'something', 'UTF-8-Up-Next...', '👍'); /* istanbul ignore next */ class TestsBase { get factory() { return () => base_1.default; } get defaultSize() { return 8; } } class FactoryTestsBase extends TestsBase { basicGeneration({ byteLength, bitLength, types }) { const Test = this.factory('Basic', types.map((type, i) => { return [type, `member${i}`]; })); alsatian_1.Expect(Test.byteLength).toBe(byteLength); alsatian_1.Expect(Test.bitLength).toBe(bitLength); } instantiation(name, offset, types) { const Test = this.factory(name, types.map((type, i) => { return [type, `member${i}`]; })); const buffer = Buffer.alloc(Test.byteLength + ((offset !== null) ? offset : 0)); const struff = new Test(buffer, (offset !== null) ? offset : undefined); alsatian_1.Expect(struff.kind).toBe(name); alsatian_1.Expect(struff.offset).toBe((offset !== null) ? offset : 0); alsatian_1.Expect(struff.size).toBe(types.length); alsatian_1.Expect(struff[Symbol.toStringTag]).toBe(`${struff.constructor.name}<${name}>`); } } exports.FactoryTestsBase = FactoryTestsBase; class APITestsBase extends TestsBase { retrievalBase(bufferData, stuff) { const Test = this.factory('Test', stuff.map(([type], i) => { return [type, `member${i}`]; })); const buf = Buffer.alloc(Test.byteLength); buf.set(bufferData); return new Test(buf); } assignmentBase(stuff) { const Test = this.factory('Test', stuff.map(([type], i) => { return [type, `member${i}`]; })); const buf = Buffer.alloc(Test.byteLength); return new Test(buf); } otherBase(names, size = this.defaultSize) { const Test = this.factory('Test', names.map(name => [`u${size}`, name])); const buf = Buffer.alloc(Test.byteLength); return new Test(buf); } } class ObjectAPITestsBase extends APITestsBase { retrieval(bufferData, stuff) { const struff = super.retrievalBase(bufferData, stuff); for (const [i, [, value]] of stuff.entries()) { alsatian_1.Expect(struff.structure[`member${i}`]).toBe(value); } alsatian_1.Expect(struff.structure.someNonexistentMember).not.toBeDefined(); } // technically, this test also includes retrieval but ¯\_(ツ)_/¯ assignment(stuff) { const struff = super.assignmentBase(stuff); for (const [i, [, value]] of stuff.entries()) { alsatian_1.Expect(() => struff.structure[`member${i}`] = value).not.toThrow(); alsatian_1.Expect(struff.structure[`member${i}`]).toBe(value); } alsatian_1.Expect(() => struff.structure.someNonexistentMember = 1).toThrow(); } presence(...names) { const struff = super.otherBase(names); for (const name of names) { alsatian_1.Expect(name in struff.structure).toBe(true); } alsatian_1.Expect('someNonexistentMember' in struff.structure).toBe(false); } deletion(...names) { const struff = super.otherBase(names); struff.buffer.fill(1); for (const name of names) { /* * in strict mode (which typescript enables by default), `delete` returning * `false` causes a `TypeError` to be thrown */ alsatian_1.Expect(() => alsatian_1.Expect(delete struff.structure[name]).toBe(true)).not.toThrow(); alsatian_1.Expect(struff.structure[name]).toBe(0); } // same here alsatian_1.Expect(() => alsatian_1.Expect(delete struff.structure.someNonexistentMember).toBe(false)).toThrow(); } enumeration(...names) { const struff = super.otherBase(names); let i = 0; for (const member of Object.keys(struff.structure)) { alsatian_1.Expect(member).toBe(names[i]); i++; } } propertyDescription(...names) { const struff = super.otherBase(names); for (const name of names) { let desc = Object.getOwnPropertyDescriptor(struff.structure, name); alsatian_1.Expect(desc).toBeDefined(); desc = desc; alsatian_1.Expect(desc.configurable).toBe(true); alsatian_1.Expect(desc.enumerable).toBe(true); alsatian_1.Expect(desc.writable).toBe(true); } const desc = Object.getOwnPropertyDescriptor(struff.structure, 'someNonexistentMember'); alsatian_1.Expect(desc).not.toBeDefined(); } } exports.ObjectAPITestsBase = ObjectAPITestsBase; class MapAPITestsBase extends APITestsBase { retrieval(bufferData, stuff) { const struff = super.retrievalBase(bufferData, stuff); for (const [i, [, value]] of stuff.entries()) { alsatian_1.Expect(struff.get(`member${i}`)).toBe(value); } alsatian_1.Expect(struff.get('someNonexistentMember')).not.toBeDefined(); } // technically, this test also includes retrieval but ¯\_(ツ)_/¯ assignment(stuff) { const struff = super.assignmentBase(stuff); for (const [i, [, value]] of stuff.entries()) { alsatian_1.Expect(() => struff.set(`member${i}`, value)).not.toThrow(); alsatian_1.Expect(struff.get(`member${i}`)).toBe(value); } alsatian_1.Expect(() => struff.set('someNonexistentMember', 1)).toThrow(); } presence(...names) { const struff = super.otherBase(names); for (const name of names) { alsatian_1.Expect(struff.has(name)).toBe(true); } alsatian_1.Expect(struff.has('someNonexistentMember')).toBe(false); } deletion(...names) { const struff = super.otherBase(names); struff.buffer.fill(1); for (const name of names) { alsatian_1.Expect(struff.delete(name)).toBe(true); alsatian_1.Expect(struff.get(name)).toBe(0); } alsatian_1.Expect(struff.delete('someNonexistentMember')).toBe(false); } enumeration(...names) { const struff = super.otherBase(names); let i = 0; for (const member of struff.keys()) { alsatian_1.Expect(member).toBe(names[i]); i++; } } clearance(...names) { const struff = super.otherBase(names); struff.buffer.fill(1); struff.clear(); for (const name of names) { alsatian_1.Expect(struff.get(name)).toBe(0); } } iteration(thisArg = undefined, ...names) { const struff = super.otherBase(names); for (const name of names) { struff.set(name, 1); } let i = 0; struff.forEach(function (value, key, map) { alsatian_1.Expect(key).toBe(names[i]); alsatian_1.Expect(value).toBe(1); alsatian_1.Expect(map).toBe(struff); alsatian_1.Expect(this).toBe(thisArg); i++; }, thisArg); } valueEnumeration(...names) { const struff = super.otherBase(names); for (const name of names) { struff.set(name, 1); } let i = 0; for (const val of struff.values()) { alsatian_1.Expect(val).toBe(1); i++; } } entryEnumeration(...names) { const struff = super.otherBase(names); for (const name of names) { struff.set(name, 1); } let i = 0; for (const [name, value] of struff.entries()) { alsatian_1.Expect(name).toBe(names[i]); alsatian_1.Expect(value).toBe(1); i++; } } automaticIteration(...names) { const struff = super.otherBase(names); for (const name of names) { struff.set(name, 1); } let i = 0; for (const [name, value] of struff) { alsatian_1.Expect(name).toBe(names[i]); alsatian_1.Expect(value).toBe(1); i++; } } } exports.MapAPITestsBase = MapAPITestsBase; class BatchAPITestsBase extends APITestsBase { retrieval(bufferData, stuff) { const struff = super.retrievalBase(bufferData, stuff); const members = stuff.filter((_, i) => i % 2 === 0).map((_, i) => `member${i}`); const dict = struff.getMany(members); for (const name of Object.keys(dict)) { const i = Number(name.slice(6)); alsatian_1.Expect(dict[name]).toBe(stuff[i][1]); } const all = struff.getMany(); for (const name of Object.keys(dict)) { const i = Number(name.slice(6)); alsatian_1.Expect(all[name]).toBe(stuff[i][1]); } } // technically, this test also includes retrieval but ¯\_(ツ)_/¯ assignment(stuff) { const struff = super.assignmentBase(stuff); const dict = {}; for (const [i, [, value]] of stuff.entries()) { dict[`member${i}`] = value; } struff.setMany(dict); for (const [i, [, value]] of stuff.entries()) { alsatian_1.Expect(struff.get(`member${i}`)).toBe(value); } } presence(...names) { const struff = super.otherBase(names); const present = struff.hasMany(names.concat('someNonexistentMember')); for (const name of names) { alsatian_1.Expect(present[name]).toBe(true); } alsatian_1.Expect(present.someNonexistentMember).toBe(false); } deletion(...names) { const struff = super.otherBase(names); for (const name of names) { struff.set(name, 1); } const toDelete = names.filter((_, i) => i % 2 === 0); const result = struff.deleteMany(toDelete); alsatian_1.Expect(result).toBe(true); for (const name of names) { if (toDelete.includes(name)) { alsatian_1.Expect(struff.get(name)).toBe(0); } else { alsatian_1.Expect(struff.get(name)).not.toBe(0); } } const wrongDelete = names.filter(n => !toDelete.includes(n)) .concat('someNonexistentMember') .concat(names[0]); const result2 = struff.deleteMany(wrongDelete); alsatian_1.Expect(result2).toBe(false); for (const name of names) { alsatian_1.Expect(struff.get(name)).toBe(0); } } } exports.BatchAPITestsBase = BatchAPITestsBase; class MiscellaneousTestsBase extends APITestsBase { stringRepresentation(factoryName, name, members) { let rep = `${factoryName}<${name}> {\n`; for (const [type, name, value] of members) { const typeInfo = common_1.parseType(type); rep += ' '; rep += name; rep += ': '; rep += (typeInfo.signature === common_1.MemberSignature.Signed) ? 'i' : 'u'; rep += typeInfo.bitSize; rep += (typeInfo.endianness === common_1.MemberEndianness.BigEndian) ? 'be' : ''; rep += ' = '; rep += value; rep += ';\n'; } rep += '}'; return rep; } pad(arr, signature = 'u', endianness = 'le') { let result = arr.join(''); if (signature === 'u') { if (endianness === 'le') { result = result.padStart(this.defaultSize, '0'); } else { result = result.padEnd(this.defaultSize, '0'); } } else { if (endianness === 'le') { result = result.padStart(this.defaultSize, String(arr[0])); } else { result = result.padEnd(this.defaultSize, String(arr[arr.length - 1])); } } return result.split('').map(i => (i === '0') ? 0 : 1); } bitEnumeration(...names) { const struff = super.otherBase(names); for (const name of names) { struff.set(name, 1); } let expected = []; expected = '1'.padStart(this.defaultSize, '0').split('').map(i => (i === '0') ? 0 : 1); /* istanbul ignore next */ if (os_1.endianness() === 'BE') { expected.reverse(); } for (const bits of struff.bits()) { alsatian_1.Expect(bits).toEqual(expected); } } bitEntryEnumeration(...names) { const struff = super.otherBase(names); for (const name of names) { struff.set(name, 1); } let expected = []; expected = '1'.padStart(this.defaultSize, '0').split('').map(i => (i === '0') ? 0 : 1); /* istanbul ignore next */ if (os_1.endianness() === 'BE') { expected.reverse(); } let i = 0; for (const [name, bits] of struff.bitEntries()) { alsatian_1.Expect(name).toBe(names[i]); alsatian_1.Expect(bits).toEqual(expected); i++; } } getBits() { const Test = this.factory('Test', [ [`u${this.defaultSize}`, 'foo'], [`i${this.defaultSize}`, 'bar'], [`u${this.defaultSize}be`, 'some'], [`i${this.defaultSize}be`, 'thing'], ]); const buf = Buffer.alloc(Test.byteLength); const struff = new Test(buf); struff.setMany({ foo: 1, bar: -2, some: 1, thing: -2, }); const expected = { foo: this.pad([1]), bar: this.pad([1, 0], 'i'), some: this.pad([1], 'u', 'be'), thing: this.pad([0, 1], 'i', 'be'), }; for (const name of ['foo', 'bar', 'some', 'thing']) { alsatian_1.Expect(struff.getBits(name)).toEqual(expected[name]); } alsatian_1.Expect(() => struff.getBits('someNonexistentMember')).toThrow(); } setBits() { const Test = this.factory('Test', [ [`u${this.defaultSize}`, 'foo'], [`i${this.defaultSize}`, 'bar'], [`u${this.defaultSize}be`, 'some'], [`i${this.defaultSize}be`, 'thing'], ]); const buf = Buffer.alloc(Test.byteLength); const struff = new Test(buf); const members = ['foo', 'bar', 'some', 'thing']; const values = { foo: this.pad([1]), bar: this.pad([1, 0], 'i'), some: this.pad([1], 'u', 'be'), thing: this.pad([0, 1], 'i', 'be'), }; for (const name of members) { struff.setBits(name, values[name]); } const expected = { foo: 1, bar: -2, some: 1, thing: -2, }; const result = struff.getMany(members); alsatian_1.Expect(result).toEqual(expected); alsatian_1.Expect(() => struff.setBits('someNonexistentMember', [1, 1])).toThrow(); } toString(name, members) { const Test = this.factory(name, members.map(([type, name]) => { return [type, name]; })); const buf = Buffer.alloc(Test.byteLength); const struff = new Test(buf); struff.setMany(members.reduce((obj, [, name, value]) => { obj[name] = value; return obj; }, {})); alsatian_1.Expect(struff.toString()).toBe(this.stringRepresentation(struff.constructor.name, name, members)); } coercion(name, members) { const Test = this.factory(name, members.map(([type, name]) => { return [type, name]; })); const buf = Buffer.alloc(Test.byteLength); const struff = new Test(buf); struff.setMany(members.reduce((obj, [, name, value]) => { obj[name] = value; return obj; }, {})); alsatian_1.Expect(() => +struff).toThrow(); // tslint:disable-next-line:max-line-length alsatian_1.Expect(`${struff}foobar`).toBe(`${this.stringRepresentation(struff.constructor.name, name, members)}foobar`); } inspection(name, members) { const Test = this.factory(name, members.map(([type, name]) => { return [type, name]; })); const buf = Buffer.alloc(Test.byteLength); const struff = new Test(buf); struff.setMany(members.reduce((obj, [, name, value]) => { obj[name] = value; return obj; }, {})); alsatian_1.Expect(util_1.inspect(struff)).toBe(this.stringRepresentation(struff.constructor.name, name, members)); } } exports.MiscellaneousTestsBase = MiscellaneousTestsBase; //# sourceMappingURL=common.js.map