//============================================================================== ANKI_TEST(Util, Mutex) { Thread t0(nullptr), t1(nullptr); Mutex mtx; static const U ITERATIONS = 1000000; class In { public: I64 m_num = ITERATIONS; Mutex* m_mtx; }; In in; in.m_mtx = &mtx; t0.start(&in, [](Thread::Info& info) -> Error { In& in = *reinterpret_cast<In*>(info.m_userData); I64& num = in.m_num; Mutex& mtx = *in.m_mtx; for(U i = 0; i < ITERATIONS; i++) { mtx.lock(); num += 2; mtx.unlock(); } return ErrorCode::NONE; }); t1.start(&in, [](Thread::Info& info) -> Error { In& in = *reinterpret_cast<In*>(info.m_userData); I64& num = in.m_num; Mutex& mtx = *in.m_mtx; for(U i = 0; i < ITERATIONS; i++) { mtx.lock(); --num; mtx.unlock(); } return ErrorCode::NONE; }); ANKI_TEST_EXPECT_NO_ERR(t0.join()); ANKI_TEST_EXPECT_NO_ERR(t1.join()); ANKI_TEST_EXPECT_EQ(in.m_num, ITERATIONS * 2); }
ANKI_TEST(Util, Threadpool) { const U32 threadsCount = 4; const U32 repeat = 5; Threadpool* tp = new Threadpool(threadsCount); TestJobTP jobs[threadsCount]; for(U32 i = 1; i < repeat; i++) { U32 iterations = rand() % 100000; for(U32 j = 0; j < threadsCount; j++) { jobs[j].in = i; jobs[j].iterations = iterations; tp->assignNewTask(j, &jobs[j]); } ANKI_TEST_EXPECT_NO_ERR(tp->waitForAllThreadsToFinish()); for(U32 j = 0; j < threadsCount; j++) { ANKI_TEST_EXPECT_EQ(jobs[j].in, i + iterations); } } delete tp; }
//============================================================================== ANKI_TEST(Resource, ResourceFilesystem) { printf("Test requires the data dir\n"); HeapAllocator<U8> alloc(allocAligned, nullptr); ResourceFilesystem fs(alloc); { ANKI_TEST_EXPECT_NO_ERR(fs.addNewPath("data/dir/../dir/")); ResourceFilePtr file; ANKI_TEST_EXPECT_NO_ERR(fs.openFile("subdir0/hello.txt", file)); StringAuto txt(alloc); ANKI_TEST_EXPECT_NO_ERR(file->readAllText(alloc, txt)); ANKI_TEST_EXPECT_EQ(txt, "hello\n"); } { ANKI_TEST_EXPECT_NO_ERR(fs.addNewPath("./data/dir.ankizip")); ResourceFilePtr file; ANKI_TEST_EXPECT_NO_ERR(fs.openFile("subdir0/hello.txt", file)); StringAuto txt(alloc); ANKI_TEST_EXPECT_NO_ERR(file->readAllText(alloc, txt)); ANKI_TEST_EXPECT_EQ(txt, "hell\n"); } }
//============================================================================== ANKI_TEST(Util, Barrier) { // Simple test { Barrier b(2); Thread t(nullptr); t.start(&b, [](Thread::Info& info) -> Error { Barrier& b = *reinterpret_cast<Barrier*>(info.m_userData); b.wait(); return ErrorCode::NONE; }); b.wait(); ANKI_TEST_EXPECT_NO_ERR(t.join()); } }
ANKI_TEST(Resource, ResourceManager) { // Create Config config; HeapAllocator<U8> alloc(allocAligned, nullptr); ResourceManagerInitInfo rinit; rinit.m_gr = nullptr; rinit.m_config = &config; rinit.m_cacheDir = "/tmp/"; rinit.m_allocCallback = allocAligned; rinit.m_allocCallbackData = nullptr; ResourceManager* resources = alloc.newInstance<ResourceManager>(); ANKI_TEST_EXPECT_NO_ERR(resources->create(rinit)); // Very simple { DummyResourcePtr a; ANKI_TEST_EXPECT_NO_ERR(resources->loadResource("blah", a)); } // Load a resource { DummyResourcePtr a; ANKI_TEST_EXPECT_NO_ERR(resources->loadResource("blah", a)); { DummyResourcePtr b = a; a = b; b = a; } } // Load and load again { DummyResourcePtr a; ANKI_TEST_EXPECT_NO_ERR(resources->loadResource("blah", a)); auto refcount = a->getRefcount().load(); DummyResourcePtr b; ANKI_TEST_EXPECT_NO_ERR(resources->loadResource("blah", b)); ANKI_TEST_EXPECT_EQ(b->getRefcount().load(), a->getRefcount().load()); ANKI_TEST_EXPECT_EQ(a->getRefcount().load(), refcount + 1); ANKI_TEST_EXPECT_EQ(b.get(), a.get()); // Again DummyResourcePtr c; ANKI_TEST_EXPECT_NO_ERR(resources->loadResource("blah", c)); ANKI_TEST_EXPECT_EQ(a->getRefcount().load(), refcount + 2); // Load something else DummyResourcePtr d; ANKI_TEST_EXPECT_NO_ERR(resources->loadResource("blih", d)); ANKI_TEST_EXPECT_EQ(a->getRefcount().load(), refcount + 2); } // Error { { DummyResourcePtr a; ANKI_TEST_EXPECT_EQ(resources->loadResource("error", a), ErrorCode::USER_DATA); } { DummyResourcePtr a; ANKI_TEST_EXPECT_EQ(resources->loadResource("error", a), ErrorCode::USER_DATA); } } // Delete alloc.deleteInstance(resources); }
ANKI_TEST(Util, String) { HeapAllocator<U8> alloc(allocAligned, nullptr); // Copy { String a, b; a.create(alloc, "123"); b.create(alloc, a); ANKI_TEST_EXPECT_EQ(a, b); ANKI_TEST_EXPECT_EQ(b, "123"); b.destroy(alloc); a.destroy(alloc); b.create(alloc, "321"); a.create(alloc, b); ANKI_TEST_EXPECT_EQ(a, b); ANKI_TEST_EXPECT_EQ(a, "321"); b.destroy(alloc); a.destroy(alloc); } // Move { String a; a.create(alloc, "123"); String b(std::move(a)); ANKI_TEST_EXPECT_EQ(a.isEmpty(), true); ANKI_TEST_EXPECT_EQ(b, "123"); b.destroy(alloc); b.create(alloc, "321"); a = std::move(b); ANKI_TEST_EXPECT_EQ(a, "321"); ANKI_TEST_EXPECT_EQ(b.isEmpty(), true); a.destroy(alloc); } // Accessors { const char* s = "123"; String a; a.create(alloc, s); ANKI_TEST_EXPECT_EQ(a[0], '1'); ANKI_TEST_EXPECT_EQ(a[1], '2'); ANKI_TEST_EXPECT_EQ(a[2], '3'); U count = 0; for(char& c : a) { ++c; ++count; } ANKI_TEST_EXPECT_EQ(a, "234"); ANKI_TEST_EXPECT_EQ(count, 3); ANKI_TEST_EXPECT_EQ(a.begin(), &a[0]); ANKI_TEST_EXPECT_EQ(a.end(), &a[0] + 3); a.destroy(alloc); } // Append { String a, b; b.create(alloc, "123"); a.append(alloc, b); ANKI_TEST_EXPECT_EQ(a, "123"); a.append(alloc, "456789"); a.append(alloc, String()); a.append(alloc, ""); a.append(alloc, "0"); ANKI_TEST_EXPECT_EQ(a, "1234567890"); a.destroy(alloc); b.destroy(alloc); } // Compare { #define COMPARE(x_, y_, op_) \ a.append(alloc, x_); \ b.append(alloc, y_); \ ANKI_TEST_EXPECT_EQ(a op_ b, std::string(x_) op_ std::string(y_)) \ a.destroy(alloc); \ b.destroy(alloc); String a, b; COMPARE("123", "1233", <); COMPARE("0123", "1233", <=); COMPARE("ASDFA", "asdf90f", >); COMPARE(" %^*^^&", "aslkdfjb", >=); #undef COMPARE } // sprintf { String a; // Simple a.sprintf(alloc, "12%c %d", '3', 123); ANKI_TEST_EXPECT_EQ(a, "123 123"); a.destroy(alloc); // Extreme const char* s = "1234567890ABCDEF!@#$%^&*()_+asfghjkl:,.;ljk\"><{}[]/"; a.sprintf(alloc, "%s%s%s%s%s%s%s%s%s%s%s %d", s, s, s, s, s, s, s, s, s, s, s, 88); String b; for(U i = 0; i < 11; i++) { b.append(alloc, s); } b.append(alloc, " 88"); ANKI_TEST_EXPECT_EQ(a, b); ANKI_TEST_EXPECT_EQ(a.getLength(), b.getLength()); a.destroy(alloc); b.destroy(alloc); } // sprintf #2: Smaller result (will trigger another path) { String a; // Simple a.sprintf(alloc, "12%c %d", '3', 123); ANKI_TEST_EXPECT_EQ(a, "123 123"); a.destroy(alloc); // Extreme const char* s = "12345"; a.sprintf(alloc, "%s%s %d", s, s, 88); String b; for(U i = 0; i < 2; i++) { b.append(alloc, s); } b.append(alloc, " 88"); ANKI_TEST_EXPECT_EQ(a, b); ANKI_TEST_EXPECT_EQ(a.getLength(), b.getLength()); a.destroy(alloc); b.destroy(alloc); } // Other create { String a; a.create(alloc, '1', 3); ANKI_TEST_EXPECT_EQ(a, "111"); ANKI_TEST_EXPECT_EQ(a.getLength(), 3); a.destroy(alloc); } // toString { String a; a.toString(alloc, 123); ANKI_TEST_EXPECT_EQ(a, "123"); a.destroy(alloc); a.toString(alloc, 123.123); ANKI_TEST_EXPECT_EQ(a, "123.123000"); a.destroy(alloc); } // To number { I64 i; String a; a.create(alloc, "123456789"); ANKI_TEST_EXPECT_NO_ERR(a.toI64(i)); ANKI_TEST_EXPECT_EQ(i, 123456789); a.destroy(alloc); a.create(alloc, "-9223372036854775807"); ANKI_TEST_EXPECT_NO_ERR(a.toI64(i)); ANKI_TEST_EXPECT_EQ(i, -9223372036854775807); a.destroy(alloc); F64 f; a.create(alloc, "123456789.145"); ANKI_TEST_EXPECT_NO_ERR(a.toF64(f)); ANKI_TEST_EXPECT_EQ(f, 123456789.145); a.destroy(alloc); } }