Commit d807907b authored by Matthieu Dorier's avatar Matthieu Dorier
Browse files

started unit tests for jx9 API

parent 39a52f02
......@@ -11,24 +11,31 @@ namespace sonata {
#define CHECK_ARGS(__fun__, __num__) do {\
if(argc != __num__) {\
unqlite_context_throw_error_format(pCtx, UNQLITE_CTX_ERR,\
#__fun__ ": unexpected number of aruments (%d, expected %d)", argc, __num__);\
return UNQLITE_ABORT;\
#__fun__ ": unexpected number of aruments (%d, expected %d)", argc, __num__);\
unqlite_result_null(pCtx);\
return UNQLITE_OK;\
}} while(false)
#define CHECK_ARGS2(__fun__, __num1__, __num2__) do {\
if(argc != (__num1__) && argc != (__num2__)) {\
unqlite_context_throw_error_format(pCtx, UNQLITE_CTX_ERR,\
#__fun__ ": unexpected number of aruments (%d, expected %d or %d)", argc, (__num1__), (__num2__));\
return UNQLITE_ABORT;\
unqlite_result_null(pCtx);\
return UNQLITE_OK;\
}} while(false)
#define CATCH_AND_ABORT(__fun__)\
catch(const Exception& ex) {\
unqlite_context_throw_error_format(pCtx, UNQLITE_CTX_ERR,\
#__fun__ " threw an exception: %s", ex.what());\
return UNQLITE_ABORT;\
unqlite_result_null(pCtx);\
return UNQLITE_OK;\
}
#define LOG_ERROR(__fun__)\
unqlite_context_throw_error_format(pCtx, UNQLITE_CTX_WARNING,\
#__fun__ " threw an exception: %s", ex.what());
struct database_info {
std::string address;
......@@ -101,6 +108,7 @@ int UnQLiteVM::snta_db_create(unqlite_context *pCtx, int argc, unqlite_value **a
db_type,
config.str(),
token);
unqlite_result_bool(pCtx, true);
} CATCH_AND_ABORT(snta_db_create);
return UNQLITE_OK;
}
......@@ -126,6 +134,7 @@ int UnQLiteVM::snta_db_attach(unqlite_context *pCtx, int argc, unqlite_value **a
db_type,
config.str(),
token);
unqlite_result_bool(pCtx, true);
} CATCH_AND_ABORT(snta_db_attach);
return UNQLITE_OK;
}
......@@ -145,6 +154,7 @@ int UnQLiteVM::snta_db_detach(unqlite_context *pCtx, int argc, unqlite_value **a
provider_id,
db_name,
token);
unqlite_result_bool(pCtx, true);
} CATCH_AND_ABORT(snta_db_detach);
return UNQLITE_OK;
}
......@@ -164,6 +174,7 @@ int UnQLiteVM::snta_db_destroy(unqlite_context *pCtx, int argc, unqlite_value **
provider_id,
db_name,
token);
unqlite_result_bool(pCtx, true);
} CATCH_AND_ABORT(snta_db_destroy);
return UNQLITE_OK;
}
......@@ -187,7 +198,6 @@ int UnQLiteVM::sntd_coll_create(unqlite_context *pCtx, int argc, unqlite_value *
int ret = unqlite_result_bool(pCtx, b);
if(ret != UNQLITE_OK)
throw Exception("Could not set result in unqlite context");
} CATCH_AND_ABORT(sntd_coll_create);
return UNQLITE_OK;
}
......@@ -219,10 +229,18 @@ int UnQLiteVM::sntd_coll_open(unqlite_context *pCtx, int argc, unqlite_value **a
throw Exception("Invalid collection name argument");
Database db = vm->m_backend->m_client.open(db_info.address, db_info.provider_id, db_info.db_name, false);
bool b = db.exists(coll_name);
unqlite_value* result = unqlite_context_new_array(pCtx);
unqlite_array_add_strkey_elem(result, "database_info", argv[0]);
unqlite_array_add_strkey_elem(result, "collection_name", argv[1]);
int ret = unqlite_result_value(pCtx, result);
unqlite_value* result;
int ret;
if(b) {
result = unqlite_context_new_array(pCtx);
unqlite_array_add_strkey_elem(result, "database_info", argv[0]);
unqlite_array_add_strkey_elem(result, "collection_name", argv[1]);
ret = unqlite_result_value(pCtx, result);
} else {
result = unqlite_context_new_scalar(pCtx);
unqlite_value_null(result);
ret = unqlite_result_value(pCtx, result);
}
if(ret != UNQLITE_OK)
throw Exception("Could not set result in unqlite context");
} CATCH_AND_ABORT(sntd_coll_exists);
......@@ -260,7 +278,7 @@ int UnQLiteVM::sntd_execute(unqlite_context *pCtx, int argc, unqlite_value **arg
}
int UnQLiteVM::sntc_store(unqlite_context *pCtx, int argc, unqlite_value **argv) {
UnQLiteVM* vm = reinterpret_cast<UnQLiteVM*>(unqlite_context_user_data(pCtx));
// TODO
return UNQLITE_OK;
}
......
......@@ -75,6 +75,9 @@ class UnQLiteVM {
UnQLiteValue operator[](const std::string& name) const {
unqlite_value* value = unqlite_vm_extract_variable(m_vm, name.c_str());
if(value == nullptr) {
return UnQLiteValue(UnQLiteValue::Null(), m_vm);
}
return UnQLiteValue(value, m_vm, nullptr);
}
......@@ -179,8 +182,6 @@ class UnQLiteVM {
error += std::string(errorBuffer, len);
throw Exception(error);
}
error += "(unknown)";
throw Exception(error);
}
static int output_callback(const void *pOutput, unsigned int nOutputLen, void *pUserData) {
......
......@@ -526,45 +526,10 @@ class UnQLiteValue {
template<typename Stream>
Stream& printToStream(Stream& os) const {
if(is<int64_t>()) {
os << as<int64_t>();
} else if(is<double>()) {
os << as<double>();
} else if(is<bool>()) {
bool b = as<bool>();
if(b) os << "true";
else os << "false";
} else if(is<UnQLiteValue::Null>()) {
os << "null";
} else if(is<std::string>()) {
os << "\"" << as<std::string>() << "\"";
} else if(unqlite_value_is_json_array(m_value)
&& !unqlite_value_is_json_object(m_value)) {
os << "[ ";
size_t size = unqlite_array_count(m_value);
size_t i = 0;
const_cast<UnQLiteValue*>(this)->foreach([&os, size, &i](unsigned index, const UnQLiteValue& val) {
val.printToStream(os);
if(i < size-1)
os << ", ";
i += 1;
});
os << "]";
} else if(unqlite_value_is_json_object(m_value)) {
os << "{ ";
size_t size = unqlite_array_count(m_value);
size_t i = 0;
const_cast<UnQLiteValue*>(this)->foreach([&os, size, &i](const std::string& key, const UnQLiteValue& val) {
os << "\"" << key << "\" : ";
val.printToStream(os);
if(i < size-1)
os << ", ";
i += 1;
});
os << "}";
} else if(unqlite_value_is_resource(m_value)) {
os << "\"resource@" << std::hex
<< (intptr_t)unqlite_value_to_resource(m_value) << "\"";
if(is<std::string>()) {
os << "\"" << unqlite_value_to_string(m_value, nullptr) << "\"";
} else {
os << unqlite_value_to_string(m_value, nullptr);
}
return os;
}
......
$rc = TRUE;
print("test output")
$rc = TRUE;
print "Executing test on address ", $addr, "\n";
// Create a database
print "Executing snta_db_create test\n";
$rc = snta_db_create($addr, 0, "dbFromJx9", "unqlite", { path : "dbFromJx9" });
if($rc != TRUE) {
print "snta_db_create failed\n";
print db_errlog();
$rc = FALSE;
return;
} else {
print "snta_db_create was successful\n";
}
// Detach the database
print "Executing snta_db_detach test\n";
$rc = snta_db_detach($addr, 0, "dbFromJx9");
if($rc != TRUE) {
print "snta_db_detach failed\n";
print db_errlog();
$rc = FALSE;
return;
} else {
print "snta_db_detach was successful\n";
}
// Attach the database
print "Executing snta_db_attach test\n";
$rc = snta_db_attach($addr, 0, "dbFromJx9", "unqlite", { path : "dbFromJx9" });
if($rc != TRUE) {
print "snta_db_attach failed\n";
print db_errlog();
$rc = FALSE;
return;
} else {
print "snta_db_attach was successful\n";
}
// Destroy the database
print "Executing snta_db_destroy test\n";
$rc = snta_db_destroy($addr, 0, "dbFromJx9");
if($rc != TRUE) {
print db_errlog();
print "snta_db_destroy failed\n";
$rc = FALSE;
return;
} else {
print "snta_db_destroy was successful\n";
}
include_directories(../include)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test.json ${CMAKE_CURRENT_BINARY_DIR}/test.json COPYONLY)
file(GLOB JX9_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.jx9)
foreach(file ${JX9_TEST_FILES})
get_filename_component(filename ${file} NAME)
message(STATUS "Found Jx9 test file ${filename}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${filename} ${CMAKE_CURRENT_BINARY_DIR}/${filename} COPYONLY)
endforeach()
add_library(sonata-test Main.cpp)
target_link_libraries(sonata-test cppunit sonata-server sonata-admin sonata-client)
......@@ -20,8 +26,12 @@ target_link_libraries(CollectionTest sonata-test)
add_executable(ExecTest ExecTest.cpp)
target_link_libraries(ExecTest sonata-test)
add_executable(Jx9Test Jx9Test.cpp)
target_link_libraries(Jx9Test sonata-test)
add_test(NAME AdminTest COMMAND ./AdminTest AdminTest.xml)
add_test(NAME ClientTest COMMAND ./ClientTest ClientTest.xml)
add_test(NAME DatabaseTest COMMAND ./DatabaseTest DatabaseTest.xml)
add_test(NAME CollectionTest COMMAND ./CollectionTest CollectionTest.xml)
add_test(NAME ExecTest COMMAND ./ExecTest ExecTest.xml)
add_test(NAME Jx9Test COMMAND ./Jx9Test Jx9Test.xml)
......@@ -37,7 +37,6 @@ class ExecTest : public CppUnit::TestFixture
std::string addr = engine->self();
sonata::Database mydb = client.open(addr, 0, "mydb");
std::string code =
"$zCol = 'users';"
"if( db_exists($zCol) ){"
......
/*
* (C) 2020 The University of Chicago
*
* See COPYRIGHT in top-level directory.
*/
#include <cppunit/extensions/HelperMacros.h>
#include <dirent.h>
#include <algorithm>
#include <sonata/Client.hpp>
#include <sonata/Admin.hpp>
#include <spdlog/spdlog.h>
extern thallium::engine* engine;
using namespace std::string_literals;
class Jx9Test : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( Jx9Test );
CPPUNIT_TEST( testExec );
CPPUNIT_TEST_SUITE_END();
static constexpr const char* db_config = "{ \"path\" : \"mydb\" }";
static std::vector<std::string> list_jx9_files(const std::string& dirname) {
DIR *dir;
struct dirent *ent;
std::vector<std::string> result;
if((dir = opendir(dirname.c_str())) != nullptr) {
while((ent = readdir(dir)) != nullptr) {
result.push_back(dirname+"/"+ent->d_name);
}
closedir(dir);
} else {
/* could not open directory */
perror("");
exit(1);
}
auto it = std::remove_if(result.begin(), result.end(), [](const std::string& filename) {
size_t s = filename.size();
if(s < 5) return true;
auto extension = filename.substr(s-4, 4);
if(extension == ".jx9") return false;
else return true;
});
result.erase(it, result.end());
std::sort(result.begin(), result.end());
return result;
}
std::vector<std::string> m_jx9_files;
public:
void setUp() {}
void tearDown() {}
void testExec() {
m_jx9_files = list_jx9_files(".");
std::string addr = engine->self();
for(const auto& jx9_file : m_jx9_files) {
sonata::Admin admin(*engine);
admin.createDatabase(addr, 0, "mydb", "unqlite", db_config);
sonata::Client client(*engine);
sonata::Database mydb = client.open(addr, 0, "mydb");
std::ifstream is(jx9_file.c_str());
std::string code((std::istreambuf_iterator<char>(is)),
std::istreambuf_iterator<char>());
code = "$addr = \""s + addr +"\";\n" + code;
std::unordered_set<std::string> vars;
std::unordered_map<std::string,std::string> results;
vars.insert("rc");
vars.insert("__output__");
CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"this call to execute should not throw.",
mydb.execute(code, vars, &results));
if(jx9_file.find("failing") == std::string::npos) {
CPPUNIT_ASSERT_EQUAL_MESSAGE(
"rc should be true.",
std::string("true"), results["rc"]);
} else {
CPPUNIT_ASSERT_EQUAL_MESSAGE(
"rc should be false.",
std::string("false"), results["rc"]);
}
std::cout << results["__output__"];
admin.destroyDatabase(addr, 0, "mydb");
}
}
};
CPPUNIT_TEST_SUITE_REGISTRATION( Jx9Test );
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment