Skip to content

Commit e09d688

Browse files
rosikgmoshkin
authored andcommitted
Enhance testing and fix bugs
1 parent 5d145bb commit e09d688

File tree

3 files changed

+128
-9
lines changed

3 files changed

+128
-9
lines changed

tarantool/src/fiber.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,22 +435,25 @@ where
435435
lua::lua_getglobal(l, c_ptr!("require"));
436436
lua::lua_pushstring(l, c_ptr!("fiber"));
437437
if lua::lua_pcall(l, 1, 1, 0) == lua::LUA_ERRRUN {
438-
return Err(impl_details::lua_error_from_top(l).into())
438+
let ret = Err(impl_details::lua_error_from_top(l).into());
439+
lua::lua_pop(l, 1);
440+
return ret
439441
};
440442
lua::lua_getfield(l, -1, c_ptr!("new"));
441443
hlua::push_some_userdata(l, callee.into_inner());
442444
lua::lua_pushcclosure(l, Self::trampoline, 1);
443445
if lua::lua_pcall(l, 1, 1, 0) == lua::LUA_ERRRUN {
444-
return Err(impl_details::lua_error_from_top(l).into())
446+
let ret = Err(impl_details::lua_error_from_top(l).into());
447+
lua::lua_pop(l, 2);
448+
return ret
445449
};
446450
lua::lua_getfield(l, -1, c_ptr!("set_joinable"));
447451
lua::lua_pushvalue(l, -2);
448452
lua::lua_pushboolean(l, true as i32);
449453
if lua::lua_pcall(l, 2, 0, 0) == lua::LUA_ERRRUN {
450-
return Err(impl_details::lua_error_from_top(l).into())
454+
panic!("{}", impl_details::lua_error_from_top(l))
451455
};
452456
let fiber_ref = lua::luaL_ref(l, lua::LUA_REGISTRYINDEX);
453-
454457
// pop the fiber module from the stack
455458
lua::lua_pop(l, 1);
456459

tests/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ fn run_tests(cfg: TestConfig) -> Result<bool, io::Error> {
286286
test_fiber::test_multiple_unit_deferred,
287287
test_fiber::deferred_doesnt_yield,
288288
test_fiber::immediate_yields,
289+
test_fiber::start_error,
290+
test_fiber::require_error,
289291

290292
test_box::test_space_get_by_name,
291293
test_box::test_space_get_system,

tests/src/test_fiber.rs

Lines changed: 119 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ use tarantool::fiber::{
88
self, fiber_yield, is_cancelled, sleep, Cond, Fiber, FiberAttr
99
};
1010
use tarantool::hlua::{
11+
AsMutLua,
1112
Lua,
1213
LuaFunction
1314
};
1415

16+
use tarantool::ffi::lua;
17+
1518
pub 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

335338
fn 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+
352387
pub 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

362399
pub 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

Comments
 (0)