Merge branch 'master' into update-project-layout
Conflicts: posix.h
This commit is contained in:
commit
3133925ab2
@ -335,7 +335,10 @@ class File {
|
|||||||
long getpagesize();
|
long getpagesize();
|
||||||
|
|
||||||
#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER)
|
#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER)
|
||||||
|
# define FMT_LOCALE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FMT_LOCALE
|
||||||
// A "C" numeric locale.
|
// A "C" numeric locale.
|
||||||
class Locale {
|
class Locale {
|
||||||
private:
|
private:
|
||||||
@ -362,13 +365,15 @@ class Locale {
|
|||||||
FMT_DISALLOW_COPY_AND_ASSIGN(Locale);
|
FMT_DISALLOW_COPY_AND_ASSIGN(Locale);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef locale_t Type;
|
||||||
|
|
||||||
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
|
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
|
||||||
if (!locale_)
|
if (!locale_)
|
||||||
throw fmt::SystemError(errno, "cannot create locale");
|
throw fmt::SystemError(errno, "cannot create locale");
|
||||||
}
|
}
|
||||||
~Locale() { freelocale(locale_); }
|
~Locale() { freelocale(locale_); }
|
||||||
|
|
||||||
locale_t get() const { return locale_; }
|
Type get() const { return locale_; }
|
||||||
|
|
||||||
// Converts string to floating-point number and advances str past the end
|
// Converts string to floating-point number and advances str past the end
|
||||||
// of the parsed input.
|
// of the parsed input.
|
||||||
@ -379,8 +384,7 @@ class Locale {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif // FMT_LOCALE
|
||||||
#endif // LC_NUMERIC
|
|
||||||
} // namespace fmt
|
} // namespace fmt
|
||||||
|
|
||||||
#if !FMT_USE_RVALUE_REFERENCES
|
#if !FMT_USE_RVALUE_REFERENCES
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
# undef ERROR
|
# undef ERROR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@ -49,6 +50,9 @@ using fmt::ErrorCode;
|
|||||||
using fmt::File;
|
using fmt::File;
|
||||||
|
|
||||||
using testing::internal::scoped_ptr;
|
using testing::internal::scoped_ptr;
|
||||||
|
using testing::_;
|
||||||
|
using testing::StrEq;
|
||||||
|
using testing::Return;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int open_count;
|
int open_count;
|
||||||
@ -449,3 +453,108 @@ TEST(BufferedFileTest, FilenoNoRetry) {
|
|||||||
EXPECT_EQ(2, fileno_count);
|
EXPECT_EQ(2, fileno_count);
|
||||||
fileno_count = 0;
|
fileno_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Mock>
|
||||||
|
struct ScopedMock : testing::StrictMock<Mock> {
|
||||||
|
private:
|
||||||
|
Mock *&global_mock_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ScopedMock(Mock *&global_mock) : global_mock_(global_mock) {
|
||||||
|
global_mock = this;
|
||||||
|
}
|
||||||
|
~ScopedMock() { global_mock_ = 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TestMock {};
|
||||||
|
|
||||||
|
TEST(ScopedMock, Scope) {
|
||||||
|
TestMock *global_mock = 0;
|
||||||
|
{
|
||||||
|
ScopedMock<TestMock> mock(global_mock);
|
||||||
|
EXPECT_EQ(&mock, global_mock);
|
||||||
|
TestMock © = mock;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(0, global_mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FMT_LOCALE
|
||||||
|
|
||||||
|
typedef fmt::Locale::Type LocaleType;
|
||||||
|
|
||||||
|
struct LocaleMock {
|
||||||
|
MOCK_METHOD3(newlocale, LocaleType (int category_mask, const char *locale,
|
||||||
|
LocaleType base));
|
||||||
|
MOCK_METHOD1(freelocale, void (LocaleType locale));
|
||||||
|
|
||||||
|
MOCK_METHOD3(strtod_l, double (const char *nptr, char **endptr,
|
||||||
|
LocaleType locale));
|
||||||
|
} *locale_mock;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
_locale_t _create_locale(int category, const char *locale) {
|
||||||
|
return locale_mock->newlocale(category, locale, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _free_locale(_locale_t locale) {
|
||||||
|
locale_mock->freelocale(locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
double _strtod_l(const char *nptr, char **endptr, _locale_t locale) {
|
||||||
|
return locale_mock->strtod_l(nptr, endptr, locale);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LocaleType newlocale(int category_mask, const char *locale, LocaleType base) {
|
||||||
|
return locale_mock->newlocale(category_mask, locale, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
typedef int FreeLocaleResult;
|
||||||
|
#else
|
||||||
|
typedef void FreeLocaleResult;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FreeLocaleResult freelocale(LocaleType locale) {
|
||||||
|
locale_mock->freelocale(locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
double strtod_l(const char *nptr, char **endptr, LocaleType locale) {
|
||||||
|
return locale_mock->strtod_l(nptr, endptr, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LocaleTest, LocaleMock) {
|
||||||
|
ScopedMock<LocaleMock> mock(locale_mock);
|
||||||
|
LocaleType locale = reinterpret_cast<LocaleType>(11);
|
||||||
|
EXPECT_CALL(mock, newlocale(222, StrEq("foo"), locale));
|
||||||
|
newlocale(222, "foo", locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LocaleTest, Locale) {
|
||||||
|
#ifndef LC_NUMERIC_MASK
|
||||||
|
enum { LC_NUMERIC_MASK = LC_NUMERIC };
|
||||||
|
#endif
|
||||||
|
ScopedMock<LocaleMock> mock(locale_mock);
|
||||||
|
LocaleType impl = reinterpret_cast<LocaleType>(42);
|
||||||
|
EXPECT_CALL(mock, newlocale(LC_NUMERIC_MASK, StrEq("C"), 0))
|
||||||
|
.WillOnce(Return(impl));
|
||||||
|
EXPECT_CALL(mock, freelocale(impl));
|
||||||
|
fmt::Locale locale;
|
||||||
|
EXPECT_EQ(impl, locale.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LocaleTest, Strtod) {
|
||||||
|
ScopedMock<LocaleMock> mock(locale_mock);
|
||||||
|
EXPECT_CALL(mock, newlocale(_, _, _))
|
||||||
|
.WillOnce(Return(reinterpret_cast<LocaleType>(42)));
|
||||||
|
EXPECT_CALL(mock, freelocale(_));
|
||||||
|
fmt::Locale locale;
|
||||||
|
const char *str = "4.2";
|
||||||
|
char end = 'x';
|
||||||
|
EXPECT_CALL(mock, strtod_l(str, _, locale.get()))
|
||||||
|
.WillOnce(testing::DoAll(testing::SetArgPointee<1>(&end), Return(777)));
|
||||||
|
EXPECT_EQ(777, locale.strtod(str));
|
||||||
|
EXPECT_EQ(&end, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FMT_LOCALE
|
||||||
|
@ -388,7 +388,7 @@ TEST(FileTest, FdopenError) {
|
|||||||
f.fdopen("r"), EBADF, "cannot associate stream with file descriptor");
|
f.fdopen("r"), EBADF, "cannot associate stream with file descriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LC_NUMERIC_MASK
|
#ifdef FMT_LOCALE
|
||||||
TEST(LocaleTest, Strtod) {
|
TEST(LocaleTest, Strtod) {
|
||||||
fmt::Locale locale;
|
fmt::Locale locale;
|
||||||
const char *start = "4.2", *ptr = start;
|
const char *start = "4.2", *ptr = start;
|
||||||
|
Loading…
Reference in New Issue
Block a user