1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 10:11:47 +02:00

Merge pull request #8699 from tweag/nix-c-bindings

(Towards) stable C bindings for libutil, libexpr
This commit is contained in:
Robert Hensing 2024-04-04 17:50:52 +02:00 committed by GitHub
commit 12ec3154b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 3624 additions and 20 deletions

View file

@ -0,0 +1,31 @@
#pragma once
///@file
#include "nix_api_expr.h"
#include "nix_api_value.h"
#include "tests/nix_api_store.hh"
#include <gtest/gtest.h>
namespace nixC {
class nix_api_expr_test : public nix_api_store_test
{
protected:
nix_api_expr_test()
{
nix_libexpr_init(ctx);
state = nix_state_create(nullptr, nullptr, store);
value = nix_alloc_value(nullptr, state);
}
~nix_api_expr_test()
{
nix_gc_decref(nullptr, value);
nix_state_free(state);
}
EvalState * state;
Value * value;
};
}

View file

@ -24,14 +24,17 @@ libexpr-tests_EXTRA_INCLUDES = \
-I tests/unit/libstore-support \
-I tests/unit/libutil-support \
$(INCLUDE_libexpr) \
$(INCLUDE_libexprc) \
$(INCLUDE_libfetchers) \
$(INCLUDE_libstore) \
$(INCLUDE_libutil)
$(INCLUDE_libstorec) \
$(INCLUDE_libutil) \
$(INCLUDE_libutilc)
libexpr-tests_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES)
libexpr-tests_LIBS = \
libexpr-test-support libstore-test-support libutils-test-support \
libexpr libfetchers libstore libutil
libexpr libexprc libfetchers libstore libstorec libutil libutilc
libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock

View file

@ -0,0 +1,100 @@
#include "nix_api_store.h"
#include "nix_api_store_internal.h"
#include "nix_api_util.h"
#include "nix_api_util_internal.h"
#include "nix_api_expr.h"
#include "nix_api_value.h"
#include "tests/nix_api_expr.hh"
#include <gtest/gtest.h>
namespace nixC {
TEST_F(nix_api_expr_test, nix_expr_eval_from_string)
{
nix_expr_eval_from_string(nullptr, state, "builtins.nixVersion", ".", value);
nix_value_force(nullptr, state, value);
auto result = nix_get_string(nullptr, value);
ASSERT_STREQ(PACKAGE_VERSION, result);
}
TEST_F(nix_api_expr_test, nix_expr_eval_add_numbers)
{
nix_expr_eval_from_string(nullptr, state, "1 + 1", ".", value);
nix_value_force(nullptr, state, value);
auto result = nix_get_int(nullptr, value);
ASSERT_EQ(2, result);
}
TEST_F(nix_api_expr_test, nix_expr_eval_drv)
{
auto expr = R"(derivation { name = "myname"; builder = "mybuilder"; system = "mysystem"; })";
nix_expr_eval_from_string(nullptr, state, expr, ".", value);
ASSERT_EQ(NIX_TYPE_ATTRS, nix_get_type(nullptr, value));
EvalState * stateFn = nix_state_create(nullptr, nullptr, store);
Value * valueFn = nix_alloc_value(nullptr, state);
nix_expr_eval_from_string(nullptr, stateFn, "builtins.toString", ".", valueFn);
ASSERT_EQ(NIX_TYPE_FUNCTION, nix_get_type(nullptr, valueFn));
EvalState * stateResult = nix_state_create(nullptr, nullptr, store);
Value * valueResult = nix_alloc_value(nullptr, stateResult);
nix_value_call(ctx, stateResult, valueFn, value, valueResult);
ASSERT_EQ(NIX_TYPE_STRING, nix_get_type(nullptr, valueResult));
std::string p = nix_get_string(nullptr, valueResult);
std::string pEnd = "-myname";
ASSERT_EQ(pEnd, p.substr(p.size() - pEnd.size()));
// Clean up
nix_gc_decref(nullptr, valueFn);
nix_state_free(stateFn);
nix_gc_decref(nullptr, valueResult);
nix_state_free(stateResult);
}
TEST_F(nix_api_expr_test, nix_build_drv)
{
auto expr = R"(derivation { name = "myname";
system = builtins.currentSystem;
builder = "/bin/sh";
args = [ "-c" "echo foo > $out" ];
})";
nix_expr_eval_from_string(nullptr, state, expr, ".", value);
Value * drvPathValue = nix_get_attr_byname(nullptr, value, state, "drvPath");
const char * drvPath = nix_get_string(nullptr, drvPathValue);
std::string p = drvPath;
std::string pEnd = "-myname.drv";
ASSERT_EQ(pEnd, p.substr(p.size() - pEnd.size()));
StorePath * drvStorePath = nix_store_parse_path(ctx, store, drvPath);
ASSERT_EQ(true, nix_store_is_valid_path(ctx, store, drvStorePath));
Value * outPathValue = nix_get_attr_byname(ctx, value, state, "outPath");
const char * outPath = nix_get_string(ctx, outPathValue);
p = outPath;
pEnd = "-myname";
ASSERT_EQ(pEnd, p.substr(p.size() - pEnd.size()));
ASSERT_EQ(true, drvStorePath->path.isDerivation());
StorePath * outStorePath = nix_store_parse_path(ctx, store, outPath);
ASSERT_EQ(false, nix_store_is_valid_path(ctx, store, outStorePath));
// TODO figure out why fails.
// `make libexpr-tests_RUN` works, but `nix build .` enters an infinite loop
/* nix_store_realise(ctx, store, drvStorePath, nullptr, nullptr); */
/* auto is_valid_path = nix_store_is_valid_path(ctx, store, outStorePath); */
/* ASSERT_EQ(true, is_valid_path); */
// Clean up
nix_store_path_free(drvStorePath);
nix_store_path_free(outStorePath);
}
}

