LuaApiTests.cs 8.8 KB

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