Something went wrong. Try again.
Personal fork of prime agent. Mirror of: https://mnemosyne.sigilzero.dev/sigilzero/prime-agent
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582use mlua::{Error, Lua, ObjectLike, Result, Table, Value};
#[test]fn test_globals_set_get() -> Result<()> { let lua = Lua::new();
let globals = lua.globals(); globals.set("foo", "bar")?; globals.set("baz", "baf")?; assert_eq!(globals.get::<String>("foo")?, "bar"); assert_eq!(globals.get::<String>("baz")?, "baf");
lua.load(r#"assert(foo == "bar")"#).exec().unwrap();
Ok(())}
#[test]fn test_table() -> Result<()> { let lua = Lua::new();
let globals = lua.globals();
lua.load( r#" table1 = {1, 2, 3, 4, 5} table2 = {} table3 = {1, 2, nil, 4, 5} "#, ) .exec()?;
let table1 = globals.get::<Table>("table1")?; assert_eq!(table1.len()?, 5); assert!(!table1.is_empty()); assert_eq!( table1.pairs().collect::<Result<Vec<(i64, i64)>>>()?, vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] ); assert_eq!( table1.sequence_values().collect::<Result<Vec<i64>>>()?, vec![1, 2, 3, 4, 5] ); assert_eq!(table1, [1, 2, 3, 4, 5]); assert_eq!(table1, [1, 2, 3, 4, 5].as_slice());
let table2 = globals.get::<Table>("table2")?; assert_eq!(table2.len()?, 0); assert!(table2.is_empty()); assert_eq!(table2.pairs().collect::<Result<Vec<(i64, i64)>>>()?, vec![]); assert_eq!(table2, [0; 0]);
let table3 = globals.get::<Table>("table3")?; // sequence_values should only iterate until the first border assert_eq!(table3, [1, 2]); assert_eq!( table3.sequence_values().collect::<Result<Vec<i64>>>()?, vec![1, 2] );
Ok(())}
#[test]#[cfg(target_os = "linux")] // Linux allow overcommiting the memory (relevant for CI)fn test_table_with_large_capacity() { let lua = Lua::new();
let t = lua.create_table_with_capacity(1 << 26, 1 << 26); assert!(t.is_ok());}
#[test]fn test_table_push_pop() -> Result<()> { let lua = Lua::new();
// Test raw access let table1 = lua.create_sequence_from([123])?; table1.raw_push(321)?; assert_eq!(table1, [123, 321]); assert_eq!(table1.raw_pop::<i64>()?, 321); assert_eq!(table1.raw_pop::<i64>()?, 123); assert_eq!(table1.raw_pop::<Value>()?, Value::Nil); // An extra pop should do nothing assert_eq!(table1.raw_len(), 0); assert_eq!(table1, [0; 0]);
// Test access through metamethods let table2 = lua .load( r#" local proxy_table = {234} table2 = setmetatable({}, { __len = function() return #proxy_table end, __index = proxy_table, __newindex = proxy_table, }) return table2 "#, ) .eval::<Table>()?; table2.push(345)?; assert_eq!(table2.len()?, 2); assert_eq!( table2.sequence_values::<i64>().collect::<Result<Vec<_>>>()?, vec![] ); assert_eq!(table2.pop::<i64>()?, 345); assert_eq!(table2.pop::<i64>()?, 234); assert_eq!(table2.pop::<Value>()?, Value::Nil); assert_eq!(table2.len()?, 0);
Ok(())}
#[test]fn test_table_insert_remove() -> Result<()> { let lua = Lua::new();
let globals = lua.globals();
globals.set("table4", [1, 2, 3, 4, 5])?; let table4 = globals.get::<Table>("table4")?; assert_eq!( table4.pairs().collect::<Result<Vec<(i64, i64)>>>()?, vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] ); table4.raw_insert(4, 35)?; table4.raw_insert(7, 7)?; assert_eq!( table4.pairs().collect::<Result<Vec<(i64, i64)>>>()?, vec![(1, 1), (2, 2), (3, 3), (4, 35), (5, 4), (6, 5), (7, 7)] ); table4.raw_remove(1)?; assert_eq!( table4.pairs().collect::<Result<Vec<(i64, i64)>>>()?, vec![(1, 2), (2, 3), (3, 35), (4, 4), (5, 5), (6, 7)] );
// Wrong index, tables are 1-indexed assert!(table4.raw_insert(0, "123").is_err());
Ok(())}
#[test]fn test_table_clear() -> Result<()> { let lua = Lua::new();
let t = lua.create_table()?;
// Check readonly error #[cfg(feature = "luau")] { t.set_readonly(true); assert!(matches!( t.clear(), Err(Error::RuntimeError(err)) if err.contains("attempt to modify a readonly table") )); t.set_readonly(false); }
// Set array and hash parts t.push("abc")?; t.push("bcd")?; t.set("a", "1")?; t.set("b", "2")?; t.clear()?; assert_eq!(t.len()?, 0); assert_eq!(t.pairs::<Value, Value>().count(), 0);
// Test table with metamethods let t2 = lua .load( r#" setmetatable({1, 2, 3, a = "1"}, { __index = function() error("index error") end, __newindex = function() error("newindex error") end, __len = function() error("len error") end, __pairs = function() error("pairs error") end, }) "#, ) .eval::<Table>()?; assert_eq!(t2.raw_len(), 3); assert!(!t2.is_empty()); t2.clear()?; assert_eq!(t2.raw_len(), 0); assert!(t2.is_empty()); assert_eq!(t2.raw_get::<Value>("a")?, Value::Nil); assert_ne!(t2.metatable(), None);
Ok(())}
#[test]fn test_table_sequence_from() -> Result<()> { let lua = Lua::new();
let get_table = lua.create_function(|_, t: Table| Ok(t))?;
assert_eq!(get_table.call::<Table>(vec![1, 2, 3])?, [1, 2, 3]); assert_eq!(get_table.call::<Table>([4, 5, 6])?, [4, 5, 6]); assert_eq!(get_table.call::<Table>([7, 8, 9].as_slice())?, [7, 8, 9]);
Ok(())}
#[test]fn test_table_pairs() -> Result<()> { let lua = Lua::new();
let table = lua .load( r#" { foo = "bar", baz = "baf", [123] = 456, [789] = 101112, 5, } "#, ) .eval::<Table>()?;
for (i, kv) in table.pairs::<String, Value>().enumerate() { let (k, _v) = kv.unwrap(); match i { // Try to add a new key 0 => table.set("new_key", "new_value")?, // Try to delete the 2nd key 1 => { table.set(k, Value::Nil)?; lua.gc_collect()?; } _ => {} } }
Ok(())}
#[test]fn test_table_for_each() -> Result<()> { let lua = Lua::new();
let table = lua .load( r#" { foo = "bar", baz = "baf", [123] = 456, [789] = 101112, 5, } "#, ) .eval::<Table>()?;
let mut i = 0; table.for_each::<String, Value>(|k, _| { if i == 0 { // Delete first key table.set(k, Value::Nil)?; lua.gc_collect()?; } Ok(i += 1) })?; assert_eq!(i, 5);
Ok(())}
#[test]fn test_table_for_each_value() -> Result<()> { let lua = Lua::new();
let table = lua.load("{1, 2, 3, 4, 5, nil, 7}").eval::<Table>()?; let mut sum = 0; table.for_each_value::<i32>(|v| { sum += v; Ok(()) })?; // Iterations stops at the first nil assert_eq!(sum, 1 + 2 + 3 + 4 + 5);
Ok(())}
#[test]fn test_table_scope() -> Result<()> { let lua = Lua::new();
let globals = lua.globals(); lua.load( r#" touter = { tin = {1, 2, 3} } "#, ) .exec()?;
// Make sure that table gets do not borrow the table, but instead just borrow lua. let tin; { let touter = globals.get::<Table>("touter")?; tin = touter.get::<Table>("tin")?; }
assert_eq!(tin.get::<i64>(1)?, 1); assert_eq!(tin.get::<i64>(2)?, 2); assert_eq!(tin.get::<i64>(3)?, 3);
Ok(())}
#[test]fn test_metatable() -> Result<()> { let lua = Lua::new();
let table = lua.create_table()?; let metatable = lua.create_table()?; metatable.set("__index", lua.create_function(|_, ()| Ok("index_value"))?)?; table.set_metatable(Some(metatable))?; assert_eq!(table.get::<String>("any_key")?, "index_value"); assert_eq!(table.raw_get::<Value>("any_key")?, Value::Nil); table.set_metatable(None)?; assert_eq!(table.get::<Value>("any_key")?, Value::Nil);
Ok(())}
#[test]fn test_table_equals() -> Result<()> { let lua = Lua::new(); let globals = lua.globals();
lua.load( r#" table1 = {1} table2 = {1} table3 = table1 table4 = {1}
setmetatable(table4, { __eq = function(a, b) return a[1] == b[1] end }) "#, ) .exec()?;
let table1 = globals.get::<Table>("table1")?; let table2 = globals.get::<Table>("table2")?; let table3 = globals.get::<Table>("table3")?; let table4 = globals.get::<Table>("table4")?;
assert!(table1 != table2); assert!(!table1.equals(&table2)?); assert!(table1 == table3); assert!(table1.equals(&table3)?); assert!(table1 != table4); assert!(table1.equals(&table4)?);
Ok(())}
#[test]fn test_table_pointer() -> Result<()> { let lua = Lua::new();
let table1 = lua.create_table()?; let table2 = lua.create_table()?;
// Clone should not create a new table assert_eq!(table1.to_pointer(), table1.clone().to_pointer()); assert_ne!(table1.to_pointer(), table2.to_pointer());
Ok(())}
#[test]fn test_table_error() -> Result<()> { let lua = Lua::new();
let globals = lua.globals(); lua.load( r#" table = {} setmetatable(table, { __index = function() error("lua error") end, __newindex = function() error("lua error") end, __len = function() error("lua error") end }) "#, ) .exec()?;
let bad_table: Table = globals.get("table")?; assert!(bad_table.set(1, 1).is_err()); assert!(bad_table.get::<i32>(1).is_err()); assert!(bad_table.len().is_err()); assert!(bad_table.raw_set(1, 1).is_ok()); assert!(bad_table.raw_get::<i32>(1).is_ok()); assert_eq!(bad_table.raw_len(), 1);
Ok(())}
#[test]fn test_table_fmt() -> Result<()> { let lua = Lua::new();
let table = lua .load( r#" local t = {1, 2, 3, a = 5, b = { 6 }} t["special-<chars>"] = 10 t[9.2] = 9.2 t[1.99] = 1.99 t[true] = true t[false] = false return t "#, ) .eval::<Table>()?; assert!(format!("{table:?}").starts_with("Table(Ref("));
// Pretty print assert_eq!( format!("{table:#?}"), "{\n [false] = false,\n [true] = true,\n [1] = 1,\n [1.99] = 1.99,\n [2] = 2,\n [3] = 3,\n [9.2] = 9.2,\n a = 5,\n b = {\n 6,\n },\n [\"special-<chars>\"] = 10,\n}" );
let table2 = lua.create_table_from([("1", "first"), ("2", "second")])?; assert_eq!( format!("{table2:#?}"), "{\n [\"1\"] = \"first\",\n [\"2\"] = \"second\",\n}" );
Ok(())}
#[test]fn test_table_object_like() -> Result<()> { let lua = Lua::new();
lua.load( r#" table = {a = 1, b = 2} setmetatable(table, { __call = function(t, key) return "call_"..t[key] end,
__tostring = function() return "table object" end })
function table.func(key) return "func_"..key end
function table:method(key) return "method_"..self[key] end "#, ) .exec()?;
let table: Table = lua.globals().get("table")?;
<Table as ObjectLike>::set(&table, "c", 3)?; assert_eq!(<Table as ObjectLike>::get::<i32>(&table, "c")?, 3); assert_eq!(table.call::<String>("b")?, "call_2"); assert_eq!(table.call_function::<String>("func", "a")?, "func_a"); assert_eq!(table.call_method::<String>("method", "a")?, "method_1"); assert_eq!(table.to_string()?, "table object");
match table.call_method::<()>("non_existent", ()) { Err(Error::RuntimeError(err)) => { assert!(err.contains("attempt to call a nil value (function 'non_existent')")) } r => panic!("expected RuntimeError, got {r:?}"), }
// Test calling non-callable table let table2 = lua.create_table()?; assert!(matches!(table2.call::<()>(()), Err(Error::RuntimeError(_))));
Ok(())}
#[test]fn test_table_get_path() -> Result<()> { let lua = Lua::new();
// Create a nested table structure let table = lua .load( r#" { a = { b = { c = "hello", d = 42 }, [1] = "first", ["special key"] = "special value" }, abc = "top level", x = {}, ["🚀"] = "rocket", [1] = { ["nested-key"] = { [42] = { final = "hello!", }, }, ["key\"with\"quotes"] = "value1", ["key'with'quotes"] = "value2", ["key\\with\\backslashes"] = "value3", [-2] = "negative index", }, } "#, ) .eval::<Table>()?;
// Test basic dot notation assert_eq!(table.get_path::<String>(".a.b.c")?, "hello"); assert_eq!(table.get_path::<String>("a.b.c")?, "hello"); assert_eq!(table.get_path::<i32>("a.b.d")?, 42); assert_eq!(table.get_path::<String>("abc")?, "top level");
// Test bracket notation with integer keys assert_eq!(table.get_path::<String>("a[1]")?, "first"); assert_eq!(table.get_path::<String>("[1][-2]")?, "negative index");
// Test bracket notation with string keys assert_eq!(table.get_path::<String>("a[\"special key\"]")?, "special value"); assert_eq!(table.get_path::<String>("a['special key']")?, "special value"); assert_eq!(table.get_path::<String>(r#"[1]["key\"with\"quotes"]"#)?, "value1"); assert_eq!(table.get_path::<String>(r#"[1]['key"with"quotes']"#)?, "value1"); assert_eq!(table.get_path::<String>(r#"[1]['key\'with\'quotes']"#)?, "value2"); assert_eq!( table.get_path::<String>(r#"[1]["key\\with\\backslashes"]"#)?, "value3" );
// Test mixed notation assert_eq!(table.get_path::<String>("[1].nested-key[42].final")?, "hello!");
// Test unicode keys assert_eq!(table.get_path::<String>("🚀")?, "rocket");
// Test empty path returns the table itself assert_eq!(table.get_path::<Table>("")?, table);
// Test safe navigation assert_eq!(table.get_path::<String>("a?.b.c")?, "hello"); assert_eq!(table.get_path::<Value>("x.y?.z")?, Value::Nil); assert_eq!(table.get_path::<Value>("[1].nested-key[43]?.final")?, Value::Nil);
// Test path with whitespace assert_eq!(table.get_path::<String>(" .a [\"b\"] .c ")?, "hello");
// Test indexing non-indexable value let err = table.get_path::<String>("abc.c").unwrap_err().to_string(); assert_eq!(err, "runtime error: attempt to index a string value with key 'c'");
Ok(())}