Increase code coverage for Lua libraries

Add test coverage for lua libraries
Remove dead code in Lua implementation

Signed-off-by: Don Brady <don.brady@delphix.com>
This commit is contained in:
Don Brady 2018-02-08 09:31:15 -07:00 committed by Brian Behlendorf
parent ee00bfb2e6
commit fc5d4b6737
17 changed files with 1372 additions and 696 deletions

View File

@ -149,14 +149,12 @@ LUA_C = \
lapi.c \
lauxlib.c \
lbaselib.c \
lbitlib.c \
lcode.c \
lcompat.c \
lcorolib.c \
lctype.c \
ldebug.c \
ldo.c \
ldump.c \
lfunc.c \
lgc.c \
llex.c \
@ -170,7 +168,6 @@ LUA_C = \
ltable.c \
ltablib.c \
ltm.c \
lundump.c \
lvm.c \
lzio.c

View File

@ -15,14 +15,12 @@ ccflags-y += $(NO_UNUSED_BUT_SET_VARIABLE)
$(MODULE)-objs += lapi.o
$(MODULE)-objs += lauxlib.o
$(MODULE)-objs += lbaselib.o
$(MODULE)-objs += lbitlib.o
$(MODULE)-objs += lcode.o
$(MODULE)-objs += lcompat.o
$(MODULE)-objs += lcorolib.o
$(MODULE)-objs += lctype.o
$(MODULE)-objs += ldebug.o
$(MODULE)-objs += ldo.o
$(MODULE)-objs += ldump.o
$(MODULE)-objs += lfunc.o
$(MODULE)-objs += lgc.o
$(MODULE)-objs += llex.o
@ -36,7 +34,6 @@ $(MODULE)-objs += lstrlib.o
$(MODULE)-objs += ltable.o
$(MODULE)-objs += ltablib.o
$(MODULE)-objs += ltm.o
$(MODULE)-objs += lundump.o
$(MODULE)-objs += lvm.o
$(MODULE)-objs += lzio.o
$(MODULE)-objs += setjmp/setjmp.o

View File

@ -22,7 +22,6 @@
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
@ -991,7 +990,7 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
return status;
}
#if defined(LUA_USE_DUMP)
LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
int status;
TValue *o;
@ -1005,7 +1004,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
lua_unlock(L);
return status;
}
#endif
LUA_API int lua_status (lua_State *L) {
return L->status;

View File

@ -1,213 +0,0 @@
/* BEGIN CSTYLED */
/*
** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/
#define lbitlib_c
#define LUA_LIB
#include <sys/lua/lua.h>
#include <sys/lua/lauxlib.h>
#include <sys/lua/lualib.h>
/* number of bits to consider in a number */
#if !defined(LUA_NBITS)
#define LUA_NBITS 32
#endif
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
/* macro to trim extra bits */
#define trim(x) ((x) & ALLONES)
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
typedef lua_Unsigned b_uint;
static b_uint andaux (lua_State *L) {
int i, n = lua_gettop(L);
b_uint r = ~(b_uint)0;
for (i = 1; i <= n; i++)
r &= luaL_checkunsigned(L, i);
return trim(r);
}
static int b_and (lua_State *L) {
b_uint r = andaux(L);
lua_pushunsigned(L, r);
return 1;
}
static int b_test (lua_State *L) {
b_uint r = andaux(L);
lua_pushboolean(L, r != 0);
return 1;
}
static int b_or (lua_State *L) {
int i, n = lua_gettop(L);
b_uint r = 0;
for (i = 1; i <= n; i++)
r |= luaL_checkunsigned(L, i);
lua_pushunsigned(L, trim(r));
return 1;
}
static int b_xor (lua_State *L) {
int i, n = lua_gettop(L);
b_uint r = 0;
for (i = 1; i <= n; i++)
r ^= luaL_checkunsigned(L, i);
lua_pushunsigned(L, trim(r));
return 1;
}
static int b_not (lua_State *L) {
b_uint r = ~luaL_checkunsigned(L, 1);
lua_pushunsigned(L, trim(r));
return 1;
}
static int b_shift (lua_State *L, b_uint r, int i) {
if (i < 0) { /* shift right? */
i = -i;
r = trim(r);
if (i >= LUA_NBITS) r = 0;
else r >>= i;
}
else { /* shift left */
if (i >= LUA_NBITS) r = 0;
else r <<= i;
r = trim(r);
}
lua_pushunsigned(L, r);
return 1;
}
static int b_lshift (lua_State *L) {
return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2));
}
static int b_rshift (lua_State *L) {
return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2));
}
static int b_arshift (lua_State *L) {
b_uint r = luaL_checkunsigned(L, 1);
int i = luaL_checkint(L, 2);
if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1))))
return b_shift(L, r, -i);
else { /* arithmetic shift for 'negative' number */
if (i >= LUA_NBITS) r = ALLONES;
else
r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */
lua_pushunsigned(L, r);
return 1;
}
}
static int b_rot (lua_State *L, int i) {
b_uint r = luaL_checkunsigned(L, 1);
i &= (LUA_NBITS - 1); /* i = i % NBITS */
r = trim(r);
if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */
r = (r << i) | (r >> (LUA_NBITS - i));
lua_pushunsigned(L, trim(r));
return 1;
}
static int b_lrot (lua_State *L) {
return b_rot(L, luaL_checkint(L, 2));
}
static int b_rrot (lua_State *L) {
return b_rot(L, -luaL_checkint(L, 2));
}
/*
** get field and width arguments for field-manipulation functions,
** checking whether they are valid.
** ('luaL_error' called without 'return' to avoid later warnings about
** 'width' being used uninitialized.)
*/
static int fieldargs (lua_State *L, int farg, int *width) {
int f = luaL_checkint(L, farg);
int w = luaL_optint(L, farg + 1, 1);
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
if (f + w > LUA_NBITS)
luaL_error(L, "trying to access non-existent bits");
*width = w;
return f;
}
static int b_extract (lua_State *L) {
int w;
b_uint r = luaL_checkunsigned(L, 1);
int f = fieldargs(L, 2, &w);
r = (r >> f) & mask(w);
lua_pushunsigned(L, r);
return 1;
}
static int b_replace (lua_State *L) {
int w;
b_uint r = luaL_checkunsigned(L, 1);
b_uint v = luaL_checkunsigned(L, 2);
int f = fieldargs(L, 3, &w);
int m = mask(w);
v &= m; /* erase bits outside given width */
r = (r & ~(m << f)) | (v << f);
lua_pushunsigned(L, r);
return 1;
}
static const luaL_Reg bitlib[] = {
{"arshift", b_arshift},
{"band", b_and},
{"bnot", b_not},
{"bor", b_or},
{"bxor", b_xor},
{"btest", b_test},
{"extract", b_extract},
{"lrotate", b_lrot},
{"lshift", b_lshift},
{"replace", b_replace},
{"rrotate", b_rrot},
{"rshift", b_rshift},
{NULL, NULL}
};
LUAMOD_API int luaopen_bit32 (lua_State *L) {
luaL_newlib(L, bitlib);
return 1;
}
/* END CSTYLED */

View File

