@@ -26,8 +26,9 @@ namespace tmp {
2626namespace {
2727
2828// / Returns whether the underlying raw file device object is open
29- bool is_open (const file& file) {
30- std::filebuf* filebuf = dynamic_cast <std::filebuf*>(file.rdbuf ());
29+ template <class charT , class traits >
30+ bool is_open (const basic_file<charT, traits>& file) {
31+ auto filebuf = dynamic_cast <std::basic_filebuf<charT, traits>*>(file.rdbuf ());
3132 return filebuf != nullptr && filebuf->is_open ();
3233}
3334
@@ -43,36 +44,68 @@ bool is_open(file::native_handle_type handle) {
4344#endif
4445}
4546
47+ template <typename charT>
48+ constexpr std::basic_string<charT> convert_string (const char * string) {
49+ if constexpr (std::is_same_v<charT, char >) {
50+ return std::basic_string<charT>(string);
51+ }
52+
53+ if constexpr (std::is_same_v<charT, wchar_t >) {
54+ std::mbstate_t state = std::mbstate_t ();
55+
56+ std::basic_string<charT> result;
57+ result.resize (std::mbsrtowcs (nullptr , &string, 0 , &state));
58+
59+ std::size_t ret =
60+ std::mbsrtowcs (result.data (), &string, result.size (), &state);
61+ assert (ret == result.size ());
62+ return result;
63+ }
64+
65+ throw std::invalid_argument (" Unknown character type" );
66+ }
67+
68+ template <typename charT> class file : public testing ::Test {};
69+
70+ using char_types = testing::Types<char , wchar_t >;
71+ TYPED_TEST_SUITE (file, char_types, testing::internal::DefaultNameGenerator);
72+
4673// / Tests file type traits and member types
47- TEST (file, type_traits) {
48- using traits = std::char_traits<char >;
49-
50- static_assert (std::is_base_of_v<std::basic_iostream<char >, file>);
51- static_assert (std::is_same_v<file::char_type, char >);
52- static_assert (std::is_same_v<file::traits_type, traits>);
53- static_assert (std::is_same_v<file::int_type, traits::int_type>);
54- static_assert (std::is_same_v<file::pos_type, traits::pos_type>);
55- static_assert (std::is_same_v<file::off_type, traits::off_type>);
74+ TYPED_TEST (file, type_traits) {
75+ using traits = std::char_traits<TypeParam>;
76+
77+ static_assert (
78+ std::is_base_of_v<std::basic_iostream<TypeParam>, basic_file<TypeParam>>);
79+ static_assert (
80+ std::is_same_v<typename basic_file<TypeParam>::char_type, TypeParam>);
81+ static_assert (
82+ std::is_same_v<typename basic_file<TypeParam>::traits_type, traits>);
83+ static_assert (std::is_same_v<typename basic_file<TypeParam>::int_type,
84+ typename traits::int_type>);
85+ static_assert (std::is_same_v<typename basic_file<TypeParam>::pos_type,
86+ typename traits::pos_type>);
87+ static_assert (std::is_same_v<typename basic_file<TypeParam>::off_type,
88+ typename traits::off_type>);
5689}
5790
5891// / Tests file creation
59- TEST (file, create) {
60- file tmpfile = file ();
92+ TYPED_TEST (file, create) {
93+ basic_file<TypeParam> tmpfile = basic_file<TypeParam> ();
6194 EXPECT_TRUE (is_open (tmpfile));
6295 EXPECT_TRUE (is_open (tmpfile.native_handle ()));
6396}
6497
6598// / Tests multiple file creation
66- TEST (file, create_multiple) {
67- file fst = file ();
68- file snd = file ();
99+ TYPED_TEST (file, create_multiple) {
100+ basic_file<TypeParam> fst = basic_file<TypeParam> ();
101+ basic_file<TypeParam> snd = basic_file<TypeParam> ();
69102
70103 EXPECT_NE (fst.native_handle (), snd.native_handle ());
71104}
72105
73106// / Tests file open mode
74- TEST (file, openmode) {
75- file tmpfile = file ();
107+ TYPED_TEST (file, openmode) {
108+ basic_file<TypeParam> tmpfile = basic_file<TypeParam> ();
76109 tmpfile << " Hello, World!" << std::flush;
77110 tmpfile.seekg (0 );
78111 tmpfile << " Goodbye!" << std::flush;
@@ -83,42 +116,44 @@ TEST(file, openmode) {
83116}
84117
85118// / Tests that destructor removes a file
86- TEST (file, destructor) {
87- file ::native_handle_type handle;
119+ TYPED_TEST (file, destructor) {
120+ typename basic_file<TypeParam> ::native_handle_type handle;
88121
89122 {
90- file tmpfile = file ();
123+ basic_file<TypeParam> tmpfile = basic_file<TypeParam> ();
91124 handle = tmpfile.native_handle ();
92125 }
93126
94127 EXPECT_FALSE (is_open (handle));
95128}
96129
97130// / Tests file move constructor
98- TEST (file, move_constructor) {
99- file fst = file ();
131+ TYPED_TEST (file, move_constructor) {
132+ basic_file<TypeParam> fst = basic_file<TypeParam> ();
100133 fst << " Hello!" ;
101134
102- file snd = file (std::move (fst));
135+ basic_file<TypeParam> snd = basic_file<TypeParam> (std::move (fst));
103136
104137 EXPECT_TRUE (is_open (snd));
105138
106139 snd.seekg (0 );
107- std::string content;
140+ std::basic_string<TypeParam> content;
108141 snd >> content;
109- EXPECT_EQ (content, " Hello!" );
142+ EXPECT_EQ (content, convert_string<TypeParam>( " Hello!" ) );
110143}
111144
112145// / Tests file move assignment operator
113- TEST (file, move_assignment) {
114- file fst = file ();
146+ TYPED_TEST (file, move_assignment) {
147+ basic_file<TypeParam> fst = basic_file<TypeParam> ();
115148
116149 {
117- file snd = file ();
150+ basic_file<TypeParam> snd = basic_file<TypeParam> ();
118151 snd << " Hello!" ;
119152
120- file::native_handle_type fst_handle = fst.native_handle ();
121- file::native_handle_type snd_handle = snd.native_handle ();
153+ typename basic_file<TypeParam>::native_handle_type fst_handle =
154+ fst.native_handle ();
155+ typename basic_file<TypeParam>::native_handle_type snd_handle =
156+ snd.native_handle ();
122157
123158 fst = std::move (snd);
124159
@@ -130,18 +165,20 @@ TEST(file, move_assignment) {
130165 EXPECT_TRUE (is_open (fst));
131166
132167 fst.seekg (0 );
133- std::string content;
168+ std::basic_string<TypeParam> content;
134169 fst >> content;
135- EXPECT_EQ (content, " Hello!" );
170+ EXPECT_EQ (content, convert_string<TypeParam>( " Hello!" ) );
136171}
137172
138173// / Tests file swapping
139- TEST (file, swap) {
140- file fst = file ();
141- file snd = file ();
142-
143- file::native_handle_type fst_handle = fst.native_handle ();
144- file::native_handle_type snd_handle = snd.native_handle ();
174+ TYPED_TEST (file, swap) {
175+ basic_file<TypeParam> fst = basic_file<TypeParam>();
176+ basic_file<TypeParam> snd = basic_file<TypeParam>();
177+
178+ typename basic_file<TypeParam>::native_handle_type fst_handle =
179+ fst.native_handle ();
180+ typename basic_file<TypeParam>::native_handle_type snd_handle =
181+ snd.native_handle ();
145182
146183 std::swap (fst, snd);
147184
0 commit comments