@@ -8,10 +8,13 @@ use tarantool::fiber::{
8
8
self , fiber_yield, is_cancelled, sleep, Cond , Fiber , FiberAttr
9
9
} ;
10
10
use tarantool:: hlua:: {
11
+ AsMutLua ,
11
12
Lua ,
12
13
LuaFunction
13
14
} ;
14
15
16
+ use tarantool:: ffi:: lua;
17
+
15
18
pub fn test_fiber_new ( ) {
16
19
let mut fiber = Fiber :: new ( "test_fiber" , & mut |_| 0 ) ;
17
20
fiber. set_joinable ( true ) ;
@@ -333,23 +336,57 @@ pub fn test_multiple_unit_deferred() {
333
336
}
334
337
335
338
fn fiber_csw ( ) -> i32 {
336
- static mut FLAG : bool = false ;
339
+ static mut FUNCTION_DEFINED : bool = false ;
337
340
let mut lua: Lua = crate :: hlua:: global ( ) ;
338
341
339
- if unsafe { !FLAG } {
342
+ if unsafe { !FUNCTION_DEFINED } {
340
343
lua. execute :: < ( ) > ( r#"
341
344
function fiber_csw()
342
- local fiber = require('fiber')
343
- return fiber.info()[fiber.id()].csw
345
+ local fiber = require('fiber')
346
+ return fiber.info()[fiber.id()].csw
344
347
end
345
348
"# ) . unwrap ( ) ;
346
- unsafe { FLAG = true ; }
349
+ unsafe { FUNCTION_DEFINED = true ; }
347
350
}
348
351
349
352
return lua. get :: < LuaFunction < _ > , _ > ( "fiber_csw" ) . unwrap ( ) . call ( ) . unwrap ( ) ;
350
353
}
351
354
355
+ struct LuaStackIntegrityGuard {
356
+ name : & ' static str ,
357
+ }
358
+
359
+ impl LuaStackIntegrityGuard {
360
+ fn new ( name : & ' static str ) -> Self {
361
+ let mut lua: Lua = crate :: hlua:: global ( ) ;
362
+ let l = lua. as_mut_lua ( ) . state_ptr ( ) ;
363
+ unsafe { lua:: lua_pushlstring ( l, name. as_bytes ( ) . as_ptr ( ) as * mut i8 , name. len ( ) ) } ;
364
+ Self { name}
365
+ }
366
+ }
367
+
368
+ impl Drop for LuaStackIntegrityGuard {
369
+ fn drop ( & mut self ) {
370
+ let mut lua: Lua = crate :: hlua:: global ( ) ;
371
+ let l = lua. as_mut_lua ( ) . state_ptr ( ) ;
372
+
373
+ let msg = unsafe {
374
+ let cstr = lua:: lua_tostring ( l, -1 ) ;
375
+ if cstr. is_null ( ) {
376
+ panic ! ( "Lua stack integrity violation" ) ;
377
+ }
378
+ let msg = std:: ffi:: CStr :: from_ptr ( cstr) . to_str ( ) . unwrap ( ) ;
379
+ lua:: lua_pop ( l, 1 ) ;
380
+ msg
381
+ } ;
382
+
383
+ assert_eq ! ( msg, self . name) ;
384
+ }
385
+ }
386
+
352
387
pub fn immediate_yields ( ) {
388
+ let _guard = LuaStackIntegrityGuard :: new ( "immediate_fiber_guard" ) ;
389
+
353
390
let mut upvalue = 0 ;
354
391
let csw1 = fiber_csw ( ) ;
355
392
fiber:: start ( || upvalue = 69 ) ;
@@ -360,6 +397,8 @@ pub fn immediate_yields() {
360
397
}
361
398
362
399
pub fn deferred_doesnt_yield ( ) {
400
+ let _guard = LuaStackIntegrityGuard :: new ( "deferred_fiber_guard" ) ;
401
+
363
402
let mut upvalue = 0 ;
364
403
let csw1 = fiber_csw ( ) ;
365
404
fiber:: defer ( || upvalue = 96 ) ;
@@ -372,3 +411,78 @@ pub fn deferred_doesnt_yield() {
372
411
assert_eq ! ( upvalue, 96 ) ;
373
412
}
374
413
414
+ pub fn start_error ( ) {
415
+ let _guard = LuaStackIntegrityGuard :: new ( "fiber_error_guard" ) ;
416
+
417
+ let _spoiler = LuaContextSpoiler :: new ( ) ;
418
+
419
+ match fiber:: LuaFiber :: new ( fiber:: LuaFiberFunc ( || ( ) ) ) . spawn ( ) {
420
+ Err ( e) => assert_eq ! (
421
+ format!( "{}" , e) ,
422
+ "Lua error: Execution error: Artificial error"
423
+ ) ,
424
+ _ => panic ! ( ) ,
425
+ }
426
+
427
+ struct LuaContextSpoiler ;
428
+
429
+ impl LuaContextSpoiler {
430
+ fn new ( ) -> Self {
431
+ let mut lua: Lua = crate :: hlua:: global ( ) ;
432
+ lua. execute :: < ( ) > ( r#"
433
+ _fiber_new_backup = package.loaded.fiber.new
434
+ package.loaded.fiber.new = function() error("Artificial error", 0) end
435
+ "# ) . unwrap ( ) ;
436
+ Self
437
+ }
438
+ }
439
+
440
+ impl Drop for LuaContextSpoiler {
441
+ fn drop ( & mut self ) {
442
+ let mut lua: Lua = crate :: hlua:: global ( ) ;
443
+ lua. execute :: < ( ) > ( r#"
444
+ package.loaded.fiber.new = _fiber_new_backup
445
+ _fiber_new_backup = nil
446
+ "# ) . unwrap ( ) ;
447
+ }
448
+ }
449
+ }
450
+
451
+ pub fn require_error ( ) {
452
+ let _guard = LuaStackIntegrityGuard :: new ( "fiber_error_guard" ) ;
453
+
454
+ let _spoiler = LuaContextSpoiler :: new ( ) ;
455
+
456
+ match fiber:: LuaFiber :: new ( fiber:: LuaFiberFunc ( || ( ) ) ) . spawn ( ) {
457
+ Err ( e) => assert_eq ! (
458
+ format!( "{}" , e) ,
459
+ "Lua error: Execution error: Artificial require error"
460
+ ) ,
461
+ _ => panic ! ( ) ,
462
+ }
463
+
464
+ struct LuaContextSpoiler ;
465
+
466
+ impl LuaContextSpoiler {
467
+ fn new ( ) -> Self {
468
+ let mut lua: Lua = crate :: hlua:: global ( ) ;
469
+ lua. execute :: < ( ) > ( r#"
470
+ _fiber_backup = package.loaded.fiber
471
+ package.loaded.fiber = nil
472
+ package.preload.fiber = function() error("Artificial require error", 0) end
473
+ "# ) . unwrap ( ) ;
474
+ Self
475
+ }
476
+ }
477
+
478
+ impl Drop for LuaContextSpoiler {
479
+ fn drop ( & mut self ) {
480
+ let mut lua: Lua = crate :: hlua:: global ( ) ;
481
+ lua. execute :: < ( ) > ( r#"
482
+ package.preload.fiber = nil
483
+ package.loaded.fiber = _fiber_backup
484
+ _fiber_backup = nil
485
+ "# ) . unwrap ( ) ;
486
+ }
487
+ }
488
+ }
0 commit comments