aboutsummaryrefslogtreecommitdiff
path: root/ltests.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-08 11:54:21 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-08 11:54:21 -0300
commit748d6d4e7a1ac247071f6354f2700d1d0ee46b24 (patch)
treec7ad182b83e6fc021ea16d81c2ce4422f94016f3 /ltests.c
parente2ea3b31c94bb3e1da27c233661cb2a16699c685 (diff)
downloadlua-748d6d4e7a1ac247071f6354f2700d1d0ee46b24.tar.gz
lua-748d6d4e7a1ac247071f6354f2700d1d0ee46b24.tar.bz2
lua-748d6d4e7a1ac247071f6354f2700d1d0ee46b24.zip
Review of asserts in 'ltests.c'
The module 'ltests.c' must work correctly with asserts off, too.
Diffstat (limited to 'ltests.c')
-rw-r--r--ltests.c126
1 files changed, 70 insertions, 56 deletions
diff --git a/ltests.c b/ltests.c
index 2020131f..6920dd69 100644
--- a/ltests.c
+++ b/ltests.c
@@ -272,11 +272,15 @@ void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) {
272 272
273 273
274/* 274/*
275** {====================================================== 275** {=====================================================================
276** Functions to check memory consistency 276** Functions to check memory consistency.
277** ======================================================= 277** Most of these checks are done through asserts, so this code does
278** not make sense with asserts off. For this reason, it uses 'assert'
279** directly, instead of 'lua_assert'.
280** ======================================================================
278*/ 281*/
279 282
283#include <assert.h>
280 284
281/* 285/*
282** Check GC invariants. For incremental mode, a black object cannot 286** Check GC invariants. For incremental mode, a black object cannot
@@ -330,13 +334,23 @@ static int testobjref (global_State *g, GCObject *f, GCObject *t) {
330 return r1; 334 return r1;
331} 335}
332 336
333#define checkobjref(g,f,t) \ 337
334 { if (t) lua_longassert(testobjref(g,f,obj2gco(t))); } 338static void checkobjref (global_State *g, GCObject *f, GCObject *t) {
339 assert(testobjref(g, f, t));
340}
341
342
343/*
344** Version where 't' can be NULL. In that case, it should not apply the
345** macro 'obj2gco' over the object. ('t' may have several types, so this
346** definition must be a macro.) Most checks need this version, because
347** the check may run while an object is still being created.
348*/
349#define checkobjrefN(g,f,t) { if (t) checkobjref(g,f,obj2gco(t)); }
335 350
336 351
337static void checkvalref (global_State *g, GCObject *f, const TValue *t) { 352static void checkvalref (global_State *g, GCObject *f, const TValue *t) {
338 lua_assert(!iscollectable(t) || 353 assert(!iscollectable(t) || (righttt(t) && testobjref(g, f, gcvalue(t))));
339 (righttt(t) && testobjref(g, f, gcvalue(t))));
340} 354}
341 355
342 356
@@ -345,14 +359,14 @@ static void checktable (global_State *g, Table *h) {
345 unsigned int asize = luaH_realasize(h); 359 unsigned int asize = luaH_realasize(h);
346 Node *n, *limit = gnode(h, sizenode(h)); 360 Node *n, *limit = gnode(h, sizenode(h));
347 GCObject *hgc = obj2gco(h); 361 GCObject *hgc = obj2gco(h);
348 checkobjref(g, hgc, h->metatable); 362 checkobjrefN(g, hgc, h->metatable);
349 for (i = 0; i < asize; i++) 363 for (i = 0; i < asize; i++)
350 checkvalref(g, hgc, &h->array[i]); 364 checkvalref(g, hgc, &h->array[i]);
351 for (n = gnode(h, 0); n < limit; n++) { 365 for (n = gnode(h, 0); n < limit; n++) {
352 if (!isempty(gval(n))) { 366 if (!isempty(gval(n))) {
353 TValue k; 367 TValue k;
354 getnodekey(g->mainthread, &k, n); 368 getnodekey(g->mainthread, &k, n);
355 lua_assert(!keyisnil(n)); 369 assert(!keyisnil(n));
356 checkvalref(g, hgc, &k); 370 checkvalref(g, hgc, &k);
357 checkvalref(g, hgc, gval(n)); 371 checkvalref(g, hgc, gval(n));
358 } 372 }
@@ -363,30 +377,26 @@ static void checktable (global_State *g, Table *h) {
363static void checkudata (global_State *g, Udata *u) { 377static void checkudata (global_State *g, Udata *u) {
364 int i; 378 int i;
365 GCObject *hgc = obj2gco(u); 379 GCObject *hgc = obj2gco(u);
366 checkobjref(g, hgc, u->metatable); 380 checkobjrefN(g, hgc, u->metatable);
367 for (i = 0; i < u->nuvalue; i++) 381 for (i = 0; i < u->nuvalue; i++)
368 checkvalref(g, hgc, &u->uv[i].uv); 382 checkvalref(g, hgc, &u->uv[i].uv);
369} 383}
370 384
371 385
372/*
373** All marks are conditional because a GC may happen while the
374** prototype is still being created
375*/
376static void checkproto (global_State *g, Proto *f) { 386static void checkproto (global_State *g, Proto *f) {
377 int i; 387 int i;
378 GCObject *fgc = obj2gco(f); 388 GCObject *fgc = obj2gco(f);
379 checkobjref(g, fgc, f->source); 389 checkobjrefN(g, fgc, f->source);
380 for (i=0; i<f->sizek; i++) { 390 for (i=0; i<f->sizek; i++) {
381 if (ttisstring(f->k + i)) 391 if (iscollectable(f->k + i))
382 checkobjref(g, fgc, tsvalue(f->k + i)); 392 checkobjref(g, fgc, gcvalue(f->k + i));
383 } 393 }
384 for (i=0; i<f->sizeupvalues; i++) 394 for (i=0; i<f->sizeupvalues; i++)
385 checkobjref(g, fgc, f->upvalues[i].name); 395 checkobjrefN(g, fgc, f->upvalues[i].name);
386 for (i=0; i<f->sizep; i++) 396 for (i=0; i<f->sizep; i++)
387 checkobjref(g, fgc, f->p[i]); 397 checkobjrefN(g, fgc, f->p[i]);
388 for (i=0; i<f->sizelocvars; i++) 398 for (i=0; i<f->sizelocvars; i++)
389 checkobjref(g, fgc, f->locvars[i].varname); 399 checkobjrefN(g, fgc, f->locvars[i].varname);
390} 400}
391 401
392 402
@@ -401,11 +411,11 @@ static void checkCclosure (global_State *g, CClosure *cl) {
401static void checkLclosure (global_State *g, LClosure *cl) { 411static void checkLclosure (global_State *g, LClosure *cl) {
402 GCObject *clgc = obj2gco(cl); 412 GCObject *clgc = obj2gco(cl);
403 int i; 413 int i;
404 checkobjref(g, clgc, cl->p); 414 checkobjrefN(g, clgc, cl->p);
405 for (i=0; i<cl->nupvalues; i++) { 415 for (i=0; i<cl->nupvalues; i++) {
406 UpVal *uv = cl->upvals[i]; 416 UpVal *uv = cl->upvals[i];
407 if (uv) { 417 if (uv) {
408 checkobjref(g, clgc, uv); 418 checkobjrefN(g, clgc, uv);
409 if (!upisopen(uv)) 419 if (!upisopen(uv))
410 checkvalref(g, obj2gco(uv), uv->v); 420 checkvalref(g, obj2gco(uv), uv->v);
411 } 421 }
@@ -428,17 +438,17 @@ static void checkstack (global_State *g, lua_State *L1) {
428 StkId o; 438 StkId o;
429 CallInfo *ci; 439 CallInfo *ci;
430 UpVal *uv; 440 UpVal *uv;
431 lua_assert(!isdead(g, L1)); 441 assert(!isdead(g, L1));
432 if (L1->stack == NULL) { /* incomplete thread? */ 442 if (L1->stack == NULL) { /* incomplete thread? */
433 lua_assert(L1->openupval == NULL && L1->ci == NULL); 443 assert(L1->openupval == NULL && L1->ci == NULL);
434 return; 444 return;
435 } 445 }
436 for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next) 446 for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next)
437 lua_assert(upisopen(uv)); /* must be open */ 447 assert(upisopen(uv)); /* must be open */
438 lua_assert(L1->top <= L1->stack_last); 448 assert(L1->top <= L1->stack_last);
439 for (ci = L1->ci; ci != NULL; ci = ci->previous) { 449 for (ci = L1->ci; ci != NULL; ci = ci->previous) {
440 lua_assert(ci->top <= L1->stack_last); 450 assert(ci->top <= L1->stack_last);
441 lua_assert(lua_checkpc(ci)); 451 assert(lua_checkpc(ci));
442 } 452 }
443 for (o = L1->stack; o < L1->stack_last; o++) 453 for (o = L1->stack; o < L1->stack_last; o++)
444 checkliveness(L1, s2v(o)); /* entire stack must have valid values */ 454 checkliveness(L1, s2v(o)); /* entire stack must have valid values */
@@ -477,10 +487,10 @@ static void checkrefs (global_State *g, GCObject *o) {
477 } 487 }
478 case LUA_VSHRSTR: 488 case LUA_VSHRSTR:
479 case LUA_VLNGSTR: { 489 case LUA_VLNGSTR: {
480 lua_assert(!isgray(o)); /* strings are never gray */ 490 assert(!isgray(o)); /* strings are never gray */
481 break; 491 break;
482 } 492 }
483 default: lua_assert(0); 493 default: assert(0);
484 } 494 }
485} 495}
486 496
@@ -499,14 +509,14 @@ static void checkrefs (global_State *g, GCObject *o) {
499static void checkobject (global_State *g, GCObject *o, int maybedead, 509static void checkobject (global_State *g, GCObject *o, int maybedead,
500 int listage) { 510 int listage) {
501 if (isdead(g, o)) 511 if (isdead(g, o))
502 lua_assert(maybedead); 512 assert(maybedead);
503 else { 513 else {
504 lua_assert(g->gcstate != GCSpause || iswhite(o)); 514 assert(g->gcstate != GCSpause || iswhite(o));
505 if (g->gckind == KGC_GEN) { /* generational mode? */ 515 if (g->gckind == KGC_GEN) { /* generational mode? */
506 lua_assert(getage(o) >= listage); 516 assert(getage(o) >= listage);
507 lua_assert(!iswhite(o) || !isold(o)); 517 assert(!iswhite(o) || !isold(o));
508 if (isold(o)) { 518 if (isold(o)) {
509 lua_assert(isblack(o) || 519 assert(isblack(o) ||
510 getage(o) == G_TOUCHED1 || 520 getage(o) == G_TOUCHED1 ||
511 getage(o) == G_OLD0 || 521 getage(o) == G_OLD0 ||
512 o->tt == LUA_VTHREAD || 522 o->tt == LUA_VTHREAD ||
@@ -522,8 +532,8 @@ static lu_mem checkgraylist (global_State *g, GCObject *o) {
522 int total = 0; /* count number of elements in the list */ 532 int total = 0; /* count number of elements in the list */
523 ((void)g); /* better to keep it available if we need to print an object */ 533 ((void)g); /* better to keep it available if we need to print an object */
524 while (o) { 534 while (o) {
525 lua_assert(!!isgray(o) ^ (getage(o) == G_TOUCHED2)); 535 assert(!!isgray(o) ^ (getage(o) == G_TOUCHED2));
526 lua_assert(!testbit(o->marked, TESTBIT)); 536 assert(!testbit(o->marked, TESTBIT));
527 if (keepinvariant(g)) 537 if (keepinvariant(g))
528 l_setbit(o->marked, TESTBIT); /* mark that object is in a gray list */ 538 l_setbit(o->marked, TESTBIT); /* mark that object is in a gray list */
529 total++; 539 total++;
@@ -534,10 +544,10 @@ static lu_mem checkgraylist (global_State *g, GCObject *o) {
534 case LUA_VTHREAD: o = gco2th(o)->gclist; break; 544 case LUA_VTHREAD: o = gco2th(o)->gclist; break;
535 case LUA_VPROTO: o = gco2p(o)->gclist; break; 545 case LUA_VPROTO: o = gco2p(o)->gclist; break;
536 case LUA_VUSERDATA: 546 case LUA_VUSERDATA:
537 lua_assert(gco2u(o)->nuvalue > 0); 547 assert(gco2u(o)->nuvalue > 0);
538 o = gco2u(o)->gclist; 548 o = gco2u(o)->gclist;
539 break; 549 break;
540 default: lua_assert(0); /* other objects cannot be in a gray list */ 550 default: assert(0); /* other objects cannot be in a gray list */
541 } 551 }
542 } 552 }
543 return total; 553 return total;
@@ -569,13 +579,13 @@ static void incifingray (global_State *g, GCObject *o, lu_mem *count) {
569 return; /* gray lists not being kept in these phases */ 579 return; /* gray lists not being kept in these phases */
570 if (o->tt == LUA_VUPVAL) { 580 if (o->tt == LUA_VUPVAL) {
571 /* only open upvalues can be gray */ 581 /* only open upvalues can be gray */
572 lua_assert(!isgray(o) || upisopen(gco2upv(o))); 582 assert(!isgray(o) || upisopen(gco2upv(o)));
573 return; /* upvalues are never in gray lists */ 583 return; /* upvalues are never in gray lists */
574 } 584 }
575 /* these are the ones that must be in gray lists */ 585 /* these are the ones that must be in gray lists */
576 if (isgray(o) || getage(o) == G_TOUCHED2) { 586 if (isgray(o) || getage(o) == G_TOUCHED2) {
577 (*count)++; 587 (*count)++;
578 lua_assert(testbit(o->marked, TESTBIT)); 588 assert(testbit(o->marked, TESTBIT));
579 resetbit(o->marked, TESTBIT); /* prepare for next cycle */ 589 resetbit(o->marked, TESTBIT); /* prepare for next cycle */
580 } 590 }
581} 591}
@@ -588,22 +598,22 @@ static lu_mem checklist (global_State *g, int maybedead, int tof,
588 for (o = newl; o != survival; o = o->next) { 598 for (o = newl; o != survival; o = o->next) {
589 checkobject(g, o, maybedead, G_NEW); 599 checkobject(g, o, maybedead, G_NEW);
590 incifingray(g, o, &total); 600 incifingray(g, o, &total);
591 lua_assert(!tof == !tofinalize(o)); 601 assert(!tof == !tofinalize(o));
592 } 602 }
593 for (o = survival; o != old; o = o->next) { 603 for (o = survival; o != old; o = o->next) {
594 checkobject(g, o, 0, G_SURVIVAL); 604 checkobject(g, o, 0, G_SURVIVAL);
595 incifingray(g, o, &total); 605 incifingray(g, o, &total);
596 lua_assert(!tof == !tofinalize(o)); 606 assert(!tof == !tofinalize(o));
597 } 607 }
598 for (o = old; o != reallyold; o = o->next) { 608 for (o = old; o != reallyold; o = o->next) {
599 checkobject(g, o, 0, G_OLD1); 609 checkobject(g, o, 0, G_OLD1);
600 incifingray(g, o, &total); 610 incifingray(g, o, &total);
601 lua_assert(!tof == !tofinalize(o)); 611 assert(!tof == !tofinalize(o));
602 } 612 }
603 for (o = reallyold; o != NULL; o = o->next) { 613 for (o = reallyold; o != NULL; o = o->next) {
604 checkobject(g, o, 0, G_OLD); 614 checkobject(g, o, 0, G_OLD);
605 incifingray(g, o, &total); 615 incifingray(g, o, &total);
606 lua_assert(!tof == !tofinalize(o)); 616 assert(!tof == !tofinalize(o));
607 } 617 }
608 return total; 618 return total;
609} 619}
@@ -616,16 +626,16 @@ int lua_checkmemory (lua_State *L) {
616 lu_mem totalin; /* total of objects that are in gray lists */ 626 lu_mem totalin; /* total of objects that are in gray lists */
617 lu_mem totalshould; /* total of objects that should be in gray lists */ 627 lu_mem totalshould; /* total of objects that should be in gray lists */
618 if (keepinvariant(g)) { 628 if (keepinvariant(g)) {
619 lua_assert(!iswhite(g->mainthread)); 629 assert(!iswhite(g->mainthread));
620 lua_assert(!iswhite(gcvalue(&g->l_registry))); 630 assert(!iswhite(gcvalue(&g->l_registry)));
621 } 631 }
622 lua_assert(!isdead(g, gcvalue(&g->l_registry))); 632 assert(!isdead(g, gcvalue(&g->l_registry)));
623 lua_assert(g->sweepgc == NULL || issweepphase(g)); 633 assert(g->sweepgc == NULL || issweepphase(g));
624 totalin = checkgrays(g); 634 totalin = checkgrays(g);
625 635
626 /* check 'fixedgc' list */ 636 /* check 'fixedgc' list */
627 for (o = g->fixedgc; o != NULL; o = o->next) { 637 for (o = g->fixedgc; o != NULL; o = o->next) {
628 lua_assert(o->tt == LUA_VSHRSTR && isgray(o) && getage(o) == G_OLD); 638 assert(o->tt == LUA_VSHRSTR && isgray(o) && getage(o) == G_OLD);
629 } 639 }
630 640
631 /* check 'allgc' list */ 641 /* check 'allgc' list */
@@ -641,11 +651,11 @@ int lua_checkmemory (lua_State *L) {
641 for (o = g->tobefnz; o != NULL; o = o->next) { 651 for (o = g->tobefnz; o != NULL; o = o->next) {
642 checkobject(g, o, 0, G_NEW); 652 checkobject(g, o, 0, G_NEW);
643 incifingray(g, o, &totalshould); 653 incifingray(g, o, &totalshould);
644 lua_assert(tofinalize(o)); 654 assert(tofinalize(o));
645 lua_assert(o->tt == LUA_VUSERDATA || o->tt == LUA_VTABLE); 655 assert(o->tt == LUA_VUSERDATA || o->tt == LUA_VTABLE);
646 } 656 }
647 if (keepinvariant(g)) 657 if (keepinvariant(g))
648 lua_assert(totalin == totalshould); 658 assert(totalin == totalshould);
649 return 0; 659 return 0;
650} 660}
651 661
@@ -1042,6 +1052,7 @@ static int tref (lua_State *L) {
1042 luaL_checkany(L, 1); 1052 luaL_checkany(L, 1);
1043 lua_pushvalue(L, 1); 1053 lua_pushvalue(L, 1);
1044 lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX)); 1054 lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX));
1055 (void)level; /* to avoid warnings */
1045 lua_assert(lua_gettop(L) == level+1); /* +1 for result */ 1056 lua_assert(lua_gettop(L) == level+1); /* +1 for result */
1046 return 1; 1057 return 1;
1047} 1058}
@@ -1049,6 +1060,7 @@ static int tref (lua_State *L) {
1049static int getref (lua_State *L) { 1060static int getref (lua_State *L) {
1050 int level = lua_gettop(L); 1061 int level = lua_gettop(L);
1051 lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_checkinteger(L, 1)); 1062 lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_checkinteger(L, 1));
1063 (void)level; /* to avoid warnings */
1052 lua_assert(lua_gettop(L) == level+1); 1064 lua_assert(lua_gettop(L) == level+1);
1053 return 1; 1065 return 1;
1054} 1066}
@@ -1056,6 +1068,7 @@ static int getref (lua_State *L) {
1056static int unref (lua_State *L) { 1068static int unref (lua_State *L) {
1057 int level = lua_gettop(L); 1069 int level = lua_gettop(L);
1058 luaL_unref(L, LUA_REGISTRYINDEX, cast_int(luaL_checkinteger(L, 1))); 1070 luaL_unref(L, LUA_REGISTRYINDEX, cast_int(luaL_checkinteger(L, 1)));
1071 (void)level; /* to avoid warnings */
1059 lua_assert(lua_gettop(L) == level); 1072 lua_assert(lua_gettop(L) == level);
1060 return 0; 1073 return 0;
1061} 1074}
@@ -1724,6 +1737,7 @@ static struct X { int x; } x;
1724 else if EQ("tostring") { 1737 else if EQ("tostring") {
1725 const char *s = lua_tostring(L1, getindex); 1738 const char *s = lua_tostring(L1, getindex);
1726 const char *s1 = lua_pushstring(L1, s); 1739 const char *s1 = lua_pushstring(L1, s);
1740 (void)s1; /* to avoid warnings */
1727 lua_longassert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0); 1741 lua_longassert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0);
1728 } 1742 }
1729 else if EQ("type") { 1743 else if EQ("type") {
@@ -1937,15 +1951,15 @@ static void checkfinalmem (void) {
1937 1951
1938int luaB_opentests (lua_State *L) { 1952int luaB_opentests (lua_State *L) {
1939 void *ud; 1953 void *ud;
1954 lua_Alloc f = lua_getallocf(L, &ud);
1940 lua_atpanic(L, &tpanic); 1955 lua_atpanic(L, &tpanic);
1941 lua_setwarnf(L, &warnf, L); 1956 lua_setwarnf(L, &warnf, L);
1942 lua_pushboolean(L, 0); 1957 lua_pushboolean(L, 0);
1943 lua_setglobal(L, "_WARN"); /* _WARN = false */ 1958 lua_setglobal(L, "_WARN"); /* _WARN = false */
1944 regcodes(L); 1959 regcodes(L);
1945 atexit(checkfinalmem); 1960 atexit(checkfinalmem);
1946 lua_assert(lua_getallocf(L, &ud) == debug_realloc); 1961 lua_assert(f == debug_realloc && ud == cast_voidp(&l_memcontrol));
1947 lua_assert(ud == cast_voidp(&l_memcontrol)); 1962 lua_setallocf(L, f, ud); /* exercise this function */
1948 lua_setallocf(L, lua_getallocf(L, NULL), ud);
1949 luaL_newlib(L, tests_funcs); 1963 luaL_newlib(L, tests_funcs);
1950 return 1; 1964 return 1;
1951} 1965}