From 5cc4af5231608d0d85d120c20bd9bbc9da9338fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Lafuente?= Date: Thu, 18 Apr 2024 20:05:59 +0200 Subject: [PATCH] Add isInitialized to nix::Value Add a method to check if a value has been initialized. This helps avoid segfaults when calling `type()`. Useful in the context of the new C API. Closes #10524 --- src/libexpr/value.hh | 9 ++++++++- tests/unit/libexpr/value/value.cc | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/unit/libexpr/value/value.cc diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 7ed3fa5a9..a1003e16b 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -23,6 +23,7 @@ class BindingsBuilder; typedef enum { + tUnset, tInt = 1, tBool, tString, @@ -166,7 +167,7 @@ public: struct Value { private: - InternalType internalType; + InternalType internalType = tUnset; friend std::string showType(const Value & v); @@ -270,6 +271,7 @@ public: inline ValueType type(bool invalidIsThunk = false) const { switch (internalType) { + case tUnset: break; case tInt: return nInt; case tBool: return nBool; case tString: return nString; @@ -294,6 +296,11 @@ public: internalType = newType; } + inline bool isInitialized() + { + return internalType != tUnset; + } + inline void mkInt(NixInt n) { finishValue(tInt, { .integer = n }); diff --git a/tests/unit/libexpr/value/value.cc b/tests/unit/libexpr/value/value.cc new file mode 100644 index 000000000..49a896c87 --- /dev/null +++ b/tests/unit/libexpr/value/value.cc @@ -0,0 +1,25 @@ +#include "value.hh" + +#include "tests/libstore.hh" + +namespace nix { + +class ValueTest : public LibStoreTest +{}; + +TEST_F(ValueTest, unsetValue) +{ + Value unsetValue; + ASSERT_EQ(false, unsetValue.isInitialized()); + ASSERT_EQ(nThunk, unsetValue.type(true)); + ASSERT_DEATH(unsetValue.type(), ""); +} + +TEST_F(ValueTest, vInt) +{ + Value vInt; + vInt.mkInt(42); + ASSERT_EQ(true, vInt.isInitialized()); +} + +} // namespace nix