acebase/spec/data-types.spec.js
2021-06-04 14:52:49 +02:00

199 lines
No EOL
7.7 KiB
JavaScript

/// <reference types="@types/jasmine" />
const { PathReference } = require("acebase-core");
const { createTempDB } = require("./tempdb");
describe('Data type', () => {
let db, removeDB;
beforeAll(async () => {
const tmp = await createTempDB();
db = tmp.db;
removeDB = tmp.removeDB;
});
it('boolean', async () => {
// Set to true
await db.ref('datatypes').update({ boolean: true });
let snap = await db.ref('datatypes/boolean').get();
expect(snap.val()).toBeTrue();
// Set to false
await db.ref('datatypes').update({ boolean: false });
snap = await db.ref('datatypes/boolean').get();
expect(snap.val()).toBeFalse();
});
it('number', async () => {
// Set to 1 (<= 15 will be stored as a "tiny value" using 4 bits)
await db.ref('datatypes').update({ number: 1 });
let snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(1);
// Set to 15 (also tiny value)
await db.ref('datatypes').update({ number: 15 });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(15);
// Set to 16 (>15 stored as "small value", stored inline in the parent object node)
await db.ref('datatypes').update({ number: 16 });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(16);
// Set to Number.MAX_SAFE_INTEGER
await db.ref('datatypes').update({ number: Number.MAX_SAFE_INTEGER });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(Number.MAX_SAFE_INTEGER);
// Set to Number.MAX_VALUE
await db.ref('datatypes').update({ number: Number.MAX_VALUE });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(Number.MAX_VALUE);
// Set to negative -1 (should be stored as small value)
await db.ref('datatypes').update({ number: -1 });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(-1);
// Set to negative -15 (should be stored as small value)
await db.ref('datatypes').update({ number: -15 });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(-15);
// Set to negative -15 (should be stored as small value)
await db.ref('datatypes').update({ number: -16 });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(-16);
// Set to Number.MIN_SAFE_INTEGER
await db.ref('datatypes').update({ number: Number.MIN_SAFE_INTEGER });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(Number.MIN_SAFE_INTEGER);
// Set to Number.MIN_VALUE
await db.ref('datatypes').update({ number: Number.MIN_VALUE });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(Number.MIN_VALUE);
// Set to NaN
await db.ref('datatypes').update({ number: Number.NaN });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBeNaN();
// Set to positive infinity
await db.ref('datatypes').update({ number: Number.POSITIVE_INFINITY });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(Number.POSITIVE_INFINITY);
// Set to negative infinity
await db.ref('datatypes').update({ number: Number.NEGATIVE_INFINITY });
snap = await db.ref('datatypes/number').get();
expect(snap.val()).toBe(Number.NEGATIVE_INFINITY);
});
it('string', async () => {
// Set to empty string (stored as "tiny value")
await db.ref('datatypes').update({ string: '' });
let snap = await db.ref('datatypes/string').get();
expect(snap.val()).toBe('');
// Set to small string (stored as "small value")
await db.ref('datatypes').update({ string: 'small value' });
snap = await db.ref('datatypes/string').get();
expect(snap.val()).toBe('small value');
// Set to small string (stored as "larger value")
const larger = `this string will be too long to store inline (in the parent nodes's record). The default inline value length is 50 bytes`
await db.ref('datatypes').update({ string: larger });
snap = await db.ref('datatypes/string').get();
expect(snap.val()).toBe(larger);
let str10kb = ''; // Generate 10KB string
for (let i = 0; i < 1000; i++) {
str10kb += '0123456789';
}
await db.ref('datatypes').update({ string: str10kb });
snap = await db.ref('datatypes/string').get();
expect(snap.val()).toBe(str10kb);
let str5mb = ''; // Generate 5MB string
for (let i = 0; i < 5 * 1000 * 100; i++) {
str5mb += '0123456789';
}
await db.ref('datatypes').update({ string: str5mb });
snap = await db.ref('datatypes/string').get();
expect(snap.val()).toBe(str5mb);
});
it('date', async () => {
// Store minimum date
await db.ref('datatypes').update({ date: new Date(0) });
snap = await db.ref('datatypes/date').get();
expect(snap.val()).toEqual(new Date(0));
// Store current date/time
let now = new Date();
await db.ref('datatypes').update({ date: now });
snap = await db.ref('datatypes/date').get();
expect(snap.val()).toEqual(now);
});
it('binary', async () => {
// Test Uint8Array storage
// Test "tiny value" (0 bytes)
let data = new Uint8Array(0);
await db.ref('datatypes').update({ binary: data });
snap = await db.ref('datatypes/binary').get();
expect(snap.val()).toBeInstanceOf(ArrayBuffer);
expect(new Uint8Array(snap.val())).toEqual(data);
// Test small value (<= 50 bytes default, stored inline)
data = new Uint8Array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]);
await db.ref('datatypes').update({ binary: data });
snap = await db.ref('datatypes/binary').get();
expect(snap.val()).toBeInstanceOf(ArrayBuffer);
expect(new Uint8Array(snap.val())).toEqual(data);
// Test larger value
data = new Uint8Array(250);
for(let i = 0 ; i < data.length; i++) {
data[i] = i;
}
await db.ref('datatypes').update({ binary: data });
snap = await db.ref('datatypes/binary').get();
expect(snap.val()).toBeInstanceOf(ArrayBuffer);
expect(new Uint8Array(snap.val())).toEqual(data);
// Test 5MB value
data = new Uint8Array(5 * 1000 * 1000);
for(let i = 0 ; i < data.length; i++) {
data[i] = i % 255;
}
await db.ref('datatypes').update({ binary: data });
snap = await db.ref('datatypes/binary').get();
expect(snap.val()).toBeInstanceOf(ArrayBuffer);
// expect(new Uint8Array(snap.val())).toEqual(data); // <-- Disabled because Jasmine is very slow to perform this comparison!
const stored = new Uint8Array(snap.val());
let isEqual = true;
for(let i = 0; i < data.length && isEqual; i++) {
isEqual = data[i] === stored[i];
}
expect(isEqual).toBeTrue();
});
it('reference', async () => {
// Test path reference - which is undocumented and currently has no benefits over using plain strings
const refPath = 'path/to/somehwere/else'
await db.ref('datatypes').update({ ref: new PathReference(refPath) });
snap = await db.ref('datatypes/ref').get();
expect(snap.val()).toBeInstanceOf(PathReference);
expect(snap.val().path).toEqual(refPath);
});
afterAll(async () => {
await removeDB();
})
});