MetatableTests.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using Lua.Standard;
  2. namespace Lua.Tests;
  3. public class MetatableTests
  4. {
  5. LuaState state = default!;
  6. [OneTimeSetUp]
  7. public void SetUp()
  8. {
  9. state = LuaState.Create();
  10. state.OpenStandardLibraries();
  11. }
  12. [Test]
  13. public async Task Test_Metamethod_Add()
  14. {
  15. var source = @"
  16. metatable = {
  17. __add = function(a, b)
  18. local t = { }
  19. for i = 1, #a do
  20. t[i] = a[i] + b[i]
  21. end
  22. return t
  23. end
  24. }
  25. local a = { 1, 2, 3 }
  26. local b = { 4, 5, 6 }
  27. setmetatable(a, metatable)
  28. return a + b
  29. ";
  30. var result = await state.DoStringAsync(source);
  31. Assert.That(result, Has.Length.EqualTo(1));
  32. var table = result[0].Read<LuaTable>();
  33. Assert.Multiple(() =>
  34. {
  35. Assert.That(table[1].Read<double>(), Is.EqualTo(5));
  36. Assert.That(table[2].Read<double>(), Is.EqualTo(7));
  37. Assert.That(table[3].Read<double>(), Is.EqualTo(9));
  38. });
  39. }
  40. [Test]
  41. public async Task Test_Metamethod_Index()
  42. {
  43. var source = @"
  44. metatable = {
  45. __index = {x=1}
  46. }
  47. local a = {}
  48. setmetatable(a, metatable)
  49. assert(a.x == 1)
  50. metatable.__index= nil
  51. assert(a.x == nil)
  52. metatable.__index= function(a,b) return b end
  53. assert(a.x == 'x')
  54. ";
  55. await state.DoStringAsync(source);
  56. }
  57. [Test]
  58. public async Task Test_Metamethod_NewIndex()
  59. {
  60. var source = @"
  61. metatable = {
  62. __newindex = {}
  63. }
  64. local a = {}
  65. a.x = 1
  66. setmetatable(a, metatable)
  67. a.x = 2
  68. assert(a.x == 2)
  69. a.x = nil
  70. a.x = 2
  71. assert(a.x == nil)
  72. assert(metatable.__newindex.x == 2)
  73. ";
  74. await state.DoStringAsync(source);
  75. }
  76. [Test]
  77. public async Task Test_Metamethod_Call()
  78. {
  79. var source = @"
  80. metatable = {
  81. __call = function(a, b)
  82. return a.x + b
  83. end
  84. }
  85. local a = {}
  86. a.x = 1
  87. setmetatable(a, metatable)
  88. assert(a(2) == 3)
  89. function tail(a, b)
  90. return a(b)
  91. end
  92. tail(a, 3)
  93. assert(tail(a, 3) == 4)
  94. ";
  95. await state.DoStringAsync(source);
  96. }
  97. [Test]
  98. public async Task Test_Metamethod_TForCall()
  99. {
  100. var source = @"
  101. local i =3
  102. function a(...)
  103. local v ={...}
  104. assert(v[1] ==t)
  105. assert(v[2] == nil)
  106. if i ==3 then
  107. assert(v[3] == nil)
  108. else
  109. assert(v[3] == i)
  110. end
  111. i =i -1
  112. if i ==0 then return nil end
  113. return i
  114. end
  115. t =setmetatable({},{__call = a})
  116. for i in t do
  117. end
  118. ";
  119. await state.DoStringAsync(source);
  120. }
  121. [Test]
  122. public async Task Test_Hook_Metamethods()
  123. {
  124. var source = """
  125. local t = {}
  126. local a =setmetatable({},{__add =function (a,b) return a end})
  127. debug.sethook(function () table.insert(t,debug.traceback()) end,"c")
  128. a =a+a
  129. return t
  130. """;
  131. var r = await state.DoStringAsync(source);
  132. Assert.That(r, Has.Length.EqualTo(1));
  133. Assert.That(r[0].Read<LuaTable>()[1].Read<string>(), Does.Contain("stack traceback:"));
  134. }
  135. }