Browse Source

Added: `object`, `parser`, `config`

TODO: add tests for `parser`, `config`
master
Jessica James 6 years ago
parent
commit
17acd742e3
  1. 2
      src/common/CMakeLists.txt
  2. 147
      src/common/config.cpp
  3. 102
      src/common/object.cpp
  4. 42
      src/common/parser/parser.cpp
  5. 121
      src/common/parser/parser_manager.cpp
  6. 69
      src/common/serialize.cpp
  7. 68
      src/include/config.hpp
  8. 77
      src/include/impl/parser_manager.hpp
  9. 436
      src/include/object.hpp
  10. 58
      src/include/parser.hpp
  11. 41
      src/include/serialize.hpp
  12. 215
      src/include/util.hpp
  13. 2
      src/test/CMakeLists.txt
  14. 932
      src/test/object.cpp
  15. 20
      src/test/thread_pool.cpp
  16. 32
      src/test/util.cpp

2
src/common/CMakeLists.txt

@ -3,6 +3,6 @@ cmake_minimum_required(VERSION 3.8)
# Setup source files # Setup source files
include_directories(../include) include_directories(../include)
set(SOURCE_FILES set(SOURCE_FILES
timer/timer.cpp timer/timer_manager.cpp thread_pool.cpp timer/timer_context.cpp timer/cancel_token.cpp timer/synchronized_timer.cpp) timer/timer.cpp timer/timer_manager.cpp thread_pool.cpp timer/timer_context.cpp timer/cancel_token.cpp timer/synchronized_timer.cpp object.cpp parser/parser.cpp parser/parser_manager.cpp config.cpp serialize.cpp)
add_library(jessilib ${SOURCE_FILES}) add_library(jessilib ${SOURCE_FILES})

147
src/common/config.cpp

@ -0,0 +1,147 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include "config.hpp"
#include <cstring>
#include <fstream>
#include "assert.hpp"
#include "serialize.hpp"
namespace jessilib {
/** Error types */
config::file_error::file_error()
: std::runtime_error{ std::strerror(errno) } {
// Empty ctor body
}
config::file_error::file_error(const std::filesystem::path& in_filename)
: std::runtime_error{ "Error openening file \"" + std::string{ in_filename } + "\". Error: " + std::strerror(errno) } {
// Empty ctor body
};
/** config */
object config::data() const {
std::shared_lock<std::shared_mutex> guard{ m_mutex };
return m_data;
}
std::filesystem::path config::filename() const {
std::shared_lock<std::shared_mutex> guard{ m_mutex };
return m_filename;
}
std::string config::format() const {
std::shared_lock<std::shared_mutex> guard{ m_mutex };
return m_format;
}
/** Modifiers */
void config::set_data(const object& in_data) {
std::lock_guard<std::shared_mutex> guard{ m_mutex };
m_data = in_data;
}
/** File I/O */
void config::load(const std::filesystem::path& in_filename, const std::string& in_format) {
jessilib_assert(!in_filename.empty());
std::lock_guard<std::shared_mutex> guard{ m_mutex };
// Determine format
m_filename = in_filename;
m_format = get_format(m_filename, in_format);
// Load
m_data = read_object(m_filename, m_format);
}
void config::reload() {
std::lock_guard<std::shared_mutex> guard{ m_mutex };
if (jessilib_debug_assert(!m_filename.empty())
&& jessilib_debug_assert(!m_format.empty())) {
// Load data from disk
m_data = read_object(m_filename, m_format);
}
}
void config::write() const {
std::shared_lock<std::shared_mutex> guard{ m_mutex };
if (jessilib_debug_assert(!m_filename.empty())
&& jessilib_debug_assert(!m_format.empty())) {
// Write data to disk
write_object(m_data, m_filename, m_format);
}
}
void config::write(const std::filesystem::path& in_filename , const std::string& in_format) {
jessilib_assert(!in_filename.empty());
std::lock_guard<std::shared_mutex> guard{ m_mutex };
// Setup
m_filename = in_filename;
m_format = get_format(m_filename, in_format);
// Write
write_object(m_data, m_filename, m_format);
}
/** Static File I/O */
object config::read_object(const std::filesystem::path& in_filename, const std::string& in_format) {
// Open up file for reading
std::ifstream file{ in_filename, std::ios::in | std::ios::binary };
if (!file) {
// Failed to open the file; throw file_error
throw file_error( in_filename );
}
// Deserialize1
return deserialize_object(file, in_format);
}
void config::write_object(const object& in_object, const std::filesystem::path& in_filename, const std::string& in_format) {
// Open up file for writing
std::ofstream file{ in_filename, std::ios::out | std::ios::binary };
if (!file) {
// Failed to open the file; throw file_error
throw file_error( in_filename );
}
// Deserialize1
return serialize_object(file, in_object, in_format);
}
std::string get_format(const std::filesystem::path& in_filename, const std::string& in_format) {
if (!in_format.empty()) {
// Use specified format
return in_format;
}
// Try to determine format from filename
std::string extension = in_filename.extension();
if jessilib_assert(!extension.empty()) {
return extension.substr(1);
}
return extension;
}
} // namespace jessilib

102
src/common/object.cpp

@ -0,0 +1,102 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include "object.hpp"
namespace jessilib {
object::object(const object& in_object) {
m_value = in_object.m_value;
}
object::object(object&& in_object) {
m_value = std::move(in_object.m_value);
}
object::object(const char* in_str)
: m_value{ std::string{ in_str } } {
// Empty ctor body
}
object::object(const std::string_view& in_str)
: m_value{ std::string{ in_str.begin(), in_str.end() } } {
// Empty ctor body
}
/** Accessors */
bool object::null() const {
// There's something funny about variants holding nullptr_t
return std::holds_alternative<nullptr_t>(m_value);
}
size_t object::size() const {
// If we're null, we don't have any members
if (null()) {
return 0;
}
// Try array
{
const array_t* array = std::get_if<array_t>(&m_value);
if (array != nullptr) {
return array->size();
}
}
// Try map
{
const map_t* map = std::get_if<map_t>(&m_value);
if (map != nullptr) {
return map->size();
}
}
// We're a single value
return 1;
}
const object& object::operator[](const std::string& in_key) const {
auto result = std::get_if<map_t>(&m_value);
if (result != nullptr) {
auto itr = result->find(in_key);
if (itr != result->end()) {
return itr->second;
}
}
static const object s_null_object;
return s_null_object;
}
object& object::operator[](const std::string& in_key) {
if (null()) {
return m_value.emplace<map_t>()[in_key];
}
auto result = std::get_if<map_t>(&m_value);
if (result != nullptr) {
return result->operator[](in_key);
}
static thread_local object s_null_object;
s_null_object.m_value.emplace<nullptr_t>();
return s_null_object;
}
} // namespace jessilib

42
src/common/parser/parser.cpp

