Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ jobs:
std: 23
install: sudo apt install g++-13
shared: -DBUILD_SHARED_LIBS=ON
- cxx: g++-14
- cxx: g++-15
Comment thread
MathewBensonCode marked this conversation as resolved.
build_type: Release
std: 23
install: sudo apt install g++-14
install: sudo apt install g++-15
gen: Ninja
- cxx: clang++-3.6
- cxx: clang++-11
Expand Down Expand Up @@ -147,7 +147,7 @@ jobs:
- name: Add repositories for newer GCC
run: |
sudo apt-add-repository ppa:ubuntu-toolchain-r/test
if: ${{ matrix.cxx == 'g++-13' || matrix.cxx == 'g++-14' }}
if: ${{ matrix.cxx == 'g++-13' || matrix.cxx == 'g++-15' }}

- name: Install LLVM-20
run: |
Expand Down Expand Up @@ -200,6 +200,6 @@ jobs:

- name: Test
working-directory: ${{runner.workspace}}/build
run: ctest -C ${{matrix.build_type}}
run: ctest -C ${{matrix.build_type}} -V
env:
CTEST_OUTPUT_ON_FAILURE: True
2 changes: 1 addition & 1 deletion .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ jobs:
- name: Test
working-directory: ${{runner.workspace}}/build
run: ctest -C ${{matrix.build_type}}
run: ctest -C ${{matrix.build_type}} -V
env:
CTEST_OUTPUT_ON_FAILURE: True
6 changes: 2 additions & 4 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function (add_fmt_test name)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wno-weak-vtables)
endif ()
elseif (ADD_FMT_TEST_MODULE)
set(libs test-main)
set(libs test-main fmt-module)
else ()
set(libs test-main fmt)
endif ()
Expand Down Expand Up @@ -81,9 +81,7 @@ add_executable(perf-sanity perf-sanity.cc)
target_link_libraries(perf-sanity fmt::fmt)

if (FMT_MODULE)
# Module tests are currently disabled.
# add_fmt_test(module-test MODULE test-main.cc)
# target_link_libraries(module-test fmt-module)
add_fmt_test(module-test MODULE)
endif ()

if (NOT DEFINED MSVC_STATIC_RUNTIME AND MSVC)
Expand Down
144 changes: 39 additions & 105 deletions test/module-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <string>
#include <string_view>
#include <system_error>
#include <gmock/gmock.h>

#if (__has_include(<fcntl.h>) || defined(__APPLE__) || \
defined(__linux__)) && \
Expand All @@ -51,6 +52,8 @@ static bool macro_leaked =
#endif

#define FMT_OS_H_ // don't pull in os.h, neither directly nor indirectly
// this define plus the #include <gmock/gmock.h> above
// prevents header inclusion after the import fmt statement
#include "gtest-extra.h"

// an implicitly exported namespace must be visible [module.interface]/2.2
Expand All @@ -60,32 +63,6 @@ TEST(module_test, namespace) {
ASSERT_TRUE(true);
}

namespace detail {
bool oops_detail_namespace_is_visible;
}

namespace fmt {
bool namespace_detail_invisible() {
#if defined(FMT_HIDE_MODULE_BUGS) && defined(_MSC_FULL_VER) && \
_MSC_FULL_VER <= 193700000
// bug in msvc up to at least 17.7:

// the namespace is visible even when it is neither
// implicitly nor explicitly exported
return true;
#else
using namespace detail;
// this fails to compile if fmt::detail is visible
return !oops_detail_namespace_is_visible;
#endif
}
} // namespace fmt

// the non-exported namespace 'detail' must be invisible [module.interface]/2
TEST(module_test, detail_namespace) {
EXPECT_TRUE(fmt::namespace_detail_invisible());
}

