@@ -191,3 +191,74 @@ TEST(fmt, result) {
191191 EXPECT_EQ (ipc::fmt (r1), ipc::fmt (" succ, error = " , std::error_code ()));
192192 }
193193}
194+
195+ // / \brief Test case for issue #171: Compiler failures under MinGW
196+ // / \see https://github.com/mutouyun/cpp-ipc/issues/171
197+ // /
198+ // / The issue is that std::hex and std::dec (I/O manipulators) were incorrectly
199+ // / used with ipc::fmt. These are function pointers of type:
200+ // / std::ios_base& (*)(std::ios_base&)
201+ // / which ipc::fmt does not support.
202+ // /
203+ // / The correct way to output hexadecimal values with ipc::fmt is to use ipc::spec.
204+ TEST (fmt, hex_output_with_spec) {
205+ // / \brief Basic hexadecimal formatting using ipc::spec
206+ // / This is the correct way to format hex values (instead of std::hex)
207+ {
208+ unsigned int val = 255 ;
209+ EXPECT_EQ (ipc::fmt (ipc::spec (" x" )(val)), " ff" );
210+ EXPECT_EQ (ipc::fmt (ipc::spec (" X" )(val)), " FF" );
211+ EXPECT_EQ (ipc::fmt (ipc::spec (" 08x" )(val)), " 000000ff" );
212+ EXPECT_EQ (ipc::fmt (ipc::spec (" 08X" )(val)), " 000000FF" );
213+ }
214+
215+ // / \brief Hex formatting with prefix (simulating "0x" prefix like std::hex would produce)
216+ {
217+ unsigned int val = 0xDEADBEEF ;
218+ // Correct way: use string concatenation with ipc::spec for hex format
219+ EXPECT_EQ (ipc::fmt (" 0x" , ipc::spec (" x" )(val)), " 0xdeadbeef" );
220+ EXPECT_EQ (ipc::fmt (" 0x" , ipc::spec (" X" )(val)), " 0xDEADBEEF" );
221+ EXPECT_EQ (ipc::fmt (" 0x" , ipc::spec (" 08x" )(val)), " 0xdeadbeef" );
222+ }
223+
224+ // / \brief Mixed decimal and hex output (simulating the problematic log pattern from issue #171)
225+ // / Original problematic code pattern was:
226+ // / log.error("fail WaitForSingleObject[", ::GetLastError(), "]: 0x", std::hex, ret, std::dec);
227+ // / Correct pattern should be:
228+ // / log.error("fail WaitForSingleObject[", ::GetLastError(), "]: ", ipc::spec("08x")(ret));
229+ {
230+ unsigned long error_code = 5 ; // ERROR_ACCESS_DENIED
231+ unsigned int ret = 0x00000102 ; // WAIT_TIMEOUT value
232+
233+ // Correct way to format the log message
234+ auto msg = ipc::fmt (" fail WaitForSingleObject[" , error_code, " ]: " , ipc::spec (" 08x" )(ret));
235+ EXPECT_EQ (msg, " fail WaitForSingleObject[5]: 00000102" );
236+
237+ // Alternative with "0x" prefix
238+ auto msg2 = ipc::fmt (" fail WaitForSingleObject[" , error_code, " ]: 0x" , ipc::spec (" x" )(ret));
239+ EXPECT_EQ (msg2, " fail WaitForSingleObject[5]: 0x102" );
240+ }
241+
242+ // / \brief Various integer types with hex formatting
243+ // / Note: ipc::spec format string should NOT include length modifiers (like "ll").
244+ // / The to_string function automatically adds the correct length modifier based on
245+ // / the argument type. Just use "x" or "X" for hex conversion.
246+ {
247+ EXPECT_EQ (ipc::fmt (ipc::spec (" x" )((unsigned char )0xAB )), " ab" );
248+ EXPECT_EQ (ipc::fmt (ipc::spec (" x" )((unsigned short )0xABCD )), " abcd" );
249+ EXPECT_EQ (ipc::fmt (ipc::spec (" x" )((unsigned int )0xABCDEF01 )), " abcdef01" );
250+ EXPECT_EQ (ipc::fmt (ipc::spec (" x" )((unsigned long )0xABCDEF01 )), " abcdef01" );
251+ // For unsigned long long, just use "x" - the length modifier is added automatically
252+ EXPECT_EQ (ipc::fmt (ipc::spec (" x" )((unsigned long long )0xABCDEF0123456789ULL )), " abcdef0123456789" );
253+ }
254+
255+ // / \brief Width and padding with hex
256+ {
257+ unsigned int val = 0x1F ;
258+ EXPECT_EQ (ipc::fmt (ipc::spec (" 2x" )(val)), " 1f" );
259+ EXPECT_EQ (ipc::fmt (ipc::spec (" 4x" )(val)), " 1f" );
260+ EXPECT_EQ (ipc::fmt (ipc::spec (" 04x" )(val)), " 001f" );
261+ EXPECT_EQ (ipc::fmt (ipc::spec (" 8x" )(val)), " 1f" );
262+ EXPECT_EQ (ipc::fmt (ipc::spec (" 08x" )(val)), " 0000001f" );
263+ }
264+ }
0 commit comments