195 lines
4.6 KiB
JavaScript
195 lines
4.6 KiB
JavaScript
import {expect, test} from 'vitest';
|
||
|
||
import Schema from './schema.js';
|
||
|
||
const compare = (specification, value) => {
|
||
expect(new Schema(specification).defaultValue())
|
||
.to.deep.equal(value);
|
||
};
|
||
|
||
test('defaults values', () => {
|
||
[
|
||
'uint8',
|
||
'int8',
|
||
'uint16',
|
||
'int16',
|
||
'uint32',
|
||
'int32',
|
||
'float32',
|
||
'float64',
|
||
].forEach((type) => {
|
||
compare({type}, 0);
|
||
});
|
||
[
|
||
'uint64',
|
||
'int64',
|
||
].forEach((type) => {
|
||
compare({type}, 0n);
|
||
});
|
||
compare({type: 'string'}, '');
|
||
compare({type: 'array', subtype: {type: 'string'}}, []);
|
||
compare(
|
||
{
|
||
type: 'object',
|
||
properties: {
|
||
foo: {type: 'uint8'},
|
||
bar: {type: 'string'},
|
||
baz: {type: 'object', properties: {blah: {type: 'array', subtype: {type: 'string'}}}},
|
||
},
|
||
},
|
||
{foo: 0, bar: '', baz: {blah: []}},
|
||
);
|
||
compare(
|
||
{
|
||
type: 'map',
|
||
value: {
|
||
type: 'object',
|
||
properties: {
|
||
foo: {type: 'uint8'},
|
||
bar: {type: 'string'},
|
||
baz: {type: 'object', properties: {blah: {type: 'array', subtype: {type: 'string'}}}},
|
||
},
|
||
},
|
||
},
|
||
{},
|
||
);
|
||
});
|
||
|
||
test.todo('defaults nested values', () => {
|
||
compare(
|
||
{
|
||
type: 'array',
|
||
subtype: {
|
||
type: 'object',
|
||
properties: {
|
||
foo: {defaultValue: 'bar', type: 'string'},
|
||
},
|
||
},
|
||
},
|
||
[{}],
|
||
[{foo: 'bar'}],
|
||
);
|
||
});
|
||
|
||
test('validates a schema', () => {
|
||
[
|
||
'uint8',
|
||
'int8',
|
||
'uint16',
|
||
'int16',
|
||
'uint32',
|
||
'int32',
|
||
'uint64',
|
||
'int64',
|
||
'float32',
|
||
'float64',
|
||
'string',
|
||
].forEach((type) => {
|
||
expect(() => {
|
||
new Schema({type});
|
||
new Schema({type: 'array', subtype: {type}});
|
||
new Schema({type: 'object', properties: {foo: {type}}});
|
||
new Schema({type: 'map', value: {type}});
|
||
})
|
||
.to.not.throw();
|
||
});
|
||
});
|
||
|
||
test('calculates the size of concrete instances', () => {
|
||
expect(
|
||
(new Schema({type: 'string'}))
|
||
.sizeOf('hi')
|
||
)
|
||
.to.equal(4 + (new TextEncoder().encode('hi')).length);
|
||
expect(
|
||
(new Schema(
|
||
{
|
||
type: 'object',
|
||
properties: {
|
||
foo: {type: 'uint8'},
|
||
bar: {type: 'uint32'},
|
||
baz: {type: 'string'},
|
||
},
|
||
},
|
||
))
|
||
.sizeOf({foo: 69, bar: 420, baz: 'aα'})
|
||
)
|
||
.to.equal(
|
||
1
|
||
+ 4
|
||
+ 4 + (new TextEncoder().encode('aα')).length
|
||
);
|
||
expect(
|
||
(new Schema({type: 'array', subtype: {type: 'string'}}))
|
||
.sizeOf(['hallo', 'hαllo'])
|
||
)
|
||
.to.equal(
|
||
4
|
||
+ 4 + (new TextEncoder().encode('hallo')).length
|
||
+ 4 + (new TextEncoder().encode('hαllo')).length
|
||
);
|
||
expect(
|
||
(new Schema(
|
||
{
|
||
type: 'map',
|
||
value: {
|
||
type: 'object',
|
||
properties: {
|
||
foo: {type: 'uint8'},
|
||
bar: {type: 'uint32'},
|
||
baz: {type: 'string'},
|
||
},
|
||
},
|
||
},
|
||
))
|
||
.sizeOf({
|
||
foo: {foo: 69, bar: 420, baz: 'aα'},
|
||
'aα': {foo: 69, bar: 420, baz: 'meow'},
|
||
})
|
||
)
|
||
.to.equal(
|
||
4
|
||
+ 4 + (new TextEncoder().encode('foo')).length
|
||
+ 1
|
||
+ 4
|
||
+ 4 + (new TextEncoder().encode('aα')).length
|
||
+ 4 + (new TextEncoder().encode('aα')).length
|
||
+ 1
|
||
+ 4
|
||
+ 4 + (new TextEncoder().encode('meow')).length
|
||
);
|
||
});
|
||
|
||
test('encodes and decodes', () => {
|
||
const entries = [
|
||
[{type: 'uint8'}, 255],
|
||
[{type: 'int8'}, -128],
|
||
[{type: 'int8'}, 127],
|
||
[{type: 'uint16'}, 65535],
|
||
[{type: 'int16'}, -32768],
|
||
[{type: 'int16'}, 32767],
|
||
[{type: 'uint32'}, 4294967295],
|
||
[{type: 'int32'}, -2147483648],
|
||
[{type: 'int32'}, 2147483647],
|
||
[{type: 'uint64'}, 18446744073709551615n],
|
||
[{type: 'int64'}, -9223372036854775808n],
|
||
[{type: 'int64'}, 9223372036854775807n],
|
||
[{type: 'float32'}, 0.5],
|
||
[{type: 'float64'}, 1.234],
|
||
[{type: 'string'}, 'hello world'],
|
||
[{type: 'string'}, 'α'],
|
||
[{type: 'array', subtype: {type: 'uint8'}}, [1, 2, 3, 4]],
|
||
[{type: 'array', subtype: {type: 'string'}}, ['one', 'two', 'three', 'four']],
|
||
[{type: 'map', value: {type: 'object', properties: {foo: {type: 'uint8'}, bar: {type: 'string'}}}}, {one: {foo: 64, bar: 'baz'}, two: {foo: 128, bar: 'baw'}}],
|
||
[{type: 'object', properties: {foo: {type: 'uint8'}, bar: {type: 'string'}}}, {foo: 64, bar: 'baz'}],
|
||
[{type: 'object', properties: {foo: {type: 'uint8'}}}, {foo: 64}],
|
||
];
|
||
entries.forEach(([specification, instance]) => {
|
||
const schema = new Schema(specification);
|
||
const view = new DataView(new ArrayBuffer(schema.sizeOf(instance)));
|
||
schema.serialize(instance, view);
|
||
expect(instance)
|
||
.to.deep.equal(schema.deserialize(view));
|
||
});
|
||
});
|