comparison 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
comparison
equal deleted inserted replaced
342:adb79bdde329 343:1faa72660932
1 // Formatting library for C++ - scanning API test
2 //
3 // Copyright (c) 2019 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7
8 #include "scan.h"
9
10 #include <time.h>
11
12 #include <climits>
13 #include <thread>
14
15 #include "fmt/os.h"
16 #include "gmock/gmock.h"
17 #include "gtest-extra.h"
18
19 TEST(scan_test, read_text) {
20 fmt::string_view s = "foo";
21 auto end = fmt::scan(s, "foo");
22 EXPECT_EQ(end, s.end());
23 EXPECT_THROW_MSG(fmt::scan("fob", "foo"), fmt::format_error, "invalid input");
24 }
25
26 TEST(scan_test, read_int) {
27 int n = 0;
28 fmt::scan("42", "{}", n);
29 EXPECT_EQ(n, 42);
30 fmt::scan("-42", "{}", n);
31 EXPECT_EQ(n, -42);
32 fmt::scan("42", "{:}", n);
33 EXPECT_EQ(n, 42);
34 EXPECT_THROW_MSG(fmt::scan(std::to_string(INT_MAX + 1u), "{}", n),
35 fmt::format_error, "number is too big");
36 }
37
38 TEST(scan_test, read_longlong) {
39 long long n = 0;
40 fmt::scan("42", "{}", n);
41 EXPECT_EQ(n, 42);
42 fmt::scan("-42", "{}", n);
43 EXPECT_EQ(n, -42);
44 }
45
46 TEST(scan_test, read_uint) {
47 unsigned n = 0;
48 fmt::scan("42", "{}", n);
49 EXPECT_EQ(n, 42);
50 EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error,
51 "invalid input");
52 }
53
54 TEST(scan_test, read_ulonglong) {
55 unsigned long long n = 0;
56 fmt::scan("42", "{}", n);
57 EXPECT_EQ(n, 42);
58 EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error,
59 "invalid input");
60 }
61
62 TEST(scan_test, read_hex) {
63 unsigned n = 0;
64 fmt::scan("2a", "{:x}", n);
65 EXPECT_EQ(n, 42);
66 auto num_digits = std::numeric_limits<unsigned>::digits / 4;
67 EXPECT_THROW_MSG(fmt::scan(fmt::format("1{:0{}}", 0, num_digits), "{:x}", n),
68 fmt::format_error, "number is too big");
69 }
70
71 TEST(scan_test, read_string) {
72 std::string s;
73 fmt::scan("foo", "{}", s);
74 EXPECT_EQ(s, "foo");
75 }
76
77 TEST(scan_test, read_string_view) {
78 fmt::string_view s;
79 fmt::scan("foo", "{}", s);
80 EXPECT_EQ(s, "foo");
81 }
82
83 TEST(scan_test, separator) {
84 int n1 = 0, n2 = 0;
85 fmt::scan("10 20", "{} {}", n1, n2);
86 EXPECT_EQ(n1, 10);
87 EXPECT_EQ(n2, 20);
88 }
89
90 struct num {
91 int value;
92 };
93
94 namespace fmt {
95 template <> struct scanner<num> {
96 bool hex = false;
97
98 auto parse(scan_parse_context& ctx) -> scan_parse_context::iterator {
99 auto it = ctx.begin(), end = ctx.end();
100 if (it != end && *it == 'x') hex = true;
101 if (it != end && *it != '}') throw_format_error("invalid format");
102 return it;
103 }
104
105 template <class ScanContext>
106 auto scan(num& n, ScanContext& ctx) const -> typename ScanContext::iterator {
107 // TODO: handle specifier
108 return fmt::scan(ctx, "{}", n.value);
109 }
110 };
111 } // namespace fmt
112
113 TEST(scan_test, read_custom) {
114 auto input = "42";
115 auto n = num();
116 fmt::scan(input, "{:}", n);
117 EXPECT_EQ(n.value, 42);
118 }
119
120 TEST(scan_test, invalid_format) {
121 EXPECT_THROW_MSG(fmt::scan("", "{}"), fmt::format_error,
122 "argument index out of range");
123 EXPECT_THROW_MSG(fmt::scan("", "{"), fmt::format_error,
124 "invalid format string");
125 }
126
127 TEST(scan_test, example) {
128 std::string key;
129 int value = 0;
130 fmt::scan("answer = 42", "{} = {}", key, value);
131 EXPECT_EQ(key, "answer");
132 EXPECT_EQ(value, 42);
133 }
134
135 TEST(scan_test, end_of_input) {
136 int value = 0;
137 fmt::scan("", "{}", value);
138 }
139
140 #if FMT_USE_FCNTL
141 TEST(scan_test, file) {
142 fmt::file read_end, write_end;
143 fmt::file::pipe(read_end, write_end);
144
145 fmt::string_view input = "10 20";
146 write_end.write(input.data(), input.size());
147 write_end.close();
148
149 int n1 = 0, n2 = 0;
150 fmt::buffered_file f = read_end.fdopen("r");
151 fmt::scan(f.get(), "{} {}", n1, n2);
152 EXPECT_EQ(n1, 10);
153 EXPECT_EQ(n2, 20);
154 }
155
156 TEST(scan_test, lock) {
157 fmt::file read_end, write_end;
158 fmt::file::pipe(read_end, write_end);
159
160 std::thread producer([&]() {
161 fmt::string_view input = "42 ";
162 for (int i = 0; i < 1000; ++i) write_end.write(input.data(), input.size());
163 write_end.close();
164 });
165
166 std::atomic<int> count(0);
167 fmt::buffered_file f = read_end.fdopen("r");
168 auto fun = [&]() {
169 int value = 0;
170 while (fmt::scan(f.get(), "{}", value)) {
171 if (value != 42) {
172 read_end.close();
173 EXPECT_EQ(value, 42);
174 break;
175 }
176 ++count;
177 }
178 };
179 std::thread consumer1(fun);
180 std::thread consumer2(fun);
181
182 producer.join();
183 consumer1.join();
184 consumer2.join();
185 EXPECT_EQ(count, 1000);
186
187 }
188 #endif // FMT_USE_FCNTL