lua_test.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. package lua
  2. import (
  3. "testing"
  4. "unsafe"
  5. )
  6. type TestStruct struct {
  7. IntField int
  8. StringField string
  9. FloatField float64
  10. }
  11. func TestGoStruct(t *testing.T) {
  12. L := NewState()
  13. L.OpenLibs()
  14. defer L.Close()
  15. ts := &TestStruct{10, "test", 2.3}
  16. L.CheckStack(1)
  17. L.PushGoStruct(ts)
  18. L.SetGlobal("t")
  19. L.GetGlobal("t")
  20. if !L.IsGoStruct(-1) {
  21. t.Fatal("Not go struct")
  22. }
  23. tsr := L.ToGoStruct(-1).(*TestStruct)
  24. if tsr != ts {
  25. t.Fatal("Retrieved something different from what we inserted")
  26. }
  27. L.Pop(1)
  28. L.PushString("This is not a struct")
  29. if L.ToGoStruct(-1) != nil {
  30. t.Fatal("Non-GoStruct value attempted to convert into GoStruct should result in nil")
  31. }
  32. L.Pop(1)
  33. }
  34. func TestCheckStringSuccess(t *testing.T) {
  35. L := NewState()
  36. L.OpenLibs()
  37. defer L.Close()
  38. Test := func(L *State) int {
  39. L.PushString("this is a test")
  40. L.CheckString(-1)
  41. return 0
  42. }
  43. L.Register("test", Test)
  44. err := L.DoString("test()")
  45. if err != nil {
  46. t.Fatalf("DoString did return an error: %v\n", err.Error())
  47. }
  48. }
  49. func TestCheckStringFail(t *testing.T) {
  50. L := NewState()
  51. L.OpenLibs()
  52. defer L.Close()
  53. Test := func(L *State) int {
  54. L.CheckString(-1)
  55. return 0
  56. }
  57. L.Register("test", Test)
  58. err := L.DoString("test();")
  59. if err == nil {
  60. t.Fatal("DoString did not return an error\n")
  61. }
  62. }
  63. func TestPCallHidden(t *testing.T) {
  64. L := NewState()
  65. L.OpenLibs()
  66. defer L.Close()
  67. err := L.DoString("pcall(print, \"ciao\")")
  68. if err == nil {
  69. t.Fatal("Can use pcall\n")
  70. }
  71. err = L.DoString("unsafe_pcall(print, \"ciao\")")
  72. if err != nil {
  73. t.Fatal("Can not use unsafe_pcall\n")
  74. }
  75. }
  76. func TestCall(t *testing.T) {
  77. L := NewState()
  78. L.OpenLibs()
  79. defer L.Close()
  80. test := func(L *State) int {
  81. arg1 := L.ToString(1)
  82. arg2 := L.ToString(2)
  83. arg3 := L.ToString(3)
  84. if arg1 != "Argument1" {
  85. t.Fatal("Got wrong argument (1)")
  86. }
  87. if arg2 != "Argument2" {
  88. t.Fatal("Got wrong argument (2)")
  89. }
  90. if arg3 != "Argument3" {
  91. t.Fatal("Got wrong argument (3)")
  92. }
  93. L.PushString("Return1")
  94. L.PushString("Return2")
  95. return 2
  96. }
  97. L.Register("test", test)
  98. L.PushString("Dummy")
  99. L.GetGlobal("test")
  100. L.PushString("Argument1")
  101. L.PushString("Argument2")
  102. L.PushString("Argument3")
  103. err := L.Call(3, 2)
  104. if err != nil {
  105. t.Fatalf("Error executing call: %v\n", err)
  106. }
  107. dummy := L.ToString(1)
  108. ret1 := L.ToString(2)
  109. ret2 := L.ToString(3)
  110. if dummy != "Dummy" {
  111. t.Fatal("The stack was disturbed")
  112. }
  113. if ret1 != "Return1" {
  114. t.Fatalf("Wrong return value (1) got: <%s>", ret1)
  115. }
  116. if ret2 != "Return2" {
  117. t.Fatalf("Wrong return value (2) got: <%s>", ret2)
  118. }
  119. }
  120. // equivalent to basic.go
  121. func TestLikeBasic(t *testing.T) {
  122. L := NewState()
  123. defer L.Close()
  124. L.OpenLibs()
  125. testCalled := 0
  126. test := func(L *State) int {
  127. testCalled++
  128. return 0
  129. }
  130. test2Arg := -1
  131. test2Argfrombottom := -1
  132. test2 := func(L *State) int {
  133. test2Arg = L.CheckInteger(-1)
  134. test2Argfrombottom = L.CheckInteger(1)
  135. return 0
  136. }
  137. L.GetGlobal("print")
  138. L.PushString("Hello World!")
  139. if err := L.Call(1, 0); err != nil {
  140. t.Fatalf("Call to print returned error")
  141. }
  142. L.PushGoFunction(test)
  143. L.PushGoFunction(test)
  144. L.PushGoFunction(test)
  145. L.PushGoFunction(test2)
  146. L.PushInteger(42)
  147. if err := L.Call(1, 0); err != nil {
  148. t.Fatalf("Call to print returned error")
  149. }
  150. if (test2Arg != 42) || (test2Argfrombottom != 42) {
  151. t.Fatalf("Call to test2 didn't work")
  152. }
  153. if err := L.Call(0, 0); err != nil {
  154. t.Fatalf("Call to print returned error")
  155. }
  156. if err := L.Call(0, 0); err != nil {
  157. t.Fatalf("Call to print returned error")
  158. }
  159. if err := L.Call(0, 0); err != nil {
  160. t.Fatalf("Call to print returned error")
  161. }
  162. if testCalled != 3 {
  163. t.Fatalf("Test function not called the correct number of times: %d\n", testCalled)
  164. }
  165. // this will fail as we didn't register test2 function
  166. if err := L.DoString("test2(42)"); err == nil {
  167. t.Fatal("No error when calling unregistered function")
  168. }
  169. }
  170. // equivalent to quickstart.go
  171. func TestLikeQuickstart(t *testing.T) {
  172. adder := func(L *State) int {
  173. a := L.ToInteger(1)
  174. b := L.ToInteger(2)
  175. L.PushInteger(int64(a + b))
  176. return 1
  177. }
  178. L := NewState()
  179. defer L.Close()
  180. L.OpenLibs()
  181. L.Register("adder", adder)
  182. if err := L.DoString("return adder(2, 2)"); err != nil {
  183. t.Fatalf("Error during call to adder: %v\n", err)
  184. }
  185. if r := L.ToInteger(1); r != 4 {
  186. t.Fatalf("Wrong return value from adder (was: %d)\n", r)
  187. }
  188. }
  189. // equivalent to userdata.go
  190. func TestLikeUserdata(t *testing.T) {
  191. type Userdata struct {
  192. a, b int
  193. }
  194. userDataProper := func(L *State) {
  195. rawptr := L.NewUserdata(uintptr(unsafe.Sizeof(Userdata{})))
  196. var ptr *Userdata
  197. ptr = (*Userdata)(rawptr)
  198. ptr.a = 2
  199. ptr.b = 3
  200. rawptr2 := L.ToUserdata(-1)
  201. ptr2 := (*Userdata)(rawptr2)
  202. if ptr != ptr2 {
  203. t.Fatalf("Failed to create userdata\n")
  204. }
  205. }
  206. testCalled := 0
  207. test := func(L *State) int {
  208. testCalled++
  209. return 0
  210. }
  211. goDefinedFunctions := func(L *State) {
  212. // example_function is registered inside Lua VM
  213. L.Register("test", test)
  214. // This code demonstrates checking that a value on the stack is a go function
  215. L.CheckStack(1)
  216. L.GetGlobal("test")
  217. if !L.IsGoFunction(-1) {
  218. t.Fatalf("IsGoFunction failed to recognize a Go function object")
  219. }
  220. L.Pop(1)
  221. // We call example_function from inside Lua VM
  222. testCalled = 0
  223. if err := L.DoString("test()"); err != nil {
  224. t.Fatalf("Error executing test function: %v\n", err)
  225. }
  226. if testCalled != 1 {
  227. t.Fatalf("It appears the test function wasn't actually called\n")
  228. }
  229. }
  230. type TestObject struct {
  231. AField int
  232. }
  233. goDefinedObjects := func(L *State) {
  234. z := &TestObject{42}
  235. L.PushGoStruct(z)
  236. L.SetGlobal("z")
  237. // This code demonstrates checking that a value on the stack is a go object
  238. L.CheckStack(1)
  239. L.GetGlobal("z")
  240. if !L.IsGoStruct(-1) {
  241. t.Fatal("IsGoStruct failed to recognize a Go struct\n")
  242. }
  243. L.Pop(1)
  244. // This code demonstrates access and assignment to a field of a go object
  245. if err := L.DoString("return z.AField"); err != nil {
  246. t.Fatal("Couldn't execute code")
  247. }
  248. before := L.ToInteger(-1)
  249. L.Pop(1)
  250. if before != 42 {
  251. t.Fatalf("Wrong value of z.AField before change (%d)\n", before)
  252. }
  253. if err := L.DoString("z.AField = 10;"); err != nil {
  254. t.Fatal("Couldn't execute code")
  255. }
  256. if err := L.DoString("return z.AField"); err != nil {
  257. t.Fatal("Couldn't execute code")
  258. }
  259. after := L.ToInteger(-1)
  260. L.Pop(1)
  261. if after != 10 {
  262. t.Fatalf("Wrong value of z.AField after change (%d)\n", after)
  263. }
  264. }
  265. L := NewState()
  266. defer L.Close()
  267. L.OpenLibs()
  268. userDataProper(L)
  269. goDefinedFunctions(L)
  270. goDefinedObjects(L)
  271. }
  272. func TestStackTrace(t *testing.T) {
  273. L := NewState()
  274. defer L.Close()
  275. L.OpenLibs()
  276. err := L.DoFile("../_example/calls.lua")
  277. if err == nil {
  278. t.Fatal("No error returned from the execution of calls.lua")
  279. }
  280. le := err.(*LuaError)
  281. if le.Code() != LUA_ERRERR {
  282. t.Fatalf("Wrong kind of error encountered running calls.lua: %v (%d %d)\n", le, le.Code(), LUA_ERRERR)
  283. }
  284. if len(le.StackTrace()) != 6 {
  285. t.Fatalf("Wrong size of stack trace (%v)\n", le.StackTrace())
  286. }
  287. }
  288. func TestConv(t *testing.T) {
  289. L := NewState()
  290. defer L.Close()
  291. L.OpenLibs()
  292. L.PushString("10")
  293. n := L.ToNumber(-1)
  294. if n != 10 {
  295. t.Fatalf("Wrong conversion (str -> int)")
  296. }
  297. if L.Type(-1) != LUA_TSTRING {
  298. t.Fatalf("Wrong type (str)")
  299. }
  300. L.Pop(1)
  301. L.PushInteger(10)
  302. s := L.ToString(-1)
  303. if s != "10" {
  304. t.Fatalf("Wrong conversion (int -> str)")
  305. }
  306. L.Pop(1)
  307. L.PushString("a\000test")
  308. s = L.ToString(-1)
  309. if s != "a\000test" {
  310. t.Fatalf("Wrong conversion (str -> str): <%s>", s)
  311. }
  312. }
  313. func TestDumpAndLoad(t *testing.T) {
  314. L := NewState()
  315. defer L.Close()
  316. L.OpenLibs()
  317. loadret := L.LoadString(`print("msg from dump_and_load_test")`)
  318. if loadret != 0 {
  319. t.Fatalf("LoadString error: %v", loadret)
  320. }
  321. dumpret := L.Dump()
  322. if dumpret != 0 {
  323. t.Fatalf("Dump error: %v", dumpret)
  324. }
  325. isstring := L.IsString(-1)
  326. if !isstring {
  327. t.Fatalf("stack top not a string")
  328. }
  329. bytecodes := L.ToBytes(-1)
  330. loadret = L.Load(bytecodes, "chunk_from_dump_and_load_test")
  331. if loadret != 0 {
  332. t.Fatalf("Load error: %v", loadret)
  333. }
  334. err := L.Call(0, 0)
  335. if err != nil {
  336. t.Fatalf("Call error: %v", err)
  337. }
  338. }
  339. func TestCustomDebugHook(t *testing.T) {
  340. L := NewState()
  341. defer L.Close()
  342. L.SetHook(func(l *State) {
  343. l.RaiseError("stop")
  344. }, 1)
  345. err := L.DoString(`
  346. local x = 0
  347. while(1 ~= 0) do
  348. x = 2
  349. end
  350. `)
  351. if err == nil {
  352. t.Fatalf("Script should have raised an error")
  353. } else {
  354. if err.Error() != "stop" {
  355. t.Fatal("Error should be coming from the hook")
  356. }
  357. }
  358. }