// macros must not be imported from a *named* module [cpp.import]/5.1
TEST(module_test, macros) {
#if defined(FMT_HIDE_MODULE_BUGS) && defined(_MSC_FULL_VER) && \
Expand Down Expand Up @@ -170,7 +147,8 @@ TEST(module_test, format_args) {
auto no_args = fmt::format_args();
EXPECT_FALSE(no_args.get(1));

fmt::basic_format_args args = fmt::make_format_args(42);
int n = 42;
fmt::basic_format_args<fmt::format_context> args = fmt::make_format_args(n);
Comment thread
MathewBensonCode marked this conversation as resolved.
EXPECT_TRUE(args.max_size() > 0);
auto arg0 = args.get(0);
EXPECT_TRUE(arg0);
Expand All @@ -182,41 +160,35 @@ TEST(module_test, format_args) {
TEST(module_test, wformat_args) {
auto no_args = fmt::wformat_args();
EXPECT_FALSE(no_args.get(1));
fmt::basic_format_args args = fmt::make_wformat_args(42);
int n = 42;
fmt::basic_format_args<fmt::wformat_context> args = fmt::make_wformat_args(n);
EXPECT_TRUE(args.get(0));
}

TEST(module_test, dynamic_format_args) {
fmt::dynamic_format_arg_store<fmt::format_context> dyn_store;
dyn_store.push_back(fmt::arg("a42", 42));
fmt::basic_format_args args = dyn_store;

fmt::basic_format_args<fmt::format_context> args = dyn_store;
EXPECT_FALSE(args.get(3));
EXPECT_TRUE(args.get(fmt::string_view("a42")));

fmt::dynamic_format_arg_store<fmt::wformat_context> wdyn_store;
wdyn_store.push_back(fmt::arg(L"a42", 42));
fmt::basic_format_args wargs = wdyn_store;
EXPECT_FALSE(wargs.get(3));
EXPECT_TRUE(wargs.get(fmt::wstring_view(L"a42")));
}

TEST(module_test, vformat) {
EXPECT_EQ("42", fmt::vformat("{}", fmt::make_format_args(42)));
int n = 42;
EXPECT_EQ("42", fmt::vformat("{}", fmt::make_format_args(n)));
EXPECT_EQ(L"42",
fmt::vformat(fmt::wstring_view(L"{}"), fmt::make_wformat_args(42)));
fmt::vformat(fmt::wstring_view(L"{}"), fmt::make_wformat_args(n)));
}

TEST(module_test, vformat_to) {
auto store = fmt::make_format_args(42);
int n = 42;
auto store = fmt::make_format_args(n);
std::string s;
fmt::vformat_to(std::back_inserter(s), "{}", store);
EXPECT_EQ("42", s);

char buffer[4] = {0};
fmt::vformat_to(buffer, "{:}", store);
EXPECT_EQ("42", std::string_view(buffer));

auto wstore = fmt::make_wformat_args(42);
auto wstore = fmt::make_wformat_args(n);
std::wstring w;
fmt::vformat_to(std::back_inserter(w), L"{}", wstore);
EXPECT_EQ(L"42", w);
Expand All @@ -227,16 +199,15 @@ TEST(module_test, vformat_to) {
}

TEST(module_test, vformat_to_n) {
auto store = fmt::make_format_args(12345);
int n = 12345;
auto store = fmt::make_format_args(n);
std::string s;
auto result = fmt::vformat_to_n(std::back_inserter(s), 1, "{}", store);
fmt::vformat_to_n(std::back_inserter(s), 1, "{}", store);
char buffer[4] = {0};
fmt::vformat_to_n(buffer, 3, "{:}", store);

auto wstore = fmt::make_wformat_args(12345);
auto wstore = fmt::make_wformat_args(n);
std::wstring w;
auto wresult = fmt::vformat_to_n(std::back_inserter(w), 1,
fmt::wstring_view(L"{}"), wstore);
wchar_t wbuffer[4] = {0};
fmt::vformat_to_n(wbuffer, 3, fmt::wstring_view(L"{:}"), wstore);
}
Expand All @@ -249,18 +220,14 @@ std::string as_string(std::wstring_view text) {
TEST(module_test, print) {
EXPECT_WRITE(stdout, fmt::print("{}µ", 42), "42µ");
EXPECT_WRITE(stderr, fmt::print(stderr, "{}µ", 4.2), "4.2µ");
EXPECT_WRITE(stdout, fmt::print(L"{}µ", 42), as_string(L"42µ"));
EXPECT_WRITE(stderr, fmt::print(stderr, L"{}µ", 4.2), as_string(L"4.2µ"));
}

TEST(module_test, vprint) {
EXPECT_WRITE(stdout, fmt::vprint("{:}µ", fmt::make_format_args(42)), "42µ");
EXPECT_WRITE(stderr, fmt::vprint(stderr, "{}", fmt::make_format_args(4.2)),
int n = 42;
double m = 4.2;
EXPECT_WRITE(stdout, fmt::vprint("{:}µ", fmt::make_format_args(n)), "42µ");
EXPECT_WRITE(stderr, fmt::vprint(stderr, "{}", fmt::make_format_args(m)),
"4.2");
EXPECT_WRITE(stdout, fmt::vprint(L"{:}µ", fmt::make_wformat_args(42)),
as_string(L"42µ"));
EXPECT_WRITE(stderr, fmt::vprint(stderr, L"{}", fmt::make_wformat_args(42)),
as_string(L"42"));
}

TEST(module_test, named_args) {
Expand All @@ -275,7 +242,8 @@ TEST(module_test, literals) {
}

TEST(module_test, locale) {
auto store = fmt::make_format_args(4.2);
const double m = 4.2;
auto store = fmt::make_format_args(m);
const auto classic = std::locale::classic();
EXPECT_EQ("4.2", fmt::format(classic, "{:L}", 4.2));
EXPECT_EQ("4.2", fmt::vformat(classic, "{:L}", store));
Expand All @@ -284,12 +252,9 @@ TEST(module_test, locale) {
EXPECT_EQ("4.2", s);
EXPECT_EQ("4.2", fmt::format("{:L}", 4.2));

auto wstore = fmt::make_wformat_args(4.2);
auto wstore = fmt::make_wformat_args(m);
EXPECT_EQ(L"4.2", fmt::format(classic, L"{:L}", 4.2));
EXPECT_EQ(L"4.2", fmt::vformat(classic, L"{:L}", wstore));
std::wstring w;
fmt::vformat_to(std::back_inserter(w), classic, L"{:L}", wstore);
EXPECT_EQ(L"4.2", w);
EXPECT_EQ(L"4.2", fmt::format(L"{:L}", 4.2));
}

Expand All @@ -313,34 +278,17 @@ TEST(module_test, memory_buffer) {
EXPECT_EQ("42", to_string(buffer));
nbuffer.clear();
EXPECT_EQ(0u, to_string(nbuffer).size());

fmt::wmemory_buffer wbuffer;
EXPECT_EQ(0u, to_string(wbuffer).size());
}

TEST(module_test, is_char) {
EXPECT_TRUE(fmt::is_char<char>());
EXPECT_TRUE(fmt::is_char<wchar_t>());
EXPECT_TRUE(fmt::is_char<char8_t>());
EXPECT_TRUE(fmt::is_char<char16_t>());
EXPECT_TRUE(fmt::is_char<char32_t>());
EXPECT_FALSE(fmt::is_char<signed char>());
}

TEST(module_test, ptr) {
uintptr_t answer = 42;
auto p = std::bit_cast<int*>(answer);
EXPECT_EQ("0x2a", fmt::to_string(fmt::ptr(p)));
std::unique_ptr<int> up(p);
EXPECT_EQ("0x2a", fmt::to_string(fmt::ptr(up)));
up.release();
auto sp = std::make_shared<int>(0);
p = sp.get();
EXPECT_EQ(fmt::to_string(fmt::ptr(p)), fmt::to_string(fmt::ptr(sp)));
}

TEST(module_test, errors) {
auto store = fmt::make_format_args(42);
int n = 42;
auto store = fmt::make_format_args(n);
EXPECT_THROW(throw fmt::format_error("oops"), std::exception);
EXPECT_THROW(throw fmt::vsystem_error(0, "{}", store), std::system_error);
EXPECT_THROW(throw fmt::system_error(0, "{}", 42), std::system_error);
Expand All @@ -365,8 +313,6 @@ TEST(module_test, error_code) {
fmt::format("{0}", std::error_code(42, std::generic_category())));
EXPECT_EQ("system:42",
fmt::format("{0}", std::error_code(42, fmt::system_category())));
EXPECT_EQ(L"generic:42",
fmt::format(L"{0}", std::error_code(42, std::generic_category())));
}

TEST(module_test, format_int) {
Expand All @@ -385,23 +331,19 @@ TEST(module_test, formatter) { EXPECT_TRUE(test_formatter{}.check()); }
TEST(module_test, join) {
int arr[3] = {1, 2, 3};
std::vector<double> vec{1.0, 2.0, 3.0};
std::initializer_list<int> il{1, 2, 3};
auto sep = fmt::string_view(", ");
EXPECT_EQ("1, 2, 3", to_string(fmt::join(arr + 0, arr + 3, sep)));
EXPECT_EQ("1, 2, 3", to_string(fmt::join(arr, sep)));
EXPECT_EQ("1, 2, 3", to_string(fmt::join(vec.begin(), vec.end(), sep)));
EXPECT_EQ("1, 2, 3", to_string(fmt::join(vec, sep)));
EXPECT_EQ("1, 2, 3", to_string(fmt::join(il, sep)));

auto wsep = fmt::wstring_view(L", ");
EXPECT_EQ(L"1, 2, 3", fmt::format(L"{}", fmt::join(arr + 0, arr + 3, wsep)));
EXPECT_EQ(L"1, 2, 3", fmt::format(L"{}", fmt::join(arr, wsep)));
EXPECT_EQ(L"1, 2, 3", fmt::format(L"{}", fmt::join(il, wsep)));
}

TEST(module_test, time) {
auto time_now = std::time(nullptr);
EXPECT_TRUE(fmt::localtime(time_now).tm_year > 120);
EXPECT_TRUE(fmt::gmtime(time_now).tm_year > 120);
auto chrono_now = std::chrono::system_clock::now();
EXPECT_TRUE(fmt::gmtime(chrono_now).tm_year > 120);
Expand Down Expand Up @@ -433,42 +375,34 @@ TEST(module_test, weekday) {
TEST(module_test, printf) {
EXPECT_WRITE(stdout, fmt::printf("%f", 42.123456), "42.123456");
EXPECT_WRITE(stdout, fmt::printf("%d", 42), "42");
EXPECT_WRITE(stdout, fmt::printf(L"%f", 42.123456), as_string(L"42.123456"));
EXPECT_WRITE(stdout, fmt::printf(L"%d", 42), as_string(L"42"));
}

TEST(module_test, fprintf) {
EXPECT_WRITE(stderr, fmt::fprintf(stderr, "%d", 42), "42");
EXPECT_WRITE(stderr, fmt::fprintf(stderr, L"%d", 42), as_string(L"42"));
}

TEST(module_test, sprintf) {
EXPECT_EQ("42", fmt::sprintf("%d", 42));
EXPECT_EQ(L"42", fmt::sprintf(L"%d", 42));
}

TEST(module_test, vprintf) {
EXPECT_WRITE(stdout, fmt::vprintf("%d", fmt::make_printf_args(42)), "42");
EXPECT_WRITE(stdout, fmt::vprintf(L"%d", fmt::make_wprintf_args(42)),
as_string(L"42"));
}

TEST(module_test, vfprintf) {
auto args = fmt::make_printf_args(42);
EXPECT_WRITE(stderr, fmt::vfprintf(stderr, "%d", args), "42");
auto wargs = fmt::make_wprintf_args(42);
EXPECT_WRITE(stderr, fmt::vfprintf(stderr, L"%d", wargs), as_string(L"42"));
int n = 42;
auto store = fmt::make_format_args<fmt::printf_context>(n);
auto args = fmt::basic_format_args<fmt::printf_context>(store);
EXPECT_WRITE(stdout, fmt::vfprintf(stdout, fmt::string_view("%d"), args),
"42");
}

TEST(module_test, vsprintf) {
EXPECT_EQ("42", fmt::vsprintf("%d", fmt::make_printf_args(42)));
EXPECT_EQ(L"42", fmt::vsprintf(L"%d", fmt::make_wprintf_args(42)));
int n = 42;
auto store = fmt::make_format_args<fmt::printf_context>(n);
auto args = fmt::basic_format_args<fmt::printf_context>(store);
EXPECT_EQ(fmt::vsprintf(fmt::string_view("%d"), args), "42");
EXPECT_WRITE(stdout, fmt::vfprintf(stdout, fmt::string_view("%d"), args),
"42");
}
Comment thread
MathewBensonCode marked this conversation as resolved.

TEST(module_test, color) {
auto fg_check = fg(fmt::rgb(255, 200, 30));
auto bg_check = bg(fmt::color::dark_slate_gray) | fmt::emphasis::italic;
auto emphasis_check = fmt::emphasis::underline | fmt::emphasis::bold;
EXPECT_EQ("\x1B[30m42\x1B[0m",
fmt::format(fg(fmt::terminal_color::black), "{}", 42));
EXPECT_EQ(L"\x1B[30m42\x1B[0m",
Expand Down
Loading