reign
Version:
A persistent, typed-objects implementation.
378 lines (324 loc) • 10.6 kB
JavaScript
;
var _2 = require("../..");
var _3 = require("./");
var _symbols = require("../../symbols");
describeRealm('ArrayType', function (options) {
let realm;
let ArrayType;
let StructType;
let instance;
let T;
before(() => {
realm = options.realm;
T = realm.T;
ArrayType = realm.ArrayType;
StructType = realm.StructType;
});
it('ArrayType should be an instance of realm.TypeClass', function () {
ArrayType.should.be.an.instanceOf(realm.TypeClass);
});
PRIMITIVE_NAMES.forEach(typeName => {
describe(`Array<${ typeName }>`, function () {
let Type;
let XArray;
let array;
let input;
before(() => {
Type = T[typeName];
XArray = Type.Array;
input = Array.from({ length: 16 }, () => Type.randomValue());
});
it(`Array<${ typeName }> should be an instance of ArrayType`, function () {
XArray.should.be.an.instanceOf(ArrayType);
});
it('should create an instance of the array', function () {
array = new XArray(16);
});
it(`array should be an instanceOf Array<${ typeName }>`, function () {
array.should.be.an.instanceOf(XArray);
});
it('should create an instance of the array from an array', function () {
array = new XArray(input);
});
it('should have the right length', function () {
array.length.should.equal(input.length);
});
it('should have the right contents', function () {
input.forEach((expected, index) => {
array[index].should.equal(expected);
});
});
it('should iterate the items in the array', function () {
let i = 0;
for (let item of array) {
item.should.equal(input[i]);
i++;
}
});
it('should iterate the array with .forEach()', function () {
array.length.should.equal(16);
array.forEach((item, index, arr) => {
item.should.equal(input[index]);
arr.should.equal(array);
});
});
it('should map over the array with .map()', function () {
array.length.should.equal(16);
const out = array.map((item, index, arr) => {
item.should.equal(input[index]);
arr.should.equal(array);
return item + 1;
});
out.should.eql(input.map(item => item + 1));
});
it('should .filter() the array', function () {
array.length.should.equal(16);
const alts = array.filter((item, index, arr) => {
item.should.equal(input[index]);
arr.should.equal(array);
return index % 2;
});
alts.length.should.equal(array.length / 2);
alts.forEach((item, index) => {
item.should.equal(array[index * 2 + 1]);
});
});
it('should reduce the array to a final value', function () {
array.length.should.equal(16);
const result = array.reduce((acc, item) => {
acc.push(item);
return acc;
}, []);
result.should.eql(input);
});
it('should reduce without an initial value', function () {
array.length.should.equal(16);
const result = array.reduce((acc, item) => {
return item;
});
result.should.equal(input[15]);
});
it('should clear the array', function () {
XArray.clear(array[_symbols.$Backing], array[_symbols.$Address]);
});
it('should have empty values for contents', function () {
array.length.should.equal(16);
array.forEach(item => {
item.should.eql(Type.emptyValue());
});
});
it('should destroy the array', function () {
XArray.destructor(array[_symbols.$Backing], array[_symbols.$Address]);
});
it('should now have a length of zero', function () {
array.length.should.equal(0);
});
it('should create a random array', function () {
const random = XArray.randomValue();
});
describe('Multidimensional', function () {
let Grid;
let grid;
before(() => {
Grid = new ArrayType(XArray);
});
it('should create an instance', function () {
grid = new Grid(Array.from({ length: 16 }, () => input));
});
it('should have the right length', function () {
grid.length.should.equal(16);
});
it('should allow nested lookups', function () {
grid[1][1].should.equal(input[1]);
});
});
describe('Array within a struct', function () {
let Simple;
let simple;
before(() => {
Simple = new StructType({ value: XArray });
});
it('should create an instance', function () {
simple = new Simple();
});
it('should load the property', function () {
simple.value.should.be.an.instanceOf(XArray);
simple.value.length.should.equal(0);
});
it('should set a new value', function () {
simple.value = input;
});
it('should have cast the value to the right type', function () {
simple.value.should.be.an.instanceOf(XArray);
});
it('should have the right length', function () {
simple.value.length.should.equal(input.length);
});
it('should overwrite the value', function () {
simple.value = [Type.randomValue()];
});
it('should have the right length', function () {
simple.value.length.should.equal(1);
});
it('should create an instance with some values', function () {
simple = new Simple({ value: input });
});
it('should have stored the value', function () {
simple.value.length.should.equal(input.length);
simple.value.should.be.an.instanceOf(XArray);
simple.value.map(item => item).should.eql(input);
});
});
describe('Struct within an array', function () {
let ListNode;
let ListArray;
let array;
before(() => {
ListNode = new StructType();
ListNode.finalize({
value: Type,
prev: ListNode.ref,
next: ListNode.ref
});
});
it('should create an array of list items', function () {
ListArray = new ArrayType(ListNode);
});
it('should create a new array instance', function () {
array = new ListArray(16);
});
it('should have set the default values', function () {
array.length.should.equal(16);
array.forEach(item => {
item.value.should.equal(Type.emptyValue());
});
});
it('should create a struct array from input', function () {
array = new ListArray(input.map(value => ({ value: value })));
});
it('should have the right length', function () {
array.length.should.equal(input.length);
});
it('should have set the right values', function () {
input.forEach((value, index) => {
array[index].value.should.eql(value);
});
});
});
});
});
it('should create a new base array type', function () {
new ArrayType(T.Int32).should.equal(T.Int32.Array);
});
it('T.Int32.Array should be an instance of ArrayType', function () {
T.Int32.Array.should.be.an.instanceOf(ArrayType);
});
it('should create an instance of the array', function () {
const instance = new T.Int32.Array(20);
});
it('should create an instance of the array from an array', function () {
const input = Array.from({ length: 20 }, (_, index) => index + 1);
const instance = new T.Int32.Array(input);
});
describe('Benchmarks', function () {
let _Custom, _Native;
let custom, native;
let input;
it('should set up the types', function () {
_Custom = T.Int32.Array;
_Native = Int32Array;
input = Array.from({ length: 200 }, (_, index) => index + 1);
custom = new _Custom(input);
native = new _Native(input);
native.length.should.equal(custom.length);
});
benchmark('Read single elements', 100000, {
Custom: function Custom() {
return custom[2];
},
Native: function Native() {
return native[2];
}
});
benchmark('Read multiple elements', 100000, {
Custom: function Custom() {
return custom[2] + custom[6] + custom[9];
},
Native: function Native() {
return native[2] + native[6] + native[9];
}
});
benchmark('Sum elements', 5000, {
Custom: function Custom() {
let total = 0;
for (let item of custom) {
total += item;
}
return total;
},
Native: function Native() {
let total = 0;
for (let item of native) {
total += item;
}
return total;
}
});
benchmark('.forEach()', 10000, {
Custom: function Custom() {
let total = 0;
custom.forEach(item => total += item);
return total;
},
Native: function Native() {
let total = 0;
native.forEach(item => total += item);
return total;
}
});
benchmark('.map()', 10000, {
Custom: function Custom() {
return custom.map(item => item + 1);
},
Native: function Native() {
return native.map(item => item + 1);
}
});
benchmark('.filter()', 10000, {
Custom: function Custom() {
return custom.filter((item, index) => index % 2);
},
Native: function Native() {
return native.filter((item, index) => index % 2);
}
});
benchmark('.reduce()', 10000, {
Custom: function Custom() {
return custom.reduce((acc, item) => {
return acc + item;
}, 0);
},
Native: function Native() {
return native.reduce((acc, item) => {
return acc + item;
}, 0);
}
});
benchmark('.reduce() without an initial value', 10000, {
Custom: function Custom() {
return custom.reduce((acc, item) => item);
},
Native: function Native() {
return native.reduce((acc, item) => item);
}
});
benchmark('Create instances', 2000, {
Custom: function Custom() {
return new _Custom(input);
},
Native: function Native() {
return new _Native(input);
}
});
});
});