Mercurial > minori
diff dep/fmt/test/scan-test.cc @ 343:1faa72660932
*: transfer back to cmake from autotools
autotools just made lots of things more complicated than
they should have and many things broke (i.e. translations)
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Thu, 20 Jun 2024 05:56:06 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dep/fmt/test/scan-test.cc Thu Jun 20 05:56:06 2024 -0400 @@ -0,0 +1,188 @@ +// Formatting library for C++ - scanning API test +// +// Copyright (c) 2019 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#include "scan.h" + +#include <time.h> + +#include <climits> +#include <thread> + +#include "fmt/os.h" +#include "gmock/gmock.h" +#include "gtest-extra.h" + +TEST(scan_test, read_text) { + fmt::string_view s = "foo"; + auto end = fmt::scan(s, "foo"); + EXPECT_EQ(end, s.end()); + EXPECT_THROW_MSG(fmt::scan("fob", "foo"), fmt::format_error, "invalid input"); +} + +TEST(scan_test, read_int) { + int n = 0; + fmt::scan("42", "{}", n); + EXPECT_EQ(n, 42); + fmt::scan("-42", "{}", n); + EXPECT_EQ(n, -42); + fmt::scan("42", "{:}", n); + EXPECT_EQ(n, 42); + EXPECT_THROW_MSG(fmt::scan(std::to_string(INT_MAX + 1u), "{}", n), + fmt::format_error, "number is too big"); +} + +TEST(scan_test, read_longlong) { + long long n = 0; + fmt::scan("42", "{}", n); + EXPECT_EQ(n, 42); + fmt::scan("-42", "{}", n); + EXPECT_EQ(n, -42); +} + +TEST(scan_test, read_uint) { + unsigned n = 0; + fmt::scan("42", "{}", n); + EXPECT_EQ(n, 42); + EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error, + "invalid input"); +} + +TEST(scan_test, read_ulonglong) { + unsigned long long n = 0; + fmt::scan("42", "{}", n); + EXPECT_EQ(n, 42); + EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error, + "invalid input"); +} + +TEST(scan_test, read_hex) { + unsigned n = 0; + fmt::scan("2a", "{:x}", n); + EXPECT_EQ(n, 42); + auto num_digits = std::numeric_limits<unsigned>::digits / 4; + EXPECT_THROW_MSG(fmt::scan(fmt::format("1{:0{}}", 0, num_digits), "{:x}", n), + fmt::format_error, "number is too big"); +} + +TEST(scan_test, read_string) { + std::string s; + fmt::scan("foo", "{}", s); + EXPECT_EQ(s, "foo"); +} + +TEST(scan_test, read_string_view) { + fmt::string_view s; + fmt::scan("foo", "{}", s); + EXPECT_EQ(s, "foo"); +} + +TEST(scan_test, separator) { + int n1 = 0, n2 = 0; + fmt::scan("10 20", "{} {}", n1, n2); + EXPECT_EQ(n1, 10); + EXPECT_EQ(n2, 20); +} + +struct num { + int value; +}; + +namespace fmt { +template <> struct scanner<num> { + bool hex = false; + + auto parse(scan_parse_context& ctx) -> scan_parse_context::iterator { + auto it = ctx.begin(), end = ctx.end(); + if (it != end && *it == 'x') hex = true; + if (it != end && *it != '}') throw_format_error("invalid format"); + return it; + } + + template <class ScanContext> + auto scan(num& n, ScanContext& ctx) const -> typename ScanContext::iterator { + // TODO: handle specifier + return fmt::scan(ctx, "{}", n.value); + } +}; +} // namespace fmt + +TEST(scan_test, read_custom) { + auto input = "42"; + auto n = num(); + fmt::scan(input, "{:}", n); + EXPECT_EQ(n.value, 42); +} + +TEST(scan_test, invalid_format) { + EXPECT_THROW_MSG(fmt::scan("", "{}"), fmt::format_error, + "argument index out of range"); + EXPECT_THROW_MSG(fmt::scan("", "{"), fmt::format_error, + "invalid format string"); +} + +TEST(scan_test, example) { + std::string key; + int value = 0; + fmt::scan("answer = 42", "{} = {}", key, value); + EXPECT_EQ(key, "answer"); + EXPECT_EQ(value, 42); +} + +TEST(scan_test, end_of_input) { + int value = 0; + fmt::scan("", "{}", value); +} + +#if FMT_USE_FCNTL +TEST(scan_test, file) { + fmt::file read_end, write_end; + fmt::file::pipe(read_end, write_end); + + fmt::string_view input = "10 20"; + write_end.write(input.data(), input.size()); + write_end.close(); + + int n1 = 0, n2 = 0; + fmt::buffered_file f = read_end.fdopen("r"); + fmt::scan(f.get(), "{} {}", n1, n2); + EXPECT_EQ(n1, 10); + EXPECT_EQ(n2, 20); +} + +TEST(scan_test, lock) { + fmt::file read_end, write_end; + fmt::file::pipe(read_end, write_end); + + std::thread producer([&]() { + fmt::string_view input = "42 "; + for (int i = 0; i < 1000; ++i) write_end.write(input.data(), input.size()); + write_end.close(); + }); + + std::atomic<int> count(0); + fmt::buffered_file f = read_end.fdopen("r"); + auto fun = [&]() { + int value = 0; + while (fmt::scan(f.get(), "{}", value)) { + if (value != 42) { + read_end.close(); + EXPECT_EQ(value, 42); + break; + } + ++count; + } + }; + std::thread consumer1(fun); + std::thread consumer2(fun); + + producer.join(); + consumer1.join(); + consumer2.join(); + EXPECT_EQ(count, 1000); + +} +#endif // FMT_USE_FCNTL