github.com/hootrhino/gopher-lua@v1.0.3/_lua5.1-tests/api.lua (about)

     1  
     2  if T==nil then
     3    (Message or print)('\a\n >>> testC not active: skipping API tests <<<\n\a')
     4    return
     5  end
     6  
     7  
     8  
     9  function tcheck (t1, t2)
    10    table.remove(t1, 1)  -- remove code
    11    assert(table.getn(t1) == table.getn(t2))
    12    for i=1,table.getn(t1) do assert(t1[i] == t2[i]) end
    13  end
    14  
    15  function pack(...) return arg end
    16  
    17  
    18  print('testing C API')
    19  
    20  -- testing allignment
    21  a = T.d2s(12458954321123)
    22  assert(string.len(a) == 8)   -- sizeof(double)
    23  assert(T.s2d(a) == 12458954321123)
    24  
    25  a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2")
    26  assert(a == 2 and b == 3 and not c)
    27  
    28  -- test that all trues are equal
    29  a,b,c = T.testC("pushbool 1; pushbool 2; pushbool 0; return 3")
    30  assert(a == b and a == true and c == false)
    31  a,b,c = T.testC"pushbool 0; pushbool 10; pushnil;\
    32                        tobool -3; tobool -3; tobool -3; return 3"
    33  assert(a==0 and b==1 and c==0)
    34  
    35  
    36  a,b,c = T.testC("gettop; return 2", 10, 20, 30, 40)
    37  assert(a == 40 and b == 5 and not c)
    38  
    39  t = pack(T.testC("settop 5; gettop; return .", 2, 3))
    40  tcheck(t, {n=4,2,3})
    41  
    42  t = pack(T.testC("settop 0; settop 15; return 10", 3, 1, 23))
    43  assert(t.n == 10 and t[1] == nil and t[10] == nil)
    44  
    45  t = pack(T.testC("remove -2; gettop; return .", 2, 3, 4))
    46  tcheck(t, {n=2,2,4})
    47  
    48  t = pack(T.testC("insert -1; gettop; return .", 2, 3))
    49  tcheck(t, {n=2,2,3})
    50  
    51  t = pack(T.testC("insert 3; gettop; return .", 2, 3, 4, 5))
    52  tcheck(t, {n=4,2,5,3,4})
    53  
    54  t = pack(T.testC("replace 2; gettop; return .", 2, 3, 4, 5))
    55  tcheck(t, {n=3,5,3,4})
    56  
    57  t = pack(T.testC("replace -2; gettop; return .", 2, 3, 4, 5))
    58  tcheck(t, {n=3,2,3,5})
    59  
    60  t = pack(T.testC("remove 3; gettop; return .", 2, 3, 4, 5))
    61  tcheck(t, {n=3,2,4,5})
    62  
    63  t = pack(T.testC("insert 3; pushvalue 3; remove 3; pushvalue 2; remove 2; \
    64                    insert 2; pushvalue 1; remove 1; insert 1; \
    65        insert -2; pushvalue -2; remove -3; gettop; return .",
    66        2, 3, 4, 5, 10, 40, 90))
    67  tcheck(t, {n=7,2,3,4,5,10,40,90})
    68  
    69  t = pack(T.testC("concat 5; gettop; return .", "alo", 2, 3, "joao", 12))
    70  tcheck(t, {n=1,"alo23joao12"})
    71  
    72  -- testing MULTRET
    73  t = pack(T.testC("rawcall 2,-1; gettop; return .",
    74       function (a,b) return 1,2,3,4,a,b end, "alo", "joao"))
    75  tcheck(t, {n=6,1,2,3,4,"alo", "joao"})
    76  
    77  do  -- test returning more results than fit in the caller stack
    78    local a = {}
    79    for i=1,1000 do a[i] = true end; a[999] = 10
    80    local b = T.testC([[call 1 -1; pop 1; tostring -1; return 1]], unpack, a)
    81    assert(b == "10")
    82  end
    83  
    84  
    85  -- testing lessthan
    86  assert(T.testC("lessthan 2 5, return 1", 3, 2, 2, 4, 2, 2))
    87  assert(T.testC("lessthan 5 2, return 1", 4, 2, 2, 3, 2, 2))
    88  assert(not T.testC("lessthan 2 -3, return 1", "4", "2", "2", "3", "2", "2"))
    89  assert(not T.testC("lessthan -3 2, return 1", "3", "2", "2", "4", "2", "2"))
    90  
    91  local b = {__lt = function (a,b) return a[1] < b[1] end}
    92  local a1,a3,a4 = setmetatable({1}, b),
    93                   setmetatable({3}, b),
    94                   setmetatable({4}, b)
    95  assert(T.testC("lessthan 2 5, return 1", a3, 2, 2, a4, 2, 2))
    96  assert(T.testC("lessthan 5 -6, return 1", a4, 2, 2, a3, 2, 2))
    97  a,b = T.testC("lessthan 5 -6, return 2", a1, 2, 2, a3, 2, 20)
    98  assert(a == 20 and b == false)
    99  
   100  
   101  -- testing lua_is
   102  
   103  function count (x, n)
   104    n = n or 2
   105    local prog = [[
   106      isnumber %d;
   107      isstring %d;
   108      isfunction %d;
   109      iscfunction %d;
   110      istable %d;
   111      isuserdata %d;
   112      isnil %d;
   113      isnull %d;
   114      return 8
   115    ]]
   116    prog = string.format(prog, n, n, n, n, n, n, n, n)
   117    local a,b,c,d,e,f,g,h = T.testC(prog, x)
   118    return a+b+c+d+e+f+g+(100*h)
   119  end
   120  
   121  assert(count(3) == 2)
   122  assert(count('alo') == 1)
   123  assert(count('32') == 2)
   124  assert(count({}) == 1)
   125  assert(count(print) == 2)
   126  assert(count(function () end) == 1)
   127  assert(count(nil) == 1)
   128  assert(count(io.stdin) == 1)
   129  assert(count(nil, 15) == 100)
   130  
   131  -- testing lua_to...
   132  
   133  function to (s, x, n)
   134    n = n or 2
   135    return T.testC(string.format("%s %d; return 1", s, n), x)
   136  end
   137  
   138  assert(to("tostring", {}) == nil)
   139  assert(to("tostring", "alo") == "alo")
   140  assert(to("tostring", 12) == "12")
   141  assert(to("tostring", 12, 3) == nil)
   142  assert(to("objsize", {}) == 0)
   143  assert(to("objsize", "alo\0\0a") == 6)
   144  assert(to("objsize", T.newuserdata(0)) == 0)
   145  assert(to("objsize", T.newuserdata(101)) == 101)
   146  assert(to("objsize", 12) == 2)
   147  assert(to("objsize", 12, 3) == 0)
   148  assert(to("tonumber", {}) == 0)
   149  assert(to("tonumber", "12") == 12)
   150  assert(to("tonumber", "s2") == 0)
   151  assert(to("tonumber", 1, 20) == 0)
   152  a = to("tocfunction", math.deg)
   153  assert(a(3) == math.deg(3) and a ~= math.deg)
   154  
   155  
   156  -- testing errors
   157  
   158  a = T.testC([[
   159    loadstring 2; call 0,1;
   160    pushvalue 3; insert -2; call 1, 1;
   161    call 0, 0;
   162    return 1
   163  ]], "x=150", function (a) assert(a==nil); return 3 end)
   164  
   165  assert(type(a) == 'string' and x == 150)
   166  
   167  function check3(p, ...)
   168    assert(arg.n == 3)
   169    assert(string.find(arg[3], p))
   170  end
   171  check3(":1:", T.testC("loadstring 2; gettop; return .", "x="))
   172  check3("cannot read", T.testC("loadfile 2; gettop; return .", "."))
   173  check3("cannot open xxxx", T.testC("loadfile 2; gettop; return .", "xxxx"))
   174  
   175  -- testing table access
   176  
   177  a = {x=0, y=12}
   178  x, y = T.testC("gettable 2; pushvalue 4; gettable 2; return 2",
   179                  a, 3, "y", 4, "x")
   180  assert(x == 0 and y == 12)
   181  T.testC("settable -5", a, 3, 4, "x", 15)
   182  assert(a.x == 15)
   183  a[a] = print
   184  x = T.testC("gettable 2; return 1", a)  -- table and key are the same object!
   185  assert(x == print)
   186  T.testC("settable 2", a, "x")    -- table and key are the same object!
   187  assert(a[a] == "x")
   188  
   189  b = setmetatable({p = a}, {})
   190  getmetatable(b).__index = function (t, i) return t.p[i] end
   191  k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x")
   192  assert(x == 15 and k == 35)
   193  getmetatable(b).__index = function (t, i) return a[i] end
   194  getmetatable(b).__newindex = function (t, i,v ) a[i] = v end
   195  y = T.testC("insert 2; gettable -5; return 1", 2, 3, 4, "y", b)
   196  assert(y == 12)
   197  k = T.testC("settable -5, return 1", b, 3, 4, "x", 16)
   198  assert(a.x == 16 and k == 4)
   199  a[b] = 'xuxu'
   200  y = T.testC("gettable 2, return 1", b)
   201  assert(y == 'xuxu')
   202  T.testC("settable 2", b, 19)
   203  assert(a[b] == 19)
   204  
   205  -- testing next
   206  a = {}
   207  t = pack(T.testC("next; gettop; return .", a, nil))
   208  tcheck(t, {n=1,a})
   209  a = {a=3}
   210  t = pack(T.testC("next; gettop; return .", a, nil))
   211  tcheck(t, {n=3,a,'a',3})
   212  t = pack(T.testC("next; pop 1; next; gettop; return .", a, nil))
   213  tcheck(t, {n=1,a})
   214  
   215  
   216  
   217  -- testing upvalues
   218  
   219  do
   220    local A = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
   221    t, b, c = A([[pushvalue U0; pushvalue U1; pushvalue U2; return 3]])
   222    assert(b == 10 and c == 20 and type(t) == 'table')
   223    a, b = A([[tostring U3; tonumber U4; return 2]])
   224    assert(a == nil and b == 0)
   225    A([[pushnum 100; pushnum 200; replace U2; replace U1]])
   226    b, c = A([[pushvalue U1; pushvalue U2; return 2]])
   227    assert(b == 100 and c == 200)
   228    A([[replace U2; replace U1]], {x=1}, {x=2})
   229    b, c = A([[pushvalue U1; pushvalue U2; return 2]])
   230    assert(b.x == 1 and c.x == 2)
   231    T.checkmemory()
   232  end
   233  
   234  local f = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
   235  assert(T.upvalue(f, 1) == 10 and
   236         T.upvalue(f, 2) == 20 and
   237         T.upvalue(f, 3) == nil)
   238  T.upvalue(f, 2, "xuxu")
   239  assert(T.upvalue(f, 2) == "xuxu")
   240  
   241  
   242  -- testing environments
   243  
   244  assert(T.testC"pushvalue G; return 1" == _G)
   245  assert(T.testC"pushvalue E; return 1" == _G)
   246  local a = {}
   247  T.testC("replace E; return 1", a)
   248  assert(T.testC"pushvalue G; return 1" == _G)
   249  assert(T.testC"pushvalue E; return 1" == a)
   250  assert(debug.getfenv(T.testC) == a)
   251  assert(debug.getfenv(T.upvalue) == _G)
   252  -- userdata inherit environment
   253  local u = T.testC"newuserdata 0; return 1"
   254  assert(debug.getfenv(u) == a)
   255  -- functions inherit environment
   256  u = T.testC"pushcclosure 0; return 1"
   257  assert(debug.getfenv(u) == a)
   258  debug.setfenv(T.testC, _G)
   259  assert(T.testC"pushvalue E; return 1" == _G)
   260  
   261  local b = newproxy()
   262  assert(debug.getfenv(b) == _G)
   263  assert(debug.setfenv(b, a))
   264  assert(debug.getfenv(b) == a)
   265  
   266  
   267  
   268  -- testing locks (refs)
   269  
   270  -- reuse of references
   271  local i = T.ref{}
   272  T.unref(i)
   273  assert(T.ref{} == i)
   274  
   275  Arr = {}
   276  Lim = 100
   277  for i=1,Lim do   -- lock many objects
   278    Arr[i] = T.ref({})
   279  end
   280  
   281  assert(T.ref(nil) == -1 and T.getref(-1) == nil)
   282  T.unref(-1); T.unref(-1)
   283  
   284  for i=1,Lim do   -- unlock all them
   285    T.unref(Arr[i])
   286  end
   287  
   288  function printlocks ()
   289    local n = T.testC("gettable R; return 1", "n")
   290    print("n", n)
   291    for i=0,n do
   292      print(i, T.testC("gettable R; return 1", i))
   293    end
   294  end
   295  
   296  
   297  for i=1,Lim do   -- lock many objects
   298    Arr[i] = T.ref({})
   299  end
   300  
   301  for i=1,Lim,2 do   -- unlock half of them
   302    T.unref(Arr[i])
   303  end
   304  
   305  assert(type(T.getref(Arr[2])) == 'table')
   306  
   307  
   308  assert(T.getref(-1) == nil)
   309  
   310  
   311  a = T.ref({})
   312  
   313  collectgarbage()
   314  
   315  assert(type(T.getref(a)) == 'table')
   316  
   317  
   318  -- colect in cl the `val' of all collected userdata
   319  tt = {}
   320  cl = {n=0}
   321  A = nil; B = nil
   322  local F
   323  F = function (x)
   324    local udval = T.udataval(x)
   325    table.insert(cl, udval)
   326    local d = T.newuserdata(100)   -- cria lixo
   327    d = nil
   328    assert(debug.getmetatable(x).__gc == F)
   329    loadstring("table.insert({}, {})")()   -- cria mais lixo
   330    collectgarbage()   -- forca coleta de lixo durante coleta!
   331    assert(debug.getmetatable(x).__gc == F)   -- coleta anterior nao melou isso?
   332    local dummy = {}    -- cria lixo durante coleta
   333    if A ~= nil then
   334      assert(type(A) == "userdata")
   335      assert(T.udataval(A) == B)
   336      debug.getmetatable(A)    -- just acess it
   337    end
   338    A = x   -- ressucita userdata
   339    B = udval
   340    return 1,2,3
   341  end
   342  tt.__gc = F
   343  
   344  -- test whether udate collection frees memory in the right time
   345  do
   346    collectgarbage();
   347    collectgarbage();
   348    local x = collectgarbage("count");
   349    local a = T.newuserdata(5001)
   350    assert(T.testC("objsize 2; return 1", a) == 5001)
   351    assert(collectgarbage("count") >= x+4) 
   352    a = nil
   353    collectgarbage();
   354    assert(collectgarbage("count") <= x+1)
   355    -- udata without finalizer
   356    x = collectgarbage("count")
   357    collectgarbage("stop")
   358    for i=1,1000 do newproxy(false) end
   359    assert(collectgarbage("count") > x+10)
   360    collectgarbage()
   361    assert(collectgarbage("count") <= x+1)
   362    -- udata with finalizer
   363    x = collectgarbage("count")
   364    collectgarbage()
   365    collectgarbage("stop")
   366    a = newproxy(true)
   367    getmetatable(a).__gc = function () end
   368    for i=1,1000 do newproxy(a) end
   369    assert(collectgarbage("count") >= x+10)
   370    collectgarbage()  -- this collection only calls TM, without freeing memory
   371    assert(collectgarbage("count") >= x+10)
   372    collectgarbage()  -- now frees memory
   373    assert(collectgarbage("count") <= x+1)
   374  end
   375  
   376  
   377  collectgarbage("stop")
   378  
   379  -- create 3 userdatas with tag `tt'
   380  a = T.newuserdata(0); debug.setmetatable(a, tt); na = T.udataval(a)
   381  b = T.newuserdata(0); debug.setmetatable(b, tt); nb = T.udataval(b)
   382  c = T.newuserdata(0); debug.setmetatable(c, tt); nc = T.udataval(c)
   383  
   384  -- create userdata without meta table
   385  x = T.newuserdata(4)
   386  y = T.newuserdata(0)
   387  
   388  assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil)
   389  
   390  d=T.ref(a);
   391  e=T.ref(b);
   392  f=T.ref(c);
   393  t = {T.getref(d), T.getref(e), T.getref(f)}
   394  assert(t[1] == a and t[2] == b and t[3] == c)
   395  
   396  t=nil; a=nil; c=nil;
   397  T.unref(e); T.unref(f)
   398  
   399  collectgarbage()
   400  
   401  -- check that unref objects have been collected
   402  assert(table.getn(cl) == 1 and cl[1] == nc)
   403  
   404  x = T.getref(d)
   405  assert(type(x) == 'userdata' and debug.getmetatable(x) == tt)
   406  x =nil
   407  tt.b = b  -- create cycle
   408  tt=nil    -- frees tt for GC
   409  A = nil
   410  b = nil
   411  T.unref(d);
   412  n5 = T.newuserdata(0)
   413  debug.setmetatable(n5, {__gc=F})
   414  n5 = T.udataval(n5)
   415  collectgarbage()
   416  assert(table.getn(cl) == 4)
   417  -- check order of collection
   418  assert(cl[2] == n5 and cl[3] == nb and cl[4] == na)
   419  
   420  
   421  a, na = {}, {}
   422  for i=30,1,-1 do
   423    a[i] = T.newuserdata(0)
   424    debug.setmetatable(a[i], {__gc=F})
   425    na[i] = T.udataval(a[i])
   426  end
   427  cl = {}
   428  a = nil; collectgarbage()
   429  assert(table.getn(cl) == 30)
   430  for i=1,30 do assert(cl[i] == na[i]) end
   431  na = nil
   432  
   433  
   434  for i=2,Lim,2 do   -- unlock the other half
   435    T.unref(Arr[i])
   436  end
   437  
   438  x = T.newuserdata(41); debug.setmetatable(x, {__gc=F})
   439  assert(T.testC("objsize 2; return 1", x) == 41)
   440  cl = {}
   441  a = {[x] = 1}
   442  x = T.udataval(x)
   443  collectgarbage()
   444  -- old `x' cannot be collected (`a' still uses it)
   445  assert(table.getn(cl) == 0)
   446  for n in pairs(a) do a[n] = nil end
   447  collectgarbage()
   448  assert(table.getn(cl) == 1 and cl[1] == x)   -- old `x' must be collected
   449  
   450  -- testing lua_equal
   451  assert(T.testC("equal 2 4; return 1", print, 1, print, 20))
   452  assert(T.testC("equal 3 2; return 1", 'alo', "alo"))
   453  assert(T.testC("equal 2 3; return 1", nil, nil))
   454  assert(not T.testC("equal 2 3; return 1", {}, {}))
   455  assert(not T.testC("equal 2 3; return 1"))
   456  assert(not T.testC("equal 2 3; return 1", 3))
   457  
   458  -- testing lua_equal with fallbacks
   459  do
   460    local map = {}
   461    local t = {__eq = function (a,b) return map[a] == map[b] end}
   462    local function f(x)
   463      local u = T.newuserdata(0)
   464      debug.setmetatable(u, t)
   465      map[u] = x
   466      return u
   467    end
   468    assert(f(10) == f(10))
   469    assert(f(10) ~= f(11))
   470    assert(T.testC("equal 2 3; return 1", f(10), f(10)))
   471    assert(not T.testC("equal 2 3; return 1", f(10), f(20)))
   472    t.__eq = nil
   473    assert(f(10) ~= f(10))
   474  end
   475  
   476  print'+'
   477  
   478  
   479  
   480  -------------------------------------------------------------------------
   481  do   -- testing errors during GC
   482    local a = {}
   483    for i=1,20 do
   484      a[i] = T.newuserdata(i)   -- creates several udata
   485    end
   486    for i=1,20,2 do   -- mark half of them to raise error during GC
   487      debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end})
   488    end
   489    for i=2,20,2 do   -- mark the other half to count and to create more garbage
   490      debug.setmetatable(a[i], {__gc = function (x) loadstring("A=A+1")() end})
   491    end
   492    _G.A = 0
   493    a = 0
   494    while 1 do
   495    if xpcall(collectgarbage, function (s) a=a+1 end) then
   496      break   -- stop if no more errors
   497    end
   498    end
   499    assert(a == 10)  -- number of errors
   500    assert(A == 10)  -- number of normal collections
   501  end
   502  -------------------------------------------------------------------------
   503  -- test for userdata vals
   504  do
   505    local a = {}; local lim = 30
   506    for i=0,lim do a[i] = T.pushuserdata(i) end
   507    for i=0,lim do assert(T.udataval(a[i]) == i) end
   508    for i=0,lim do assert(T.pushuserdata(i) == a[i]) end
   509    for i=0,lim do a[a[i]] = i end
   510    for i=0,lim do a[T.pushuserdata(i)] = i end
   511    assert(type(tostring(a[1])) == "string")
   512  end
   513  
   514  
   515  -------------------------------------------------------------------------
   516  -- testing multiple states
   517  T.closestate(T.newstate());
   518  L1 = T.newstate()
   519  assert(L1)
   520  assert(pack(T.doremote(L1, "function f () return 'alo', 3 end; f()")).n == 0)
   521  
   522  a, b = T.doremote(L1, "return f()")
   523  assert(a == 'alo' and b == '3')
   524  
   525  T.doremote(L1, "_ERRORMESSAGE = nil")
   526  -- error: `sin' is not defined
   527  a, b = T.doremote(L1, "return sin(1)")
   528  assert(a == nil and b == 2)   -- 2 == run-time error
   529  
   530  -- error: syntax error
   531  a, b, c = T.doremote(L1, "return a+")
   532  assert(a == nil and b == 3 and type(c) == "string")   -- 3 == syntax error
   533  
   534  T.loadlib(L1)
   535  a, b = T.doremote(L1, [[
   536    a = strlibopen()
   537    a = packageopen()
   538    a = baselibopen(); assert(a == _G and require("_G") == a)
   539    a = iolibopen(); assert(type(a.read) == "function")
   540    assert(require("io") == a)
   541    a = tablibopen(); assert(type(a.insert) == "function")
   542    a = dblibopen(); assert(type(a.getlocal) == "function")
   543    a = mathlibopen(); assert(type(a.sin) == "function")
   544    return string.sub('okinama', 1, 2)
   545  ]])
   546  assert(a == "ok")
   547  
   548  T.closestate(L1);
   549  
   550  L1 = T.newstate()
   551  T.loadlib(L1)
   552  T.doremote(L1, "a = {}")
   553  T.testC(L1, [[pushstring a; gettable G; pushstring x; pushnum 1;
   554               settable -3]])
   555  assert(T.doremote(L1, "return a.x") == "1")
   556  
   557  T.closestate(L1)
   558  
   559  L1 = nil
   560  
   561  print('+')
   562  
   563  -------------------------------------------------------------------------
   564  -- testing memory limits
   565  -------------------------------------------------------------------------
   566  collectgarbage()
   567  T.totalmem(T.totalmem()+5000)   -- set low memory limit (+5k)
   568  assert(not pcall(loadstring"local a={}; for i=1,100000 do a[i]=i end"))
   569  T.totalmem(1000000000)          -- restore high limit
   570  
   571  
   572  local function stack(x) if x>0 then stack(x-1) end end
   573  
   574  -- test memory errors; increase memory limit in small steps, so that
   575  -- we get memory errors in different parts of a given task, up to there
   576  -- is enough memory to complete the task without errors
   577  function testamem (s, f)
   578    collectgarbage()
   579    stack(10)    -- ensure minimum stack size
   580    local M = T.totalmem()
   581    local oldM = M
   582    local a,b = nil
   583    while 1 do
   584      M = M+3   -- increase memory limit in small steps
   585      T.totalmem(M)
   586      a, b = pcall(f)
   587      if a and b then break end       -- stop when no more errors
   588      collectgarbage()
   589      if not a and not string.find(b, "memory") then   -- `real' error?
   590        T.totalmem(1000000000)  -- restore high limit
   591        error(b, 0)
   592      end
   593    end
   594    T.totalmem(1000000000)  -- restore high limit
   595    print("\nlimit for " .. s .. ": " .. M-oldM)
   596    return b
   597  end
   598  
   599  
   600  -- testing memory errors when creating a new state
   601  
   602  b = testamem("state creation", T.newstate)
   603  T.closestate(b);  -- close new state
   604  
   605  
   606  -- testing threads
   607  
   608  function expand (n,s)
   609    if n==0 then return "" end
   610    local e = string.rep("=", n)
   611    return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
   612                                e, s, expand(n-1,s), e)
   613  end
   614  
   615  G=0; collectgarbage(); a =collectgarbage("count")
   616  loadstring(expand(20,"G=G+1"))()
   617  assert(G==20); collectgarbage();  -- assert(gcinfo() <= a+1)
   618  
   619  testamem("thread creation", function ()
   620    return T.doonnewstack("x=1") == 0  -- try to create thread
   621  end)
   622  
   623  
   624  -- testing memory x compiler
   625  
   626  testamem("loadstring", function ()
   627    return loadstring("x=1")  -- try to do a loadstring
   628  end)
   629  
   630  
   631  local testprog = [[
   632  local function foo () return end
   633  local t = {"x"}
   634  a = "aaa"
   635  for _, v in ipairs(t) do a=a..v end
   636  return true
   637  ]]
   638  
   639  -- testing memory x dofile
   640  _G.a = nil
   641  local t =os.tmpname()
   642  local f = assert(io.open(t, "w"))
   643  f:write(testprog)
   644  f:close()
   645  testamem("dofile", function ()
   646    local a = loadfile(t)
   647    return a and a()
   648  end)
   649  assert(os.remove(t))
   650  assert(_G.a == "aaax")
   651  
   652  
   653  -- other generic tests
   654  
   655  testamem("string creation", function ()
   656    local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
   657    return (a == 'ablo ablo')
   658  end)
   659  
   660  testamem("dump/undump", function ()
   661    local a = loadstring(testprog)
   662    local b = a and string.dump(a)
   663    a = b and loadstring(b)
   664    return a and a()
   665  end)
   666  
   667  local t = os.tmpname()
   668  testamem("file creation", function ()
   669    local f = assert(io.open(t, 'w'))
   670    assert (not io.open"nomenaoexistente")
   671    io.close(f);
   672    return not loadfile'nomenaoexistente'
   673  end)
   674  assert(os.remove(t))
   675  
   676  testamem("table creation", function ()
   677    local a, lim = {}, 10
   678    for i=1,lim do a[i] = i; a[i..'a'] = {} end
   679    return (type(a[lim..'a']) == 'table' and a[lim] == lim)
   680  end)
   681  
   682  local a = 1
   683  close = nil
   684  testamem("closure creation", function ()
   685    function close (b,c)
   686     return function (x) return a+b+c+x end
   687    end
   688    return (close(2,3)(4) == 10)
   689  end)
   690  
   691  testamem("coroutines", function ()
   692    local a = coroutine.wrap(function ()
   693                coroutine.yield(string.rep("a", 10))
   694                return {}
   695              end)
   696    assert(string.len(a()) == 10)
   697    return a()
   698  end)
   699  
   700  print'+'
   701  
   702  -- testing some auxlib functions
   703  assert(T.gsub("alo.alo.uhuh.", ".", "//") == "alo//alo//uhuh//")
   704  assert(T.gsub("alo.alo.uhuh.", "alo", "//") == "//.//.uhuh.")
   705  assert(T.gsub("", "alo", "//") == "")
   706  assert(T.gsub("...", ".", "/.") == "/././.")
   707  assert(T.gsub("...", "...", "") == "")
   708  
   709  
   710  print'OK'
   711