muschema
Version:
Schemas for mudb
262 lines (218 loc) • 6.71 kB
text/typescript
import test = require('tape');
import {
MuWriteStream,
MuReadStream,
} from 'mustreams';
import {
MuASCII,
MuBoolean,
MuFixedASCII,
MuFloat32,
MuFloat64,
MuInt8,
MuInt16,
MuInt32,
MuString,
MuStruct,
MuUint8,
MuUint16,
MuUint32,
MuVector,
} from '../';
import { muPrimitiveTypes } from '../constants';
import {
muPrimitiveSchema,
randomString,
randomValue,
testPatchingPairFactory,
} from './helper';
test('struct - muData', (t) => {
const spec = {
v: new MuFloat32(),
};
const structSchema = new MuStruct(spec);
t.notEquals(structSchema.muData, spec);
t.equals(structSchema.muData.v, spec.v);
t.end();
});
test('struct - identity', (t) => {
const structSchema = new MuStruct({
v: new MuFloat64(0.233),
vs: new MuVector(new MuFloat64(0.233), 2),
s: new MuString('foo'),
b: new MuBoolean(),
});
t.equals(structSchema.identity.v, 0.233);
t.same(structSchema.identity.vs, [0.233, 0.233]);
t.equals(structSchema.identity.s, 'foo');
t.equals(structSchema.identity.b, false);
t.end();
});
test('struct - equal()', (t) => {
const structSchema = new MuStruct({
b: new MuBoolean(),
s: new MuStruct({
b: new MuBoolean(),
s: new MuStruct({
b: new MuBoolean(),
}),
}),
});
const a = structSchema.alloc();
const b = structSchema.alloc();
t.ok(structSchema.equal(a, b));
b.s.s.b = !b.s.s.b;
t.notOk(structSchema.equal(a, b));
t.end();
});
test('struct - copy()', (t) => {
const structSchema = new MuStruct({
s: new MuStruct({
s: new MuStruct({
a: new MuASCII(),
b: new MuBoolean(),
fa: new MuFixedASCII(5),
f32: new MuFloat32(),
f64: new MuFloat64(),
i8: new MuInt8(),
i16: new MuInt16(),
i32: new MuInt32(),
str: new MuString(),
u8: new MuUint8(),
u16: new MuUint16(),
u32: new MuUint32(),
}),
}),
});
const source = structSchema.alloc();
const target = structSchema.alloc();
source.s.s.a = randomValue('ascii');
source.s.s.b = true;
source.s.s.fa = 'abcde';
source.s.s.f32 = randomValue('float32');
source.s.s.f64 = randomValue('float64');
source.s.s.i8 = randomValue('int8');
source.s.s.i16 = randomValue('int16');
source.s.s.i32 = randomValue('int32');
source.s.s.str = randomValue('string');
source.s.s.u8 = randomValue('uint8');
source.s.s.u16 = randomValue('uint16');
source.s.s.u32 = randomValue('uint32');
structSchema.copy(source, target);
t.deepEqual(target, source);
t.end();
});
test('struct (flat) - diff() & patch()', (t) => {
function structSpec () {
const result = {};
for (const muType of muPrimitiveTypes) {
const valueSchema = muPrimitiveSchema(muType);
if (valueSchema) {
result[randomString()] = valueSchema;
}
}
return result;
}
for (let i = 0; i < 500; ++i) {
const spec = structSpec();
const structSchema = new MuStruct(spec);
const testPatchingPair = testPatchingPairFactory(t, structSchema);
const randomStruct = () => {
const result = {};
const propNames = Object.keys(spec);
const muTypes = propNames.map((name) => spec[name].muType);
propNames.forEach((propName, idx) => {
result[propName] = randomValue(muTypes[idx]);
});
return result;
};
testPatchingPair(randomStruct(), randomStruct());
}
t.end();
});
test('struct (nested)', (t) => {
function structSchemaOf (depth:number) : MuStruct<any> {
if (depth <= 2) {
return new MuStruct({
type: new MuString('nested'),
struct: new MuStruct({
type: new MuString('flat'),
}),
});
}
return new MuStruct({
type: new MuString('nested'),
struct: structSchemaOf(depth - 1),
});
}
function modifyStruct (s) {
if (s.struct) {
s.type = 'branch';
modifyStruct(s.struct);
} else {
s.type = 'leaf';
}
}
for (let depth = 2; depth < 100; ++depth) {
const structSchema = structSchemaOf(depth);
// clone
const identity = structSchema.identity;
const struct = structSchema.clone(identity);
t.notEquals(struct, identity);
t.same(struct, identity);
// diff & patch
const ws = new MuWriteStream(2);
structSchema.diff(identity, struct, ws);
const rs = new MuReadStream(ws.buffer.uint8);
t.same(structSchema.patch(identity, rs), struct);
modifyStruct(struct);
const testPatchingPair = testPatchingPairFactory(t, structSchema);
testPatchingPair(identity, struct);
}
t.end();
});
test('random test', (t) => {
const testSchema = new MuStruct({
a: new MuFloat32(1),
b: new MuUint8(),
c: new MuVector(new MuFloat32(), 3),
foo: new MuString('0'),
});
type structT = typeof testSchema['identity'];
function randomStruct () {
const result = testSchema.alloc();
result.a = ((Math.random() * 2) | 0) / 2;
result.b = (Math.random() * 2) | 0
result.c = new Float32Array([
((Math.random() * 2) | 0) / 2,
((Math.random() * 2) | 0) / 2,
((Math.random() * 2) | 0) / 2
]);
result.foo = Math.round(Math.random() * 8).toString();
return result;
}
function calcDiff (a:structT, b:structT) : MuReadStream {
const x = new MuWriteStream(1);
testSchema.diff(a, b, x);
return new MuReadStream(x.bytes());
}
function testPair (a:structT, b:structT) {
const x = calcDiff(a, b);
if (x.length === 0) {
t.same(a, b, 'structs are equal');
} else {
const c = testSchema.patch(a, x);
t.same(b, c, 'patch ok');
t.equals(x.length, x.offset, 'offset ok');
}
}
for (let i = 0; i < 100; ++i) {
const as = randomStruct();
const bs = randomStruct();
testPair(as, bs);
testPair(bs, as);
testPair(testSchema.identity, as);
testPair(testSchema.identity, bs);
}
t.end();
});