1+ using System ;
2+ using System . Linq ;
3+ using System . Threading ;
4+ using System . Threading . Tasks ;
5+ using Xunit ;
6+ using FluentAssertions ;
7+ using System . Collections . Generic ;
8+
9+ namespace JsonRpc . Tests
10+ {
11+ public class ProcessSchedulerTests
12+ {
13+ private const int SLEEPTIME_MS = 50 ;
14+
15+ class AllRequestProcessTypes : TheoryData
16+ {
17+ public override IEnumerator < object [ ] > GetEnumerator ( )
18+ {
19+ var values = ( object [ ] ) Enum . GetValues ( typeof ( RequestProcessType ) ) ;
20+ var qy = from v in values select new object [ ] { v } ;
21+ return qy . GetEnumerator ( ) ;
22+ }
23+ }
24+
25+ [ Theory , ClassData ( typeof ( AllRequestProcessTypes ) ) ]
26+ public void ShouldScheduleCompletedTask ( RequestProcessType type )
27+ {
28+ using ( IScheduler s = new ProcessScheduler ( ) )
29+ {
30+ var done = false ;
31+ s . Start ( ) ;
32+ s . Add ( type , ( ) => {
33+ done = true ;
34+ return Task . CompletedTask ;
35+ } ) ;
36+ Thread . Sleep ( SLEEPTIME_MS ) ;
37+ done . Should ( ) . Be ( true ) ;
38+ }
39+ }
40+
41+ [ Theory , ClassData ( typeof ( AllRequestProcessTypes ) ) ]
42+ public void ShouldScheduleAwaitableTask ( RequestProcessType type )
43+ {
44+ using ( IScheduler s = new ProcessScheduler ( ) )
45+ {
46+ var done = false ;
47+ s . Start ( ) ;
48+ s . Add ( RequestProcessType . Serial , async ( ) => {
49+ done = true ;
50+ await Task . Yield ( ) ;
51+ } ) ;
52+ Thread . Sleep ( SLEEPTIME_MS ) ;
53+ done . Should ( ) . Be ( true ) ;
54+ }
55+ }
56+
57+ public void ShouldScheduleSerialInOrder ( )
58+ {
59+ using ( IScheduler s = new ProcessScheduler ( ) )
60+ {
61+ var done = 0 ;
62+ var peek = 0 ;
63+ var peekWasMoreThanOne = 0 ;
64+
65+ Func < Task > HandlePeek = async ( ) => {
66+ Interlocked . Increment ( ref done ) ; // record that I was called
67+ var p = Interlocked . Increment ( ref peek ) ;
68+ if ( p > 1 )
69+ Interlocked . Increment ( ref peekWasMoreThanOne ) ;
70+ await Task . Delay ( SLEEPTIME_MS ) ; // give a different HandlePeek task a chance to run
71+ Interlocked . Decrement ( ref peek ) ;
72+ } ;
73+
74+ s . Start ( ) ;
75+ s . Add ( RequestProcessType . Serial , HandlePeek ) ;
76+ s . Add ( RequestProcessType . Serial , HandlePeek ) ;
77+
78+ Thread . Sleep ( SLEEPTIME_MS * 3 ) ;
79+ done . Should ( ) . Be ( 2 ) ;
80+ peek . Should ( ) . Be ( 0 ) ;
81+ peekWasMoreThanOne . Should ( ) . Be ( 0 ) ;
82+ }
83+ }
84+
85+ public void ShouldScheduleParallelInParallel ( )
86+ {
87+ using ( IScheduler s = new ProcessScheduler ( ) )
88+ {
89+ var done = 0 ;
90+ var peek = 0 ;
91+ var peekWasMoreThanOne = 0 ;
92+
93+ Func < Task > HandlePeek = async ( ) => {
94+ Interlocked . Increment ( ref done ) ; // record that I was called
95+ var p = Interlocked . Increment ( ref peek ) ;
96+ if ( p > 1 )
97+ Interlocked . Increment ( ref peekWasMoreThanOne ) ;
98+ await Task . Delay ( SLEEPTIME_MS ) ; // give a different HandlePeek task a chance to run
99+ Interlocked . Decrement ( ref peek ) ;
100+ } ;
101+
102+ s . Start ( ) ;
103+ s . Add ( RequestProcessType . Parallel , HandlePeek ) ;
104+ s . Add ( RequestProcessType . Parallel , HandlePeek ) ;
105+ s . Add ( RequestProcessType . Parallel , HandlePeek ) ;
106+ s . Add ( RequestProcessType . Parallel , HandlePeek ) ;
107+
108+ Thread . Sleep ( SLEEPTIME_MS * 2 ) ;
109+ done . Should ( ) . Be ( 4 ) ;
110+ peek . Should ( ) . Be ( 0 ) ;
111+ peekWasMoreThanOne . Should ( ) . BeGreaterThan ( 0 ) ;
112+ }
113+ }
114+ }
115+ }
0 commit comments