LuaApiTests.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. using Lua.Runtime;
  2. using Lua.Standard;
  3. namespace Lua.Tests;
  4. public class LuaApiTests
  5. {
  6. LuaState state = default!;
  7. [OneTimeSetUp]
  8. public void SetUp()
  9. {
  10. state = LuaState.Create();
  11. state.OpenStandardLibraries();
  12. }
  13. [Test]
  14. public async Task TestArithmetic()
  15. {
  16. var source = """
  17. metatable = {
  18. __add = function(a, b)
  19. local t = { }
  20. for i = 1, #a do
  21. t[i] = a[i] + b[i]
  22. end
  23. return t
  24. end
  25. }
  26. local a = { 1, 2, 3 }
  27. local b = { 4, 5, 6 }
  28. setmetatable(a, metatable)
  29. return a, b
  30. """;
  31. var access = state.TopLevelAccess;
  32. var result = await access.DoStringAsync(source);
  33. var a = result[0].Read<LuaTable>();
  34. var b = result[1].Read<LuaTable>();
  35. var c = await access.Arithmetic(a, b, OpCode.Add);
  36. var table = c.Read<LuaTable>();
  37. Assert.Multiple(() =>
  38. {
  39. Assert.That(table[1].Read<double>(), Is.EqualTo(5));
  40. Assert.That(table[2].Read<double>(), Is.EqualTo(7));
  41. Assert.That(table[3].Read<double>(), Is.EqualTo(9));
  42. });
  43. }
  44. [Test]
  45. public async Task TestUnary()
  46. {
  47. var source = """
  48. metatable = {
  49. __unm = function(a)
  50. local t = { }
  51. for i = 1, #a do
  52. t[i] = -a[i]
  53. end
  54. return t
  55. end
  56. }
  57. local a = { 1, 2, 3 }
  58. setmetatable(a, metatable)
  59. return a
  60. """;
  61. var access = state.TopLevelAccess;
  62. var result = await access.DoStringAsync(source);
  63. var a = result[0].Read<LuaTable>();
  64. var c = await access.Unary(a, OpCode.Unm);
  65. var table = c.Read<LuaTable>();
  66. Assert.Multiple(() =>
  67. {
  68. Assert.That(table[1].Read<double>(), Is.EqualTo(-1));
  69. Assert.That(table[2].Read<double>(), Is.EqualTo(-2));
  70. Assert.That(table[3].Read<double>(), Is.EqualTo(-3));
  71. });
  72. }
  73. [Test]
  74. public async Task TestCompare()
  75. {
  76. var source = """
  77. metatable = {
  78. __eq = function(a, b)
  79. if(#a ~= #b) then
  80. return false
  81. end
  82. for i = 1, #a do
  83. if(a[i] ~= b[i]) then
  84. return false
  85. end
  86. end
  87. return true
  88. end
  89. }
  90. local a = { 1, 2, 3 }
  91. local b = { 4, 5, 6 }
  92. local c = { 1, 2, 3 }
  93. setmetatable(a, metatable)
  94. return a, b, c
  95. """;
  96. var access = state.TopLevelAccess;
  97. var result = await access.DoStringAsync(source);
  98. var a = result[0].Read<LuaTable>();
  99. var b = result[1].Read<LuaTable>();
  100. var c = result[2].Read<LuaTable>();
  101. var ab = await access.Compare(a, b, OpCode.Eq);
  102. Assert.False(ab);
  103. var ac = await access.Compare(a, c, OpCode.Eq);
  104. Assert.True(ac);
  105. }
  106. [Test]
  107. public async Task TestGetTable()
  108. {
  109. var source = """
  110. metatable = {
  111. __index = {x=1}
  112. }
  113. local a = {}
  114. setmetatable(a, metatable)
  115. return a
  116. """;
  117. var access = state.TopLevelAccess;
  118. var result = await access.DoStringAsync(source);
  119. var a = result[0].Read<LuaTable>();
  120. Assert.That(await access.GetTable(a, "x"), Is.EqualTo(new LuaValue(1)));
  121. a.Metatable!["__index"] = state.DoStringAsync("return function(a,b) return b end").Result[0];
  122. Assert.That(await access.GetTable(a, "x"), Is.EqualTo(new LuaValue("x")));
  123. }
  124. [Test]
  125. public async Task TestSetTable()
  126. {
  127. var source = """
  128. metatable = {
  129. __newindex = {}
  130. }
  131. local a = {}
  132. a.x = 1
  133. setmetatable(a, metatable)
  134. return a
  135. """;
  136. var access = state.TopLevelAccess;
  137. var result = await access.DoStringAsync(source);
  138. var a = result[0].Read<LuaTable>();
  139. await access.SetTable(a, "a", "b");
  140. var b = a.Metatable!["__newindex"].Read<LuaTable>()["a"];
  141. Assert.True(b.Read<string>() == "b");
  142. }
  143. [Test]
  144. public async Task Test_Metamethod_Concat()
  145. {
  146. var source = @"
  147. metatable = {
  148. __concat = function(a, b)
  149. local t = { }
  150. for i = 1, #a do
  151. table.insert(t, a[i])
  152. end
  153. for i = 1, #b do
  154. table.insert(t, b[i])
  155. end
  156. return t
  157. end
  158. }
  159. local a = { 1, 2, 3 }
  160. local b = { 4, 5, 6 }
  161. local c = { 7, 8, 9 }
  162. setmetatable(a, metatable)
  163. setmetatable(c, metatable)
  164. return a,b,c
  165. ";
  166. var access = state.TopLevelAccess;
  167. var result = await access.DoStringAsync(source);
  168. Assert.That(result, Has.Length.EqualTo(3));
  169. var a = result[0];
  170. var b = result[1];
  171. var c = result[2];
  172. var d = await access.Concat([a, b, c]);
  173. var table = d.Read<LuaTable>();
  174. Assert.That(table.ArrayLength, Is.EqualTo(9));
  175. Assert.Multiple(() =>
  176. {
  177. Assert.That(table[1].Read<double>(), Is.EqualTo(1));
  178. Assert.That(table[2].Read<double>(), Is.EqualTo(2));
  179. Assert.That(table[3].Read<double>(), Is.EqualTo(3));
  180. Assert.That(table[4].Read<double>(), Is.EqualTo(4));
  181. Assert.That(table[5].Read<double>(), Is.EqualTo(5));
  182. Assert.That(table[6].Read<double>(), Is.EqualTo(6));
  183. Assert.That(table[7].Read<double>(), Is.EqualTo(7));
  184. Assert.That(table[8].Read<double>(), Is.EqualTo(8));
  185. Assert.That(table[9].Read<double>(), Is.EqualTo(9));
  186. });
  187. }
  188. [Test]
  189. public async Task Test_Metamethod_MetaCallViaMeta()
  190. {
  191. var source = """
  192. local a = {name ="a"}
  193. setmetatable(a, {
  194. __call = function(a, b, c)
  195. return a.name..b.name..c.name
  196. end
  197. })
  198. local b = setmetatable({name="b"},
  199. {__unm = a,
  200. __add= a,
  201. __concat =a
  202. })
  203. local c ={name ="c"}
  204. return a,b,c
  205. """;
  206. var access = state.TopLevelAccess;
  207. var result = await access.DoStringAsync(source);
  208. var a = result[0];
  209. var b = result[1];
  210. var c = result[2];
  211. var d = await access.Arithmetic(b, c, OpCode.Add);
  212. Assert.True(d.TryRead(out string s));
  213. Assert.That(s, Is.EqualTo("abc"));
  214. d = await access.Unary(b, OpCode.Unm);
  215. Assert.True(d.TryRead(out s));
  216. Assert.That(s, Is.EqualTo("abb"));
  217. d = await access.Concat([c, b]);
  218. Assert.True(d.TryRead(out s));
  219. Assert.That(s, Is.EqualTo("acb"));
  220. var aResult = await access.Call(a, [b, c]);
  221. Assert.That(aResult, Has.Length.EqualTo(1));
  222. Assert.That(aResult[0].Read<string>(), Is.EqualTo("abc"));
  223. }
  224. [Test]
  225. public async Task Test_Metamethod_MetaCallViaMeta_VarArg()
  226. {
  227. var source = """
  228. local a = {name ="a"}
  229. setmetatable(a, {
  230. __call = function(a, ...)
  231. local args = {...}
  232. local b,c =args[1],args[2]
  233. return a.name..b.name..c.name
  234. end
  235. })
  236. local b = setmetatable({name="b"},
  237. {__unm = a,
  238. __add= a,
  239. __concat =a
  240. })
  241. local c ={name ="c"}
  242. return a,b,c
  243. """;
  244. var access = state.TopLevelAccess;
  245. var result = await access.DoStringAsync(source);
  246. var a = result[0];
  247. var b = result[1];
  248. var c = result[2];
  249. var d = await access.Arithmetic(b, c, OpCode.Add);
  250. Assert.True(d.TryRead(out string s));
  251. Assert.That(s, Is.EqualTo("abc"));
  252. d = await access.Unary(b, OpCode.Unm);
  253. Assert.True(d.TryRead(out s));
  254. Assert.That(s, Is.EqualTo("abb"));
  255. d = await access.Concat([c, b]);
  256. Assert.True(d.TryRead(out s));
  257. Assert.That(s, Is.EqualTo("acb"));
  258. var aResult = await access.Call(a, [b, c]);
  259. Assert.That(aResult, Has.Length.EqualTo(1));
  260. Assert.That(aResult[0].Read<string>(), Is.EqualTo("abc"));
  261. }
  262. }