View file

@ -0,0 +1,63 @@
#include "nix_api_store.h"
#include "nix_api_store_internal.h"
#include "nix_api_util.h"
#include "nix_api_util_internal.h"
#include "nix_api_expr.h"
#include "nix_api_expr_internal.h"
#include "nix_api_value.h"
#include "nix_api_external.h"
#include "tests/nix_api_expr.hh"
#include <gtest/gtest.h>
namespace nixC {
class MyExternalValueDesc : public NixCExternalValueDesc
{
public:
MyExternalValueDesc(int x)
: _x(x)
{
print = print_function;
showType = show_type_function;
typeOf = type_of_function;
}
private:
int _x;
static void print_function(void * self, nix_printer * printer) {}
static void show_type_function(void * self, nix_string_return * res) {}
static void type_of_function(void * self, nix_string_return * res)
{
MyExternalValueDesc * obj = static_cast<MyExternalValueDesc *>(self);
std::string type_string = "nix-external<MyExternalValueDesc( ";
type_string += std::to_string(obj->_x);
type_string += " )>";
res->str = &*type_string.begin();
}
};
TEST_F(nix_api_expr_test, nix_expr_eval_external)
{
MyExternalValueDesc * external = new MyExternalValueDesc(42);
ExternalValue * val = nix_create_external_value(ctx, external, external);
nix_init_external(ctx, value, val);
EvalState * stateResult = nix_state_create(nullptr, nullptr, store);
Value * valueResult = nix_alloc_value(nullptr, stateResult);
EvalState * stateFn = nix_state_create(nullptr, nullptr, store);
Value * valueFn = nix_alloc_value(nullptr, stateFn);
nix_expr_eval_from_string(nullptr, state, "builtins.typeOf", ".", valueFn);
ASSERT_EQ(NIX_TYPE_EXTERNAL, nix_get_type(nullptr, value));
nix_value_call(ctx, state, valueFn, value, valueResult);
ASSERT_STREQ("nix-external<MyExternalValueDesc( 42 )>", nix_get_string(nullptr, valueResult));
}
}

View file

