mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-25 15:26:17 +02:00
C API: add (un)initialized value checks
This commit is contained in:
parent
9d7dee4a8f
commit
ccad6e94e2
3 changed files with 128 additions and 24 deletions
|
@ -20,7 +20,7 @@
|
|||
# include "gc_cpp.h"
|
||||
#endif
|
||||
|
||||
// Helper function to throw an exception if value is null
|
||||
// Helper function to throw an exception if value is null or in an invalid state
|
||||
static const nix::Value & check_value_not_null(const Value * value)
|
||||
{
|
||||
if (!value) {
|
||||
|
@ -37,6 +37,20 @@ static nix::Value & check_value_not_null(Value * value)
|
|||
return *((nix::Value *) value);
|
||||
}
|
||||
|
||||
static void check_value_initialized(const nix::Value & value)
|
||||
{
|
||||
if (!value.isValid()) {
|
||||
throw std::runtime_error("Uninitialized Value");
|
||||
}
|
||||
}
|
||||
|
||||
static void check_value_uninitialized(const nix::Value & value)
|
||||
{
|
||||
if (value.isValid()) {
|
||||
throw std::runtime_error("Value already initialized. Variables are immutable");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert calls from nix into C API.
|
||||
*
|
||||
|
@ -112,6 +126,7 @@ ValueType nix_get_type(nix_c_context * context, const Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
using namespace nix;
|
||||
switch (v.type()) {
|
||||
case nThunk:
|
||||
|
@ -148,6 +163,7 @@ const char * nix_get_typename(nix_c_context * context, const Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
auto s = nix::showType(v);
|
||||
return strdup(s.c_str());
|
||||
}
|
||||
|
@ -160,6 +176,7 @@ bool nix_get_bool(nix_c_context * context, const Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nBool);
|
||||
return v.boolean();
|
||||
}
|
||||
|
@ -172,6 +189,7 @@ nix_err nix_get_string(nix_c_context * context, const Value * value, nix_get_str
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nString);
|
||||
call_nix_get_string_callback(v.c_str(), callback, user_data);
|
||||
}
|
||||
|
@ -184,6 +202,7 @@ const char * nix_get_path_string(nix_c_context * context, const Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nPath);
|
||||
// NOTE (from @yorickvP)
|
||||
// v._path.path should work but may not be how Eelco intended it.
|
||||
|
@ -203,6 +222,7 @@ unsigned int nix_get_list_size(nix_c_context * context, const Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nList);
|
||||
return v.listSize();
|
||||
}
|
||||
|
@ -215,6 +235,7 @@ unsigned int nix_get_attrs_size(nix_c_context * context, const Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nAttrs);
|
||||
return v.attrs()->size();
|
||||
}
|
||||
|
@ -227,6 +248,7 @@ double nix_get_float(nix_c_context * context, const Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nFloat);
|
||||
return v.fpoint();
|
||||
}
|
||||
|
@ -239,6 +261,7 @@ int64_t nix_get_int(nix_c_context * context, const Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nInt);
|
||||
return v.integer();
|
||||
}
|
||||
|
@ -251,6 +274,7 @@ ExternalValue * nix_get_external(nix_c_context * context, Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nExternal);
|
||||
return (ExternalValue *) v.external();
|
||||
}
|
||||
|
@ -263,6 +287,7 @@ Value * nix_get_list_byidx(nix_c_context * context, const Value * value, EvalSta
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nList);
|
||||
auto * p = v.listElems()[ix];
|
||||
nix_gc_incref(nullptr, p);
|
||||
|
@ -279,6 +304,7 @@ Value * nix_get_attr_byname(nix_c_context * context, const Value * value, EvalSt
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nAttrs);
|
||||
nix::Symbol s = state->state.symbols.create(name);
|
||||
auto attr = v.attrs()->get(s);
|
||||
|
@ -299,6 +325,7 @@ bool nix_has_attr_byname(nix_c_context * context, const Value * value, EvalState
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
assert(v.type() == nix::nAttrs);
|
||||
nix::Symbol s = state->state.symbols.create(name);
|
||||
auto attr = v.attrs()->get(s);
|
||||
|
@ -316,6 +343,7 @@ nix_get_attr_byidx(nix_c_context * context, const Value * value, EvalState * sta
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
const nix::Attr & a = (*v.attrs())[i];
|
||||
*name = ((const std::string &) (state->state.symbols[a.name])).c_str();
|
||||
nix_gc_incref(nullptr, a.value);
|
||||
|
@ -331,6 +359,7 @@ const char * nix_get_attr_name_byidx(nix_c_context * context, const Value * valu
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
const nix::Attr & a = (*v.attrs())[i];
|
||||
return ((const std::string &) (state->state.symbols[a.name])).c_str();
|
||||
}
|
||||
|
@ -343,6 +372,7 @@ nix_err nix_init_bool(nix_c_context * context, Value * value, bool b)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkBool(b);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -355,6 +385,7 @@ nix_err nix_init_string(nix_c_context * context, Value * value, const char * str
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkString(std::string_view(str));
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -366,6 +397,7 @@ nix_err nix_init_path_string(nix_c_context * context, EvalState * s, Value * val
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkPath(s->state.rootPath(nix::CanonPath(str)));
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -377,6 +409,7 @@ nix_err nix_init_float(nix_c_context * context, Value * value, double d)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkFloat(d);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -388,6 +421,7 @@ nix_err nix_init_int(nix_c_context * context, Value * value, int64_t i)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkInt(i);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -399,6 +433,7 @@ nix_err nix_init_null(nix_c_context * context, Value * value)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkNull();
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -423,6 +458,7 @@ nix_err nix_init_external(nix_c_context * context, Value * value, ExternalValue
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
auto r = (nix::ExternalValueBase *) val;
|
||||
v.mkExternal(r);
|
||||
}
|
||||
|
@ -450,6 +486,7 @@ nix_err nix_list_builder_insert(nix_c_context * context, ListBuilder * list_buil
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & e = check_value_not_null(value);
|
||||
check_value_initialized(e);
|
||||
list_builder->builder[index] = &e;
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -470,6 +507,7 @@ nix_err nix_make_list(nix_c_context * context, ListBuilder * list_builder, Value
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkList(list_builder->builder);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -481,6 +519,7 @@ nix_err nix_init_primop(nix_c_context * context, Value * value, PrimOp * p)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkPrimOp((nix::PrimOp *) p);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -492,7 +531,9 @@ nix_err nix_copy_value(nix_c_context * context, Value * value, Value * source)
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
auto & s = check_value_not_null(source);
|
||||
check_value_initialized(s);
|
||||
v = s;
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -504,6 +545,7 @@ nix_err nix_make_attrs(nix_c_context * context, Value * value, BindingsBuilder *
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_uninitialized(v);
|
||||
v.mkAttrs(b->builder);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
|
@ -530,6 +572,7 @@ nix_err nix_bindings_builder_insert(nix_c_context * context, BindingsBuilder * b
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
nix::Symbol s = bb->builder.state.symbols.create(name);
|
||||
bb->builder.insert(s, &v);
|
||||
}
|
||||
|
@ -551,6 +594,7 @@ nix_realised_string * nix_string_realise(nix_c_context * context, EvalState * st
|
|||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto & v = check_value_not_null(value);
|
||||
check_value_initialized(v);
|
||||
nix::NixStringContext stringContext;
|
||||
auto rawStr = state->state.coerceToString(nix::noPos, v, stringContext, "while realising a string").toOwned();
|
||||
nix::StorePathSet storePaths;
|
||||
|
|
|
@ -14,11 +14,16 @@
|
|||
|
||||
namespace nixC {
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_int)
|
||||
TEST_F(nix_api_expr_test, nix_value_get_int_invalid)
|
||||
{
|
||||
ASSERT_EQ(0, nix_get_int(ctx, nullptr));
|
||||
ASSERT_DEATH(nix_get_int(ctx, value), "");
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(0, nix_get_int(ctx, value));
|
||||
assert_ctx_err();
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_int)
|
||||
{
|
||||
int myInt = 1;
|
||||
nix_init_int(ctx, value, myInt);
|
||||
|
||||
|
@ -27,11 +32,16 @@ TEST_F(nix_api_expr_test, nix_value_set_get_int)
|
|||
ASSERT_EQ(NIX_TYPE_INT, nix_get_type(ctx, value));
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_float)
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_float_invalid)
|
||||
{
|
||||
ASSERT_FLOAT_EQ(0.0, nix_get_float(ctx, nullptr));
|
||||
ASSERT_DEATH(nix_get_float(ctx, value), "");
|
||||
assert_ctx_err();
|
||||
ASSERT_FLOAT_EQ(0.0, nix_get_float(ctx, value));
|
||||
assert_ctx_err();
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_float)
|
||||
{
|
||||
float myDouble = 1.0;
|
||||
nix_init_float(ctx, value, myDouble);
|
||||
|
||||
|
@ -40,11 +50,16 @@ TEST_F(nix_api_expr_test, nix_value_set_get_float)
|
|||
ASSERT_EQ(NIX_TYPE_FLOAT, nix_get_type(ctx, value));
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_bool)
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_bool_invalid)
|
||||
{
|
||||
ASSERT_EQ(false, nix_get_bool(ctx, nullptr));
|
||||
ASSERT_DEATH(nix_get_bool(ctx, value), "");
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(false, nix_get_bool(ctx, value));
|
||||
assert_ctx_err();
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_bool)
|
||||
{
|
||||
bool myBool = true;
|
||||
nix_init_bool(ctx, value, myBool);
|
||||
|
||||
|
@ -53,12 +68,18 @@ TEST_F(nix_api_expr_test, nix_value_set_get_bool)
|
|||
ASSERT_EQ(NIX_TYPE_BOOL, nix_get_type(ctx, value));
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_string)
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_string_invalid)
|
||||
{
|
||||
std::string string_value;
|
||||
ASSERT_EQ(NIX_ERR_UNKNOWN, nix_get_string(ctx, nullptr, OBSERVE_STRING(string_value)));
|
||||
ASSERT_DEATH(nix_get_string(ctx, value, OBSERVE_STRING(string_value)), "");
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(NIX_ERR_UNKNOWN, nix_get_string(ctx, value, OBSERVE_STRING(string_value)));
|
||||
assert_ctx_err();
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_string)
|
||||
{
|
||||
std::string string_value;
|
||||
const char * myString = "some string";
|
||||
nix_init_string(ctx, value, myString);
|
||||
|
||||
|
@ -68,21 +89,29 @@ TEST_F(nix_api_expr_test, nix_value_set_get_string)
|
|||
ASSERT_EQ(NIX_TYPE_STRING, nix_get_type(ctx, value));
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_null_invalid)
|
||||
{
|
||||
ASSERT_EQ(NULL, nix_get_typename(ctx, value));
|
||||
assert_ctx_err();
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_null)
|
||||
{
|
||||
ASSERT_DEATH(nix_get_typename(ctx, value), "");
|
||||
|
||||
nix_init_null(ctx, value);
|
||||
|
||||
ASSERT_STREQ("null", nix_get_typename(ctx, value));
|
||||
ASSERT_EQ(NIX_TYPE_NULL, nix_get_type(ctx, value));
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_path)
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_path_invalid)
|
||||
{
|
||||
ASSERT_EQ(nullptr, nix_get_path_string(ctx, nullptr));
|
||||
ASSERT_DEATH(nix_get_path_string(ctx, value), "");
|
||||
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(nullptr, nix_get_path_string(ctx, value));
|
||||
assert_ctx_err();
|
||||
}
|
||||
TEST_F(nix_api_expr_test, nix_value_set_get_path)
|
||||
{
|
||||
const char * p = "/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname";
|
||||
nix_init_path_string(ctx, state, value, p);
|
||||
|
||||
|
@ -91,14 +120,21 @@ TEST_F(nix_api_expr_test, nix_value_set_get_path)
|
|||
ASSERT_EQ(NIX_TYPE_PATH, nix_get_type(ctx, value));
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_build_and_init_list)
|
||||
TEST_F(nix_api_expr_test, nix_build_and_init_list_invalid)
|
||||
{
|
||||
ASSERT_EQ(nullptr, nix_get_list_byidx(ctx, nullptr, state, 0));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(0, nix_get_list_size(ctx, nullptr));
|
||||
assert_ctx_err();
|
||||
|
||||
ASSERT_DEATH(nix_get_list_byidx(ctx, value, state, 0), "");
|
||||
ASSERT_DEATH(nix_get_list_size(ctx, value), "");
|
||||
ASSERT_EQ(nullptr, nix_get_list_byidx(ctx, value, state, 0));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(0, nix_get_list_size(ctx, value));
|
||||
assert_ctx_err();
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_build_and_init_list)
|
||||
{
|
||||
int size = 10;
|
||||
ListBuilder * builder = nix_make_list_builder(ctx, state, size);
|
||||
|
||||
|
@ -119,20 +155,33 @@ TEST_F(nix_api_expr_test, nix_build_and_init_list)
|
|||
nix_gc_decref(ctx, intValue);
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_build_and_init_attr)
|
||||
TEST_F(nix_api_expr_test, nix_build_and_init_attr_invalid)
|
||||
{
|
||||
ASSERT_EQ(nullptr, nix_get_attr_byname(ctx, nullptr, state, 0));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(nullptr, nix_get_attr_byidx(ctx, nullptr, state, 0, nullptr));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(nullptr, nix_get_attr_name_byidx(ctx, nullptr, state, 0));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(0, nix_get_attrs_size(ctx, nullptr));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(false, nix_has_attr_byname(ctx, nullptr, state, "no-value"));
|
||||
assert_ctx_err();
|
||||
|
||||
ASSERT_DEATH(nix_get_attr_byname(ctx, value, state, 0), "");
|
||||
ASSERT_DEATH(nix_get_attr_byidx(ctx, value, state, 0, nullptr), "");
|
||||
ASSERT_DEATH(nix_get_attr_name_byidx(ctx, value, state, 0), "");
|
||||
ASSERT_DEATH(nix_get_attrs_size(ctx, value), "");
|
||||
ASSERT_DEATH(nix_has_attr_byname(ctx, value, state, "no-value"), "");
|
||||
ASSERT_EQ(nullptr, nix_get_attr_byname(ctx, value, state, 0));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(nullptr, nix_get_attr_byidx(ctx, value, state, 0, nullptr));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(nullptr, nix_get_attr_name_byidx(ctx, value, state, 0));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(0, nix_get_attrs_size(ctx, value));
|
||||
assert_ctx_err();
|
||||
ASSERT_EQ(false, nix_has_attr_byname(ctx, value, state, "no-value"));
|
||||
assert_ctx_err();
|
||||
}
|
||||
|
||||
TEST_F(nix_api_expr_test, nix_build_and_init_attr)
|
||||
{
|
||||
int size = 10;
|
||||
const char ** out_name = (const char **) malloc(sizeof(char *));
|
||||
|
||||
|
|
|
@ -24,7 +24,9 @@ protected:
|
|||
|
||||
nix_c_context * ctx;
|
||||
|
||||
inline void assert_ctx_ok() {
|
||||
inline void assert_ctx_ok()
|
||||
{
|
||||
|
||||
if (nix_err_code(ctx) == NIX_OK) {
|
||||
return;
|
||||
}
|
||||
|
@ -33,5 +35,14 @@ protected:
|
|||
std::string msg(p, n);
|
||||
FAIL() << "nix_err_code(ctx) != NIX_OK, message: " << msg;
|
||||
}
|
||||
|
||||
inline void assert_ctx_err()
|
||||
{
|
||||
if (nix_err_code(ctx) != NIX_OK) {
|
||||
return;
|
||||
}
|
||||
FAIL() << "Got NIX_OK, but expected an error!";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue