See More

#include #include #include #include #include #include using LCompilers::TRY; using LCompilers::Result; using LCompilers::LPython::BigInt::is_int_ptr; using LCompilers::LPython::BigInt::ptr_to_int; using LCompilers::LPython::BigInt::int_to_ptr; using LCompilers::LPython::BigInt::string_to_largeint; using LCompilers::LPython::BigInt::largeint_to_string; using LCompilers::LPython::BigInt::MAX_SMALL_INT; using LCompilers::LPython::BigInt::MIN_SMALL_INT; // Print any vector like iterable to a string template inline std::ostream &print_vec(std::ostream &out, T &d) { out << "["; for (auto p = d.begin(); p != d.end(); p++) { if (p != d.begin()) out << ", "; out << *p; } out << "]"; return out; } namespace doctest { // Convert std::vector to string for doctest template struct StringMaker<:vector>> { static String convert(const std::vector &value) { std::ostringstream oss; print_vec(oss, value); return oss.str().c_str(); } }; } class TokenizerError0 { }; TEST_CASE("Test Big Int") { int64_t i; void *p, *p2; /* Integer tests */ i = 0; CHECK(!is_int_ptr(i)); i = 5; CHECK(!is_int_ptr(i)); i = -5; CHECK(!is_int_ptr(i)); // Largest integer that is allowed is 2^62-1 i = 4611686018427387903LL; CHECK(i == MAX_SMALL_INT); CHECK(!is_int_ptr(i)); // this is an integer i = 4611686018427387904LL; CHECK(is_int_ptr(i)); // this is a pointer // Smallest integer that is allowed is -2^63 i = -9223372036854775808ULL; CHECK(i == MIN_SMALL_INT); CHECK(!is_int_ptr(i)); // this is an integer i = -9223372036854775809ULL; // This does not fit into a signed 64bit int CHECK(is_int_ptr(i)); // this is a pointer /* Pointer tests */ // Smallest pointer value is 0 (nullptr) p = nullptr; i = ptr_to_int(p); CHECK(is_int_ptr(i)); p2 = int_to_ptr(i); CHECK(p == p2); // Second smallest pointer value aligned to 4 is 4 p = (void*)4; i = ptr_to_int(p); CHECK(is_int_ptr(i)); p2 = int_to_ptr(i); CHECK(p == p2); // Maximum pointer value aligned to 4 is (2^64-1)-3 p = (void*)18446744073709551612ULL; i = ptr_to_int(p); CHECK(is_int_ptr(i)); p2 = int_to_ptr(i); CHECK(p == p2); /* Big int tests */ Allocator al(1024); LCompilers::Str s; char *cs; s.from_str(al, "123"); i = string_to_largeint(al, s); CHECK(is_int_ptr(i)); cs = largeint_to_string(i); CHECK(std::string(cs) == "123"); s.from_str(al, "123567890123456789012345678901234567890"); i = string_to_largeint(al, s); CHECK(is_int_ptr(i)); cs = largeint_to_string(i); CHECK(std::string(cs) == "123567890123456789012345678901234567890"); } TEST_CASE("Test LCompilers::Vec") { Allocator al(1024); LCompilers::Vec v; v.reserve(al, 2); CHECK(v.size() == 0); CHECK(v.capacity() == 2); v.push_back(al, 1); CHECK(v.size() == 1); CHECK(v.capacity() == 2); CHECK(v.p[0] == 1); CHECK(v[0] == 1); v.push_back(al, 2); CHECK(v.size() == 2); CHECK(v.capacity() == 2); CHECK(v.p[0] == 1); CHECK(v.p[1] == 2); CHECK(v[0] == 1); CHECK(v[1] == 2); v.push_back(al, 3); CHECK(v.size() == 3); CHECK(v.capacity() == 4); CHECK(v.p[0] == 1); CHECK(v.p[1] == 2); CHECK(v.p[2] == 3); CHECK(v[0] == 1); CHECK(v[1] == 2); CHECK(v[2] == 3); v.push_back(al, 4); CHECK(v.size() == 4); CHECK(v.capacity() == 4); CHECK(v.p[0] == 1); CHECK(v.p[1] == 2); CHECK(v.p[2] == 3); CHECK(v.p[3] == 4); CHECK(v[0] == 1); CHECK(v[1] == 2); CHECK(v[2] == 3); CHECK(v[3] == 4); v.push_back(al, 5); CHECK(v.size() == 5); CHECK(v.capacity() == 8); CHECK(v.p[0] == 1); CHECK(v.p[1] == 2); CHECK(v.p[2] == 3); CHECK(v.p[3] == 4); CHECK(v.p[4] == 5); CHECK(v[0] == 1); CHECK(v[1] == 2); CHECK(v[2] == 3); CHECK(v[3] == 4); CHECK(v[4] == 5); std::vector sv = v.as_vector(); CHECK(sv.size() == 5); CHECK(&(sv[0]) != &(v.p[0])); CHECK(sv[0] == 1); CHECK(sv[1] == 2); CHECK(sv[2] == 3); CHECK(sv[3] == 4); CHECK(sv[4] == 5); } TEST_CASE("LCompilers::Vec iterators") { Allocator al(1024); LCompilers::Vec v; v.reserve(al, 2); v.push_back(al, 1); v.push_back(al, 2); v.push_back(al, 3); v.push_back(al, 4); // Check reference (auto) int i = 0; for (auto &a : v) { i += a; } CHECK(i == 10); // Check reference (must be const) i = 0; for (const int &a : v) { i += a; } CHECK(i == 10); // Check direct type (auto) i = 0; for (auto a : v) { i += a; } CHECK(i == 10); // Check direct type (const) i = 0; for (const int a : v) { i += a; } CHECK(i == 10); // Check direct type (non const) i = 0; for (int a : v) { i += a; } CHECK(i == 10); } TEST_CASE("Test LCompilers::Str") { Allocator al(1024); LCompilers::Str s; const char *data = "Some string."; s.p = const_cast(data); s.n = 2; CHECK(s.size() == 2); CHECK(s.p == data); CHECK(s.str() == "So"); std::string scopy = s.str(); CHECK(s.p != &scopy[0]); CHECK(scopy == "So"); CHECK(scopy[0] == 'S'); CHECK(scopy[1] == 'o'); CHECK(scopy[2] == '\x00'); char *copy = s.c_str(al); CHECK(s.p != copy); CHECK(copy[0] == 'S'); CHECK(copy[1] == 'o'); CHECK(copy[2] == '\x00'); } TEST_CASE("Test LCompilers::Allocator") { Allocator al(32); // Size is what we asked (32) plus alignment (8) = 40 CHECK(al.size_total() == 40); // Fits in the pre-allocated chunk al.alloc(32); CHECK(al.size_total() == 40); // Chunk doubles al.alloc(32); CHECK(al.size_total() == 80); // Chunk doubles al.alloc(90); CHECK(al.size_total() == 160); // We asked more than can fit in the doubled chunk (2*160), // so the chunk will be equal to what we asked (1024) plus alignment (8) al.alloc(1024); CHECK(al.size_total() == 1032); } TEST_CASE("Test LCompilers::Allocator 2") { Allocator al(32); int *p = al.allocate(); p[0] = 5; p = al.allocate(3); p[0] = 1; p[1] = 2; p[2] = 3; std::vector *v = al.make_new<:vector>>(5); CHECK(v->size() == 5); // Must manually call the destructor: v->~vector(); }