@ -0,0 +1,42 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include "parser.hpp"
#include <istream>
namespace jessilib {
object parser::deserialize(std::istream& in_stream) {
std::vector<char> data;
// Read entire stream into data
char buffer[1024];
while(!in_stream.eof()) {
in_stream.read(buffer, sizeof(buffer));
data.insert(data.end(), buffer, buffer + in_stream.gcount());
}
// Pass data to deserialize
return deserialize(std::string_view{ &data.front(), data.size() });
}
void parser::serialize(std::ostream& in_stream, const object& in_object) {
in_stream << serialize(in_object);
}
} // namespace jessilib

121
src/common/parser/parser_manager.cpp

@ -0,0 +1,121 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include "impl/parser_manager.hpp"
#include "parser.hpp"
#include "assert.hpp"
namespace jessilib {
namespace impl {
parser_manager::registration::registration(id in_id)
: m_id{ in_id } {
// Empty ctor body
}
parser_manager::registration::registration(const std::string& in_format)
: m_format{ in_format } {
// Empty ctor body
}
parser_manager::registration::registration(id in_id, const std::string& in_format)
: m_id{ in_id },
m_format{ in_format } {
// Empty ctor body
}
bool parser_manager::registration::operator<(const registration& rhs) const {
if (m_id != 0 && rhs.m_id) {
// Both registrations have an ID; this is a search by ID
return m_id < rhs.m_id;
}
// One of the registrations lacked an ID; this must be a search by format
return m_format < rhs.m_format;
}
parser_manager::id parser_manager::register_parser(std::shared_ptr<parser> in_parser, const std::string& in_format, bool in_force) {
std::lock_guard<std::shared_mutex> guard{ m_mutex };
// Check for any existing parser
auto itr = m_parsers.find(in_format);
if (itr != m_parsers.end()) {
// A parser already exists; return or replace
if (!in_force) {
return bad_id;
}
// Remove existing parser and registration
m_parsers.erase(itr);
m_registrations.erase(registration{ in_format });
}
// Register our new parser
id parser_id = ++m_last_id;
m_parsers.emplace(in_format, in_parser);
m_registrations.emplace(parser_id, in_format);
// Our parser is registered; return the parser ID we just registered
return parser_id;
}
void parser_manager::unregister_parser(id in_id) {
std::lock_guard<std::shared_mutex> guard{ m_mutex };
// Search for registration
auto itr = m_registrations.find(registration{ in_id });
if (itr == m_registrations.end()) {
// Parser already unregistered; do nothing
return;
}
// Unregister
registration removed_registration = *itr;
m_registrations.erase(itr);
m_parsers.erase(removed_registration.m_format);
}
std::shared_ptr<parser> parser_manager::find_parser(const std::string& in_format) {
std::shared_lock<std::shared_mutex> guard{ m_mutex };
// Search for the parser by key
auto itr = m_parsers.find(in_format);
if (itr != m_parsers.end()) {
// Found our parser; return
return itr->second;
}
// No parser exists for the given format
return nullptr;
}
void parser_manager::clear() {
std::lock_guard<std::shared_mutex> guard{ m_mutex };
m_parsers.clear();
m_registrations.clear();
}
/** Singleton */
parser_manager& parser_manager::instance() {
static parser_manager s_parser_manager{};
return s_parser_manager;
}
} // namespace jessilib
} // namespace jessilib

69
src/common/serialize.cpp

@ -0,0 +1,69 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include "serialize.hpp"
#include "impl/parser_manager.hpp"
#include "parser.hpp"
namespace jessilib {
/** Exception types */
format_not_available::format_not_available(const std::string& in_format)
: std::runtime_error{ "Format \"" + in_format + "\"not recognized" } {
// Empty ctor body
};
/** Helpers */
std::shared_ptr<parser> get_parser(const std::string& in_format) {
auto parser = impl::parser_manager::instance().find_parser(in_format);
if (parser == nullptr) {
throw format_not_available{ in_format };
}
return parser;
}
/** Deserialization */
object deserialize_object(const std::string& in_data, const std::string& in_format) {
return deserialize_object(std::string_view{ &in_data.front(), in_data.size() }, in_format);
}
object deserialize_object(const std::vector<char>& in_data, const std::string& in_format) {
return deserialize_object(std::string_view{ &in_data.front(), in_data.size() }, in_format);
}
object deserialize_object(std::string_view in_data, const std::string& in_format) {
return get_parser(in_format)->deserialize(in_data);
}
object deserialize_object(std::istream& in_stream, const std::string& in_format) {
return get_parser(in_format)->deserialize(in_stream);
}
/** Serialization */
std::string serialize_object(const object& in_object, const std::string& in_format) {
return get_parser(in_format)->serialize(in_object);
}
void serialize_object(std::ostream& in_stream, const object& in_object, const std::string& in_format) {
get_parser(in_format)->serialize(in_stream, in_object);
}
} // namespace jessilib

68
src/include/config.hpp

@ -0,0 +1,68 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#pragma once
#include <vector>
#include <string>
#include <istream>
#include <filesystem>
#include <shared_mutex>
#include "object.hpp"
namespace jessilib {
class config {
public:
/** Types */
class file_error : public std::runtime_error {
public:
file_error();
file_error(const std::filesystem::path& in_filename);
};
/** Accessors */
object data() const;
std::filesystem::path filename() const;
std::string format() const;
/** Modifiers */
void set_data(const object& in_data);
/** File I/O */
void load(const std::filesystem::path& in_filename, const std::string& in_format = {});
void reload();
void write() const;
void write(const std::filesystem::path& in_filename , const std::string& in_format = {});
/** Static File I/O */
static object read_object(const std::filesystem::path& in_filename, const std::string& in_format = {});
static void write_object(const object& in_object, const std::filesystem::path& in_filename, const std::string& in_format = {});
/** Static helpers */
static std::string get_format(const std::filesystem::path& in_filename, const std::string& in_format = {});
private:
mutable std::shared_mutex m_mutex;
object m_data;
std::string m_format;
std::filesystem::path m_filename;
};
} // namespace jessilib

77
src/include/impl/parser_manager.hpp

@ -0,0 +1,77 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#pragma once
#include <cstdint>
#include <memory>
#include <unordered_map>
#include <set>
#include <shared_mutex>
namespace jessilib {
class parser;
namespace impl {
class parser_manager {
public:
/** Types */
using id = size_t;
/** Constants */
static constexpr id bad_id = 0;
/** Methods */
id register_parser(std::shared_ptr<parser> in_parser, const std::string& in_format, bool in_force = false);
void unregister_parser(id in_id);
std::shared_ptr<parser> find_parser(const std::string& in_format);
void clear();
/** Singleton */
static parser_manager& instance();
private:
class registration {
public:
registration() = default;
registration(const registration&) = default;
registration(registration&&) = default;
explicit registration(id in_id);
explicit registration(const std::string& in_format);
registration(id in_id, const std::string& in_format);
registration& operator=(const registration&) = default;
registration& operator=(registration&&) = default;
bool operator<(const registration& rhs) const;
id m_id{};
std::string m_format;
};
std::shared_mutex m_mutex;
id m_last_id{};
std::set<registration> m_registrations; // This set and map could be condensed into a bimap
std::unordered_map<std::string, std::shared_ptr<parser>> m_parsers;
}; // parser_manager
} // namespace impl
} // namespace jessilib