@ -57,7 +57,7 @@ static int luaB_coresume (lua_State *L) {
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + `resume' returns */
return r + 1; /* return true + 'resume' returns */
}
}

View File

@ -24,7 +24,6 @@
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
#include "lzio.h"
@ -684,14 +683,9 @@ static void f_parser (lua_State *L, void *ud) {
Closure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = zgetc(p->z); /* read first character */
if (c == LUA_SIGNATURE[0]) {
checkmode(L, p->mode, "binary");
cl = luaU_undump(L, p->z, &p->buff, p->name);
}
else {
checkmode(L, p->mode, "text");
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
}
lua_assert(c != LUA_SIGNATURE[0]); /* binary not supported */
checkmode(L, p->mode, "text");
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */
UpVal *up = luaF_newupval(L);

View File

@ -1,173 +0,0 @@
/* BEGIN CSTYLED */
/*
** $Id: ldump.c,v 2.17.1.1 2013/04/12 18:48:47 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#define ldump_c
#define LUA_CORE
#include <sys/lua/lua.h>
#include "lobject.h"
#include "lstate.h"
#include "lundump.h"
typedef struct {
lua_State* L;
lua_Writer writer;
void* data;
int strip;
int status;
} DumpState;
#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
static void DumpBlock(const void* b, size_t size, DumpState* D)
{
if (D->status==0)
{
lua_unlock(D->L);
D->status=(*D->writer)(D->L,b,size,D->data);
lua_lock(D->L);
}
}
static void DumpChar(int y, DumpState* D)
{
char x=(char)y;
DumpVar(x,D);
}
static void DumpInt(int x, DumpState* D)
{
DumpVar(x,D);
}
static void DumpNumber(lua_Number x, DumpState* D)
{
DumpVar(x,D);
}
static void DumpVector(const void* b, int n, size_t size, DumpState* D)
{
DumpInt(n,D);
DumpMem(b,n,size,D);
}
static void DumpString(const TString* s, DumpState* D)
{
if (s==NULL)
{
size_t size=0;
DumpVar(size,D);
}
else
{
size_t size=s->tsv.len+1; /* include trailing '\0' */
DumpVar(size,D);
DumpBlock(getstr(s),size*sizeof(char),D);
}
}
#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
static void DumpFunction(const Proto* f, DumpState* D);
static void DumpConstants(const Proto* f, DumpState* D)
{
int i,n=f->sizek;
DumpInt(n,D);
for (i=0; i<n; i++)
{
const TValue* o=&f->k[i];
DumpChar(ttypenv(o),D);
switch (ttypenv(o))
{
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
DumpChar(bvalue(o),D);
break;
case LUA_TNUMBER:
DumpNumber(nvalue(o),D);
break;
case LUA_TSTRING:
DumpString(rawtsvalue(o),D);
break;
default: lua_assert(0);
}
}
n=f->sizep;
DumpInt(n,D);
for (i=0; i<n; i++) DumpFunction(f->p[i],D);
}
static void DumpUpvalues(const Proto* f, DumpState* D)
{
int i,n=f->sizeupvalues;
DumpInt(n,D);
for (i=0; i<n; i++)
{
DumpChar(f->upvalues[i].instack,D);
DumpChar(f->upvalues[i].idx,D);
}
}
static void DumpDebug(const Proto* f, DumpState* D)
{
int i,n;
DumpString((D->strip) ? NULL : f->source,D);
n= (D->strip) ? 0 : f->sizelineinfo;
DumpVector(f->lineinfo,n,sizeof(int),D);
n= (D->strip) ? 0 : f->sizelocvars;
DumpInt(n,D);
for (i=0; i<n; i++)
{
DumpString(f->locvars[i].varname,D);
DumpInt(f->locvars[i].startpc,D);
DumpInt(f->locvars[i].endpc,D);
}
n= (D->strip) ? 0 : f->sizeupvalues;
DumpInt(n,D);
for (i=0; i<n; i++) DumpString(f->upvalues[i].name,D);
}
static void DumpFunction(const Proto* f, DumpState* D)
{
DumpInt(f->linedefined,D);
DumpInt(f->lastlinedefined,D);
DumpChar(f->numparams,D);
DumpChar(f->is_vararg,D);
DumpChar(f->maxstacksize,D);
DumpCode(f,D);
DumpConstants(f,D);
DumpUpvalues(f,D);
DumpDebug(f,D);
}
static void DumpHeader(DumpState* D)
{
lu_byte h[LUAC_HEADERSIZE];
luaU_header(h);
DumpBlock(h,LUAC_HEADERSIZE,D);
}
/*
** dump Lua function as precompiled chunk
*/
int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
{
DumpState D;
D.L=L;
D.writer=w;
D.data=data;
D.strip=strip;
D.status=0;
DumpHeader(&D);
DumpFunction(f,&D);
return D.status;
}
/* END CSTYLED */

View File

@ -174,6 +174,7 @@ static int str_char (lua_State *L) {
}
#if defined(LUA_USE_DUMP)
static int writer (lua_State *L, const void* b, size_t size, void* B) {
(void)L;
luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
@ -191,7 +192,7 @@ static int str_dump (lua_State *L) {
luaL_pushresult(&b);
return 1;
}
#endif
/*
@ -992,7 +993,9 @@ static int str_format (lua_State *L) {
static const luaL_Reg strlib[] = {
{"byte", str_byte},
{"char", str_char},
#if defined(LUA_USE_DUMP)
{"dump", str_dump},
#endif
{"find", str_find},
{"format", str_format},
{"gmatch", str_gmatch},

View File

@ -1,258 +0,0 @@
/* BEGIN CSTYLED */
/*
** $Id: lundump.c,v 2.22.1.1 2013/04/12 18:48:47 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#define lundump_c
#define LUA_CORE
#include <sys/lua/lua.h>
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstring.h"
#include "lundump.h"
#include "lzio.h"
typedef struct {
lua_State* L;
ZIO* Z;
Mbuffer* b;
const char* name;
} LoadState;
static l_noret error(LoadState* S, const char* why)
{
luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why);
luaD_throw(S->L,LUA_ERRSYNTAX);
}
#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
#define LoadByte(S) (lu_byte)LoadChar(S)
#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
#if !defined(luai_verifycode)
#define luai_verifycode(L,b,f) /* empty */
#endif
static void LoadBlock(LoadState* S, void* b, size_t size)
{
if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated");
}
static int LoadChar(LoadState* S)
{
char x;
LoadVar(S,x);
return x;
}
static int LoadInt(LoadState* S)
{
int x;
LoadVar(S,x);
if (x<0) error(S,"corrupted");
return x;
}
static lua_Number LoadNumber(LoadState* S)
{
lua_Number x;
LoadVar(S,x);
return x;
}
static TString* LoadString(LoadState* S)
{
size_t size;
LoadVar(S,size);
if (size==0)
return NULL;
else
{
char* s=luaZ_openspace(S->L,S->b,size);
LoadBlock(S,s,size*sizeof(char));
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
}
}
static void LoadCode(LoadState* S, Proto* f)
{
int n=LoadInt(S);
f->code=luaM_newvector(S->L,n,Instruction);
f->sizecode=n;
LoadVector(S,f->code,n,sizeof(Instruction));
}
static void LoadFunction(LoadState* S, Proto* f);
static void LoadConstants(LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
f->k=luaM_newvector(S->L,n,TValue);
f->sizek=n;
for (i=0; i<n; i++) setnilvalue(&f->k[i]);
for (i=0; i<n; i++)
{
TValue* o=&f->k[i];
int t=LoadChar(S);
switch (t)
{
case LUA_TNIL:
setnilvalue(o);
break;
case LUA_TBOOLEAN:
setbvalue(o,LoadChar(S));
break;
case LUA_TNUMBER:
setnvalue(o,LoadNumber(S));
break;
case LUA_TSTRING:
setsvalue2n(S->L,o,LoadString(S));
break;
default: lua_assert(0);
}
}
n=LoadInt(S);
f->p=luaM_newvector(S->L,n,Proto*);
f->sizep=n;
for (i=0; i<n; i++) f->p[i]=NULL;
for (i=0; i<n; i++)
{
f->p[i]=luaF_newproto(S->L);
LoadFunction(S,f->p[i]);
}
}
static void LoadUpvalues(LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
f->upvalues=luaM_newvector(S->L,n,Upvaldesc);
f->sizeupvalues=n;
for (i=0; i<n; i++) f->upvalues[i].name=NULL;
for (i=0; i<n; i++)
{
f->upvalues[i].instack=LoadByte(S);
f->upvalues[i].idx=LoadByte(S);
}
}
static void LoadDebug(LoadState* S, Proto* f)
{
int i,n;
f->source=LoadString(S);
n=LoadInt(S);
f->lineinfo=luaM_newvector(S->L,n,int);
f->sizelineinfo=n;
LoadVector(S,f->lineinfo,n,sizeof(int));
n=LoadInt(S);
f->locvars=luaM_newvector(S->L,n,LocVar);
f->sizelocvars=n;
for (i=0; i<n; i++) f->locvars[i].varname=NULL;
for (i=0; i<n; i++)
{
f->locvars[i].varname=LoadString(S);
f->locvars[i].startpc=LoadInt(S);
f->locvars[i].endpc=LoadInt(S);
}
n=LoadInt(S);
for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S);
}
static void LoadFunction(LoadState* S, Proto* f)
{
f->linedefined=LoadInt(S);
f->lastlinedefined=LoadInt(S);
f->numparams=LoadByte(S);
f->is_vararg=LoadByte(S);
f->maxstacksize=LoadByte(S);
LoadCode(S,f);
LoadConstants(S,f);
LoadUpvalues(S,f);
LoadDebug(S,f);
}
/* the code below must be consistent with the code in luaU_header */
#define N0 LUAC_HEADERSIZE
#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char))
#define N2 N1+2
#define N3 N2+6
static void LoadHeader(LoadState* S)
{
lu_byte h[LUAC_HEADERSIZE];
lu_byte s[LUAC_HEADERSIZE];
luaU_header(h);
memcpy(s,h,sizeof(char)); /* first char already read */
LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char));
if (memcmp(h,s,N0)==0) return;
if (memcmp(h,s,N1)!=0) error(S,"not a");
if (memcmp(h,s,N2)!=0) error(S,"version mismatch in");
if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted");
}
/*
** load precompiled chunk
*/
Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
{
LoadState S;
Closure* cl;
if (*name=='@' || *name=='=')
S.name=name+1;
else if (*name==LUA_SIGNATURE[0])
S.name="binary string";
else
S.name=name;
S.L=L;
S.Z=Z;
S.b=buff;
LoadHeader(&S);
cl=luaF_newLclosure(L,1);
setclLvalue(L,L->top,cl); incr_top(L);
cl->l.p=luaF_newproto(L);
LoadFunction(&S,cl->l.p);
if (cl->l.p->sizeupvalues != 1)
{
Proto* p=cl->l.p;
cl=luaF_newLclosure(L,cl->l.p->sizeupvalues);
cl->l.p=p;
setclLvalue(L,L->top-1,cl);
}
luai_verifycode(L,buff,cl->l.p);
return cl;
}
#define MYINT(s) (s[0]-'0')
#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)
#define FORMAT 0 /* this is the official format */
/*
* make header for precompiled chunks
* if you change the code below be sure to update LoadHeader and FORMAT above
* and LUAC_HEADERSIZE in lundump.h
*/
void luaU_header (lu_byte* h)
{
int x=1;
memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char));
h+=sizeof(LUA_SIGNATURE)-sizeof(char);
*h++=cast_byte(VERSION);
*h++=cast_byte(FORMAT);
*h++=cast_byte(*(char*)&x); /* endianness */
*h++=cast_byte(sizeof(int));
*h++=cast_byte(sizeof(size_t));
*h++=cast_byte(sizeof(Instruction));
*h++=cast_byte(sizeof(lua_Number));
*h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */
memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char));
}
/* END CSTYLED */

View File

@ -1,30 +0,0 @@
/* BEGIN CSTYLED */
/*
** $Id: lundump.h,v 1.39.1.1 2013/04/12 18:48:47 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#ifndef lundump_h
#define lundump_h
#include "lobject.h"
#include "lzio.h"
/* load one chunk; from lundump.c */
LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
/* make header; from lundump.c */
LUAI_FUNC void luaU_header (lu_byte* h);
/* dump one chunk; from ldump.c */
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
/* data to catch conversion errors */
#define LUAC_TAIL "\x19\x93\r\n\x1a\n"
/* size in bytes of header of binary files */
#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char))
#endif
/* END CSTYLED */

View File

@ -65,8 +65,8 @@ tags = ['functional', 'casenorm']
[tests/functional/channel_program/lua_core]
tests = ['tst.args_to_lua', 'tst.divide_by_zero', 'tst.exists',
'tst.integer_illegal', 'tst.integer_overflow', 'tst.language_functions_neg',
'tst.language_functions_pos', 'tst.large_prog', 'tst.memory_limit',
'tst.nested_neg', 'tst.nested_pos', 'tst.nvlist_to_lua',
'tst.language_functions_pos', 'tst.large_prog', 'tst.libraries',
'tst.memory_limit', 'tst.nested_neg', 'tst.nested_pos', 'tst.nvlist_to_lua',
'tst.recursive_neg', 'tst.recursive_pos', 'tst.return_large',
'tst.return_nvlist_neg', 'tst.return_nvlist_pos',
'tst.return_recursive_table', 'tst.timeout']

View File

@ -17,6 +17,11 @@ dist_pkgdata_SCRIPTS = \
tst.large_prog.ksh \
tst.large_prog.out \
tst.large_prog.zcp \
tst.lib_base.lua \
tst.lib_coroutine.lua \
tst.lib_strings.lua \
tst.lib_table.lua \
tst.libraries.ksh \
tst.memory_limit.ksh \
tst.nested_neg.ksh \
tst.nested_neg.zcp \

View File

@ -0,0 +1,469 @@
--[[
--*****************************************************************************
--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
--*
--* Permission is hereby granted, free of charge, to any person obtaining
--* a copy of this software and associated documentation files (the
--* "Software"), to deal in the Software without restriction, including
--* without limitation the rights to use, copy, modify, merge, publish,
--* distribute, sublicense, and/or sell copies of the Software, and to
--* permit persons to whom the Software is furnished to do so, subject to
--* the following conditions:
--*
--* The above copyright notice and this permission notice shall be
--* included in all copies or substantial portions of the Software.
--*
--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--*****************************************************************************
--]]
-- testing metatables
X = 20; B = 30
_ENV = setmetatable({}, {__index=_G})
collectgarbage()
X = X+10
assert(X == 30 and _G.X == 20)
B = false
assert(B == false)
B = nil
assert(B == 30)
assert(getmetatable{} == nil)
assert(getmetatable(4) == nil)
assert(getmetatable(nil) == nil)
a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu",
__tostring=function(x) return x.name end})
assert(getmetatable(a) == "xuxu")
assert(tostring(a) == "NAME")
local a, t = {10,20,30; x="10", y="20"}, {}
assert(setmetatable(a,t) == a)
assert(getmetatable(a) == t)
assert(setmetatable(a,nil) == a)
assert(getmetatable(a) == nil)
assert(setmetatable(a,t) == a)
function f (t, i, e)
assert(not e)
local p = rawget(t, "parent")
return (p and p[i]+3), "dummy return"
end
t.__index = f
a.parent = {z=25, x=12, [4] = 24}
assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
collectgarbage()
a = setmetatable({}, t)
function f(t, i, v) rawset(t, i, v-3) end
setmetatable(t, t) -- causes a bug in 5.1 !
t.__newindex = f
a[1] = 30; a.x = "101"; a[5] = 200
assert(a[1] == 27 and a.x == 98 and a[5] == 197)
local c = {}
a = setmetatable({}, t)
t.__newindex = c
a[1] = 10; a[2] = 20; a[3] = 90
assert(c[1] == 10 and c[2] == 20 and c[3] == 90)
do
local a;
a = setmetatable({}, {__index = setmetatable({},
{__index = setmetatable({},
{__index = function (_,n) return a[n-3]+4, "lixo" end})})})
a[0] = 20
for i=0,10 do
assert(a[i*3] == 20 + i*4)
end
end
do -- newindex
local foi
local a = {}
for i=1,10 do a[i] = 0; a['a'..i] = 0; end
setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
foi = false; a[1]=0; assert(not foi)
foi = false; a['a1']=0; assert(not foi)
foi = false; a['a11']=0; assert(foi)
foi = false; a[11]=0; assert(foi)
foi = false; a[1]=nil; assert(not foi)
foi = false; a[1]=nil; assert(foi)
end
setmetatable(t, nil)
function f (t, ...) return t, {...} end
t.__call = f
do
local x,y = a(table.unpack{'a', 1})
assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil)
x,y = a()
assert(x==a and y[1]==nil)
end
local b = setmetatable({}, t)
setmetatable(b,t)
function f(op)
return function (...) cap = {[0] = op, ...} ; return (...) end
end
t.__add = f("add")
t.__sub = f("sub")
t.__mul = f("mul")
t.__div = f("div")
t.__mod = f("mod")
t.__unm = f("unm")
t.__pow = f("pow")
t.__len = f("len")
assert(b+5 == b)
assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil)
assert(b+'5' == b)
assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil)
assert(5+b == 5)
assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil)
assert('5'+b == '5')
assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil)
b=b-3; assert(getmetatable(b) == t)
assert(5-a == 5)
assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil)
assert('5'-a == '5')
assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil)
assert(a*a == a)
assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil)
assert(a/0 == a)
assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil)
assert(a%2 == a)
assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil)
assert(-a == a)
assert(cap[0] == "unm" and cap[1] == a)
assert(a^4 == a)
assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil)
assert(a^'4' == a)
assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil)
assert(4^a == 4)
assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil)
assert('4'^a == '4')
assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil)
assert(#a == a)
assert(cap[0] == "len" and cap[1] == a)
-- test for rawlen
t = setmetatable({1,2,3}, {__len = function () return 10 end})
assert(#t == 10 and rawlen(t) == 3)
assert(rawlen"abc" == 3)
assert(rawlen(string.rep('a', 1000)) == 1000)
t = {}
t.__lt = function (a,b,c)
collectgarbage()
assert(c == nil)
if type(a) == 'table' then a = a.x end
if type(b) == 'table' then b = b.x end
return a<b, "dummy"
end
function Op(x) return setmetatable({x=x}, t) end
local function test ()
assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1)))
assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a')))
assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1))
assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a')))
end
test()
t.__le = function (a,b,c)
assert(c == nil)
if type(a) == 'table' then a = a.x end
if type(b) == 'table' then b = b.x end
return a<=b, "dummy"
end
test() -- retest comparisons, now using both `lt' and `le'
-- test `partial order'
local function Set(x)
local y = {}
for _,k in pairs(x) do y[k] = 1 end
return setmetatable(y, t)
end
t.__lt = function (a,b)
for k in pairs(a) do
if not b[k] then return false end
b[k] = nil
end
return next(b) ~= nil
end
t.__le = nil
assert(Set{1,2,3} < Set{1,2,3,4})
assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
assert((Set{1,2,3,4} <= Set{1,2,3,4}))
assert((Set{1,2,3,4} >= Set{1,2,3,4}))
assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
t.__le = function (a,b)
for k in pairs(a) do
if not b[k] then return false end
end
return true
end
assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
assert(not(Set{1,3} <= Set{3,5}))
assert(not(Set{1,3} >= Set{3,5}))
t.__eq = function (a,b)
for k in pairs(a) do
if not b[k] then return false end
b[k] = nil
end
return next(b) == nil
end
local s = Set{1,3,5}
assert(s == Set{3,5,1})
assert(not rawequal(s, Set{3,5,1}))
assert(rawequal(s, s))
assert(Set{1,3,5,1} == Set{3,5,1})
assert(Set{1,3,5} ~= Set{3,5,1,6})
t[Set{1,3,5}] = 1
assert(t[Set{1,3,5}] == nil) -- `__eq' is not valid for table accesses
t.__concat = function (a,b,c)
assert(c == nil)
if type(a) == 'table' then a = a.val end
if type(b) == 'table' then b = b.val end
if A then return a..b
else
return setmetatable({val=a..b}, t)
end
end
c = {val="c"}; setmetatable(c, t)
d = {val="d"}; setmetatable(d, t)
A = true
assert(c..d == 'cd')
assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
A = false
assert((c..d..c..d).val == 'cdcd')
x = c..d
assert(getmetatable(x) == t and x.val == 'cd')
x = 0 .."a".."b"..c..d.."e".."f".."g"
assert(x.val == "0abcdefg")
-- concat metamethod x numbers (bug in 5.1.1)
c = {}
local x
setmetatable(c, {__concat = function (a,b)
assert(type(a) == "number" and b == c or type(b) == "number" and a == c)
return c
end})
assert(c..5 == c and 5 .. c == c)
assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c)
-- test comparison compatibilities
local t1, t2, c, d
t1 = {}; c = {}; setmetatable(c, t1)
d = {}
t1.__eq = function () return true end
t1.__lt = function () return true end
setmetatable(d, t1)
assert(c == d and c < d and not(d <= c))
t2 = {}
t2.__eq = t1.__eq
t2.__lt = t1.__lt
setmetatable(d, t2)
assert(c == d and c < d and not(d <= c))
-- test for several levels of calls
local i
local tt = {
__call = function (t, ...)
i = i+1
if t.f then return t.f(...)
else return {...}
end
end
}
local a = setmetatable({}, tt)
local b = setmetatable({f=a}, tt)
local c = setmetatable({f=b}, tt)
i = 0
x = c(3,4,5)
assert(i == 3 and x[1] == 3 and x[3] == 5)
assert(_G.X == 20)
local _g = _G
_ENV = setmetatable({}, {__index=function (_,k) return _g[k] end})
a = {}
rawset(a, "x", 1, 2, 3)
assert(a.x == 1 and rawget(a, "x", 3) == 1)
-- bug in 5.1
T, K, V = nil
grandparent = {}
grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end
parent = {}
parent.__newindex = parent
setmetatable(parent, grandparent)
child = setmetatable({}, parent)
child.foo = 10 --> CRASH (on some machines)
assert(T == parent and K == "foo" and V == 10)
-- testing 'tonumber'
assert(tonumber{} == nil)
assert(tonumber('-012') == -010-2)
assert(tonumber("0xffffffffffff") == 2^(4*12) - 1)
assert(tonumber("0x"..string.rep("f", 150)) == 2^(4*150) - 1)
-- testing 'tonumber' with base
assert(tonumber(' 001010 ', 2) == 10)
assert(tonumber(' 001010 ', 10) == 1010)
assert(tonumber(' -1010 ', 2) == -10)
assert(tonumber('10', 36) == 36)
assert(tonumber(' -10 ', 36) == -36)
assert(tonumber(' +1Z ', 36) == 36 + 35)
assert(tonumber(' -1z ', 36) == -36 + -35)
assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15)))))))
assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42)
assert(tonumber(string.rep('1', 34), 2) + 1 == 2^34)
assert(tonumber('ffffFFFF', 16)+1 == 2^32)
assert(tonumber('0ffffFFFF', 16)+1 == 2^32)
assert(tonumber('-0ffffffFFFF', 16) - 1 == -2^40)
for i = 2,36 do
assert(tonumber('\t10000000000\t', i) == i^10)
end
-- testing 'tonumber' for invalid formats
function f(...)
if select('#', ...) == 1 then
return (...)
else
return "***"
end
end
assert(f(tonumber('fFfa', 15)) == nil)
assert(f(tonumber('099', 8)) == nil)
assert(f(tonumber('1\0', 2)) == nil)
assert(f(tonumber('', 8)) == nil)
assert(f(tonumber(' ', 9)) == nil)
assert(f(tonumber('0xf', 10)) == nil)
assert(f(tonumber('inf')) == nil)
assert(f(tonumber(' INF ')) == nil)
assert(f(tonumber('Nan')) == nil)
assert(f(tonumber('nan')) == nil)
assert(f(tonumber('')) == nil)
assert(f(tonumber('1 a')) == nil)
assert(f(tonumber('1\0')) == nil)
assert(f(tonumber('1 \0')) == nil)
assert(f(tonumber('1\0 ')) == nil)
assert(f(tonumber('e1')) == nil)
assert(f(tonumber('e 1')) == nil)
-- testing 'tonumber' for invalid hexadecimal formats
assert(tonumber('0x') == nil)
assert(tonumber('x') == nil)
assert(tonumber('x3') == nil)
assert(tonumber('00x2') == nil)
assert(tonumber('0x 2') == nil)
assert(tonumber('0 x2') == nil)
assert(tonumber('23x') == nil)
assert(tonumber('- 0xaa') == nil)
-- testing hexadecimal numerals
assert(tonumber('+0x2') == 2)
assert(tonumber('-0xaA') == -170)
assert(tonumber('-0xffFFFfff') == -2^32 + 1)
-- testing 'tostring'
assert(tostring("alo") == "alo")
assert(tostring(12) == "12")
assert(tostring(1234567890123) == '1234567890123')
assert(type(tostring("hello")) == "string")
assert(tostring(true) == "true")
assert(tostring(false) == "false")
assert(string.find(tostring{}, 'table:'))
assert(string.find(tostring(select), 'function:'))
assert(#tostring('\0') == 1)
-- testing ipairs
local x = 0
for k,v in ipairs{10,20,30;x=12} do
x = x + 1
assert(k == x and v == x * 10)
end
for _ in ipairs{x=12, y=24} do assert(nil) end
-- test for 'false' x ipair
x = false
local i = 0
for k,v in ipairs{true,false,true,false} do
i = i + 1
x = not x
assert(x == v)
end
assert(i == 4)
return "OK"

View File

@ -0,0 +1,362 @@
--[[
--*****************************************************************************
--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
--*
--* Permission is hereby granted, free of charge, to any person obtaining
--* a copy of this software and associated documentation files (the
--* "Software"), to deal in the Software without restriction, including
--* without limitation the rights to use, copy, modify, merge, publish,
--* distribute, sublicense, and/or sell copies of the Software, and to
--* permit persons to whom the Software is furnished to do so, subject to
--* the following conditions:
--*
--* The above copyright notice and this permission notice shall be
--* included in all copies or substantial portions of the Software.
--*
--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--*****************************************************************************
--]]
local f
local main, ismain = coroutine.running()
assert(type(main) == "thread" and ismain)
assert(not coroutine.resume(main))
-- tests for multiple yield/resume arguments
local function eqtab (t1, t2)
assert(#t1 == #t2)
for i = 1, #t1 do
local v = t1[i]
assert(t2[i] == v)
end
end
_G.x = nil -- declare x
function foo (a, ...)
local x, y = coroutine.running()
assert(x == f and y == false)
-- next call should not corrupt coroutine (but must fail,
-- as it attempts to resume the running coroutine)
assert(coroutine.resume(f) == false)
assert(coroutine.status(f) == "running")
local arg = {...}
for i=1,#arg do
_G.x = {coroutine.yield(table.unpack(arg[i]))}
end
return table.unpack(a)
end
f = coroutine.create(foo)
assert(type(f) == "thread" and coroutine.status(f) == "suspended")
assert(string.find(tostring(f), "thread"))
local s,a,b,c,d
s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'})
assert(s and a == nil and coroutine.status(f) == "suspended")
s,a,b,c,d = coroutine.resume(f)
eqtab(_G.x, {})
assert(s and a == 1 and b == nil)
s,a,b,c,d = coroutine.resume(f, 1, 2, 3)
eqtab(_G.x, {1, 2, 3})
assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil)
s,a,b,c,d = coroutine.resume(f, "xuxu")
eqtab(_G.x, {"xuxu"})
assert(s and a == 1 and b == 2 and c == 3 and d == nil)
assert(coroutine.status(f) == "dead")
s, a = coroutine.resume(f, "xuxu")
assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
-- yields in tail calls
local function foo (i) return coroutine.yield(i) end
f = coroutine.wrap(function ()
for i=1,10 do
assert(foo(i) == _G.x)
end
return 'a'
end)
for i=1,10 do _G.x = i; assert(f(i) == i) end
_G.x = 'xuxu'; assert(f('xuxu') == 'a')
-- recursive
function pf (n, i)
coroutine.yield(n)
pf(n*i, i+1)
end
f = coroutine.wrap(pf)
local s=1
for i=1,10 do
assert(f(1, 1) == s)
s = s*i
end
-- sieve implemented with co-routines
-- generate all the numbers from 2 to n
function gen (n)
return coroutine.wrap(function ()
for i=2,n do coroutine.yield(i) end
end)
end
-- filter the numbers generated by 'g', removing multiples of 'p'
function filter (p, g)
return coroutine.wrap(function ()
for n in g do
if n%p ~= 0 then coroutine.yield(n) end
end
end)
end
-- generate primes up to 20
local x = gen(20)
local a = {}
while 1 do
local n = x()
if n == nil then break end
table.insert(a, n)
x = filter(n, x)
end
-- expect 8 primes and last one is 19
assert(#a == 8 and a[#a] == 19)
x, a = nil
-- yielding across C boundaries
co = coroutine.wrap(function()
coroutine.yield(20)
return 30
end)
assert(co() == 20)
assert(co() == 30)
local f = function (s, i) return coroutine.yield(i) end
function f (a, b) a = coroutine.yield(a); error{a + b} end
function g(x) return x[1]*2 end
-- unyieldable C call
do
local function f (c)
return c .. c
end
local co = coroutine.wrap(function (c)
local s = string.gsub("a", ".", f)
return s
end)
assert(co() == "aa")
end
-- errors in coroutines
function foo ()
coroutine.yield(3)
error(foo)
end
function goo() foo() end
x = coroutine.wrap(goo)
assert(x() == 3)
x = coroutine.create(goo)
a,b = coroutine.resume(x)
assert(a and b == 3)
a,b = coroutine.resume(x)
assert(not a and b == foo and coroutine.status(x) == "dead")
a,b = coroutine.resume(x)
assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
-- co-routines x for loop
function all (a, n, k)
if k == 0 then coroutine.yield(a)
else
for i=1,n do
a[k] = i
all(a, n, k-1)
end
end
end
local a = 0
for t in coroutine.wrap(function () all({}, 5, 4) end) do
a = a+1
end
assert(a == 5^4)
-- access to locals of collected corroutines
local C = {}; setmetatable(C, {__mode = "kv"})
local x = coroutine.wrap (function ()
local a = 10
local function f () a = a+10; return a end
while true do
a = a+1
coroutine.yield(f)
end
end)
C[1] = x;
local f = x()
assert(f() == 21 and x()() == 32 and x() == f)
x = nil
collectgarbage()
assert(C[1] == nil)
assert(f() == 43 and f() == 53)
-- old bug: attempt to resume itself
function co_func (current_co)
assert(coroutine.running() == current_co)
assert(coroutine.resume(current_co) == false)
coroutine.yield(10, 20)
assert(coroutine.resume(current_co) == false)
coroutine.yield(23)
return 10
end
local co = coroutine.create(co_func)
local a,b,c = coroutine.resume(co, co)
assert(a == true and b == 10 and c == 20)
a,b = coroutine.resume(co, co)
assert(a == true and b == 23)
a,b = coroutine.resume(co, co)
assert(a == true and b == 10)
assert(coroutine.resume(co, co) == false)
assert(coroutine.resume(co, co) == false)
-- attempt to resume 'normal' coroutine
local co1, co2
co1 = coroutine.create(function () return co2() end)
co2 = coroutine.wrap(function ()
assert(coroutine.status(co1) == 'normal')
assert(not coroutine.resume(co1))
coroutine.yield(3)
end)
a,b = coroutine.resume(co1)
assert(a and b == 3)
assert(coroutine.status(co1) == 'dead')
-- access to locals of erroneous coroutines
local x = coroutine.create (function ()
local a = 10
_G.f = function () a=a+1; return a end
error('x')
end)
assert(not coroutine.resume(x))
-- overwrite previous position of local `a'
assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
assert(_G.f() == 11)
assert(_G.f() == 12)
-- leaving a pending coroutine open
_X = coroutine.wrap(function ()
local a = 10
local x = function () a = a+1 end
coroutine.yield()
end)
_X()
assert(coroutine.running() == main)
-- testing yields inside metamethods
local mt = {
__eq = function(a,b) coroutine.yield(nil, "eq"); return a.x == b.x end,
__lt = function(a,b) coroutine.yield(nil, "lt"); return a.x < b.x end,
__le = function(a,b) coroutine.yield(nil, "le"); return a - b <= 0 end,
__add = function(a,b) coroutine.yield(nil, "add"); return a.x + b.x end,
__sub = function(a,b) coroutine.yield(nil, "sub"); return a.x - b.x end,
__mod = function(a,b) coroutine.yield(nil, "mod"); return a.x % b.x end,
__unm = function(a,b) coroutine.yield(nil, "unm"); return -a.x end,
__concat = function(a,b)
coroutine.yield(nil, "concat");
a = type(a) == "table" and a.x or a
b = type(b) == "table" and b.x or b
return a .. b
end,
__index = function (t,k) coroutine.yield(nil, "idx"); return t.k[k] end,
__newindex = function (t,k,v) coroutine.yield(nil, "nidx"); t.k[k] = v end,
}
local function new (x)
return setmetatable({x = x, k = {}}, mt)
end
local a = new(10)
local b = new(12)
local c = new"hello"
local function run (f, t)
local i = 1
local c = coroutine.wrap(f)
while true do
local res, stat = c()
if res then assert(t[i] == nil); return res, t end
assert(stat == t[i])
i = i + 1
end
end
assert(run(function () if (a>=b) then return '>=' else return '<' end end,
{"le", "sub"}) == "<")
-- '<=' using '<'
mt.__le = nil
assert(run(function () if (a<=b) then return '<=' else return '>' end end,
{"lt"}) == "<=")
assert(run(function () if (a==b) then return '==' else return '~=' end end,
{"eq"}) == "~=")
assert(run(function () return a % b end, {"mod"}) == 10)
assert(run(function () return a..b end, {"concat"}) == "1012")
assert(run(function() return a .. b .. c .. a end,
{"concat", "concat", "concat"}) == "1012hello10")
assert(run(function() return "a" .. "b" .. a .. "c" .. c .. b .. "x" end,
{"concat", "concat", "concat"}) == "ab10chello12x")
-- testing yields inside 'for' iterators
local f = function (s, i)
if i%2 == 0 then coroutine.yield(nil, "for") end
if i < s then return i + 1 end
end
assert(run(function ()
local s = 0
for i in f, 4, 0 do s = s + i end
return s
end, {"for", "for", "for"}) == 10)
return "OK"

View File

@ -0,0 +1,241 @@
--[[
--*****************************************************************************
--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
--*
--* Permission is hereby granted, free of charge, to any person obtaining
--* a copy of this software and associated documentation files (the
--* "Software"), to deal in the Software without restriction, including
--* without limitation the rights to use, copy, modify, merge, publish,
--* distribute, sublicense, and/or sell copies of the Software, and to
--* permit persons to whom the Software is furnished to do so, subject to
--* the following conditions:
--*
--* The above copyright notice and this permission notice shall be
--* included in all copies or substantial portions of the Software.
--*
--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--*****************************************************************************
--]]
-- testing string library
local maxi, mini = 0x7fffffffffffffff, 0x8000000000000000
-- testing string.sub
assert(string.sub("123456789",2,4) == "234")
assert(string.sub("123456789",7) == "789")
assert(string.sub("123456789",7,6) == "")
assert(string.sub("123456789",7,7) == "7")
assert(string.sub("123456789",0,0) == "")
assert(string.sub("123456789",-10,10) == "123456789")
assert(string.sub("123456789",1,9) == "123456789")
assert(string.sub("123456789",-10,-20) == "")
assert(string.sub("123456789",-1) == "9")
assert(string.sub("123456789",-4) == "6789")
assert(string.sub("123456789",-6, -4) == "456")
assert(string.sub("123456789", mini, -4) == "123456")
assert(string.sub("123456789", mini, maxi) == "123456789")
assert(string.sub("123456789", mini, mini) == "")
assert(string.sub("\000123456789",3,5) == "234")
assert(("\000123456789"):sub(8) == "789")
-- testing string.find
assert(string.find("123456789", "345") == 3)
a,b = string.find("123456789", "345")
assert(string.sub("123456789", a, b) == "345")
assert(string.find("1234567890123456789", "345", 3) == 3)
assert(string.find("1234567890123456789", "345", 4) == 13)
assert(string.find("1234567890123456789", "346", 4) == nil)
assert(string.find("1234567890123456789", ".45", -9) == 13)
assert(string.find("abcdefg", "\0", 5, 1) == nil)
assert(string.find("", "") == 1)
assert(string.find("", "", 1) == 1)
assert(not string.find("", "", 2))
assert(string.find('', 'aaa', 1) == nil)
assert(('alo(.)alo'):find('(.)', 1, 1) == 4)
assert(string.len("") == 0)
assert(string.len("\0\0\0") == 3)
assert(string.len("1234567890") == 10)
assert(#"" == 0)
assert(#"\0\0\0" == 3)
assert(#"1234567890" == 10)
-- testing string.byte/string.char
assert(string.byte("a") == 97)
assert(string.byte("\xe4") > 127)
assert(string.byte(string.char(255)) == 255)
assert(string.byte(string.char(0)) == 0)
assert(string.byte("\0") == 0)
assert(string.byte("\0\0alo\0x", -1) == string.byte('x'))
assert(string.byte("ba", 2) == 97)
assert(string.byte("\n\n", 2, -1) == 10)
assert(string.byte("\n\n", 2, 2) == 10)
assert(string.byte("") == nil)
assert(string.byte("hi", -3) == nil)
assert(string.byte("hi", 3) == nil)
assert(string.byte("hi", 9, 10) == nil)
assert(string.byte("hi", 2, 1) == nil)
assert(string.char() == "")
assert(string.char(0, 255, 0) == "\0\255\0")
assert(string.char(0, string.byte("\xe4"), 0) == "\0\xe4\0")
assert(string.char(string.byte("\xe4l\0\195\179u", 1, -1)) == "\xe4l\0\195\179u")
assert(string.char(string.byte("\xe4l\0\195\179u", 1, 0)) == "")
assert(string.char(string.byte("\xe4l\0\195\179u", -10, 100)) == "\xe4l\0\195\179u")
assert(string.upper("ab\0c") == "AB\0C")
assert(string.lower("\0ABCc%$") == "\0abcc%$")
assert(string.rep('teste', 0) == '')
assert(string.rep('t\195\169s\00t\195\170', 2) == 't\195\169s\0t\195\170t\195\169s\000t\195\170')
assert(string.rep('', 10) == '')
-- repetitions with separator
assert(string.rep('teste', 0, 'xuxu') == '')
assert(string.rep('teste', 1, 'xuxu') == 'teste')
assert(string.rep('\1\0\1', 2, '\0\0') == '\1\0\1\0\0\1\0\1')
assert(string.rep('', 10, '.') == string.rep('.', 9))
assert(string.reverse"" == "")
assert(string.reverse"\0\1\2\3" == "\3\2\1\0")
assert(string.reverse"\0001234" == "4321\0")
for i=0,30 do assert(string.len(string.rep('a', i)) == i) end
x = '"\195\174lo"\n\\'
assert(string.format('%q%s', x, x) == '"\\"\195\174lo\\"\\\n\\\\""\195\174lo"\n\\')
assert(string.format('%q', "\0") == [["\0"]])
x = "\0\1\0023\5\0009"
assert(string.format("\0%c\0%c%x\0", string.byte("\xe4"), string.byte("b"), 140) ==
"\0\xe4\0b8c\0")
assert(string.format('') == "")
assert(string.format("%c",34)..string.format("%c",48)..string.format("%c",90)..string.format("%c",100) ==
string.format("%c%c%c%c", 34, 48, 90, 100))
assert(string.format("%s\0 is not \0%s", 'not be', 'be') == 'not be\0 is not \0be')
assert(string.format("%%%d %010d", 10, 23) == "%10 0000000023")
x = string.format('"%-50s"', 'a')
assert(#x == 52)
assert(string.sub(x, 1, 4) == '"a ')
assert(string.format("-%.20s.20s", string.rep("%", 2000)) ==
"-"..string.rep("%", 20)..".20s")
assert(string.format('"-%20s.20s"', string.rep("%", 2000)) ==
string.format("%q", "-"..string.rep("%", 2000)..".20s"))
-- format x tostring
assert(string.format("%s %s", nil, true) == "nil true")
assert(string.format("%s %.4s", false, true) == "false true")
assert(string.format("%.3s %.3s", false, true) == "fal tru")
-- testing large numbers for format
do
local max, min = 0x7fffffff, -0x80000000 -- "large" for 32 bits
assert(string.sub(string.format("%8x", -1), -8) == "ffffffff")
assert(string.format("%x", max) == "7fffffff")
assert(string.sub(string.format("%x", min), -8) == "80000000")
assert(string.format("%d", max) == "2147483647")
assert(string.format("%d", min) == "-2147483648")
assert(string.format("%u", 0xffffffff) == "4294967295")
assert(string.format("%o", 0xABCD) == "125715")
max, min = 0x7fffffffffffffff, -0x8000000000000000
assert(string.format("0x%8X", 0x8f000003) == "0x8F000003")
assert(string.format("%d", 2^53) == "9007199254740992")
assert(string.format("%x", max) == "7fffffffffffffff")
assert(string.format("%x", min) == "8000000000000000")
assert(string.format("%d", max) == "9223372036854775807")
assert(string.format("%d", min) == "-9223372036854775808")
end
assert(table.concat{} == "")
assert(table.concat({}, 'x') == "")
assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2")
local a = {}; for i=1,300 do a[i] = "xuxu" end
assert(table.concat(a, "123").."123" == string.rep("xuxu123", 300))
assert(table.concat(a, "b", 20, 20) == "xuxu")
assert(table.concat(a, "", 20, 21) == "xuxuxuxu")
assert(table.concat(a, "x", 22, 21) == "")
assert(table.concat(a, "3", 299) == "xuxu3xuxu")
assert(table.concat({}, "x", 2^31-1, 2^31-2) == "")
assert(table.concat({}, "x", -2^31+1, -2^31) == "")
assert(table.concat({}, "x", 2^31-1, -2^31) == "")
assert(table.concat({[2^31-1] = "alo"}, "x", 2^31-1, 2^31-1) == "alo")
a = {"a","b","c"}
assert(table.concat(a, ",", 1, 0) == "")
assert(table.concat(a, ",", 1, 1) == "a")
assert(table.concat(a, ",", 1, 2) == "a,b")
assert(table.concat(a, ",", 2) == "b,c")
assert(table.concat(a, ",", 3) == "c")
assert(table.concat(a, ",", 4) == "")
-- tests for gmatch
local a = 0
for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end
assert(a==6)
t = {n=0}
for w in string.gmatch("first second word", "%w+") do
t.n=t.n+1; t[t.n] = w
end
assert(t[1] == "first" and t[2] == "second" and t[3] == "word")
t = {3, 6, 9}
for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do
assert(i == table.remove(t, 1))
end
assert(#t == 0)
t = {}
for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do
t[i] = j
end
a = 0
for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end
assert(a == 3)
-- tests for gsub
function f1(s, p)
p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end)
p = string.gsub(p, "^(^?)", "%1()", 1)
p = string.gsub(p, "($?)$", "()%1", 1)
local t = {string.match(s, p)}
return string.sub(s, t[1], t[#t] - 1)
end
assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o")
assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3')
assert(f1('=======', '^(=*)=%1$') == '=======')
-- gsub with tables
assert(string.gsub("alo alo", ".", {}) == "alo alo")
assert(string.gsub("alo alo", "(.)", {a="AA", l=""}) == "AAo AAo")
assert(string.gsub("alo alo", "(.).", {a="AA", l="K"}) == "AAo AAo")
assert(string.gsub("alo alo", "((.)(.?))", {al="AA", o=false}) == "AAo AAo")
assert(string.gsub("alo alo", "().", {2,5,6}) == "256 alo")
t = {}; setmetatable(t, {__index = function (t,s) return string.upper(s) end})
assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
-- tests for match
assert(string.match('==========', '^([=]*)=%1$') == nil)
assert(string.match("alo xyzK", "(%w+)K") == "xyz")
assert(string.match("254 K", "(%d*)K") == "")
assert(string.match("alo ", "(%w*)$") == "")
assert(string.match("alo ", "(%w+)$") == nil)
assert(string.match("ab\0\1\2c", "[\0-\2]+") == "\0\1\2")
return "OK"

View File

@ -0,0 +1,252 @@
--[[
--*****************************************************************************
--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
--*
--* Permission is hereby granted, free of charge, to any person obtaining
--* a copy of this software and associated documentation files (the
--* "Software"), to deal in the Software without restriction, including
--* without limitation the rights to use, copy, modify, merge, publish,
--* distribute, sublicense, and/or sell copies of the Software, and to
--* permit persons to whom the Software is furnished to do so, subject to
--* the following conditions:
--*
--* The above copyright notice and this permission notice shall be
--* included in all copies or substantial portions of the Software.
--*
--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--*****************************************************************************
--]]
-- testing table library
-- workaround missing pcall in zfs lua implementation
local function tuple(...)
return {n=select('#', ...), ...}
end
function pcall(f, ...)
local co = coroutine.create(f)
local res = tuple(coroutine.resume(co, ...))
if res[1] and coroutine.status(co) == "suspended" then
res[1] = false
end
return table.unpack(res, 1, res.n)
end
-- workaround missing math lib in zfs lua implementation
local A1, A2 = 727595, 798405 -- 5^17=D20*A1+A2
local D20, D40 = 1048576, 1099511627776 -- 2^20, 2^40
local X1, X2 = 0, 1
function rand()
local U = X2*A2
local V = (X1*A2 + X2*A1) % D20
V = (V*D20 + U) % D40
X1 = V/D20
X2 = V - X1*D20
return V*100/D40
end
-- testing unpack
local unpack = table.unpack
local x,y,z,a,n
a = {}; lim = 2000
for i=1, lim do a[i]=i end
assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim)
x = unpack(a)
assert(x == 1)
x = {unpack(a)}
assert(#x == lim and x[1] == 1 and x[lim] == lim)
x = {unpack(a, lim-2)}
assert(#x == 3 and x[1] == lim-2 and x[3] == lim)
x = {unpack(a, 10, 6)}
assert(next(x) == nil) -- no elements
x = {unpack(a, 11, 10)}
assert(next(x) == nil) -- no elements
x,y = unpack(a, 10, 10)
assert(x == 10 and y == nil)
x,y,z = unpack(a, 10, 11)
assert(x == 10 and y == 11 and z == nil)
a,x = unpack{1}
assert(a==1 and x==nil)
a,x = unpack({1,2}, 1, 1)
assert(a==1 and x==nil)
if not _no32 then
assert(not pcall(unpack, {}, 0, 2^31-1))
assert(not pcall(unpack, {}, 1, 2^31-1))
assert(not pcall(unpack, {}, -(2^31), 2^31-1))
assert(not pcall(unpack, {}, -(2^31 - 1), 2^31-1))
assert(pcall(unpack, {}, 2^31-1, 0))
assert(pcall(unpack, {}, 2^31-1, 1))
pcall(unpack, {}, 1, 2^31)
a, b = unpack({[2^31-1] = 20}, 2^31-1, 2^31-1)
assert(a == 20 and b == nil)
a, b = unpack({[2^31-1] = 20}, 2^31-2, 2^31-1)
assert(a == nil and b == 20)
end
-- testing pack
a = table.pack()
assert(a[1] == nil and a.n == 0)
a = table.pack(table)
assert(a[1] == table and a.n == 1)
a = table.pack(nil, nil, nil, nil)
assert(a[1] == nil and a.n == 4)
-- testing sort
-- test checks for invalid order functions
local function check (t)
local function f(a, b) assert(a and b); return true end
local s, e = pcall(table.sort, t, f)
assert(not s and e:find("invalid order function"))
end
check{1,2,3,4}
check{1,2,3,4,5}
check{1,2,3,4,5,6}
function check (a, f)
f = f or function (x,y) return x<y end;
for n = #a, 2, -1 do
assert(not f(a[n], a[n-1]))
end
end
a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"}
table.sort(a)
check(a)
function perm (s, n)
n = n or #s
if n == 1 then
local t = {unpack(s)}
table.sort(t)
check(t)
else
for i = 1, n do
s[i], s[n] = s[n], s[i]
perm(s, n - 1)
s[i], s[n] = s[n], s[i]
end
end
end
perm{}
perm{1}
perm{1,2}
perm{1,2,3}
perm{1,2,3,4}
perm{2,2,3,4}
perm{1,2,3,4,5}
perm{1,2,3,3,5}
perm{1,2,3,4,5,6}
perm{2,2,3,3,5,6}
limit = 5000
a = {}
for i=1,limit do
a[i] = rand()
end
table.sort(a)
check(a)
table.sort(a)
check(a)
a = {}
for i=1,limit do
a[i] = rand()
end
i=0
table.sort(a, function(x,y) i=i+1; return y<x end)
check(a, function(x,y) return y<x end)
table.sort{} -- empty array
for i=1,limit do a[i] = false end
table.sort(a, function(x,y) return nil end)
check(a, function(x,y) return nil end)
for i,v in pairs(a) do assert(not v or i=='n' and v==limit) end
A = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"}
table.sort(A)
check(A)
tt = {__lt = function (a,b) return a.val < b.val end}
a = {}
for i=1,10 do a[i] = {val=rand(100)}; setmetatable(a[i], tt); end
table.sort(a)
check(a, tt.__lt)
check(a)
-- test remove
local function test (a)
table.insert(a, 10); table.insert(a, 2, 20);
table.insert(a, 1, -1); table.insert(a, 40);
table.insert(a, #a+1, 50)
table.insert(a, 2, -2)
assert(table.remove(a,1) == -1)
assert(table.remove(a,1) == -2)
assert(table.remove(a,1) == 10)
assert(table.remove(a,1) == 20)
assert(table.remove(a,1) == 40)
assert(table.remove(a,1) == 50)
assert(table.remove(a,1) == nil)
end
a = {n=0, [-7] = "ban"}
test(a)
assert(a.n == 0 and a[-7] == "ban")
a = {[-7] = "ban"};
test(a)
assert(a.n == nil and #a == 0 and a[-7] == "ban")
table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1)
assert(table.remove(a) == 10)
assert(table.remove(a) == 20)
assert(table.remove(a) == -1)
a = {'c', 'd'}
table.insert(a, 3, 'a')
table.insert(a, 'b')
assert(table.remove(a, 1) == 'c')
assert(table.remove(a, 1) == 'd')
assert(table.remove(a, 1) == 'a')
assert(table.remove(a, 1) == 'b')
assert(#a == 0 and a.n == nil)
a = {10,20,30,40}
assert(a[#a] == 40)
assert(table.remove(a, #a) == 40)
assert(a[#a] == 30)
assert(table.remove(a, 2) == 20)
assert(a[#a] == 30 and #a == 2)
return "OK"

View File

@ -0,0 +1,31 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright (c) 2017 by Delphix. All rights reserved.
#
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
verify_runnable "global"
arch=$(uname -m)
if [[ "$arch" == "sparc64" ]]; then
log_note "Skipping lib_base and lib_coroutine on sparc64 to avoid stack overflow"
else
log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_base.lua
log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_coroutine.lua
fi
log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_strings.lua
log_must_program -m 40000000 $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_table.lua
log_pass "lua libraries work correctly."