1 |
|
2 |
|
3 |
|
4 |
|
5 | "use strict";
|
6 |
|
7 | var l8 = require( "l8/lib/l8.js" )
|
8 | require( "l8/lib/transpiler.js" )
|
9 | require( "l8/lib/call.js" )
|
10 | require( "l8/lib/selector.js" )
|
11 | require( "l8/lib/aggregator.js" )
|
12 | require( "l8/lib/timeout.js" )
|
13 | require( "l8/lib/generator.js" )
|
14 | require( "l8/lib/semaphore.js" )
|
15 | require( "l8/lib/signal.js" )
|
16 | require( "l8/lib/queue.js" )
|
17 | require( "l8/lib/mutex.js" )
|
18 | require( "l8/lib/lock.js" )
|
19 | require( "l8/lib/parole.js" )
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | var trace = l8.trace
|
26 | var bug = trace
|
27 | var de = true
|
28 | l8.debug( true)
|
29 | l8.logger( function(){ return function(){} } )
|
30 | l8.trace( "SILENT TRACE" )
|
31 | l8.logger( null )
|
32 | l8.trace( "L8 TEST SUITE" )
|
33 |
|
34 | var test
|
35 |
|
36 | var traces = []
|
37 | function t(){
|
38 | if( traces.length > 200 ){
|
39 | trace( "!!! too many traces, infinite loop? exiting...")
|
40 | process.exit( 1)
|
41 | }
|
42 | var buf = ["test" + (test ? " " + test : ""), "" + l8.current.currentStep]
|
43 | for( var ii = 0 ; ii < arguments.length ; ii++ ) buf.push( arguments[ii])
|
44 | buf = trace.apply( this, buf)
|
45 | traces.push( buf)
|
46 | return buf
|
47 | }
|
48 |
|
49 | function check(){
|
50 | var ii = 0
|
51 | var msg
|
52 | var tt = 0
|
53 | var tmsg
|
54 | while( ii < arguments.length ){
|
55 | msg = arguments[ii++]
|
56 | while( true ){
|
57 | tmsg = traces[tt]
|
58 | if( tmsg && tmsg.indexOf( msg) >= 0 )break;
|
59 | if( ++tt >= traces.length ){
|
60 | msg = "FAILED test " + test + ", missing trace: " + msg
|
61 | trace( msg)
|
62 | for( var jj = 0 ; jj < ii ; jj++ ){
|
63 | trace( arguments[jj])
|
64 | }
|
65 | traces = []
|
66 | throw new Error( msg)
|
67 | }
|
68 | }
|
69 | }
|
70 | trace( "Test " + test, "PASSED")
|
71 | traces = []
|
72 | }
|
73 |
|
74 | var test_1 = function test1(){
|
75 | test = 1
|
76 | t( "go")
|
77 | l8.begin
|
78 | .step( function(){ t( "start") })
|
79 | .step( function(){ t( "step") })
|
80 | .step( function(){ t( "sleep")
|
81 | this.sleep( 100)
|
82 | t( "sleeping") })
|
83 | .step( function(){ t( "sleep done") })
|
84 | .failure( function( e ){ t( "!!! unexpected failure", e) })
|
85 | .final( function(){ t( "final")
|
86 | check( "start",
|
87 | "step",
|
88 | "sleep",
|
89 | "sleeping",
|
90 | "sleep done",
|
91 | "final"
|
92 | )
|
93 | test_2()
|
94 | })
|
95 | .end
|
96 | }
|
97 |
|
98 | var test_2 = l8.Task( function test2(){
|
99 | test = 2; this
|
100 | .step( function(){ t( "start") })
|
101 | .step( function(){ setTimeout( this.walk, 0) })
|
102 | .step( function(){ t( "sleep/timeout done") })
|
103 | .failure( function( e ){ t( "unexpected failure", e) })
|
104 | .final( function(){ t( "final")
|
105 | check( "start",
|
106 | "sleep/timeout done",
|
107 | "final"
|
108 | )
|
109 | test_3()
|
110 | })
|
111 | })
|
112 |
|
113 | var test_3 = l8.Task( function test3(){
|
114 | test = 3; this
|
115 | .step( function(){ t( "start") })
|
116 | .step( function(){ t( "add step 1"); this
|
117 | .step( function(){ t( "first step") })
|
118 | t( "add step 2"); this
|
119 | .step( function(){ t( "second step") }) })
|
120 | .step( function(){ t("third & final step") })
|
121 | .success( function(){ t("success") })
|
122 | .failure( function( e ){ t( "unexpected failure", e) })
|
123 | .final( function(){ t( "final")
|
124 | check( "start",
|
125 | "success",
|
126 | "final"
|
127 | )
|
128 | test_4()
|
129 | })
|
130 | })
|
131 |
|
132 | var test_4 = l8.Task( function test4(){
|
133 | test = 4; this
|
134 | .step( function(){ t( "start") })
|
135 | .step( function(){ t( "raise error")
|
136 | throw new Error( "step error") })
|
137 | .step( function(){ t("!!! skipped step") })
|
138 | .failure( function(){ t("error raised", this.error) })
|
139 | .final( function(){ t( "final")
|
140 | check( "start",
|
141 | "error raised",
|
142 | "final"
|
143 | )
|
144 | test_5()
|
145 | })
|
146 | })
|
147 |
|
148 | var test_5 = l8.Task( function test5(){
|
149 | test = 5; t( "start"); this
|
150 | .fork( function(){ this.label = t( "fork 1"); this
|
151 | .step( function(){ this.sleep( 10) })
|
152 | .step( function(){ t( "end fork 1") }) })
|
153 | .fork( function(){ this.label = t( "fork 2"); this
|
154 | .step( function(){ this.sleep( 5) })
|
155 | .step( function(){ t( "end fork 2") }) })
|
156 | .step( function(){ t( "joined") })
|
157 | .fork( function(){ this.label = t( "fork 3"); this
|
158 | .step( function(){ this.sleep( 1) })
|
159 | .final( function(){ t( "final of fork 3") }) })
|
160 | .fork( function(){ this.label = t( "fork 4"); this
|
161 | .final( function(){ t( "final of fork 4") }) })
|
162 | .step( function(){ t( "joined again") })
|
163 | .failure( function( e ){ t( "unexpected failure", e) })
|
164 | .final( function(){ t( "final")
|
165 | check( "start",
|
166 | "fork 1",
|
167 | "fork 2",
|
168 | "end fork 2",
|
169 | "end fork 1",
|
170 | "joined",
|
171 | "fork 3",
|
172 | "fork 4",
|
173 | "final of fork 4",
|
174 | "final of fork 3",
|
175 | "joined again",
|
176 | "final"
|
177 | )
|
178 | test_6()
|
179 | })
|
180 | })
|
181 |
|
182 | var test_6 = l8.Task( function test6(){
|
183 | function other1(){ l8.step( function(){ t( "in other1")} )}
|
184 | function other2(){ l8.fork( function(){ t( "in other2")} )}
|
185 | test = 6; this
|
186 | .step( function(){ other1(); t( "other1() called") })
|
187 | .step( function(){ t( "other1 result", this.result); this
|
188 | other2(); t( "other2() called") })
|
189 | .step( function(){ t( "other2 result", this.result) })
|
190 | .failure( function( e ){ t( "unexpected failure", e) })
|
191 | .final( function(){ t( "final result", this.result)
|
192 | check( "other1() called",
|
193 | "in other1",
|
194 | "other1 result",
|
195 | "other2() called",
|
196 | "in other2",
|
197 | "other2 result",
|
198 | "final result"
|
199 | )
|
200 | test_7()
|
201 | })
|
202 | })
|
203 |
|
204 | var test_7 = l8.Task( function test7(){
|
205 | test = 7
|
206 | var ii; this
|
207 | .step( function(){ t( "simple, times", ii = 3) })
|
208 | .repeat( function(){ t( "repeat simple step", ii)
|
209 | if( --ii === 0 ){
|
210 | t( "break simple repeat")
|
211 | this.break
|
212 | } })
|
213 | .step( function(){ t( "simple repeat done") })
|
214 | .step( function(){ t( "sleep, times", ii = 2) })
|
215 | .repeat( function(){ this
|
216 | .step( function(){ t( "repeat sleep", ii)
|
217 | this.sleep( 1) })
|
218 | .step( function(){ t( "done sleep", ii) })
|
219 | .step( function(){ if( --ii === 0 ){
|
220 | t( "break sleep repeat")
|
221 | this.break
|
222 | } }) })
|
223 | .step( function(){ t( "done ") })
|
224 | .failure( function( e ){ t( "unexpected failure", e) })
|
225 | .final( function(){ t( "final result", this.result)
|
226 | check( "simple, times",
|
227 | "repeat simple step",
|
228 | "break simple repeat",
|
229 | "simple repeat done",
|
230 | "sleep, times",
|
231 | "done sleep",
|
232 | "break sleep repeat",
|
233 | "done",
|
234 | "final result"
|
235 | )
|
236 | test_8()
|
237 | })
|
238 | })
|
239 |
|
240 |
|
241 |
|
242 |
|
243 | l8.eval = function( expr ){ return eval( expr) }
|
244 |
|
245 | var test_8 = l8.compile( function xx(){
|
246 | test = 8
|
247 | var f1 = l8.Task( function( p1, p2 ){
|
248 | t( "p1", p1, "p2", p2)
|
249 | return [p1,p2]
|
250 | })
|
251 | step;
|
252 | t( "pass parameter, get result");
|
253 | f1( "aa", "bb")
|
254 | step( r );
|
255 | t( "both", r.join( "+"))
|
256 | f1( "11", "22")
|
257 | step( a, b ); t( "a", a, "b", b)
|
258 | fork; return "f1"
|
259 | fork; return "f2"
|
260 | step( f1, f2 ); t( "f1", f1, "f2", f2)
|
261 | fork; f1( "hello", "world")
|
262 | fork; f1( "keep calm", "carry on")
|
263 | step( h, k ); t( h.join( "! "), k.join( "? "))
|
264 | failure( e ); t( "unexpected error", e)
|
265 | final; check(
|
266 | "p1, aa, p2, bb",
|
267 | "both, aa+bb",
|
268 | "a, 11, b, 22",
|
269 | "f1, f1, f2, f2",
|
270 | "hello! world, keep calm? carry on"
|
271 | )
|
272 | test_9()
|
273 | })
|
274 |
|
275 | var test_9 = l8.Task( function(){
|
276 | test = 9
|
277 | var fibonacci = function(){
|
278 | var i = 0, j = 1;
|
279 | repeat; begin
|
280 | t( "yield", i)
|
281 | this.yield( i);
|
282 | var tmp = i;
|
283 | i = j;
|
284 | j += tmp;
|
285 | end
|
286 | step; t( "producer done")
|
287 | failure( e ); t( "fib, unexpected error", e)
|
288 | }
|
289 | fibonacci = l8.compileGenerator( fibonacci)
|
290 | var gen = fibonacci()
|
291 | var count_down = 10
|
292 | this.repeat( function(){
|
293 | this.step( function( ){
|
294 | if( !count_down-- ) this.break
|
295 | gen.next()
|
296 | }).step( function( r ){
|
297 | t( count_down, "fibo", r)
|
298 | })
|
299 | }).step( function(){
|
300 | t( "consumer done")
|
301 | }).failure( function( e ){ t( "unexpected error", e)
|
302 | }).final( function(){
|
303 | check(
|
304 | "fibo, 1",
|
305 | "fibo, 1",
|
306 | "fibo, 2",
|
307 | "fibo, 3",
|
308 | "fibo, 5",
|
309 | "fibo, 8",
|
310 | "fibo, 13",
|
311 | "fibo, 21",
|
312 | "fibo, 34",
|
313 | "yield, 55",
|
314 | "consumer done"
|
315 | )
|
316 | test_10()
|
317 | })
|
318 | })
|
319 |
|
320 | var test_10 = l8.Task( function(){
|
321 | test = 10
|
322 | var inner = l8.Task( function(){
|
323 | innerer( this)
|
324 | this.step( function( ){ t( "!!! Unexpected step in inner()")})
|
325 | this.success( function( r ){ t( "inner success", r) })
|
326 | this.final( function( e, r ){ t( "inner final", e, r) })
|
327 | })
|
328 | var innerer = l8.Task( function( ret ){
|
329 | innerest( ret)
|
330 | this.step( function( ){ t( "!!! Unexpected step in innerer()")})
|
331 | this.success( function( r ){ t( "innerer success", r) })
|
332 | this.final( function( e, r ){ t( "innerer final", e, r) })
|
333 | })
|
334 | var innerest = l8.Task( function( ret ){
|
335 | this.final( function( e, r ){ t( "innerest final", e, r) })
|
336 | ret.return( "From innerest")
|
337 | this.step( function( ){ t( "!!! Unexpected step in innerer()")})
|
338 | this.success( function( r ){ t( "!!! Unexpected success", r) })
|
339 | })
|
340 | this
|
341 | .step( function( ){ t( "inner()") })
|
342 | .step( function( ){ inner() })
|
343 | .step( function( r ){ t( "return", r) })
|
344 | .failure( function( e ){ t( "Unexpected error", e) })
|
345 | .final( function( ){
|
346 | check(
|
347 | "inner()",
|
348 | "innerest final, From innerest",
|
349 | "innerer success, From innerest",
|
350 | "innerer final, From innerest",
|
351 | "inner success, From innerest",
|
352 | "inner final, From innerest",
|
353 | "return, From innerest"
|
354 | )
|
355 | test_11()
|
356 | })
|
357 | })
|
358 |
|
359 | var test_11 = l8.Task( function(){
|
360 | test = 11
|
361 |
|
362 | function recur( n, next ){
|
363 | if( --n > 0 ){
|
364 |
|
365 | l8.tick( function(){ recur( n, next) })
|
366 | }else{
|
367 | next()
|
368 | }
|
369 | }
|
370 |
|
371 | var l8recur = l8.Task( function l8recur_task( n ){
|
372 |
|
373 | if( --n > 0 ){ l8recur( n) }
|
374 | })
|
375 | var now
|
376 | var n = 3
|
377 | var p = 10000
|
378 | var factor = 2
|
379 | var ii
|
380 | var duration
|
381 | var l8duration
|
382 | var tid
|
383 | var last_tid
|
384 | var was_debug = l8.debug()
|
385 | this
|
386 | .step( function(){ this.sleep( 1) })
|
387 | .step( function(){ now = l8.now; l8.debug( false) })
|
388 | .step( function(){
|
389 | var done = 0
|
390 | var task = this
|
391 | for( var ii = 0 ; ii < p ; ii++ ){
|
392 | l8.tick( function(){
|
393 | recur( n, function(){ if( ++done === p ) task.resume() })
|
394 | })
|
395 | }
|
396 | task.pause()
|
397 | })
|
398 | .step( function(){ this.sleep( 1) })
|
399 | .step( function(){
|
400 | duration = -1 + l8.now - now
|
401 | t( n * p, "times async recur()", duration, "millisecs")
|
402 | })
|
403 | .step( function(){ this.sleep( 1) })
|
404 | .step( function(){
|
405 | now = l8.now
|
406 | ii = 0
|
407 | tid = l8.current.id
|
408 | })
|
409 | .repeat( function(){
|
410 | if( ii >= p / factor ) this.break
|
411 | l8recur( n)
|
412 | ii++
|
413 | })
|
414 | .step( function(){ this.sleep( 1) })
|
415 | .fork( function(){ last_tid = this.current.id } )
|
416 | .step( function(){
|
417 | l8.debug( was_debug )
|
418 | l8duration = (-1 + (l8.now - now)) * factor
|
419 | t( n * p, "times l8recur()", l8duration, "estimated millisecs")
|
420 | t( l8duration / duration, "times slower than if native")
|
421 | t( (n * p) / duration * 1000, "native calls/sec")
|
422 | t( (n * p) / l8duration * 1000, "l8 calls/sec")
|
423 | t( (last_tid - tid) / l8duration * 1000 * factor, "l8 tasks/sec")
|
424 | })
|
425 | .failure( function( e ){ t( "!!! unexpected error", e) })
|
426 | .final( function(){
|
427 | check(
|
428 | "l8 calls/sec"
|
429 | )
|
430 | test_12()
|
431 | })
|
432 | })
|
433 |
|
434 | var test_12 = l8.Task( function(){
|
435 | try{
|
436 | test = 12
|
437 | var trace = function(){
|
438 | t( "Current task " + l8.current
|
439 | + " gets message '" + l8.get( "message")
|
440 | + "' from " + l8.binding( "message").task)
|
441 | }
|
442 | var subtask = function(){
|
443 | l8.label = "sub"
|
444 | l8.step( function(){ trace() })
|
445 | l8.step( function(){ l8.var( "message", "deeper") })
|
446 | l8.step( function(){ l8.sleep( 100) })
|
447 | l8.step( function(){ trace() })
|
448 | }
|
449 | l8.task( function(){
|
450 | l8.label = "main"
|
451 | l8.var( "message", "top")
|
452 | l8.spawn( subtask )
|
453 | l8.step( function(){ trace() })
|
454 | l8.step( function(){ l8.join() })
|
455 | })
|
456 | l8.failure( function( e ){ t( "!!! unexpected error", e) })
|
457 | l8.final( function(){
|
458 | check(
|
459 | "top",
|
460 | "top",
|
461 | "deeper"
|
462 | )
|
463 | test_last()
|
464 | })
|
465 | }catch( e ){ t( "!!! error " + e) }
|
466 | })
|
467 |
|
468 | var test_last = function(){
|
469 | trace( "SUCCESS!!! All tests ok")
|
470 | process.exit( 0)
|
471 | }
|
472 |
|
473 | trace( "starting l8")
|
474 | l8.countdown( 10)
|
475 | test_1()
|