@@ -8,10 +8,13 @@ use tarantool::fiber::{
88 self , fiber_yield, is_cancelled, sleep, Cond , Fiber , FiberAttr
99} ;
1010use tarantool:: hlua:: {
11+ AsMutLua ,
1112 Lua ,
1213 LuaFunction
1314} ;
1415
16+ use tarantool:: ffi:: lua;
17+
1518pub fn test_fiber_new ( ) {
1619 let mut fiber = Fiber :: new ( "test_fiber" , & mut |_| 0 ) ;
1720 fiber. set_joinable ( true ) ;
@@ -333,23 +336,57 @@ pub fn test_multiple_unit_deferred() {
333336}
334337
335338fn fiber_csw ( ) -> i32 {
336- static mut FLAG : bool = false ;
339+ static mut FUNCTION_DEFINED : bool = false ;
337340 let mut lua: Lua = crate :: hlua:: global ( ) ;
338341
339- if unsafe { !FLAG } {
342+ if unsafe { !FUNCTION_DEFINED } {
340343 lua. execute :: < ( ) > ( r#"
341344 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
344347 end
345348 "# ) . unwrap ( ) ;
346- unsafe { FLAG = true ; }
349+ unsafe { FUNCTION_DEFINED = true ; }
347350 }
348351
349352 return lua. get :: < LuaFunction < _ > , _ > ( "fiber_csw" ) . unwrap ( ) . call ( ) . unwrap ( ) ;
350353}
351354
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+
352387pub fn immediate_yields ( ) {
388+ let _guard = LuaStackIntegrityGuard :: new ( "immediate_fiber_guard" ) ;
389+
353390 let mut upvalue = 0 ;
354391 let csw1 = fiber_csw ( ) ;
355392 fiber:: start ( || upvalue = 69 ) ;
@@ -360,6 +397,8 @@ pub fn immediate_yields() {
360397}
361398
362399pub fn deferred_doesnt_yield ( ) {
400+ let _guard = LuaStackIntegrityGuard :: new ( "deferred_fiber_guard" ) ;
401+
363402 let mut upvalue = 0 ;
364403 let csw1 = fiber_csw ( ) ;
365404 fiber:: defer ( || upvalue = 96 ) ;
@@ -372,3 +411,78 @@ pub fn deferred_doesnt_yield() {
372411 assert_eq ! ( upvalue, 96 ) ;
373412}
374413
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