void gc_test_alloc4(CuTest *T) { PN ptr = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN ptr2 = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN ptr3 = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN ptr4 = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN_SIZE count = potion_mark_stack(P, 0); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr)); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr2)); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr3)); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr4)); CuAssertIntEquals(T, "four allocations should be found", 5, count); }
void potion_test_empty(CuTest *T) { PN empty = PN_TUP0(); CuAssert(T, "empty isn't a tuple", PN_IS_TUPLE(empty)); CuAssert(T, "empty isn't a ref", PN_IS_PTR(empty)); CuAssertIntEquals(T, "tuple length is off", 0, PN_INT(potion_send(empty, potion_str(P, "length")))); }
/**\memberof PNFile \c "write" a binary representation of obj to the file handle. \param obj PNString, PNBytes, PNInteger (long or double), PNBoolean (char 0 or 1) \return PNInteger written bytes or PN_NIL */ PN potion_file_write(Potion *P, PN cl, pn_file self, PN obj) { long len = 0; char *ptr = NULL; union { double d; long l; char c; } tmp; //TODO: maybe extract ptr+len to seperate function if (!PN_IS_PTR(obj)) { if (!obj) return PN_NIL; //silent else if (PN_IS_INT(obj)) { tmp.l = PN_NUM(obj); len = sizeof(tmp); ptr = (char *)&tmp.l; } else if (PN_IS_BOOL(obj)) { tmp.c = (obj == PN_TRUE) ? 1 : 0; len = 1; ptr = (char *)&tmp.c; } else { assert(0 && "Invalid primitive type"); } } else { switch (PN_TYPE(obj)) { case PN_TSTRING: len = PN_STR_LEN(obj); ptr = PN_STR_PTR(obj); break; case PN_TBYTES: len = potion_send(obj, PN_STR("length")); ptr = PN_STR_PTR(obj); break; case PN_TNUMBER: { tmp.d = PN_DBL(obj); len = sizeof(tmp); ptr = (char *)&tmp.d; break; } default: return potion_type_error(P, obj); } } int r = write(self->fd, ptr, len); if (r == -1) return potion_io_error(P, "write"); return PN_NUM(r); }
void potion_test_int3(CuTest *T) { PN neg = PN_NUM(-4343); CuAssert(T, "negative numbers invalid", PN_INT(neg) == -4343); CuAssert(T, "negative not a number", PN_IS_INT(neg)); CuAssert(T, "negative is a ref", !PN_IS_PTR(neg)); CuAssert(T, "negative bad add", -3853 == PN_INT(potion_send(neg, potion_str(P, "+"), num))); }
void potion_test_int2(CuTest *T) { PN pos = PN_NUM(10891); CuAssert(T, "positive numbers invalid", PN_INT(pos) == 10891); CuAssert(T, "positive not a number", PN_IS_INT(pos)); CuAssert(T, "positive is a ref", !PN_IS_PTR(pos)); CuAssert(T, "positive bad add", 11381 == PN_INT(potion_send(pos, potion_str(P, "+"), num))); }
void potion_test_int1(CuTest *T) { PN zero = PN_ZERO; CuAssert(T, "zero isn't zero", PN_INT(zero) == 0); CuAssert(T, "zero isn't a number", PN_IS_INT(zero)); CuAssert(T, "zero is a ref", !PN_IS_PTR(zero)); CuAssert(T, "zero bad add", 490 == PN_INT(potion_send(zero, potion_str(P, "+"), num))); }
static inline char *potion_type_name(Potion *P, PN obj) { obj = potion_fwd(obj); return PN_IS_PTR(obj) ? AS_STR(potion_send(PN_VTABLE(PN_TYPE(obj)), PN_string)) : PN_IS_NIL(obj) ? "nil" : PN_IS_NUM(obj) ? "Number" : "Boolean"; }
void potion_test_tuple(CuTest *T) { PN tup = potion_tuple_with_size(P, 3); PN_TUPLE_AT(tup, 0) = PN_NIL; PN_TUPLE_AT(tup, 1) = PN_string; PN_TUPLE_AT(tup, 2) = tup; CuAssert(T, "tuple isn't a tuple", PN_IS_TUPLE(tup)); CuAssert(T, "tuple isn't a ref", PN_IS_PTR(tup)); CuAssertIntEquals(T, "tuple length is off", 3, PN_INT(potion_send(tup, potion_str(P, "length")))); }
// // Both this function and potion_gc_major embody a simple // Cheney loop (also called a "two-finger collector.") // http://en.wikipedia.org/wiki/Cheney%27s_algorithm // (Again, many thanks to Basile Starynkevitch for // his tutelage in this matter.) // static int potion_gc_minor(Potion *P, int sz) { struct PNMemory *M = P->mem; void *scanptr = 0; void **storead = 0, **wb = 0; if (sz < 0) sz = 0; else if (sz >= POTION_MAX_BIRTH_SIZE) return POTION_NO_MEM; scanptr = (void *) M->old_cur; info("running gc_minor\n" "(young: %p -> %p = %ld)\n" "(old: %p -> %p = %ld)\n" "(storeptr len = %ld)\n", M->birth_lo, M->birth_hi, (long)(M->birth_hi - M->birth_lo), M->old_lo, M->old_hi, (long)(M->old_hi - M->old_lo), (long)((void *)M->birth_hi - (void *)M->birth_storeptr)); potion_mark_stack(P, 1); GC_MINOR_STRINGS(); wb = (void **)M->birth_storeptr; for (storead = wb; storead < (void **)M->birth_hi; storead++) { PN v = (PN)*storead; if (PN_IS_PTR(v)) potion_mark_minor(P, (const struct PNObject *)v); } storead = 0; while ((PN)scanptr < (PN)M->old_cur) scanptr = potion_mark_minor(P, scanptr); scanptr = 0; sz += 2 * POTION_PAGESIZE; sz = max(sz, potion_birth_suggest(sz, M->old_lo, M->old_cur)); sz = NEW_BIRTH_REGION(M, wb, sz); M->minors++; info("(new young: %p -> %p = %d)\n", M->birth_lo, M->birth_hi, (long)(M->birth_hi - M->birth_lo)); return POTION_OK; }
void potion_test_str(CuTest *T) { CuAssert(T, "string isn't a string", PN_IS_STR(PN_string)); CuAssert(T, "string isn't a ref", PN_IS_PTR(PN_string)); CuAssert(T, "string length isn't working", 6 == PN_INT(potion_send(PN_string, potion_str(P, "length")))); }
void potion_test_bool(CuTest *T) { CuAssert(T, "true isn't a bool type", PN_TYPE(PN_TRUE) == PN_TBOOLEAN); CuAssert(T, "true is a ref", !PN_IS_PTR(PN_TRUE)); CuAssert(T, "false isn't a bool type", PN_TYPE(PN_FALSE) == PN_TBOOLEAN); CuAssert(T, "false is a ref", !PN_IS_PTR(PN_FALSE)); }
void potion_test_nil(CuTest *T) { CuAssert(T, "nil isn't a nil type", PN_TYPE(PN_NIL) == PN_TNIL); CuAssert(T, "nil is a ref", !PN_IS_PTR(PN_NIL)); CuAssert(T, "nil nil? is false", PN_TRUE == potion_send(PN_NIL, potion_str(P, "nil?"))); }
// // everything allocated in alloc1 and alloc4 tests goes out of scope, so will // not be moved to the old generation. data in the `forward` test will be copied. // void gc_test_alloc1(CuTest *T) { PN ptr = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN_SIZE count = potion_mark_stack(P, 0); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr)); CuAssertIntEquals(T, "only one allocation should be found", 2, count); }