Mercurial > minori
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 |