1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
// SPDX-License-Identifier: BSL-1.0
#include <stdlib.h>
#ifndef BUNDLED_CATCH2
#ifdef CATCH3
#include "catch2/catch_all.hpp"
#else
#include "catch2/catch.hpp"
#endif
#else
#include "../third-party/catch.hpp"
#endif
#include <termpaint_hash.h>
template <typename X>
const unsigned char* u8p(X); // intentionally undefined
template <>
const unsigned char* u8p(const char *str) {
return (const unsigned char*)str;
}
struct termpaint_hash_test : public termpaint_hash_item {
int data;
};
TEST_CASE("hash: Add strings") {
termpaint_hash* hash = static_cast<termpaint_hash*>(calloc(1, sizeof(termpaint_hash)));
hash->item_size = sizeof(termpaint_hash_test);
for (int i = 0; i < 128; i++) {
std::string str = "test";
str += std::to_string(i + 1);
void *item = termpaintp_hash_ensure(hash, u8p(str.data()));
REQUIRE(hash->count == i + 1);
CHECK(item == termpaintp_hash_get(hash, u8p(str.data())));
}
termpaintp_hash_destroy(hash);
free(hash);
}
TEST_CASE("hash: Add and retrieve strings") {
termpaint_hash* hash = static_cast<termpaint_hash*>(calloc(1, sizeof(termpaint_hash)));
hash->item_size = sizeof(termpaint_hash_test);
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test1")))->data = 12;
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test2")))->data = 42;
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test3")))->data = 128;
REQUIRE(static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test2")))->data == 42);
// grow and rehash
for (int i = 0; i < 128; i++) {
std::string str = "test";
str += std::to_string(i + 1);
termpaintp_hash_ensure(hash, u8p(str.data()));
}
REQUIRE(static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test2")))->data == 42);
termpaintp_hash_destroy(hash);
free(hash);
}
TEST_CASE("hash: GC") {
termpaint_hash* hash = static_cast<termpaint_hash*>(calloc(1, sizeof(termpaint_hash)));
hash->item_size = sizeof(termpaint_hash_test);
hash->gc_mark_cb = [] (termpaint_hash* h) {
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(h, u8p("test1")))->unused = false;
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(h, u8p("test2")))->unused = false;
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(h, u8p("test3")))->unused = false;
};
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test1")))->data = 1;
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test2")))->data = 2;
static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test3")))->data = 3;
REQUIRE(static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test2")))->data == 2);
// add strings that are garbage collected instead of growing.
for (int i = 0; i < 128; i++) {
std::string str = "test";
str += std::to_string(i + 1);
termpaintp_hash_ensure(hash, u8p(str.data()));
}
CHECK(hash->allocated >= 3);
CHECK(hash->allocated <= 32);
REQUIRE(static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test1")))->data == 1);
REQUIRE(static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test2")))->data == 2);
REQUIRE(static_cast<termpaint_hash_test*>(termpaintp_hash_ensure(hash, u8p("test3")))->data == 3);
termpaintp_hash_destroy(hash);
free(hash);
}
|