436
src/include/object.hpp

@ -0,0 +1,436 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <map>
#include <variant>
#include <utility>
#include "util.hpp"
namespace jessilib {
class object {
public:
using array_t = std::vector<object>;
using map_t = std::map<std::string, object>;
/** is_backing */
template<typename T, typename enable = void>
struct is_backing {
static constexpr bool value = false;
};
template<typename T>
struct is_backing<T, typename std::enable_if<std::is_same<T, bool>::value>::type> {
static constexpr bool value = true;
using type = bool;
};
template<typename T>
struct is_backing<T, typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value>::type> {
static constexpr bool value = true;
using type = intmax_t;
};
template<typename T>
struct is_backing<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
static constexpr bool value = true;
using type = long double;
};
template<typename T>
struct is_backing<T, typename std::enable_if<std::is_same<T, std::string>::value>::type> {
static constexpr bool value = true;
using type = std::string;
};
template<typename T>
struct is_backing<T, typename std::enable_if<is_sequence_container<T>::value>::type> {
static constexpr bool value = true;
using type = array_t;
};
template<typename T>
struct is_backing<T, typename std::enable_if<std::is_same<T, map_t>::value>::type> {
static constexpr bool value = true;
using type = map_t;
};
// Standard constructors
object() = default;
object(const object& in_config);
object(object&& in_config);
~object() = default;
// Value constructors
template<typename T,
typename std::enable_if<is_backing<typename std::decay<T>::type>::value
&& !is_sequence_container<typename std::decay<T>::type>::value>::type* = nullptr>
object(T&& in_value)
: m_value{ typename is_backing<typename std::decay<T>::type>::type{ std::forward<T>(in_value) } } {
// Empty ctor body
}
template<typename T,
typename std::enable_if<is_sequence_container<typename std::decay<T>::type>::value
&& !std::is_same<typename std::decay<T>::type, std::vector<bool>>::value>::type* = nullptr>
object(T&& in_value)
: m_value{ array_t{ in_value.begin(), in_value.end() } } {
// Empty ctor body
}
// std::vector<bool>
template<typename T,
typename std::enable_if<std::is_same<typename std::decay<T>::type, std::vector<bool>>::value>::type* = nullptr>
object(T&& in_value)
: m_value{ array_t{} } {
auto& array = std::get<array_t>(m_value);
array.reserve(in_value.size());
for (const auto& item : in_value) {
array.emplace_back(bool{item});
}
}
object(const char* in_str);
object(const std::string_view& in_str);
// Comparison operators
bool operator==(const object& rhs) const {
return m_value == rhs.m_value;
}
bool operator!=(const object& rhs) const {
return m_value != rhs.m_value;
}
bool operator<(const object& rhs) const {
return m_value < rhs.m_value;
}
bool operator>(const object& rhs) const {
return m_value > rhs.m_value;
}
bool operator<=(const object& rhs) const {
return m_value <= rhs.m_value;
}
bool operator>=(const object& rhs) const {
return m_value >= rhs.m_value;
}
// Assignment operators
object& operator=(const object& in_config) = default;
object& operator=(object&& in_config) = default;
// Non-copy/move assignment operator; forwards to set()
template<typename T,
typename std::enable_if<!std::is_same<typename std::decay<T>::type, object>::value>::type* = nullptr>
object& operator=(T&& in) {
set(std::forward<T>(in));
return *this;
}
const object& operator[](const std::string& in_key) const;
object& operator[](const std::string& in_key);
/** Accessors */
bool null() const;
size_t size() const;
template<typename T>
bool has() const {
using backing_t = typename is_backing<T>::type;
return std::holds_alternative<backing_t>(m_value);
}
/** arithmetic types (numbers, bool) */
template<typename T,
typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
T get(T in_default_value = {}) const {
using backing_t = typename is_backing<T>::type;
const backing_t* result = std::get_if<backing_t>(&m_value);
if (result != nullptr) {
return static_cast<T>(*result);
}
return in_default_value;
}
/** strings */
// TODO: support other basic_string types
template<typename T, typename DefaultT = T,
typename std::enable_if<std::is_same<T, std::string>::value && std::is_convertible<typename std::decay<DefaultT>::type, T>::value>::type* = nullptr>
T get(DefaultT&& in_default_value = {}) const {
const std::string* result = std::get_if<std::string>(&m_value);
if (result != nullptr) {
return *result;
}
return std::forward<DefaultT>(in_default_value);
}
// TODO: support other basic_string_view types
template<typename T, typename DefaultT = T,
typename std::enable_if<std::is_same<T, std::string>::value && std::is_same<typename std::decay<DefaultT>::type, std::string_view>::value>::type* = nullptr>
T get(DefaultT&& in_default_value) const {
const std::string* result = std::get_if<std::string>(&m_value);
if (result != nullptr) {
return *result;
}
return { in_default_value.begin(), in_default_value.end() };
}
/** arrays */
// reference getter (array_t)
template<typename T,
typename std::enable_if<std::is_same<T, array_t>::value>::type* = nullptr>
const T& get(const T& in_default_value) const {
const array_t* result = std::get_if<array_t>(&m_value);
if (result != nullptr) {
return *result;
}
return in_default_value;
}
// copy getter (array_t)
template<typename T,
typename std::enable_if<std::is_same<T, array_t>::value>::type* = nullptr>
T get(T&& in_default_value = {}) const {
const array_t* result = std::get_if<array_t>(&m_value);
if (result != nullptr) {
return *result;
}
return std::move(in_default_value);
}
// conversion getter (non-array_t)
template<typename T, typename DefaultT = T,
typename std::enable_if<is_sequence_container<T>::value && !std::is_same<T, array_t>::value && std::is_same<typename std::decay<DefaultT>::type, T>::value>::type* = nullptr>
T get(DefaultT&& in_default_value = {}) const {
using backing_t = typename is_sequence_container<T>::type;
const array_t* array = std::get_if<array_t>(&m_value);
if (array != nullptr) {
T result;
// Expand capacity to fit values (if possible)
if constexpr (is_vector<T>::value) {
result.reserve(array->size());
}
// Populate result from array
if constexpr (is_forward_list<T>::value) {
// forward_list
if constexpr (std::is_same<backing_t, class object>::value) {
// forward_list<object>
result.insert_after(result.begin(), array->begin(), array->end());
}
else {
for (auto itr = array->rend(); itr != array->rbegin(); ++itr) {
if (itr->has<backing_t>()) {
result.push_front(itr->get<backing_t>());
}
}
}
}
else if constexpr (is_set<T>::value || is_multiset<T>::value || is_unordered_set<T>::value || is_unordered_multiset<T>::value) {
// set, unordered_set, multiset, unordered_multiset
if constexpr (std::is_same<backing_t, class object>::value) {
// <object>
result.insert(array->begin(), array->end());
}
else {
for (auto& object : *array) {
if (object.has<backing_t>()) {
result.insert(object.get<backing_t>());
}
}
}
}
else {
// vector, list, etc
for (auto& object : *array) {
if constexpr (std::is_same<backing_t, class object>::value) {
// <object>
result.push_back(object);
}
else if (object.has<backing_t>()) {
result.push_back(object.get<backing_t>());
}
}
}
return result;
}
return std::forward<DefaultT>(in_default_value);
}
/** maps */
// TODO: implement in a way that does not require exposing map_t
// reference getter (map_t)
template<typename T,
typename std::enable_if<std::is_same<T, map_t>::value>::type* = nullptr>
const T& get(const T& in_default_value) const {
const map_t* result = std::get_if<map_t>(&m_value);
if (result != nullptr) {
return *result;
}
return in_default_value;
}
// copy getter (map_t)
template<typename T,
typename std::enable_if<std::is_same<T, map_t>::value>::type* = nullptr>
T get(T&& in_default_value = {}) const {
const map_t* result = std::get_if<map_t>(&m_value);
if (result != nullptr) {
return *result;
}
return std::move(in_default_value);
}
// TODO: conversion getter (non-map_t, i.e: unordered_map)
/** set */
// arithmetic types
template<typename T,
typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
void set(T in_value) {
using backing_t = typename is_backing<T>::type;
m_value.emplace<backing_t>(in_value);
}
// string
template<typename T,
typename std::enable_if<std::is_convertible<typename std::decay<T>::type, std::string>::value>::type* = nullptr>
void set(T&& in_value) {
m_value.emplace<std::string>(std::forward<T>(in_value));
}
// string_view
template<typename T,
typename std::enable_if<std::is_same<T, std::string_view>::value>::type* = nullptr>
void set(const T& in_value) {
m_value.emplace<std::string>(in_value.begin(), in_value.end());
}
// array_t
template<typename T,
typename std::enable_if<std::is_same<typename std::decay<T>::type, array_t>::value>::type* = nullptr>
void set(T&& in_value) {
m_value.emplace<array_t>(std::forward<T>(in_value));
}
// is_sequence_container
template<typename T,
typename std::enable_if<is_sequence_container<typename std::decay<T>::type>::value
&& !std::is_same<typename std::decay<T>::type, array_t>::value
&& !std::is_same<typename std::decay<T>::type, std::vector<bool>>::value>::type* = nullptr>
void set(T&& in_value) {
m_value.emplace<array_t>(in_value.begin(), in_value.end());
}
// std::vector<bool>
template<typename T,
typename std::enable_if<std::is_same<typename std::decay<T>::type, std::vector<bool>>::value>::type* = nullptr>
void set(T&& in_value) {
auto& array = m_value.emplace<array_t>();
array.reserve(in_value.size());
for (const auto& item : in_value) {
array.emplace_back(bool{item});
}
}
// object
template<typename T,
typename std::enable_if<std::is_same<typename std::decay<T>::type, object>::value>::type* = nullptr>
void set(T&& in_value) {
operator=(std::forward<T>(in_value));
}
size_t hash() const {
return std::visit([this](auto&& value) -> size_t {
using T = typename std::decay<decltype(value)>::type;
if constexpr (std::is_same<T, nullptr_t>::value) {
return 0;
}
else if constexpr (std::is_same<T, array_t>::value) {
size_t result{};
for (auto& obj : value) {
result += obj.hash();
}
return result;
}
else if constexpr (std::is_same<T, map_t>::value) {
size_t result{};
for (auto& pair : value) {
result += std::hash<std::string>{}(pair.first);
}
return result;
}
else {
return std::hash<T>{}(std::forward<decltype(value)>(value));
}
}, m_value);
}
private:
std::variant<nullptr_t, bool, intmax_t, long double, std::string, array_t, map_t> m_value;
}; // object
} // namespace jessilib
namespace std {
template<>
struct hash<jessilib::object> {
using argument_type = jessilib::object;
using result_type = size_t;
result_type operator()(const argument_type& in_object) const noexcept {
return in_object.hash();
}
};
} // namepsace std

