mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
encoder for updateStringTable
This commit is contained in:
parent
89b9c3b25c
commit
ae79b6a0d4
11 changed files with 280 additions and 57 deletions
|
|
@ -87,8 +87,7 @@ suite('CreateStringTable', () => {
|
|||
});
|
||||
|
||||
test('Encode createStringTable', () => {
|
||||
// more bits are used for encoding because we don't do a lot of compression tricks
|
||||
assertEncoder(ParseCreateStringTable, EncodeCreateStringTable, examplePacket, 401);
|
||||
assertEncoder(ParseCreateStringTable, EncodeCreateStringTable, examplePacket2, 628);
|
||||
assertEncoder(ParseCreateStringTable, EncodeCreateStringTable, examplePacket, 388);
|
||||
assertEncoder(ParseCreateStringTable, EncodeCreateStringTable, examplePacket2, 615);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import * as assert from 'assert';
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {Packet} from '../../../../Data/Packet';
|
||||
import {deepEqual} from '../../deepEqual';
|
||||
|
||||
export function getStream(data: string | number[]) {
|
||||
if (typeof data === 'string') {
|
||||
|
|
@ -28,14 +29,20 @@ export function assertEncoder(parser: Parser, encoder: Encoder, data: any, lengt
|
|||
stream.index = 0;
|
||||
|
||||
const result = parser(stream);
|
||||
assert.deepEqual(result, data, 'Re-decoded value not equal to original value');
|
||||
deepEqual(result, data);
|
||||
if (!deepEqual(result, data)) {
|
||||
assert.deepEqual(result, data, 'Re-decoded value not equal to original value');
|
||||
}
|
||||
assert.equal(stream.index, pos, 'Number of bits used for encoding and parsing not equal');
|
||||
}
|
||||
|
||||
export type Parser = (stream: BitStream) => any;
|
||||
export type Parser = (stream: BitStream, match?) => any;
|
||||
|
||||
export function assertParser(parser: Parser, stream: BitStream, expected: any, length: number) {
|
||||
const start = stream.index;
|
||||
assert.deepEqual(parser(stream), expected);
|
||||
const result = parser(stream);
|
||||
if (!deepEqual(result, expected)) {
|
||||
assert.deepEqual(result, expected);
|
||||
}
|
||||
assert.equal(stream.index - start, length, 'Unexpected number of bits consumed from stream');
|
||||
}
|
||||
|
|
|
|||
68
src/tests/unit/Parser/Packet/UpdateStringTableTest.ts
Normal file
68
src/tests/unit/Parser/Packet/UpdateStringTableTest.ts
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import {BitStream} from 'bit-buffer';
|
||||
import {assertEncoder, assertParser, getStream} from './PacketTest';
|
||||
import {EncodeUpdateStringTable, ParseUpdateStringTable} from '../../../../Parser/Packet/UpdateStringTable';
|
||||
import {Match} from '../../../../Data/Match';
|
||||
import {StringTable} from '../../../../Data/StringTable';
|
||||
import {UpdateStringTablePacket} from '../../../../Data/Packet';
|
||||
|
||||
const exampleData = [200, 3, 0, 48, 130, 53];
|
||||
|
||||
function getExistingMatch() {
|
||||
const existingTable: StringTable = {
|
||||
name: 'downloadables',
|
||||
entries: [],
|
||||
maxEntries: 2048,
|
||||
fixedUserDataSize: 1,
|
||||
fixedUserDataSizeBits: 1
|
||||
};
|
||||
existingTable.entries[70] = {text: 'maps\\pl_badwater_pro_v9.bsp'};
|
||||
const match = new Match();
|
||||
match.stringTables[8] = existingTable;
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
const examplePacket: UpdateStringTablePacket = {
|
||||
packetType: 'updateStringTable',
|
||||
entries: [],
|
||||
tableId: 8
|
||||
};
|
||||
const extraData = getStream(exampleData);
|
||||
extraData.index = 40;
|
||||
examplePacket.entries[70] = {
|
||||
text: 'maps\\pl_badwater_pro_v9.bsp',
|
||||
extraData: extraData.readBitStream(
|
||||
1
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
const examplePacket2: UpdateStringTablePacket = {
|
||||
packetType: 'updateStringTable',
|
||||
entries: [
|
||||
{text: 'foo', extraData: undefined},
|
||||
{text: 'foobar', extraData: undefined},
|
||||
{text: 'assadasdas', extraData: undefined},
|
||||
{text: 'foo', extraData: undefined}
|
||||
],
|
||||
tableId: 8
|
||||
};
|
||||
|
||||
function ParseUpdate(stream: BitStream) {
|
||||
return ParseUpdateStringTable(stream, getExistingMatch());
|
||||
}
|
||||
|
||||
function EncodeUpdate(packet: UpdateStringTablePacket, stream: BitStream) {
|
||||
return EncodeUpdateStringTable(packet, stream, getExistingMatch());
|
||||
}
|
||||
|
||||
suite('UpdateStringTable', () => {
|
||||
test('Parse updateStringTable', () => {
|
||||
assertParser(ParseUpdate, getStream(exampleData), examplePacket, 41);
|
||||
});
|
||||
|
||||
test('Encode updateStringTable', () => {
|
||||
assertEncoder(ParseUpdate, EncodeUpdate, examplePacket, 266);
|
||||
assertEncoder(ParseUpdate, EncodeUpdate, examplePacket2, 299);
|
||||
});
|
||||
});
|
||||
108
src/tests/unit/deepEqual.ts
Normal file
108
src/tests/unit/deepEqual.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import {BitStream} from 'bit-buffer';
|
||||
|
||||
export interface EqualOpts {
|
||||
strict?: boolean;
|
||||
}
|
||||
|
||||
export function deepEqual(actual, expected, opts: EqualOpts = {}) {
|
||||
// 7.1. All identical values are equivalent, as determined by ===.
|
||||
if (actual === expected) {
|
||||
return true;
|
||||
|
||||
} else if (actual instanceof Date && expected instanceof Date) {
|
||||
return actual.getTime() === expected.getTime();
|
||||
|
||||
// 7.3. Other pairs that do not both pass typeof value == 'object',
|
||||
// equivalence is determined by ==.
|
||||
} else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') {
|
||||
return opts.strict ? actual === expected : actual == expected;
|
||||
|
||||
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
||||
// determined by having the same number of owned properties (as verified
|
||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
||||
// (although not necessarily the same order), equivalent values for every
|
||||
// corresponding key, and an identical 'prototype' property. Note: this
|
||||
// accounts for both named and indexed properties on Arrays.
|
||||
} else {
|
||||
return objEquiv(actual, expected, opts);
|
||||
}
|
||||
}
|
||||
|
||||
function isUndefinedOrNull(value) {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
|
||||
function isBuffer(x): x is Buffer {
|
||||
if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false;
|
||||
if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
|
||||
return false;
|
||||
}
|
||||
return !(x.length > 0 && typeof x[0] !== 'number');
|
||||
}
|
||||
|
||||
function isStream(stream): stream is BitStream {
|
||||
return stream instanceof BitStream;
|
||||
}
|
||||
|
||||
function objEquiv(a, b, opts) {
|
||||
let i, key;
|
||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
||||
return false;
|
||||
// an identical 'prototype' property.
|
||||
if (a.prototype !== b.prototype) return false;
|
||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
||||
// Converting to array solves the problem.
|
||||
if (isBuffer(a)) {
|
||||
if (!isBuffer(b)) {
|
||||
return false;
|
||||
}
|
||||
if (a.length !== b.length) return false;
|
||||
for (i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (isStream(a)) {
|
||||
if (!isStream(b)) {
|
||||
return false;
|
||||
}
|
||||
if (a.length !== b.length) return false;
|
||||
a.index = 0;
|
||||
b.index = 0;
|
||||
while (a.bitsLeft > 0) {
|
||||
const bitsToRead = Math.min(32, a.bitsLeft);
|
||||
if (a.readBits(bitsToRead) !== b.readBits(bitsToRead)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
a.index = 0;
|
||||
b.index = 0;
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
const ka = Object.keys(a);
|
||||
const kb = Object.keys(b);
|
||||
|
||||
// having the same number of owned properties (keys incorporates
|
||||
// hasOwnProperty)
|
||||
if (ka.length != kb.length)
|
||||
return false;
|
||||
//the same set of keys (although not necessarily the same order),
|
||||
ka.sort();
|
||||
kb.sort();
|
||||
//~~~cheap key test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
if (ka[i] != kb[i])
|
||||
return false;
|
||||
}
|
||||
//equivalent values for every corresponding key, and
|
||||
//~~~possibly expensive deep test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
key = ka[i];
|
||||
if (!deepEqual(a[key], b[key], opts)) return false;
|
||||
}
|
||||
return typeof a === typeof b;
|
||||
} catch (e) {//happens when one is a string literal and the other isn't
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue