-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest.html
146 lines (128 loc) · 6.91 KB
/
test.html
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<html>
<head>
</head>
<body>
<script src="tinyveil.js"></script>
<script>
// Helper function to delay
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Define our "assert" functions for testing
const assert = {
isTrue: (condition, message) => {
if (!condition) {
throw new Error(message || "Expected condition to be true but was false");
}
},
isEqual: (actual, expected, message) => {
if (actual !== expected) {
throw new Error(message || `Expected ${actual} to equal ${expected}`);
}
},
throws: (fn, expectedMessage) => {
try {
fn();
} catch (error) {
assert.isEqual(error.message, expectedMessage, `Expected thrown message to be "${expectedMessage}" but was "${error.message}"`);
return;
}
throw new Error(`Expected function to throw an error with message "${expectedMessage}" but did not throw`);
}
};
(async () => {
console.log("Test 1: Constructor should initialize with given value");
const ocu1 = new OrderedConcurrentUpdate("initial");
assert.isEqual(ocu1.Get(), "initial", "Constructor did not initialize correctly");
console.log("Test 2: Set method should set value when no promise is in queue");
ocu1.Set("changed");
assert.isEqual(ocu1.Get(), "changed");
console.log("Test 3: Set method should throw if promises are pending");
const dummyPromise = new Promise(() => { });
ocu1.Lock(dummyPromise, (prev) => prev + " updated");
assert.throws(() => ocu1.Set("illegal"), "We cannot set this value when they are still promises working on it");
console.log("Test 4: Updates should be ordered and executed after promises are resolved");
const ocu2 = new OrderedConcurrentUpdate(0);
ocu2.Lock(delay(200).then(() => 1), (prev) => prev + 1);
ocu2.Lock(delay(100).then(() => 2), (prev) => prev * 2);
ocu2.Lock(delay(50).then(() => 3), (prev) => prev * 3);
await delay(300); // Waiting a bit more than the longest delay
assert.isEqual(ocu2.Get(), 6, "Updates were not ordered or executed correctly");
console.log("Test 5: MakeQueryablePromise should change state correctly");
const unresolvedPromise = new Promise(() => { });
const queryableUnresolved = MakeQueryablePromise(unresolvedPromise);
assert.isTrue(queryableUnresolved.isPending());
const rejectedPromise = Promise.reject(new Error("Rejected!"));
const queryableRejected = MakeQueryablePromise(rejectedPromise);
await delay(50);
assert.isTrue(queryableRejected.isRejected());
const resolvedPromise = Promise.resolve("Resolved!");
const queryableResolved = MakeQueryablePromise(resolvedPromise);
await delay(50);
assert.isTrue(queryableResolved.isFulfilled());
// Test 6: RunAtQueueEnd should execute immediately when no promises are in the queue
console.log("Test 6: RunAtQueueEnd with no promises in the queue");
const ocu3 = new OrderedConcurrentUpdate(10);
ocu3.RunAtQueueEnd(prev => prev + 10);
assert.isEqual(ocu3.Get(), 20, "RunAtQueueEnd did not execute immediately");
// Test 7: RunAtQueueEnd should execute after all promises in the queue are resolved
console.log("Test 7: RunAtQueueEnd after promises");
const ocu4 = new OrderedConcurrentUpdate(0);
ocu4.Lock(delay(100).then(() => 1), prev => prev + 1);
ocu4.Lock(delay(50).then(() => 2), prev => prev * 2);
ocu4.RunAtQueueEnd(prev => prev + 3);
await delay(150); // Waiting a bit more than the longest delay
assert.isEqual(ocu4.Get(), 5, "RunAtQueueEnd did not execute after promises");
// Test 8: RunAtQueueEnd should wait when promises are still in the queue
console.log("Test 8: RunAtQueueEnd amidst promises");
const ocu5 = new OrderedConcurrentUpdate("start");
ocu5.Lock(delay(200).then(() => "first"), prev => prev + " first");
ocu5.RunAtQueueEnd(prev => prev + " middle");
ocu5.Lock(delay(100).then(() => "last"), prev => prev + " last");
await delay(350); // Waiting for all promises to resolve and updates to run
assert.isEqual(ocu5.Get(), "start first middle last", "RunAtQueueEnd did not execute in order");
// Test 9: Nested reactions using Nested RunAtQueueEnd
console.log("Test 9: Nested reactions with Nested RunAtQueueEnd");
const ocu6 = new OrderedConcurrentUpdate(0);
ocu6.RunAtQueueEnd(prev => {
ocu6.RunAtQueueEnd(prevInner => prevInner + 2);
return prev * 3;
});
await delay(100);
assert.isEqual(ocu6.Get(), 2, "Nested reactions with Nested RunAtQueueEnd did not execute correctly");
// Test 10: Nested reactions using Nested RunAtQueueEnd and Lock
console.log("Test 10: Nested reactions with Nested RunAtQueueEnd and Lock");
const ocu7 = new OrderedConcurrentUpdate(0);
ocu7.RunAtQueueEnd(prev => {
ocu7.Lock(delay(100), function (prev2) {
ocu7.RunAtQueueEnd(function (prevInner) {
return prevInner * 2
});
return prev2 + 3;
});
ocu7.RunAtQueueEnd(function (prevInner) {
return prevInner * 5;
});
return prev * 4;
});
await delay(300);
assert.isEqual(ocu7.Get(), 30, "Nested reactions with Nested RunAtQueueEnd and Lock did not execute correctly");
// Test 11: Chain reactions using Nested RunAtQueueEnd and Lock
console.log("Test 11: Chain reactions with Nested RunAtQueueEnd and Lock");
const ocu8 = new OrderedConcurrentUpdate(0);
ocu8.RunAtQueueEnd(prev => prev + 2).Lock(delay(100), function (prev) {
ocu8.RunAtQueueEnd(function (prevInner) {
return prevInner * 2
});
return prev + 3;
}.bind(this));
ocu8.RunAtQueueEnd(prevInner => prevInner * 5);
await delay(300);
assert.isEqual(ocu8.Get(), 50, "Chain reactions with Nested RunAtQueueEnd and Lock did not execute correctly");
console.log("All tests passed!");
})().catch(error => {
console.error(`Test failed: ${error.message}`);
});
</script>
</body>
</html>