58
src/include/parser.hpp

@ -0,0 +1,58 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#pragma once
#include <memory>
#include "object.hpp"
#include "impl/parser_manager.hpp"
namespace jessilib {
class parser {
public:
/** Interface methods */
/**
* Deserializes an object directly from a stream
* May throw: invalid_argument
*
* @param in_stream Stream to deserialize object from
* @return A valid (possibly null) object
*/
virtual object deserialize(std::istream& in_stream);
virtual object deserialize(std::string_view in_data) = 0;
virtual void serialize(std::ostream& in_stream, const object& in_object);
virtual std::string serialize(const object& in_object) = 0;
}; // parser
template<typename T>
class parser_registration {
public:
parser_registration(std::string in_format, bool in_force = false) {
m_id = impl::parser_manager::instance().register_parser(std::make_shared<T>(), in_format, in_force);
}
~parser_registration() {
impl::parser_manager::instance().unregister_parser(m_id);
}
impl::parser_manager::id m_id;
}; // parser_registration
} // namespace jessilib

41
src/include/serialize.hpp

@ -0,0 +1,41 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#pragma once
#include <istream>
#include "object.hpp"
namespace jessilib {
class format_not_available : public std::runtime_error {
public:
format_not_available(const std::string& in_format);
};
/** Deserialization */
object deserialize_object(const std::string& in_data, const std::string& in_format);
object deserialize_object(const std::vector<char>& in_data, const std::string& in_format);
object deserialize_object(std::string_view in_data, const std::string& in_format);
object deserialize_object(std::istream& in_stream, const std::string& in_format);
/** Serialization */
std::string serialize_object(const object& in_object, const std::string& in_format);
void serialize_object(std::ostream& in_stream, const object& in_object, const std::string& in_format);
} // namespace jessilib

215
src/include/util.hpp

