496 lines
11 KiB
JavaScript
496 lines
11 KiB
JavaScript
import assert from 'assert';
|
|
import {VersionedStruct, String as StringT, Pointer, uint8, DecodeStream, EncodeStream} from 'restructure';
|
|
|
|
describe('VersionedStruct', function() {
|
|
describe('decode', function() {
|
|
it('should get version from number type', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
let stream = new DecodeStream(Buffer.from('\x00\x05devon\x15'));
|
|
assert.deepEqual(struct.decode(stream), {
|
|
version: 0,
|
|
name: 'devon',
|
|
age: 21
|
|
});
|
|
|
|
stream = new DecodeStream(Buffer.from('\x01\x0adevon 👍\x15\x00', 'utf8'));
|
|
assert.deepEqual(struct.decode(stream), {
|
|
version: 1,
|
|
name: 'devon 👍',
|
|
age: 21,
|
|
gender: 0
|
|
});
|
|
});
|
|
|
|
it('should throw for unknown version', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
const stream = new DecodeStream(Buffer.from('\x05\x05devon\x15'));
|
|
return assert.throws(() => struct.decode(stream));
|
|
});
|
|
|
|
it('should support common header block', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
header: {
|
|
age: uint8,
|
|
alive: uint8
|
|
},
|
|
0: {
|
|
name: new StringT(uint8, 'ascii')
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
let stream = new DecodeStream(Buffer.from('\x00\x15\x01\x05devon'));
|
|
assert.deepEqual(struct.decode(stream), {
|
|
version: 0,
|
|
age: 21,
|
|
alive: 1,
|
|
name: 'devon'
|
|
});
|
|
|
|
stream = new DecodeStream(Buffer.from('\x01\x15\x01\x0adevon 👍\x00', 'utf8'));
|
|
assert.deepEqual(struct.decode(stream), {
|
|
version: 1,
|
|
age: 21,
|
|
alive: 1,
|
|
name: 'devon 👍',
|
|
gender: 0
|
|
});
|
|
});
|
|
|
|
it('should support parent version key', function() {
|
|
const struct = new VersionedStruct('version', {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
let stream = new DecodeStream(Buffer.from('\x05devon\x15'));
|
|
assert.deepEqual(struct.decode(stream, {version: 0}), {
|
|
version: 0,
|
|
name: 'devon',
|
|
age: 21
|
|
});
|
|
|
|
stream = new DecodeStream(Buffer.from('\x0adevon 👍\x15\x00', 'utf8'));
|
|
assert.deepEqual(struct.decode(stream, {version: 1}), {
|
|
version: 1,
|
|
name: 'devon 👍',
|
|
age: 21,
|
|
gender: 0
|
|
});
|
|
});
|
|
|
|
it('should support parent version nested key', function() {
|
|
const struct = new VersionedStruct('obj.version', {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
let stream = new DecodeStream(Buffer.from('\x05devon\x15'));
|
|
assert.deepEqual(struct.decode(stream, {obj: {version: 0}}), {
|
|
version: 0,
|
|
name: 'devon',
|
|
age: 21
|
|
});
|
|
|
|
stream = new DecodeStream(Buffer.from('\x0adevon 👍\x15\x00', 'utf8'));
|
|
assert.deepEqual(struct.decode(stream, {obj: {version: 1}}), {
|
|
version: 1,
|
|
name: 'devon 👍',
|
|
age: 21,
|
|
gender: 0
|
|
});
|
|
});
|
|
|
|
it('should support sub versioned structs', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8)
|
|
},
|
|
1: {
|
|
name: new StringT(uint8),
|
|
isDesert: uint8
|
|
}
|
|
}
|
|
)
|
|
}
|
|
);
|
|
|
|
let stream = new DecodeStream(Buffer.from('\x00\x05devon\x15'));
|
|
assert.deepEqual(struct.decode(stream, {version: 0}), {
|
|
version: 0,
|
|
name: 'devon',
|
|
age: 21
|
|
});
|
|
|
|
stream = new DecodeStream(Buffer.from('\x01\x00\x05pasta'));
|
|
assert.deepEqual(struct.decode(stream, {version: 0}), {
|
|
version: 0,
|
|
name: 'pasta'
|
|
});
|
|
|
|
stream = new DecodeStream(Buffer.from('\x01\x01\x09ice cream\x01'));
|
|
assert.deepEqual(struct.decode(stream, {version: 0}), {
|
|
version: 1,
|
|
name: 'ice cream',
|
|
isDesert: 1
|
|
});
|
|
});
|
|
|
|
it('should support process hook', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
struct.process = function() {
|
|
return this.processed = true;
|
|
};
|
|
|
|
const stream = new DecodeStream(Buffer.from('\x00\x05devon\x15'));
|
|
assert.deepEqual(struct.decode(stream), {
|
|
version: 0,
|
|
name: 'devon',
|
|
age: 21,
|
|
processed: true
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('size', function() {
|
|
it('should compute the correct size', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
let size = struct.size({
|
|
version: 0,
|
|
name: 'devon',
|
|
age: 21
|
|
});
|
|
|
|
assert.equal(size, 8);
|
|
|
|
size = struct.size({
|
|
version: 1,
|
|
name: 'devon 👍',
|
|
age: 21,
|
|
gender: 0
|
|
});
|
|
|
|
assert.equal(size, 14);
|
|
});
|
|
|
|
it('should throw for unknown version', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
assert.throws(() =>
|
|
struct.size({
|
|
version: 5,
|
|
name: 'devon',
|
|
age: 21
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should support common header block', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
header: {
|
|
age: uint8,
|
|
alive: uint8
|
|
},
|
|
0: {
|
|
name: new StringT(uint8, 'ascii')
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
let size = struct.size({
|
|
version: 0,
|
|
age: 21,
|
|
alive: 1,
|
|
name: 'devon'
|
|
});
|
|
|
|
assert.equal(size, 9);
|
|
|
|
size = struct.size({
|
|
version: 1,
|
|
age: 21,
|
|
alive: 1,
|
|
name: 'devon 👍',
|
|
gender: 0
|
|
});
|
|
|
|
assert.equal(size, 15);
|
|
});
|
|
|
|
it('should compute the correct size with pointers', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
ptr: new Pointer(uint8, new StringT(uint8))
|
|
}
|
|
}
|
|
);
|
|
|
|
const size = struct.size({
|
|
version: 1,
|
|
name: 'devon',
|
|
age: 21,
|
|
ptr: 'hello'
|
|
});
|
|
|
|
assert.equal(size, 15);
|
|
});
|
|
|
|
it('should throw if no value is given', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(4, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(4, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
}
|
|
);
|
|
|
|
assert.throws(() => struct.size(), /not a fixed size/i);
|
|
});
|
|
});
|
|
|
|
describe('encode', function() {
|
|
it('should encode objects to buffers', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
});
|
|
|
|
const buf1 = struct.toBuffer({
|
|
version: 0,
|
|
name: 'devon',
|
|
age: 21
|
|
});
|
|
|
|
assert.deepEqual(buf1, Buffer.from('\x00\x05devon\x15', 'utf8'));
|
|
|
|
const buf2 = struct.toBuffer({
|
|
version: 1,
|
|
name: 'devon 👍',
|
|
age: 21,
|
|
gender: 0
|
|
});
|
|
|
|
assert.deepEqual(buf2, Buffer.from('\x01\x0adevon 👍\x15\x00', 'utf8'));
|
|
});
|
|
|
|
it('should throw for unknown version', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
});
|
|
|
|
assert.throws(() =>
|
|
struct.toBuffer({
|
|
version: 5,
|
|
name: 'devon',
|
|
age: 21
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should support common header block', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
header: {
|
|
age: uint8,
|
|
alive: uint8
|
|
},
|
|
0: {
|
|
name: new StringT(uint8, 'ascii')
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
gender: uint8
|
|
}
|
|
});
|
|
|
|
const buf1 = struct.toBuffer({
|
|
version: 0,
|
|
age: 21,
|
|
alive: 1,
|
|
name: 'devon'
|
|
});
|
|
|
|
assert.deepEqual(buf1, Buffer.from('\x00\x15\x01\x05devon', 'utf8'));
|
|
|
|
const buf2 = struct.toBuffer({
|
|
version: 1,
|
|
age: 21,
|
|
alive: 1,
|
|
name: 'devon 👍',
|
|
gender: 0
|
|
});
|
|
|
|
assert.deepEqual(buf2, Buffer.from('\x01\x15\x01\x0adevon 👍\x00', 'utf8'));
|
|
});
|
|
|
|
it('should encode pointer data after structure', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
ptr: new Pointer(uint8, new StringT(uint8))
|
|
}
|
|
});
|
|
|
|
const buf = struct.toBuffer({
|
|
version: 1,
|
|
name: 'devon',
|
|
age: 21,
|
|
ptr: 'hello'
|
|
});
|
|
|
|
assert.deepEqual(buf, Buffer.from('\x01\x05devon\x15\x09\x05hello', 'utf8'));
|
|
});
|
|
|
|
it('should support preEncode hook', function() {
|
|
const struct = new VersionedStruct(uint8, {
|
|
0: {
|
|
name: new StringT(uint8, 'ascii'),
|
|
age: uint8
|
|
},
|
|
1: {
|
|
name: new StringT(uint8, 'utf8'),
|
|
age: uint8,
|
|
gender: uint8
|
|
}
|
|
});
|
|
|
|
struct.preEncode = function() {
|
|
return this.version = (this.gender != null) ? 1 : 0;
|
|
};
|
|
|
|
const buf1 = struct.toBuffer({
|
|
name: 'devon',
|
|
age: 21
|
|
});
|
|
|
|
assert.deepEqual(buf1, Buffer.from('\x00\x05devon\x15', 'utf8'));
|
|
|
|
const buf2 = struct.toBuffer({
|
|
name: 'devon 👍',
|
|
age: 21,
|
|
gender: 0
|
|
});
|
|
|
|
assert.deepEqual(buf2, Buffer.from('\x01\x0adevon 👍\x15\x00', 'utf8'));
|
|
});
|
|
});
|
|
});
|