gristlabs_grist-core/test/common/BinaryIndexedTree.js
Paul Fitzpatrick bcbf57d590 (core) bump mocha version to allow parallel tests; move more tests to core
Summary:
This uses a newer version of mocha in grist-core so that tests can be run in parallel. That allows more tests to be moved without slowing things down overall. Tests moved are venerable browser tests; only the ones that "just work" or worked without too much trouble to are moved, in order to keep the diff from growing too large. Will wrestle with more in follow up.

Parallelism is at the file level, rather than the individual test.

The newer version of mocha isn't needed for grist-saas repo; tests are parallelized in our internal CI by other means. I've chosen to allocate files to workers in a cruder way than our internal CI, based on initial characters rather than an automated process. The automated process would need some reworking to be compatible with mocha running in parallel mode.

Test Plan: this diff was tested first on grist-core, then ported to grist-saas so saas repo history will correctly track history of moved files.

Reviewers: jarek

Reviewed By: jarek

Subscribers: jarek

Differential Revision: https://phab.getgrist.com/D3927
2023-06-27 02:55:34 -04:00

243 lines
9.3 KiB
JavaScript

var assert = require('assert');
var BinaryIndexedTree = require('app/common/BinaryIndexedTree');
describe("BinaryIndexedTree", function() {
describe('#leastSignificantOne', function() {
it("should only keep the least significant one", function() {
assert.equal(BinaryIndexedTree.leastSignificantOne(1), 1);
assert.equal(BinaryIndexedTree.leastSignificantOne(6), 2);
assert.equal(BinaryIndexedTree.leastSignificantOne(15), 1);
assert.equal(BinaryIndexedTree.leastSignificantOne(16), 16);
assert.equal(BinaryIndexedTree.leastSignificantOne(0), 0);
});
});
describe('#stripLeastSignificantOne', function() {
it("should strip the least significant one", function() {
assert.equal(BinaryIndexedTree.stripLeastSignificantOne(1), 0);
assert.equal(BinaryIndexedTree.stripLeastSignificantOne(6), 4);
assert.equal(BinaryIndexedTree.stripLeastSignificantOne(15), 14);
assert.equal(BinaryIndexedTree.stripLeastSignificantOne(16), 0);
assert.equal(BinaryIndexedTree.stripLeastSignificantOne(0), 0);
assert.equal(BinaryIndexedTree.stripLeastSignificantOne(24), 16);
});
});
describe('#mostSignificantOne', function() {
it("should keep the most significant one", function() {
assert.equal(BinaryIndexedTree.mostSignificantOne(1), 1);
assert.equal(BinaryIndexedTree.mostSignificantOne(6), 4);
assert.equal(BinaryIndexedTree.mostSignificantOne(15), 8);
assert.equal(BinaryIndexedTree.mostSignificantOne(16), 16);
assert.equal(BinaryIndexedTree.mostSignificantOne(24), 16);
assert.equal(BinaryIndexedTree.mostSignificantOne(0), 0);
});
});
describe('#cumulToValues', function() {
it("should convert cumulative array to regular values", function() {
assert.deepEqual(BinaryIndexedTree.cumulToValues([1, 3, 6, 10]), [1, 2, 3, 4]);
assert.deepEqual(BinaryIndexedTree.cumulToValues([1, 3, 6, 10, 15, 21]), [1, 2, 3, 4, 5, 6]);
assert.deepEqual(BinaryIndexedTree.cumulToValues([]), []);
});
});
describe('#valuesToCumul', function() {
it("should convert value array to cumulative array", function() {
assert.deepEqual(BinaryIndexedTree.valuesToCumul([1, 2, 3, 4]), [1, 3, 6, 10]);
assert.deepEqual(BinaryIndexedTree.valuesToCumul([1, 2, 3, 4, 5, 6]), [1, 3, 6, 10, 15, 21]);
assert.deepEqual(BinaryIndexedTree.valuesToCumul([]), []);
});
});
//----------------------------------------------------------------------
// Test array of length 25.
var data1 = [47, 17, 28, 96, 10, 2, 11, 43, 7, 94, 37, 81, 75, 2, 33, 57, 68, 71, 68, 86, 27, 44, 64, 41, 23];
// Test array of length 64.
var data2 = [722, 106, 637, 881, 752, 940, 989, 295, 344, 716, 283, 609, 482, 268, 884, 782, 628, 778, 442, 456, 171, 821, 346, 367, 12, 46, 582, 164, 876, 421, 749, 357, 586, 319, 847, 79, 649, 353, 545, 353, 609, 865, 229, 476, 697, 579, 109, 935, 412, 286, 701, 712, 288, 45, 990, 176, 775, 143, 187, 241, 721, 691, 162, 460];
var cdata1, cdata2; // Cumulative versions.
function dumbGetCumulativeValue(array, index) {
for (var i = 0, x = 0; i <= index; i++) {
x += array[i];
}
return x;
}
/*
function dumbGetIndex(array, cumulValue) {
for (var i = 0, x = 0; i <= array.length && x <= cumulValue; i++) {
x += array[i];
}
return i;
}
*/
before(function() {
cdata1 = data1.map(function(value, i) { return dumbGetCumulativeValue(data1, i); });
cdata2 = data2.map(function(value, i) { return dumbGetCumulativeValue(data2, i); });
});
describe('BinaryIndexedTree class', function() {
it("should construct trees with zeroes", function() {
var bit = new BinaryIndexedTree();
assert.equal(bit.size(), 0);
bit.fillFromValues([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
var bit2 = new BinaryIndexedTree(10);
assert.deepEqual(bit, bit2);
});
it("should convert from cumulative array and back", function() {
var bit = new BinaryIndexedTree();
bit.fillFromCumulative(cdata1);
assert.equal(bit.size(), 25);
assert.deepEqual(bit.toCumulativeArray(), cdata1);
assert.deepEqual(bit.toValueArray(), data1);
bit.fillFromCumulative([]);
assert.equal(bit.size(), 0);
assert.deepEqual(bit.toCumulativeArray(), []);
assert.deepEqual(bit.toValueArray(), []);
bit.fillFromCumulative(cdata2);
assert.equal(bit.size(), 64);
assert.deepEqual(bit.toCumulativeArray(), cdata2);
assert.deepEqual(bit.toValueArray(), data2);
});
it("should convert from value array and back", function() {
var bit = new BinaryIndexedTree();
bit.fillFromValues(data1);
assert.equal(bit.size(), 25);
assert.deepEqual(bit.toCumulativeArray(), cdata1);
assert.deepEqual(bit.toValueArray(), data1);
bit.fillFromValues([]);
assert.equal(bit.size(), 0);
assert.deepEqual(bit.toCumulativeArray(), []);
assert.deepEqual(bit.toValueArray(), []);
bit.fillFromValues(data2);
assert.equal(bit.size(), 64);
assert.deepEqual(bit.toCumulativeArray(), cdata2);
assert.deepEqual(bit.toValueArray(), data2);
bit.fillFromValues([1, 2, 3, 4, 5]);
assert.equal(bit.size(), 5);
assert.deepEqual(bit.toCumulativeArray(), [1, 3, 6, 10, 15]);
assert.deepEqual(bit.toValueArray(), [1, 2, 3, 4, 5]);
});
it("should compute individual and cumulative values", function() {
var i, bit = new BinaryIndexedTree();
bit.fillFromValues(data1);
assert.equal(bit.size(), 25);
for (i = 0; i < 25; i++) {
assert.equal(bit.getValue(i), data1[i]);
assert.equal(bit.getCumulativeValue(i), cdata1[i]);
assert.equal(bit.getSumTo(i), cdata1[i] - data1[i]);
}
assert.equal(bit.getTotal(), data1.reduce(function(a, b) { return a + b; }));
bit.fillFromValues(data2);
assert.equal(bit.size(), 64);
for (i = 0; i < 64; i++) {
assert.equal(bit.getValue(i), data2[i]);
assert.equal(bit.getCumulativeValue(i), cdata2[i]);
assert.equal(bit.getSumTo(i), cdata2[i] - data2[i]);
}
assert.equal(bit.getTotal(), data2.reduce(function(a, b) { return a + b; }));
});
it("should compute cumulative range values", function() {
var i, bit = new BinaryIndexedTree();
bit.fillFromValues(data1);
assert.equal(bit.getCumulativeValueRange(0, data1.length),
bit.getCumulativeValue(data1.length-1));
for(i = 1; i < 25; i++) {
assert.equal(bit.getCumulativeValueRange(i, 25),
cdata1[24] - cdata1[i-1]);
}
for(i = 24; i >= 0; i-- ){
assert.equal(bit.getCumulativeValueRange(0, i+1), cdata1[i]);
}
bit.fillFromValues(data2);
assert.equal(bit.getCumulativeValueRange(0, 64),
bit.getCumulativeValue(63));
for(i = 1; i < 64; i++) {
assert.equal(bit.getCumulativeValueRange(i, 64),
cdata2[63] - cdata2[i-1]);
}
for(i = 63; i >= 0; i-- ){
assert.equal(bit.getCumulativeValueRange(0, i+1), cdata2[i]);
}
});
it("should search by cumulative value", function() {
var bit = new BinaryIndexedTree();
bit.fillFromValues([1, 2, 3, 4]);
assert.equal(bit.getIndex(-1), 0);
assert.equal(bit.getIndex(0), 0);
assert.equal(bit.getIndex(1), 0);
assert.equal(bit.getIndex(2), 1);
assert.equal(bit.getIndex(3), 1);
assert.equal(bit.getIndex(4), 2);
assert.equal(bit.getIndex(5), 2);
assert.equal(bit.getIndex(6), 2);
assert.equal(bit.getIndex(7), 3);
assert.equal(bit.getIndex(8), 3);
assert.equal(bit.getIndex(9), 3);
assert.equal(bit.getIndex(10), 3);
assert.equal(bit.getIndex(11), 4);
bit.fillFromValues(data1);
// data1 is [47,17,28,96,10,2,11,43,7,94,37,81,75,2,33,57,68,71,68,86,27,44,64,41,23];
assert.equal(bit.getIndex(0), 0);
assert.equal(bit.getIndex(1), 0);
assert.equal(bit.getIndex(46.9), 0);
assert.equal(bit.getIndex(47), 0);
assert.equal(bit.getIndex(63), 1);
assert.equal(bit.getIndex(64), 1);
assert.equal(bit.getIndex(64.1), 2);
assert.equal(bit.getIndex(bit.getCumulativeValue(5)), 5);
assert.equal(bit.getIndex(bit.getCumulativeValue(20)), 20);
assert.equal(bit.getIndex(bit.getCumulativeValue(24)), 24);
assert.equal(bit.getIndex(1000000), 25);
});
it("should support add and set", function() {
var i, bit = new BinaryIndexedTree(4);
bit.setValue(1, 2);
assert.deepEqual(bit.toValueArray(), [0, 2, 0, 0]);
bit.setValue(3, 4);
assert.deepEqual(bit.toValueArray(), [0, 2, 0, 4]);
bit.setValue(0, 1);
assert.deepEqual(bit.toValueArray(), [1, 2, 0, 4]);
bit.addValue(2, 1);
assert.deepEqual(bit.toValueArray(), [1, 2, 1, 4]);
bit.addValue(2, 1);
assert.deepEqual(bit.toValueArray(), [1, 2, 2, 4]);
bit.addValue(2, 1);
assert.deepEqual(bit.toValueArray(), [1, 2, 3, 4]);
bit.fillFromValues(data1);
for (i = 0; i < data1.length; i++) {
bit.addValue(i, -data1[i]);
}
assert.deepEqual(bit.toValueArray(), data1.map(function() { return 0; }));
bit.fillFromValues(data1);
for (i = data1.length - 1; i >= 0; i--) {
bit.addValue(i, data1[i]);
}
assert.deepEqual(bit.toValueArray(), data1.map(function(x) { return 2*x; }));
});
});
});