@ -0,0 +1,215 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#pragma once
#include <cstddef>
#include <type_traits>
#include <vector>
#include <list>
#include <forward_list>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
/** Macros */
#define JESSILIB_FILENAME \
(::jessilib::impl::filename_from_string(__FILE__))
namespace jessilib {
/** is_vector */
template<typename T>
struct is_vector : std::false_type {};
template<typename T>
struct is_vector<std::vector<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
/** is_list */
template<typename T>
struct is_list : std::false_type {};
template<typename T>
struct is_list<std::list<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
/** is_forward_list */
template<typename T>
struct is_forward_list : std::false_type {};
template<typename T>
struct is_forward_list<std::forward_list<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
/** is_set */
template<typename T>
struct is_set : std::false_type {};
template<typename T>
struct is_set<std::set<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
/** is_multiset */
template<typename T>
struct is_multiset : std::false_type {};
template<typename T>
struct is_multiset<std::multiset<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
/** is_unordered_set */
template<typename T>
struct is_unordered_set : std::false_type {};
template<typename T>
struct is_unordered_set<std::unordered_set<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
/** is_unordered_set */
template<typename T>
struct is_unordered_multiset : std::false_type {};
template<typename T>
struct is_unordered_multiset<std::unordered_multiset<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
/** is_sequence_container */
template<typename T>
struct is_sequence_container : std::false_type {};
template<typename T>
struct is_sequence_container<std::vector<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
template<typename T>
struct is_sequence_container<std::list<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
template<typename T>
struct is_sequence_container<std::forward_list<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
template<typename T>
struct is_sequence_container<std::set<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
template<typename T>
struct is_sequence_container<std::multiset<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
template<typename T>
struct is_sequence_container<std::unordered_set<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
template<typename T>
struct is_sequence_container<std::unordered_multiset<T>> {
using type = T;
static constexpr bool value{ true };
constexpr operator bool() const noexcept { return true; }
constexpr bool operator()() const noexcept { return true; }
};
/** Implementation details */
namespace impl {
template<size_t in_filename_length>
constexpr const char* filename_from_string(const char (&in_filename)[in_filename_length]) {
const char* filename_itr = in_filename;
const char* filename_end = filename_itr + in_filename_length;
const char* result = filename_itr;
while (filename_itr != filename_end) {
if (*filename_itr == '/' || *filename_itr == '\\') {
++filename_itr;
result = filename_itr;
}
else {
++filename_itr;
}
}
return result;
}
} // namespace impl
} // namespace jessilib

2
src/test/CMakeLists.txt

@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.8)
# Setup source files # Setup source files
include_directories(../include) include_directories(../include)
set(SOURCE_FILES set(SOURCE_FILES
timer.cpp thread_pool.cpp) timer.cpp thread_pool.cpp util.cpp object.cpp)
# Setup gtest # Setup gtest
add_subdirectory(googletest/googletest) add_subdirectory(googletest/googletest)

932
src/test/object.cpp

