-
-
Notifications
You must be signed in to change notification settings - Fork 186
/
main.spec.ts
106 lines (94 loc) · 3.36 KB
/
main.spec.ts
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
import fc from 'fast-check';
import { CasCounter as Counter } from './src/CasCounter';
//import { Counter } from './src/Counter';
// import { SynchronizedCounter as Counter } from './src/SynchronizedCounter';
if (!fc.readConfigureGlobal()) {
// Global config of Jest has been ignored, we will have a timeout after 5000ms
// (CodeSandbox falls in this category)
fc.configureGlobal({ interruptAfterTimeLimit: 4000 });
}
describe('Counter', () => {
it('should handle two concurrent calls to "inc"', async () => {
await fc.assert(
fc.asyncProperty(fc.scheduler(), async (s) => {
// Arrange
let dbValue = 0;
const db = {
read: s.scheduleFunction(async function read() {
return dbValue;
}),
write: s.scheduleFunction(async function write(newValue: number, oldValue?: number) {
if (oldValue !== undefined && dbValue !== oldValue) return false;
dbValue = newValue;
return true;
}),
};
const counter = new Counter(db);
// Act
s.schedule(Promise.resolve('inc1')).then(() => counter.inc());
s.schedule(Promise.resolve('inc2')).then(() => counter.inc());
await s.waitAll();
// Assert
expect(dbValue).toBe(2);
})
);
});
it('should handle concurrent calls to "inc"', async () => {
await fc.assert(
fc.asyncProperty(fc.scheduler(), fc.nat(64), async (s, numCalls) => {
// Arrange
let dbValue = 0;
const db = {
read: s.scheduleFunction(async function read() {
return dbValue;
}),
write: s.scheduleFunction(async function write(newValue: number, oldValue?: number) {
if (oldValue !== undefined && dbValue !== oldValue) return false;
dbValue = newValue;
return true;
}),
};
const counter = new Counter(db);
// Act
for (let callId = 0; callId < numCalls; ++callId) {
s.schedule(Promise.resolve(`inc${callId + 1}`)).then(() => counter.inc());
}
await s.waitAll();
// Assert
expect(dbValue).toBe(numCalls);
})
);
});
it('should handle concurrent calls to "inc" on multiple "Counter"', async () => {
await fc.assert(
fc.asyncProperty(fc.scheduler(), fc.array(fc.nat(64)), async (s, numCallsByCounter) => {
// Arrange
let dbValue = 0;
const db = {
read: s.scheduleFunction(async function read() {
return dbValue;
}),
write: s.scheduleFunction(async function write(newValue: number, oldValue?: number) {
if (oldValue !== undefined && dbValue !== oldValue) return false;
dbValue = newValue;
return true;
}),
};
// Act
let expectedNumCalls = 0;
for (let counterId = 0; counterId < numCallsByCounter.length; ++counterId) {
const counter = new Counter(db);
const numCalls = numCallsByCounter[counterId];
expectedNumCalls += numCalls;
for (let callId = 0; callId < numCalls; ++callId) {
s.schedule(Promise.resolve(`counter[${counterId}].inc${callId + 1}`)).then(() => counter.inc());
}
}
await s.waitAll();
// Assert
expect(dbValue).toBe(expectedNumCalls);
})
);
});
});
// Helpers