aboutsummaryrefslogtreecommitdiff
path: root/tests/unit/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit/libutil')
-rw-r--r--tests/unit/libutil/async-collect.cc104
-rw-r--r--tests/unit/libutil/async-semaphore.cc74
-rw-r--r--tests/unit/libutil/compression.cc3
3 files changed, 180 insertions, 1 deletions
diff --git a/tests/unit/libutil/async-collect.cc b/tests/unit/libutil/async-collect.cc
new file mode 100644
index 000000000..770374d21
--- /dev/null
+++ b/tests/unit/libutil/async-collect.cc
@@ -0,0 +1,104 @@
+#include "async-collect.hh"
+
+#include <gtest/gtest.h>
+#include <kj/array.h>
+#include <kj/async.h>
+#include <kj/exception.h>
+#include <stdexcept>
+
+namespace nix {
+
+TEST(AsyncCollect, void)
+{
+ kj::EventLoop loop;
+ kj::WaitScope waitScope(loop);
+
+ auto a = kj::newPromiseAndFulfiller<void>();
+ auto b = kj::newPromiseAndFulfiller<void>();
+ auto c = kj::newPromiseAndFulfiller<void>();
+ auto d = kj::newPromiseAndFulfiller<void>();
+
+ auto collect = asyncCollect(kj::arr(
+ std::pair(1, std::move(a.promise)),
+ std::pair(2, std::move(b.promise)),
+ std::pair(3, std::move(c.promise)),
+ std::pair(4, std::move(d.promise))
+ ));
+
+ auto p = collect.next();
+ ASSERT_FALSE(p.poll(waitScope));
+
+ // collection is ordered
+ c.fulfiller->fulfill();
+ b.fulfiller->fulfill();
+
+ ASSERT_TRUE(p.poll(waitScope));
+ ASSERT_EQ(p.wait(waitScope), 3);
+
+ p = collect.next();
+ ASSERT_TRUE(p.poll(waitScope));
+ ASSERT_EQ(p.wait(waitScope), 2);
+
+ p = collect.next();
+ ASSERT_FALSE(p.poll(waitScope));
+
+ // exceptions propagate
+ a.fulfiller->rejectIfThrows([] { throw std::runtime_error("test"); });
+
+ p = collect.next();
+ ASSERT_TRUE(p.poll(waitScope));
+ ASSERT_THROW(p.wait(waitScope), kj::Exception);
+
+ // first exception aborts collection
+ p = collect.next();
+ ASSERT_TRUE(p.poll(waitScope));
+ ASSERT_THROW(p.wait(waitScope), kj::Exception);
+}
+
+TEST(AsyncCollect, nonVoid)
+{
+ kj::EventLoop loop;
+ kj::WaitScope waitScope(loop);
+
+ auto a = kj::newPromiseAndFulfiller<int>();
+ auto b = kj::newPromiseAndFulfiller<int>();
+ auto c = kj::newPromiseAndFulfiller<int>();
+ auto d = kj::newPromiseAndFulfiller<int>();
+
+ auto collect = asyncCollect(kj::arr(
+ std::pair(1, std::move(a.promise)),
+ std::pair(2, std::move(b.promise)),
+ std::pair(3, std::move(c.promise)),
+ std::pair(4, std::move(d.promise))
+ ));
+
+ auto p = collect.next();
+ ASSERT_FALSE(p.poll(waitScope));
+
+ // collection is ordered
+ c.fulfiller->fulfill(1);
+ b.fulfiller->fulfill(2);
+
+ ASSERT_TRUE(p.poll(waitScope));
+ ASSERT_EQ(p.wait(waitScope), std::pair(3, 1));
+
+ p = collect.next();
+ ASSERT_TRUE(p.poll(waitScope));
+ ASSERT_EQ(p.wait(waitScope), std::pair(2, 2));
+
+ p = collect.next();
+ ASSERT_FALSE(p.poll(waitScope));
+
+ // exceptions propagate
+ a.fulfiller->rejectIfThrows([] { throw std::runtime_error("test"); });
+
+ p = collect.next();
+ ASSERT_TRUE(p.poll(waitScope));
+ ASSERT_THROW(p.wait(waitScope), kj::Exception);
+
+ // first exception aborts collection
+ p = collect.next();
+ ASSERT_TRUE(p.poll(waitScope));
+ ASSERT_THROW(p.wait(waitScope), kj::Exception);
+}
+}
diff --git a/tests/unit/libutil/async-semaphore.cc b/tests/unit/libutil/async-semaphore.cc
new file mode 100644
index 000000000..12b52885d
--- /dev/null
+++ b/tests/unit/libutil/async-semaphore.cc
@@ -0,0 +1,74 @@
+#include "async-semaphore.hh"
+
+#include <gtest/gtest.h>
+#include <kj/async.h>
+
+namespace nix {
+
+TEST(AsyncSemaphore, counting)
+{
+ kj::EventLoop loop;
+ kj::WaitScope waitScope(loop);
+
+ AsyncSemaphore sem(2);
+
+ ASSERT_EQ(sem.available(), 2);
+ ASSERT_EQ(sem.used(), 0);
+
+ auto a = kj::evalNow([&] { return sem.acquire(); });
+ ASSERT_EQ(sem.available(), 1);
+ ASSERT_EQ(sem.used(), 1);
+ auto b = kj::evalNow([&] { return sem.acquire(); });
+ ASSERT_EQ(sem.available(), 0);
+ ASSERT_EQ(sem.used(), 2);
+
+ auto c = kj::evalNow([&] { return sem.acquire(); });
+ auto d = kj::evalNow([&] { return sem.acquire(); });
+
+ ASSERT_TRUE(a.poll(waitScope));
+ ASSERT_TRUE(b.poll(waitScope));
+ ASSERT_FALSE(c.poll(waitScope));
+ ASSERT_FALSE(d.poll(waitScope));
+
+ a = nullptr;
+ ASSERT_TRUE(c.poll(waitScope));
+ ASSERT_FALSE(d.poll(waitScope));
+
+ {
+ auto lock = b.wait(waitScope);
+ ASSERT_FALSE(d.poll(waitScope));
+ }
+
+ ASSERT_TRUE(d.poll(waitScope));
+
+ ASSERT_EQ(sem.available(), 0);
+ ASSERT_EQ(sem.used(), 2);
+ c = nullptr;
+ ASSERT_EQ(sem.available(), 1);
+ ASSERT_EQ(sem.used(), 1);
+ d = nullptr;
+ ASSERT_EQ(sem.available(), 2);
+ ASSERT_EQ(sem.used(), 0);
+}
+
+TEST(AsyncSemaphore, cancelledWaiter)
+{
+ kj::EventLoop loop;
+ kj::WaitScope waitScope(loop);
+
+ AsyncSemaphore sem(1);
+
+ auto a = kj::evalNow([&] { return sem.acquire(); });
+ auto b = kj::evalNow([&] { return sem.acquire(); });
+ auto c = kj::evalNow([&] { return sem.acquire(); });
+
+ ASSERT_TRUE(a.poll(waitScope));
+ ASSERT_FALSE(b.poll(waitScope));
+
+ b = nullptr;
+ a = nullptr;
+
+ ASSERT_TRUE(c.poll(waitScope));
+}
+
+}
diff --git a/tests/unit/libutil/compression.cc b/tests/unit/libutil/compression.cc
index 8d181f53d..6dd8c96df 100644
--- a/tests/unit/libutil/compression.cc
+++ b/tests/unit/libutil/compression.cc
@@ -1,4 +1,5 @@
#include "compression.hh"
+#include <cstddef>
#include <gtest/gtest.h>
namespace nix {
@@ -147,7 +148,7 @@ TEST_P(PerTypeNonNullCompressionTest, truncatedValidInput)
/* n.b. This also tests zero-length input, which is also invalid.
* As of the writing of this comment, it returns empty output, but is
* allowed to throw a compression error instead. */
- for (int i = 0; i < compressed.length(); ++i) {
+ for (size_t i = 0u; i < compressed.length(); ++i) {
auto newCompressed = compressed.substr(compressed.length() - i);
try {
decompress(method, newCompressed);