@ -0,0 +1,932 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include <chrono>
#include "test.hpp"
#include "object.hpp"
using namespace jessilib;
using namespace std::literals;
void object_compilation_test() {
object config {};
// Map accessor
config["bob"]["builder"].get<std::string>(""s);
config["bob"]["builder"] = "whatever";
}
using signed_char_t = signed char;
using unsigned_char_t = unsigned char;
using long_long_t = long long;
using long_double_t = long double;
/** basic tests; these test function calls against null objects and heavily test for compilation errors */
TEST(ObjectTest, basic) {
object obj;
EXPECT_TRUE(obj.null());
EXPECT_EQ(obj.size(), 0U);
}
/** basic_has tests */
TEST(ObjectTest, basic_has) {
object obj;
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.has<signed char>());
EXPECT_FALSE(obj.has<unsigned char>());
EXPECT_FALSE(obj.has<short>());
EXPECT_FALSE(obj.has<int>());
EXPECT_FALSE(obj.has<long>());
EXPECT_FALSE(obj.has<long long>());
EXPECT_FALSE(obj.has<intmax_t>());
EXPECT_FALSE(obj.has<float>());
EXPECT_FALSE(obj.has<double>());
EXPECT_FALSE(obj.has<long double>());
EXPECT_FALSE(obj.has<std::string>());
EXPECT_FALSE(obj.has<object::array_t>());
EXPECT_FALSE(obj.has<object::map_t>());
}
TEST(ObjectTest, basic_has_vector) {
object obj;
EXPECT_FALSE(obj.has<std::vector<bool>>());
EXPECT_FALSE(obj.has<std::vector<signed char>>());
EXPECT_FALSE(obj.has<std::vector<unsigned char>>());
EXPECT_FALSE(obj.has<std::vector<short>>());
EXPECT_FALSE(obj.has<std::vector<int>>());
EXPECT_FALSE(obj.has<std::vector<long>>());
EXPECT_FALSE(obj.has<std::vector<long long>>());
EXPECT_FALSE(obj.has<std::vector<intmax_t>>());
EXPECT_FALSE(obj.has<std::vector<float>>());
EXPECT_FALSE(obj.has<std::vector<double>>());
EXPECT_FALSE(obj.has<std::vector<long double>>());
EXPECT_FALSE(obj.has<std::vector<std::string>>());
EXPECT_FALSE(obj.has<std::vector<object>>());
}
TEST(ObjectTest, basic_has_list) {
object obj;
EXPECT_FALSE(obj.has<std::list<bool>>());
EXPECT_FALSE(obj.has<std::list<signed char>>());
EXPECT_FALSE(obj.has<std::list<unsigned char>>());
EXPECT_FALSE(obj.has<std::list<short>>());
EXPECT_FALSE(obj.has<std::list<int>>());
EXPECT_FALSE(obj.has<std::list<long>>());
EXPECT_FALSE(obj.has<std::list<long long>>());
EXPECT_FALSE(obj.has<std::list<intmax_t>>());
EXPECT_FALSE(obj.has<std::list<float>>());
EXPECT_FALSE(obj.has<std::list<double>>());
EXPECT_FALSE(obj.has<std::list<long double>>());
EXPECT_FALSE(obj.has<std::list<std::string>>());
EXPECT_FALSE(obj.has<std::list<object>>());
}
TEST(ObjectTest, basic_has_forward_list) {
object obj;
EXPECT_FALSE(obj.has<std::forward_list<bool>>());
EXPECT_FALSE(obj.has<std::forward_list<signed char>>());
EXPECT_FALSE(obj.has<std::forward_list<unsigned char>>());
EXPECT_FALSE(obj.has<std::forward_list<short>>());
EXPECT_FALSE(obj.has<std::forward_list<int>>());
EXPECT_FALSE(obj.has<std::forward_list<long>>());
EXPECT_FALSE(obj.has<std::forward_list<long long>>());
EXPECT_FALSE(obj.has<std::forward_list<intmax_t>>());
EXPECT_FALSE(obj.has<std::forward_list<float>>());
EXPECT_FALSE(obj.has<std::forward_list<double>>());
EXPECT_FALSE(obj.has<std::forward_list<long double>>());
EXPECT_FALSE(obj.has<std::forward_list<std::string>>());
EXPECT_FALSE(obj.has<std::forward_list<object>>());
}
TEST(ObjectTest, basic_has_set) {
object obj;
EXPECT_FALSE(obj.has<std::set<bool>>());
EXPECT_FALSE(obj.has<std::set<signed char>>());
EXPECT_FALSE(obj.has<std::set<unsigned char>>());
EXPECT_FALSE(obj.has<std::set<short>>());
EXPECT_FALSE(obj.has<std::set<int>>());
EXPECT_FALSE(obj.has<std::set<long>>());
EXPECT_FALSE(obj.has<std::set<long long>>());
EXPECT_FALSE(obj.has<std::set<intmax_t>>());
EXPECT_FALSE(obj.has<std::set<float>>());
EXPECT_FALSE(obj.has<std::set<double>>());
EXPECT_FALSE(obj.has<std::set<long double>>());
EXPECT_FALSE(obj.has<std::set<std::string>>());
EXPECT_FALSE(obj.has<std::set<object>>());
}
TEST(ObjectTest, basic_has_unordered_set) {
object obj;
EXPECT_FALSE(obj.has<std::unordered_set<bool>>());
EXPECT_FALSE(obj.has<std::unordered_set<signed char>>());
EXPECT_FALSE(obj.has<std::unordered_set<unsigned char>>());
EXPECT_FALSE(obj.has<std::unordered_set<short>>());
EXPECT_FALSE(obj.has<std::unordered_set<int>>());
EXPECT_FALSE(obj.has<std::unordered_set<long>>());
EXPECT_FALSE(obj.has<std::unordered_set<long long>>());
EXPECT_FALSE(obj.has<std::unordered_set<intmax_t>>());
EXPECT_FALSE(obj.has<std::unordered_set<float>>());
EXPECT_FALSE(obj.has<std::unordered_set<double>>());
EXPECT_FALSE(obj.has<std::unordered_set<long double>>());
EXPECT_FALSE(obj.has<std::unordered_set<std::string>>());
EXPECT_FALSE(obj.has<std::unordered_set<object>>());
}
/** basic_get tests */
TEST(ObjectTest, basic_get) {
object obj;
EXPECT_EQ(obj.get<bool>(), bool{});
EXPECT_EQ(obj.get<signed char>(), signed_char_t{});
EXPECT_EQ(obj.get<unsigned char>(), unsigned_char_t{});
EXPECT_EQ(obj.get<short>(), short{});
EXPECT_EQ(obj.get<int>(), int{});
EXPECT_EQ(obj.get<long>(), long{});
EXPECT_EQ(obj.get<long long>(), long_long_t{});
EXPECT_EQ(obj.get<intmax_t>(), intmax_t{});
EXPECT_EQ(obj.get<float>(), float{});
EXPECT_EQ(obj.get<double>(), double{});
EXPECT_EQ(obj.get<long double>(), long_double_t{});
EXPECT_EQ(obj.get<std::string>(), std::string{});
EXPECT_TRUE(obj.get<object::array_t>().empty());
EXPECT_TRUE(obj.get<object::map_t>().empty());
}
TEST(ObjectTest, basic_get_vector) {
object obj;
EXPECT_TRUE(obj.get<std::vector<bool>>().empty());
EXPECT_TRUE(obj.get<std::vector<signed char>>().empty());
EXPECT_TRUE(obj.get<std::vector<unsigned char>>().empty());
EXPECT_TRUE(obj.get<std::vector<short>>().empty());
EXPECT_TRUE(obj.get<std::vector<int>>().empty());
EXPECT_TRUE(obj.get<std::vector<long>>().empty());
EXPECT_TRUE(obj.get<std::vector<long long>>().empty());
EXPECT_TRUE(obj.get<std::vector<intmax_t>>().empty());
EXPECT_TRUE(obj.get<std::vector<float>>().empty());
EXPECT_TRUE(obj.get<std::vector<double>>().empty());
EXPECT_TRUE(obj.get<std::vector<long double>>().empty());
EXPECT_TRUE(obj.get<std::vector<std::string>>().empty());
EXPECT_TRUE(obj.get<std::vector<object>>().empty());
}
TEST(ObjectTest, basic_get_list) {
object obj;
EXPECT_TRUE(obj.get<std::list<bool>>().empty());
EXPECT_TRUE(obj.get<std::list<signed char>>().empty());
EXPECT_TRUE(obj.get<std::list<unsigned char>>().empty());
EXPECT_TRUE(obj.get<std::list<short>>().empty());
EXPECT_TRUE(obj.get<std::list<int>>().empty());
EXPECT_TRUE(obj.get<std::list<long>>().empty());
EXPECT_TRUE(obj.get<std::list<long long>>().empty());
EXPECT_TRUE(obj.get<std::list<intmax_t>>().empty());
EXPECT_TRUE(obj.get<std::list<float>>().empty());
EXPECT_TRUE(obj.get<std::list<double>>().empty());
EXPECT_TRUE(obj.get<std::list<long double>>().empty());
EXPECT_TRUE(obj.get<std::list<std::string>>().empty());
EXPECT_TRUE(obj.get<std::list<object>>().empty());
}
TEST(ObjectTest, basic_get_forward_list) {
object obj;
EXPECT_TRUE(obj.get<std::forward_list<bool>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<signed char>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<unsigned char>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<short>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<int>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<long>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<long long>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<intmax_t>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<float>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<double>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<long double>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<std::string>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<object>>().empty());
}
TEST(ObjectTest, basic_get_set) {
object obj;
EXPECT_TRUE(obj.get<std::set<bool>>().empty());
EXPECT_TRUE(obj.get<std::set<signed char>>().empty());
EXPECT_TRUE(obj.get<std::set<unsigned char>>().empty());
EXPECT_TRUE(obj.get<std::set<short>>().empty());
EXPECT_TRUE(obj.get<std::set<int>>().empty());
EXPECT_TRUE(obj.get<std::set<long>>().empty());
EXPECT_TRUE(obj.get<std::set<long long>>().empty());
EXPECT_TRUE(obj.get<std::set<intmax_t>>().empty());
EXPECT_TRUE(obj.get<std::set<float>>().empty());
EXPECT_TRUE(obj.get<std::set<double>>().empty());
EXPECT_TRUE(obj.get<std::set<long double>>().empty());
EXPECT_TRUE(obj.get<std::set<std::string>>().empty());
EXPECT_TRUE(obj.get<std::set<object>>().empty());
}
TEST(ObjectTest, basic_get_multiset) {
object obj;
EXPECT_TRUE(obj.get<std::multiset<bool>>().empty());
EXPECT_TRUE(obj.get<std::multiset<signed char>>().empty());
EXPECT_TRUE(obj.get<std::multiset<unsigned char>>().empty());
EXPECT_TRUE(obj.get<std::multiset<short>>().empty());
EXPECT_TRUE(obj.get<std::multiset<int>>().empty());
EXPECT_TRUE(obj.get<std::multiset<long>>().empty());
EXPECT_TRUE(obj.get<std::multiset<long long>>().empty());
EXPECT_TRUE(obj.get<std::multiset<intmax_t>>().empty());
EXPECT_TRUE(obj.get<std::multiset<float>>().empty());
EXPECT_TRUE(obj.get<std::multiset<double>>().empty());
EXPECT_TRUE(obj.get<std::multiset<long double>>().empty());
EXPECT_TRUE(obj.get<std::multiset<std::string>>().empty());
EXPECT_TRUE(obj.get<std::multiset<object>>().empty());
}
TEST(ObjectTest, basic_get_unordered_set) {
object obj;
EXPECT_TRUE(obj.get<std::unordered_set<bool>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<signed char>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<unsigned char>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<short>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<int>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<long>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<long long>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<intmax_t>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<float>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<double>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<long double>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<std::string>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<object>>().empty());
}
TEST(ObjectTest, basic_get_unordered_multiset) {
object obj;
EXPECT_TRUE(obj.get<std::unordered_multiset<bool>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<signed char>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<unsigned char>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<short>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<int>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<long>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<long long>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<intmax_t>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<float>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<double>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<long double>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<std::string>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<object>>().empty());
}
/** basic_value_constructor */
#define OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(in_type) \
{ object test_object__{ in_type {} }; \
EXPECT_TRUE(test_object__ .has< in_type >()); \
EXPECT_EQ(test_object__.get< in_type >(), in_type {} ); }
// asdf
TEST(ObjectTest, basic_value_constructor) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(bool);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(signed_char_t);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(unsigned_char_t);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(short);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(int);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(long);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(long_long_t);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(intmax_t);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(float);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(double);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(long_double_t);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::string);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(object::array_t);
// const char*
{
object obj{ "" };
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
}
// std::string_view
{
object obj{ ""sv };
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
}
}
TEST(ObjectTest, basic_value_constructor_vector) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<bool>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<signed char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<unsigned char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<short>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<int>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<long long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<intmax_t>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<object>);
}
TEST(ObjectTest, basic_value_constructor_list) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<bool>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<signed char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<unsigned char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<short>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<int>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<long long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<intmax_t>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<object>);
}
TEST(ObjectTest, basic_value_constructor_forward_list) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<bool>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<signed char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<unsigned char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<short>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<int>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<long long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<intmax_t>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<object>);
}
TEST(ObjectTest, basic_value_constructor_set) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<bool>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<signed char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<unsigned char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<short>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<int>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<long long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<intmax_t>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<object>);
}
TEST(ObjectTest, basic_value_constructor_multiset) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<bool>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<signed char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<unsigned char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<short>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<int>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<long long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<intmax_t>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<object>);
}
TEST(ObjectTest, basic_value_constructor_unordered_set) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<bool>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<signed char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<unsigned char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<short>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<int>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<long long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<intmax_t>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<object>);
}
TEST(ObjectTest, basic_value_constructor_unordered_multiset) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<bool>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<signed char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<unsigned char>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<short>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<int>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<long long>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<intmax_t>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<object>);
}
/** basic_set */
#define OBJECT_BASIC_SET_TEST(in_object, in_type) \
in_object .set< in_type >( in_type {} ); \
EXPECT_TRUE(in_object .has< in_type >()); \
EXPECT_EQ(in_object .get< in_type >(), in_type {} )
TEST(ObjectTest, basic_set) {
object obj;
OBJECT_BASIC_SET_TEST(obj, bool);
OBJECT_BASIC_SET_TEST(obj, signed_char_t);
OBJECT_BASIC_SET_TEST(obj, unsigned_char_t);
OBJECT_BASIC_SET_TEST(obj, short);
OBJECT_BASIC_SET_TEST(obj, int);
OBJECT_BASIC_SET_TEST(obj, long);
OBJECT_BASIC_SET_TEST(obj, long_long_t);
OBJECT_BASIC_SET_TEST(obj, intmax_t);
OBJECT_BASIC_SET_TEST(obj, float);
OBJECT_BASIC_SET_TEST(obj, double);
OBJECT_BASIC_SET_TEST(obj, long_double_t);
OBJECT_BASIC_SET_TEST(obj, std::string);
OBJECT_BASIC_SET_TEST(obj, object::array_t);
// const char*
obj.set("");
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
// std::string_view
obj.set(""sv);
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
}
TEST(ObjectTest, basic_set_vector) {
object obj;
OBJECT_BASIC_SET_TEST(obj, std::vector<bool>);
OBJECT_BASIC_SET_TEST(obj, std::vector<signed char>);
OBJECT_BASIC_SET_TEST(obj, std::vector<unsigned char>);
OBJECT_BASIC_SET_TEST(obj, std::vector<short>);
OBJECT_BASIC_SET_TEST(obj, std::vector<int>);
OBJECT_BASIC_SET_TEST(obj, std::vector<long>);
OBJECT_BASIC_SET_TEST(obj, std::vector<long long>);
OBJECT_BASIC_SET_TEST(obj, std::vector<intmax_t>);
OBJECT_BASIC_SET_TEST(obj, std::vector<float>);
OBJECT_BASIC_SET_TEST(obj, std::vector<double>);
OBJECT_BASIC_SET_TEST(obj, std::vector<long double>);
OBJECT_BASIC_SET_TEST(obj, std::vector<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::vector<object>);
}
TEST(ObjectTest, basic_set_list) {
object obj;
OBJECT_BASIC_SET_TEST(obj, std::list<bool>);
OBJECT_BASIC_SET_TEST(obj, std::list<signed char>);
OBJECT_BASIC_SET_TEST(obj, std::list<unsigned char>);
OBJECT_BASIC_SET_TEST(obj, std::list<short>);
OBJECT_BASIC_SET_TEST(obj, std::list<int>);
OBJECT_BASIC_SET_TEST(obj, std::list<long>);
OBJECT_BASIC_SET_TEST(obj, std::list<long long>);
OBJECT_BASIC_SET_TEST(obj, std::list<intmax_t>);
OBJECT_BASIC_SET_TEST(obj, std::list<float>);
OBJECT_BASIC_SET_TEST(obj, std::list<double>);
OBJECT_BASIC_SET_TEST(obj, std::list<long double>);
OBJECT_BASIC_SET_TEST(obj, std::list<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::list<object>);
}
TEST(ObjectTest, basic_set_forward_list) {
object obj;
OBJECT_BASIC_SET_TEST(obj, std::forward_list<bool>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<signed char>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<unsigned char>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<short>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<int>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<long>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<long long>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<intmax_t>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<float>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<double>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<long double>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<object>);
}
TEST(ObjectTest, basic_set_set) {
object obj;
OBJECT_BASIC_SET_TEST(obj, std::set<bool>);
OBJECT_BASIC_SET_TEST(obj, std::set<signed char>);
OBJECT_BASIC_SET_TEST(obj, std::set<unsigned char>);
OBJECT_BASIC_SET_TEST(obj, std::set<short>);
OBJECT_BASIC_SET_TEST(obj, std::set<int>);
OBJECT_BASIC_SET_TEST(obj, std::set<long>);
OBJECT_BASIC_SET_TEST(obj, std::set<long long>);
OBJECT_BASIC_SET_TEST(obj, std::set<intmax_t>);
OBJECT_BASIC_SET_TEST(obj, std::set<float>);
OBJECT_BASIC_SET_TEST(obj, std::set<double>);
OBJECT_BASIC_SET_TEST(obj, std::set<long double>);
OBJECT_BASIC_SET_TEST(obj, std::set<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::set<object>);
}
TEST(ObjectTest, basic_set_multiset) {
object obj;
OBJECT_BASIC_SET_TEST(obj, std::multiset<bool>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<signed char>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<unsigned char>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<short>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<int>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<long>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<long long>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<intmax_t>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<float>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<double>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<long double>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<object>);
}
TEST(ObjectTest, basic_set_unordered_set) {
object obj;
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<bool>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<signed char>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<unsigned char>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<short>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<int>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<long>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<long long>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<intmax_t>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<float>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<double>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<long double>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<object>);
}
TEST(ObjectTest, basic_set_unordered_multiset) {
object obj;
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<bool>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<signed char>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<unsigned char>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<short>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<int>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<long>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<long long>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<intmax_t>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<float>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<double>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<long double>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<object>);
}
/** basic_assignment_operator */
#define OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(in_object, in_type) \
in_object = in_type {}; \
EXPECT_TRUE(in_object .has< in_type >()); \
EXPECT_EQ(in_object .get< in_type >(), in_type {} )
TEST(ObjectTest, basic_assignment_operator) {
object obj;
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, bool);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, signed_char_t);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, unsigned_char_t);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, short);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, int);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, long);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, long_long_t);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, intmax_t);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, float);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, double);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, long_double_t);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::string);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, object::array_t);
// const char*
obj = "";
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
// std::string_view
obj = ""sv;
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
}
TEST(ObjectTest, basic_assignment_operator_vector) {
object obj;
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<bool>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<signed char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<unsigned char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<short>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<int>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<long long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<intmax_t>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<object>);
}
TEST(ObjectTest, basic_assignment_operator_list) {
object obj;
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<bool>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<signed char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<unsigned char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<short>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<int>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<long long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<intmax_t>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<object>);
}
TEST(ObjectTest, basic_assignment_operator_forward_list) {
object obj;
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<bool>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<signed char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<unsigned char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<short>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<int>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<long long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<intmax_t>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<object>);
}
TEST(ObjectTest, basic_assignment_operator_set) {
object obj;
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<bool>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<signed char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<unsigned char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<short>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<int>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<long long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<intmax_t>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<object>);
}
TEST(ObjectTest, basic_assignment_operator_multiset) {
object obj;
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<bool>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<signed char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<unsigned char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<short>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<int>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<long long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<intmax_t>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<object>);
}
TEST(ObjectTest, basic_assignment_operator_unordered_set) {
object obj;
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<bool>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<signed char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<unsigned char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<short>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<int>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<long long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<intmax_t>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<object>);
}
TEST(ObjectTest, basic_assignment_operator_unordered_multiset) {
object obj;
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<bool>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<signed char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<unsigned char>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<short>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<int>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<long long>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<intmax_t>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<object>);
}
/** basic_access_operator */
TEST(ObjectTest, basic_access_operator) {
object obj;
obj["test"] = 1234;
EXPECT_EQ(obj["test"].get<int>(), 1234);
EXPECT_EQ(obj["test2"].get<int>(), 0);
obj["test"] = 4567;
EXPECT_EQ(obj["test"].get<int>(), 4567);
EXPECT_EQ(obj["test2"].get<int>(), 0);
obj["test2"] = 1234;
EXPECT_EQ(obj["test"].get<int>(), 4567);
EXPECT_EQ(obj["test2"].get<int>(), 1234);
}
/** end basic tests */
TEST(ObjectTest, set_bool) {
object obj;
obj.set(true);
EXPECT_TRUE(obj.has<bool>());
EXPECT_TRUE(obj.get<bool>());
EXPECT_FALSE(obj.has<int>());
EXPECT_EQ(obj.get<int>(), 0);
obj.set(false);
EXPECT_TRUE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
EXPECT_FALSE(obj.has<int>());
EXPECT_EQ(obj.get<int>(), 0);
}
TEST(ObjectTest, set_int) {
object obj;
obj.set(1337);
EXPECT_TRUE(obj.has<int>());
EXPECT_EQ(obj.get<int>(), 1337);
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set(7331);
EXPECT_TRUE(obj.has<int>());
EXPECT_EQ(obj.get<int>(), 7331);
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set(0);
EXPECT_TRUE(obj.has<int>());
EXPECT_EQ(obj.get<int>(), 0);
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
}
TEST(ObjectTest, set_float) {
object obj;
obj.set(13.37);
EXPECT_TRUE(obj.has<double>());
EXPECT_EQ(obj.get<double>(), 13.37);
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set(73.31);
EXPECT_TRUE(obj.has<double>());
EXPECT_EQ(obj.get<double>(), 73.31);
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set(0.0);
EXPECT_TRUE(obj.has<double>());
EXPECT_EQ(obj.get<double>(), 0.0);
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
}
TEST(ObjectTest, set_string) {
object obj;
obj.set("Jessica");
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), "Jessica");
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set("was"s);
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), "was");
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set("here"sv);
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), "here");
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set("");
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), "");
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
}
TEST(ObjectTest, set_vector) {
object obj;
obj.set(std::vector<bool>{ true });
EXPECT_TRUE(obj.has<std::vector<bool>>());
EXPECT_EQ(obj.get<std::vector<bool>>(), std::vector<bool>{ true });
EXPECT_TRUE(obj.has<std::vector<object>>());
EXPECT_EQ(obj.get<std::vector<object>>().size(), 1U);
EXPECT_TRUE(obj.has<std::vector<int>>());
EXPECT_EQ(obj.get<std::vector<int>>().size(), 0U);
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set(std::vector<bool>{});
EXPECT_TRUE(obj.has<std::vector<bool>>());
EXPECT_EQ(obj.get<std::vector<bool>>().size(), 0U);
EXPECT_TRUE(obj.has<std::vector<object>>());
EXPECT_EQ(obj.get<std::vector<object>>().size(), 0U);
EXPECT_TRUE(obj.has<std::vector<int>>());
EXPECT_EQ(obj.get<std::vector<int>>().size(), 0U);
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
}
TEST(ObjectTest, set_object) {
object obj1, obj2;
obj1.set(true);
obj2.set(obj1);
EXPECT_EQ(obj1, obj2);
}

