/[sudobot]/branches/9.x-dev/tests/framework/concurrent/Semaphore.test.ts
ViewVC logotype

Annotation of /branches/9.x-dev/tests/framework/concurrent/Semaphore.test.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (hide annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 3436 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 rakinar2 577 import Semaphore from "@framework/concurrent/Semaphore";
2     import { setTimeout } from "timers/promises";
3     import { describe, expect, it } from "vitest";
4    
5     describe("Semaphore", () => {
6     describe("basic usage", () => {
7     it("can be acquired and released", async () => {
8     // Arrange
9     const semaphore = new Semaphore(1);
10    
11     // Act
12     await semaphore.acquire();
13     semaphore.release();
14    
15     // Assert
16     expect(semaphore.availablePermits).toBe(1);
17     });
18    
19     it("can be acquired and released with extraneous releases", async () => {
20     // Arrange
21     const semaphore = new Semaphore({
22     ignoreExtraneousReleases: true,
23     maxPermits: 1
24     });
25    
26     // Act
27     await semaphore.acquire();
28     const permitsAfterAcquire = semaphore.availablePermits;
29     semaphore.release();
30    
31     // Assert
32     expect(semaphore.availablePermits).toBe(1);
33     expect(permitsAfterAcquire).toBe(0);
34     });
35    
36     it("can be acquired and released with extraneous releases and ignore them", async () => {
37     // Arrange
38     const semaphore = new Semaphore({
39     ignoreExtraneousReleases: true,
40     maxPermits: 1
41     });
42    
43     // Act
44     await semaphore.acquire();
45     const permitsAfterAcquire = semaphore.availablePermits;
46     semaphore.release();
47     const permitsAfterFirstRelease = semaphore.availablePermits;
48     semaphore.release();
49    
50     // Assert
51     expect(semaphore.availablePermits).toBe(1);
52     expect(permitsAfterFirstRelease).toBe(1);
53     expect(permitsAfterAcquire).toBe(0);
54     });
55    
56     it("can be acquired with extraneous releases and throws an error if opted-in", async () => {
57     // Arrange
58     const semaphore = new Semaphore({
59     ignoreExtraneousReleases: false,
60     maxPermits: 1
61     });
62    
63     // Act
64     await semaphore.acquire();
65     semaphore.release();
66    
67     // Assert
68     expect(() => semaphore.release()).toThrowError(
69     Semaphore.EXTRANEOUS_RELEASE_ERROR_MESSAGE
70     );
71     });
72     });
73    
74     describe("race condition checks", () => {
75     it(
76     "can be acquired and released with multiple acquires",
77     {
78     repeats: 10
79     },
80     async () => {
81     // Arrange
82     const semaphore = new Semaphore(1);
83     const output: number[] = [];
84     const fn1 = async () => {
85     await semaphore.acquire();
86     await setTimeout(700 * Math.random());
87     output.push(1);
88     semaphore.release();
89     };
90    
91     const fn2 = async () => {
92     await semaphore.acquire();
93     await setTimeout(240 * Math.random());
94     output.push(2);
95     semaphore.release();
96     };
97    
98     // Act
99     await Promise.all([fn1(), fn2(), fn2(), fn1(), fn1()]);
100    
101     // Assert
102     expect(semaphore.availablePermits).toBe(1);
103     expect(output).toStrictEqual([1, 2, 2, 1, 1]);
104     }
105     );
106     });
107     });

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26