@ -0,0 +1,184 @@
#include "nix_api_store.h"
#include "nix_api_store_internal.h"
#include "nix_api_util.h"
#include "nix_api_util_internal.h"
#include "nix_api_expr.h"
#include "nix_api_value.h"
#include "tests/nix_api_expr.hh"
#include <cstdlib>
#include <gtest/gtest.h>
namespace nixC {
TEST_F(nix_api_expr_test, nix_value_set_get_int)
{
ASSERT_EQ(0, nix_get_int(ctx, nullptr));
ASSERT_DEATH(nix_get_int(ctx, value), "");
int myInt = 1;
nix_init_int(ctx, value, myInt);
ASSERT_EQ(myInt, nix_get_int(ctx, value));
ASSERT_STREQ("an integer", nix_get_typename(ctx, value));
ASSERT_EQ(NIX_TYPE_INT, nix_get_type(ctx, value));
}
TEST_F(nix_api_expr_test, nix_value_set_get_float)
{
ASSERT_FLOAT_EQ(0.0, nix_get_float(ctx, nullptr));
ASSERT_DEATH(nix_get_float(ctx, value), "");
float myDouble = 1.0;
nix_init_float(ctx, value, myDouble);
ASSERT_FLOAT_EQ(myDouble, nix_get_float(ctx, value));
ASSERT_STREQ("a float", nix_get_typename(ctx, value));
ASSERT_EQ(NIX_TYPE_FLOAT, nix_get_type(ctx, value));
}
TEST_F(nix_api_expr_test, nix_value_set_get_bool)
{
ASSERT_EQ(false, nix_get_bool(ctx, nullptr));
ASSERT_DEATH(nix_get_bool(ctx, value), "");
bool myBool = true;
nix_init_bool(ctx, value, myBool);
ASSERT_EQ(myBool, nix_get_bool(ctx, value));
ASSERT_STREQ("a Boolean", nix_get_typename(ctx, value));
ASSERT_EQ(NIX_TYPE_BOOL, nix_get_type(ctx, value));
}
TEST_F(nix_api_expr_test, nix_value_set_get_string)
{
ASSERT_EQ(nullptr, nix_get_string(ctx, nullptr));
ASSERT_DEATH(nix_get_string(ctx, value), "");
const char * myString = "some string";
nix_init_string(ctx, value, myString);
ASSERT_STREQ(myString, nix_get_string(ctx, value));
ASSERT_STREQ("a string", nix_get_typename(ctx, value));
ASSERT_EQ(NIX_TYPE_STRING, nix_get_type(ctx, value));
}
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)
{
ASSERT_EQ(nullptr, nix_get_path_string(ctx, nullptr));
ASSERT_DEATH(nix_get_path_string(ctx, value), "");
const char * p = "/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname";
nix_init_path_string(ctx, state, value, p);
ASSERT_STREQ(p, nix_get_path_string(ctx, value));
ASSERT_STREQ("a path", nix_get_typename(ctx, value));
ASSERT_EQ(NIX_TYPE_PATH, nix_get_type(ctx, value));
}
TEST_F(nix_api_expr_test, nix_build_and_init_list)
{
ASSERT_EQ(nullptr, nix_get_list_byidx(ctx, nullptr, state, 0));
ASSERT_EQ(0, nix_get_list_size(ctx, nullptr));
ASSERT_DEATH(nix_get_list_byidx(ctx, value, state, 0), "");
ASSERT_DEATH(nix_get_list_size(ctx, value), "");
int size = 10;
ListBuilder * builder = nix_make_list_builder(ctx, state, size);
Value * intValue = nix_alloc_value(ctx, state);
nix_init_int(ctx, intValue, 42);
nix_list_builder_insert(ctx, builder, 0, intValue);
nix_make_list(ctx, builder, value);
nix_list_builder_free(builder);
ASSERT_EQ(42, nix_get_int(ctx, nix_get_list_byidx(ctx, value, state, 0)));
ASSERT_EQ(nullptr, nix_get_list_byidx(ctx, value, state, 1));
ASSERT_EQ(10, nix_get_list_size(ctx, value));
ASSERT_STREQ("a list", nix_get_typename(ctx, value));
ASSERT_EQ(NIX_TYPE_LIST, nix_get_type(ctx, value));
// Clean up
nix_gc_decref(ctx, intValue);
}
TEST_F(nix_api_expr_test, nix_build_and_init_attr)
{
ASSERT_EQ(nullptr, nix_get_attr_byname(ctx, nullptr, state, 0));
ASSERT_EQ(nullptr, nix_get_attr_byidx(ctx, nullptr, state, 0, nullptr));
ASSERT_EQ(nullptr, nix_get_attr_name_byidx(ctx, nullptr, state, 0));
ASSERT_EQ(0, nix_get_attrs_size(ctx, nullptr));
ASSERT_EQ(false, nix_has_attr_byname(ctx, nullptr, state, "no-value"));
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"), "");
int size = 10;
const char ** out_name = (const char **) malloc(sizeof(char *));
BindingsBuilder * builder = nix_make_bindings_builder(ctx, state, size);
Value * intValue = nix_alloc_value(ctx, state);
nix_init_int(ctx, intValue, 42);
Value * stringValue = nix_alloc_value(ctx, state);
nix_init_string(ctx, stringValue, "foo");
nix_bindings_builder_insert(ctx, builder, "a", intValue);
nix_bindings_builder_insert(ctx, builder, "b", stringValue);
nix_make_attrs(ctx, value, builder);
nix_bindings_builder_free(builder);
ASSERT_EQ(2, nix_get_attrs_size(ctx, value));
Value * out_value = nix_get_attr_byname(ctx, value, state, "a");
ASSERT_EQ(42, nix_get_int(ctx, out_value));
nix_gc_decref(ctx, out_value);
out_value = nix_get_attr_byidx(ctx, value, state, 0, out_name);
ASSERT_EQ(42, nix_get_int(ctx, out_value));
ASSERT_STREQ("a", *out_name);
nix_gc_decref(ctx, out_value);
ASSERT_STREQ("a", nix_get_attr_name_byidx(ctx, value, state, 0));
ASSERT_EQ(true, nix_has_attr_byname(ctx, value, state, "b"));
ASSERT_EQ(false, nix_has_attr_byname(ctx, value, state, "no-value"));
out_value = nix_get_attr_byname(ctx, value, state, "b");
ASSERT_STREQ("foo", nix_get_string(ctx, out_value));
nix_gc_decref(nullptr, out_value);
out_value = nix_get_attr_byidx(ctx, value, state, 1, out_name);
ASSERT_STREQ("foo", nix_get_string(ctx, out_value));
ASSERT_STREQ("b", *out_name);
nix_gc_decref(nullptr, out_value);
ASSERT_STREQ("b", nix_get_attr_name_byidx(ctx, value, state, 1));
ASSERT_STREQ("a set", nix_get_typename(ctx, value));
ASSERT_EQ(NIX_TYPE_ATTRS, nix_get_type(ctx, value));
// Clean up
nix_gc_decref(ctx, intValue);
nix_gc_decref(ctx, stringValue);
free(out_name);
}
}

