int main() { tap_plan(11); tap_ok(1==1, "1==1"); tap_not_ok(1==2, "1==2"); tap_is(1, 1, "1 is 1"); tap_is('a', 'a', "'a' is 'a'"); tap_is(4.0, 4.0, "4.0 is 4.0"); tap_isnt(1, 2, "1 isn't 2"); tap_isnt('a', 'b', "'a' isn't 'b'"); tap_isnt(2.0, 4.0, "2.0 isn't 4.0"); tap_like("foobar", "^foo", REG_EXTENDED, "\"foobar\" is like \"^foo\""); tap_unlike("foobar", "foo$", REG_EXTENDED, "\"foobar\" is unlike \"foo$\""); tap_pass("just passing"); return tap_status(); }
int main(int argc, char **argv) { tap_n((3+5)*4 + (2+5)*2 + (2+5)); if (argc > 1) { long s = atol(argv[1]); init_by_array((uint32_t*)&s, sizeof s / sizeof(uint32_t)); } else { time_t s = time(NULL); init_by_array((uint32_t*)&s, sizeof s / sizeof(uint32_t)); } void *data = malloc(DATA_LEN); random_fill(data, DATA_LEN); const size_t codepoints = DATA_LEN * CHAR_BIT / 21; const mushcell pos = MUSHCELL_MAX - WRAP_AFTER; mushcoords beg = MUSHCOORDS(pos,pos,pos), end; void *space_buf = malloc(mushspace_sizeof); mushspace *space; bool ok; mushbounds bounds, expected_loose, expected_tight; size_t spaces_beg, spaces_end; codepoint_reader cp_reader; #define BOUNDS_CHECK \ mushspace_get_loose_bounds(space, &bounds); \ \ tap_leqcos(bounds.beg, expected_loose.beg, \ "get_loose_bounds reports appropriate beg", \ "get_loose_bounds reports too large beg"); \ tap_geqcos(bounds.end, expected_loose.end, \ "get_loose_bounds reports appropriate end", \ "get_loose_bounds reports too small end"); \ \ ok = mushspace_get_tight_bounds(space, &bounds); \ tap_bool(ok, "get_tight_bounds says that the space is nonempty", \ "get_tight_bounds says that the space is empty"); \ \ tap_eqcos(bounds.beg, expected_tight.beg, \ "get_tight_bounds reports correct beg", \ "get_tight_bounds reports incorrect beg"); \ tap_eqcos(bounds.end, expected_tight.end, \ "get_tight_bounds reports correct end", \ "get_tight_bounds reports incorrect end"); \ #define LOAD_STRING(suf, T, ENCODER, BLOWUP, FOREACH_CP) \ space = mushspace_init(space_buf, NULL); \ if (!space) { \ tap_not_ok("init returned null"); \ tap_skip_remaining("init failed"); \ return 1; \ } \ tap_ok("init succeeded"); \ \ T *encoded_data##suf = (T*)data; \ size_t encoded_len##suf = DATA_LEN / sizeof *encoded_data##suf; \ if (BLOWUP) { \ encoded_data##suf = \ malloc((codepoints * BLOWUP) * sizeof *encoded_data##suf); \ encoded_len##suf = ENCODER(data, encoded_data##suf, codepoints); \ } \ \ mushspace_load_string##suf( \ space, encoded_data##suf, encoded_len##suf, &end, beg, true); \ \ if (BLOWUP) \ free(encoded_data##suf); \ \ size_t ii##suf = 0; \ mushcell cp##suf; \ \ spaces_beg = 0; \ spaces_end = 0; \ \ FOREACH_CP(suf) { \ if (ii##suf <= WRAP_AFTER) { \ if (cp##suf == ' ') \ ++spaces_end; \ else \ spaces_end = 0; \ continue; \ } \ if (cp##suf == ' ') \ ++spaces_beg; \ else \ break; \ } \ \ expected_loose.beg = expected_tight.beg = \ MUSHCOORDS(MUSHCELL_MIN, beg.y, beg.z); \ expected_loose.end = expected_tight.end = \ MUSHCOORDS(MUSHCELL_MAX, beg.y, beg.z); \ \ expected_loose.beg.x = expected_tight.beg.x += spaces_beg; \ expected_loose.end.x = expected_tight.end.x -= spaces_end; \ \ tap_eqcos(end, expected_tight.end, \ "load_string" #suf " reports correct end", \ "load_string" #suf " reports incorrect end"); \ \ ok = true; \ FOREACH_CP(suf) { \ mushcell gc = \ mushspace_get(space, mushcoords_add(beg, MUSHCOORDS(ii##suf,0,0))); \ if (gc == cp##suf) \ continue; \ ok = false; \ tap_not_ok("get doesn't match data given to load_string" #suf); \ printf(" ---\n" \ " failed index: %zu\n" \ " expected: %" MUSHCELL_PRIx "\n" \ " got: %" MUSHCELL_PRIx "\n" \ " ...\n", \ ii##suf, cp##suf, gc); \ break; \ } \ if (ok) \ tap_ok("get matches data given to load_string" #suf); \ \ BOUNDS_CHECK; \ mushspace_free(space); #define DIRECT_FOREACH_CP(s) \ ii##s = 0; \ for (; ii##s < encoded_len##s && (cp##s = encoded_data##s[ii##s], true); \ ++ii##s) #define READER_FOREACH_CP(s) \ cp_reader = make_codepoint_reader(data, codepoints); \ for (ii##s = 0; (cp##s = next_codepoint(&cp_reader)) != UINT32_MAX; ++ii##s) LOAD_STRING(, unsigned char, dummy, 0, DIRECT_FOREACH_CP); LOAD_STRING(_cell, mushcell, dummy, 0, DIRECT_FOREACH_CP); LOAD_STRING(_utf8, uint8_t, encode_utf8, 4, READER_FOREACH_CP); LOAD_STRING(_utf16, uint16_t, encode_utf16, 2, READER_FOREACH_CP); const mushcell *data_cell = (const mushcell*)data; const size_t data_cell_count = DATA_LEN / sizeof *data_cell; spaces_beg = 0; spaces_end = 0; for (size_t i = WRAP_AFTER+1; i < data_cell_count && data_cell[i++] == ' ';) ++spaces_beg; for (size_t i = WRAP_AFTER+1; i-- > 0 && data_cell[i] == ' ';) ++spaces_end; expected_loose.beg = expected_tight.beg = MUSHCOORDS(MUSHCELL_MIN, beg.y, beg.z); expected_loose.end = expected_tight.end = MUSHCOORDS(MUSHCELL_MAX, beg.y, beg.z); expected_loose.beg.x = expected_tight.beg.x += spaces_beg; expected_loose.end.x = expected_tight.end.x -= spaces_beg; #define PUT(FOREACH_CELL, S) \ space = mushspace_init(space_buf, NULL); \ if (!space) { \ tap_not_ok("init returned null"); \ tap_skip_remaining("init failed"); \ return 1; \ } \ tap_ok("init succeeded"); \ FOREACH_CELL { \ mushspace_put(space, mushcoords_add(beg, MUSHCOORDS(i, 0, 0)), \ data_cell[i]); \ } \ \ ok = true; \ for (size_t i = 0; i < data_cell_count; ++i) { \ mushcell dc = data_cell[i], \ gc = mushspace_get(space, \ mushcoords_add(beg, MUSHCOORDS(i, 0, 0))); \ if (gc == dc) \ continue; \ ok = false; \ tap_not_ok("get doesn't match what was put" S); \ printf(" ---\n" \ " failed index: %zu\n" \ " expected: %" MUSHCELL_PRIx "\n" \ " got: %" MUSHCELL_PRIx "\n" \ " ...\n", \ i, dc, gc); \ break; \ } \ if (ok) \ tap_ok("get matches what was put" S); \ \ BOUNDS_CHECK; #define FORWARD for (size_t i = 0; i < data_cell_count; ++i) #define REVERSE for (size_t i = data_cell_count; i--;) PUT(FORWARD, " (forward order)"); mushspace_free(space); PUT(REVERSE, " (reverse order)"); if (!ok) { tap_skip_remaining("won't copy bad space"); return 1; } void *space_buf2 = malloc(mushspace_sizeof); mushspace *space2 = mushspace_copy(space_buf2, space, NULL); mushspace_free(space); free(space_buf); space = space2; if (!space) { tap_not_ok("copy returned null"); tap_skip_remaining("copy failed"); return 1; } tap_ok("copy succeeded"); ok = true; for (size_t i = 0; i < DATA_LEN / sizeof *data_cell; ++i) { mushcell dc = data_cell[i], gc = mushspace_get(space, mushcoords_add(beg, MUSHCOORDS(i, 0, 0))); if (gc == dc) continue; ok = false; tap_not_ok("get in copy doesn't match data"); printf(" ---\n" " failed index: %zu\n" " expected: %" MUSHCELL_PRIx "\n" " got: %" MUSHCELL_PRIx "\n" " ...\n", i, dc, gc); break; } if (ok) tap_ok("get in copy matched data"); BOUNDS_CHECK; free(data); mushspace_free(space); free(space_buf2); }
int main(int argc, char **argv) { // We don't check bounds here: we'd end up essentially duplicating the logic // from load_string, and there's little point in that. tap_n(2*4 + 2*2 + 2); if (argc > 1) { long s = atol(argv[1]); init_by_array((uint32_t*)&s, sizeof s / sizeof(uint32_t)); } else { time_t s = time(NULL); init_by_array((uint32_t*)&s, sizeof s / sizeof(uint32_t)); } void *data = malloc(DATA_LEN); random_fill(data, DATA_LEN); const size_t codepoints = DATA_LEN * CHAR_BIT / 21; mushcoords beg = MUSHCOORDS(MUSHCELL_MAX-WRAP_AFTER, MUSHCELL_MAX-WRAP_AFTER, MUSHCELL_MAX-WRAP_AFTER), end; void *space_buf = malloc(mushspace_sizeof); mushspace *space; bool ok; codepoint_reader cp_reader; mushcoords pos, pos_next; bool cr; #define POS_INIT \ pos_next = beg; \ cr = false; #define CP_POS(cp) \ pos = pos_next; \ switch (cp) { \ default: \ if (MUSHSPACE_DIM > 1 && cr) { \ cr = false; \ pos = MUSHCOORDS(beg.x, pos.y + 1, pos.z); \ } \ pos_next = MUSHCOORDS(pos.x + 1, pos.y, pos.z); \ break; \ case '\r': \ if (MUSHSPACE_DIM > 1) { \ if (cr) \ pos_next = pos = MUSHCOORDS(beg.x, pos.y + 1, pos.z); \ cr = true; \ } \ continue; \ case '\n': \ if (MUSHSPACE_DIM > 1) { \ cr = false; \ pos_next = pos = MUSHCOORDS(beg.x, pos.y + 1, pos.z); \ } \ continue; \ case '\f': \ if (MUSHSPACE_DIM > 2) { \ cr = false; \ pos_next = pos = MUSHCOORDS(beg.x, beg.y, pos.z + 1); \ } else if (cr) { \ cr = false; \ pos_next = pos = MUSHCOORDS(beg.x, pos.y + 1, pos.z); \ } \ continue; \ } #define LOAD_STRING(suf, T, ENCODER, BLOWUP, FOREACH_CP) \ space = mushspace_init(space_buf, NULL); \ if (!space) { \ tap_not_ok("init returned null"); \ tap_skip_remaining("init failed"); \ return 1; \ } \ tap_ok("init succeeded"); \ \ T *encoded_data##suf = (T*)data; \ size_t encoded_len##suf = DATA_LEN / sizeof *encoded_data##suf; \ if (BLOWUP) { \ encoded_data##suf = \ malloc((codepoints * BLOWUP) * sizeof *encoded_data##suf); \ encoded_len##suf = ENCODER(data, encoded_data##suf, codepoints); \ } \ \ mushspace_load_string##suf( \ space, encoded_data##suf, encoded_len##suf, &end, beg, false); \ \ if (BLOWUP) \ free(encoded_data##suf); \ \ ok = true; \ POS_INIT; \ FOREACH_CP(suf) { \ CP_POS(cp##suf); \ mushcell gc = mushspace_get(space, pos); \ if (gc == cp##suf) \ continue; \ ok = false; \ tap_not_ok("get doesn't match data given to load_string" #suf); \ printf(" ---\n" \ " expected: %" MUSHCELL_PRIx "\n" \ " got: %" MUSHCELL_PRIx "\n" \ " failed index: %zu\n", \ cp##suf, gc, ii##suf); \ printf(" failed pos relative to min: ("); \ for (uint8_t i = 0; i < MUSHSPACE_DIM; ++i) \ printf(" %" MUSHCELL_PRId, mushcell_sub(pos.v[i], MUSHCELL_MIN)); \ printf(" )\n" \ " ...\n"); \ break; \ } \ if (ok) \ tap_ok("get matches data given to load_string" #suf); \ \ mushspace_free(space); #define DIRECT_FOREACH_CP(s) \ mushcell cp##s; \ size_t ii##s = 0; \ for (; ii##s < encoded_len##s && (cp##s = encoded_data##s[ii##s], true); \ ++ii##s) #define READER_FOREACH_CP(s) \ cp_reader = make_codepoint_reader(data, codepoints); \ size_t ii##s = 0; \ for (mushcell cp##s; (cp##s = next_codepoint(&cp_reader)) != UINT32_MAX; \ ++ii##s) LOAD_STRING(, unsigned char, dummy, 0, DIRECT_FOREACH_CP); LOAD_STRING(_cell, mushcell, dummy, 0, DIRECT_FOREACH_CP); LOAD_STRING(_utf8, uint8_t, encode_utf8, 4, READER_FOREACH_CP); LOAD_STRING(_utf16, uint16_t, encode_utf16, 2, READER_FOREACH_CP); const mushcell *data_cell = (const mushcell*)data; const size_t data_cell_count = DATA_LEN / sizeof *data_cell; mushcoords *saved_pos = malloc(data_cell_count * sizeof *saved_pos); #define PUT(FOREACH_CELL, S, GET_POS, SAVE_POS) \ space = mushspace_init(space_buf, NULL); \ if (!space) { \ tap_not_ok("init returned null"); \ tap_skip_remaining("init failed"); \ free(saved_pos); \ return 1; \ } \ tap_ok("init succeeded"); \ POS_INIT; \ FOREACH_CELL { \ GET_POS(data_cell[i]); \ if (SAVE_POS) \ saved_pos[i] = pos; \ mushspace_put(space, pos, data_cell[i]); \ } \ \ ok = true; \ POS_INIT; \ for (size_t i = 0; i < data_cell_count; ++i) { \ mushcell dc = data_cell[i]; \ GET_POS(dc); \ mushcell gc = mushspace_get(space, pos); \ if (gc == dc) \ continue; \ ok = false; \ tap_not_ok("get doesn't match what was put" S); \ printf(" ---\n" \ " failed index: %zu\n" \ " expected: %" MUSHCELL_PRIx "\n" \ " got: %" MUSHCELL_PRIx "\n", \ i, dc, gc); \ printf(" failed pos relative to min: ("); \ for (uint8_t j = 0; j < MUSHSPACE_DIM; ++j) \ printf(" %" MUSHCELL_PRId, mushcell_sub(pos.v[j], MUSHCELL_MIN)); \ printf(" )\n" \ " ...\n"); \ break; \ } \ if (ok) \ tap_ok("get matches what was put" S); #define FORWARD for (size_t i = 0; i < data_cell_count; ++i) #define REVERSE for (size_t i = data_cell_count; i--;) #define SAVED_POS(_) pos = saved_pos[i]; PUT(FORWARD, " (forward order)", CP_POS, true); mushspace_free(space); PUT(REVERSE, " (reverse order)", SAVED_POS, false); free(saved_pos); if (!ok) { tap_skip_remaining("won't copy bad space"); return 1; } void *space_buf2 = malloc(mushspace_sizeof); mushspace *space2 = mushspace_copy(space_buf2, space, NULL); mushspace_free(space); free(space_buf); space = space2; if (!space) { tap_not_ok("copy returned null"); tap_skip_remaining("copy failed"); return 1; } tap_ok("copy succeeded"); ok = true; POS_INIT; for (size_t i = 0; i < DATA_LEN / sizeof *data_cell; ++i) { mushcell dc = data_cell[i]; CP_POS(dc); mushcell gc = mushspace_get(space, pos); if (gc == dc) continue; ok = false; tap_not_ok("get in copy doesn't match data"); printf(" ---\n" " failed index: %zu\n" " expected: %" MUSHCELL_PRIx "\n" " got: %" MUSHCELL_PRIx "\n", i, dc, gc); printf(" failed pos relative to min: ("); for (uint8_t j = 0; j < MUSHSPACE_DIM; ++j) printf(" %" MUSHCELL_PRId, mushcell_sub(pos.v[j], MUSHCELL_MIN)); \ printf(" )\n" " ...\n"); break; } if (ok) tap_ok("get in copy matched data"); free(data); mushspace_free(space); free(space_buf2); }