Mercurial > pub > ImplabNet
comparison Implab.Test/PollingComponentTests.cs @ 203:4d9830a9bbb8 v2
Added 'Fail' method to RunnableComponent which allows component to move from
Running to Failed state.
Added PollingComponent a timer based runnable component
More tests
Added FailPromise a thin class to wrap exceptions
Fixed error handling in SuccessPromise classes.
author | cin |
---|---|
date | Tue, 18 Oct 2016 17:49:54 +0300 |
parents | |
children | 8200ab154c8a |
comparison
equal
deleted
inserted
replaced
202:2651cb9a4250 | 203:4d9830a9bbb8 |
---|---|
1 using System; | |
2 using System.Reflection; | |
3 using System.Threading; | |
4 using Implab.Parallels; | |
5 using Implab.Components; | |
6 using Implab.Test.Mock; | |
7 | |
8 #if MONO | |
9 | |
10 using NUnit.Framework; | |
11 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; | |
12 using TestMethodAttribute = NUnit.Framework.TestAttribute; | |
13 using AssertFailedException = NUnit.Framework.AssertionException; | |
14 #else | |
15 | |
16 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
17 | |
18 #endif | |
19 | |
20 namespace Implab.Test { | |
21 [TestClass] | |
22 public class PollingComponentTests { | |
23 static void ShouldThrow(Action action) { | |
24 try { | |
25 action(); | |
26 Assert.Fail(); | |
27 } catch (AssertFailedException) { | |
28 throw; | |
29 } catch { | |
30 } | |
31 } | |
32 | |
33 [TestMethod] | |
34 public void NormalFlowTest() { | |
35 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, false); | |
36 | |
37 Assert.AreEqual(ExecutionState.Created, comp.State); | |
38 | |
39 comp.Init(); | |
40 | |
41 Assert.AreEqual(ExecutionState.Ready, comp.State); | |
42 | |
43 comp.Start().Join(1000); | |
44 | |
45 Assert.AreEqual(ExecutionState.Running, comp.State); | |
46 | |
47 comp.Stop().Join(1000); | |
48 | |
49 Assert.AreEqual(ExecutionState.Disposed, comp.State); | |
50 | |
51 } | |
52 | |
53 [TestMethod] | |
54 public void ShouldStartTicks() { | |
55 var signal = new Signal(); | |
56 | |
57 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true); | |
58 comp.MockTick = ct => { | |
59 signal.Set(); | |
60 return Promise.SUCCESS; | |
61 }; | |
62 | |
63 comp.Start().Join(1000); | |
64 signal.Wait(1000); | |
65 comp.Stop().Join(1000); | |
66 } | |
67 | |
68 [TestMethod] | |
69 public void StopShouldWaitForTickToComplete() { | |
70 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true); | |
71 var signal = new Signal(); | |
72 var promise = new Promise(); | |
73 | |
74 // timer should tick once | |
75 comp.MockTick = ct => { | |
76 signal.Set(); | |
77 return promise; | |
78 }; | |
79 | |
80 // start timer | |
81 comp.Start().Join(1000); | |
82 | |
83 signal.Wait(); // wait for tick | |
84 | |
85 // try to stop component | |
86 var stopping = comp.Stop(); | |
87 | |
88 Assert.AreEqual(ExecutionState.Stopping, comp.State); | |
89 ShouldThrow(() => stopping.Join(100)); | |
90 Assert.AreEqual(ExecutionState.Stopping, comp.State); | |
91 | |
92 // complete operation | |
93 promise.Resolve(); | |
94 | |
95 // the component should stop normally | |
96 stopping.Join(1000); | |
97 | |
98 Assert.AreEqual(ExecutionState.Disposed, comp.State); | |
99 } | |
100 | |
101 [TestMethod] | |
102 public void ShouldRecoverAfterTickError() { | |
103 var ticks = 0; | |
104 | |
105 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true); | |
106 var signal = new Signal(); // will signal when timer fires 10 times | |
107 | |
108 comp.MockTick = ct => { | |
109 ticks++; | |
110 if (ticks == 10) | |
111 signal.Set(); | |
112 // each time handler dies | |
113 throw new Exception("tainted handler"); | |
114 }; | |
115 | |
116 comp.Start(); | |
117 | |
118 signal.Wait(1000); | |
119 | |
120 comp.Stop().Join(1000); | |
121 | |
122 Assert.AreEqual(ExecutionState.Disposed, comp.State); | |
123 } | |
124 | |
125 [TestMethod] | |
126 public void StopCancelHandlerOnStop() { | |
127 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true); | |
128 var started = new Signal(); | |
129 bool cancelled = false; | |
130 | |
131 // timer should tick once | |
132 comp.MockTick = ct => { | |
133 started.Set(); | |
134 | |
135 while(!ct.IsCancellationRequested) { | |
136 Thread.Sleep(1); | |
137 } | |
138 | |
139 cancelled = true; | |
140 | |
141 throw new OperationCanceledException(); | |
142 }; | |
143 | |
144 // start timer | |
145 comp.Start().Join(1000); | |
146 | |
147 started.Wait(); // wait for tick | |
148 | |
149 // try to stop component | |
150 comp.Stop().Join(1000); | |
151 | |
152 Assert.AreEqual(true, cancelled); | |
153 | |
154 Assert.AreEqual(ExecutionState.Disposed, comp.State); | |
155 } | |
156 | |
157 [TestMethod] | |
158 public void FailTickOnStopShouldBeIgnored() { | |
159 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true); | |
160 var started = new Signal(); | |
161 var finish = new Signal(); | |
162 | |
163 // timer should tick once | |
164 comp.MockTick = ct => { | |
165 started.Set(); | |
166 finish.Wait(); | |
167 // component is in stopping state here | |
168 throw new Exception("Die, die, die!!!"); | |
169 }; | |
170 | |
171 | |
172 comp.MockOnError = comp.CallComponentFail; | |
173 | |
174 // start timer | |
175 comp.Start().Join(1000); | |
176 | |
177 started.Wait(); // wait for tick | |
178 | |
179 // try to stop component | |
180 var stopping = comp.Stop(); | |
181 | |
182 // the component is in stopping state but it is waiting for the tick handler to complete | |
183 finish.Set(); // signal the tick handler to finish | |
184 | |
185 // tick handler should stop rather soon | |
186 stopping.Join(1000); | |
187 | |
188 // validate the component is disposed | |
189 Assert.AreEqual(ExecutionState.Disposed, comp.State); | |
190 } | |
191 | |
192 [TestMethod] | |
193 public void FailTickShouldFailComponent() { | |
194 var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true); | |
195 var started = new Signal(); | |
196 var finish = new Signal(); | |
197 | |
198 // timer should tick once | |
199 comp.MockTick = ct => { | |
200 started.Set(); | |
201 throw new Exception("Die, die, die!!!"); | |
202 }; | |
203 | |
204 | |
205 comp.MockOnError = err => { | |
206 comp.CallComponentFail(err); | |
207 finish.Set(); | |
208 }; | |
209 | |
210 // start timer | |
211 comp.Start().Join(1000); | |
212 | |
213 started.Wait(); // wait for tick | |
214 | |
215 finish.Wait(); | |
216 | |
217 // try to stop component | |
218 ShouldThrow(() => comp.Stop()); | |
219 | |
220 Assert.AreEqual(ExecutionState.Failed, comp.State); | |
221 Assert.IsNotNull(comp.LastError); | |
222 Assert.AreEqual("Die, die, die!!!", comp.LastError.Message); | |
223 | |
224 comp.Dispose(); | |
225 Assert.AreEqual(ExecutionState.Disposed, comp.State); | |
226 } | |
227 | |
228 } | |
229 } | |
230 |