aboutsummaryrefslogtreecommitdiff
path: root/test/pthreadpool.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/pthreadpool.cc')
-rw-r--r--test/pthreadpool.cc111
1 files changed, 111 insertions, 0 deletions
diff --git a/test/pthreadpool.cc b/test/pthreadpool.cc
new file mode 100644
index 0000000..e1c2559
--- /dev/null
+++ b/test/pthreadpool.cc
@@ -0,0 +1,111 @@
+#include <gtest/gtest.h>
+
+#include <pthreadpool.h>
+
+const size_t itemsCount1D = 1024;
+
+TEST(SetupAndShutdown, Basic) {
+ pthreadpool* threadpool = pthreadpool_create(0);
+ EXPECT_TRUE(threadpool != nullptr);
+ pthreadpool_destroy(threadpool);
+}
+
+static void computeNothing1D(void*, size_t) {
+}
+
+TEST(Compute1D, Basic) {
+ pthreadpool* threadpool = pthreadpool_create(0);
+ EXPECT_TRUE(threadpool != nullptr);
+ pthreadpool_compute_1d(threadpool, computeNothing1D, NULL, itemsCount1D);
+ pthreadpool_destroy(threadpool);
+}
+
+static void checkRange1D(void*, size_t itemId) {
+ EXPECT_LT(itemId, itemsCount1D);
+}
+
+TEST(Compute1D, ValidRange) {
+ pthreadpool* threadpool = pthreadpool_create(0);
+ EXPECT_TRUE(threadpool != nullptr);
+ pthreadpool_compute_1d(threadpool, checkRange1D, NULL, itemsCount1D);
+ pthreadpool_destroy(threadpool);
+}
+
+static void setTrue1D(bool indicators[], size_t itemId) {
+ indicators[itemId] = true;
+}
+
+TEST(Compute1D, AllItemsProcessed) {
+ bool processed[itemsCount1D];
+ memset(processed, 0, sizeof(processed));
+
+ pthreadpool* threadpool = pthreadpool_create(0);
+ EXPECT_TRUE(threadpool != nullptr);
+ pthreadpool_compute_1d(threadpool, reinterpret_cast<pthreadpool_function_1d_t>(setTrue1D), processed, itemsCount1D);
+ for (size_t itemId = 0; itemId < itemsCount1D; itemId++) {
+ EXPECT_TRUE(processed[itemId]) << "Item " << itemId << " not processed";
+ }
+ pthreadpool_destroy(threadpool);
+}
+
+static void increment1D(int counters[], size_t itemId) {
+ counters[itemId] += 1;
+}
+
+TEST(Compute1D, EachItemProcessedOnce) {
+ int processedCount[itemsCount1D];
+ memset(processedCount, 0, sizeof(processedCount));
+
+ pthreadpool* threadpool = pthreadpool_create(0);
+ EXPECT_TRUE(threadpool != nullptr);
+ pthreadpool_compute_1d(threadpool, reinterpret_cast<pthreadpool_function_1d_t>(increment1D), processedCount, itemsCount1D);
+ for (size_t itemId = 0; itemId < itemsCount1D; itemId++) {
+ EXPECT_EQ(1, processedCount[itemId]) << "Item " << itemId << " processed " << processedCount[itemId] << " times";
+ }
+ pthreadpool_destroy(threadpool);
+}
+
+TEST(Compute1D, EachItemProcessedMultipleTimes) {
+ int processedCount[itemsCount1D];
+ memset(processedCount, 0, sizeof(processedCount));
+ const size_t iterations = 100;
+
+ pthreadpool* threadpool = pthreadpool_create(0);
+ EXPECT_TRUE(threadpool != nullptr);
+
+ for (size_t iteration = 0; iteration < iterations; iteration++) {
+ pthreadpool_compute_1d(threadpool, reinterpret_cast<pthreadpool_function_1d_t>(increment1D), processedCount, itemsCount1D);
+ }
+ for (size_t itemId = 0; itemId < itemsCount1D; itemId++) {
+ EXPECT_EQ(iterations, processedCount[itemId]) << "Item " << itemId << " processed " << processedCount[itemId] << " times";
+ }
+ pthreadpool_destroy(threadpool);
+}
+
+static void workImbalance1D(volatile size_t* computedItems, size_t itemId) {
+ __sync_fetch_and_add(computedItems, 1);
+ if (itemId == 0) {
+ /* Wait until all items are computed */
+ while (*computedItems != itemsCount1D) {
+ __sync_synchronize();
+ }
+ }
+}
+
+TEST(Compute1D, WorkStealing) {
+ volatile size_t computedItems = 0;
+
+ pthreadpool* threadpool = pthreadpool_create(0);
+ EXPECT_TRUE(threadpool != nullptr);
+
+ pthreadpool_compute_1d(threadpool, reinterpret_cast<pthreadpool_function_1d_t>(workImbalance1D), reinterpret_cast<void*>(const_cast<size_t*>(&computedItems)), itemsCount1D);
+ EXPECT_EQ(computedItems, itemsCount1D);
+
+ pthreadpool_destroy(threadpool);
+}
+
+int main(int argc, char* argv[]) {
+ setenv("TERM", "xterm-256color", 0);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}