diff options
Diffstat (limited to 'ext/librethinkdbxx/test/testlib.cc')
-rw-r--r-- | ext/librethinkdbxx/test/testlib.cc | 356 |
1 files changed, 0 insertions, 356 deletions
diff --git a/ext/librethinkdbxx/test/testlib.cc b/ext/librethinkdbxx/test/testlib.cc deleted file mode 100644 index ddc9cc27..00000000 --- a/ext/librethinkdbxx/test/testlib.cc +++ /dev/null @@ -1,356 +0,0 @@ -#include <algorithm> -#include <regex> -#include <thread> -#include <chrono> -#include <unistd.h> - -#include "testlib.h" - -int verbosity = 0; - -int failed = 0; -int count = 0; -std::vector<std::pair<const char*, bool>> section; - -std::unique_ptr<R::Connection> conn; - -// std::string to_string(const R::Cursor&) { -// return "<Cursor>"; -// } - -std::string to_string(const R::Term& query) { - return to_string(query.get_datum()); -} - -std::string to_string(const R::Datum& datum) { - return datum.as_json(); -} - -std::string to_string(const R::Object& object) { - auto it = object.find("special"); - if (it != object.end()) { - std::string type = *(it->second).get_string(); - auto bag = object.find(type); - if (bag != object.end()) { - return to_string((R::Datum)bag->second); - } - } - - return to_string((R::Datum)object); -} - -std::string to_string(const R::Error& error) { - return "Error(\"" + error.message + "\")"; -} - -void enter_section(const char* name) { - if (verbosity == 0) { - section.emplace_back(name, true); - } else { - printf("%sSection %s\n", indent(), name); - section.emplace_back(name, false); - } -} - -void section_cleanup() { - R::db("test").table_list().for_each([=](R::Var table) { - return R::db("test").table_drop(*table); - }).run(*conn); -} - -void exit_section() { - section.pop_back(); -} - -std::string to_string(const err& error) { - return "Error(\"" + error.convert_type() + ": " + error.message + "\")"; -} - -bool equal(const R::Error& a, const err& b) { - // @TODO: I think the proper solution to this proble is to in fact create - // a hierarchy of exception types. This would not only simplify these - // error cases, but could be of great use to the user. - std::string error_type = b.convert_type(); - if (error_type == "ReqlServerCompileError" && - a.message.find("ReqlCompileError") != std::string::npos) { - return true; - } - - return b.trim_message(a.message) == (error_type + ": " + b.message); -} - -bool match(const char* pattern, const char* string) { - return std::regex_match(string, std::regex(pattern)); -} - -bool equal(const R::Error& a, const err_regex& b) { - if (b.message == "Object keys must be strings" && - a.message == "runtime error: Expected type STRING but found NUMBER.") { - return true; - } - return match(b.regex().c_str(), a.message.c_str()); -} - -std::string to_string(const err_regex& error) { - return "err_regex(" + error.type + ", " + error.message + ")"; -} - -R::Object partial(R::Object&& object) { - return R::Object{{"special", "partial"}, {"partial", std::move(object)}}; -} - -R::Datum uuid() { - return R::Object{{"special", "uuid"}}; -} - -R::Object arrlen(int n, R::Datum&& datum) { - return R::Object{{"special", "arrlen"},{"len",n},{"of",datum}}; -} - -R::Object arrlen(int n) { - return R::Object{{"special", "arrlen"},{"len",n}}; -} - -std::string repeat(std::string&& s, int n) { - std::string string; - string.reserve(n * s.size()); - for (int i = 0; i < n; ++i) { - string.append(s); - } - return string; -} - -R::Term fetch(R::Cursor& cursor, int count, double timeout) { - // printf("fetch(..., %d, %lf)\n", count, timeout); - R::Array array; - int deadline = time(NULL) + int(timeout); - for (int i = 0; count == -1 || i < count; ++i) { - // printf("fetching next (%d)\n", i); - time_t now = time(NULL); - if (now > deadline) break; - - try { - array.emplace_back(cursor.next(deadline - now)); - // printf("got %s\n", write_datum(array[array.size()-1]).c_str()); - } catch (const R::Error &e) { - if (e.message != "next: No more data") { - throw e; // rethrow - } - - break; - } catch (const R::TimeoutException &e){ - // printf("fetch timeout\n"); - break; - } - } - - return expr(std::move(array)); -} - -R::Object bag(R::Array&& array) { - return R::Object{{"special", "bag"}, {"bag", std::move(array)}}; -}; - -R::Object bag(R::Datum&& d) { - return R::Object{{"special", "bag"}, {"bag", std::move(d)}}; -}; - -std::string string_key(const R::Datum& datum) { - const std::string* string = datum.get_string(); - if (string) return *string; - return datum.as_json(); -} - -bool falsey(R::Datum&& datum) { - bool* boolean = datum.get_boolean(); - if (boolean) return !*boolean; - double* number = datum.get_number(); - if (number) return *number == 0; - return false; -} - -bool equal(const R::Datum& got, const R::Datum& expected) { - const std::string* string = expected.get_string(); - if (string) { - const R::Binary* binary = got.get_binary(); - if (binary) { - return *binary == R::Binary(*string); - } - } - if (expected.get_object() && expected.get_field("$reql_type$")) { - if (!got.get_field("$reql_type$")) { - R::Datum datum = got.to_raw(); - if (datum.get_field("$reql_type$")) { - return equal(datum, expected); - } - } - } - if (got.get_object() && got.get_field("$reql_type$")) { - const std::string* type = got.get_field("$reql_type$")->get_string(); - if (type && *type == "GROUPED_DATA" && - (!expected.get_object() || !expected.get_field("$reql_type$"))) { - const R::Array* data = got.get_field("data")->get_array(); - R::Object object; - for (R::Datum it : *data) { - object.emplace(string_key(it.extract_nth(0)), it.extract_nth(1)); - } - return equal(object, expected); - } - } - do { - if (!expected.get_object()) break; - if(!expected.get_field("special")) break; - const std::string* type = expected.get_field("special")->get_string(); - if (!type) break; - if (*type == "bag") { - const R::Datum* bag_datum = expected.get_field("bag"); - if (!bag_datum || !bag_datum->get_array()) { - break; - } - R::Array bag = *bag_datum->get_array(); - const R::Array* array = got.get_array(); - if (!array) { - return false; - } - if (bag.size() != array->size()) { - return false; - } - for (const auto& it : *array) { - auto ref = std::find(bag.begin(), bag.end(), it); - if (ref == bag.end()) return false; - bag.erase(ref); - } - return true; - } else if (*type == "arrlen") { - const R::Datum* len_datum = expected.get_field("len"); - if (!len_datum) break; - const double *len = len_datum->get_number(); - if (!len) break; - const R::Array* array = got.get_array(); - if (!array) break; - return array->size() == *len; - } else if (*type == "partial") { - const R::Object* object = got.get_object(); - if (object) { - const R::Datum* partial_datum = expected.get_field("partial"); - if (!partial_datum) break; - const R::Object* partial = partial_datum->get_object(); - if (!partial) break; - for (const auto& it : *partial) { - if (!object->count(it.first) || !equal((*object).at(it.first), it.second)) { - return false; - } - return true; - } - } - const R::Array* array = got.get_array(); - if (array) { - const R::Datum* partial_datum = expected.get_field("partial"); - if (!partial_datum) break; - const R::Array* partial = partial_datum->get_array(); - if (!partial) break; - - for (const auto& want : *partial) { - bool match = false; - for (const auto& have : *array) { - if (equal(have, want)) { - match = true; - break; - } - } - if (match == false) return false; - } - return true; - } - } else if(*type == "uuid") { - const std::string* string = got.get_string(); - if (string && string->size() == 36) { - return true; - } - } else if (*type == "regex") { - const R::Datum* regex_datum = expected.get_field("regex"); - if (!regex_datum) break; - const std::string* regex = regex_datum->get_string(); - if (!regex) break; - const std::string* str = got.get_string(); - if (!str) break; - return match(regex->c_str(), str->c_str()); - } - } while(0); - const R::Object* got_object = got.get_object(); - const R::Object* expected_object = expected.get_object(); - if (got_object && expected_object) { - R::Object have = *got_object; - for (const auto& it : *expected_object) { - auto other = have.find(it.first); - if (other == have.end()) return false; - if (!equal(other->second, it.second)) return false; - have.erase(other); - } - for (auto& it : have) { - if (!falsey(std::move(it.second))) { - return false; - } - } - return true; - } - const R::Array* got_array = got.get_array(); - const R::Array* expected_array = expected.get_array(); - if (got_array && expected_array) { - if (got_array->size() != expected_array->size()) return false; - for (R::Array::const_iterator i = got_array->begin(), j = expected_array->begin(); - i < got_array->end(); - i++, j++) { - if(!equal(*i, *j)) return false; - } - return true; - } - return got == expected; -} - -R::Object partial(R::Array&& array) { - return R::Object{{"special", "partial"}, {"partial", std::move(array)}}; -} - -R::Object regex(const char* pattern) { - return R::Object{{"special", "regex"}, {"regex", pattern}}; -} - -void clean_slate() { - R::table_list().for_each([](R::Var t){ return R::table_drop(*t); }); - R::db("rethinkdb").table("_debug_scratch").delete_().run(*conn); -} - -const char* indent() { - static const char spaces[] = " "; - return spaces + sizeof(spaces) - 1 - 2 * section.size(); -} - -std::string truncate(std::string&& string) { - if (string.size() > 200) { - return string.substr(0, 197) + "..."; - } - return string; -} - -int len(const R::Datum& d) { - const R::Array* arr = d.get_array(); - if (!arr) throw ("testlib: len: expected an array but got " + to_string(d)); - return arr->size(); -} - -R::Term wait(int n) { - std::this_thread::sleep_for(std::chrono::seconds(n)); - return R::expr(n); -} - -R::Datum nil = R::Nil(); - -R::Array append(R::Array lhs, R::Array rhs) { - if (lhs.empty()) { - return rhs; - } - lhs.reserve(lhs.size() + rhs.size()); - std::move(std::begin(rhs), std::end(rhs), std::back_inserter(lhs)); - return lhs; -} |