View file

@ -0,0 +1,54 @@
#pragma once
///@file
#include "tests/nix_api_util.hh"
#include "nix_api_store.h"
#include "nix_api_store_internal.h"
#include <filesystem>
#include <gtest/gtest.h>
namespace fs = std::filesystem;
namespace nixC {
class nix_api_store_test : public nix_api_util_context
{
public:
nix_api_store_test()
{
nix_libstore_init(ctx);
init_local_store();
};
~nix_api_store_test() override
{
nix_store_free(store);
for (auto & path : fs::recursive_directory_iterator(nixDir)) {
fs::permissions(path, fs::perms::owner_all);
}
fs::remove_all(nixDir);
}
Store * store;
std::string nixDir;
std::string nixStoreDir;
protected:
void init_local_store()
{
auto tmpl = nix::getEnv("TMPDIR").value_or("/tmp") + "/tests_nix-store.XXXXXX";
nixDir = mkdtemp((char *) tmpl.c_str());
nixStoreDir = nixDir + "/my_nix_store";
// Options documented in `nix help-stores`
const char * p1[] = {"store", nixStoreDir.c_str()};
const char * p2[] = {"state", (new std::string(nixDir + "/my_state"))->c_str()};
const char * p3[] = {"log", (new std::string(nixDir + "/my_log"))->c_str()};
const char ** params[] = {p1, p2, p3, nullptr};
store = nix_store_open(ctx, "local", params);
}
};
}

View file

@ -20,12 +20,14 @@ libstore-tests_EXTRA_INCLUDES = \
-I tests/unit/libstore-support \
-I tests/unit/libutil-support \
$(INCLUDE_libstore) \
$(INCLUDE_libutil)
$(INCLUDE_libstorec) \
$(INCLUDE_libutil) \
$(INCLUDE_libutilc)
libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES)
libstore-tests_LIBS = \
libstore-test-support libutil-test-support \
libstore libutil
libstore libstorec libutil libutilc
libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)

View file

