UNPKG

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