mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-29 13:21:05 +00:00
Fix Fix https://github.com/cppformat/cppformat/issues/50 in tests too.
This commit is contained in:
parent
24d6baa60f
commit
8f8fd769ee
@ -37,12 +37,12 @@
|
||||
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
// Fix MSVC warning about "unsafe" fopen.
|
||||
FILE *FOpen(const char *filename, const char *mode) {
|
||||
FILE *safe_fopen(const char *filename, const char *mode) {
|
||||
FILE *f = 0;
|
||||
errno = fopen_s(&f, filename, mode);
|
||||
return f;
|
||||
}
|
||||
#define fopen FOpen
|
||||
#define fopen safe_fopen
|
||||
#endif
|
||||
|
||||
#include "format.h"
|
||||
@ -70,7 +70,7 @@ namespace {
|
||||
// Checks if writing value to BasicWriter<Char> produces the same result
|
||||
// as writing it to std::basic_ostringstream<Char>.
|
||||
template <typename Char, typename T>
|
||||
static ::testing::AssertionResult CheckWrite(const T &value, const char *type) {
|
||||
::testing::AssertionResult check_write(const T &value, const char *type) {
|
||||
std::basic_ostringstream<Char> os;
|
||||
os << value;
|
||||
std::basic_string<Char> expected = os.str();
|
||||
@ -86,8 +86,8 @@ static ::testing::AssertionResult CheckWrite(const T &value, const char *type) {
|
||||
struct AnyWriteChecker {
|
||||
template <typename T>
|
||||
::testing::AssertionResult operator()(const char *, const T &value) const {
|
||||
::testing::AssertionResult result = CheckWrite<char>(value, "char");
|
||||
return result ? CheckWrite<wchar_t>(value, "wchar_t") : result;
|
||||
::testing::AssertionResult result = check_write<char>(value, "char");
|
||||
return result ? check_write<wchar_t>(value, "wchar_t") : result;
|
||||
}
|
||||
};
|
||||
|
||||
@ -95,7 +95,7 @@ template <typename Char>
|
||||
struct WriteChecker {
|
||||
template <typename T>
|
||||
::testing::AssertionResult operator()(const char *, const T &value) const {
|
||||
return CheckWrite<Char>(value, "char");
|
||||
return check_write<Char>(value, "char");
|
||||
}
|
||||
};
|
||||
|
||||
@ -107,14 +107,7 @@ struct WriteChecker {
|
||||
EXPECT_PRED_FORMAT1(WriteChecker<char>(), value)
|
||||
#define CHECK_WRITE_WCHAR(value) \
|
||||
EXPECT_PRED_FORMAT1(WriteChecker<wchar_t>(), value)
|
||||
|
||||
std::string ReadFile(StringRef filename) {
|
||||
std::ifstream out(filename.c_str());
|
||||
std::stringstream content;
|
||||
content << out.rdbuf();
|
||||
return content.str();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class TestString {
|
||||
private:
|
||||
@ -137,7 +130,7 @@ TEST(ArrayTest, Ctor) {
|
||||
|
||||
#if FMT_USE_RVALUE_REFERENCES
|
||||
|
||||
void CheckMoveArray(const char *str, Array<char, 5> &array) {
|
||||
void check_move_array(const char *str, Array<char, 5> &array) {
|
||||
Array<char, 5> array2(std::move(array));
|
||||
// Move shouldn't destroy the inline content of the first array.
|
||||
EXPECT_EQ(str, std::string(&array[0], array.size()));
|
||||
@ -149,11 +142,11 @@ TEST(ArrayTest, MoveCtor) {
|
||||
Array<char, 5> array;
|
||||
const char test[] = "test";
|
||||
array.append(test, test + 4);
|
||||
CheckMoveArray("test", array);
|
||||
check_move_array("test", array);
|
||||
// Adding one more character fills the inline buffer, but doesn't cause
|
||||
// dynamic allocation.
|
||||
array.push_back('a');
|
||||
CheckMoveArray("testa", array);
|
||||
check_move_array("testa", array);
|
||||
const char *inline_buffer_ptr = &array[0];
|
||||
// Adding one more character causes the content to move from the inline to
|
||||
// a dynamically allocated buffer.
|
||||
@ -165,7 +158,7 @@ TEST(ArrayTest, MoveCtor) {
|
||||
EXPECT_GT(array2.capacity(), 5u);
|
||||
}
|
||||
|
||||
void CheckMoveAssignArray(const char *str, Array<char, 5> &array) {
|
||||
void check_move_assign_array(const char *str, Array<char, 5> &array) {
|
||||
Array<char, 5> array2;
|
||||
array2 = std::move(array);
|
||||
// Move shouldn't destroy the inline content of the first array.
|
||||
@ -178,11 +171,11 @@ TEST(ArrayTest, MoveAssignment) {
|
||||
Array<char, 5> array;
|
||||
const char test[] = "test";
|
||||
array.append(test, test + 4);
|
||||
CheckMoveAssignArray("test", array);
|
||||
check_move_assign_array("test", array);
|
||||
// Adding one more character fills the inline buffer, but doesn't cause
|
||||
// dynamic allocation.
|
||||
array.push_back('a');
|
||||
CheckMoveAssignArray("testa", array);
|
||||
check_move_assign_array("testa", array);
|
||||
const char *inline_buffer_ptr = &array[0];
|
||||
// Adding one more character causes the content to move from the inline to
|
||||
// a dynamically allocated buffer.
|
||||
@ -286,7 +279,7 @@ TEST(WriterTest, Ctor) {
|
||||
|
||||
#if FMT_USE_RVALUE_REFERENCES
|
||||
|
||||
void CheckMoveWriter(const std::string &str, Writer &w) {
|
||||
void check_move_writer(const std::string &str, Writer &w) {
|
||||
Writer w2(std::move(w));
|
||||
// Move shouldn't destroy the inline content of the first writer.
|
||||
EXPECT_EQ(str, w.str());
|
||||
@ -296,14 +289,14 @@ void CheckMoveWriter(const std::string &str, Writer &w) {
|
||||
TEST(WriterTest, MoveCtor) {
|
||||
Writer w;
|
||||
w << "test";
|
||||
CheckMoveWriter("test", w);
|
||||
check_move_writer("test", w);
|
||||
// This fills the inline buffer, but doesn't cause dynamic allocation.
|
||||
std::string s;
|
||||
for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE; ++i)
|
||||
s += '*';
|
||||
w.clear();
|
||||
w << s;
|
||||
CheckMoveWriter(s, w);
|
||||
check_move_writer(s, w);
|
||||
const char *inline_buffer_ptr = w.data();
|
||||
// Adding one more character causes the content to move from the inline to
|
||||
// a dynamically allocated buffer.
|
||||
@ -611,15 +604,15 @@ TEST(FormatterTest, ArgErrors) {
|
||||
"argument index is out of range in format");
|
||||
|
||||
char format_str[BUFFER_SIZE];
|
||||
SPrintf(format_str, "{%u", INT_MAX);
|
||||
safe_sprintf(format_str, "{%u", INT_MAX);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format");
|
||||
SPrintf(format_str, "{%u}", INT_MAX);
|
||||
safe_sprintf(format_str, "{%u}", INT_MAX);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError,
|
||||
"argument index is out of range in format");
|
||||
|
||||
SPrintf(format_str, "{%u", INT_MAX + 1u);
|
||||
safe_sprintf(format_str, "{%u", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format");
|
||||
SPrintf(format_str, "{%u}", INT_MAX + 1u);
|
||||
safe_sprintf(format_str, "{%u}", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError, "number is too big in format");
|
||||
}
|
||||
|
||||
@ -892,8 +885,8 @@ TEST(FormatterTest, ZeroFlag) {
|
||||
|
||||
TEST(FormatterTest, Width) {
|
||||
char format_str[BUFFER_SIZE];
|
||||
SPrintf(format_str, "{0:%u", UINT_MAX);
|
||||
Increment(format_str + 3);
|
||||
safe_sprintf(format_str, "{0:%u", UINT_MAX);
|
||||
increment(format_str + 3);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format");
|
||||
std::size_t size = std::strlen(format_str);
|
||||
format_str[size] = '}';
|
||||
@ -901,9 +894,9 @@ TEST(FormatterTest, Width) {
|
||||
EXPECT_THROW_MSG(format(format_str, 0),
|
||||
FormatError, "number is too big in format");
|
||||
|
||||
SPrintf(format_str, "{0:%u", INT_MAX + 1u);
|
||||
safe_sprintf(format_str, "{0:%u", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format");
|
||||
SPrintf(format_str, "{0:%u}", INT_MAX + 1u);
|
||||
safe_sprintf(format_str, "{0:%u}", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str, 0),
|
||||
FormatError, "number is too big in format");
|
||||
EXPECT_EQ(" -42", format("{0:4}", -42));
|
||||
@ -922,8 +915,8 @@ TEST(FormatterTest, Width) {
|
||||
|
||||
TEST(FormatterTest, Precision) {
|
||||
char format_str[BUFFER_SIZE];
|
||||
SPrintf(format_str, "{0:.%u", UINT_MAX);
|
||||
Increment(format_str + 4);
|
||||
safe_sprintf(format_str, "{0:.%u", UINT_MAX);
|
||||
increment(format_str + 4);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format");
|
||||
std::size_t size = std::strlen(format_str);
|
||||
format_str[size] = '}';
|
||||
@ -931,9 +924,9 @@ TEST(FormatterTest, Precision) {
|
||||
EXPECT_THROW_MSG(format(format_str, 0),
|
||||
FormatError, "number is too big in format");
|
||||
|
||||
SPrintf(format_str, "{0:.%u", INT_MAX + 1u);
|
||||
safe_sprintf(format_str, "{0:.%u", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format");
|
||||
SPrintf(format_str, "{0:.%u}", INT_MAX + 1u);
|
||||
safe_sprintf(format_str, "{0:.%u}", INT_MAX + 1u);
|
||||
EXPECT_THROW_MSG(format(format_str, 0),
|
||||
FormatError, "number is too big in format");
|
||||
|
||||
@ -994,8 +987,8 @@ TEST(FormatterTest, Precision) {
|
||||
|
||||
TEST(FormatterTest, RuntimePrecision) {
|
||||
char format_str[BUFFER_SIZE];
|
||||
SPrintf(format_str, "{0:.{%u", UINT_MAX);
|
||||
Increment(format_str + 4);
|
||||
safe_sprintf(format_str, "{0:.{%u", UINT_MAX);
|
||||
increment(format_str + 4);
|
||||
EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format");
|
||||
std::size_t size = std::strlen(format_str);
|
||||
format_str[size] = '}';
|
||||
@ -1085,18 +1078,18 @@ TEST(FormatterTest, RuntimePrecision) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void CheckUnknownTypes(
|
||||
void check_unknown_types(
|
||||
const T &value, const char *types, const char *type_name) {
|
||||
char format_str[BUFFER_SIZE], message[BUFFER_SIZE];
|
||||
const char *special = ".0123456789}";
|
||||
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
|
||||
char c = i;
|
||||
if (std::strchr(types, c) || std::strchr(special, c) || !c) continue;
|
||||
SPrintf(format_str, "{0:10%c}", c);
|
||||
safe_sprintf(format_str, "{0:10%c}", c);
|
||||
if (std::isprint(static_cast<unsigned char>(c)))
|
||||
SPrintf(message, "unknown format code '%c' for %s", c, type_name);
|
||||
safe_sprintf(message, "unknown format code '%c' for %s", c, type_name);
|
||||
else
|
||||
SPrintf(message, "unknown format code '\\x%02x' for %s", c, type_name);
|
||||
safe_sprintf(message, "unknown format code '\\x%02x' for %s", c, type_name);
|
||||
EXPECT_THROW_MSG(format(format_str, value), FormatError, message)
|
||||
<< format_str << " " << message;
|
||||
}
|
||||
@ -1116,7 +1109,7 @@ TEST(FormatterTest, FormatShort) {
|
||||
TEST(FormatterTest, FormatInt) {
|
||||
EXPECT_THROW_MSG(format("{0:v", 42),
|
||||
FormatError, "unmatched '{' in format");
|
||||
CheckUnknownTypes(42, "bBdoxX", "integer");
|
||||
check_unknown_types(42, "bBdoxX", "integer");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatBin) {
|
||||
@ -1140,17 +1133,17 @@ TEST(FormatterTest, FormatDec) {
|
||||
EXPECT_EQ("12345", format("{0}", 12345));
|
||||
EXPECT_EQ("67890", format("{0}", 67890));
|
||||
char buffer[BUFFER_SIZE];
|
||||
SPrintf(buffer, "%d", INT_MIN);
|
||||
safe_sprintf(buffer, "%d", INT_MIN);
|
||||
EXPECT_EQ(buffer, format("{0}", INT_MIN));
|
||||
SPrintf(buffer, "%d", INT_MAX);
|
||||
safe_sprintf(buffer, "%d", INT_MAX);
|
||||
EXPECT_EQ(buffer, format("{0}", INT_MAX));
|
||||
SPrintf(buffer, "%u", UINT_MAX);
|
||||
safe_sprintf(buffer, "%u", UINT_MAX);
|
||||
EXPECT_EQ(buffer, format("{0}", UINT_MAX));
|
||||
SPrintf(buffer, "%ld", 0 - static_cast<unsigned long>(LONG_MIN));
|
||||
safe_sprintf(buffer, "%ld", 0 - static_cast<unsigned long>(LONG_MIN));
|
||||
EXPECT_EQ(buffer, format("{0}", LONG_MIN));
|
||||
SPrintf(buffer, "%ld", LONG_MAX);
|
||||
safe_sprintf(buffer, "%ld", LONG_MAX);
|
||||
EXPECT_EQ(buffer, format("{0}", LONG_MAX));
|
||||
SPrintf(buffer, "%lu", ULONG_MAX);
|
||||
safe_sprintf(buffer, "%lu", ULONG_MAX);
|
||||
EXPECT_EQ(buffer, format("{0}", ULONG_MAX));
|
||||
}
|
||||
|
||||
@ -1165,17 +1158,17 @@ TEST(FormatterTest, FormatHex) {
|
||||
EXPECT_EQ("90ABCDEF", format("{0:X}", 0x90ABCDEF));
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
SPrintf(buffer, "-%x", 0 - static_cast<unsigned>(INT_MIN));
|
||||
safe_sprintf(buffer, "-%x", 0 - static_cast<unsigned>(INT_MIN));
|
||||
EXPECT_EQ(buffer, format("{0:x}", INT_MIN));
|
||||
SPrintf(buffer, "%x", INT_MAX);
|
||||
safe_sprintf(buffer, "%x", INT_MAX);
|
||||
EXPECT_EQ(buffer, format("{0:x}", INT_MAX));
|
||||
SPrintf(buffer, "%x", UINT_MAX);
|
||||
safe_sprintf(buffer, "%x", UINT_MAX);
|
||||
EXPECT_EQ(buffer, format("{0:x}", UINT_MAX));
|
||||
SPrintf(buffer, "-%lx", 0 - static_cast<unsigned long>(LONG_MIN));
|
||||
safe_sprintf(buffer, "-%lx", 0 - static_cast<unsigned long>(LONG_MIN));
|
||||
EXPECT_EQ(buffer, format("{0:x}", LONG_MIN));
|
||||
SPrintf(buffer, "%lx", LONG_MAX);
|
||||
safe_sprintf(buffer, "%lx", LONG_MAX);
|
||||
EXPECT_EQ(buffer, format("{0:x}", LONG_MAX));
|
||||
SPrintf(buffer, "%lx", ULONG_MAX);
|
||||
safe_sprintf(buffer, "%lx", ULONG_MAX);
|
||||
EXPECT_EQ(buffer, format("{0:x}", ULONG_MAX));
|
||||
}
|
||||
|
||||
@ -1186,17 +1179,17 @@ TEST(FormatterTest, FormatOct) {
|
||||
EXPECT_EQ("-42", format("{0:o}", -042));
|
||||
EXPECT_EQ("12345670", format("{0:o}", 012345670));
|
||||
char buffer[BUFFER_SIZE];
|
||||
SPrintf(buffer, "-%o", 0 - static_cast<unsigned>(INT_MIN));
|
||||
safe_sprintf(buffer, "-%o", 0 - static_cast<unsigned>(INT_MIN));
|
||||
EXPECT_EQ(buffer, format("{0:o}", INT_MIN));
|
||||
SPrintf(buffer, "%o", INT_MAX);
|
||||
safe_sprintf(buffer, "%o", INT_MAX);
|
||||
EXPECT_EQ(buffer, format("{0:o}", INT_MAX));
|
||||
SPrintf(buffer, "%o", UINT_MAX);
|
||||
safe_sprintf(buffer, "%o", UINT_MAX);
|
||||
EXPECT_EQ(buffer, format("{0:o}", UINT_MAX));
|
||||
SPrintf(buffer, "-%lo", 0 - static_cast<unsigned long>(LONG_MIN));
|
||||
safe_sprintf(buffer, "-%lo", 0 - static_cast<unsigned long>(LONG_MIN));
|
||||
EXPECT_EQ(buffer, format("{0:o}", LONG_MIN));
|
||||
SPrintf(buffer, "%lo", LONG_MAX);
|
||||
safe_sprintf(buffer, "%lo", LONG_MAX);
|
||||
EXPECT_EQ(buffer, format("{0:o}", LONG_MAX));
|
||||
SPrintf(buffer, "%lo", ULONG_MAX);
|
||||
safe_sprintf(buffer, "%lo", ULONG_MAX);
|
||||
EXPECT_EQ(buffer, format("{0:o}", ULONG_MAX));
|
||||
}
|
||||
|
||||
@ -1205,7 +1198,7 @@ TEST(FormatterTest, FormatFloat) {
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatDouble) {
|
||||
CheckUnknownTypes(1.2, "eEfFgGaA", "double");
|
||||
check_unknown_types(1.2, "eEfFgGaA", "double");
|
||||
EXPECT_EQ("0", format("{0:}", 0.0));
|
||||
EXPECT_EQ("0.000000", format("{0:f}", 0.0));
|
||||
EXPECT_EQ("392.65", format("{0:}", 392.65));
|
||||
@ -1214,14 +1207,14 @@ TEST(FormatterTest, FormatDouble) {
|
||||
EXPECT_EQ("392.650000", format("{0:f}", 392.65));
|
||||
EXPECT_EQ("392.650000", format("{0:F}", 392.65));
|
||||
char buffer[BUFFER_SIZE];
|
||||
SPrintf(buffer, "%e", 392.65);
|
||||
safe_sprintf(buffer, "%e", 392.65);
|
||||
EXPECT_EQ(buffer, format("{0:e}", 392.65));
|
||||
SPrintf(buffer, "%E", 392.65);
|
||||
safe_sprintf(buffer, "%E", 392.65);
|
||||
EXPECT_EQ(buffer, format("{0:E}", 392.65));
|
||||
EXPECT_EQ("+0000392.6", format("{0:+010.4g}", 392.65));
|
||||
SPrintf(buffer, "%a", -42.0);
|
||||
safe_sprintf(buffer, "%a", -42.0);
|
||||
EXPECT_EQ(buffer, format("{:a}", -42.0));
|
||||
SPrintf(buffer, "%A", -42.0);
|
||||
safe_sprintf(buffer, "%A", -42.0);
|
||||
EXPECT_EQ(buffer, format("{:A}", -42.0));
|
||||
}
|
||||
|
||||
@ -1261,15 +1254,15 @@ TEST(FormatterTest, FormatLongDouble) {
|
||||
EXPECT_EQ("392.650000", format("{0:f}", 392.65l));
|
||||
EXPECT_EQ("392.650000", format("{0:F}", 392.65l));
|
||||
char buffer[BUFFER_SIZE];
|
||||
SPrintf(buffer, "%Le", 392.65l);
|
||||
safe_sprintf(buffer, "%Le", 392.65l);
|
||||
EXPECT_EQ(buffer, format("{0:e}", 392.65l));
|
||||
SPrintf(buffer, "%LE", 392.65l);
|
||||
safe_sprintf(buffer, "%LE", 392.65l);
|
||||
EXPECT_EQ("+0000392.6", format("{0:+010.4g}", 392.65l));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatChar) {
|
||||
const char types[] = "cbBdoxX";
|
||||
CheckUnknownTypes('a', types, "char");
|
||||
check_unknown_types('a', types, "char");
|
||||
EXPECT_EQ("a", format("{0}", 'a'));
|
||||
EXPECT_EQ("z", format("{0:c}", 'z'));
|
||||
EXPECT_EQ(L"a", format(L"{0}", 'a'));
|
||||
@ -1288,7 +1281,7 @@ TEST(FormatterTest, FormatWChar) {
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatCString) {
|
||||
CheckUnknownTypes("test", "s", "string");
|
||||
check_unknown_types("test", "s", "string");
|
||||
EXPECT_EQ("test", format("{0}", "test"));
|
||||
EXPECT_EQ("test", format("{0:s}", "test"));
|
||||
char nonconst[] = "nonconst";
|
||||
@ -1298,7 +1291,7 @@ TEST(FormatterTest, FormatCString) {
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatPointer) {
|
||||
CheckUnknownTypes(reinterpret_cast<void*>(0x1234), "p", "pointer");
|
||||
check_unknown_types(reinterpret_cast<void*>(0x1234), "p", "pointer");
|
||||
EXPECT_EQ("0x0", format("{0}", reinterpret_cast<void*>(0)));
|
||||
EXPECT_EQ("0x1234", format("{0}", reinterpret_cast<void*>(0x1234)));
|
||||
EXPECT_EQ("0x1234", format("{0:p}", reinterpret_cast<void*>(0x1234)));
|
||||
@ -1319,7 +1312,7 @@ TEST(FormatterTest, FormatUsingIOStreams) {
|
||||
std::string s = format("The date is {0}", Date(2012, 12, 9));
|
||||
EXPECT_EQ("The date is 2012-12-9", s);
|
||||
Date date(2012, 12, 9);
|
||||
CheckUnknownTypes(date, "s", "string");
|
||||
check_unknown_types(date, "s", "string");
|
||||
}
|
||||
|
||||
class Answer {};
|
||||
@ -1401,7 +1394,7 @@ TEST(FormatterTest, Examples) {
|
||||
EXPECT_EQ("From 1 to 3", format("From {} to {}", 1, 3));
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
SPrintf(buffer, "%03.2f", -1.2);
|
||||
safe_sprintf(buffer, "%03.2f", -1.2);
|
||||
EXPECT_EQ(buffer, format("{:03.2f}", -1.2));
|
||||
|
||||
EXPECT_EQ("a, b, c", format("{0}, {1}, {2}", 'a', 'b', 'c'));
|
||||
@ -1519,7 +1512,7 @@ TEST(StrTest, Convert) {
|
||||
EXPECT_EQ("2012-12-9", s);
|
||||
}
|
||||
|
||||
std::string FormatMessage(int id, const char *format,
|
||||
std::string format_message(int id, const char *format,
|
||||
const fmt::ArgList &args) {
|
||||
fmt::Writer w;
|
||||
w.write("[{}] ", id);
|
||||
@ -1527,9 +1520,9 @@ std::string FormatMessage(int id, const char *format,
|
||||
return w.str();
|
||||
}
|
||||
|
||||
FMT_VARIADIC(std::string, FormatMessage, int, const char *)
|
||||
FMT_VARIADIC(std::string, format_message, int, const char *)
|
||||
|
||||
TEST(FormatTest, FormatMessageExample) {
|
||||
EXPECT_EQ("[42] something happened",
|
||||
FormatMessage(42, "{} happened", "something"));
|
||||
format_message(42, "{} happened", "something"));
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ class SuppressAssert {
|
||||
_invalid_parameter_handler original_handler_;
|
||||
int original_report_mode_;
|
||||
|
||||
static void InvalidParameterHandler(const wchar_t *,
|
||||
static void handle_invalid_parameter(const wchar_t *,
|
||||
const wchar_t *, const wchar_t *, unsigned , uintptr_t) {}
|
||||
|
||||
public:
|
||||
SuppressAssert()
|
||||
: original_handler_(_set_invalid_parameter_handler(InvalidParameterHandler)),
|
||||
: original_handler_(_set_invalid_parameter_handler(handle_invalid_parameter)),
|
||||
original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) {
|
||||
}
|
||||
~SuppressAssert() {
|
||||
@ -65,12 +65,12 @@ class SuppressAssert {
|
||||
|
||||
// Fix "secure" warning about using fopen without defining
|
||||
// _CRT_SECURE_NO_WARNINGS.
|
||||
FILE *OpenFile(const char *filename, const char *mode) {
|
||||
FILE *safe_fopen(const char *filename, const char *mode) {
|
||||
FILE *f = 0;
|
||||
errno = fopen_s(&f, filename, mode);
|
||||
return f;
|
||||
}
|
||||
#define fopen OpenFile
|
||||
#define fopen safe_fopen
|
||||
#else
|
||||
# define SUPPRESS_ASSERT(statement) statement
|
||||
using std::fopen;
|
||||
@ -100,13 +100,13 @@ const char* SingleEvaluationTest::p_;
|
||||
int SingleEvaluationTest::a_;
|
||||
int SingleEvaluationTest::b_;
|
||||
|
||||
void DoNothing() {}
|
||||
void do_nothing() {}
|
||||
|
||||
void ThrowException() {
|
||||
void throw_exception() {
|
||||
throw std::runtime_error("test");
|
||||
}
|
||||
|
||||
void ThrowSystemError() {
|
||||
void throw_system_error() {
|
||||
throw fmt::SystemError(EDOM, "test");
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ void ThrowSystemError() {
|
||||
// exactly once.
|
||||
TEST_F(SingleEvaluationTest, FailedEXPECT_THROW_MSG) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_THROW_MSG(ThrowException(), std::exception, p_++), "01234");
|
||||
EXPECT_THROW_MSG(throw_exception(), std::exception, p_++), "01234");
|
||||
EXPECT_EQ(s_ + 1, p_);
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ TEST_F(SingleEvaluationTest, FailedEXPECT_THROW_MSG) {
|
||||
// exactly once.
|
||||
TEST_F(SingleEvaluationTest, FailedEXPECT_SYSTEM_ERROR) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, p_++), "01234");
|
||||
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, p_++), "01234");
|
||||
EXPECT_EQ(s_ + 1, p_);
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@ TEST_F(SingleEvaluationTest, ExceptionTests) {
|
||||
// successful EXPECT_THROW_MSG
|
||||
EXPECT_THROW_MSG({ // NOLINT
|
||||
a_++;
|
||||
ThrowException();
|
||||
throw_exception();
|
||||
}, std::exception, (b_++, "test"));
|
||||
EXPECT_EQ(1, a_);
|
||||
EXPECT_EQ(1, b_);
|
||||
@ -147,7 +147,7 @@ TEST_F(SingleEvaluationTest, ExceptionTests) {
|
||||
// failed EXPECT_THROW_MSG, throws different type
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG({ // NOLINT
|
||||
a_++;
|
||||
ThrowException();
|
||||
throw_exception();
|
||||
}, std::logic_error, (b_++, "test")), "throws a different type");
|
||||
EXPECT_EQ(2, a_);
|
||||
EXPECT_EQ(2, b_);
|
||||
@ -155,7 +155,7 @@ TEST_F(SingleEvaluationTest, ExceptionTests) {
|
||||
// failed EXPECT_THROW_MSG, throws an exception with different message
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG({ // NOLINT
|
||||
a_++;
|
||||
ThrowException();
|
||||
throw_exception();
|
||||
}, std::exception, (b_++, "other")),
|
||||
"throws an exception with a different message");
|
||||
EXPECT_EQ(3, a_);
|
||||
@ -172,7 +172,7 @@ TEST_F(SingleEvaluationTest, SystemErrorTests) {
|
||||
// successful EXPECT_SYSTEM_ERROR
|
||||
EXPECT_SYSTEM_ERROR({ // NOLINT
|
||||
a_++;
|
||||
ThrowSystemError();
|
||||
throw_system_error();
|
||||
}, EDOM, (b_++, "test"));
|
||||
EXPECT_EQ(1, a_);
|
||||
EXPECT_EQ(1, b_);
|
||||
@ -180,7 +180,7 @@ TEST_F(SingleEvaluationTest, SystemErrorTests) {
|
||||
// failed EXPECT_SYSTEM_ERROR, throws different type
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR({ // NOLINT
|
||||
a_++;
|
||||
ThrowException();
|
||||
throw_exception();
|
||||
}, EDOM, (b_++, "test")), "throws a different type");
|
||||
EXPECT_EQ(2, a_);
|
||||
EXPECT_EQ(2, b_);
|
||||
@ -188,7 +188,7 @@ TEST_F(SingleEvaluationTest, SystemErrorTests) {
|
||||
// failed EXPECT_SYSTEM_ERROR, throws an exception with different message
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR({ // NOLINT
|
||||
a_++;
|
||||
ThrowSystemError();
|
||||
throw_system_error();
|
||||
}, EDOM, (b_++, "other")),
|
||||
"throws an exception with a different message");
|
||||
EXPECT_EQ(3, a_);
|
||||
@ -245,22 +245,22 @@ TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) {
|
||||
|
||||
TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) {
|
||||
if (::testing::internal::AlwaysFalse())
|
||||
EXPECT_THROW_MSG(DoNothing(), std::exception, "");
|
||||
EXPECT_THROW_MSG(do_nothing(), std::exception, "");
|
||||
|
||||
if (::testing::internal::AlwaysTrue())
|
||||
EXPECT_THROW_MSG(ThrowException(), std::exception, "test");
|
||||
EXPECT_THROW_MSG(throw_exception(), std::exception, "test");
|
||||
else
|
||||
DoNothing();
|
||||
do_nothing();
|
||||
}
|
||||
|
||||
TEST(AssertionSyntaxTest, SystemErrorAssertionBehavesLikeSingleStatement) {
|
||||
if (::testing::internal::AlwaysFalse())
|
||||
EXPECT_SYSTEM_ERROR(DoNothing(), EDOM, "");
|
||||
EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "");
|
||||
|
||||
if (::testing::internal::AlwaysTrue())
|
||||
EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "test");
|
||||
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test");
|
||||
else
|
||||
DoNothing();
|
||||
do_nothing();
|
||||
}
|
||||
|
||||
TEST(AssertionSyntaxTest, WriteAssertionBehavesLikeSingleStatement) {
|
||||
@ -270,42 +270,42 @@ TEST(AssertionSyntaxTest, WriteAssertionBehavesLikeSingleStatement) {
|
||||
if (::testing::internal::AlwaysTrue())
|
||||
EXPECT_WRITE(stdout, std::printf("x"), "x");
|
||||
else
|
||||
DoNothing();
|
||||
do_nothing();
|
||||
}
|
||||
|
||||
// Tests EXPECT_THROW_MSG.
|
||||
TEST(ExpectTest, EXPECT_THROW_MSG) {
|
||||
EXPECT_THROW_MSG(ThrowException(), std::exception, "test");
|
||||
EXPECT_THROW_MSG(throw_exception(), std::exception, "test");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_THROW_MSG(ThrowException(), std::logic_error, "test"),
|
||||
"Expected: ThrowException() throws an exception of "
|
||||
EXPECT_THROW_MSG(throw_exception(), std::logic_error, "test"),
|
||||
"Expected: throw_exception() throws an exception of "
|
||||
"type std::logic_error.\n Actual: it throws a different type.");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_THROW_MSG(DoNothing(), std::exception, "test"),
|
||||
EXPECT_THROW_MSG(do_nothing(), std::exception, "test"),
|
||||
"Expected: DoNothing() throws an exception of type std::exception.\n"
|
||||
" Actual: it throws nothing.");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_THROW_MSG(ThrowException(), std::exception, "other"),
|
||||
"ThrowException() throws an exception with a different message.\n"
|
||||
EXPECT_THROW_MSG(throw_exception(), std::exception, "other"),
|
||||
"throw_exception() throws an exception with a different message.\n"
|
||||
"Expected: other\n"
|
||||
" Actual: test");
|
||||
}
|
||||
|
||||
// Tests EXPECT_SYSTEM_ERROR.
|
||||
TEST(ExpectTest, EXPECT_SYSTEM_ERROR) {
|
||||
EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "test");
|
||||
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_SYSTEM_ERROR(ThrowException(), EDOM, "test"),
|
||||
"Expected: ThrowException() throws an exception of "
|
||||
EXPECT_SYSTEM_ERROR(throw_exception(), EDOM, "test"),
|
||||
"Expected: throw_exception() throws an exception of "
|
||||
"type fmt::SystemError.\n Actual: it throws a different type.");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_SYSTEM_ERROR(DoNothing(), EDOM, "test"),
|
||||
EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "test"),
|
||||
"Expected: DoNothing() throws an exception of type fmt::SystemError.\n"
|
||||
" Actual: it throws nothing.");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "other"),
|
||||
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other"),
|
||||
fmt::format(
|
||||
"ThrowSystemError() throws an exception with a different message.\n"
|
||||
"throw_system_error() throws an exception with a different message.\n"
|
||||
"Expected: {}\n"
|
||||
" Actual: {}",
|
||||
format_system_error(EDOM, "other"),
|
||||
@ -314,7 +314,7 @@ TEST(ExpectTest, EXPECT_SYSTEM_ERROR) {
|
||||
|
||||
// Tests EXPECT_WRITE.
|
||||
TEST(ExpectTest, EXPECT_WRITE) {
|
||||
EXPECT_WRITE(stdout, DoNothing(), "");
|
||||
EXPECT_WRITE(stdout, do_nothing(), "");
|
||||
EXPECT_WRITE(stdout, std::printf("test"), "test");
|
||||
EXPECT_WRITE(stderr, std::fprintf(stderr, "test"), "test");
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
@ -324,18 +324,18 @@ TEST(ExpectTest, EXPECT_WRITE) {
|
||||
}
|
||||
|
||||
TEST(StreamingAssertionsTest, EXPECT_THROW_MSG) {
|
||||
EXPECT_THROW_MSG(ThrowException(), std::exception, "test")
|
||||
EXPECT_THROW_MSG(throw_exception(), std::exception, "test")
|
||||
<< "unexpected failure";
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_THROW_MSG(ThrowException(), std::exception, "other")
|
||||
EXPECT_THROW_MSG(throw_exception(), std::exception, "other")
|
||||
<< "expected failure", "expected failure");
|
||||
}
|
||||
|
||||
TEST(StreamingAssertionsTest, EXPECT_SYSTEM_ERROR) {
|
||||
EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "test")
|
||||
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test")
|
||||
<< "unexpected failure";
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "other")
|
||||
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other")
|
||||
<< "expected failure", "expected failure");
|
||||
}
|
||||
|
||||
@ -360,12 +360,12 @@ using fmt::ErrorCode;
|
||||
using fmt::File;
|
||||
|
||||
// Checks if the file is open by reading one character from it.
|
||||
bool IsOpen(int fd) {
|
||||
bool isopen(int fd) {
|
||||
char buffer;
|
||||
return FMT_POSIX(read(fd, &buffer, 1)) == 1;
|
||||
}
|
||||
|
||||
bool IsClosed(int fd) {
|
||||
bool isclosed(int fd) {
|
||||
char buffer;
|
||||
std::streamsize result = 0;
|
||||
SUPPRESS_ASSERT(result = FMT_POSIX(read(fd, &buffer, 1)));
|
||||
@ -373,7 +373,7 @@ bool IsClosed(int fd) {
|
||||
}
|
||||
|
||||
// Attempts to read count characters from a file.
|
||||
std::string Read(File &f, std::size_t count) {
|
||||
std::string read(File &f, std::size_t count) {
|
||||
std::string buffer(count, '\0');
|
||||
std::streamsize n = 0;
|
||||
std::size_t offset = 0;
|
||||
@ -387,7 +387,7 @@ std::string Read(File &f, std::size_t count) {
|
||||
}
|
||||
|
||||
// Attempts to write a string to a file.
|
||||
void Write(File &f, fmt::StringRef s) {
|
||||
void write(File &f, fmt::StringRef s) {
|
||||
std::size_t num_chars_left = s.size();
|
||||
const char *ptr = s.c_str();
|
||||
do {
|
||||
@ -400,7 +400,7 @@ void Write(File &f, fmt::StringRef s) {
|
||||
}
|
||||
|
||||
#define EXPECT_READ(file, expected_content) \
|
||||
EXPECT_EQ(expected_content, Read(file, std::strlen(expected_content)))
|
||||
EXPECT_EQ(expected_content, read(file, std::strlen(expected_content)))
|
||||
|
||||
TEST(ErrorCodeTest, Ctor) {
|
||||
EXPECT_EQ(0, ErrorCode().get());
|
||||
@ -410,7 +410,7 @@ TEST(ErrorCodeTest, Ctor) {
|
||||
const char FILE_CONTENT[] = "Don't panic!";
|
||||
|
||||
// Opens a file for reading.
|
||||
File OpenFile() {
|
||||
File open_file() {
|
||||
File read_end, write_end;
|
||||
File::pipe(read_end, write_end);
|
||||
write_end.write(FILE_CONTENT, sizeof(FILE_CONTENT) - 1);
|
||||
@ -419,7 +419,7 @@ File OpenFile() {
|
||||
}
|
||||
|
||||
// Opens a buffered file for reading.
|
||||
BufferedFile OpenBufferedFile(FILE **fp = 0) {
|
||||
BufferedFile open_buffered_file(FILE **fp = 0) {
|
||||
File read_end, write_end;
|
||||
File::pipe(read_end, write_end);
|
||||
write_end.write(FILE_CONTENT, sizeof(FILE_CONTENT) - 1);
|
||||
@ -436,7 +436,7 @@ TEST(BufferedFileTest, DefaultCtor) {
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, MoveCtor) {
|
||||
BufferedFile bf = OpenBufferedFile();
|
||||
BufferedFile bf = open_buffered_file();
|
||||
FILE *fp = bf.get();
|
||||
EXPECT_TRUE(fp != 0);
|
||||
BufferedFile bf2(std::move(bf));
|
||||
@ -445,7 +445,7 @@ TEST(BufferedFileTest, MoveCtor) {
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, MoveAssignment) {
|
||||
BufferedFile bf = OpenBufferedFile();
|
||||
BufferedFile bf = open_buffered_file();
|
||||
FILE *fp = bf.get();
|
||||
EXPECT_TRUE(fp != 0);
|
||||
BufferedFile bf2;
|
||||
@ -455,44 +455,44 @@ TEST(BufferedFileTest, MoveAssignment) {
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, MoveAssignmentClosesFile) {
|
||||
BufferedFile bf = OpenBufferedFile();
|
||||
BufferedFile bf2 = OpenBufferedFile();
|
||||
BufferedFile bf = open_buffered_file();
|
||||
BufferedFile bf2 = open_buffered_file();
|
||||
int old_fd = bf2.fileno();
|
||||
bf2 = std::move(bf);
|
||||
EXPECT_TRUE(IsClosed(old_fd));
|
||||
EXPECT_TRUE(isclosed(old_fd));
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, MoveFromTemporaryInCtor) {
|
||||
FILE *fp = 0;
|
||||
BufferedFile f(OpenBufferedFile(&fp));
|
||||
BufferedFile f(open_buffered_file(&fp));
|
||||
EXPECT_EQ(fp, f.get());
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, MoveFromTemporaryInAssignment) {
|
||||
FILE *fp = 0;
|
||||
BufferedFile f;
|
||||
f = OpenBufferedFile(&fp);
|
||||
f = open_buffered_file(&fp);
|
||||
EXPECT_EQ(fp, f.get());
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, MoveFromTemporaryInAssignmentClosesFile) {
|
||||
BufferedFile f = OpenBufferedFile();
|
||||
BufferedFile f = open_buffered_file();
|
||||
int old_fd = f.fileno();
|
||||
f = OpenBufferedFile();
|
||||
EXPECT_TRUE(IsClosed(old_fd));
|
||||
f = open_buffered_file();
|
||||
EXPECT_TRUE(isclosed(old_fd));
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, CloseFileInDtor) {
|
||||
int fd = 0;
|
||||
{
|
||||
BufferedFile f = OpenBufferedFile();
|
||||
BufferedFile f = open_buffered_file();
|
||||
fd = f.fileno();
|
||||
}
|
||||
EXPECT_TRUE(IsClosed(fd));
|
||||
EXPECT_TRUE(isclosed(fd));
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, CloseErrorInDtor) {
|
||||
BufferedFile *f = new BufferedFile(OpenBufferedFile());
|
||||
BufferedFile *f = new BufferedFile(open_buffered_file());
|
||||
EXPECT_WRITE(stderr, {
|
||||
// The close function must be called inside EXPECT_WRITE, otherwise
|
||||
// the system may recycle closed file descriptor when redirecting the
|
||||
@ -504,15 +504,15 @@ TEST(BufferedFileTest, CloseErrorInDtor) {
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, Close) {
|
||||
BufferedFile f = OpenBufferedFile();
|
||||
BufferedFile f = open_buffered_file();
|
||||
int fd = f.fileno();
|
||||
f.close();
|
||||
EXPECT_TRUE(f.get() == 0);
|
||||
EXPECT_TRUE(IsClosed(fd));
|
||||
EXPECT_TRUE(isclosed(fd));
|
||||
}
|
||||
|
||||
TEST(BufferedFileTest, CloseError) {
|
||||
BufferedFile f = OpenBufferedFile();
|
||||
BufferedFile f = open_buffered_file();
|
||||
FMT_POSIX(close(f.fileno()));
|
||||
EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
|
||||
EXPECT_TRUE(f.get() == 0);
|
||||
@ -528,7 +528,7 @@ TEST(BufferedFileTest, Fileno) {
|
||||
std::exit(1);
|
||||
}
|
||||
}, "");
|
||||
f = OpenBufferedFile();
|
||||
f = open_buffered_file();
|
||||
EXPECT_TRUE(f.fileno() != -1);
|
||||
File copy = File::dup(f.fileno());
|
||||
EXPECT_READ(copy, FILE_CONTENT);
|
||||
@ -544,7 +544,7 @@ TEST(FileTest, OpenBufferedFileInCtor) {
|
||||
std::fputs(FILE_CONTENT, fp);
|
||||
std::fclose(fp);
|
||||
File f("test-file", File::RDONLY);
|
||||
ASSERT_TRUE(IsOpen(f.descriptor()));
|
||||
ASSERT_TRUE(isopen(f.descriptor()));
|
||||
}
|
||||
|
||||
TEST(FileTest, OpenBufferedFileError) {
|
||||
@ -553,7 +553,7 @@ TEST(FileTest, OpenBufferedFileError) {
|
||||
}
|
||||
|
||||
TEST(FileTest, MoveCtor) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
int fd = f.descriptor();
|
||||
EXPECT_NE(-1, fd);
|
||||
File f2(std::move(f));
|
||||
@ -562,7 +562,7 @@ TEST(FileTest, MoveCtor) {
|
||||
}
|
||||
|
||||
TEST(FileTest, MoveAssignment) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
int fd = f.descriptor();
|
||||
EXPECT_NE(-1, fd);
|
||||
File f2;
|
||||
@ -572,15 +572,15 @@ TEST(FileTest, MoveAssignment) {
|
||||
}
|
||||
|
||||
TEST(FileTest, MoveAssignmentClosesFile) {
|
||||
File f = OpenFile();
|
||||
File f2 = OpenFile();
|
||||
File f = open_file();
|
||||
File f2 = open_file();
|
||||
int old_fd = f2.descriptor();
|
||||
f2 = std::move(f);
|
||||
EXPECT_TRUE(IsClosed(old_fd));
|
||||
EXPECT_TRUE(isclosed(old_fd));
|
||||
}
|
||||
|
||||
File OpenBufferedFile(int &fd) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
fd = f.descriptor();
|
||||
return std::move(f);
|
||||
}
|
||||
@ -600,23 +600,23 @@ TEST(FileTest, MoveFromTemporaryInAssignment) {
|
||||
|
||||
TEST(FileTest, MoveFromTemporaryInAssignmentClosesFile) {
|
||||
int fd = 0xdeadbeef;
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
int old_fd = f.descriptor();
|
||||
f = OpenBufferedFile(fd);
|
||||
EXPECT_TRUE(IsClosed(old_fd));
|
||||
EXPECT_TRUE(isclosed(old_fd));
|
||||
}
|
||||
|
||||
TEST(FileTest, CloseFileInDtor) {
|
||||
int fd = 0;
|
||||
{
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
fd = f.descriptor();
|
||||
}
|
||||
EXPECT_TRUE(IsClosed(fd));
|
||||
EXPECT_TRUE(isclosed(fd));
|
||||
}
|
||||
|
||||
TEST(FileTest, CloseErrorInDtor) {
|
||||
File *f = new File(OpenFile());
|
||||
File *f = new File(open_file());
|
||||
EXPECT_WRITE(stderr, {
|
||||
// The close function must be called inside EXPECT_WRITE, otherwise
|
||||
// the system may recycle closed file descriptor when redirecting the
|
||||
@ -628,22 +628,22 @@ TEST(FileTest, CloseErrorInDtor) {
|
||||
}
|
||||
|
||||
TEST(FileTest, Close) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
int fd = f.descriptor();
|
||||
f.close();
|
||||
EXPECT_EQ(-1, f.descriptor());
|
||||
EXPECT_TRUE(IsClosed(fd));
|
||||
EXPECT_TRUE(isclosed(fd));
|
||||
}
|
||||
|
||||
TEST(FileTest, CloseError) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
FMT_POSIX(close(f.descriptor()));
|
||||
EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
|
||||
EXPECT_EQ(-1, f.descriptor());
|
||||
}
|
||||
|
||||
TEST(FileTest, Read) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
EXPECT_READ(f, FILE_CONTENT);
|
||||
}
|
||||
|
||||
@ -658,7 +658,7 @@ TEST(FileTest, ReadError) {
|
||||
TEST(FileTest, Write) {
|
||||
File read_end, write_end;
|
||||
File::pipe(read_end, write_end);
|
||||
Write(write_end, "test");
|
||||
write(write_end, "test");
|
||||
write_end.close();
|
||||
EXPECT_READ(read_end, "test");
|
||||
}
|
||||
@ -671,10 +671,10 @@ TEST(FileTest, WriteError) {
|
||||
}
|
||||
|
||||
TEST(FileTest, Dup) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
File copy = File::dup(f.descriptor());
|
||||
EXPECT_NE(f.descriptor(), copy.descriptor());
|
||||
EXPECT_EQ(FILE_CONTENT, Read(copy, sizeof(FILE_CONTENT) - 1));
|
||||
EXPECT_EQ(FILE_CONTENT, read(copy, sizeof(FILE_CONTENT) - 1));
|
||||
}
|
||||
|
||||
TEST(FileTest, DupError) {
|
||||
@ -683,22 +683,22 @@ TEST(FileTest, DupError) {
|
||||
}
|
||||
|
||||
TEST(FileTest, Dup2) {
|
||||
File f = OpenFile();
|
||||
File copy = OpenFile();
|
||||
File f = open_file();
|
||||
File copy = open_file();
|
||||
f.dup2(copy.descriptor());
|
||||
EXPECT_NE(f.descriptor(), copy.descriptor());
|
||||
EXPECT_READ(copy, FILE_CONTENT);
|
||||
}
|
||||
|
||||
TEST(FileTest, Dup2Error) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
EXPECT_SYSTEM_ERROR_NOASSERT(f.dup2(-1), EBADF,
|
||||
fmt::format("cannot duplicate file descriptor {} to -1", f.descriptor()));
|
||||
}
|
||||
|
||||
TEST(FileTest, Dup2NoExcept) {
|
||||
File f = OpenFile();
|
||||
File copy = OpenFile();
|
||||
File f = open_file();
|
||||
File copy = open_file();
|
||||
ErrorCode ec;
|
||||
f.dup2(copy.descriptor(), ec);
|
||||
EXPECT_EQ(0, ec.get());
|
||||
@ -707,7 +707,7 @@ TEST(FileTest, Dup2NoExcept) {
|
||||
}
|
||||
|
||||
TEST(FileTest, Dup2NoExceptError) {
|
||||
File f = OpenFile();
|
||||
File f = open_file();
|
||||
ErrorCode ec;
|
||||
SUPPRESS_ASSERT(f.dup2(-1, ec));
|
||||
EXPECT_EQ(EBADF, ec.get());
|
||||
@ -718,7 +718,7 @@ TEST(FileTest, Pipe) {
|
||||
File::pipe(read_end, write_end);
|
||||
EXPECT_NE(-1, read_end.descriptor());
|
||||
EXPECT_NE(-1, write_end.descriptor());
|
||||
Write(write_end, "test");
|
||||
write(write_end, "test");
|
||||
EXPECT_READ(read_end, "test");
|
||||
}
|
||||
|
||||
@ -768,7 +768,7 @@ TEST(OutputRedirectTest, FlushErrorInCtor) {
|
||||
}
|
||||
|
||||
TEST(OutputRedirectTest, DupErrorInCtor) {
|
||||
BufferedFile f = OpenBufferedFile();
|
||||
BufferedFile f = open_buffered_file();
|
||||
int fd = f.fileno();
|
||||
File copy = File::dup(fd);
|
||||
FMT_POSIX(close(fd));
|
||||
@ -786,8 +786,8 @@ TEST(OutputRedirectTest, RestoreAndRead) {
|
||||
std::fprintf(file.get(), "[[[");
|
||||
OutputRedirect redir(file.get());
|
||||
std::fprintf(file.get(), "censored");
|
||||
EXPECT_EQ("censored", redir.RestoreAndRead());
|
||||
EXPECT_EQ("", redir.RestoreAndRead());
|
||||
EXPECT_EQ("censored", redir.restore_and_read());
|
||||
EXPECT_EQ("", redir.restore_and_read());
|
||||
std::fprintf(file.get(), "]]]");
|
||||
file = BufferedFile();
|
||||
EXPECT_READ(read_end, "[[[]]]");
|
||||
@ -804,7 +804,7 @@ TEST(OutputRedirectTest, FlushErrorInRestoreAndRead) {
|
||||
// Put a character in a file buffer.
|
||||
EXPECT_EQ('x', fputc('x', f.get()));
|
||||
FMT_POSIX(close(write_fd));
|
||||
EXPECT_SYSTEM_ERROR_NOASSERT(redir.RestoreAndRead(),
|
||||
EXPECT_SYSTEM_ERROR_NOASSERT(redir.restore_and_read(),
|
||||
EBADF, "cannot flush stream");
|
||||
write_copy.dup2(write_fd); // "undo" close or dtor will fail
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
using fmt::File;
|
||||
|
||||
void OutputRedirect::Flush() {
|
||||
void OutputRedirect::flush() {
|
||||
#if EOF != -1
|
||||
# error "FMT_RETRY assumes return value of -1 indicating failure"
|
||||
#endif
|
||||
@ -41,17 +41,17 @@ void OutputRedirect::Flush() {
|
||||
throw fmt::SystemError(errno, "cannot flush stream");
|
||||
}
|
||||
|
||||
void OutputRedirect::Restore() {
|
||||
void OutputRedirect::restore() {
|
||||
if (original_.descriptor() == -1)
|
||||
return; // Already restored.
|
||||
Flush();
|
||||
flush();
|
||||
// Restore the original file.
|
||||
original_.dup2(FMT_POSIX(fileno(file_)));
|
||||
original_.close();
|
||||
}
|
||||
|
||||
OutputRedirect::OutputRedirect(FILE *file) : file_(file) {
|
||||
Flush();
|
||||
flush();
|
||||
int fd = FMT_POSIX(fileno(file));
|
||||
// Create a File object referring to the original file.
|
||||
original_ = File::dup(fd);
|
||||
@ -64,15 +64,15 @@ OutputRedirect::OutputRedirect(FILE *file) : file_(file) {
|
||||
|
||||
OutputRedirect::~OutputRedirect() FMT_NOEXCEPT(true) {
|
||||
try {
|
||||
Restore();
|
||||
restore();
|
||||
} catch (const std::exception &e) {
|
||||
std::fputs(e.what(), stderr);
|
||||
}
|
||||
}
|
||||
|
||||
std::string OutputRedirect::RestoreAndRead() {
|
||||
std::string OutputRedirect::restore_and_read() {
|
||||
// Restore output.
|
||||
Restore();
|
||||
restore();
|
||||
|
||||
// Read everything from the pipe.
|
||||
std::string content;
|
||||
|
@ -99,8 +99,8 @@ class OutputRedirect {
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(OutputRedirect);
|
||||
|
||||
void Flush();
|
||||
void Restore();
|
||||
void flush();
|
||||
void restore();
|
||||
|
||||
public:
|
||||
explicit OutputRedirect(FILE *file);
|
||||
@ -108,7 +108,7 @@ class OutputRedirect {
|
||||
|
||||
// Restores the original file, reads output from the pipe into a string
|
||||
// and returns it.
|
||||
std::string RestoreAndRead();
|
||||
std::string restore_and_read();
|
||||
};
|
||||
|
||||
#define FMT_TEST_WRITE_(statement, expected_output, file, fail) \
|
||||
@ -117,7 +117,7 @@ class OutputRedirect {
|
||||
std::string gtest_expected_output = expected_output; \
|
||||
OutputRedirect gtest_redir(file); \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
std::string gtest_output = gtest_redir.RestoreAndRead(); \
|
||||
std::string gtest_output = gtest_redir.restore_and_read(); \
|
||||
if (gtest_output != gtest_expected_output) { \
|
||||
gtest_ar \
|
||||
<< #statement " produces different output.\n" \
|
||||
|
@ -71,23 +71,23 @@ int result;
|
||||
result += args[i].int_value; \
|
||||
}
|
||||
|
||||
MAKE_TEST(TestFunc)
|
||||
MAKE_TEST(test_func)
|
||||
|
||||
typedef char Char;
|
||||
FMT_WRAP1(TestFunc, const char *, 1)
|
||||
FMT_WRAP1(test_func, const char *, 1)
|
||||
|
||||
TEST(UtilTest, Wrap1) {
|
||||
result = 0;
|
||||
TestFunc("", 42);
|
||||
test_func("", 42);
|
||||
EXPECT_EQ(42, result);
|
||||
}
|
||||
|
||||
MAKE_TEST(TestVariadicVoid)
|
||||
FMT_VARIADIC_VOID(TestVariadicVoid, const char *)
|
||||
MAKE_TEST(test_variadic_void)
|
||||
FMT_VARIADIC_VOID(test_variadic_void, const char *)
|
||||
|
||||
TEST(UtilTest, VariadicVoid) {
|
||||
result = 0;
|
||||
TestVariadicVoid("", 10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
|
||||
test_variadic_void("", 10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
|
||||
EXPECT_EQ(550, result);
|
||||
}
|
||||
|
||||
@ -96,18 +96,18 @@ struct S {};
|
||||
|
||||
#define GET_TYPE(n) S<n>
|
||||
|
||||
int TestVariadic(FMT_GEN(10, GET_TYPE), const fmt::ArgList &args) { \
|
||||
int test_variadic(FMT_GEN(10, GET_TYPE), const fmt::ArgList &args) { \
|
||||
int result = 0; \
|
||||
for (std::size_t i = 0, n = args.size(); i < n; ++i) \
|
||||
result += args[i].int_value; \
|
||||
return result;
|
||||
}
|
||||
FMT_VARIADIC(int, TestVariadic,
|
||||
FMT_VARIADIC(int, test_variadic,
|
||||
S<0>, S<1>, S<2>, S<3>, S<4>, S<5>, S<6>, S<7>, S<8>, S<9>)
|
||||
|
||||
#define MAKE_ARG(n) S<n>()
|
||||
|
||||
TEST(UtilTest, Variadic) {
|
||||
EXPECT_EQ(550, TestVariadic(FMT_GEN(10, MAKE_ARG),
|
||||
EXPECT_EQ(550, test_variadic(FMT_GEN(10, MAKE_ARG),
|
||||
10, 20, 30, 40, 50, 60, 70, 80, 90, 100));
|
||||
}
|
||||
|
@ -35,18 +35,10 @@
|
||||
using fmt::format;
|
||||
using fmt::FormatError;
|
||||
|
||||
// Returns a number UINT_MAX + 1 formatted as a string.
|
||||
std::string GetBigNumber() {
|
||||
char format[BUFFER_SIZE];
|
||||
SPrintf(format, "%u", UINT_MAX);
|
||||
Increment(format + 1);
|
||||
return format;
|
||||
}
|
||||
|
||||
const unsigned BIG_NUM = INT_MAX + 1u;
|
||||
|
||||
// Makes format string argument positional.
|
||||
std::string MakePositional(fmt::StringRef format) {
|
||||
std::string make_positional(fmt::StringRef format) {
|
||||
std::string s(format);
|
||||
s.replace(s.find('%'), 1, "%1$");
|
||||
return s;
|
||||
@ -54,7 +46,7 @@ std::string MakePositional(fmt::StringRef format) {
|
||||
|
||||
#define EXPECT_PRINTF(expected_output, format, arg) \
|
||||
EXPECT_EQ(expected_output, fmt::sprintf(format, arg)); \
|
||||
EXPECT_EQ(expected_output, fmt::sprintf(MakePositional(format), arg))
|
||||
EXPECT_EQ(expected_output, fmt::sprintf(make_positional(format), arg))
|
||||
|
||||
TEST(PrintfTest, NoArgs) {
|
||||
EXPECT_EQ("test", fmt::sprintf("test"));
|
||||
@ -187,17 +179,17 @@ TEST(PrintfTest, HashFlag) {
|
||||
EXPECT_PRINTF("-42.000000", "%#F", -42.0);
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
SPrintf(buffer, "%#e", -42.0);
|
||||
safe_sprintf(buffer, "%#e", -42.0);
|
||||
EXPECT_PRINTF(buffer, "%#e", -42.0);
|
||||
SPrintf(buffer, "%#E", -42.0);
|
||||
safe_sprintf(buffer, "%#E", -42.0);
|
||||
EXPECT_PRINTF(buffer, "%#E", -42.0);
|
||||
|
||||
EXPECT_PRINTF("-42.0000", "%#g", -42.0);
|
||||
EXPECT_PRINTF("-42.0000", "%#G", -42.0);
|
||||
|
||||
SPrintf(buffer, "%#a", 16.0);
|
||||
safe_sprintf(buffer, "%#a", 16.0);
|
||||
EXPECT_PRINTF(buffer, "%#a", 16.0);
|
||||
SPrintf(buffer, "%#A", 16.0);
|
||||
safe_sprintf(buffer, "%#A", 16.0);
|
||||
EXPECT_PRINTF(buffer, "%#A", 16.0);
|
||||
|
||||
// '#' flag is ignored for non-numeric types.
|
||||
@ -251,12 +243,12 @@ TEST(PrintfTest, IntPrecision) {
|
||||
|
||||
TEST(PrintfTest, FloatPrecision) {
|
||||
char buffer[BUFFER_SIZE];
|
||||
SPrintf(buffer, "%.3e", 1234.5678);
|
||||
safe_sprintf(buffer, "%.3e", 1234.5678);
|
||||
EXPECT_PRINTF(buffer, "%.3e", 1234.5678);
|
||||
EXPECT_PRINTF("1234.568", "%.3f", 1234.5678);
|
||||
SPrintf(buffer, "%.3g", 1234.5678);
|
||||
safe_sprintf(buffer, "%.3g", 1234.5678);
|
||||
EXPECT_PRINTF(buffer, "%.3g", 1234.5678);
|
||||
SPrintf(buffer, "%.3a", 1234.5678);
|
||||
safe_sprintf(buffer, "%.3a", 1234.5678);
|
||||
EXPECT_PRINTF(buffer, "%.3a", 1234.5678);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ using fmt::internal::Arg;
|
||||
using fmt::internal::MakeArg;
|
||||
|
||||
namespace {
|
||||
std::string GetSystemErrorMessage(int error_code) {
|
||||
std::string get_system_error(int error_code) {
|
||||
#if defined(__MINGW32__) || !defined(_WIN32)
|
||||
return strerror(error_code);
|
||||
#else
|
||||
@ -64,19 +64,19 @@ template <typename Char>
|
||||
std::basic_ostream<Char> &operator<<(std::basic_ostream<Char> &os, Test) {
|
||||
return os << "test";
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(UtilTest, Increment) {
|
||||
char s[10] = "123";
|
||||
Increment(s);
|
||||
increment(s);
|
||||
EXPECT_STREQ("124", s);
|
||||
s[2] = '8';
|
||||
Increment(s);
|
||||
increment(s);
|
||||
EXPECT_STREQ("129", s);
|
||||
Increment(s);
|
||||
increment(s);
|
||||
EXPECT_STREQ("130", s);
|
||||
s[1] = s[2] = '9';
|
||||
Increment(s);
|
||||
increment(s);
|
||||
EXPECT_STREQ("200", s);
|
||||
}
|
||||
|
||||
@ -355,7 +355,7 @@ TEST(ArgVisitorTest, VisitInvalidArg) {
|
||||
|
||||
// Tests fmt::internal::count_digits for integer type Int.
|
||||
template <typename Int>
|
||||
void TestCountDigits(Int) {
|
||||
void test_count_digits() {
|
||||
for (Int i = 0; i < 10; ++i)
|
||||
EXPECT_EQ(1u, fmt::internal::count_digits(i));
|
||||
for (Int i = 1, n = 1,
|
||||
@ -367,8 +367,8 @@ void TestCountDigits(Int) {
|
||||
}
|
||||
|
||||
TEST(UtilTest, CountDigits) {
|
||||
TestCountDigits(uint32_t());
|
||||
TestCountDigits(uint64_t());
|
||||
test_count_digits<uint32_t>();
|
||||
test_count_digits<uint64_t>();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -387,7 +387,7 @@ TEST(UtilTest, UTF8ToUTF16) {
|
||||
}
|
||||
|
||||
template <typename Converter>
|
||||
void CheckUTFConversionError(const char *message) {
|
||||
void check_utf_conversion_error(const char *message) {
|
||||
fmt::Writer out;
|
||||
fmt::internal::format_windows_error(out, ERROR_INVALID_PARAMETER, message);
|
||||
fmt::SystemError error(0, "");
|
||||
@ -401,12 +401,12 @@ void CheckUTFConversionError(const char *message) {
|
||||
}
|
||||
|
||||
TEST(UtilTest, UTF16ToUTF8Error) {
|
||||
CheckUTFConversionError<fmt::internal::UTF16ToUTF8>(
|
||||
check_utf_conversion_error<fmt::internal::UTF16ToUTF8>(
|
||||
"cannot convert string from UTF-16 to UTF-8");
|
||||
}
|
||||
|
||||
TEST(UtilTest, UTF8ToUTF16Error) {
|
||||
CheckUTFConversionError<fmt::internal::UTF8ToUTF16>(
|
||||
check_utf_conversion_error<fmt::internal::UTF8ToUTF16>(
|
||||
"cannot convert string from UTF-8 to UTF-16");
|
||||
}
|
||||
|
||||
@ -437,7 +437,7 @@ TEST(UtilTest, StrError) {
|
||||
EXPECT_EQ(0, result);
|
||||
std::size_t message_size = std::strlen(message);
|
||||
EXPECT_GE(BUFFER_SIZE - 1u, message_size);
|
||||
EXPECT_EQ(GetSystemErrorMessage(error_code), message);
|
||||
EXPECT_EQ(get_system_error(error_code), message);
|
||||
|
||||
// safe_strerror never uses buffer on MinGW.
|
||||
#ifndef __MINGW32__
|
||||
@ -454,7 +454,7 @@ typedef void (*FormatErrorMessage)(
|
||||
fmt::Writer &out, int error_code, StringRef message);
|
||||
|
||||
template <typename Error>
|
||||
void CheckThrowError(int error_code, FormatErrorMessage format) {
|
||||
void check_throw_error(int error_code, FormatErrorMessage format) {
|
||||
fmt::SystemError error(0, "");
|
||||
try {
|
||||
throw Error(error_code, "test {}", "error");
|
||||
@ -471,14 +471,14 @@ TEST(UtilTest, FormatSystemError) {
|
||||
fmt::Writer message;
|
||||
fmt::internal::format_system_error(message, EDOM, "test");
|
||||
EXPECT_EQ(fmt::format("test: {}",
|
||||
GetSystemErrorMessage(EDOM)), message.str());
|
||||
get_system_error(EDOM)), message.str());
|
||||
}
|
||||
|
||||
TEST(UtilTest, SystemError) {
|
||||
fmt::SystemError e(EDOM, "test");
|
||||
EXPECT_EQ(fmt::format("test: {}", GetSystemErrorMessage(EDOM)), e.what());
|
||||
EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), e.what());
|
||||
EXPECT_EQ(EDOM, e.error_code());
|
||||
CheckThrowError<fmt::SystemError>(EDOM, fmt::internal::format_system_error);
|
||||
check_throw_error<fmt::SystemError>(EDOM, fmt::internal::format_system_error);
|
||||
}
|
||||
|
||||
TEST(UtilTest, ReportSystemError) {
|
||||
@ -506,7 +506,7 @@ TEST(UtilTest, FormatWindowsError) {
|
||||
}
|
||||
|
||||
TEST(UtilTest, WindowsError) {
|
||||
CheckThrowError<fmt::WindowsError>(
|
||||
check_throw_error<fmt::WindowsError>(
|
||||
ERROR_FILE_EXISTS, fmt::internal::format_windows_error);
|
||||
}
|
||||
|
||||
|
15
test/util.cc
15
test/util.cc
@ -26,22 +26,9 @@
|
||||
*/
|
||||
|
||||
#include "util.h"
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define vsnprintf vsprintf_s
|
||||
#endif
|
||||
|
||||
void SPrintf(char *buffer, const char *format, ...) {
|
||||
std::va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(buffer, BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Increment(char *s) {
|
||||
void increment(char *s) {
|
||||
for (int i = static_cast<int>(std::strlen(s)) - 1; i >= 0; --i) {
|
||||
if (s[i] != '9') {
|
||||
++s[i];
|
||||
|
19
test/util.h
19
test/util.h
@ -25,9 +25,24 @@
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
enum {BUFFER_SIZE = 256};
|
||||
|
||||
void SPrintf(char *buffer, const char *format, ...);
|
||||
#ifdef _MSC_VER
|
||||
# define FMT_VSNPRINTF vsprintf_s
|
||||
#else
|
||||
# define FMT_VSNPRINTF vsnprintf
|
||||
#endif
|
||||
|
||||
template <std::size_t SIZE>
|
||||
void safe_sprintf(char (&buffer)[SIZE], const char *format, ...) {
|
||||
std::va_list args;
|
||||
va_start(args, format);
|
||||
FMT_VSNPRINTF(buffer, SIZE, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// Increment a number in a string.
|
||||
void Increment(char *s);
|
||||
void increment(char *s);
|
||||
|
Loading…
Reference in New Issue
Block a user