Merge branch 'core_integration' into fix_imports
This commit is contained in:
@@ -1,14 +1,16 @@
|
|||||||
function mainThread() {
|
function mainThread() {
|
||||||
var maxDepth = max(6, Number(arg[0] || 16));
|
var maxDepth = max(6, Number(arg[0] || 16));
|
||||||
|
|
||||||
var stretchDepth = maxDepth + 1;
|
var stretchDepth = maxDepth + 1;
|
||||||
var check = itemCheck(bottomUpTree(stretchDepth));
|
var check = itemCheck(bottomUpTree(stretchDepth));
|
||||||
|
var longLivedTree = null
|
||||||
|
var depth = null
|
||||||
|
var iterations = null
|
||||||
log.console(`stretch tree of depth ${stretchDepth}\t check: ${check}`);
|
log.console(`stretch tree of depth ${stretchDepth}\t check: ${check}`);
|
||||||
|
|
||||||
var longLivedTree = bottomUpTree(maxDepth);
|
longLivedTree = bottomUpTree(maxDepth);
|
||||||
|
|
||||||
for (var depth = 4; depth <= maxDepth; depth += 2) {
|
for (depth = 4; depth <= maxDepth; depth += 2) {
|
||||||
var iterations = 1 << maxDepth - depth + 4;
|
iterations = 1 << maxDepth - depth + 4;
|
||||||
work(iterations, depth);
|
work(iterations, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,7 +19,8 @@ function mainThread() {
|
|||||||
|
|
||||||
function work(iterations, depth) {
|
function work(iterations, depth) {
|
||||||
var check = 0;
|
var check = 0;
|
||||||
for (var i = 0; i < iterations; i++)
|
var i = 0
|
||||||
|
for (i = 0; i < iterations; i++)
|
||||||
check += itemCheck(bottomUpTree(depth));
|
check += itemCheck(bottomUpTree(depth));
|
||||||
log.console(`${iterations}\t trees of depth ${depth}\t check: ${check}`);
|
log.console(`${iterations}\t trees of depth ${depth}\t check: ${check}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
var blob = use('blob')
|
var blob = use('blob')
|
||||||
var math = use('math/radians')
|
var math = use('math/radians')
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
var j = 0
|
||||||
|
|
||||||
function eratosthenes (n) {
|
function eratosthenes (n) {
|
||||||
var sieve = blob(n, true)
|
var sieve = blob(n, true)
|
||||||
var sqrtN = whole(math.sqrt(n));
|
var sqrtN = whole(math.sqrt(n));
|
||||||
@@ -17,7 +20,7 @@ var sieve = eratosthenes(10000000);
|
|||||||
stone(sieve)
|
stone(sieve)
|
||||||
|
|
||||||
var c = 0
|
var c = 0
|
||||||
for (var i = 0; i < length(sieve); i++)
|
for (i = 0; i < length(sieve); i++)
|
||||||
if (sieve.read_logical(i)) c++
|
if (sieve.read_logical(i)) c++
|
||||||
|
|
||||||
log.console(c)
|
log.console(c)
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
function fannkuch(n) {
|
function fannkuch(n) {
|
||||||
var perm1 = [n]
|
var perm1 = [n]
|
||||||
for (var i = 0; i < n; i++) perm1[i] = i
|
var i = 0
|
||||||
|
var k = null
|
||||||
|
var r = null
|
||||||
|
var t = null
|
||||||
|
var p0 = null
|
||||||
|
var j = null
|
||||||
|
var more = null
|
||||||
|
for (i = 0; i < n; i++) perm1[i] = i
|
||||||
var perm = [n]
|
var perm = [n]
|
||||||
var count = [n]
|
var count = [n]
|
||||||
var f = 0, flips = 0, nperm = 0, checksum = 0
|
var f = 0
|
||||||
var i, k, r
|
var flips = 0
|
||||||
|
var nperm = 0
|
||||||
|
var checksum = 0
|
||||||
|
|
||||||
r = n
|
r = n
|
||||||
while (r > 0) {
|
while (r > 0) {
|
||||||
@@ -12,13 +21,12 @@ function fannkuch(n) {
|
|||||||
while (r != 1) { count[r-1] = r; r -= 1 }
|
while (r != 1) { count[r-1] = r; r -= 1 }
|
||||||
while (i < n) { perm[i] = perm1[i]; i += 1 }
|
while (i < n) { perm[i] = perm1[i]; i += 1 }
|
||||||
|
|
||||||
// Count flips and update max and checksum
|
|
||||||
f = 0
|
f = 0
|
||||||
k = perm[0]
|
k = perm[0]
|
||||||
while (k != 0) {
|
while (k != 0) {
|
||||||
i = 0
|
i = 0
|
||||||
while (2*i < k) {
|
while (2*i < k) {
|
||||||
var t = perm[i]; perm[i] = perm[k-i]; perm[k-i] = t
|
t = perm[i]; perm[i] = perm[k-i]; perm[k-i] = t
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
k = perm[0]
|
k = perm[0]
|
||||||
@@ -27,17 +35,16 @@ function fannkuch(n) {
|
|||||||
if (f > flips) flips = f
|
if (f > flips) flips = f
|
||||||
if ((nperm & 0x1) == 0) checksum += f; else checksum -= f
|
if ((nperm & 0x1) == 0) checksum += f; else checksum -= f
|
||||||
|
|
||||||
// Use incremental change to generate another permutation
|
more = true
|
||||||
var more = true
|
|
||||||
while (more) {
|
while (more) {
|
||||||
if (r == n) {
|
if (r == n) {
|
||||||
log.console( checksum )
|
log.console( checksum )
|
||||||
return flips
|
return flips
|
||||||
}
|
}
|
||||||
var p0 = perm1[0]
|
p0 = perm1[0]
|
||||||
i = 0
|
i = 0
|
||||||
while (i < r) {
|
while (i < r) {
|
||||||
var j = i + 1
|
j = i + 1
|
||||||
perm1[i] = perm1[j]
|
perm1[i] = perm1[j]
|
||||||
i = j
|
i = j
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,12 @@
|
|||||||
var time = use('time')
|
var time = use('time')
|
||||||
var math = use('math/radians')
|
var math = use('math/radians')
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// JavaScript Performance Benchmark Suite
|
|
||||||
// Tests core JS operations: property access, function calls, arithmetic, etc.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Test configurations
|
|
||||||
def iterations = {
|
def iterations = {
|
||||||
simple: 10000000,
|
simple: 10000000,
|
||||||
medium: 1000000,
|
medium: 1000000,
|
||||||
complex: 100000
|
complex: 100000
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Utility: measureTime(fn) => how long fn() takes in seconds
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function measureTime(fn) {
|
function measureTime(fn) {
|
||||||
var start = time.number();
|
var start = time.number();
|
||||||
fn();
|
fn();
|
||||||
@@ -24,10 +14,6 @@ function measureTime(fn) {
|
|||||||
return (end - start);
|
return (end - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Benchmark: Property Access
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function benchPropertyAccess() {
|
function benchPropertyAccess() {
|
||||||
var obj = {
|
var obj = {
|
||||||
a: 1, b: 2, c: 3, d: 4, e: 5,
|
a: 1, b: 2, c: 3, d: 4, e: 5,
|
||||||
@@ -36,14 +22,16 @@ function benchPropertyAccess() {
|
|||||||
|
|
||||||
var readTime = measureTime(function() {
|
var readTime = measureTime(function() {
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
for (var i = 0; i < iterations.simple; i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < iterations.simple; i++) {
|
||||||
sum += obj.a + obj.b + obj.c + obj.d + obj.e;
|
sum += obj.a + obj.b + obj.c + obj.d + obj.e;
|
||||||
sum += obj.nested.x + obj.nested.y + obj.nested.z;
|
sum += obj.nested.x + obj.nested.y + obj.nested.z;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var writeTime = measureTime(function() {
|
var writeTime = measureTime(function() {
|
||||||
for (var i = 0; i < iterations.simple; i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < iterations.simple; i++) {
|
||||||
obj.a = i;
|
obj.a = i;
|
||||||
obj.b = i + 1;
|
obj.b = i + 1;
|
||||||
obj.c = i + 2;
|
obj.c = i + 2;
|
||||||
@@ -55,10 +43,6 @@ function benchPropertyAccess() {
|
|||||||
return { readTime: readTime, writeTime: writeTime };
|
return { readTime: readTime, writeTime: writeTime };
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Benchmark: Function Calls
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function benchFunctionCalls() {
|
function benchFunctionCalls() {
|
||||||
function add(a, b) { return a + b; }
|
function add(a, b) { return a + b; }
|
||||||
function multiply(a, b) { return a * b; }
|
function multiply(a, b) { return a * b; }
|
||||||
@@ -73,7 +57,8 @@ function benchFunctionCalls() {
|
|||||||
|
|
||||||
var simpleCallTime = measureTime(function() {
|
var simpleCallTime = measureTime(function() {
|
||||||
var result = 0;
|
var result = 0;
|
||||||
for (var i = 0; i < iterations.simple; i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < iterations.simple; i++) {
|
||||||
result = add(i, 1);
|
result = add(i, 1);
|
||||||
result = multiply(result, 2);
|
result = multiply(result, 2);
|
||||||
}
|
}
|
||||||
@@ -81,7 +66,8 @@ function benchFunctionCalls() {
|
|||||||
|
|
||||||
var methodCallTime = measureTime(function() {
|
var methodCallTime = measureTime(function() {
|
||||||
var result = 0;
|
var result = 0;
|
||||||
for (var i = 0; i < iterations.simple; i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < iterations.simple; i++) {
|
||||||
result = obj.method(i);
|
result = obj.method(i);
|
||||||
result = obj.nested.deepMethod(result, i);
|
result = obj.nested.deepMethod(result, i);
|
||||||
}
|
}
|
||||||
@@ -89,7 +75,8 @@ function benchFunctionCalls() {
|
|||||||
|
|
||||||
var complexCallTime = measureTime(function() {
|
var complexCallTime = measureTime(function() {
|
||||||
var result = 0;
|
var result = 0;
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < iterations.medium; i++) {
|
||||||
result = complexCalc(i, i + 1, i + 2);
|
result = complexCalc(i, i + 1, i + 2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -101,33 +88,35 @@ function benchFunctionCalls() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Benchmark: Array Operations
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function benchArrayOps() {
|
function benchArrayOps() {
|
||||||
|
var i = 0
|
||||||
|
|
||||||
var pushTime = measureTime(function() {
|
var pushTime = measureTime(function() {
|
||||||
var arr = [];
|
var arr = [];
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var j = 0
|
||||||
push(arr, i);
|
for (j = 0; j < iterations.medium; j++) {
|
||||||
|
push(arr, j);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var arr = [];
|
var arr = [];
|
||||||
for (var i = 0; i < 10000; i++) push(arr, i);
|
for (i = 0; i < 10000; i++) push(arr, i);
|
||||||
|
|
||||||
var accessTime = measureTime(function() {
|
var accessTime = measureTime(function() {
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var j = 0
|
||||||
sum += arr[i % 10000];
|
for (j = 0; j < iterations.medium; j++) {
|
||||||
|
sum += arr[j % 10000];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var iterateTime = measureTime(function() {
|
var iterateTime = measureTime(function() {
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
for (var j = 0; j < 1000; j++) {
|
var j = 0
|
||||||
for (var i = 0; i < length(arr); i++) {
|
var k = 0
|
||||||
sum += arr[i];
|
for (j = 0; j < 1000; j++) {
|
||||||
|
for (k = 0; k < length(arr); k++) {
|
||||||
|
sum += arr[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -139,14 +128,12 @@ function benchArrayOps() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Benchmark: Object Creation
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function benchObjectCreation() {
|
function benchObjectCreation() {
|
||||||
var literalTime = measureTime(function() {
|
var literalTime = measureTime(function() {
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var i = 0
|
||||||
var obj = { x: i, y: i * 2, z: i * 3 };
|
var obj = null
|
||||||
|
for (i = 0; i < iterations.medium; i++) {
|
||||||
|
obj = { x: i, y: i * 2, z: i * 3 };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -155,8 +142,10 @@ function benchObjectCreation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var defructorTime = measureTime(function() {
|
var defructorTime = measureTime(function() {
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var i = 0
|
||||||
var p = Point(i, i * 2);
|
var p = null
|
||||||
|
for (i = 0; i < iterations.medium; i++) {
|
||||||
|
p = Point(i, i * 2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -170,8 +159,10 @@ function benchObjectCreation() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var prototypeTime = measureTime(function() {
|
var prototypeTime = measureTime(function() {
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var i = 0
|
||||||
var obj = meme(protoObj);
|
var obj = null
|
||||||
|
for (i = 0; i < iterations.medium; i++) {
|
||||||
|
obj = meme(protoObj);
|
||||||
obj.x = i;
|
obj.x = i;
|
||||||
obj.y = i * 2;
|
obj.y = i * 2;
|
||||||
}
|
}
|
||||||
@@ -184,33 +175,36 @@ function benchObjectCreation() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Benchmark: String Operations
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function benchStringOps() {
|
function benchStringOps() {
|
||||||
|
var i = 0
|
||||||
|
var strings = [];
|
||||||
|
|
||||||
var concatTime = measureTime(function() {
|
var concatTime = measureTime(function() {
|
||||||
var str = "";
|
var str = "";
|
||||||
for (var i = 0; i < iterations.complex; i++) {
|
var j = 0
|
||||||
str = "test" + i + "value";
|
for (j = 0; j < iterations.complex; j++) {
|
||||||
|
str = "test" + j + "value";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var strings = [];
|
for (i = 0; i < 1000; i++) {
|
||||||
for (var i = 0; i < 1000; i++) {
|
|
||||||
push(strings, "string" + i);
|
push(strings, "string" + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
var joinTime = measureTime(function() {
|
var joinTime = measureTime(function() {
|
||||||
for (var i = 0; i < iterations.complex; i++) {
|
var j = 0
|
||||||
var result = text(strings, ",");
|
var result = null
|
||||||
|
for (j = 0; j < iterations.complex; j++) {
|
||||||
|
result = text(strings, ",");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var splitTime = measureTime(function() {
|
var splitTime = measureTime(function() {
|
||||||
var str = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p";
|
var str = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p";
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var j = 0
|
||||||
var parts = array(str, ",");
|
var parts = null
|
||||||
|
for (j = 0; j < iterations.medium; j++) {
|
||||||
|
parts = array(str, ",");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -221,14 +215,11 @@ function benchStringOps() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Benchmark: Arithmetic Operations
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function benchArithmetic() {
|
function benchArithmetic() {
|
||||||
var intMathTime = measureTime(function() {
|
var intMathTime = measureTime(function() {
|
||||||
var result = 1;
|
var result = 1;
|
||||||
for (var i = 0; i < iterations.simple; i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < iterations.simple; i++) {
|
||||||
result = ((result + i) * 2 - 1) / 3;
|
result = ((result + i) * 2 - 1) / 3;
|
||||||
result = result % 1000 + 1;
|
result = result % 1000 + 1;
|
||||||
}
|
}
|
||||||
@@ -236,7 +227,8 @@ function benchArithmetic() {
|
|||||||
|
|
||||||
var floatMathTime = measureTime(function() {
|
var floatMathTime = measureTime(function() {
|
||||||
var result = 1.5;
|
var result = 1.5;
|
||||||
for (var i = 0; i < iterations.simple; i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < iterations.simple; i++) {
|
||||||
result = math.sine(result) + math.cosine(i * 0.01);
|
result = math.sine(result) + math.cosine(i * 0.01);
|
||||||
result = math.sqrt(abs(result)) + 0.1;
|
result = math.sqrt(abs(result)) + 0.1;
|
||||||
}
|
}
|
||||||
@@ -244,7 +236,8 @@ function benchArithmetic() {
|
|||||||
|
|
||||||
var bitwiseTime = measureTime(function() {
|
var bitwiseTime = measureTime(function() {
|
||||||
var result = 0;
|
var result = 0;
|
||||||
for (var i = 0; i < iterations.simple; i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < iterations.simple; i++) {
|
||||||
result = (result ^ i) & 0xFFFF;
|
result = (result ^ i) & 0xFFFF;
|
||||||
result = (result << 1) | (result >> 15);
|
result = (result << 1) | (result >> 15);
|
||||||
}
|
}
|
||||||
@@ -257,31 +250,31 @@ function benchArithmetic() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Benchmark: Closure Operations
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function benchClosures() {
|
function benchClosures() {
|
||||||
|
var i = 0
|
||||||
|
|
||||||
function makeAdder(x) {
|
function makeAdder(x) {
|
||||||
return function(y) { return x + y; };
|
return function(y) { return x + y; };
|
||||||
}
|
}
|
||||||
|
|
||||||
var closureCreateTime = measureTime(function() {
|
var closureCreateTime = measureTime(function() {
|
||||||
var funcs = [];
|
var funcs = [];
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var j = 0
|
||||||
push(funcs, makeAdder(i));
|
for (j = 0; j < iterations.medium; j++) {
|
||||||
|
push(funcs, makeAdder(j));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var adders = [];
|
var adders = [];
|
||||||
for (var i = 0; i < 1000; i++) {
|
for (i = 0; i < 1000; i++) {
|
||||||
push(adders, makeAdder(i));
|
push(adders, makeAdder(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
var closureCallTime = measureTime(function() {
|
var closureCallTime = measureTime(function() {
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
for (var i = 0; i < iterations.medium; i++) {
|
var j = 0
|
||||||
sum += adders[i % 1000](i);
|
for (j = 0; j < iterations.medium; j++) {
|
||||||
|
sum += adders[j % 1000](j);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -291,14 +284,9 @@ function benchClosures() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Main benchmark runner
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
log.console("JavaScript Performance Benchmark");
|
log.console("JavaScript Performance Benchmark");
|
||||||
log.console("======================\n");
|
log.console("======================\n");
|
||||||
|
|
||||||
// Property Access
|
|
||||||
log.console("BENCHMARK: Property Access");
|
log.console("BENCHMARK: Property Access");
|
||||||
var propResults = benchPropertyAccess();
|
var propResults = benchPropertyAccess();
|
||||||
log.console(" Read time: " + propResults.readTime.toFixed(3) + "s => " +
|
log.console(" Read time: " + propResults.readTime.toFixed(3) + "s => " +
|
||||||
@@ -309,7 +297,6 @@ log.console(" Write time: " + propResults.writeTime.toFixed(3) + "s => " +
|
|||||||
(propResults.writeTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
(propResults.writeTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
||||||
log.console("");
|
log.console("");
|
||||||
|
|
||||||
// Function Calls
|
|
||||||
log.console("BENCHMARK: Function Calls");
|
log.console("BENCHMARK: Function Calls");
|
||||||
var funcResults = benchFunctionCalls();
|
var funcResults = benchFunctionCalls();
|
||||||
log.console(" Simple calls: " + funcResults.simpleCallTime.toFixed(3) + "s => " +
|
log.console(" Simple calls: " + funcResults.simpleCallTime.toFixed(3) + "s => " +
|
||||||
@@ -323,7 +310,6 @@ log.console(" Complex calls: " + funcResults.complexCallTime.toFixed(3) + "s =>
|
|||||||
(funcResults.complexCallTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
(funcResults.complexCallTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
||||||
log.console("");
|
log.console("");
|
||||||
|
|
||||||
// Array Operations
|
|
||||||
log.console("BENCHMARK: Array Operations");
|
log.console("BENCHMARK: Array Operations");
|
||||||
var arrayResults = benchArrayOps();
|
var arrayResults = benchArrayOps();
|
||||||
log.console(" Push: " + arrayResults.pushTime.toFixed(3) + "s => " +
|
log.console(" Push: " + arrayResults.pushTime.toFixed(3) + "s => " +
|
||||||
@@ -336,7 +322,6 @@ log.console(" Iterate: " + arrayResults.iterateTime.toFixed(3) + "s => " +
|
|||||||
(1000 / arrayResults.iterateTime).toFixed(1) + " full iterations/sec");
|
(1000 / arrayResults.iterateTime).toFixed(1) + " full iterations/sec");
|
||||||
log.console("");
|
log.console("");
|
||||||
|
|
||||||
// Object Creation
|
|
||||||
log.console("BENCHMARK: Object Creation");
|
log.console("BENCHMARK: Object Creation");
|
||||||
var objResults = benchObjectCreation();
|
var objResults = benchObjectCreation();
|
||||||
log.console(" Literal: " + objResults.literalTime.toFixed(3) + "s => " +
|
log.console(" Literal: " + objResults.literalTime.toFixed(3) + "s => " +
|
||||||
@@ -350,7 +335,6 @@ log.console(" Prototype: " + objResults.prototypeTime.toFixed(3) + "s => " +
|
|||||||
(objResults.prototypeTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
(objResults.prototypeTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
||||||
log.console("");
|
log.console("");
|
||||||
|
|
||||||
// String Operations
|
|
||||||
log.console("BENCHMARK: String Operations");
|
log.console("BENCHMARK: String Operations");
|
||||||
var strResults = benchStringOps();
|
var strResults = benchStringOps();
|
||||||
log.console(" Concat: " + strResults.concatTime.toFixed(3) + "s => " +
|
log.console(" Concat: " + strResults.concatTime.toFixed(3) + "s => " +
|
||||||
@@ -364,7 +348,6 @@ log.console(" Split: " + strResults.splitTime.toFixed(3) + "s => " +
|
|||||||
(strResults.splitTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
(strResults.splitTime / iterations.medium * 1e9).toFixed(1) + " ns/op]");
|
||||||
log.console("");
|
log.console("");
|
||||||
|
|
||||||
// Arithmetic Operations
|
|
||||||
log.console("BENCHMARK: Arithmetic Operations");
|
log.console("BENCHMARK: Arithmetic Operations");
|
||||||
var mathResults = benchArithmetic();
|
var mathResults = benchArithmetic();
|
||||||
log.console(" Integer math: " + mathResults.intMathTime.toFixed(3) + "s => " +
|
log.console(" Integer math: " + mathResults.intMathTime.toFixed(3) + "s => " +
|
||||||
@@ -378,7 +361,6 @@ log.console(" Bitwise: " + mathResults.bitwiseTime.toFixed(3) + "s => " +
|
|||||||
(mathResults.bitwiseTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
(mathResults.bitwiseTime / iterations.simple * 1e9).toFixed(1) + " ns/op]");
|
||||||
log.console("");
|
log.console("");
|
||||||
|
|
||||||
// Closures
|
|
||||||
log.console("BENCHMARK: Closures");
|
log.console("BENCHMARK: Closures");
|
||||||
var closureResults = benchClosures();
|
var closureResults = benchClosures();
|
||||||
log.console(" Create: " + closureResults.closureCreateTime.toFixed(3) + "s => " +
|
log.console(" Create: " + closureResults.closureCreateTime.toFixed(3) + "s => " +
|
||||||
|
|||||||
@@ -1,39 +1,45 @@
|
|||||||
var blob = use('blob')
|
var blob = use('blob')
|
||||||
|
|
||||||
var iter = 50, limit = 2.0;
|
var iter = 50
|
||||||
var zr, zi, cr, ci, tr, ti;
|
var limit = 2.0
|
||||||
|
var zr = null
|
||||||
|
var zi = null
|
||||||
|
var cr = null
|
||||||
|
var ci = null
|
||||||
|
var tr = null
|
||||||
|
var ti = null
|
||||||
|
var y = 0
|
||||||
|
var x = 0
|
||||||
|
var i = 0
|
||||||
|
var row = null
|
||||||
|
|
||||||
var h = Number(arg[0]) || 500
|
var h = Number(arg[0]) || 500
|
||||||
var w = h
|
var w = h
|
||||||
|
|
||||||
log.console(`P4\n${w} ${h}`);
|
log.console(`P4\n${w} ${h}`);
|
||||||
|
|
||||||
for (var y = 0; y < h; ++y) {
|
for (y = 0; y < h; ++y) {
|
||||||
// Create a blob for the row - we need w bits
|
row = blob(w);
|
||||||
var row = blob(w);
|
|
||||||
|
|
||||||
for (var x = 0; x < w; ++x) {
|
for (x = 0; x < w; ++x) {
|
||||||
zr = zi = tr = ti = 0;
|
zr = 0; zi = 0; tr = 0; ti = 0;
|
||||||
cr = 2 * x / w - 1.5;
|
cr = 2 * x / w - 1.5;
|
||||||
ci = 2 * y / h - 1;
|
ci = 2 * y / h - 1;
|
||||||
for (var i = 0; i < iter && (tr + ti <= limit * limit); ++i) {
|
for (i = 0; i < iter && (tr + ti <= limit * limit); ++i) {
|
||||||
zi = 2 * zr * zi + ci;
|
zi = 2 * zr * zi + ci;
|
||||||
zr = tr - ti + cr;
|
zr = tr - ti + cr;
|
||||||
tr = zr * zr;
|
tr = zr * zr;
|
||||||
ti = zi * zi;
|
ti = zi * zi;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a 1 bit if inside the set, 0 if outside
|
|
||||||
if (tr + ti <= limit * limit)
|
if (tr + ti <= limit * limit)
|
||||||
row.write_bit(1);
|
row.write_bit(1);
|
||||||
else
|
else
|
||||||
row.write_bit(0);
|
row.write_bit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the blob to stone (immutable) to prepare for output
|
|
||||||
stone(row)
|
stone(row)
|
||||||
|
|
||||||
// Output the blob data as raw bytes
|
|
||||||
log.console(text(row, 'b'));
|
log.console(text(row, 'b'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
var math = use('math/radians')
|
var math = use('math/radians')
|
||||||
var N = 1000000;
|
var N = 1000000;
|
||||||
var num = 0;
|
var num = 0;
|
||||||
for (var i = 0; i < N; i ++) {
|
var i = 0
|
||||||
var x = 2 * $random();
|
var x = null
|
||||||
var y = $random();
|
var y = null
|
||||||
|
for (i = 0; i < N; i++) {
|
||||||
|
x = 2 * $random();
|
||||||
|
y = $random();
|
||||||
if (y < math.sine(x * x))
|
if (y < math.sine(x * x))
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,60 +2,60 @@ var math = use('math/radians')
|
|||||||
var SOLAR_MASS = 4 * pi * pi;
|
var SOLAR_MASS = 4 * pi * pi;
|
||||||
var DAYS_PER_YEAR = 365.24;
|
var DAYS_PER_YEAR = 365.24;
|
||||||
|
|
||||||
function Body(x, y, z, vx, vy, vz, mass) {
|
function Body(p) {
|
||||||
return {x, y, z, vx, vy, vz, mass};
|
return {x: p.x, y: p.y, z: p.z, vx: p.vx, vy: p.vy, vz: p.vz, mass: p.mass};
|
||||||
}
|
}
|
||||||
|
|
||||||
function Jupiter() {
|
function Jupiter() {
|
||||||
return Body(
|
return Body({
|
||||||
4.84143144246472090e+00,
|
x: 4.84143144246472090e+00,
|
||||||
-1.16032004402742839e+00,
|
y: -1.16032004402742839e+00,
|
||||||
-1.03622044471123109e-01,
|
z: -1.03622044471123109e-01,
|
||||||
1.66007664274403694e-03 * DAYS_PER_YEAR,
|
vx: 1.66007664274403694e-03 * DAYS_PER_YEAR,
|
||||||
7.69901118419740425e-03 * DAYS_PER_YEAR,
|
vy: 7.69901118419740425e-03 * DAYS_PER_YEAR,
|
||||||
-6.90460016972063023e-05 * DAYS_PER_YEAR,
|
vz: -6.90460016972063023e-05 * DAYS_PER_YEAR,
|
||||||
9.54791938424326609e-04 * SOLAR_MASS
|
mass: 9.54791938424326609e-04 * SOLAR_MASS
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function Saturn() {
|
function Saturn() {
|
||||||
return Body(
|
return Body({
|
||||||
8.34336671824457987e+00,
|
x: 8.34336671824457987e+00,
|
||||||
4.12479856412430479e+00,
|
y: 4.12479856412430479e+00,
|
||||||
-4.03523417114321381e-01,
|
z: -4.03523417114321381e-01,
|
||||||
-2.76742510726862411e-03 * DAYS_PER_YEAR,
|
vx: -2.76742510726862411e-03 * DAYS_PER_YEAR,
|
||||||
4.99852801234917238e-03 * DAYS_PER_YEAR,
|
vy: 4.99852801234917238e-03 * DAYS_PER_YEAR,
|
||||||
2.30417297573763929e-05 * DAYS_PER_YEAR,
|
vz: 2.30417297573763929e-05 * DAYS_PER_YEAR,
|
||||||
2.85885980666130812e-04 * SOLAR_MASS
|
mass: 2.85885980666130812e-04 * SOLAR_MASS
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function Uranus() {
|
function Uranus() {
|
||||||
return Body(
|
return Body({
|
||||||
1.28943695621391310e+01,
|
x: 1.28943695621391310e+01,
|
||||||
-1.51111514016986312e+01,
|
y: -1.51111514016986312e+01,
|
||||||
-2.23307578892655734e-01,
|
z: -2.23307578892655734e-01,
|
||||||
2.96460137564761618e-03 * DAYS_PER_YEAR,
|
vx: 2.96460137564761618e-03 * DAYS_PER_YEAR,
|
||||||
2.37847173959480950e-03 * DAYS_PER_YEAR,
|
vy: 2.37847173959480950e-03 * DAYS_PER_YEAR,
|
||||||
-2.96589568540237556e-05 * DAYS_PER_YEAR,
|
vz: -2.96589568540237556e-05 * DAYS_PER_YEAR,
|
||||||
4.36624404335156298e-05 * SOLAR_MASS
|
mass: 4.36624404335156298e-05 * SOLAR_MASS
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function Neptune() {
|
function Neptune() {
|
||||||
return Body(
|
return Body({
|
||||||
1.53796971148509165e+01,
|
x: 1.53796971148509165e+01,
|
||||||
-2.59193146099879641e+01,
|
y: -2.59193146099879641e+01,
|
||||||
1.79258772950371181e-01,
|
z: 1.79258772950371181e-01,
|
||||||
2.68067772490389322e-03 * DAYS_PER_YEAR,
|
vx: 2.68067772490389322e-03 * DAYS_PER_YEAR,
|
||||||
1.62824170038242295e-03 * DAYS_PER_YEAR,
|
vy: 1.62824170038242295e-03 * DAYS_PER_YEAR,
|
||||||
-9.51592254519715870e-05 * DAYS_PER_YEAR,
|
vz: -9.51592254519715870e-05 * DAYS_PER_YEAR,
|
||||||
5.15138902046611451e-05 * SOLAR_MASS
|
mass: 5.15138902046611451e-05 * SOLAR_MASS
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function Sun() {
|
function Sun() {
|
||||||
return Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
|
return Body({x: 0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: SOLAR_MASS});
|
||||||
}
|
}
|
||||||
|
|
||||||
var bodies = Array(Sun(), Jupiter(), Saturn(), Uranus(), Neptune());
|
var bodies = Array(Sun(), Jupiter(), Saturn(), Uranus(), Neptune());
|
||||||
@@ -65,15 +65,18 @@ function offsetMomentum() {
|
|||||||
var py = 0;
|
var py = 0;
|
||||||
var pz = 0;
|
var pz = 0;
|
||||||
var size = length(bodies);
|
var size = length(bodies);
|
||||||
for (var i = 0; i < size; i++) {
|
var i = 0
|
||||||
var body = bodies[i];
|
var body = null
|
||||||
var mass = body.mass;
|
var mass = null
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
body = bodies[i];
|
||||||
|
mass = body.mass;
|
||||||
px += body.vx * mass;
|
px += body.vx * mass;
|
||||||
py += body.vy * mass;
|
py += body.vy * mass;
|
||||||
pz += body.vz * mass;
|
pz += body.vz * mass;
|
||||||
}
|
}
|
||||||
|
|
||||||
var body = bodies[0];
|
body = bodies[0];
|
||||||
body.vx = -px / SOLAR_MASS;
|
body.vx = -px / SOLAR_MASS;
|
||||||
body.vy = -py / SOLAR_MASS;
|
body.vy = -py / SOLAR_MASS;
|
||||||
body.vz = -pz / SOLAR_MASS;
|
body.vz = -pz / SOLAR_MASS;
|
||||||
@@ -81,27 +84,42 @@ function offsetMomentum() {
|
|||||||
|
|
||||||
function advance(dt) {
|
function advance(dt) {
|
||||||
var size = length(bodies);
|
var size = length(bodies);
|
||||||
|
var i = 0
|
||||||
|
var j = 0
|
||||||
|
var bodyi = null
|
||||||
|
var bodyj = null
|
||||||
|
var vxi = null
|
||||||
|
var vyi = null
|
||||||
|
var vzi = null
|
||||||
|
var dx = null
|
||||||
|
var dy = null
|
||||||
|
var dz = null
|
||||||
|
var d2 = null
|
||||||
|
var mag = null
|
||||||
|
var massj = null
|
||||||
|
var massi = null
|
||||||
|
var body = null
|
||||||
|
|
||||||
for (var i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
var bodyi = bodies[i];
|
bodyi = bodies[i];
|
||||||
var vxi = bodyi.vx;
|
vxi = bodyi.vx;
|
||||||
var vyi = bodyi.vy;
|
vyi = bodyi.vy;
|
||||||
var vzi = bodyi.vz;
|
vzi = bodyi.vz;
|
||||||
for (var j = i + 1; j < size; j++) {
|
for (j = i + 1; j < size; j++) {
|
||||||
var bodyj = bodies[j];
|
bodyj = bodies[j];
|
||||||
var dx = bodyi.x - bodyj.x;
|
dx = bodyi.x - bodyj.x;
|
||||||
var dy = bodyi.y - bodyj.y;
|
dy = bodyi.y - bodyj.y;
|
||||||
var dz = bodyi.z - bodyj.z;
|
dz = bodyi.z - bodyj.z;
|
||||||
|
|
||||||
var d2 = dx * dx + dy * dy + dz * dz;
|
d2 = dx * dx + dy * dy + dz * dz;
|
||||||
var mag = dt / (d2 * math.sqrt(d2));
|
mag = dt / (d2 * math.sqrt(d2));
|
||||||
|
|
||||||
var massj = bodyj.mass;
|
massj = bodyj.mass;
|
||||||
vxi -= dx * massj * mag;
|
vxi -= dx * massj * mag;
|
||||||
vyi -= dy * massj * mag;
|
vyi -= dy * massj * mag;
|
||||||
vzi -= dz * massj * mag;
|
vzi -= dz * massj * mag;
|
||||||
|
|
||||||
var massi = bodyi.mass;
|
massi = bodyi.mass;
|
||||||
bodyj.vx += dx * massi * mag;
|
bodyj.vx += dx * massi * mag;
|
||||||
bodyj.vy += dy * massi * mag;
|
bodyj.vy += dy * massi * mag;
|
||||||
bodyj.vz += dz * massi * mag;
|
bodyj.vz += dz * massi * mag;
|
||||||
@@ -111,8 +129,8 @@ function advance(dt) {
|
|||||||
bodyi.vz = vzi;
|
bodyi.vz = vzi;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
var body = bodies[i];
|
body = bodies[i];
|
||||||
body.x += dt * body.vx;
|
body.x += dt * body.vx;
|
||||||
body.y += dt * body.vy;
|
body.y += dt * body.vy;
|
||||||
body.z += dt * body.vz;
|
body.z += dt * body.vz;
|
||||||
@@ -122,20 +140,28 @@ function advance(dt) {
|
|||||||
function energy() {
|
function energy() {
|
||||||
var e = 0;
|
var e = 0;
|
||||||
var size = length(bodies);
|
var size = length(bodies);
|
||||||
|
var i = 0
|
||||||
|
var j = 0
|
||||||
|
var bodyi = null
|
||||||
|
var bodyj = null
|
||||||
|
var dx = null
|
||||||
|
var dy = null
|
||||||
|
var dz = null
|
||||||
|
var distance = null
|
||||||
|
|
||||||
for (var i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
var bodyi = bodies[i];
|
bodyi = bodies[i];
|
||||||
|
|
||||||
e += 0.5 * bodyi.mass * ( bodyi.vx * bodyi.vx +
|
e += 0.5 * bodyi.mass * ( bodyi.vx * bodyi.vx +
|
||||||
bodyi.vy * bodyi.vy + bodyi.vz * bodyi.vz );
|
bodyi.vy * bodyi.vy + bodyi.vz * bodyi.vz );
|
||||||
|
|
||||||
for (var j = i + 1; j < size; j++) {
|
for (j = i + 1; j < size; j++) {
|
||||||
var bodyj = bodies[j];
|
bodyj = bodies[j];
|
||||||
var dx = bodyi.x - bodyj.x;
|
dx = bodyi.x - bodyj.x;
|
||||||
var dy = bodyi.y - bodyj.y;
|
dy = bodyi.y - bodyj.y;
|
||||||
var dz = bodyi.z - bodyj.z;
|
dz = bodyi.z - bodyj.z;
|
||||||
|
|
||||||
var distance = math.sqrt(dx * dx + dy * dy + dz * dz);
|
distance = math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||||
e -= (bodyi.mass * bodyj.mass) / distance;
|
e -= (bodyi.mass * bodyj.mass) / distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,12 +169,13 @@ function energy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var n = arg[0] || 100000
|
var n = arg[0] || 100000
|
||||||
|
var i = 0
|
||||||
|
|
||||||
offsetMomentum();
|
offsetMomentum();
|
||||||
|
|
||||||
log.console(`n = ${n}`)
|
log.console(`n = ${n}`)
|
||||||
log.console(energy().toFixed(9))
|
log.console(energy().toFixed(9))
|
||||||
for (var i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
advance(0.01);
|
advance(0.01);
|
||||||
log.console(energy().toFixed(9))
|
log.console(energy().toFixed(9))
|
||||||
|
|
||||||
|
|||||||
@@ -7,41 +7,40 @@ var ll = io.slurp('benchmarks/nota.json')
|
|||||||
|
|
||||||
var newarr = []
|
var newarr = []
|
||||||
var accstr = ""
|
var accstr = ""
|
||||||
for (var i = 0; i < 10000; i++) {
|
var i = 0
|
||||||
|
var start = null
|
||||||
|
var jll = null
|
||||||
|
var jsonStr = null
|
||||||
|
var nll = null
|
||||||
|
var oll = null
|
||||||
|
for (i = 0; i < 10000; i++) {
|
||||||
accstr += i;
|
accstr += i;
|
||||||
newarrpush(i.toString())
|
push(newarr, text(i))
|
||||||
}
|
}
|
||||||
// Arrays to store timing results
|
|
||||||
var jsonDecodeTimes = [];
|
var jsonDecodeTimes = [];
|
||||||
var jsonEncodeTimes = [];
|
var jsonEncodeTimes = [];
|
||||||
var notaEncodeTimes = [];
|
var notaEncodeTimes = [];
|
||||||
var notaDecodeTimes = [];
|
var notaDecodeTimes = [];
|
||||||
var notaSizes = [];
|
var notaSizes = [];
|
||||||
|
|
||||||
// Run 100 tests
|
for (i = 0; i < 100; i++) {
|
||||||
for (var i = 0; i < 100; i++) {
|
|
||||||
// JSON Decode test
|
|
||||||
var start = os.now();
|
|
||||||
var jll = json.decode(ll);
|
|
||||||
jsonDecodeTimespush((os.now() - start) * 1000);
|
|
||||||
|
|
||||||
// JSON Encode test
|
|
||||||
start = os.now();
|
start = os.now();
|
||||||
var jsonStr = JSON.stringify(jll);
|
jll = json.decode(ll);
|
||||||
jsonEncodeTimespush((os.now() - start) * 1000);
|
push(jsonDecodeTimes, (os.now() - start) * 1000);
|
||||||
|
|
||||||
// NOTA Encode test
|
|
||||||
start = os.now();
|
start = os.now();
|
||||||
var nll = nota.encode(jll);
|
jsonStr = JSON.stringify(jll);
|
||||||
notaEncodeTimespush((os.now() - start) * 1000);
|
push(jsonEncodeTimes, (os.now() - start) * 1000);
|
||||||
|
|
||||||
// NOTA Decode test
|
|
||||||
start = os.now();
|
start = os.now();
|
||||||
var oll = nota.decode(nll);
|
nll = nota.encode(jll);
|
||||||
notaDecodeTimespush((os.now() - start) * 1000);
|
push(notaEncodeTimes, (os.now() - start) * 1000);
|
||||||
|
|
||||||
|
start = os.now();
|
||||||
|
oll = nota.decode(nll);
|
||||||
|
push(notaDecodeTimes, (os.now() - start) * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate statistics
|
|
||||||
function getStats(arr) {
|
function getStats(arr) {
|
||||||
return {
|
return {
|
||||||
avg: reduce(arr, (a,b) => a+b, 0) / length(arr),
|
avg: reduce(arr, (a,b) => a+b, 0) / length(arr),
|
||||||
@@ -50,7 +49,6 @@ function getStats(arr) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pretty print results
|
|
||||||
log.console("\n== Performance Test Results (100 iterations) ==");
|
log.console("\n== Performance Test Results (100 iterations) ==");
|
||||||
log.console("\nJSON Decoding (ms):");
|
log.console("\nJSON Decoding (ms):");
|
||||||
def jsonDecStats = getStats(jsonDecodeTimes);
|
def jsonDecStats = getStats(jsonDecodeTimes);
|
||||||
@@ -75,4 +73,3 @@ def notaDecStats = getStats(notaDecodeTimes);
|
|||||||
log.console(`Average: ${notaDecStats.avg.toFixed(2)} ms`);
|
log.console(`Average: ${notaDecStats.avg.toFixed(2)} ms`);
|
||||||
log.console(`Min: ${notaDecStats.min.toFixed(2)} ms`);
|
log.console(`Min: ${notaDecStats.min.toFixed(2)} ms`);
|
||||||
log.console(`Max: ${notaDecStats.max.toFixed(2)} ms`);
|
log.console(`Max: ${notaDecStats.max.toFixed(2)} ms`);
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,12 @@ function A(i,j) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Au(u,v) {
|
function Au(u,v) {
|
||||||
for (var i=0; i<length(u); ++i) {
|
var i = 0
|
||||||
var t = 0;
|
var j = 0
|
||||||
for (var j=0; j<length(u); ++j)
|
var t = null
|
||||||
|
for (i = 0; i < length(u); ++i) {
|
||||||
|
t = 0;
|
||||||
|
for (j = 0; j < length(u); ++j)
|
||||||
t += A(i,j) * u[j];
|
t += A(i,j) * u[j];
|
||||||
|
|
||||||
v[i] = t;
|
v[i] = t;
|
||||||
@@ -15,9 +18,12 @@ function Au(u,v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Atu(u,v) {
|
function Atu(u,v) {
|
||||||
for (var i=0; i<length(u); ++i) {
|
var i = 0
|
||||||
var t = 0;
|
var j = 0
|
||||||
for (var j=0; j<length(u); ++j)
|
var t = null
|
||||||
|
for (i = 0; i < length(u); ++i) {
|
||||||
|
t = 0;
|
||||||
|
for (j = 0; j < length(u); ++j)
|
||||||
t += A(j,i) * u[j];
|
t += A(j,i) * u[j];
|
||||||
|
|
||||||
v[i] = t;
|
v[i] = t;
|
||||||
@@ -30,9 +36,15 @@ function AtAu(u,v,w) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function spectralnorm(n) {
|
function spectralnorm(n) {
|
||||||
var i, u=[], v=[], w=[], vv=0, vBv=0;
|
var i = 0
|
||||||
for (i=0; i<n; ++i)
|
var u = []
|
||||||
u[i] = 1; v[i] = w[i] = 0;
|
var v = []
|
||||||
|
var w = []
|
||||||
|
var vv = 0
|
||||||
|
var vBv = 0
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
u[i] = 1; v[i] = 0; w[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < 10; ++i) {
|
for (i = 0; i < 10; ++i) {
|
||||||
AtAu(u,v,w);
|
AtAu(u,v,w);
|
||||||
|
|||||||
@@ -1,41 +1,22 @@
|
|||||||
//
|
|
||||||
// wota_benchmark.js
|
|
||||||
//
|
|
||||||
// Usage in QuickJS:
|
|
||||||
// qjs wota_benchmark.js
|
|
||||||
//
|
|
||||||
// Prerequisite:
|
|
||||||
var wota = use('wota');
|
var wota = use('wota');
|
||||||
var os = use('os');
|
var os = use('os');
|
||||||
// or otherwise ensure `wota` and `os` are available.
|
|
||||||
// Make sure wota_benchmark.js is loaded after wota.js or combined with it.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Helper to run a function repeatedly and measure total time in seconds.
|
var i = 0
|
||||||
// Returns elapsed time in seconds.
|
|
||||||
function measureTime(fn, iterations) {
|
function measureTime(fn, iterations) {
|
||||||
var t1 = os.now();
|
var t1 = os.now();
|
||||||
for (var i = 0; i < iterations; i++) {
|
for (i = 0; i < iterations; i++) {
|
||||||
fn();
|
fn();
|
||||||
}
|
}
|
||||||
var t2 = os.now();
|
var t2 = os.now();
|
||||||
return t2 - t1;
|
return t2 - t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll define a function that does `encode -> decode` for a given value:
|
|
||||||
function roundTripWota(value) {
|
function roundTripWota(value) {
|
||||||
var encoded = wota.encode(value);
|
var encoded = wota.encode(value);
|
||||||
var decoded = wota.decode(encoded);
|
var decoded = wota.decode(encoded);
|
||||||
// Not doing a deep compare here, just measuring performance.
|
|
||||||
// (We trust the test suite to verify correctness.)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A small suite of data we want to benchmark. Each entry includes:
|
|
||||||
// name: label for printing
|
|
||||||
// data: the test value(s) to encode/decode
|
|
||||||
// iterations: how many times to loop
|
|
||||||
//
|
|
||||||
// You can tweak these as you like for heavier or lighter tests.
|
|
||||||
def benchmarks = [
|
def benchmarks = [
|
||||||
{
|
{
|
||||||
name: "Small Integers",
|
name: "Small Integers",
|
||||||
@@ -62,22 +43,17 @@ def benchmarks = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Large Array (1k numbers)",
|
name: "Large Array (1k numbers)",
|
||||||
// A thousand random numbers
|
|
||||||
data: [ array(1000, i => i *0.5) ],
|
data: [ array(1000, i => i *0.5) ],
|
||||||
iterations: 1000
|
iterations: 1000
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Print a header
|
|
||||||
log.console("Wota Encode/Decode Benchmark");
|
log.console("Wota Encode/Decode Benchmark");
|
||||||
log.console("===================\n");
|
log.console("===================\n");
|
||||||
|
|
||||||
// We'll run each benchmark scenario in turn.
|
|
||||||
arrfor(benchmarks, function(bench) {
|
arrfor(benchmarks, function(bench) {
|
||||||
var totalIterations = bench.iterations * length(bench.data);
|
var totalIterations = bench.iterations * length(bench.data);
|
||||||
|
|
||||||
// We'll define a function that does a roundTrip for *each* data item in bench.data
|
|
||||||
// to measure in one loop iteration. Then we multiply by bench.iterations.
|
|
||||||
function runAllData() {
|
function runAllData() {
|
||||||
arrfor(bench.data, roundTripWota)
|
arrfor(bench.data, roundTripWota)
|
||||||
}
|
}
|
||||||
@@ -91,5 +67,4 @@ arrfor(benchmarks, function(bench) {
|
|||||||
log.console(` Throughput: ${opsPerSec} encode+decode ops/sec\n`);
|
log.console(` Throughput: ${opsPerSec} encode+decode ops/sec\n`);
|
||||||
})
|
})
|
||||||
|
|
||||||
// All done
|
|
||||||
log.console("Benchmark completed.\n");
|
log.console("Benchmark completed.\n");
|
||||||
|
|||||||
@@ -1,18 +1,9 @@
|
|||||||
//
|
|
||||||
// benchmark_wota_nota_json.js
|
|
||||||
//
|
|
||||||
// Usage in QuickJS:
|
|
||||||
// qjs benchmark_wota_nota_json.js <LibraryName> <ScenarioName>
|
|
||||||
//
|
|
||||||
// Ensure wota, nota, json, and os are all available, e.g.:
|
|
||||||
var wota = use('wota');
|
var wota = use('wota');
|
||||||
var nota = use('nota');
|
var nota = use('nota');
|
||||||
var json = use('json');
|
var json = use('json');
|
||||||
var jswota = use('jswota')
|
var jswota = use('jswota')
|
||||||
var os = use('os');
|
var os = use('os');
|
||||||
//
|
|
||||||
|
|
||||||
// Parse command line arguments
|
|
||||||
if (length(arg) != 2) {
|
if (length(arg) != 2) {
|
||||||
log.console('Usage: cell benchmark_wota_nota_json.ce <LibraryName> <ScenarioName>');
|
log.console('Usage: cell benchmark_wota_nota_json.ce <LibraryName> <ScenarioName>');
|
||||||
$stop()
|
$stop()
|
||||||
@@ -21,16 +12,11 @@ if (length(arg) != 2) {
|
|||||||
var lib_name = arg[0];
|
var lib_name = arg[0];
|
||||||
var scenario_name = arg[1];
|
var scenario_name = arg[1];
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 1. Setup "libraries" array to easily switch among wota, nota, and json
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
def libraries = [
|
def libraries = [
|
||||||
{
|
{
|
||||||
name: "wota",
|
name: "wota",
|
||||||
encode: wota.encode,
|
encode: wota.encode,
|
||||||
decode: wota.decode,
|
decode: wota.decode,
|
||||||
// wota produces an ArrayBuffer. We'll count `buffer.byteLength` as size.
|
|
||||||
getSize(encoded) {
|
getSize(encoded) {
|
||||||
return length(encoded);
|
return length(encoded);
|
||||||
}
|
}
|
||||||
@@ -39,7 +25,6 @@ def libraries = [
|
|||||||
name: "nota",
|
name: "nota",
|
||||||
encode: nota.encode,
|
encode: nota.encode,
|
||||||
decode: nota.decode,
|
decode: nota.decode,
|
||||||
// nota also produces an ArrayBuffer:
|
|
||||||
getSize(encoded) {
|
getSize(encoded) {
|
||||||
return length(encoded);
|
return length(encoded);
|
||||||
}
|
}
|
||||||
@@ -48,19 +33,12 @@ def libraries = [
|
|||||||
name: "json",
|
name: "json",
|
||||||
encode: json.encode,
|
encode: json.encode,
|
||||||
decode: json.decode,
|
decode: json.decode,
|
||||||
// json produces a JS string. We'll measure its UTF-16 code unit length
|
|
||||||
// as a rough "size". Alternatively, you could convert to UTF-8 for
|
|
||||||
getSize(encodedStr) {
|
getSize(encodedStr) {
|
||||||
return length(encodedStr);
|
return length(encodedStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 2. Test data sets (similar to wota benchmarks).
|
|
||||||
// Each scenario has { name, data, iterations }
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
def benchmarks = [
|
def benchmarks = [
|
||||||
{
|
{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
@@ -102,42 +80,24 @@ def benchmarks = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 3. Utility: measureTime(fn) => how long fn() takes in seconds.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function measureTime(fn) {
|
function measureTime(fn) {
|
||||||
var start = os.now();
|
var start = os.now();
|
||||||
fn();
|
fn();
|
||||||
var end = os.now();
|
var end = os.now();
|
||||||
return (end - start); // in seconds
|
return (end - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 4. For each library, we run each benchmark scenario and measure:
|
|
||||||
// - Encoding time (seconds)
|
|
||||||
// - Decoding time (seconds)
|
|
||||||
// - Total encoded size (bytes or code units for json)
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function runBenchmarkForLibrary(lib, bench) {
|
function runBenchmarkForLibrary(lib, bench) {
|
||||||
// We'll encode and decode each item in `bench.data`.
|
|
||||||
// We do 'bench.iterations' times. Then sum up total time.
|
|
||||||
|
|
||||||
// Pre-store the encoded results for all items so we can measure decode time
|
|
||||||
// in a separate pass. Also measure total size once.
|
|
||||||
var encodedList = [];
|
var encodedList = [];
|
||||||
var totalSize = 0;
|
var totalSize = 0;
|
||||||
|
var i = 0
|
||||||
|
var j = 0
|
||||||
|
var e = null
|
||||||
|
|
||||||
// 1) Measure ENCODING
|
|
||||||
var encodeTime = measureTime(() => {
|
var encodeTime = measureTime(() => {
|
||||||
for (var i = 0; i < bench.iterations; i++) {
|
for (i = 0; i < bench.iterations; i++) {
|
||||||
// For each data item, encode it
|
for (j = 0; j < length(bench.data); j++) {
|
||||||
for (var j = 0; j < length(bench.data); j++) {
|
e = lib.encode(bench.data[j]);
|
||||||
var e = lib.encode(bench.data[j]);
|
|
||||||
// store only in the very first iteration, so we can decode them later
|
|
||||||
// but do not store them every iteration or we blow up memory.
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
push(encodedList, e);
|
push(encodedList, e);
|
||||||
totalSize += lib.getSize(e);
|
totalSize += lib.getSize(e);
|
||||||
@@ -146,9 +106,8 @@ function runBenchmarkForLibrary(lib, bench) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2) Measure DECODING
|
|
||||||
var decodeTime = measureTime(() => {
|
var decodeTime = measureTime(() => {
|
||||||
for (var i = 0; i < bench.iterations; i++) {
|
for (i = 0; i < bench.iterations; i++) {
|
||||||
arrfor(encodedList, lib.decode)
|
arrfor(encodedList, lib.decode)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -156,11 +115,6 @@ function runBenchmarkForLibrary(lib, bench) {
|
|||||||
return { encodeTime, decodeTime, totalSize };
|
return { encodeTime, decodeTime, totalSize };
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 5. Main driver: run only the specified library and scenario
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Find the requested library and scenario
|
|
||||||
var lib = libraries[find(libraries, l => l.name == lib_name)];
|
var lib = libraries[find(libraries, l => l.name == lib_name)];
|
||||||
var bench = benchmarks[find(benchmarks, b => b.name == scenario_name)];
|
var bench = benchmarks[find(benchmarks, b => b.name == scenario_name)];
|
||||||
|
|
||||||
@@ -176,10 +130,11 @@ if (!bench) {
|
|||||||
$stop()
|
$stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the benchmark for this library/scenario combination
|
var bench_result = runBenchmarkForLibrary(lib, bench);
|
||||||
var { encodeTime, decodeTime, totalSize } = runBenchmarkForLibrary(lib, bench);
|
var encodeTime = bench_result.encodeTime;
|
||||||
|
var decodeTime = bench_result.decodeTime;
|
||||||
|
var totalSize = bench_result.totalSize;
|
||||||
|
|
||||||
// Output json for easy parsing by hyperfine or other tools
|
|
||||||
var totalOps = bench.iterations * length(bench.data);
|
var totalOps = bench.iterations * length(bench.data);
|
||||||
var result = {
|
var result = {
|
||||||
lib: lib_name,
|
lib: lib_name,
|
||||||
|
|||||||
170
cellfs.cm
170
cellfs.cm
@@ -1,28 +1,23 @@
|
|||||||
var cellfs = {}
|
var cellfs = {}
|
||||||
|
|
||||||
// CellFS: A filesystem implementation using miniz and raw OS filesystem
|
|
||||||
// Supports mounting multiple sources (fs, zip) and named mounts (@name)
|
|
||||||
|
|
||||||
var fd = use('fd')
|
var fd = use('fd')
|
||||||
var miniz = use('miniz')
|
var miniz = use('miniz')
|
||||||
var qop = use('qop')
|
var qop = use('qop')
|
||||||
var wildstar = use('wildstar')
|
var wildstar = use('wildstar')
|
||||||
|
|
||||||
// Internal state
|
var mounts = []
|
||||||
var mounts = [] // Array of {source, type, handle, name}
|
|
||||||
|
|
||||||
var writepath = "."
|
var writepath = "."
|
||||||
|
|
||||||
// Helper to normalize paths
|
|
||||||
function normalize_path(path) {
|
function normalize_path(path) {
|
||||||
if (!path) return ""
|
if (!path) return ""
|
||||||
// Remove leading/trailing slashes and normalize
|
|
||||||
return replace(path, /^\/+|\/+$/, "")
|
return replace(path, /^\/+|\/+$/, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a file exists in a specific mount
|
|
||||||
function mount_exists(mount, path) {
|
function mount_exists(mount, path) {
|
||||||
var result = false
|
var result = false
|
||||||
|
var full_path = null
|
||||||
|
var st = null
|
||||||
var _check = null
|
var _check = null
|
||||||
if (mount.type == 'zip') {
|
if (mount.type == 'zip') {
|
||||||
_check = function() {
|
_check = function() {
|
||||||
@@ -36,9 +31,9 @@ function mount_exists(mount, path) {
|
|||||||
} disruption {}
|
} disruption {}
|
||||||
_check()
|
_check()
|
||||||
} else {
|
} else {
|
||||||
var full_path = fd.join_paths(mount.source, path)
|
full_path = fd.join_paths(mount.source, path)
|
||||||
_check = function() {
|
_check = function() {
|
||||||
var st = fd.stat(full_path)
|
st = fd.stat(full_path)
|
||||||
result = st.isFile || st.isDirectory
|
result = st.isFile || st.isDirectory
|
||||||
} disruption {}
|
} disruption {}
|
||||||
_check()
|
_check()
|
||||||
@@ -46,11 +41,12 @@ function mount_exists(mount, path) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a path refers to a directory in a specific mount
|
|
||||||
function is_directory(path) {
|
function is_directory(path) {
|
||||||
var res = resolve(path)
|
var res = resolve(path)
|
||||||
var mount = res.mount
|
var mount = res.mount
|
||||||
var result = false
|
var result = false
|
||||||
|
var full_path = null
|
||||||
|
var st = null
|
||||||
var _check = null
|
var _check = null
|
||||||
if (mount.type == 'zip') {
|
if (mount.type == 'zip') {
|
||||||
_check = function() {
|
_check = function() {
|
||||||
@@ -63,9 +59,9 @@ function is_directory(path) {
|
|||||||
} disruption {}
|
} disruption {}
|
||||||
_check()
|
_check()
|
||||||
} else {
|
} else {
|
||||||
var full_path = fd.join_paths(mount.source, path)
|
full_path = fd.join_paths(mount.source, path)
|
||||||
_check = function() {
|
_check = function() {
|
||||||
var st = fd.stat(full_path)
|
st = fd.stat(full_path)
|
||||||
result = st.isDirectory
|
result = st.isDirectory
|
||||||
} disruption {}
|
} disruption {}
|
||||||
_check()
|
_check()
|
||||||
@@ -73,27 +69,25 @@ function is_directory(path) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a path to a specific mount and relative path
|
|
||||||
// Returns { mount, path } or throws/returns null
|
|
||||||
function resolve(path, must_exist) {
|
function resolve(path, must_exist) {
|
||||||
path = normalize_path(path)
|
var idx = null
|
||||||
|
|
||||||
// Check for named mount
|
|
||||||
if (starts_with(path, "@")) {
|
|
||||||
var idx = search(path, "/")
|
|
||||||
var mount_name = ""
|
var mount_name = ""
|
||||||
var rel_path = ""
|
var rel_path = ""
|
||||||
|
var mount = null
|
||||||
|
var found_mount = null
|
||||||
|
var npath = normalize_path(path)
|
||||||
|
|
||||||
|
if (starts_with(npath, "@")) {
|
||||||
|
idx = search(npath, "/")
|
||||||
|
|
||||||
if (idx == null) {
|
if (idx == null) {
|
||||||
mount_name = text(path, 1)
|
mount_name = text(npath, 1)
|
||||||
rel_path = ""
|
rel_path = ""
|
||||||
} else {
|
} else {
|
||||||
mount_name = text(path, 1, idx)
|
mount_name = text(npath, 1, idx)
|
||||||
rel_path = text(path, idx + 1)
|
rel_path = text(npath, idx + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find named mount
|
|
||||||
var mount = null
|
|
||||||
arrfor(mounts, function(m) {
|
arrfor(mounts, function(m) {
|
||||||
if (m.name == mount_name) {
|
if (m.name == mount_name) {
|
||||||
mount = m
|
mount = m
|
||||||
@@ -108,11 +102,9 @@ function resolve(path, must_exist) {
|
|||||||
return { mount: mount, path: rel_path }
|
return { mount: mount, path: rel_path }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search path
|
arrfor(mounts, function(m) {
|
||||||
var found_mount = null
|
if (mount_exists(m, npath)) {
|
||||||
arrfor(mounts, function(mount) {
|
found_mount = { mount: m, path: npath }
|
||||||
if (mount_exists(mount, path)) {
|
|
||||||
found_mount = { mount: mount, path: path }
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}, false, true)
|
}, false, true)
|
||||||
@@ -122,14 +114,17 @@ function resolve(path, must_exist) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (must_exist) {
|
if (must_exist) {
|
||||||
print("File not found in any mount: " + path); disrupt
|
print("File not found in any mount: " + npath); disrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount a source
|
|
||||||
function mount(source, name) {
|
function mount(source, name) {
|
||||||
// Check if source exists
|
|
||||||
var st = fd.stat(source)
|
var st = fd.stat(source)
|
||||||
|
var blob = null
|
||||||
|
var qop_archive = null
|
||||||
|
var zip = null
|
||||||
|
|
||||||
|
var _try_qop = null
|
||||||
|
|
||||||
var mount_info = {
|
var mount_info = {
|
||||||
source: source,
|
source: source,
|
||||||
@@ -142,10 +137,10 @@ function mount(source, name) {
|
|||||||
if (st.isDirectory) {
|
if (st.isDirectory) {
|
||||||
mount_info.type = 'fs'
|
mount_info.type = 'fs'
|
||||||
} else if (st.isFile) {
|
} else if (st.isFile) {
|
||||||
var blob = fd.slurp(source)
|
blob = fd.slurp(source)
|
||||||
|
|
||||||
var qop_archive = null
|
qop_archive = null
|
||||||
var _try_qop = function() {
|
_try_qop = function() {
|
||||||
qop_archive = qop.open(blob)
|
qop_archive = qop.open(blob)
|
||||||
} disruption {}
|
} disruption {}
|
||||||
_try_qop()
|
_try_qop()
|
||||||
@@ -153,16 +148,16 @@ function mount(source, name) {
|
|||||||
if (qop_archive) {
|
if (qop_archive) {
|
||||||
mount_info.type = 'qop'
|
mount_info.type = 'qop'
|
||||||
mount_info.handle = qop_archive
|
mount_info.handle = qop_archive
|
||||||
mount_info.zip_blob = blob // keep blob alive
|
mount_info.zip_blob = blob
|
||||||
} else {
|
} else {
|
||||||
var zip = miniz.read(blob)
|
zip = miniz.read(blob)
|
||||||
if (!is_object(zip) || !is_function(zip.count)) {
|
if (!is_object(zip) || !is_function(zip.count)) {
|
||||||
print("Invalid archive file (not zip or qop): " + source); disrupt
|
print("Invalid archive file (not zip or qop): " + source); disrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
mount_info.type = 'zip'
|
mount_info.type = 'zip'
|
||||||
mount_info.handle = zip
|
mount_info.handle = zip
|
||||||
mount_info.zip_blob = blob // keep blob alive
|
mount_info.zip_blob = blob
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print("Unsupported mount source type: " + source); disrupt
|
print("Unsupported mount source type: " + source); disrupt
|
||||||
@@ -171,31 +166,30 @@ function mount(source, name) {
|
|||||||
push(mounts, mount_info)
|
push(mounts, mount_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmount
|
|
||||||
function unmount(name_or_source) {
|
function unmount(name_or_source) {
|
||||||
mounts = filter(mounts, function(mount) {
|
mounts = filter(mounts, function(m) {
|
||||||
return mount.name != name_or_source && mount.source != name_or_source
|
return m.name != name_or_source && m.source != name_or_source
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read file
|
|
||||||
function slurp(path) {
|
function slurp(path) {
|
||||||
var res = resolve(path, true)
|
var res = resolve(path, true)
|
||||||
|
var data = null
|
||||||
|
var full_path = null
|
||||||
if (!res) { print("File not found: " + path); disrupt }
|
if (!res) { print("File not found: " + path); disrupt }
|
||||||
|
|
||||||
if (res.mount.type == 'zip') {
|
if (res.mount.type == 'zip') {
|
||||||
return res.mount.handle.slurp(res.path)
|
return res.mount.handle.slurp(res.path)
|
||||||
} else if (res.mount.type == 'qop') {
|
} else if (res.mount.type == 'qop') {
|
||||||
var data = res.mount.handle.read(res.path)
|
data = res.mount.handle.read(res.path)
|
||||||
if (!data) { print("File not found in qop: " + path); disrupt }
|
if (!data) { print("File not found in qop: " + path); disrupt }
|
||||||
return data
|
return data
|
||||||
} else {
|
} else {
|
||||||
var full_path = fd.join_paths(res.mount.source, res.path)
|
full_path = fd.join_paths(res.mount.source, res.path)
|
||||||
return fd.slurp(full_path)
|
return fd.slurp(full_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write file
|
|
||||||
function slurpwrite(path, data) {
|
function slurpwrite(path, data) {
|
||||||
var full_path = writepath + "/" + path
|
var full_path = writepath + "/" + path
|
||||||
|
|
||||||
@@ -204,7 +198,6 @@ function slurpwrite(path, data) {
|
|||||||
fd.close(f)
|
fd.close(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check existence
|
|
||||||
function exists(path) {
|
function exists(path) {
|
||||||
var res = resolve(path, false)
|
var res = resolve(path, false)
|
||||||
if (starts_with(path, "@")) {
|
if (starts_with(path, "@")) {
|
||||||
@@ -213,20 +206,22 @@ function exists(path) {
|
|||||||
return res != null
|
return res != null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat
|
|
||||||
function stat(path) {
|
function stat(path) {
|
||||||
var res = resolve(path, true)
|
var res = resolve(path, true)
|
||||||
|
var mod = null
|
||||||
|
var s = null
|
||||||
|
var full_path = null
|
||||||
if (!res) { print("File not found: " + path); disrupt }
|
if (!res) { print("File not found: " + path); disrupt }
|
||||||
|
|
||||||
if (res.mount.type == 'zip') {
|
if (res.mount.type == 'zip') {
|
||||||
var mod = res.mount.handle.mod(res.path)
|
mod = res.mount.handle.mod(res.path)
|
||||||
return {
|
return {
|
||||||
filesize: 0,
|
filesize: 0,
|
||||||
modtime: mod * 1000,
|
modtime: mod * 1000,
|
||||||
isDirectory: false
|
isDirectory: false
|
||||||
}
|
}
|
||||||
} else if (res.mount.type == 'qop') {
|
} else if (res.mount.type == 'qop') {
|
||||||
var s = res.mount.handle.stat(res.path)
|
s = res.mount.handle.stat(res.path)
|
||||||
if (!s) { print("File not found in qop: " + path); disrupt }
|
if (!s) { print("File not found in qop: " + path); disrupt }
|
||||||
return {
|
return {
|
||||||
filesize: s.size,
|
filesize: s.size,
|
||||||
@@ -234,8 +229,8 @@ function stat(path) {
|
|||||||
isDirectory: s.isDirectory
|
isDirectory: s.isDirectory
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var full_path = fd.join_paths(res.mount.source, res.path)
|
full_path = fd.join_paths(res.mount.source, res.path)
|
||||||
var s = fd.stat(full_path)
|
s = fd.stat(full_path)
|
||||||
return {
|
return {
|
||||||
filesize: s.size,
|
filesize: s.size,
|
||||||
modtime: s.mtime,
|
modtime: s.mtime,
|
||||||
@@ -244,12 +239,10 @@ function stat(path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get search paths
|
|
||||||
function searchpath() {
|
function searchpath() {
|
||||||
return array(mounts)
|
return array(mounts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount a package using the shop system
|
|
||||||
function mount_package(name) {
|
function mount_package(name) {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
mount('.', null)
|
mount('.', null)
|
||||||
@@ -266,18 +259,18 @@ function mount_package(name) {
|
|||||||
mount(dir, name)
|
mount(dir, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New functions for qjs_io compatibility
|
|
||||||
|
|
||||||
function match(str, pattern) {
|
function match(str, pattern) {
|
||||||
return wildstar.match(pattern, str, wildstar.WM_PATHNAME | wildstar.WM_PERIOD | wildstar.WM_WILDSTAR)
|
return wildstar.match(pattern, str, wildstar.WM_PATHNAME | wildstar.WM_PERIOD | wildstar.WM_WILDSTAR)
|
||||||
}
|
}
|
||||||
|
|
||||||
function rm(path) {
|
function rm(path) {
|
||||||
var res = resolve(path, true)
|
var res = resolve(path, true)
|
||||||
|
var full_path = null
|
||||||
|
var st = null
|
||||||
if (res.mount.type != 'fs') { print("Cannot delete from non-fs mount"); disrupt }
|
if (res.mount.type != 'fs') { print("Cannot delete from non-fs mount"); disrupt }
|
||||||
|
|
||||||
var full_path = fd.join_paths(res.mount.source, res.path)
|
full_path = fd.join_paths(res.mount.source, res.path)
|
||||||
var st = fd.stat(full_path)
|
st = fd.stat(full_path)
|
||||||
if (st.isDirectory) fd.rmdir(full_path)
|
if (st.isDirectory) fd.rmdir(full_path)
|
||||||
else fd.unlink(full_path)
|
else fd.unlink(full_path)
|
||||||
}
|
}
|
||||||
@@ -305,11 +298,17 @@ function realdir(path) {
|
|||||||
return fd.join_paths(res.mount.source, res.path)
|
return fd.join_paths(res.mount.source, res.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
function enumerate(path, recurse) {
|
function enumerate(_path, recurse) {
|
||||||
if (path == null) path = ""
|
var path = _path == null ? "" : _path
|
||||||
|
|
||||||
var res = resolve(path, true)
|
var res = resolve(path, true)
|
||||||
var results = []
|
var results = []
|
||||||
|
var full = null
|
||||||
|
var st = null
|
||||||
|
var all = null
|
||||||
|
var prefix = null
|
||||||
|
var prefix_len = null
|
||||||
|
var seen = null
|
||||||
|
|
||||||
function visit(curr_full, rel_prefix) {
|
function visit(curr_full, rel_prefix) {
|
||||||
var list = fd.readdir(curr_full)
|
var list = fd.readdir(curr_full)
|
||||||
@@ -317,11 +316,12 @@ function enumerate(path, recurse) {
|
|||||||
|
|
||||||
arrfor(list, function(item) {
|
arrfor(list, function(item) {
|
||||||
var item_rel = rel_prefix ? rel_prefix + "/" + item : item
|
var item_rel = rel_prefix ? rel_prefix + "/" + item : item
|
||||||
|
var child_st = null
|
||||||
push(results, item_rel)
|
push(results, item_rel)
|
||||||
|
|
||||||
if (recurse) {
|
if (recurse) {
|
||||||
var st = fd.stat(fd.join_paths(curr_full, item))
|
child_st = fd.stat(fd.join_paths(curr_full, item))
|
||||||
if (st.isDirectory) {
|
if (child_st.isDirectory) {
|
||||||
visit(fd.join_paths(curr_full, item), item_rel)
|
visit(fd.join_paths(curr_full, item), item_rel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,26 +329,27 @@ function enumerate(path, recurse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res.mount.type == 'fs') {
|
if (res.mount.type == 'fs') {
|
||||||
var full = fd.join_paths(res.mount.source, res.path)
|
full = fd.join_paths(res.mount.source, res.path)
|
||||||
var st = fd.stat(full)
|
st = fd.stat(full)
|
||||||
if (st && st.isDirectory) {
|
if (st && st.isDirectory) {
|
||||||
visit(full, "")
|
visit(full, "")
|
||||||
}
|
}
|
||||||
} else if (res.mount.type == 'qop') {
|
} else if (res.mount.type == 'qop') {
|
||||||
var all = res.mount.handle.list()
|
all = res.mount.handle.list()
|
||||||
var prefix = res.path ? res.path + "/" : ""
|
prefix = res.path ? res.path + "/" : ""
|
||||||
var prefix_len = length(prefix)
|
prefix_len = length(prefix)
|
||||||
|
|
||||||
// Use a set to avoid duplicates if we are simulating directories
|
seen = {}
|
||||||
var seen = {}
|
|
||||||
|
|
||||||
arrfor(all, function(p) {
|
arrfor(all, function(p) {
|
||||||
|
var rel = null
|
||||||
|
var slash = null
|
||||||
if (starts_with(p, prefix)) {
|
if (starts_with(p, prefix)) {
|
||||||
var rel = text(p, prefix_len)
|
rel = text(p, prefix_len)
|
||||||
if (length(rel) == 0) return
|
if (length(rel) == 0) return
|
||||||
|
|
||||||
if (!recurse) {
|
if (!recurse) {
|
||||||
var slash = search(rel, '/')
|
slash = search(rel, '/')
|
||||||
if (slash != null) {
|
if (slash != null) {
|
||||||
rel = text(rel, 0, slash)
|
rel = text(rel, 0, slash)
|
||||||
}
|
}
|
||||||
@@ -365,10 +366,15 @@ function enumerate(path, recurse) {
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
function globfs(globs, dir) {
|
function globfs(globs, _dir) {
|
||||||
if (dir == null) dir = ""
|
var dir = _dir == null ? "" : _dir
|
||||||
var res = resolve(dir, true)
|
var res = resolve(dir, true)
|
||||||
var results = []
|
var results = []
|
||||||
|
var full = null
|
||||||
|
var st = null
|
||||||
|
var all = null
|
||||||
|
var prefix = null
|
||||||
|
var prefix_len = null
|
||||||
|
|
||||||
function check_neg(path) {
|
function check_neg(path) {
|
||||||
var result = false
|
var result = false
|
||||||
@@ -402,9 +408,9 @@ function globfs(globs, dir) {
|
|||||||
var item_rel = rel_prefix ? rel_prefix + "/" + item : item
|
var item_rel = rel_prefix ? rel_prefix + "/" + item : item
|
||||||
|
|
||||||
var child_full = fd.join_paths(curr_full, item)
|
var child_full = fd.join_paths(curr_full, item)
|
||||||
var st = fd.stat(child_full)
|
var child_st = fd.stat(child_full)
|
||||||
|
|
||||||
if (st.isDirectory) {
|
if (child_st.isDirectory) {
|
||||||
if (!check_neg(item_rel)) {
|
if (!check_neg(item_rel)) {
|
||||||
visit(child_full, item_rel)
|
visit(child_full, item_rel)
|
||||||
}
|
}
|
||||||
@@ -417,19 +423,20 @@ function globfs(globs, dir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res.mount.type == 'fs') {
|
if (res.mount.type == 'fs') {
|
||||||
var full = fd.join_paths(res.mount.source, res.path)
|
full = fd.join_paths(res.mount.source, res.path)
|
||||||
var st = fd.stat(full)
|
st = fd.stat(full)
|
||||||
if (st && st.isDirectory) {
|
if (st && st.isDirectory) {
|
||||||
visit(full, "")
|
visit(full, "")
|
||||||
}
|
}
|
||||||
} else if (res.mount.type == 'qop') {
|
} else if (res.mount.type == 'qop') {
|
||||||
var all = res.mount.handle.list()
|
all = res.mount.handle.list()
|
||||||
var prefix = res.path ? res.path + "/" : ""
|
prefix = res.path ? res.path + "/" : ""
|
||||||
var prefix_len = length(prefix)
|
prefix_len = length(prefix)
|
||||||
|
|
||||||
arrfor(all, function(p) {
|
arrfor(all, function(p) {
|
||||||
|
var rel = null
|
||||||
if (starts_with(p, prefix)) {
|
if (starts_with(p, prefix)) {
|
||||||
var rel = text(p, prefix_len)
|
rel = text(p, prefix_len)
|
||||||
if (length(rel) == 0) return
|
if (length(rel) == 0) return
|
||||||
|
|
||||||
if (!check_neg(rel) && check_pos(rel)) {
|
if (!check_neg(rel) && check_pos(rel)) {
|
||||||
@@ -442,7 +449,6 @@ function globfs(globs, dir) {
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exports
|
|
||||||
cellfs.mount = mount
|
cellfs.mount = mount
|
||||||
cellfs.mount_package = mount_package
|
cellfs.mount_package = mount_package
|
||||||
cellfs.unmount = unmount
|
cellfs.unmount = unmount
|
||||||
|
|||||||
@@ -8,15 +8,17 @@ $contact((actor, reason) => {
|
|||||||
log.console(reason)
|
log.console(reason)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
address: "108.210.60.32", // NAT server's public IP
|
address: "108.210.60.32",
|
||||||
port: 4000,
|
port: 4000,
|
||||||
actor: $self
|
actor: $self
|
||||||
})
|
})
|
||||||
|
|
||||||
$receiver(e => {
|
var handlers = {
|
||||||
switch(e.type) {
|
greet: function() {
|
||||||
case 'greet':
|
|
||||||
log.console(`hello!`)
|
log.console(`hello!`)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$receiver(e => {
|
||||||
|
if (handlers[e.type]) handlers[e.type]()
|
||||||
})
|
})
|
||||||
@@ -1436,7 +1436,7 @@ Shop.build_package_scripts = function(package)
|
|||||||
// compiles all .ce and .cm files in a package
|
// compiles all .ce and .cm files in a package
|
||||||
// continues past failures and returns results
|
// continues past failures and returns results
|
||||||
var scripts = get_package_scripts(package)
|
var scripts = get_package_scripts(package)
|
||||||
var pkg_dir = get_package_abs_dir(package)
|
var pkg_dir = starts_with(package, '/') ? package : get_package_abs_dir(package)
|
||||||
var errors = []
|
var errors = []
|
||||||
var ok = 0
|
var ok = 0
|
||||||
|
|
||||||
|
|||||||
98
package.cm
98
package.cm
@@ -41,64 +41,6 @@ function get_path(name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var config_cache = {}
|
var config_cache = {}
|
||||||
var compilation_cache = {}
|
|
||||||
|
|
||||||
// Fallback parser for [compilation] sections when toml.decode() is unreliable.
|
|
||||||
// Stores results as flat keys in compilation_cache: "key|CFLAGS", "key|target|CFLAGS"
|
|
||||||
function parse_compilation_into_cache(content, cache_key) {
|
|
||||||
var lines = array(content, "\n")
|
|
||||||
var current_section = null
|
|
||||||
var i = 0
|
|
||||||
var line = null
|
|
||||||
var trimmed = null
|
|
||||||
var eq_pos = null
|
|
||||||
var key = null
|
|
||||||
var val_part = null
|
|
||||||
var val = null
|
|
||||||
var sub = null
|
|
||||||
var flat_key = null
|
|
||||||
for (i = 0; i < length(lines); i++) {
|
|
||||||
line = lines[i]
|
|
||||||
trimmed = trim(line)
|
|
||||||
if (length(trimmed) == 0 || starts_with(trimmed, '#')) continue
|
|
||||||
|
|
||||||
// Detect section headers
|
|
||||||
if (starts_with(trimmed, '[compilation.') && ends_with(trimmed, ']')) {
|
|
||||||
sub = text(trimmed, 13, -1)
|
|
||||||
current_section = sub
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (trimmed == '[compilation]') {
|
|
||||||
current_section = '_base_'
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (starts_with(trimmed, '[')) {
|
|
||||||
current_section = null
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse KEY = "VALUE" in a compilation section
|
|
||||||
if (current_section == null) continue
|
|
||||||
eq_pos = search(trimmed, '=')
|
|
||||||
if (eq_pos == null) continue
|
|
||||||
key = trim(text(trimmed, 0, eq_pos))
|
|
||||||
val_part = trim(text(trimmed, eq_pos + 1))
|
|
||||||
// Strip surrounding quotes
|
|
||||||
if (starts_with(val_part, '"') && ends_with(val_part, '"')) {
|
|
||||||
val = text(val_part, 1, -1)
|
|
||||||
} else {
|
|
||||||
val = val_part
|
|
||||||
}
|
|
||||||
if (current_section == '_base_') {
|
|
||||||
flat_key = cache_key + '|' + key
|
|
||||||
} else {
|
|
||||||
flat_key = cache_key + '|' + current_section + '|' + key
|
|
||||||
}
|
|
||||||
compilation_cache[flat_key] = val
|
|
||||||
}
|
|
||||||
// Mark that we parsed this package
|
|
||||||
compilation_cache[cache_key] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
package.load_config = function(name)
|
package.load_config = function(name)
|
||||||
{
|
{
|
||||||
@@ -121,16 +63,6 @@ package.load_config = function(name)
|
|||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the raw TOML text has [compilation] sections, always use
|
|
||||||
// the fallback line parser (the TOML decoder is unreliable for
|
|
||||||
// nested [compilation.target] sub-tables).
|
|
||||||
// We store it alongside the result in a separate cache since
|
|
||||||
// toml.decode returns frozen objects.
|
|
||||||
var has_compilation = search(content, /\[compilation/) != null
|
|
||||||
if (has_compilation) {
|
|
||||||
parse_compilation_into_cache(content, cache_key)
|
|
||||||
}
|
|
||||||
|
|
||||||
config_cache[cache_key] = result
|
config_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -339,34 +271,24 @@ package.list_programs = function(name) {
|
|||||||
// Returns an array of flag strings
|
// Returns an array of flag strings
|
||||||
package.get_flags = function(name, flag_type, target) {
|
package.get_flags = function(name, flag_type, target) {
|
||||||
var config = package.load_config(name)
|
var config = package.load_config(name)
|
||||||
var cache_key = name || '_project_'
|
var comp = config.compilation
|
||||||
var flags = []
|
var flags = []
|
||||||
var base = null
|
var base = null
|
||||||
var target_flags = null
|
var target_flags = null
|
||||||
|
|
||||||
if (compilation_cache[cache_key]) {
|
if (!comp) return flags
|
||||||
// Use flat cache: keys are "cache_key|FLAG_TYPE" and "cache_key|target|FLAG_TYPE"
|
|
||||||
base = compilation_cache[cache_key + '|' + flag_type]
|
// Base flags
|
||||||
if (base) {
|
if (comp[flag_type]) {
|
||||||
|
base = comp[flag_type]
|
||||||
flags = array(flags, filter(array(base, /\s+/), function(f) { return length(f) > 0 }))
|
flags = array(flags, filter(array(base, /\s+/), function(f) { return length(f) > 0 }))
|
||||||
}
|
}
|
||||||
if (target) {
|
|
||||||
target_flags = compilation_cache[cache_key + '|' + target + '|' + flag_type]
|
// Target-specific flags
|
||||||
if (target_flags) {
|
if (target && comp[target] && comp[target][flag_type]) {
|
||||||
|
target_flags = comp[target][flag_type]
|
||||||
flags = array(flags, filter(array(target_flags, /\s+/), function(f) { return length(f) > 0 }))
|
flags = array(flags, filter(array(target_flags, /\s+/), function(f) { return length(f) > 0 }))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if (config.compilation) {
|
|
||||||
// Fall back to toml.decode() result
|
|
||||||
if (config.compilation[flag_type]) {
|
|
||||||
base = config.compilation[flag_type]
|
|
||||||
flags = array(flags, filter(array(base, /\s+/), function(f) { return length(f) > 0 }))
|
|
||||||
}
|
|
||||||
if (target && config.compilation[target] && config.compilation[target][flag_type]) {
|
|
||||||
target_flags = config.compilation[target][flag_type]
|
|
||||||
flags = array(flags, filter(array(target_flags, /\s+/), function(f) { return length(f) > 0 }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -526,7 +526,7 @@ JS_BOOL js_key_equal_str (JSValue a, const char *str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_IsPtr (a)) return FALSE;
|
if (!JS_IsPtr (a)) return FALSE;
|
||||||
JSText *ta = (JSText *)JS_VALUE_GET_PTR (a);
|
JSText *ta = (JSText *)chase (a);
|
||||||
if (objhdr_type (ta->hdr) != OBJ_TEXT) return FALSE;
|
if (objhdr_type (ta->hdr) != OBJ_TEXT) return FALSE;
|
||||||
uint64_t txt_len = objhdr_cap56 (ta->hdr);
|
uint64_t txt_len = objhdr_cap56 (ta->hdr);
|
||||||
if (txt_len != len) return FALSE;
|
if (txt_len != len) return FALSE;
|
||||||
@@ -704,6 +704,16 @@ int rec_set_own (JSContext *ctx, JSValue *pobj, JSValue k, JSValue val) {
|
|||||||
rec->slots[insert_slot].val = val;
|
rec->slots[insert_slot].val = val;
|
||||||
rec->len++;
|
rec->len++;
|
||||||
|
|
||||||
|
#ifdef VALIDATE_GC
|
||||||
|
/* Verify the just-inserted key is findable */
|
||||||
|
int verify = rec_find_slot (rec, k);
|
||||||
|
if (verify <= 0) {
|
||||||
|
fprintf (stderr, "rec_set_own: INSERTED KEY NOT FINDABLE! slot=%d insert_slot=%d len=%u\n",
|
||||||
|
verify, insert_slot, (uint32_t)rec->len);
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1873,6 +1883,12 @@ JSText *js_alloc_string (JSContext *ctx, int max_len) {
|
|||||||
/* Initialize objhdr_t with OBJ_TEXT type and capacity in cap56 */
|
/* Initialize objhdr_t with OBJ_TEXT type and capacity in cap56 */
|
||||||
str->hdr = objhdr_make (max_len, OBJ_TEXT, false, false, false, false);
|
str->hdr = objhdr_make (max_len, OBJ_TEXT, false, false, false, false);
|
||||||
str->length = 0; /* length starts at 0, capacity is in hdr */
|
str->length = 0; /* length starts at 0, capacity is in hdr */
|
||||||
|
/* Zero packed data so odd-length strings have deterministic padding.
|
||||||
|
js_malloc is a bump allocator and does not zero memory; without this,
|
||||||
|
the last word's unused low 32 bits contain garbage, causing
|
||||||
|
fash64_hash_words and JSText_equal (memcmp) to produce inconsistent
|
||||||
|
results for different allocations of the same text content. */
|
||||||
|
memset (str->packed, 0, data_words * sizeof (uint64_t));
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@@ -3514,9 +3530,9 @@ JSValue JS_GetPropertyKey (JSContext *ctx, JSValue this_obj, JSValue key) {
|
|||||||
return JS_GetProperty (ctx, this_obj, key);
|
return JS_GetProperty (ctx, this_obj, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CAUTION: rec_set_own is NOT GC-safe if rec_resize is implemented.
|
/* rec_set_own calls rec_resize which can move the record.
|
||||||
Currently safe because rec_resize always fails.
|
JS_SetProperty uses a local copy so the caller's JSValue is NOT updated;
|
||||||
When resize is implemented, rec pointer may become stale. */
|
the VM must call mach_resolve_forward after store operations. */
|
||||||
int JS_SetPropertyKey (JSContext *ctx, JSValue this_obj, JSValue key, JSValue val) {
|
int JS_SetPropertyKey (JSContext *ctx, JSValue this_obj, JSValue key, JSValue val) {
|
||||||
if (JS_IsRecord (key)) {
|
if (JS_IsRecord (key)) {
|
||||||
if (!JS_IsRecord (this_obj)) {
|
if (!JS_IsRecord (this_obj)) {
|
||||||
|
|||||||
121
tests/blob.cm
121
tests/blob.cm
@@ -1,17 +1,12 @@
|
|||||||
// blob_test.cm
|
|
||||||
var Blob = use('blob');
|
var Blob = use('blob');
|
||||||
var os = use('os');
|
var os = use('os');
|
||||||
|
|
||||||
function assert(condition, message) {
|
function assert(condition, message) {
|
||||||
if (!condition) {
|
if (!condition) disrupt
|
||||||
throw Error(message || "Assertion failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertEqual(actual, expected, message) {
|
function assertEqual(actual, expected, message) {
|
||||||
if (actual != expected) {
|
if (actual != expected) disrupt
|
||||||
throw Error(message || "Expected " + expected + ", got " + actual);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -42,24 +37,27 @@ return {
|
|||||||
|
|
||||||
test_out_of_range_read_throws_error: function() {
|
test_out_of_range_read_throws_error: function() {
|
||||||
var b = Blob();
|
var b = Blob();
|
||||||
|
var threw = false;
|
||||||
b.write_bit(true);
|
b.write_bit(true);
|
||||||
stone(b);
|
stone(b);
|
||||||
|
|
||||||
var threw = false;
|
threw = false;
|
||||||
try {
|
var _try1 = function() {
|
||||||
b.read_logical(100);
|
b.read_logical(100);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "Out of range read should throw");
|
_try1();
|
||||||
|
assert(threw, "Out of range read should disrupt");
|
||||||
|
|
||||||
threw = false;
|
threw = false;
|
||||||
try {
|
var _try2 = function() {
|
||||||
b.read_logical(-1);
|
b.read_logical(-1);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "Negative index read should throw");
|
_try2();
|
||||||
|
assert(threw, "Negative index read should disrupt");
|
||||||
},
|
},
|
||||||
|
|
||||||
test_write_and_read_numbers: function() {
|
test_write_and_read_numbers: function() {
|
||||||
@@ -121,7 +119,8 @@ return {
|
|||||||
|
|
||||||
test_blob_partial_copy_constructor: function() {
|
test_blob_partial_copy_constructor: function() {
|
||||||
var b1 = Blob();
|
var b1 = Blob();
|
||||||
for (var i = 0; i < 10; i++) {
|
var i = 0;
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
b1.write_bit(i % 2 == 0);
|
b1.write_bit(i % 2 == 0);
|
||||||
}
|
}
|
||||||
stone(b1);
|
stone(b1);
|
||||||
@@ -136,11 +135,12 @@ return {
|
|||||||
test_create_blob_with_fill: function() {
|
test_create_blob_with_fill: function() {
|
||||||
var b1 = Blob(8, true);
|
var b1 = Blob(8, true);
|
||||||
var b2 = Blob(8, false);
|
var b2 = Blob(8, false);
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
stone(b1);
|
stone(b1);
|
||||||
stone(b2);
|
stone(b2);
|
||||||
|
|
||||||
for (var i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
assertEqual(b1.read_logical(i), true, "Bit " + i + " should be true");
|
assertEqual(b1.read_logical(i), true, "Bit " + i + " should be true");
|
||||||
assertEqual(b2.read_logical(i), false, "Bit " + i + " should be false");
|
assertEqual(b2.read_logical(i), false, "Bit " + i + " should be false");
|
||||||
}
|
}
|
||||||
@@ -149,13 +149,14 @@ return {
|
|||||||
test_create_blob_with_random_function: function() {
|
test_create_blob_with_random_function: function() {
|
||||||
var sequence = [true, false, true, true, false];
|
var sequence = [true, false, true, true, false];
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
var b = Blob(5, function() {
|
var b = Blob(5, function() {
|
||||||
return sequence[index++] ? 1 : 0;
|
return sequence[index++] ? 1 : 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
stone(b);
|
stone(b);
|
||||||
for (var i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
assertEqual(b.read_logical(i), sequence[i], "Bit " + i + " should match sequence");
|
assertEqual(b.read_logical(i), sequence[i], "Bit " + i + " should match sequence");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -176,7 +177,8 @@ return {
|
|||||||
|
|
||||||
test_read_blob_from_stone_blob: function() {
|
test_read_blob_from_stone_blob: function() {
|
||||||
var b1 = Blob();
|
var b1 = Blob();
|
||||||
for (var i = 0; i < 16; i++) {
|
var i = 0;
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
b1.write_bit(i % 3 == 0);
|
b1.write_bit(i % 3 == 0);
|
||||||
}
|
}
|
||||||
stone(b1);
|
stone(b1);
|
||||||
@@ -191,16 +193,17 @@ return {
|
|||||||
|
|
||||||
test_stone_blob_is_immutable: function() {
|
test_stone_blob_is_immutable: function() {
|
||||||
var b = Blob();
|
var b = Blob();
|
||||||
|
var threw = false;
|
||||||
b.write_bit(true);
|
b.write_bit(true);
|
||||||
stone(b);
|
stone(b);
|
||||||
|
|
||||||
var threw = false;
|
var _try = function() {
|
||||||
try {
|
|
||||||
b.write_bit(false);
|
b.write_bit(false);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "Writing to stone blob should throw error");
|
_try();
|
||||||
|
assert(threw, "Writing to stone blob should disrupt");
|
||||||
},
|
},
|
||||||
|
|
||||||
test_multiple_stone_calls_are_safe: function() {
|
test_multiple_stone_calls_are_safe: function() {
|
||||||
@@ -217,26 +220,28 @@ return {
|
|||||||
|
|
||||||
test_invalid_constructor_arguments: function() {
|
test_invalid_constructor_arguments: function() {
|
||||||
var threw = false;
|
var threw = false;
|
||||||
try {
|
var _try = function() {
|
||||||
var b = Blob("invalid");
|
var b = Blob("invalid");
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "Invalid constructor arguments should throw");
|
_try();
|
||||||
|
assert(threw, "Invalid constructor arguments should disrupt");
|
||||||
},
|
},
|
||||||
|
|
||||||
test_write_bit_validation: function() {
|
test_write_bit_validation: function() {
|
||||||
var b = Blob();
|
var b = Blob();
|
||||||
|
var threw = false;
|
||||||
b.write_bit(0);
|
b.write_bit(0);
|
||||||
b.write_bit(1);
|
b.write_bit(1);
|
||||||
|
|
||||||
var threw = false;
|
var _try = function() {
|
||||||
try {
|
|
||||||
b.write_bit(2);
|
b.write_bit(2);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "write_bit with value 2 should throw");
|
_try();
|
||||||
|
assert(threw, "write_bit with value 2 should disrupt");
|
||||||
},
|
},
|
||||||
|
|
||||||
test_complex_data_round_trip: function() {
|
test_complex_data_round_trip: function() {
|
||||||
@@ -267,8 +272,9 @@ return {
|
|||||||
test_large_blob_handling: function() {
|
test_large_blob_handling: function() {
|
||||||
var b = Blob();
|
var b = Blob();
|
||||||
var testSize = 1000;
|
var testSize = 1000;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
for (var i = 0; i < testSize; i++) {
|
for (i = 0; i < testSize; i++) {
|
||||||
b.write_bit(i % 7 == 0);
|
b.write_bit(i % 7 == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,49 +289,55 @@ return {
|
|||||||
|
|
||||||
test_non_stone_blob_read_methods_should_throw: function() {
|
test_non_stone_blob_read_methods_should_throw: function() {
|
||||||
var b = Blob();
|
var b = Blob();
|
||||||
|
var threw = false;
|
||||||
b.write_bit(true);
|
b.write_bit(true);
|
||||||
b.write_number(42);
|
b.write_number(42);
|
||||||
b.write_text("test");
|
b.write_text("test");
|
||||||
|
|
||||||
var threw = false;
|
threw = false;
|
||||||
try {
|
var _try1 = function() {
|
||||||
b.read_logical(0);
|
b.read_logical(0);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "read_logical on non-stone blob should throw");
|
_try1();
|
||||||
|
assert(threw, "read_logical on non-stone blob should disrupt");
|
||||||
|
|
||||||
threw = false;
|
threw = false;
|
||||||
try {
|
var _try2 = function() {
|
||||||
b.read_number(0);
|
b.read_number(0);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "read_number on non-stone blob should throw");
|
_try2();
|
||||||
|
assert(threw, "read_number on non-stone blob should disrupt");
|
||||||
|
|
||||||
threw = false;
|
threw = false;
|
||||||
try {
|
var _try3 = function() {
|
||||||
b.read_text(0);
|
b.read_text(0);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "read_text on non-stone blob should throw");
|
_try3();
|
||||||
|
assert(threw, "read_text on non-stone blob should disrupt");
|
||||||
|
|
||||||
threw = false;
|
threw = false;
|
||||||
try {
|
var _try4 = function() {
|
||||||
b.read_blob(0, 10);
|
b.read_blob(0, 10);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "read_blob on non-stone blob should throw");
|
_try4();
|
||||||
|
assert(threw, "read_blob on non-stone blob should disrupt");
|
||||||
|
|
||||||
threw = false;
|
threw = false;
|
||||||
try {
|
var _try5 = function() {
|
||||||
b['pad?'](0, 8);
|
b['pad?'](0, 8);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "pad? on non-stone blob should throw");
|
_try5();
|
||||||
|
assert(threw, "pad? on non-stone blob should disrupt");
|
||||||
},
|
},
|
||||||
|
|
||||||
test_empty_text_write_and_read: function() {
|
test_empty_text_write_and_read: function() {
|
||||||
@@ -337,23 +349,26 @@ return {
|
|||||||
|
|
||||||
test_invalid_read_positions: function() {
|
test_invalid_read_positions: function() {
|
||||||
var b = Blob();
|
var b = Blob();
|
||||||
|
var threw = false;
|
||||||
b.write_number(42);
|
b.write_number(42);
|
||||||
stone(b);
|
stone(b);
|
||||||
|
|
||||||
var threw = false;
|
threw = false;
|
||||||
try {
|
var _try1 = function() {
|
||||||
b.read_number(-10);
|
b.read_number(-10);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "Negative position should throw");
|
_try1();
|
||||||
|
assert(threw, "Negative position should disrupt");
|
||||||
|
|
||||||
threw = false;
|
threw = false;
|
||||||
try {
|
var _try2 = function() {
|
||||||
b.read_number(1000);
|
b.read_number(1000);
|
||||||
} catch (e) {
|
} disruption {
|
||||||
threw = true;
|
threw = true;
|
||||||
}
|
}
|
||||||
assert(threw, "Position beyond length should throw");
|
_try2();
|
||||||
|
assert(threw, "Position beyond length should disrupt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ var time = use('time')
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
test_cat: function() {
|
test_cat: function() {
|
||||||
// Create temp file
|
|
||||||
var tmp = "cat_test.tmp"
|
var tmp = "cat_test.tmp"
|
||||||
var f = fd.open(tmp, 'w')
|
var f = fd.open(tmp, 'w')
|
||||||
fd.write(f, "Hello world")
|
fd.write(f, "Hello world")
|
||||||
@@ -16,9 +15,8 @@ return {
|
|||||||
fd.close(f2)
|
fd.close(f2)
|
||||||
log.console(`cat took ${time.number()-st}`)
|
log.console(`cat took ${time.number()-st}`)
|
||||||
|
|
||||||
// fd.read returns a blob, read it as text
|
|
||||||
stone(data)
|
stone(data)
|
||||||
if (data.read_text(0) != "Hello world") throw "Data mismatch"
|
if (data.read_text(0) != "Hello world") disrupt
|
||||||
|
|
||||||
fd.unlink(tmp)
|
fd.unlink(tmp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,21 +4,22 @@ var blob = use('blob')
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
test_chunkread: function() {
|
test_chunkread: function() {
|
||||||
// Create temp file
|
|
||||||
var tmp = "chunk_test.tmp"
|
var tmp = "chunk_test.tmp"
|
||||||
var f = fd.open(tmp, 'w')
|
var f = fd.open(tmp, 'w')
|
||||||
var bigdata = ""
|
var bigdata = ""
|
||||||
for(var i=0; i<100; i++) bigdata += "HelloWorld" // 1000 bytes
|
var i = 0
|
||||||
|
var chunk = null
|
||||||
|
for (i = 0; i < 100; i++) bigdata += "HelloWorld"
|
||||||
fd.write(f, bigdata)
|
fd.write(f, bigdata)
|
||||||
fd.close(f)
|
fd.close(f)
|
||||||
|
|
||||||
var data = blob()
|
var data = blob()
|
||||||
var st = time.number()
|
var st = time.number()
|
||||||
var f2 = fd.open(tmp, 'r')
|
var f2 = fd.open(tmp, 'r')
|
||||||
var chunksize = 1024 // reduced for test
|
var chunksize = 1024
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
var chunk = fd.read(f2, chunksize);
|
chunk = fd.read(f2, chunksize);
|
||||||
data.write_blob(chunk);
|
data.write_blob(chunk);
|
||||||
if (length(chunk) < chunksize * 8) break;
|
if (length(chunk) < chunksize * 8) break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
return {
|
return {
|
||||||
test_disrupt: function() {
|
test_disrupt: function() {
|
||||||
throw 1
|
disrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
122
tests/fit.cm
122
tests/fit.cm
@@ -2,186 +2,186 @@ var fit = use("fit");
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
and_12_10: function() {
|
and_12_10: function() {
|
||||||
if (fit.and(12, 10) != 8) throw "fit.and(12, 10) expected 8";
|
if (fit.and(12, 10) != 8) disrupt
|
||||||
},
|
},
|
||||||
and_16_2: function() {
|
and_16_2: function() {
|
||||||
if (fit.and(16, 2) != 0) throw "fit.and(16, 2) expected 0";
|
if (fit.and(16, 2) != 0) disrupt
|
||||||
},
|
},
|
||||||
and_15_3: function() {
|
and_15_3: function() {
|
||||||
if (fit.and(15, 3) != 3) throw "fit.and(15, 3) expected 3";
|
if (fit.and(15, 3) != 3) disrupt
|
||||||
},
|
},
|
||||||
and_13_3: function() {
|
and_13_3: function() {
|
||||||
if (fit.and(13, 3) != 1) throw "fit.and(13, 3) expected 1";
|
if (fit.and(13, 3) != 1) disrupt
|
||||||
},
|
},
|
||||||
and_string_input: function() {
|
and_string_input: function() {
|
||||||
if (fit.and("10", 3) != null) throw "fit.and('10', 3) expected null";
|
if (fit.and("10", 3) != null) disrupt
|
||||||
},
|
},
|
||||||
or_12_10: function() {
|
or_12_10: function() {
|
||||||
if (fit.or(12, 10) != 14) throw "fit.or(12, 10) expected 14";
|
if (fit.or(12, 10) != 14) disrupt
|
||||||
},
|
},
|
||||||
or_16_2: function() {
|
or_16_2: function() {
|
||||||
if (fit.or(16, 2) != 18) throw "fit.or(16, 2) expected 18";
|
if (fit.or(16, 2) != 18) disrupt
|
||||||
},
|
},
|
||||||
or_15_3: function() {
|
or_15_3: function() {
|
||||||
if (fit.or(15, 3) != 15) throw "fit.or(15, 3) expected 15";
|
if (fit.or(15, 3) != 15) disrupt
|
||||||
},
|
},
|
||||||
or_13_3: function() {
|
or_13_3: function() {
|
||||||
if (fit.or(13, 3) != 15) throw "fit.or(13, 3) expected 15";
|
if (fit.or(13, 3) != 15) disrupt
|
||||||
},
|
},
|
||||||
xor_12_10: function() {
|
xor_12_10: function() {
|
||||||
if (fit.xor(12, 10) != 6) throw "fit.xor(12, 10) expected 6";
|
if (fit.xor(12, 10) != 6) disrupt
|
||||||
},
|
},
|
||||||
xor_16_2: function() {
|
xor_16_2: function() {
|
||||||
if (fit.xor(16, 2) != 18) throw "fit.xor(16, 2) expected 18";
|
if (fit.xor(16, 2) != 18) disrupt
|
||||||
},
|
},
|
||||||
xor_15_3: function() {
|
xor_15_3: function() {
|
||||||
if (fit.xor(15, 3) != 12) throw "fit.xor(15, 3) expected 12";
|
if (fit.xor(15, 3) != 12) disrupt
|
||||||
},
|
},
|
||||||
xor_13_3: function() {
|
xor_13_3: function() {
|
||||||
if (fit.xor(13, 3) != 14) throw "fit.xor(13, 3) expected 14";
|
if (fit.xor(13, 3) != 14) disrupt
|
||||||
},
|
},
|
||||||
xor_float_input: function() {
|
xor_float_input: function() {
|
||||||
if (fit.xor(13.01, 3) != null) throw "fit.xor(13.01, 3) expected null";
|
if (fit.xor(13.01, 3) != null) disrupt
|
||||||
},
|
},
|
||||||
left_12_10: function() {
|
left_12_10: function() {
|
||||||
if (fit.left(12, 10) != 12288) throw "fit.left(12, 10) expected 12288";
|
if (fit.left(12, 10) != 12288) disrupt
|
||||||
},
|
},
|
||||||
left_16_2: function() {
|
left_16_2: function() {
|
||||||
if (fit.left(16, 2) != 64) throw "fit.left(16, 2) expected 64";
|
if (fit.left(16, 2) != 64) disrupt
|
||||||
},
|
},
|
||||||
left_15_53: function() {
|
left_15_53: function() {
|
||||||
if (fit.left(15, 53) != -9007199254740992) throw "fit.left(15, 53) expected -9007199254740992";
|
if (fit.left(15, 53) != -9007199254740992) disrupt
|
||||||
},
|
},
|
||||||
right_12_10: function() {
|
right_12_10: function() {
|
||||||
if (fit.right(12, 10) != 0) throw "fit.right(12, 10) expected 0";
|
if (fit.right(12, 10) != 0) disrupt
|
||||||
},
|
},
|
||||||
right_19_2: function() {
|
right_19_2: function() {
|
||||||
if (fit.right(19, 2) != 4) throw "fit.right(19, 2) expected 4";
|
if (fit.right(19, 2) != 4) disrupt
|
||||||
},
|
},
|
||||||
right_large: function() {
|
right_large: function() {
|
||||||
if (fit.right(-9007199254740992, 53) != 7) throw "fit.right(-9007199254740992, 53) expected 7";
|
if (fit.right(-9007199254740992, 53) != 7) disrupt
|
||||||
},
|
},
|
||||||
right_signed: function() {
|
right_signed: function() {
|
||||||
if (fit.right_signed(-2, 1) != -1) throw "fit.right_signed(-2, 1) expected -1";
|
if (fit.right_signed(-2, 1) != -1) disrupt
|
||||||
},
|
},
|
||||||
mask_0: function() {
|
mask_0: function() {
|
||||||
if (fit.mask(0) != 0) throw "fit.mask(0) expected 0";
|
if (fit.mask(0) != 0) disrupt
|
||||||
},
|
},
|
||||||
mask_1: function() {
|
mask_1: function() {
|
||||||
if (fit.mask(1) != 1) throw "fit.mask(1) expected 1";
|
if (fit.mask(1) != 1) disrupt
|
||||||
},
|
},
|
||||||
mask_3: function() {
|
mask_3: function() {
|
||||||
if (fit.mask(3) != 7) throw "fit.mask(3) expected 7";
|
if (fit.mask(3) != 7) disrupt
|
||||||
},
|
},
|
||||||
mask_8: function() {
|
mask_8: function() {
|
||||||
if (fit.mask(8) != 255) throw "fit.mask(8) expected 255";
|
if (fit.mask(8) != 255) disrupt
|
||||||
},
|
},
|
||||||
mask_16: function() {
|
mask_16: function() {
|
||||||
if (fit.mask(16) != 65535) throw "fit.mask(16) expected 65535";
|
if (fit.mask(16) != 65535) disrupt
|
||||||
},
|
},
|
||||||
mask_32: function() {
|
mask_32: function() {
|
||||||
if (fit.mask(32) != 4294967295) throw "fit.mask(32) expected 4294967295";
|
if (fit.mask(32) != 4294967295) disrupt
|
||||||
},
|
},
|
||||||
mask_55: function() {
|
mask_55: function() {
|
||||||
if (fit.mask(55) != 36028797018963967) throw "fit.mask(55) expected 36028797018963967";
|
if (fit.mask(55) != 36028797018963967) disrupt
|
||||||
},
|
},
|
||||||
mask_56: function() {
|
mask_56: function() {
|
||||||
if (fit.mask(56) != -1) throw "fit.mask(56) expected -1";
|
if (fit.mask(56) != -1) disrupt
|
||||||
},
|
},
|
||||||
mask_57: function() {
|
mask_57: function() {
|
||||||
if (fit.mask(57) != null) throw "fit.mask(57) expected null";
|
if (fit.mask(57) != null) disrupt
|
||||||
},
|
},
|
||||||
mask_neg1: function() {
|
mask_neg1: function() {
|
||||||
if (fit.mask(-1) != -2) throw "fit.mask(-1) expected -2";
|
if (fit.mask(-1) != -2) disrupt
|
||||||
},
|
},
|
||||||
mask_neg3: function() {
|
mask_neg3: function() {
|
||||||
if (fit.mask(-3) != -8) throw "fit.mask(-3) expected -8";
|
if (fit.mask(-3) != -8) disrupt
|
||||||
},
|
},
|
||||||
mask_neg8: function() {
|
mask_neg8: function() {
|
||||||
if (fit.mask(-8) != -256) throw "fit.mask(-8) expected -256";
|
if (fit.mask(-8) != -256) disrupt
|
||||||
},
|
},
|
||||||
mask_neg16: function() {
|
mask_neg16: function() {
|
||||||
if (fit.mask(-16) != -65536) throw "fit.mask(-16) expected -65536";
|
if (fit.mask(-16) != -65536) disrupt
|
||||||
},
|
},
|
||||||
mask_neg32: function() {
|
mask_neg32: function() {
|
||||||
if (fit.mask(-32) != -4294967296) throw "fit.mask(-32) expected -4294967296";
|
if (fit.mask(-32) != -4294967296) disrupt
|
||||||
},
|
},
|
||||||
mask_neg55: function() {
|
mask_neg55: function() {
|
||||||
if (fit.mask(-55) != -36028797018963968) throw "fit.mask(-55) expected -36028797018963968";
|
if (fit.mask(-55) != -36028797018963968) disrupt
|
||||||
},
|
},
|
||||||
mask_neg56: function() {
|
mask_neg56: function() {
|
||||||
if (fit.mask(-56) != 0) throw "fit.mask(-56) expected 0";
|
if (fit.mask(-56) != 0) disrupt
|
||||||
},
|
},
|
||||||
not_0: function() {
|
not_0: function() {
|
||||||
if (fit.not(0) != -1) throw "fit.not(0) expected -1";
|
if (fit.not(0) != -1) disrupt
|
||||||
},
|
},
|
||||||
not_1: function() {
|
not_1: function() {
|
||||||
if (fit.not(1) != -2) throw "fit.not(1) expected -2";
|
if (fit.not(1) != -2) disrupt
|
||||||
},
|
},
|
||||||
not_neg1: function() {
|
not_neg1: function() {
|
||||||
if (fit.not(-1) != 0) throw "fit.not(-1) expected 0";
|
if (fit.not(-1) != 0) disrupt
|
||||||
},
|
},
|
||||||
ones_neg1: function() {
|
ones_neg1: function() {
|
||||||
if (fit.ones(-1) != 56) throw "fit.ones(-1) expected 56";
|
if (fit.ones(-1) != 56) disrupt
|
||||||
},
|
},
|
||||||
ones_0: function() {
|
ones_0: function() {
|
||||||
if (fit.ones(0) != 0) throw "fit.ones(0) expected 0";
|
if (fit.ones(0) != 0) disrupt
|
||||||
},
|
},
|
||||||
ones_8: function() {
|
ones_8: function() {
|
||||||
if (fit.ones(8) != 1) throw "fit.ones(8) expected 1";
|
if (fit.ones(8) != 1) disrupt
|
||||||
},
|
},
|
||||||
ones_18: function() {
|
ones_18: function() {
|
||||||
if (fit.ones(18) != 2) throw "fit.ones(18) expected 2";
|
if (fit.ones(18) != 2) disrupt
|
||||||
},
|
},
|
||||||
ones_255: function() {
|
ones_255: function() {
|
||||||
if (fit.ones(255) != 8) throw "fit.ones(255) expected 8";
|
if (fit.ones(255) != 8) disrupt
|
||||||
},
|
},
|
||||||
zeros_neg1: function() {
|
zeros_neg1: function() {
|
||||||
if (fit.zeros(-1) != 0) throw "fit.zeros(-1) expected 0";
|
if (fit.zeros(-1) != 0) disrupt
|
||||||
},
|
},
|
||||||
zeros_0: function() {
|
zeros_0: function() {
|
||||||
if (fit.zeros(0) != 56) throw "fit.zeros(0) expected 56";
|
if (fit.zeros(0) != 56) disrupt
|
||||||
},
|
},
|
||||||
zeros_1: function() {
|
zeros_1: function() {
|
||||||
if (fit.zeros(1) != 55) throw "fit.zeros(1) expected 55";
|
if (fit.zeros(1) != 55) disrupt
|
||||||
},
|
},
|
||||||
zeros_2: function() {
|
zeros_2: function() {
|
||||||
if (fit.zeros(2) != 54) throw "fit.zeros(2) expected 54";
|
if (fit.zeros(2) != 54) disrupt
|
||||||
},
|
},
|
||||||
zeros_1024: function() {
|
zeros_1024: function() {
|
||||||
if (fit.zeros(1024) != 45) throw "fit.zeros(1024) expected 45";
|
if (fit.zeros(1024) != 45) disrupt
|
||||||
},
|
},
|
||||||
rotate_1_1: function() {
|
rotate_1_1: function() {
|
||||||
if (fit.rotate(1, 1) != 2) throw "fit.rotate(1, 1) expected 2";
|
if (fit.rotate(1, 1) != 2) disrupt
|
||||||
},
|
},
|
||||||
rotate_neg2_1: function() {
|
rotate_neg2_1: function() {
|
||||||
if (fit.rotate(-2, 1) != -3) throw "fit.rotate(-2, 1) expected -3";
|
if (fit.rotate(-2, 1) != -3) disrupt
|
||||||
},
|
},
|
||||||
rotate_full: function() {
|
rotate_full: function() {
|
||||||
if (fit.rotate(1, 56) != 1) throw "fit.rotate(1, 56) expected 1";
|
if (fit.rotate(1, 56) != 1) disrupt
|
||||||
},
|
},
|
||||||
rotate_right: function() {
|
rotate_right: function() {
|
||||||
if (fit.rotate(1, -1) != 1 << 55) throw "fit.rotate(1, -1) expected 1 << 55";
|
if (fit.rotate(1, -1) != 1 << 55) disrupt
|
||||||
},
|
},
|
||||||
reverse_neg: function() {
|
reverse_neg: function() {
|
||||||
if (fit.reverse(-36028797018963968) != 1) throw "fit.reverse(-36028797018963968) expected 1";
|
if (fit.reverse(-36028797018963968) != 1) disrupt
|
||||||
},
|
},
|
||||||
reverse_pi: function() {
|
reverse_pi: function() {
|
||||||
if (fit.reverse(3141592653589793) != 2334719610726733) throw "fit.reverse(3141592653589793) expected 2334719610726733";
|
if (fit.reverse(3141592653589793) != 2334719610726733) disrupt
|
||||||
},
|
},
|
||||||
and_out_of_range: function() {
|
and_out_of_range: function() {
|
||||||
if (fit.and(1 << 56, 1) != null) throw "fit.and with out-of-range expected null";
|
if (fit.and(1 << 56, 1) != null) disrupt
|
||||||
},
|
},
|
||||||
left_negative_shift: function() {
|
left_negative_shift: function() {
|
||||||
if (fit.left(1, -1) != null) throw "fit.left with negative shift expected null";
|
if (fit.left(1, -1) != null) disrupt
|
||||||
},
|
},
|
||||||
left_large_shift: function() {
|
left_large_shift: function() {
|
||||||
if (fit.left(1, 100) != null) throw "fit.left with large shift expected null";
|
if (fit.left(1, 100) != null) disrupt
|
||||||
},
|
},
|
||||||
right_negative_shift: function() {
|
right_negative_shift: function() {
|
||||||
if (fit.right(1, -1) != null) throw "fit.right with negative shift expected null";
|
if (fit.right(1, -1) != null) disrupt
|
||||||
},
|
},
|
||||||
mask_float: function() {
|
mask_float: function() {
|
||||||
if (fit.mask(3.5) != null) throw "fit.mask with float expected null";
|
if (fit.mask(3.5) != null) disrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ var http = use('http')
|
|||||||
return function() {
|
return function() {
|
||||||
var url = "http://example.com"
|
var url = "http://example.com"
|
||||||
var b2 = http.fetch(url)
|
var b2 = http.fetch(url)
|
||||||
if (length(b2) == 0) throw "Empty response"
|
if (length(b2) == 0) disrupt
|
||||||
}
|
}
|
||||||
10
tests/kim.cm
10
tests/kim.cm
@@ -6,34 +6,34 @@ return {
|
|||||||
var input = "Hello, World!";
|
var input = "Hello, World!";
|
||||||
var encoded = kim.encode(input);
|
var encoded = kim.encode(input);
|
||||||
var decoded = kim.decode(encoded);
|
var decoded = kim.decode(encoded);
|
||||||
if (input != decoded) throw "ASCII encoding/decoding failed"
|
if (input != decoded) disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
unicode_multilingual: function() {
|
unicode_multilingual: function() {
|
||||||
var input = "Hello, 世界! 🌍 Привет мир";
|
var input = "Hello, 世界! 🌍 Привет мир";
|
||||||
var encoded = kim.encode(input);
|
var encoded = kim.encode(input);
|
||||||
var decoded = kim.decode(encoded);
|
var decoded = kim.decode(encoded);
|
||||||
if (input != decoded) throw "Unicode multilingual encoding/decoding failed"
|
if (input != decoded) disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
empty_string: function() {
|
empty_string: function() {
|
||||||
var input = " ";
|
var input = " ";
|
||||||
var encoded = kim.encode(input);
|
var encoded = kim.encode(input);
|
||||||
var decoded = kim.decode(encoded);
|
var decoded = kim.decode(encoded);
|
||||||
if (input != decoded) throw "Empty string encoding/decoding failed"
|
if (input != decoded) disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
mixed_unicode_ranges: function() {
|
mixed_unicode_ranges: function() {
|
||||||
var input = "αβγδε АБВГД 你好 😀😎🎉 ∑∏∫";
|
var input = "αβγδε АБВГД 你好 😀😎🎉 ∑∏∫";
|
||||||
var encoded = kim.encode(input);
|
var encoded = kim.encode(input);
|
||||||
var decoded = kim.decode(encoded);
|
var decoded = kim.decode(encoded);
|
||||||
if (input != decoded) throw "Mixed Unicode ranges encoding/decoding failed"
|
if (input != decoded) disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
high_codepoints: function() {
|
high_codepoints: function() {
|
||||||
var input = "🌍🌎🌏🗺️🧭";
|
var input = "🌍🌎🌏🗺️🧭";
|
||||||
var encoded = kim.encode(input);
|
var encoded = kim.encode(input);
|
||||||
var decoded = kim.decode(encoded);
|
var decoded = kim.decode(encoded);
|
||||||
if (input != decoded) throw "High codepoints encoding/decoding failed"
|
if (input != decoded) disrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,79 +8,99 @@ return {
|
|||||||
var SOURCE_PATH = "miniz_source.txt"
|
var SOURCE_PATH = "miniz_source.txt"
|
||||||
var ENTRY_PATH = "sample/hello.txt"
|
var ENTRY_PATH = "sample/hello.txt"
|
||||||
var PAYLOAD = "Miniz integration test payload."
|
var PAYLOAD = "Miniz integration test payload."
|
||||||
|
var source_blob = null
|
||||||
|
var writer = null
|
||||||
|
var zip_blob = null
|
||||||
|
var reader = null
|
||||||
|
var extracted_blob = null
|
||||||
|
var extracted_text = null
|
||||||
|
|
||||||
function write_text_file(path, text) {
|
function write_text_file(path, txt) {
|
||||||
var handle = fd.open(path, "w")
|
var handle = fd.open(path, "w")
|
||||||
fd.write(handle, text)
|
fd.write(handle, txt)
|
||||||
fd.close(handle)
|
fd.close(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
var _run = function() {
|
||||||
write_text_file(SOURCE_PATH, PAYLOAD)
|
write_text_file(SOURCE_PATH, PAYLOAD)
|
||||||
var source_blob = fd.slurp(SOURCE_PATH)
|
source_blob = fd.slurp(SOURCE_PATH)
|
||||||
var writer = miniz.write(ZIP_PATH)
|
writer = miniz.write(ZIP_PATH)
|
||||||
writer.add_file(ENTRY_PATH, source_blob)
|
writer.add_file(ENTRY_PATH, source_blob)
|
||||||
writer = null
|
writer = null
|
||||||
|
|
||||||
var zip_blob = fd.slurp(ZIP_PATH)
|
zip_blob = fd.slurp(ZIP_PATH)
|
||||||
var reader = miniz.read(zip_blob)
|
reader = miniz.read(zip_blob)
|
||||||
|
|
||||||
if (!reader.exists(ENTRY_PATH))
|
if (!reader.exists(ENTRY_PATH))
|
||||||
throw "entry missing in archive"
|
disrupt
|
||||||
|
|
||||||
var extracted_blob = reader.slurp(ENTRY_PATH)
|
extracted_blob = reader.slurp(ENTRY_PATH)
|
||||||
var extracted_text = utf8.decode(extracted_blob)
|
extracted_text = utf8.decode(extracted_blob)
|
||||||
|
|
||||||
if (extracted_text != PAYLOAD)
|
if (extracted_text != PAYLOAD)
|
||||||
throw "extracted text mismatch"
|
disrupt
|
||||||
} finally {
|
} disruption {}
|
||||||
try { fd.unlink(ZIP_PATH) } catch(e) {}
|
_run()
|
||||||
try { fd.unlink(SOURCE_PATH) } catch(e) {}
|
|
||||||
}
|
var _clean1 = function() { fd.unlink(ZIP_PATH) } disruption {}
|
||||||
|
_clean1()
|
||||||
|
var _clean2 = function() { fd.unlink(SOURCE_PATH) } disruption {}
|
||||||
|
_clean2()
|
||||||
},
|
},
|
||||||
|
|
||||||
list_and_count: function() {
|
list_and_count: function() {
|
||||||
var ZIP_PATH = "miniz_list_test.zip"
|
var ZIP_PATH = "miniz_list_test.zip"
|
||||||
var ENTRY1 = "file1.txt"
|
var ENTRY1 = "file1.txt"
|
||||||
var ENTRY2 = "dir/file2.txt"
|
var ENTRY2 = "dir/file2.txt"
|
||||||
|
var writer = null
|
||||||
|
var zip_blob = null
|
||||||
|
var reader = null
|
||||||
|
var listed = null
|
||||||
|
|
||||||
try {
|
var _run = function() {
|
||||||
var writer = miniz.write(ZIP_PATH)
|
writer = miniz.write(ZIP_PATH)
|
||||||
writer.add_file(ENTRY1, utf8.encode("content1"))
|
writer.add_file(ENTRY1, utf8.encode("content1"))
|
||||||
writer.add_file(ENTRY2, utf8.encode("content2"))
|
writer.add_file(ENTRY2, utf8.encode("content2"))
|
||||||
writer = null
|
writer = null
|
||||||
|
|
||||||
var zip_blob = fd.slurp(ZIP_PATH)
|
zip_blob = fd.slurp(ZIP_PATH)
|
||||||
var reader = miniz.read(zip_blob)
|
reader = miniz.read(zip_blob)
|
||||||
|
|
||||||
var listed = reader.list()
|
listed = reader.list()
|
||||||
if (length(listed) != reader.count())
|
if (length(listed) != reader.count())
|
||||||
throw "list/count mismatch"
|
disrupt
|
||||||
if (length(listed) != 2)
|
if (length(listed) != 2)
|
||||||
throw "unexpected entry count"
|
disrupt
|
||||||
} finally {
|
} disruption {}
|
||||||
try { fd.unlink(ZIP_PATH) } catch(e) {}
|
_run()
|
||||||
}
|
|
||||||
|
var _clean = function() { fd.unlink(ZIP_PATH) } disruption {}
|
||||||
|
_clean()
|
||||||
},
|
},
|
||||||
|
|
||||||
exists_check: function() {
|
exists_check: function() {
|
||||||
var ZIP_PATH = "miniz_exists_test.zip"
|
var ZIP_PATH = "miniz_exists_test.zip"
|
||||||
var ENTRY_PATH = "existing.txt"
|
var ENTRY_PATH = "existing.txt"
|
||||||
|
var writer = null
|
||||||
|
var zip_blob = null
|
||||||
|
var reader = null
|
||||||
|
|
||||||
try {
|
var _run = function() {
|
||||||
var writer = miniz.write(ZIP_PATH)
|
writer = miniz.write(ZIP_PATH)
|
||||||
writer.add_file(ENTRY_PATH, utf8.encode("data"))
|
writer.add_file(ENTRY_PATH, utf8.encode("data"))
|
||||||
writer = null
|
writer = null
|
||||||
|
|
||||||
var zip_blob = fd.slurp(ZIP_PATH)
|
zip_blob = fd.slurp(ZIP_PATH)
|
||||||
var reader = miniz.read(zip_blob)
|
reader = miniz.read(zip_blob)
|
||||||
|
|
||||||
if (!reader.exists(ENTRY_PATH))
|
if (!reader.exists(ENTRY_PATH))
|
||||||
throw "existing entry not found"
|
disrupt
|
||||||
if (reader.exists("nonexistent.txt"))
|
if (reader.exists("nonexistent.txt"))
|
||||||
throw "nonexistent entry reported as existing"
|
disrupt
|
||||||
} finally {
|
} disruption {}
|
||||||
try { fd.unlink(ZIP_PATH) } catch(e) {}
|
_run()
|
||||||
}
|
|
||||||
|
var _clean = function() { fd.unlink(ZIP_PATH) } disruption {}
|
||||||
|
_clean()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,23 +8,31 @@ function stone_if_needed(b) { if (!stone.p(b)) stone(b) }
|
|||||||
|
|
||||||
function bytes_to_blob(bytes) {
|
function bytes_to_blob(bytes) {
|
||||||
var b = blob()
|
var b = blob()
|
||||||
for (var i = 0; i < length(bytes); i++) {
|
var i = 0
|
||||||
var byte = bytes[i]
|
var byte = null
|
||||||
for (var bit = 7; bit >= 0; bit--) b.write_bit((byte >> bit) & 1)
|
var bit = null
|
||||||
|
for (i = 0; i < length(bytes); i++) {
|
||||||
|
byte = bytes[i]
|
||||||
|
for (bit = 7; bit >= 0; bit--) b.write_bit((byte >> bit) & 1)
|
||||||
}
|
}
|
||||||
stone(b)
|
stone(b)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
function deepCompare(expected, actual, path) {
|
function deepCompare(expected, actual, _path) {
|
||||||
path = path || ''
|
var diff = null
|
||||||
|
var messages = null
|
||||||
|
var expKeys = null
|
||||||
|
var actKeys = null
|
||||||
|
var i = 0
|
||||||
|
var path = _path || ''
|
||||||
if (expected == actual) return { passed: true, messages: [] };
|
if (expected == actual) return { passed: true, messages: [] };
|
||||||
|
|
||||||
if (is_number(expected) && is_number(actual)) {
|
if (is_number(expected) && is_number(actual)) {
|
||||||
if (isNaN(expected) && isNaN(actual))
|
if (isNaN(expected) && isNaN(actual))
|
||||||
return { passed: true, messages: [] };
|
return { passed: true, messages: [] };
|
||||||
|
|
||||||
var diff = abs(expected - actual);
|
diff = abs(expected - actual);
|
||||||
if (diff <= EPSILON)
|
if (diff <= EPSILON)
|
||||||
return { passed: true, messages: [] };
|
return { passed: true, messages: [] };
|
||||||
|
|
||||||
@@ -41,7 +49,7 @@ function deepCompare(expected, actual, path) {
|
|||||||
stone_if_needed(expected); stone_if_needed(actual)
|
stone_if_needed(expected); stone_if_needed(actual)
|
||||||
if (length(expected) != length(actual))
|
if (length(expected) != length(actual))
|
||||||
return { passed: false, messages: [`blob length mismatch at ${path}: ${length(expected)} vs ${length(actual)}`] }
|
return { passed: false, messages: [`blob length mismatch at ${path}: ${length(expected)} vs ${length(actual)}`] }
|
||||||
for (var i = 0; i < length(expected); i++) {
|
for (i = 0; i < length(expected); i++) {
|
||||||
if (expected.read_logical(i) != actual.read_logical(i))
|
if (expected.read_logical(i) != actual.read_logical(i))
|
||||||
return { passed: false, messages: [`blob bit mismatch at ${path}[${i}]`] }
|
return { passed: false, messages: [`blob bit mismatch at ${path}[${i}]`] }
|
||||||
}
|
}
|
||||||
@@ -54,7 +62,7 @@ function deepCompare(expected, actual, path) {
|
|||||||
passed: false,
|
passed: false,
|
||||||
messages: [`Array length mismatch at ${path}: expected ${length(expected)}, got ${length(actual)}`]
|
messages: [`Array length mismatch at ${path}: expected ${length(expected)}, got ${length(actual)}`]
|
||||||
};
|
};
|
||||||
var messages = [];
|
messages = [];
|
||||||
arrfor(expected, function(val, i) {
|
arrfor(expected, function(val, i) {
|
||||||
var result = deepCompare(val, actual[i], `${path}[${i}]`);
|
var result = deepCompare(val, actual[i], `${path}[${i}]`);
|
||||||
if (!result.passed)
|
if (!result.passed)
|
||||||
@@ -64,14 +72,14 @@ function deepCompare(expected, actual, path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_object(expected) && is_object(actual)) {
|
if (is_object(expected) && is_object(actual)) {
|
||||||
var expKeys = sort(array(expected))
|
expKeys = sort(array(expected))
|
||||||
var actKeys = sort(array(actual))
|
actKeys = sort(array(actual))
|
||||||
if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
|
if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
|
||||||
return {
|
return {
|
||||||
passed: false,
|
passed: false,
|
||||||
messages: [`Object keys mismatch at ${path}: expected ${expKeys}, got ${actKeys}`]
|
messages: [`Object keys mismatch at ${path}: expected ${expKeys}, got ${actKeys}`]
|
||||||
};
|
};
|
||||||
var messages = [];
|
messages = [];
|
||||||
arrfor(expKeys, function(key) {
|
arrfor(expKeys, function(key) {
|
||||||
var result = deepCompare(expected[key], actual[key], `${path}.${key}`);
|
var result = deepCompare(expected[key], actual[key], `${path}.${key}`);
|
||||||
if (!result.passed)
|
if (!result.passed)
|
||||||
@@ -89,26 +97,32 @@ function deepCompare(expected, actual, path) {
|
|||||||
function makeTest(test) {
|
function makeTest(test) {
|
||||||
return function() {
|
return function() {
|
||||||
var encoded = test.replacer ? nota.encode(test.input, test.replacer) : nota.encode(test.input);
|
var encoded = test.replacer ? nota.encode(test.input, test.replacer) : nota.encode(test.input);
|
||||||
|
var decoded = null
|
||||||
|
var expected = null
|
||||||
|
var key = null
|
||||||
|
var compareResult = null
|
||||||
if (!is_blob(encoded)) {
|
if (!is_blob(encoded)) {
|
||||||
throw "encode() should return blob";
|
disrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
var decoded = test.reviver ? nota.decode(encoded, test.reviver) : nota.decode(encoded);
|
decoded = test.reviver ? nota.decode(encoded, test.reviver) : nota.decode(encoded);
|
||||||
var expected = test.expected || test.input;
|
expected = test.expected || test.input;
|
||||||
if (expected && (expected.private || expected.system)) {
|
if (expected && (expected.private || expected.system)) {
|
||||||
var key = expected.private ? 'private' : 'system';
|
key = expected.private ? 'private' : 'system';
|
||||||
expected = { [key]: expected[key] };
|
expected = { [key]: expected[key] };
|
||||||
}
|
}
|
||||||
|
|
||||||
var compareResult = deepCompare(expected, decoded);
|
compareResult = deepCompare(expected, decoded);
|
||||||
if (!compareResult.passed) {
|
if (!compareResult.passed) {
|
||||||
throw text(compareResult.messages, '; ');
|
disrupt
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var testarr = []
|
var testarr = []
|
||||||
for (var i = 0; i < 500; i++) {
|
var i = 0
|
||||||
|
var t = null
|
||||||
|
for (i = 0; i < 500; i++) {
|
||||||
push(testarr, 1)
|
push(testarr, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,8 +186,8 @@ var testCases = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
var tests = {};
|
var tests = {};
|
||||||
for (var i = 0; i < length(testCases); i++) {
|
for (i = 0; i < length(testCases); i++) {
|
||||||
var t = testCases[i];
|
t = testCases[i];
|
||||||
tests[t.name] = makeTest(t);
|
tests[t.name] = makeTest(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,28 +2,17 @@ var time = use('time');
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
test_overling: function() {
|
test_overling: function() {
|
||||||
// Ported from overling.ce
|
|
||||||
// Note: This test spawns actors and waits for them.
|
|
||||||
// In a sync function test, we can't easily wait for async actor events unless we block/poll.
|
|
||||||
// However, the new test runner might expect sync return or a promise (not available yet?).
|
|
||||||
// For now, we'll just spawn them to ensure no immediate crashes.
|
|
||||||
// Full async testing might require a different approach or `dmon.poll` style loop if events are exposed.
|
|
||||||
// Assuming for now that we just verify strict logical errors.
|
|
||||||
|
|
||||||
var underlingCount = 0;
|
var underlingCount = 0;
|
||||||
var targetCount = 3;
|
var targetCount = 3;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
// Spawn several underlings
|
for (i = 0; i < targetCount; i++) {
|
||||||
for (var i = 0; i < targetCount; i++) {
|
|
||||||
$start(function(greet) {
|
$start(function(greet) {
|
||||||
underlingCount++;
|
underlingCount++;
|
||||||
log.console("Underling spawned: " + underlingCount);
|
log.console("Underling spawned: " + underlingCount);
|
||||||
}, "tests/underling_actor", ["test" + i]);
|
}, "tests/underling_actor", ["test" + i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't easily wait here without a loop that yields, but this is a single threaded JS env usually.
|
|
||||||
// If $delay is async, we return immediately.
|
|
||||||
|
|
||||||
log.console("Spawned " + targetCount + " underlings (async)");
|
log.console("Spawned " + targetCount + " underlings (async)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,14 +22,7 @@ return {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var st = time.number()
|
var st = time.number()
|
||||||
var actor
|
var actor = null
|
||||||
|
|
||||||
// This test depends on 'tests/comments' which we created as 'comments.cm'
|
|
||||||
// but 'comments.cm' wraps the actor logic in a function.
|
|
||||||
// The original 'comments.ce' was an actor script.
|
|
||||||
// We should probably restore 'comments.ce' as 'comments_actor.ce' for this test to work if it relies on spawning it.
|
|
||||||
// But 'comments.cm' (the new test file) also has the logic.
|
|
||||||
// We need an actor file for $start to work with.
|
|
||||||
|
|
||||||
$start(e => {
|
$start(e => {
|
||||||
if (actor) return
|
if (actor) return
|
||||||
@@ -42,6 +35,6 @@ return {
|
|||||||
|
|
||||||
log.console(`took ${time.number()-st} secs`)
|
log.console(`took ${time.number()-st} secs`)
|
||||||
});
|
});
|
||||||
}, "tests/comments_actor") // We will create this next
|
}, "tests/comments_actor")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,247 +1,241 @@
|
|||||||
return {
|
return {
|
||||||
// Array conversion tests
|
|
||||||
test_array_basic: function() {
|
test_array_basic: function() {
|
||||||
var arr1 = ["Hello", " ", "World"]
|
var arr1 = ["Hello", " ", "World"]
|
||||||
var result1 = text(arr1)
|
var result1 = text(arr1)
|
||||||
if (result1 != "Hello World") throw "Basic array concat failed"
|
if (result1 != "Hello World") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_separator: function() {
|
test_array_separator: function() {
|
||||||
var arr2 = ["one", "two", "three"]
|
var arr2 = ["one", "two", "three"]
|
||||||
var result2 = text(arr2, ", ")
|
var result2 = text(arr2, ", ")
|
||||||
if (result2 != "one, two, three") throw "Array with separator failed"
|
if (result2 != "one, two, three") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_codepoints: function() {
|
test_array_codepoints: function() {
|
||||||
var arr3 = [72, 101, 108, 108, 111]
|
var arr3 = [72, 101, 108, 108, 111]
|
||||||
var result3 = text(arr3)
|
var result3 = text(arr3)
|
||||||
if (result3 != "Hello") throw "Codepoints failed"
|
if (result3 != "Hello") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_mixed: function() {
|
test_array_mixed: function() {
|
||||||
var arr4 = ["Hi", 32, "there", 33]
|
var arr4 = ["Hi", 32, "there", 33]
|
||||||
var result4 = text(arr4)
|
var result4 = text(arr4)
|
||||||
if (result4 != "Hi there!") throw "Mixed array failed"
|
if (result4 != "Hi there!") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
// Radix tests
|
|
||||||
test_radix_10: function() {
|
test_radix_10: function() {
|
||||||
var result = text(12, 10)
|
var result = text(12, 10)
|
||||||
if (result != "12") throw "Radix 10 failed"
|
if (result != "12") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_radix_8: function() {
|
test_radix_8: function() {
|
||||||
var result = text(12, 8)
|
var result = text(12, 8)
|
||||||
if (result != "14") throw "Radix 8 failed"
|
if (result != "14") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_radix_16: function() {
|
test_radix_16: function() {
|
||||||
var result = text(12, 16)
|
var result = text(12, 16)
|
||||||
if (result != "c") throw "Radix 16 failed"
|
if (result != "c") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_radix_2: function() {
|
test_radix_2: function() {
|
||||||
var result = text(12, 2)
|
var result = text(12, 2)
|
||||||
if (result != "1100") throw "Radix 2 failed"
|
if (result != "1100") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_radix_32: function() {
|
test_radix_32: function() {
|
||||||
var result = text(12, 32)
|
var result = text(12, 32)
|
||||||
if (result != "c") throw "Radix 32 failed"
|
if (result != "c") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_radix_hex_large: function() {
|
test_radix_hex_large: function() {
|
||||||
var result = text(255, 16)
|
var result = text(255, 16)
|
||||||
if (result != "ff") throw "Radix 16 large failed"
|
if (result != "ff") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_radix_negative: function() {
|
test_radix_negative: function() {
|
||||||
var result = text(-42, 10)
|
var result = text(-42, 10)
|
||||||
if (result != "-42") throw "Radix negative failed"
|
if (result != "-42") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_radix_36: function() {
|
test_radix_36: function() {
|
||||||
var result = text(100, 36)
|
var result = text(100, 36)
|
||||||
if (result != "2s") throw "Radix 36 failed"
|
if (result != "2s") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
// Formatted number tests
|
|
||||||
test_format_n: function() {
|
test_format_n: function() {
|
||||||
var result = text(123456789.1, "n")
|
var result = text(123456789.1, "n")
|
||||||
if (result != "123456789.1") throw "Format n failed"
|
if (result != "123456789.1") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_spaced_decimal: function() {
|
test_format_spaced_decimal: function() {
|
||||||
var result = text(123456789.1, "3s4")
|
var result = text(123456789.1, "3s4")
|
||||||
if (result != "123 456 789.1000") throw "Format 3s4 failed"
|
if (result != "123 456 789.1000") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_s: function() {
|
test_format_s: function() {
|
||||||
var result = text(123456789.1, "s")
|
var result = text(123456789.1, "s")
|
||||||
if (result != "123 456 789.1") throw "Format s failed"
|
if (result != "123 456 789.1") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_d2: function() {
|
test_format_d2: function() {
|
||||||
var result = text(123456789.1, "d2")
|
var result = text(123456789.1, "d2")
|
||||||
if (result != "123,456,789.10") throw "Format d2 failed"
|
if (result != "123,456,789.10") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_4d0: function() {
|
test_format_4d0: function() {
|
||||||
var result = text(123456789.1, "4d0")
|
var result = text(123456789.1, "4d0")
|
||||||
if (result != "1,2345,6789.1") throw "Format 4d0 failed"
|
if (result != "1,2345,6789.1") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_e: function() {
|
test_format_e: function() {
|
||||||
var result = text(123456789.1, "e")
|
var result = text(123456789.1, "e")
|
||||||
if (result != "1.234567891e+8") throw "Format e failed"
|
if (result != "1.234567891e+8") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_e4: function() {
|
test_format_e4: function() {
|
||||||
var result = text(123456789.1, "e4")
|
var result = text(123456789.1, "e4")
|
||||||
if (result != "1.2346e+8") throw "Format e4 failed"
|
if (result != "1.2346e+8") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_i: function() {
|
test_format_i: function() {
|
||||||
var result = text(123456789.1, "i")
|
var result = text(123456789.1, "i")
|
||||||
if (result != "123456789") throw "Format i failed"
|
if (result != "123456789") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_8b: function() {
|
test_format_8b: function() {
|
||||||
var result = text(123456789.1, "8b")
|
var result = text(123456789.1, "8b")
|
||||||
if (result != "111_01011011_11001101_00010101") throw "Format 8b failed"
|
if (result != "111_01011011_11001101_00010101") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_o: function() {
|
test_format_o: function() {
|
||||||
var result = text(123456789.1, "o")
|
var result = text(123456789.1, "o")
|
||||||
if (result != "726746425") throw "Format o failed"
|
if (result != "726746425") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_h: function() {
|
test_format_h: function() {
|
||||||
var result = text(123456789.1, "h")
|
var result = text(123456789.1, "h")
|
||||||
if (result != "75BCD15") throw "Format h failed"
|
if (result != "75BCD15") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_format_t: function() {
|
test_format_t: function() {
|
||||||
var result = text(123456789.1, "t")
|
var result = text(123456789.1, "t")
|
||||||
if (result != "3NQK8N") throw "Format t failed"
|
if (result != "3NQK8N") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
// Integer formatting tests
|
|
||||||
test_int_4b8: function() {
|
test_int_4b8: function() {
|
||||||
var result = text(12, "4b8")
|
var result = text(12, "4b8")
|
||||||
if (result != "0000_1100") throw "Int format 4b8 failed"
|
if (result != "0000_1100") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_int_o3: function() {
|
test_int_o3: function() {
|
||||||
var result = text(12, "o3")
|
var result = text(12, "o3")
|
||||||
if (result != "014") throw "Int format o3 failed"
|
if (result != "014") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_int_h4: function() {
|
test_int_h4: function() {
|
||||||
var result = text(12, "h4")
|
var result = text(12, "h4")
|
||||||
if (result != "000C") throw "Int format h4 failed"
|
if (result != "000C") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_int_t2: function() {
|
test_int_t2: function() {
|
||||||
var result = text(12, "t2")
|
var result = text(12, "t2")
|
||||||
if (result != "0C") throw "Int format t2 failed"
|
if (result != "0C") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_int_h_negative: function() {
|
test_int_h_negative: function() {
|
||||||
var result = text(-15, "h")
|
var result = text(-15, "h")
|
||||||
if (result != "-F") throw "Int format negative h failed"
|
if (result != "-F") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_int_b_zero: function() {
|
test_int_b_zero: function() {
|
||||||
var result = text(0, "b")
|
var result = text(0, "b")
|
||||||
if (result != "0") throw "Int format zero b failed"
|
if (result != "0") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
// Substring tests
|
|
||||||
test_substr_start: function() {
|
test_substr_start: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, 0, 3)
|
var result = text(str, 0, 3)
|
||||||
if (result != "mis") throw "Substr start failed"
|
if (result != "mis") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_substr_middle: function() {
|
test_substr_middle: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, 3, 6)
|
var result = text(str, 3, 6)
|
||||||
if (result != "kat") throw "Substr middle failed"
|
if (result != "kat") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_substr_to_end: function() {
|
test_substr_to_end: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, 5, null)
|
var result = text(str, 5, null)
|
||||||
if (result != "tonic") throw "Substr to end failed"
|
if (result != "tonic") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_substr_negative_to: function() {
|
test_substr_negative_to: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, 0, -4)
|
var result = text(str, 0, -4)
|
||||||
if (result != "miskat") throw "Substr negative to failed"
|
if (result != "miskat") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_substr_negative_from: function() {
|
test_substr_negative_from: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, -3, null)
|
var result = text(str, -3, null)
|
||||||
if (result != "nic") throw "Substr negative from failed"
|
if (result != "nic") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_substr_empty_range: function() {
|
test_substr_empty_range: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, 0, 0)
|
var result = text(str, 0, 0)
|
||||||
if (result != "") throw "Substr empty range failed"
|
if (result != "") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_substr_past_end: function() {
|
test_substr_past_end: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, 10, null)
|
var result = text(str, 10, null)
|
||||||
if (result != "") throw "Substr past end failed"
|
if (result != "") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_substr_out_of_bounds: function() {
|
test_substr_out_of_bounds: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, 11, null)
|
var result = text(str, 11, null)
|
||||||
if (result != null) throw "Substr out of bounds failed"
|
if (result != null) disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_substr_invalid_range: function() {
|
test_substr_invalid_range: function() {
|
||||||
var str = "miskatonic"
|
var str = "miskatonic"
|
||||||
var result = text(str, 2, 1)
|
var result = text(str, 2, 1)
|
||||||
if (result != null) throw "Substr invalid range failed"
|
if (result != null) disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
// Edge cases
|
|
||||||
test_empty_array: function() {
|
test_empty_array: function() {
|
||||||
var result = text([])
|
var result = text([])
|
||||||
if (result != "") throw "Empty array test failed"
|
if (result != "") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_single_element: function() {
|
test_single_element: function() {
|
||||||
var result = text([42])
|
var result = text([42])
|
||||||
if (result != "42") throw "Single element array test failed"
|
if (result != "42") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_identity: function() {
|
test_identity: function() {
|
||||||
var result = text("hello")
|
var result = text("hello")
|
||||||
if (result != "hello") throw "Text identity test failed"
|
if (result != "hello") disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_invalid_format: function() {
|
test_invalid_format: function() {
|
||||||
var result = text(123, "xyz")
|
var result = text(123, "xyz")
|
||||||
if (result != null) throw "Invalid format test failed"
|
if (result != null) disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_tiny_number: function() {
|
test_tiny_number: function() {
|
||||||
var tiny = 0.0000001
|
var tiny = 0.0000001
|
||||||
var result = text(tiny, "n")
|
var result = text(tiny, "n")
|
||||||
if (search(result, 'e', 0) == null) throw "Tiny number format failed"
|
if (search(result, 'e', 0) == null) disrupt
|
||||||
},
|
},
|
||||||
|
|
||||||
test_huge_number: function() {
|
test_huge_number: function() {
|
||||||
var huge = 1e22
|
var huge = 1e22
|
||||||
var result = text(huge, "n")
|
var result = text(huge, "n")
|
||||||
if (search(result, 'e', 0) == null) throw "Huge number format failed"
|
if (search(result, 'e', 0) == null) disrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
var toml = use('toml')
|
var toml = use('toml')
|
||||||
|
|
||||||
function deep_equal(a, b) {
|
function deep_equal(a, b) {
|
||||||
|
var keys_a = null
|
||||||
|
var keys_b = null
|
||||||
|
var i = 0
|
||||||
if (a == b) return true
|
if (a == b) return true
|
||||||
if (is_null(a) || is_null(b)) return false
|
if (is_null(a) || is_null(b)) return false
|
||||||
if ((is_number(a) && !is_number(b)) || (is_text(a) && !is_text(b)) || (is_object(a) && !is_object(b)) || (is_array(a) && !is_array(b)) || (is_blob(a) && !is_blob(b)) || (is_function(a) && !is_function(b)) || (is_logical(a) && !is_logical(b))) return false
|
if ((is_number(a) && !is_number(b)) || (is_text(a) && !is_text(b)) || (is_object(a) && !is_object(b)) || (is_array(a) && !is_array(b)) || (is_blob(a) && !is_blob(b)) || (is_function(a) && !is_function(b)) || (is_logical(a) && !is_logical(b))) return false
|
||||||
|
|
||||||
if (is_object(a)) {
|
if (is_object(a)) {
|
||||||
var keys_a = array(a)
|
keys_a = array(a)
|
||||||
var keys_b = array(b)
|
keys_b = array(b)
|
||||||
if (length(keys_a) != length(keys_b)) return false
|
if (length(keys_a) != length(keys_b)) return false
|
||||||
|
|
||||||
for (var i = 0; i < length(keys_a); i++) {
|
for (i = 0; i < length(keys_a); i++) {
|
||||||
if (!deep_equal(a[keys_a[i]], b[keys_a[i]])) return false
|
if (!deep_equal(a[keys_a[i]], b[keys_a[i]])) return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -25,7 +28,7 @@ function test_roundtrip(obj, name) {
|
|||||||
if (!deep_equal(obj, decoded)) {
|
if (!deep_equal(obj, decoded)) {
|
||||||
log.console(name + " - Original:", obj)
|
log.console(name + " - Original:", obj)
|
||||||
log.console(name + " - Round-trip:", decoded)
|
log.console(name + " - Round-trip:", decoded)
|
||||||
throw name + " round-trip failed"
|
disrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
var cmds = {
|
var cmds = {
|
||||||
stop: $stop,
|
stop: $stop,
|
||||||
disrupt: _ => {
|
disrupt: _ => {
|
||||||
$delay(_ => { throw Error() }, 0.5)
|
$delay(_ => { disrupt }, 0.5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
try {
|
var _try = function() {
|
||||||
var u = use('tests/use')
|
var u = use('tests/use')
|
||||||
} catch(e) {
|
} disruption {
|
||||||
log.console(e)
|
log.console("disruption caught")
|
||||||
}
|
}
|
||||||
|
_try()
|
||||||
|
|||||||
@@ -7,14 +7,18 @@ var EPSILON = 1e-12
|
|||||||
|
|
||||||
function stone_if_needed(b) { if (!stone.p(b)) stone(b) }
|
function stone_if_needed(b) { if (!stone.p(b)) stone(b) }
|
||||||
|
|
||||||
/* Deep comparison capable of blobs + tolerance for floating diff */
|
function deep_compare(expected, actual, _path) {
|
||||||
function deep_compare(expected, actual, path) {
|
var diff = null
|
||||||
path = path || ''
|
var msgs = null
|
||||||
|
var expKeys = null
|
||||||
|
var actKeys = null
|
||||||
|
var i = 0
|
||||||
|
var path = _path || ''
|
||||||
if (expected == actual) return { passed: true, messages: [] }
|
if (expected == actual) return { passed: true, messages: [] }
|
||||||
|
|
||||||
if (is_number(expected) && is_number(actual)) {
|
if (is_number(expected) && is_number(actual)) {
|
||||||
if (isNaN(expected) && isNaN(actual)) return { passed: true, messages: [] }
|
if (isNaN(expected) && isNaN(actual)) return { passed: true, messages: [] }
|
||||||
var diff = abs(expected - actual)
|
diff = abs(expected - actual)
|
||||||
if (diff <= EPSILON) return { passed: true, messages: [] }
|
if (diff <= EPSILON) return { passed: true, messages: [] }
|
||||||
return { passed: false, messages: [`Value mismatch at ${path}: ${expected} vs ${actual} (diff ${diff})`] }
|
return { passed: false, messages: [`Value mismatch at ${path}: ${expected} vs ${actual} (diff ${diff})`] }
|
||||||
}
|
}
|
||||||
@@ -33,7 +37,7 @@ function deep_compare(expected, actual, path) {
|
|||||||
if (is_array(expected) && is_array(actual)) {
|
if (is_array(expected) && is_array(actual)) {
|
||||||
if (length(expected) != length(actual))
|
if (length(expected) != length(actual))
|
||||||
return { passed: false, messages: [`Array length mismatch at ${path}: ${length(expected)} vs ${length(actual)}`] }
|
return { passed: false, messages: [`Array length mismatch at ${path}: ${length(expected)} vs ${length(actual)}`] }
|
||||||
var msgs = []
|
msgs = []
|
||||||
arrfor(array(expected), function(i) {
|
arrfor(array(expected), function(i) {
|
||||||
var res = deep_compare(expected[i], actual[i], `${path}[${i}]`)
|
var res = deep_compare(expected[i], actual[i], `${path}[${i}]`)
|
||||||
if (!res.passed) array(msgs, res.messages)
|
if (!res.passed) array(msgs, res.messages)
|
||||||
@@ -42,11 +46,11 @@ function deep_compare(expected, actual, path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_object(expected) && is_object(actual)) {
|
if (is_object(expected) && is_object(actual)) {
|
||||||
var expKeys = sort(array(expected))
|
expKeys = sort(array(expected))
|
||||||
var actKeys = sort(array(actual))
|
actKeys = sort(array(actual))
|
||||||
if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
|
if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
|
||||||
return { passed: false, messages: [`Object keys mismatch at ${path}: ${expKeys} vs ${actKeys}`] }
|
return { passed: false, messages: [`Object keys mismatch at ${path}: ${expKeys} vs ${actKeys}`] }
|
||||||
var msgs = []
|
msgs = []
|
||||||
arrfor(expKeys, function(k) {
|
arrfor(expKeys, function(k) {
|
||||||
var res = deep_compare(expected[k], actual[k], `${path}.${k}`)
|
var res = deep_compare(expected[k], actual[k], `${path}.${k}`)
|
||||||
if (!res.passed) array(msgs, res.messages)
|
if (!res.passed) array(msgs, res.messages)
|
||||||
@@ -58,7 +62,10 @@ function deep_compare(expected, actual, path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var testarr = []
|
var testarr = []
|
||||||
for (var i = 0; i < 500; i++) { push(testarr, 1) }
|
var i = 0
|
||||||
|
var t = null
|
||||||
|
var name = null
|
||||||
|
for (i = 0; i < 500; i++) { push(testarr, 1) }
|
||||||
|
|
||||||
var testCases = [
|
var testCases = [
|
||||||
{ name: 'zero', input: 0 },
|
{ name: 'zero', input: 0 },
|
||||||
@@ -84,7 +91,7 @@ var testCases = [
|
|||||||
|
|
||||||
{ name: 'empty_string', input: '' },
|
{ name: 'empty_string', input: '' },
|
||||||
{ name: 'string_cat', input: 'cat' },
|
{ name: 'string_cat', input: 'cat' },
|
||||||
{ name: 'string_unicode', input: 'U+1F4A9 「うんち絵文字」 «💩»' },
|
{ name: 'string_unicode', input: 'U+1F4A9 「うんち絵文字」 «💩»' },
|
||||||
|
|
||||||
{ name: 'large_array', input: testarr },
|
{ name: 'large_array', input: testarr },
|
||||||
|
|
||||||
@@ -106,19 +113,19 @@ var testCases = [
|
|||||||
function make_test(t) {
|
function make_test(t) {
|
||||||
return function() {
|
return function() {
|
||||||
var enc = wota.encode(t.input)
|
var enc = wota.encode(t.input)
|
||||||
if (!is_blob(enc)) throw 'encode() should return a blob'
|
if (!is_blob(enc)) disrupt
|
||||||
|
|
||||||
var dec = wota.decode(enc)
|
var dec = wota.decode(enc)
|
||||||
|
|
||||||
var cmp = deep_compare(t.input, dec)
|
var cmp = deep_compare(t.input, dec)
|
||||||
if (!cmp.passed) throw text(cmp.messages, '; ')
|
if (!cmp.passed) disrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var tests = {}
|
var tests = {}
|
||||||
for (var i = 0; i < length(testCases); i++) {
|
for (i = 0; i < length(testCases); i++) {
|
||||||
var t = testCases[i]
|
t = testCases[i]
|
||||||
var name = t.name || ('case_' + i)
|
name = t.name || ('case_' + i)
|
||||||
tests[name] = make_test(t)
|
tests[name] = make_test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
toml.cm
8
toml.cm
@@ -87,8 +87,8 @@ function parse_toml(toml_text) {
|
|||||||
if (current_section[key] == null) return null
|
if (current_section[key] == null) return null
|
||||||
} else if (value == 'true' || value == 'false') {
|
} else if (value == 'true' || value == 'false') {
|
||||||
current_section[key] = value == 'true'
|
current_section[key] = value == 'true'
|
||||||
} else if (is_number(value)) {
|
} else if (number(value) != null) {
|
||||||
current_section[key] = Number(value)
|
current_section[key] = number(value)
|
||||||
} else {
|
} else {
|
||||||
// Unquoted string
|
// Unquoted string
|
||||||
current_section[key] = value
|
current_section[key] = value
|
||||||
@@ -187,8 +187,8 @@ function parse_value(str) {
|
|||||||
}
|
}
|
||||||
if (str == 'true' || str == 'false') return str == 'true'
|
if (str == 'true' || str == 'false') return str == 'true'
|
||||||
|
|
||||||
// Use your existing numeric test; TOML numeric formats are richer, but this keeps your "module TOML" scope.
|
var n = number(str)
|
||||||
if (!isNaN(Number(str))) return Number(str)
|
if (n != null) return n
|
||||||
|
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user