-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
Expand file tree
/
Copy pathtest-assert-large-object-diff-oom.js
More file actions
91 lines (78 loc) Β· 2.56 KB
/
test-assert-large-object-diff-oom.js
File metadata and controls
91 lines (78 loc) Β· 2.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Flags: --max-old-space-size=512
'use strict';
// Regression test: assert.strictEqual should not OOM when comparing objects
// with many converging paths to shared objects. Such objects cause exponential
// growth in util.inspect output, which previously led to OOM during error
// message generation.
require('../common');
const assert = require('assert');
// Test: should throw AssertionError, not OOM
{
const { doc1, doc2 } = createTestObjects();
assert.throws(
() => assert.strictEqual(doc1, doc2),
(err) => {
assert.ok(err instanceof assert.AssertionError);
// Message should be bounded (fix truncates inspect output at 2MB)
assert.ok(err.message.length < 5 * 1024 * 1024);
return true;
}
);
}
// Creates objects where many paths converge on shared objects, causing
// exponential growth in util.inspect output at high depths.
function createTestObjects() {
const base = createBase();
const s1 = createSchema(base, 's1');
const s2 = createSchema(base, 's2');
base.schemas.s1 = s1;
base.schemas.s2 = s2;
const doc1 = createDoc(s1, base);
const doc2 = createDoc(s2, base);
// Populated refs create additional converging paths
for (let i = 0; i < 2; i++) {
const ps = createSchema(base, 'p' + i);
base.schemas['p' + i] = ps;
doc1.$__.pop['r' + i] = { value: createDoc(ps, base), opts: { base, schema: ps } };
}
// Cross-link creates more converging paths
doc1.$__.pop.r0.value.$__parent = doc2;
return { doc1, doc2 };
}
function createBase() {
const base = { types: {}, schemas: {} };
for (let i = 0; i < 4; i++) {
base.types['t' + i] = {
base,
caster: { base },
opts: { base, validators: [{ base }, { base }] }
};
}
return base;
}
function createSchema(base, name) {
const schema = { name, base, paths: {}, children: [] };
for (let i = 0; i < 6; i++) {
schema.paths['f' + i] = {
schema, base,
type: base.types['t' + (i % 4)],
caster: base.types['t' + (i % 4)].caster,
opts: { schema, base, validators: [{ schema, base }] }
};
}
for (let i = 0; i < 2; i++) {
const child = { name: name + '_c' + i, base, parent: schema, paths: {} };
for (let j = 0; j < 3; j++) {
child.paths['cf' + j] = { schema: child, base, type: base.types['t' + (j % 4)] };
}
schema.children.push(child);
}
return schema;
}
function createDoc(schema, base) {
const doc = { schema, base, $__: { scopes: {}, pop: {} } };
for (let i = 0; i < 6; i++) {
doc.$__.scopes['p' + i] = { schema, base, type: base.types['t' + (i % 4)] };
}
return doc;
}