@ -0,0 +1,93 @@
#include "nix_api_util.h"
#include "nix_api_util_internal.h"
#include "nix_api_store.h"
#include "nix_api_store_internal.h"
#include "tests/nix_api_store.hh"
namespace nixC {
void observe_string_cb(const char * start, unsigned int n, std::string * user_data)
{
*user_data = std::string(start);
}
std::string PATH_SUFFIX = "/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-name";
TEST_F(nix_api_util_context, nix_libstore_init)
{
auto ret = nix_libstore_init(ctx);
ASSERT_EQ(NIX_OK, ret);
}
TEST_F(nix_api_store_test, nix_store_get_uri)
{
std::string str;
auto ret = nix_store_get_uri(ctx, store, (void *) observe_string_cb, &str);
ASSERT_EQ(NIX_OK, ret);
ASSERT_STREQ("local", str.c_str());
}
TEST_F(nix_api_store_test, InvalidPathFails)
{
nix_store_parse_path(ctx, store, "invalid-path");
ASSERT_EQ(ctx->last_err_code, NIX_ERR_NIX_ERROR);
}
TEST_F(nix_api_store_test, ReturnsValidStorePath)
{
StorePath * result = nix_store_parse_path(ctx, store, (nixStoreDir + PATH_SUFFIX).c_str());
ASSERT_NE(result, nullptr);
ASSERT_STREQ("name", result->path.name().data());
ASSERT_STREQ(PATH_SUFFIX.substr(1).c_str(), result->path.to_string().data());
}
TEST_F(nix_api_store_test, SetsLastErrCodeToNixOk)
{
nix_store_parse_path(ctx, store, (nixStoreDir + PATH_SUFFIX).c_str());
ASSERT_EQ(ctx->last_err_code, NIX_OK);
}
TEST_F(nix_api_store_test, DoesNotCrashWhenContextIsNull)
{
ASSERT_NO_THROW(nix_store_parse_path(ctx, store, (nixStoreDir + PATH_SUFFIX).c_str()));
}
TEST_F(nix_api_store_test, get_version)
{
std::string str;
auto ret = nix_store_get_version(ctx, store, (void *) observe_string_cb, &str);
ASSERT_EQ(NIX_OK, ret);
ASSERT_STREQ(PACKAGE_VERSION, str.c_str());
}
TEST_F(nix_api_util_context, nix_store_open_dummy)
{
nix_libstore_init(ctx);
Store * store = nix_store_open(ctx, "dummy://", nullptr);
ASSERT_EQ(NIX_OK, ctx->last_err_code);
ASSERT_STREQ("dummy", store->ptr->getUri().c_str());
std::string str;
nix_store_get_version(ctx, store, (void *) observe_string_cb, &str);
ASSERT_STREQ("", str.c_str());
nix_store_free(store);
}
TEST_F(nix_api_util_context, nix_store_open_invalid)
{
nix_libstore_init(ctx);
Store * store = nix_store_open(ctx, "invalid://", nullptr);
ASSERT_EQ(NIX_ERR_NIX_ERROR, ctx->last_err_code);
ASSERT_EQ(nullptr, store);
nix_store_free(store);
}
TEST_F(nix_api_store_test, nix_store_is_valid_path_not_in_store)
{
StorePath * path = nix_store_parse_path(ctx, store, (nixStoreDir + PATH_SUFFIX).c_str());
ASSERT_EQ(false, nix_store_is_valid_path(ctx, store, path));
}
}

View file

@ -0,0 +1,27 @@
#pragma once
///@file
#include "nix_api_util.h"
#include <gtest/gtest.h>
namespace nixC {
class nix_api_util_context : public ::testing::Test
{
protected:
nix_api_util_context()
{
ctx = nix_c_context_create();
nix_libutil_init(ctx);
};
~nix_api_util_context() override
{
nix_c_context_free(ctx);
ctx = nullptr;
}
nix_c_context * ctx;
};
}

View file

