add test for async and fix some pre-c++17 compatibility issues in async
This commit is contained in:
parent
bfd84f66be
commit
2703cb0be6
@ -90,6 +90,7 @@ namespace async {
|
||||
namespace detail {
|
||||
namespace detail = fmt::detail;
|
||||
template <typename T> using decay_t = typename std::decay<T>::type;
|
||||
template <typename T> using add_const_t = typename std::add_const<T>::type;
|
||||
|
||||
enum class store_method {
|
||||
numeric, // stored by libfmt as numeric value, no need for extra storage
|
||||
@ -188,7 +189,7 @@ struct arg_transformer {
|
||||
|
||||
template <typename Arg, typename Context, typename Type = detail::mapped_type_constant<remove_reference_t<Arg>, Context>>
|
||||
using transformed_arg_type = conditional_t<custom_store_method<Arg, Context>::custom_store, typename custom_store_method<Arg, Context>::transformed_type,
|
||||
conditional_t<stored_as_string<Type>::value && !stored_as_string_object<Type, Arg>::value, basic_string_view<typename Context::char_type>, std::add_const_t<remove_reference_t<Arg>>&>
|
||||
conditional_t<stored_as_string<Type>::value && !stored_as_string_object<Type, Arg>::value, basic_string_view<typename Context::char_type>, add_const_t<remove_reference_t<Arg>>&>
|
||||
>;
|
||||
|
||||
template <typename Context, typename... Args>
|
||||
@ -205,7 +206,7 @@ struct async_entry_constructor {
|
||||
private:
|
||||
using range = typename range_builder<0, sizeof...(Args)>::type;
|
||||
template <typename S, size_t... Indice>
|
||||
constexpr async_entry_constructor(void* buf, const S& format_str, index_list<Indice...>, Args... args) : pEntry(reinterpret_cast<char*>(buf)), pBuffer(get_buffer_store(buf)) {
|
||||
FMT_CONSTEXPR async_entry_constructor(void* buf, const S& format_str, index_list<Indice...>, Args... args) : pEntry(reinterpret_cast<char*>(buf)), pBuffer(get_buffer_store(buf)) {
|
||||
auto p = new(buf) Entry(format_str, store<Indice>(std::forward<Args>(args))...);
|
||||
p->set_dtor(Dtor::value ? Dtor::destruct : nullptr);
|
||||
}
|
||||
@ -257,7 +258,7 @@ private:
|
||||
return basic_string_view<typename Context::char_type>(pStart, sv.size());
|
||||
}
|
||||
|
||||
static constexpr char* get_buffer_store(void* buf) {
|
||||
static FMT_CONSTEXPR char* get_buffer_store(void* buf) {
|
||||
char* const pentry = reinterpret_cast<char*>(buf); // entry will be constructed here
|
||||
char* const pobjs = pentry + sizeof(Entry); // objects will be stored starting here
|
||||
char* const pbufs = pobjs + get_obj_size(); // buffers will be stored starting here
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
#define FMT_HEADER_ONLY
|
||||
#include "async.h"
|
||||
|
||||
using namespace fmt;
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
fmt::print("entry header: {}\n", sizeof(basic_async_entry<format_context>));
|
||||
auto entry = make_async_entry("The answer is {}\n", 42);
|
||||
async::print(entry);
|
||||
|
||||
char buf[2000];
|
||||
size_t size = store_async_entry(buf, "This {} is {}{}\n", "answer", std::to_string(4), 2);
|
||||
fmt::print("entry size: {}\n", size);
|
||||
auto& entryref1 = entry;
|
||||
auto& entryref = reinterpret_cast<decltype(entryref1)>(buf[0]);
|
||||
async::print(entryref);
|
||||
|
||||
std::cout << &entryref << "\n" << &(entryref.arg_store_) << "\n" << sizeof(entryref.arg_store_) << std::endl;
|
||||
}
|
||||
@ -88,6 +88,7 @@ function(add_fmt_test name)
|
||||
endfunction()
|
||||
|
||||
add_fmt_test(assert-test)
|
||||
add_fmt_test(async-test)
|
||||
add_fmt_test(chrono-test)
|
||||
add_fmt_test(color-test)
|
||||
add_fmt_test(core-test)
|
||||
|
||||
103
test/async-test.cc
Normal file
103
test/async-test.cc
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
#ifdef WIN32
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "fmt/async.h"
|
||||
#include "gtest-extra.h"
|
||||
|
||||
#define TWENTY_ARGS "{} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} "
|
||||
static const char multiple_brackets[] = TWENTY_ARGS;
|
||||
static fmt::string_view get_format_string(size_t num_args) { return fmt::string_view(&multiple_brackets[(20 - num_args)*3], num_args * 3); }
|
||||
|
||||
namespace trivial_entry_test {
|
||||
template <typename... Args>
|
||||
inline void make_async_entry_test(Args&&... args) {
|
||||
std::string formatted = fmt::format(std::forward<Args>(args)...);
|
||||
// format_arg_store containing named_args are not copy-constructible, auto&& is required.
|
||||
auto&& entry = fmt::make_async_entry(std::forward<Args>(args)...);
|
||||
EXPECT_EQ(formatted, fmt::async::format(entry));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void make_async_entry_test_args(Args&&... args) {
|
||||
make_async_entry_test(get_format_string(sizeof...(args)), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void make_async_entry_and_alter(const std::string& s) {
|
||||
std::string str = s;
|
||||
std::string formatted = fmt::format("{}", str);
|
||||
auto entry = fmt::make_async_entry("{}", str);
|
||||
str.front() = formatted.front() = '#';
|
||||
str.back() = formatted.back() = '#';
|
||||
EXPECT_EQ(formatted, fmt::format("{}", str));
|
||||
EXPECT_EQ(formatted, fmt::async::format(entry));
|
||||
}
|
||||
}
|
||||
|
||||
namespace stored_entry_test {
|
||||
static char buf[1 * 1024 * 1024] = {}; // 1M should be enough for this test
|
||||
static fmt::basic_async_entry<fmt::format_context>& entry = reinterpret_cast<fmt::basic_async_entry<fmt::format_context>&>(buf);
|
||||
|
||||
template <typename... Args>
|
||||
inline void make_async_entry_test(Args&&... args) {
|
||||
std::string formatted = fmt::format(std::forward<Args>(args)...);
|
||||
// FIXME: how to test entry_size?
|
||||
size_t entry_size = fmt::store_async_entry(buf, std::forward<Args>(args)...);
|
||||
EXPECT_EQ(formatted, fmt::async::format(entry));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void make_async_entry_test_args(Args&&... args) {
|
||||
make_async_entry_test(get_format_string(sizeof...(args)), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void make_async_entry_and_alter(const std::string& s) {
|
||||
std::string str = s;
|
||||
std::string formatted = fmt::format("{}", str);
|
||||
size_t entry_size = fmt::store_async_entry(buf, "{}", str);
|
||||
str.front() = str.back() = '#';
|
||||
EXPECT_EQ(formatted, fmt::async::format(entry));
|
||||
formatted.front() = formatted.back() = '#';
|
||||
EXPECT_EQ(formatted, fmt::format("{}", str));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AsyncTest, TrivialEntry) {
|
||||
using namespace trivial_entry_test;
|
||||
// basic test
|
||||
make_async_entry_test("The answer is {}", 42);
|
||||
// index
|
||||
make_async_entry_test("The answer of {2}*{1} is {0}", 42, 6, 7);
|
||||
|
||||
// named args
|
||||
using namespace fmt::literals;
|
||||
make_async_entry_test("The answer of {}*{a} is {product}", 6, "product"_a=42, "a"_a=7);
|
||||
|
||||
// long arg list (>=16, as max_packed_args = 15)
|
||||
make_async_entry_test_args(short(1), (unsigned short)2, 3, 4U, 5L, 6UL, 7LL, 8ULL, 9.0F, 10.0, 11, 12, 13, 14, 15, 16, 17, 18);
|
||||
make_async_entry_test(TWENTY_ARGS "{narg}", 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,0/*ignore*/,"narg"_a="bingo");
|
||||
|
||||
// this API copies only reference.
|
||||
make_async_entry_and_alter("[change me]");
|
||||
}
|
||||
|
||||
|
||||
TEST(AsyncTest, StoredEntry) {
|
||||
using namespace stored_entry_test;
|
||||
// basic test
|
||||
make_async_entry_test("The answer is {}", 42);
|
||||
// index
|
||||
make_async_entry_test("The answer of {2}*{1} is {0}", 42, 6, 7);
|
||||
|
||||
// named args
|
||||
using namespace fmt::literals;
|
||||
// make_async_entry_test("The answer of {}*{a} is {product}", 6, "product"_a=42, "a"_a=7);
|
||||
|
||||
// long arg list (>=16, as max_packed_args = 15)
|
||||
make_async_entry_test_args(short(1), (unsigned short)2, 3, 4U, 5L, 6UL, 7LL, 8ULL, 9.0F, 10.0, 11, 12, 13, 14, 15, 16, 17, 18);
|
||||
// make_async_entry_test(TWENTY_ARGS "{narg}", 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,0/*ignore*/,"narg"_a="bingo");
|
||||
|
||||
// this API copies only reference.
|
||||
make_async_entry_and_alter("[change me]");
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user