20
src/test/thread_pool.cpp

@ -53,19 +53,17 @@ TEST(ThreadPoolTest, initialSizeDefined) {
} }
TEST(ThreadPoolTest, push) { TEST(ThreadPoolTest, push) {
repeat (total_iterations) { std::atomic<size_t> iterations{0};
std::atomic<size_t> iterations{0}; thread_pool pool;
thread_pool pool;
repeat (total_iterations) {
pool.push([&iterations, &pool]() {
++iterations;
});
}
pool.join(); repeat (total_iterations) {
EXPECT_EQ(iterations, total_iterations); pool.push([&iterations, &pool]() {
++iterations;
});
} }
pool.join();
EXPECT_EQ(iterations, total_iterations);
} }
TEST(ThreadPoolTest, deadlockSingleThread) { TEST(ThreadPoolTest, deadlockSingleThread) {

32
src/test/util.cpp

@ -0,0 +1,32 @@
/**
* Copyright (C) 2018 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include "util.hpp"
#include "test.hpp"
#include "object.hpp"
using namespace jessilib;
using namespace std::literals;
TEST(UtilTest, filename) {
constexpr const char* filename = JESSILIB_FILENAME;
EXPECT_STREQ(filename, "util.cpp");
}
// Non-virtual using variant: 48
//
Loading…
Cancel
Save