@ -18,11 +18,12 @@ libutil-tests_SOURCES := $(wildcard $(d)/*.cc)
libutil-tests_EXTRA_INCLUDES = \
-I tests/unit/libutil-support \
$(INCLUDE_libutil)
$(INCLUDE_libutil) \
$(INCLUDE_libutilc)
libutil-tests_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES)
libutil-tests_LIBS = libutil-test-support libutil
libutil-tests_LIBS = libutil-test-support libutil libutilc
libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)

View file

@ -0,0 +1,145 @@
#include "config.hh"
#include "args.hh"
#include "nix_api_util.h"
#include "nix_api_util_internal.h"
#include "tests/nix_api_util.hh"
#include <gtest/gtest.h>
namespace nixC {
void observe_string_cb(const char * start, unsigned int n, std::string * user_data)
{
*user_data = std::string(start);
}
TEST_F(nix_api_util_context, nix_context_error)
{
std::string err_msg_ref;
try {
throw nix::Error("testing error");
} catch (nix::Error & e) {
err_msg_ref = e.what();
nix_context_error(ctx);
}
ASSERT_EQ(ctx->last_err_code, NIX_ERR_NIX_ERROR);
ASSERT_EQ(ctx->name, "nix::Error");
ASSERT_EQ(*ctx->last_err, err_msg_ref);
ASSERT_EQ(ctx->info->msg.str(), "testing error");
try {
throw std::runtime_error("testing exception");
} catch (std::exception & e) {
err_msg_ref = e.what();
nix_context_error(ctx);
}
ASSERT_EQ(ctx->last_err_code, NIX_ERR_UNKNOWN);
ASSERT_EQ(*ctx->last_err, err_msg_ref);
}
TEST_F(nix_api_util_context, nix_set_err_msg)
{
ASSERT_EQ(ctx->last_err_code, NIX_OK);
nix_set_err_msg(ctx, NIX_ERR_UNKNOWN, "unknown test error");
ASSERT_EQ(ctx->last_err_code, NIX_ERR_UNKNOWN);
ASSERT_EQ(*ctx->last_err, "unknown test error");
}
TEST(nix_api_util, nix_version_get)
{
ASSERT_EQ(std::string(nix_version_get()), PACKAGE_VERSION);
}
struct MySettings : nix::Config
{
nix::Setting<std::string> settingSet{this, "empty", "setting-name", "Description"};
};
MySettings mySettings;
static nix::GlobalConfig::Register rs(&mySettings);
TEST_F(nix_api_util_context, nix_setting_get)
{
ASSERT_EQ(ctx->last_err_code, NIX_OK);
std::string setting_value;
nix_err result = nix_setting_get(ctx, "invalid-key", (void *) observe_string_cb, &setting_value);
ASSERT_EQ(result, NIX_ERR_KEY);
result = nix_setting_get(ctx, "setting-name", (void *) observe_string_cb, &setting_value);
ASSERT_EQ(result, NIX_OK);
ASSERT_STREQ("empty", setting_value.c_str());
}
TEST_F(nix_api_util_context, nix_setting_set)
{
nix_err result = nix_setting_set(ctx, "invalid-key", "new-value");
ASSERT_EQ(result, NIX_ERR_KEY);
result = nix_setting_set(ctx, "setting-name", "new-value");
ASSERT_EQ(result, NIX_OK);
std::string setting_value;
result = nix_setting_get(ctx, "setting-name", (void *) observe_string_cb, &setting_value);
ASSERT_EQ(result, NIX_OK);
ASSERT_STREQ("new-value", setting_value.c_str());
}
TEST_F(nix_api_util_context, nix_err_msg)
{
// no error
EXPECT_THROW(nix_err_msg(nullptr, ctx, NULL), nix::Error);
// set error
nix_set_err_msg(ctx, NIX_ERR_UNKNOWN, "unknown test error");
// basic usage
std::string err_msg = nix_err_msg(NULL, ctx, NULL);
ASSERT_EQ(err_msg, "unknown test error");
// advanced usage
unsigned int sz;
err_msg = nix_err_msg(nix_c_context_create(), ctx, &sz);
ASSERT_EQ(sz, err_msg.size());
}
TEST_F(nix_api_util_context, nix_err_info_msg)
{
std::string err_info;
// no error
EXPECT_THROW(nix_err_info_msg(NULL, ctx, (void *) observe_string_cb, &err_info), nix::Error);
try {
throw nix::Error("testing error");
} catch (...) {
nix_context_error(ctx);
}
nix_err_info_msg(nix_c_context_create(), ctx, (void *) observe_string_cb, &err_info);
ASSERT_STREQ("testing error", err_info.c_str());
}
TEST_F(nix_api_util_context, nix_err_name)
{
std::string err_name;
// no error
EXPECT_THROW(nix_err_name(NULL, ctx, (void *) observe_string_cb, &err_name), nix::Error);
std::string err_msg_ref;
try {
throw nix::Error("testing error");
} catch (...) {
nix_context_error(ctx);
}
nix_err_name(nix_c_context_create(), ctx, (void *) observe_string_cb, &err_name);
ASSERT_EQ(std::string(err_name), "nix::Error");
}
TEST_F(nix_api_util_context, nix_err_code)
{
ASSERT_EQ(nix_err_code(ctx), NIX_OK);
nix_set_err_msg(ctx, NIX_ERR_UNKNOWN, "unknown test error");
ASSERT_EQ(nix_err_code(ctx), NIX_ERR_UNKNOWN);
}
}