Commit 8051d349 authored by Francis Dupont's avatar Francis Dupont

[65-libyang-generic] Imported generic stuff

parent 61289a15
SUBDIRS = . tests
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES) $(SYSREPO_CPPFLAGS)
AM_CXXFLAGS = $(KEA_CXXFLAGS)
lib_LTLIBRARIES = libkea-yang.la
libkea_yang_la_SOURCES = sysrepo_error.h
libkea_yang_la_SOURCES += sysrepo_connection.cc sysrepo_connection.h
libkea_yang_la_SOURCES += translator.cc translator.h
libkea_yang_la_SOURCES += watcher.cc watcher.h
libkea_yang_la_LIBADD = $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/cc/libkea-cc.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/log/libkea-log.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
libkea_yang_la_LIBADD += $(LOG4CPLUS_LIBS) $(BOOST_LIBS) $(SYSREPO_LIBS)
libkea_yang_la_LDFLAGS = -no-undefined -version-info 0:0:0
# Specify the headers for copying into the installation directory tree.
libkea_yang_includedir = $(pkgincludedir)/yang
libkea_yang_include_HEADERS = \
sysrepo_connection.h \
sysrepo_error.h \
translator.h \
watcher.h
EXTRA_DIST = yang.dox
CLEANFILES = *.gcno *.gcda
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <yang/sysrepo_connection.h>
namespace isc {
namespace yang {
SysrepoConnection::SysrepoConnection() {
}
SysrepoConnection::~SysrepoConnection() {
if (session_) {
session_->discard_changes();
session_->unlock_datastore();
session_->session_stop();
// how to call disconnect?
}
}
void
SysrepoConnection::connect() {
// Get a connection.
S_Connection conn(new Connection("kea-netconf"));
// Get a session.
session_.reset(new Session(conn, SR_DS_CANDIDATE));
// Get a from yang object.
}
void
SysrepoConnection::commit() {
if (!session_) {
isc_throw(SysrepoConnectionError, "session not established");
}
session_->commit();
}
}
}
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef NETCONF_CONNECTION_H
#define NETCONF_CONNECTION_H
#include <exceptions/exceptions.h>
#include <sysrepo-cpp/Session.h>
namespace isc {
namespace yang {
class SysrepoConnectionError : public Exception {
public:
SysrepoConnectionError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
class SysrepoConnection {
public:
SysrepoConnection();
virtual ~SysrepoConnection();
void connect();
void commit();
private:
S_Session session_;
};
} // sysrepo
} // isc
#endif /* NETCONF_CONNECTION_H_ */
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef ISC_SYSREPO_ERROR_H
#define ISC_SYSREPO_ERROR_H 1
#include <exceptions/exceptions.h>
namespace isc {
namespace yang {
/// @brief Sysrepo error.
class SysrepoError : public isc::Exception {
public:
SysrepoError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what)
{}
};
}; // end of namespace isc::yang
}; // end of namespace isc
#endif // ISC_SYSREPO_ERROR_H
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES) $(SYSREPO_CPPFLAGS)
AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples\"
AM_CXXFLAGS = $(KEA_CXXFLAGS)
if USE_STATIC_LINK
AM_LDFLAGS = -static
endif
CLEANFILES = *.gcno *.gcda
TESTS_ENVIRONMENT = \
$(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
TESTS =
if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = translator_unittests.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(top_builddir)/src/lib/yang/testutils/libyangtest.la
run_unittests_LDADD += $(top_builddir)/src/lib/yang/libkea-yang.la
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
run_unittests_LDADD += $(LOG4CPLUS_LIBS) $(BOOST_LIBS)
run_unittests_LDADD += $(SYSREPO_LIBS) $(GTEST_LDADD)
endif
noinst_PROGRAMS = $(TESTS)
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <gtest/gtest.h>
#include <util/unittests/run_all.h>
#include <log/logger_support.h>
int
main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
isc::log::initLogger();
return (isc::util::unittests::run_all());
}
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <yang/translator.h>
#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
using namespace std;
using namespace isc;
using namespace isc::data;
using namespace isc::yang;
namespace {
// Test constructor.
TEST(TranslatorBasicTest, constructor) {
// Get a connection.
S_Connection conn(new Connection("translator unittests"));
// Get a session.
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
// Get a translator object.
boost::scoped_ptr<TranslatorBasic> t_obj;
EXPECT_NO_THROW(t_obj.reset(new TranslatorBasic(sess)));
}
// Test basic yang value to JSON using the static method.
TEST(TranslatorBasicTest, valueFrom) {
S_Val s_val;
ConstElementPtr elem;
// Null.
EXPECT_THROW(TranslatorBasic::value(s_val), BadValue);
// No easy and direct way to build a container or a list...
// String.
string str("foo");
s_val.reset(new Val(str.c_str(), SR_STRING_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::string, elem->getType());
EXPECT_EQ(str, elem->stringValue());
elem.reset();
// Bool.
s_val.reset(new Val(false, SR_BOOL_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::boolean, elem->getType());
EXPECT_FALSE(elem->boolValue());
elem.reset();
// Unsigned 8 bit integer.
uint8_t u8(123);
s_val.reset(new Val(u8, SR_UINT8_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(u8, elem->intValue());
elem.reset();
// Unsigned 16 bit integer.
uint16_t u16(12345);
s_val.reset(new Val(u16, SR_UINT16_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(u16, elem->intValue());
elem.reset();
// Unsigned 32 bit integer.
uint32_t u32(123456789);
s_val.reset(new Val(u32, SR_UINT32_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(u32, elem->intValue());
elem.reset();
// Signed 8 bit integer.
int8_t s8(-123);
s_val.reset(new Val(s8, SR_INT8_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(s8, elem->intValue());
elem.reset();
// Signed 16 bit integer.
int16_t s16(-12345);
s_val.reset(new Val(s16, SR_INT16_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(s16, elem->intValue());
elem.reset();
// Signed 32 bit integer.
int32_t s32(-123456789);
s_val.reset(new Val(s32, SR_INT32_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(s32, elem->intValue());
elem.reset();
// Identity reference.
s_val.reset(new Val(str.c_str(), SR_IDENTITYREF_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::string, elem->getType());
EXPECT_EQ(str, elem->stringValue());
elem.reset();
// Enumeration item.
s_val.reset(new Val(str.c_str(), SR_ENUM_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::string, elem->getType());
EXPECT_EQ(str, elem->stringValue());
elem.reset();
// Binary.
string binary("Zm9vYmFy");
s_val.reset(new Val(binary.c_str(), SR_BINARY_T));
EXPECT_NO_THROW(elem = TranslatorBasic::value(s_val));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::string, elem->getType());
EXPECT_EQ("foobar", elem->stringValue());
elem.reset();
// Unknown / unsupported.
double d64(.1234);
s_val.reset(new Val(d64));
EXPECT_THROW(TranslatorBasic::value(s_val), NotImplemented);
}
// Test basic yang value to JSON using sysrepo test models.
TEST(TranslatorBasicTest, getItem) {
// Get a translator object to play with.
S_Connection conn(new Connection("translator unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorBasic> t_obj;
ASSERT_NO_THROW(t_obj.reset(new TranslatorBasic(sess)));
// Container.
string xpath = "/example-module:container/list";
S_Val s_val;
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
ConstElementPtr elem;
EXPECT_NO_THROW(elem = t_obj->getItem("/example-module:container"));
EXPECT_FALSE(elem);
elem.reset();
// List.
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::list, elem->getType());
EXPECT_EQ(0, elem->size());
elem.reset();
// String.
xpath = "/test-module:main/string";
s_val.reset(new Val("str", SR_STRING_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::string, elem->getType());
EXPECT_EQ("str", elem->stringValue());
elem.reset();
// Bool.
xpath = "/test-module:main/boolean";
s_val.reset(new Val(true, SR_BOOL_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::boolean, elem->getType());
EXPECT_TRUE(elem->boolValue());
elem.reset();
// Unsigned 8 bit integer.
xpath = "/test-module:main/ui8";
uint8_t u8(8);
s_val.reset(new Val(u8, SR_UINT8_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(8, elem->intValue());
elem.reset();
// Unsigned 16 bit integer.
xpath = "/test-module:main/ui16";
uint16_t u16(16);
s_val.reset(new Val(u16, SR_UINT16_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(16, elem->intValue());
elem.reset();
// Unsigned 32 bit integer.
xpath = "/test-module:main/ui32";
uint32_t u32(32);
s_val.reset(new Val(u32, SR_UINT32_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(32, elem->intValue());
elem.reset();
// Signed 8 bit integer.
xpath = "/test-module:main/i8";
int8_t s8(8);
s_val.reset(new Val(s8, SR_INT8_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(8, elem->intValue());
elem.reset();
// Signed 16 bit integer.
xpath = "/test-module:main/i16";
int16_t s16(16);
s_val.reset(new Val(s16, SR_INT16_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(16, elem->intValue());
elem.reset();
// Signed 32 bit integer.
xpath = "/test-module:main/i32";
int32_t s32(32);
s_val.reset(new Val(s32, SR_INT32_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::integer, elem->getType());
EXPECT_EQ(32, elem->intValue());
elem.reset();
// Identity reference.
xpath = "/test-module:main/id_ref";
s_val.reset(new Val("id_1", SR_IDENTITYREF_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::string, elem->getType());
EXPECT_EQ("id_1", elem->stringValue());
elem.reset();
// Enumeration item.
xpath = "/test-module:main/enum";
s_val.reset(new Val("maybe", SR_ENUM_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::string, elem->getType());
EXPECT_EQ("maybe", elem->stringValue());
elem.reset();
// Binary.
xpath = "/test-module:main/raw";
s_val.reset(new Val("Zm9vYmFy", SR_BINARY_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::string, elem->getType());
EXPECT_EQ("foobar", elem->stringValue());
elem.reset();
// Leaf-list: not yet exist.
xpath = "/test-module:main/numbers";
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
EXPECT_FALSE(elem);
elem.reset();
// No easy way to create it empty.
// Leaf-list: 1, 2 and 3.
u8 = 1;
s_val.reset(new Val(u8, SR_UINT8_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
u8 = 2;
s_val.reset(new Val(u8, SR_UINT8_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
u8 = 3;
s_val.reset(new Val(u8, SR_UINT8_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_NO_THROW(elem = t_obj->getItems(xpath));
ASSERT_TRUE(elem);
ASSERT_EQ(Element::list, elem->getType());
EXPECT_EQ(3, elem->size());
EXPECT_EQ("[ 1, 2, 3 ]", elem->str());
elem.reset();
// Unknown / unsupported.
xpath = "/test-module:main/dec64";
s_val.reset(new Val(9.85));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
EXPECT_THROW(elem = t_obj->getItem(xpath), NotImplemented);
elem.reset();
// Not found.
xpath = "/test-module:main/no_such_string";
EXPECT_NO_THROW(sess->delete_item(xpath.c_str()));
EXPECT_NO_THROW(elem = t_obj->getItem(xpath));
EXPECT_FALSE(elem);
elem.reset();
// Check error.
xpath = "null";
try {
elem = t_obj->getItem(xpath);
ADD_FAILURE() << "expected exception";
} catch (const SysrepoError& ex) {
EXPECT_EQ("sysrepo error getting item at 'null': Invalid argument",
string(ex.what()));
} catch (const std::exception& ex) {
ADD_FAILURE() << "unexpected exception with: " << ex.what();
}
}
// Test JSON to basic yang value using the static method.
TEST(TranslatorBasicTest, valueTo) {
// Null.
ConstElementPtr elem;
EXPECT_THROW(TranslatorBasic::value(elem, SR_STRING_T), BadValue);
// Container.
elem = Element::createMap();
EXPECT_THROW(TranslatorBasic::value(elem, SR_CONTAINER_T), NotImplemented);
EXPECT_THROW(TranslatorBasic::value(elem, SR_CONTAINER_PRESENCE_T), NotImplemented);
// List.
elem = Element::createList();
S_Val s_val;
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_LIST_T));
EXPECT_FALSE(s_val);
s_val.reset();
// String.
string str("foo");
elem = Element::create(str);
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_STRING_T));
ASSERT_TRUE(s_val);
ASSERT_EQ(SR_STRING_T, s_val->type());
EXPECT_EQ(str, string(s_val->data()->get_string()));
s_val.reset();
// Bool.
elem = Element::create(false);
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_BOOL_T));
ASSERT_TRUE(s_val);
ASSERT_EQ(SR_BOOL_T, s_val->type());
EXPECT_FALSE(s_val->data()->get_bool());
s_val.reset();
// Unsigned 8 bit integer.
elem = Element::create(123);
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_UINT8_T));
ASSERT_TRUE(s_val);
ASSERT_EQ(SR_UINT8_T, s_val->type());
EXPECT_EQ(123, s_val->data()->get_uint8());
elem.reset();
// Unsigned 16 bit integer.
elem = Element::create(12345);
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_UINT16_T));
ASSERT_TRUE(s_val);
ASSERT_EQ(SR_UINT16_T, s_val->type());
EXPECT_EQ(12345, s_val->data()->get_uint16());
elem.reset();
// Unsigned 32 bit integer.
elem = Element::create(123456789);
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_UINT32_T));
ASSERT_TRUE(s_val);
ASSERT_EQ(SR_UINT32_T, s_val->type());
EXPECT_EQ(123456789, s_val->data()->get_uint32());
elem.reset();
// Signed 8 bit integer.
elem = Element::create(-123);
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_INT8_T));
ASSERT_TRUE(s_val);
ASSERT_EQ(SR_INT8_T, s_val->type());
EXPECT_EQ(-123, s_val->data()->get_int8());
elem.reset();
// Signed 16 bit integer.
elem = Element::create(-12345);
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_INT16_T));
ASSERT_TRUE(s_val);
ASSERT_EQ(SR_INT16_T, s_val->type());
EXPECT_EQ(-12345, s_val->data()->get_int16());
elem.reset();
// Signed 32 bit integer.
elem = Element::create(-123456789);
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_INT32_T));
ASSERT_TRUE(s_val);
ASSERT_EQ(SR_INT32_T, s_val->type());
EXPECT_EQ(-123456789, s_val->data()->get_int32());
elem.reset();