1 module ut.concurrency.slist;
2 
3 import concurrency.slist;
4 import concurrency.sender;
5 import concurrency.operations.whenall;
6 import concurrency.operations.then;
7 import concurrency.operations.via;
8 import concurrency.thread : ThreadSender;
9 import concurrency : syncWait;
10 import std.range : walkLength;
11 import unit_threaded;
12 
13 @("pushFront.race")
14 @safe unittest {
15   auto list = new shared SList!int;
16 
17   auto filler = just(list).then((shared SList!int list) @safe shared {
18       foreach(i; 0..100) {
19         list.pushFront(i);
20       }
21     }).via(ThreadSender());
22 
23   whenAll(filler, filler).syncWait();
24 
25   list[].walkLength.should == 200;
26 }
27 
28 @("pushBack.race")
29 @safe unittest {
30   auto list = new shared SList!int;
31 
32   auto filler = just(list).then((shared SList!int list) @safe shared {
33       foreach(i; 0..100) {
34         list.pushBack(i);
35       }
36     }).via(ThreadSender());
37 
38   whenAll(filler, filler).syncWait();
39 
40   list[].walkLength.should == 200;
41 }
42 
43 @("pushFront.adversary")
44 @safe unittest {
45   auto list = new shared SList!int;
46 
47   foreach(i; 0..50)
48     list.pushFront(1);
49 
50   auto filler = just(list).then((shared SList!int list) @safe shared {
51       foreach(i; 0..50) {
52         list.pushFront(1);
53       }
54     }).via(ThreadSender());
55   auto remover = just(list).then((shared SList!int list) @safe shared {
56       foreach(i; 0..50) {
57         list.remove(1);
58       }
59     }).via(ThreadSender());
60 
61   whenAll(filler, remover).syncWait();
62 
63   list[].walkLength.should == 50;
64 }
65 
66 @("pushBack.adversary")
67 @safe unittest {
68   auto list = new shared SList!int;
69 
70   auto filler = just(list).then((shared SList!int list) @safe shared {
71       foreach(i; 0..100) {
72         list.pushBack(1);
73       }
74     }).via(ThreadSender());
75   auto remover = just(list).then((shared SList!int list) @safe shared {
76       int n = 0;
77       while(n < 99)
78         if (list.remove(1))
79           n++;
80     }).via(ThreadSender());
81 
82   whenAll(filler, remover).syncWait();
83 
84   list[].walkLength.should == 1;
85 }
86 
87 @("remove.race")
88 @safe unittest {
89   auto list = new shared SList!int;
90 
91   foreach(i; 0..100)
92     list.pushFront(i);
93 
94   auto remover = just(list).then((shared SList!int list) @safe shared {
95       foreach(i; 0..100) {
96         if (i % 10 > 4)
97           list.remove(i);
98       }
99     }).via(ThreadSender());
100 
101   whenAll(remover, remover).syncWait();
102 
103   list[].walkLength.should == 50;
104 }
105 
106 @("remove.adjacent")
107 @safe unittest {
108   auto list = new shared SList!int;
109 
110   foreach(_; 0..2)
111     foreach(i; 0..100)
112       list.pushFront(i);
113 
114   auto remover1 = just(list).then((shared SList!int list) @safe shared {
115       foreach(i; 0..100) {
116         if (i % 2 == 0)
117           list.remove(i);
118       }
119     }).via(ThreadSender());
120   auto remover2 = just(list).then((shared SList!int list) @safe shared {
121       foreach(i; 0..100) {
122         if (i % 2 == 1)
123           list.remove(i);
124       }
125     }).via(ThreadSender());
126 
127   whenAll(remover1, remover2, remover1, remover2).syncWait();
128 
129   list[].walkLength.should == 0;
130 }