9#ifndef INCLUDED_BSLFMT_FORMATTERTESTUTIL
10#define INCLUDED_BSLFMT_FORMATTERTESTUTIL
116#include <bslscm_version.h>
149#if defined(BSLS_COMPILERFEATURES_FULL_CPP11)
150# include <type_traits>
153using namespace BloombergLP;
155#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20
156# define BSLFMT_FORMATTER_TEST_CONSTEVAL consteval
158# define BSLFMT_FORMATTER_TEST_CONSTEVAL
161#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
162#define BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING \
163 std::format_string<t_TYPE>
164#define BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_ONE_ARG \
165 std::format_string<t_TYPE, t_ARG>
166#define BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_TWO_ARGS \
167 std::format_string<t_TYPE, t_ARG_1, t_ARG_2>
168#define BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING \
169 std::wformat_string<t_TYPE>
170#define BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_ONE_ARG \
171 std::wformat_string<t_TYPE, t_ARG>
172#define BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_TWO_ARGS \
173 std::wformat_string<t_TYPE, t_ARG_1, t_ARG_2>
174#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING \
175 std::basic_format_string<t_CHAR, t_TYPE>
176#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_ONE_ARG \
177 std::basic_format_string<t_CHAR, t_TYPE, t_ARG>
178#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_TWO_ARGS \
179 std::basic_format_string<t_CHAR, t_TYPE, t_ARG_1, t_ARG_2>
180#define BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_P \
181 std::format_string<t_TYPE, int, int>
182#define BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_P \
183 std::wformat_string<t_TYPE, int, int>
184#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_P \
185 std::basic_format_string<t_CHAR, t_TYPE, int, int>
186#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_GETTER(ARG) \
189#define BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING \
190 bslfmt::basic_format_string<char>
191#define BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_ONE_ARG \
192 bslfmt::basic_format_string<char>
193#define BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_TWO_ARGS \
194 bslfmt::basic_format_string<char>
195#define BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING \
196 bslfmt::basic_format_string<wchar_t>
197#define BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_ONE_ARG \
198 bslfmt::basic_format_string<wchar_t>
199#define BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_TWO_ARGS \
200 bslfmt::basic_format_string<wchar_t>
201#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING \
202 bslfmt::basic_format_string<t_CHAR>
203#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_ONE_ARG \
204 bslfmt::basic_format_string<t_CHAR>
205#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_TWO_ARGS \
206 bslfmt::basic_format_string<t_CHAR>
207#define BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_P \
208 bslfmt::basic_format_string<char>
209#define BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_P \
210 bslfmt::basic_format_string<wchar_t>
211#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_P \
212 bslfmt::basic_format_string<t_CHAR>
213#define BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_GETTER(ARG) \
220#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
231template <
class t_CHAR>
232struct FormatterTestUtil_Oracle {
237struct FormatterTestUtil_Oracle<char> {
245 template <
class t_TYPE,
class... t_ARGS>
255struct FormatterTestUtil_Oracle<wchar_t> {
263 template <
class t_TYPE,
class... t_ARGS>
284template <
class t_CHAR>
295 template <
class t_TYPE>
296 static bool evaluateBslfmtResult(
309 template <
class t_TYPE>
310 static bool testEvaluateVFormatBslfmtImpl(
317#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
323 template <
class t_TYPE,
class... t_ARGS>
324 static bool testEvaluateVFormatStdImpl(
340 template <
class t_TYPE>
345 bool expectedToFail);
368 template <
class t_TYPE>
375 template <
class t_TYPE,
class t_ARG>
383 template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
404 template <
class t_TYPE>
411 template <
class t_TYPE,
class t_ARG>
419 template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
435 template <
class t_TYPE>
449 template <
class t_TYPE>
463 template <
class t_TYPE>
480template <
class t_CHAR>
501 template <
class t_TYPE>
502 static bool testEvaluateFormat(
508 template <
class t_TYPE,
class t_ARG>
509 static bool testEvaluateFormat(
516 template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
517 static bool testEvaluateFormat(
537 template <
class t_TYPE>
538 static bool testEvaluateVFormat(
545 template <
class t_TYPE,
class t_ARG>
546 static bool testEvaluateVFormat(
554 template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
555 static bool testEvaluateVFormat(
570 template <
class t_TYPE>
583 template <
class t_TYPE>
597 template <
class t_TYPE>
620 template <
class t_TYPE>
621 static bool testEvaluateFormat(
628 template <
class t_TYPE,
class t_ARG>
629 static bool testEvaluateFormat(
637 template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
638 static bool testEvaluateFormat(
658 template <
class t_TYPE>
659 static bool testEvaluateVFormat(
666 template <
class t_TYPE,
class t_ARG>
667 static bool testEvaluateVFormat(
675 template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
676 static bool testEvaluateVFormat(
691 template <
class t_TYPE>
692 static bool testParseFailure(
705 template <
class t_TYPE>
719 template <
class t_TYPE>
720 static bool testParseVFormat(
730#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
736template <
class t_TYPE,
class... t_ARGS>
737void FormatterTestUtil_Oracle<char>::evaluateOracle(
743 *result = std::vformat(fmtStr, std::make_format_args(value, args...));
746template <
class t_TYPE,
class... t_ARGS>
747void FormatterTestUtil_Oracle<wchar_t>::evaluateOracle(
753 *result = std::vformat(fmtStr, std::make_wformat_args(value, args...));
763template <
class t_CHAR>
764template <
class t_TYPE>
765bool FormatterTestUtil_Impl<t_CHAR>::evaluateBslfmtResult(
772 MockParseContext<t_CHAR> mpc(fmtStr, 3);
774 if (fmtStr.
size() == 0) {
776 *message =
"Empty format string";
780 if (fmtStr.
front() !=
'{') {
782 *message =
"Opening brace missing";
786 mpc.advance_to(mpc.begin() + 1);
788 if (fmtStr.
size() == 0) {
790 *message =
"Format string too short";
794 if (fmtStr.
front() !=
'0' && fmtStr.
front() !=
':' &&
795 fmtStr.
front() !=
'}') {
797 *message =
"For testing, value must be arg 0 if specified";
801 if (fmtStr.
front() ==
'0') {
804 mpc.advance_to(mpc.begin() + 1);
805 if (fmtStr.
size() == 0) {
807 *message =
"Format string too short";
810 if (fmtStr.
front() !=
':' && fmtStr.
front() !=
'}') {
812 *message =
"Missing ':' separator";
817 (void) mpc.next_arg_id();
820 if (fmtStr.
front() ==
':') {
822 mpc.advance_to(mpc.begin() + 1);
825 if (fmtStr.
size() == 0) {
827 *message =
"Format string too short";
834 mpc.advance_to(formatter.parse(mpc));
836 if (mpc.begin() != mpc.end() &&
837 (*mpc.begin() !=
'}' || mpc.begin() + 1 != mpc.end())) {
839 *message =
"Spec string has extra characters";
843 MockFormatContext<t_CHAR>& mockFormatContext = mockContext;
844 mockFormatContext.advance_to(
849 catch (
const bsl::format_error& e) {
851 *message =
"Exception bsl::format_error: ";
852 *message += e.what();
860template <
class t_CHAR>
861template <
class t_TYPE>
862bool FormatterTestUtil_Impl<t_CHAR>::testEvaluateVFormatBslfmtImpl(
871 bool rv = evaluateBslfmtResult(
882 if (expectedResult != bslfmtResult) {
884 *message =
"bslfmt result does not match: Format: \"";
885 *message += toNarrow(fmtStr);
886 *message +=
"\", result: \"";
887 *message += toNarrow(bslfmtResult);
888 *message +=
"\" != EXPECTED: \"";
889 *message += toNarrow(expectedResult);
898#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
899template <
class t_CHAR>
900template <
class t_TYPE,
class... t_ARGS>
901bool FormatterTestUtil_Impl<t_CHAR>::testEvaluateVFormatStdImpl(
910 FormatterTestUtil_Oracle<t_CHAR>::evaluateOracle(
913 std::forward<t_TYPE>(value),
914 std::forward<t_ARGS>(args)...);
916 catch (
const std::format_error& e) {
918 *message =
"Exception std::format_error: ";
919 *message += e.what();
924 if (expectedResult != stdResult) {
926 *message =
"oracle result does not match: Format: \"";
927 *message += toNarrow(fmtStr);
928 *message +=
"\", Oracle: \"";
929 *message += toNarrow(stdResult);
930 *message +=
"\" != EXPECTED: \"";
931 *message += toNarrow(expectedResult);
941template <
class t_CHAR>
942template <
class t_TYPE>
944FormatterTestUtil_Impl<t_CHAR>::testParseFormatImpl(
950 MockParseContext<t_CHAR> mpc(fmtStr, 3);
952 if (fmtStr.
size() == 0) {
954 *message =
"Empty format string";
958 if (fmtStr.
front() !=
'{') {
960 *message =
"Opening brace missing";
964 mpc.advance_to(mpc.begin() + 1);
966 if (fmtStr.
size() == 0) {
968 *message =
"Format string too short";
972 if (fmtStr.
front() !=
'0' && fmtStr.
front() !=
':' &&
973 fmtStr.
front() !=
'}') {
975 *message =
"For testing, value must be arg 0 if specified";
981 if (fmtStr.
front() ==
'0') {
984 mpc.advance_to(mpc.begin() + 1);
985 if (fmtStr.
size() == 0) {
987 *message =
"Format string too short";
990 if (fmtStr.
front() !=
':' && fmtStr.
front() !=
'}') {
992 *message =
"Missing ':' separator";
998 (void)mpc.next_arg_id();
1002 if (fmtStr.
front() ==
':') {
1004 mpc.advance_to(mpc.begin() + 1);
1007 if (fmtStr.
size() == 0) {
1009 *message =
"Format string too short";
1015 if (expectedToFail) {
1017 mpc.advance_to(bslFormatter.parse(mpc));
1020 *message =
"bslfmt parsing failed to fail";
1023 catch (
const bsl::format_error&) {
1028 mpc.advance_to(bslFormatter.parse(mpc));
1030 catch (
const bsl::format_error&) {
1032 *message =
"bslfmt parsing failed";
1037#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
1041# if defined(BSLS_PLATFORM_CMP_MSVC)
1042 if (std::is_constant_evaluated()) {
1043 alsoTestOracle =
false;
1047 if (alsoTestOracle) {
1050 std::basic_format_parse_context<t_CHAR> spc(fmtStr, 3);
1053 spc.check_arg_id(0);
1056 (void)spc.next_arg_id();
1058 std::formatter<typename bsl::decay<t_TYPE>::type, t_CHAR> stdFormatter;
1060 if (expectedToFail) {
1062 spc.advance_to(stdFormatter.parse(spc));
1065 *message =
"std parsing failed to fail";
1068 catch (
const bsl::format_error&) {
1073 spc.advance_to(stdFormatter.parse(spc));
1075 catch (
const bsl::format_error&) {
1077 *message =
"std parsing failed";
1083 (void)alsoTestOracle;
1090template <
class t_CHAR>
1097template <
class t_CHAR>
1102 const std::locale loc;
1105 for (Cit i =
string.
begin(); i !=
string.end(); ++i) {
1106 rv += std::use_facet<std::ctype<wchar_t> >(loc).narrow(*i,
'?');
1112template <
class t_CHAR>
1113template <
class t_TYPE>
1117 bool alsoTestOracle,
1124 return testEvaluateVFormat(message,
1131template <
class t_CHAR>
1132template <
class t_TYPE,
class t_ARG>
1136 bool alsoTestOracle,
1144 return testEvaluateVFormat(message,
1152template <
class t_CHAR>
1153template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
1157 bool alsoTestOracle,
1166 return testEvaluateVFormat(message,
1175template <
class t_CHAR>
1176template <
class t_TYPE>
1180 bool alsoTestOracle,
1185 bool rv = testEvaluateVFormatBslfmtImpl(
1196#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
1197 if (alsoTestOracle) {
1198 rv = testEvaluateVFormatStdImpl(message,
1201 std::forward<t_TYPE>(value));
1204 (void) alsoTestOracle;
1210template <
class t_CHAR>
1211template <
class t_TYPE,
class t_ARG>
1215 bool alsoTestOracle,
1221 bool rv = testEvaluateVFormatBslfmtImpl(
1232#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
1233 if (alsoTestOracle) {
1234 rv = testEvaluateVFormatStdImpl(message,
1237 std::forward<t_TYPE>(value),
1238 std::forward<t_ARG>(arg));
1241 (void) alsoTestOracle;
1247template <
class t_CHAR>
1248template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
1252 bool alsoTestOracle,
1259 bool rv = testEvaluateVFormatBslfmtImpl(
1270#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
1271 if (alsoTestOracle) {
1272 rv = testEvaluateVFormatStdImpl(message,
1275 std::forward<t_TYPE>(value),
1276 std::forward<t_ARG_1>(arg1),
1277 std::forward<t_ARG_2>(arg2));
1280 (void) alsoTestOracle;
1286template <
class t_CHAR>
1287template <
class t_TYPE>
1290 bool alsoTestOracle,
1293 return testParseFormatImpl<t_TYPE>(message, alsoTestOracle, fmtStr,
true);
1296template <
class t_CHAR>
1297template <
class t_TYPE>
1301 bool alsoTestOracle,
1307 return testParseFormatImpl<t_TYPE>(message,
1313template <
class t_CHAR>
1314template <
class t_TYPE>
1317 bool alsoTestOracle,
1320 return testParseFormatImpl<t_TYPE>(message, alsoTestOracle, fmtStr,
false);
1328template <
class t_TYPE>
1332 bool alsoTestOracle,
1344template <
class t_TYPE,
class t_ARG>
1348 bool alsoTestOracle,
1362template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
1366 bool alsoTestOracle,
1382template <
class t_TYPE>
1386 bool alsoTestOracle,
1398template <
class t_TYPE,
class t_ARG>
1402 bool alsoTestOracle,
1416template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
1420 bool alsoTestOracle,
1436template <
class t_TYPE>
1439 bool alsoTestOracle,
1448template <
class t_TYPE>
1452 bool alsoTestOracle,
1461template <
class t_TYPE>
1464 bool alsoTestOracle,
1473template <
class t_TYPE>
1477 bool alsoTestOracle,
1489template <
class t_TYPE,
class t_ARG>
1493 bool alsoTestOracle,
1507template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
1511 bool alsoTestOracle,
1527template <
class t_TYPE>
1531 bool alsoTestOracle,
1543template <
class t_TYPE,
class t_ARG>
1547 bool alsoTestOracle,
1561template <
class t_TYPE,
class t_ARG_1,
class t_ARG_2>
1565 bool alsoTestOracle,
1581template <
class t_TYPE>
1584 bool alsoTestOracle,
1593template <
class t_TYPE>
1597 bool alsoTestOracle,
1606template <
class t_TYPE>
1609 bool alsoTestOracle,
1621#undef BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING
1622#undef BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_ONE_ARG
1623#undef BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_TWO_ARGS
1624#undef BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING
1625#undef BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_ONE_ARG
1626#undef BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_TWO_ARGS
1627#undef BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING
1628#undef BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_ONE_ARG
1629#undef BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_TWO_ARGS
1630#undef BSLFMT_FORMATTER_TEST_UTIL_FORMAT_STRING_P
1631#undef BSLFMT_FORMATTER_TEST_UTIL_WFORMAT_STRING_P
1632#undef BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_P
1633#undef BSLFMT_FORMATTER_TEST_UTIL_BASIC_FORMAT_STRING_GETTER
1634#undef BSLFMT_FORMATTER_TEST_CONSTEVAL
Definition bslstl_stringview.h:471
BSLS_KEYWORD_CONSTEXPR size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the length of this view.
Definition bslstl_stringview.h:1904
BSLS_KEYWORD_CONSTEXPR_CPP14 const_reference front() const
Definition bslstl_stringview.h:1966
const value_type * const_iterator
Definition bslstl_stringview.h:481
BSLS_KEYWORD_CONSTEXPR_CPP14 void remove_prefix(size_type numChars)
Definition bslstl_stringview.h:1800
Definition bslstl_string.h:1252
Definition bslfmt_mockformatcontext.h:206
Definition bslmf_movableref.h:752
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR_CPP20
Definition bsls_keyword.h:645
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
T::iterator begin(T &container)
Definition bslstl_iterator.h:1593
basic_string< char > string
Definition bslstl_string.h:844
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1325
BSLS_KEYWORD_CONSTEXPR bsl::add_const< TYPE >::type & as_const(TYPE &t) BSLS_KEYWORD_NOEXCEPT
Return a reference offering non-modifiable access to the specified t.
Definition bslstl_utility.h:129
Definition bslfmt_enablestreamedformatter.h:130
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1039