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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (show 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 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