aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/tests')
-rw-r--r--src/libutil/tests/hash.cc32
-rw-r--r--src/libutil/tests/local.mk2
-rw-r--r--src/libutil/tests/logging.cc255
-rw-r--r--src/libutil/tests/pool.cc127
4 files changed, 399 insertions, 17 deletions
diff --git a/src/libutil/tests/hash.cc b/src/libutil/tests/hash.cc
index ecc0d4a03..412c03030 100644
--- a/src/libutil/tests/hash.cc
+++ b/src/libutil/tests/hash.cc
@@ -10,53 +10,53 @@ namespace nix {
TEST(hashString, testKnownMD5Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc1321
auto s1 = "";
- auto hash = hashString(HashType::MD5, s1);
- ASSERT_EQ(hash.to_string(Base::Base16), "md5:d41d8cd98f00b204e9800998ecf8427e");
+ auto hash = hashString(HashType::htMD5, s1);
+ ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e");
}
TEST(hashString, testKnownMD5Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc1321
auto s2 = "abc";
- auto hash = hashString(HashType::MD5, s2);
- ASSERT_EQ(hash.to_string(Base::Base16), "md5:900150983cd24fb0d6963f7d28e17f72");
+ auto hash = hashString(HashType::htMD5, s2);
+ ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72");
}
TEST(hashString, testKnownSHA1Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc3174
auto s = "abc";
- auto hash = hashString(HashType::SHA1, s);
- ASSERT_EQ(hash.to_string(Base::Base16),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
+ auto hash = hashString(HashType::htSHA1, s);
+ ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
}
TEST(hashString, testKnownSHA1Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc3174
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
- auto hash = hashString(HashType::SHA1, s);
- ASSERT_EQ(hash.to_string(Base::Base16),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
+ auto hash = hashString(HashType::htSHA1, s);
+ ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
}
TEST(hashString, testKnownSHA256Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abc";
- auto hash = hashString(HashType::SHA256, s);
- ASSERT_EQ(hash.to_string(Base::Base16),
+ auto hash = hashString(HashType::htSHA256, s);
+ ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
}
TEST(hashString, testKnownSHA256Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
- auto hash = hashString(HashType::SHA256, s);
- ASSERT_EQ(hash.to_string(Base::Base16),
+ auto hash = hashString(HashType::htSHA256, s);
+ ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
}
TEST(hashString, testKnownSHA512Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abc";
- auto hash = hashString(HashType::SHA512, s);
- ASSERT_EQ(hash.to_string(Base::Base16),
+ auto hash = hashString(HashType::htSHA512, s);
+ ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9"
"7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd"
"454d4423643ce80e2a9ac94fa54ca49f");
@@ -66,8 +66,8 @@ namespace nix {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
- auto hash = hashString(HashType::SHA512, s);
- ASSERT_EQ(hash.to_string(Base::Base16),
+ auto hash = hashString(HashType::htSHA512, s);
+ ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1"
"7299aeadb6889018501d289e4900f7e4331b99dec4b5433a"
"c7d329eeb6dd26545e96e55b874be909");
diff --git a/src/libutil/tests/local.mk b/src/libutil/tests/local.mk
index a297edb64..815e18560 100644
--- a/src/libutil/tests/local.mk
+++ b/src/libutil/tests/local.mk
@@ -8,7 +8,7 @@ libutil-tests_INSTALL_DIR :=
libutil-tests_SOURCES := $(wildcard $(d)/*.cc)
-libutil-tests_CXXFLAGS += -I src/libutil
+libutil-tests_CXXFLAGS += -I src/libutil -I src/libexpr
libutil-tests_LIBS = libutil
diff --git a/src/libutil/tests/logging.cc b/src/libutil/tests/logging.cc
new file mode 100644
index 000000000..4cb54995b
--- /dev/null
+++ b/src/libutil/tests/logging.cc
@@ -0,0 +1,255 @@
+#include "logging.hh"
+#include "nixexpr.hh"
+#include "util.hh"
+
+#include <gtest/gtest.h>
+
+namespace nix {
+
+ /* ----------------------------------------------------------------------------
+ * logEI
+ * --------------------------------------------------------------------------*/
+
+ TEST(logEI, catpuresBasicProperties) {
+
+ MakeError(TestError, Error);
+ ErrorInfo::programName = std::optional("error-unit-test");
+
+ try {
+ throw TestError("an error for testing purposes");
+ } catch (Error &e) {
+ testing::internal::CaptureStderr();
+ logger->logEI(e.info());
+ auto str = testing::internal::GetCapturedStderr();
+
+ ASSERT_STREQ(str.c_str(),"\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\nan error for testing purposes\n");
+ }
+ }
+
+ TEST(logEI, appendingHintsToPreviousError) {
+
+ MakeError(TestError, Error);
+ ErrorInfo::programName = std::optional("error-unit-test");
+
+ try {
+ auto e = Error("initial error");
+ throw TestError(e.info());
+ } catch (Error &e) {
+ ErrorInfo ei = e.info();
+ ei.hint = hintfmt("%s; subsequent error message.", normaltxt(e.info().hint ? e.info().hint->str() : ""));
+
+ testing::internal::CaptureStderr();
+ logger->logEI(ei);
+ auto str = testing::internal::GetCapturedStderr();
+
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0minitial error\x1B[0m; subsequent error message.\n");
+ }
+
+ }
+
+ TEST(logEI, picksUpSysErrorExitCode) {
+
+ MakeError(TestError, Error);
+ ErrorInfo::programName = std::optional("error-unit-test");
+
+ try {
+ auto x = readFile(-1);
+ }
+ catch (SysError &e) {
+ testing::internal::CaptureStderr();
+ logError(e.info());
+ auto str = testing::internal::GetCapturedStderr();
+
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- SysError --- error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0mstatting file\x1B[0m: \x1B[33;1mBad file descriptor\x1B[0m\n");
+
+ }
+ }
+
+ TEST(logEI, loggingErrorOnInfoLevel) {
+ testing::internal::CaptureStderr();
+
+ logger->logEI({ .level = lvlInfo,
+ .name = "Info name",
+ .description = "Info description",
+ });
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[32;1minfo:\x1B[0m\x1B[34;1m --- Info name --- error-unit-test\x1B[0m\nInfo description\n");
+ }
+
+ TEST(logEI, loggingErrorOnTalkativeLevel) {
+ verbosity = lvlTalkative;
+
+ testing::internal::CaptureStderr();
+
+ logger->logEI({ .level = lvlTalkative,
+ .name = "Talkative name",
+ .description = "Talkative description",
+ });
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[32;1mtalk:\x1B[0m\x1B[34;1m --- Talkative name --- error-unit-test\x1B[0m\nTalkative description\n");
+ }
+
+ TEST(logEI, loggingErrorOnChattyLevel) {
+ verbosity = lvlChatty;
+
+ testing::internal::CaptureStderr();
+
+ logger->logEI({ .level = lvlChatty,
+ .name = "Chatty name",
+ .description = "Talkative description",
+ });
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[32;1mchat:\x1B[0m\x1B[34;1m --- Chatty name --- error-unit-test\x1B[0m\nTalkative description\n");
+ }
+
+ TEST(logEI, loggingErrorOnDebugLevel) {
+ verbosity = lvlDebug;
+
+ testing::internal::CaptureStderr();
+
+ logger->logEI({ .level = lvlDebug,
+ .name = "Debug name",
+ .description = "Debug description",
+ });
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[33;1mdebug:\x1B[0m\x1B[34;1m --- Debug name --- error-unit-test\x1B[0m\nDebug description\n");
+ }
+
+ TEST(logEI, loggingErrorOnVomitLevel) {
+ verbosity = lvlVomit;
+
+ testing::internal::CaptureStderr();
+
+ logger->logEI({ .level = lvlVomit,
+ .name = "Vomit name",
+ .description = "Vomit description",
+ });
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[32;1mvomit:\x1B[0m\x1B[34;1m --- Vomit name --- error-unit-test\x1B[0m\nVomit description\n");
+ }
+
+ /* ----------------------------------------------------------------------------
+ * logError
+ * --------------------------------------------------------------------------*/
+
+
+ TEST(logError, logErrorWithoutHintOrCode) {
+ testing::internal::CaptureStderr();
+
+ logError({
+ .name = "name",
+ .description = "error description",
+ });
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n");
+ }
+
+ TEST(logError, logErrorWithPreviousAndNextLinesOfCode) {
+ SymbolTable testTable;
+ auto problem_file = testTable.create("myfile.nix");
+
+ testing::internal::CaptureStderr();
+
+ logError({
+ .name = "error name",
+ .description = "error with code lines",
+ .hint = hintfmt("this hint has %1% templated %2%!!",
+ "yellow",
+ "values"),
+ .nixCode = NixCode {
+ .errPos = Pos(problem_file, 40, 13),
+ .prevLineOfCode = "previous line of code",
+ .errLineOfCode = "this is the problem line of code",
+ .nextLineOfCode = "next line of code",
+ }});
+
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror with code lines\n\n 39| previous line of code\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 41| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
+ }
+
+ TEST(logError, logErrorWithoutLinesOfCode) {
+ SymbolTable testTable;
+ auto problem_file = testTable.create("myfile.nix");
+ testing::internal::CaptureStderr();
+
+ logError({
+ .name = "error name",
+ .description = "error without any code lines.",
+ .hint = hintfmt("this hint has %1% templated %2%!!",
+ "yellow",
+ "values"),
+ .nixCode = NixCode {
+ .errPos = Pos(problem_file, 40, 13)
+ }});
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror without any code lines.\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
+ }
+
+ TEST(logError, logErrorWithOnlyHintAndName) {
+ SymbolTable testTable;
+ auto problem_file = testTable.create("myfile.nix");
+ testing::internal::CaptureStderr();
+
+ logError({
+ .name = "error name",
+ .hint = hintfmt("hint %1%", "only"),
+ .nixCode = NixCode {
+ .errPos = Pos(problem_file, 40, 13)
+ }});
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nhint \x1B[33;1monly\x1B[0m\n");
+
+ }
+
+ /* ----------------------------------------------------------------------------
+ * logWarning
+ * --------------------------------------------------------------------------*/
+
+ TEST(logWarning, logWarningWithNameDescriptionAndHint) {
+ testing::internal::CaptureStderr();
+
+ logWarning({
+ .name = "name",
+ .description = "error description",
+ .hint = hintfmt("there was a %1%", "warning"),
+ });
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n\nthere was a \x1B[33;1mwarning\x1B[0m\n");
+ }
+
+ TEST(logWarning, logWarningWithFileLineNumAndCode) {
+
+ SymbolTable testTable;
+ auto problem_file = testTable.create("myfile.nix");
+
+ testing::internal::CaptureStderr();
+
+ logWarning({
+ .name = "warning name",
+ .description = "warning description",
+ .hint = hintfmt("this hint has %1% templated %2%!!",
+ "yellow",
+ "values"),
+ .nixCode = NixCode {
+ .errPos = Pos(problem_file, 40, 13),
+ .prevLineOfCode = std::nullopt,
+ .errLineOfCode = "this is the problem line of code",
+ .nextLineOfCode = std::nullopt
+ }});
+
+
+ auto str = testing::internal::GetCapturedStderr();
+ ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- warning name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nwarning description\n\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
+ }
+
+}
diff --git a/src/libutil/tests/pool.cc b/src/libutil/tests/pool.cc
new file mode 100644
index 000000000..127e42dda
--- /dev/null
+++ b/src/libutil/tests/pool.cc
@@ -0,0 +1,127 @@
+#include "pool.hh"
+#include <gtest/gtest.h>
+
+namespace nix {
+
+ struct TestResource
+ {
+
+ TestResource() {
+ static int counter = 0;
+ num = counter++;
+ }
+
+ int dummyValue = 1;
+ bool good = true;
+ int num;
+ };
+
+ /* ----------------------------------------------------------------------------
+ * Pool
+ * --------------------------------------------------------------------------*/
+
+ TEST(Pool, freshPoolHasZeroCountAndSpecifiedCapacity) {
+ auto isGood = [](const ref<TestResource> & r) { return r->good; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+
+ ASSERT_EQ(pool.count(), 0);
+ ASSERT_EQ(pool.capacity(), 1);
+ }
+
+ TEST(Pool, freshPoolCanGetAResource) {
+ auto isGood = [](const ref<TestResource> & r) { return r->good; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+ ASSERT_EQ(pool.count(), 0);
+
+ TestResource r = *(pool.get());
+
+ ASSERT_EQ(pool.count(), 1);
+ ASSERT_EQ(pool.capacity(), 1);
+ ASSERT_EQ(r.dummyValue, 1);
+ ASSERT_EQ(r.good, true);
+ }
+
+ TEST(Pool, capacityCanBeIncremented) {
+ auto isGood = [](const ref<TestResource> & r) { return r->good; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+ ASSERT_EQ(pool.capacity(), 1);
+ pool.incCapacity();
+ ASSERT_EQ(pool.capacity(), 2);
+ }
+
+ TEST(Pool, capacityCanBeDecremented) {
+ auto isGood = [](const ref<TestResource> & r) { return r->good; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+ ASSERT_EQ(pool.capacity(), 1);
+ pool.decCapacity();
+ ASSERT_EQ(pool.capacity(), 0);
+ }
+
+ TEST(Pool, flushBadDropsOutOfScopeResources) {
+ auto isGood = [](const ref<TestResource> & r) { return false; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+
+ {
+ auto _r = pool.get();
+ ASSERT_EQ(pool.count(), 1);
+ }
+
+ pool.flushBad();
+ ASSERT_EQ(pool.count(), 0);
+ }
+
+ // Test that the resources we allocate are being reused when they are still good.
+ TEST(Pool, reuseResource) {
+ auto isGood = [](const ref<TestResource> & r) { return true; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+
+ // Compare the instance counter between the two handles. We expect them to be equal
+ // as the pool should hand out the same (still) good one again.
+ int counter = -1;
+ {
+ Pool<TestResource>::Handle h = pool.get();
+ counter = h->num;
+ } // the first handle goes out of scope
+
+ { // the second handle should contain the same resource (with the same counter value)
+ Pool<TestResource>::Handle h = pool.get();
+ ASSERT_EQ(h->num, counter);
+ }
+ }
+
+ // Test that the resources we allocate are being thrown away when they are no longer good.
+ TEST(Pool, badResourceIsNotReused) {
+ auto isGood = [](const ref<TestResource> & r) { return false; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+
+ // Compare the instance counter between the two handles. We expect them
+ // to *not* be equal as the pool should hand out a new instance after
+ // the first one was returned.
+ int counter = -1;
+ {
+ Pool<TestResource>::Handle h = pool.get();
+ counter = h->num;
+ } // the first handle goes out of scope
+
+ {
+ // the second handle should contain a different resource (with a
+ //different counter value)
+ Pool<TestResource>::Handle h = pool.get();
+ ASSERT_NE(h->num, counter);
+ }
+ }
+}