Squid Web Cache master
Loading...
Searching...
No Matches
testIoManip.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10#include "base/IoManip.h"
11#include "compat/cppunit.h"
12#include "unitTestMain.h"
13
14#include <cstdint>
15#include <limits>
16#include <sstream>
17
18class TestIoManip: public CPPUNIT_NS::TestFixture
19{
24
25protected:
26 void testAsHex();
27 void testAtMostOnce();
28};
29
31
33static void
34resetStream(std::ostringstream &dirty)
35{
36 std::ostringstream clean;
37 dirty.swap(clean);
38}
39
41template <typename Integer>
42static std::string
43toStdString(const AsHex<Integer> &manipulator)
44{
45 std::ostringstream os;
46 os << manipulator;
47 return os.str();
48}
49
50void
52{
53 // basic values
54 CPPUNIT_ASSERT_EQUAL(std::string("0"), toStdString(asHex(0)));
55 CPPUNIT_ASSERT_EQUAL(std::string("123abc"), toStdString(asHex(0x123abc)));
56
57 // large values
58 CPPUNIT_ASSERT_EQUAL(std::string("7fffffffffffffff"), toStdString(asHex(std::numeric_limits<int64_t>::max())));
59 CPPUNIT_ASSERT_EQUAL(std::string("ffffffffffffffff"), toStdString(asHex(std::numeric_limits<uint64_t>::max())));
60
61 // negative values
62 // C++ defines printing with std::hex in terms of calling std::printf() with
63 // %x (or %X) conversion specifier; printf(%x) interprets its value argument
64 // as an unsigned integer, making it impossible for std::hex to print
65 // negative values as negative hex integers. AsHex has the same limitation.
66 CPPUNIT_ASSERT_EQUAL(std::string("80000000"), toStdString(asHex(std::numeric_limits<int32_t>::min())));
67
68 // integer and integer-like types that std::ostream formats specially by default
69 CPPUNIT_ASSERT_EQUAL(std::string("0"), toStdString(asHex(false)));
70 CPPUNIT_ASSERT_EQUAL(std::string("1"), toStdString(asHex(true)));
71 CPPUNIT_ASSERT_EQUAL(std::string("5a"), toStdString(asHex('Z')));
72 CPPUNIT_ASSERT_EQUAL(std::string("77"), toStdString(asHex(int8_t(0x77))));
73 CPPUNIT_ASSERT_EQUAL(std::string("ff"), toStdString(asHex(uint8_t(0xFF))));
74
75 // other interesting integer-like types we may want to print
76 enum { enumValue = 0xABCD };
77 CPPUNIT_ASSERT_EQUAL(std::string("abcd"), toStdString(asHex(enumValue)));
78 struct { uint8_t bitField:2; } s;
79 s.bitField = 3; // TODO: Convert to default initializer after switching to C++20.
80 CPPUNIT_ASSERT_EQUAL(std::string("3"), toStdString(asHex(s.bitField)));
81
82 // padding with zeros works
83 CPPUNIT_ASSERT_EQUAL(std::string("1"), toStdString(asHex(1).minDigits(1)));
84 CPPUNIT_ASSERT_EQUAL(std::string("01"), toStdString(asHex(1).minDigits(2)));
85 CPPUNIT_ASSERT_EQUAL(std::string("001"), toStdString(asHex(1).minDigits(3)));
86
87 // padding with zeros works even for zero values
88 CPPUNIT_ASSERT_EQUAL(std::string("0000"), toStdString(asHex(0).minDigits(4)));
89
90 // minDigits() does not truncate
91 CPPUNIT_ASSERT_EQUAL(std::string("1"), toStdString(asHex(0x1).minDigits(0)));
92 CPPUNIT_ASSERT_EQUAL(std::string("12"), toStdString(asHex(0x12).minDigits(1)));
93 CPPUNIT_ASSERT_EQUAL(std::string("123"), toStdString(asHex(0x123).minDigits(2)));
94
95 // upperCase() forces uppercase
96 CPPUNIT_ASSERT_EQUAL(std::string("A"), toStdString(asHex(0xA).upperCase()));
97 CPPUNIT_ASSERT_EQUAL(std::string("1A2B"), toStdString(asHex(0x1a2b).upperCase(true)));
98
99 std::ostringstream ss;
100
101 // upperCase(false) forces lowercase
102 ss << std::uppercase << asHex(0xABC).upperCase(false);
103 CPPUNIT_ASSERT_EQUAL(std::string("abc"), ss.str());
104 resetStream(ss);
105
106 // a combination of formatting options
107 CPPUNIT_ASSERT_EQUAL(std::string("01A"), toStdString(asHex(0x1A).upperCase().minDigits(3)));
108
109 // Test the effects of stream formatting flags on AsHex printing and the
110 // effects of AsHex printing on stream formatting flags.
111
112 // upperCase() effects are not leaked into the stream
113 ss << asHex(0xa0).upperCase() << asHex(0xa0);
114 CPPUNIT_ASSERT_EQUAL(std::string("A0a0"), ss.str());
115 resetStream(ss);
116
117 // original std::showbase is honored
118 ss << std::showbase << asHex(1);
119 CPPUNIT_ASSERT_EQUAL(std::string("0x1"), ss.str());
120 resetStream(ss);
121
122 // original std::uppercase is honored
123 ss << std::uppercase << std::hex << 0xA << asHex(0xB) << 0xC;
124 CPPUNIT_ASSERT_EQUAL(std::string("ABC"), ss.str());
125 resetStream(ss);
126
127 // original std::uppercase is preserved
128 ss << std::uppercase << std::hex << 0xA << asHex(0xB).upperCase(false) << 0xC;
129 CPPUNIT_ASSERT_EQUAL(std::string("AbC"), ss.str());
130 resetStream(ss);
131
132 // original std::oct is preserved
133 ss << std::oct << 9 << asHex(0xA) << 11;
134 CPPUNIT_ASSERT_EQUAL(std::string("11a13"), ss.str());
135 resetStream(ss);
136
137 // original std::setw() is honored
138 ss << std::setw(4) << asHex(0x1);
139 CPPUNIT_ASSERT_EQUAL(std::string(" 1"), ss.str());
140 resetStream(ss);
141
142 // original std::setw() is consumed (by the printed number)
143 ss << std::setw(4) << asHex(0x1) << 2;
144 CPPUNIT_ASSERT_EQUAL(std::string(" 12"), ss.str());
145 resetStream(ss);
146
147 // original std::setfill() is honored
148 ss << std::setfill('.') << std::setw(4) << asHex(0x2);
149 CPPUNIT_ASSERT_EQUAL(std::string("...2"), ss.str());
150 resetStream(ss);
151
152 // original std::setfill() is preserved
153 ss << std::setfill('.') << asHex(0x3).minDigits(2) << std::setw(4) << 4;
154 CPPUNIT_ASSERT_EQUAL(std::string("03...4"), ss.str());
155 resetStream(ss);
156}
157
158void
160{
161 {
162 std::ostringstream ss;
163 auto textOnce = AtMostOnce("text1");
164 ss << textOnce;
165 CPPUNIT_ASSERT_EQUAL(std::string("text1"), ss.str());
166 ss << textOnce;
167 ss << textOnce;
168 CPPUNIT_ASSERT_EQUAL(std::string("text1"), ss.str());
169 }
170
171 {
172 std::ostringstream ss;
173 // Cannot create std::string when creating textOnce because the string may be
174 // destroyed before we are done with textOnce:
175 // auto textOnce = AtMostOnce(std::string("do not do this"));
176 const std::string s("text2");
177 auto textOnce = AtMostOnce(s);
178 ss << textOnce;
179 CPPUNIT_ASSERT_EQUAL(std::string("text2"), ss.str());
180 ss << textOnce;
181 ss << textOnce;
182 CPPUNIT_ASSERT_EQUAL(std::string("text2"), ss.str());
183 }
184}
185
186int
187main(int argc, char *argv[])
188{
189 return TestProgram().run(argc, argv);
190}
191
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
Definition IoManip.h:169
void testAsHex()
void testAtMostOnce()
CPPUNIT_TEST_SUITE(TestIoManip)
CPPUNIT_TEST(testAsHex)
CPPUNIT_TEST(testAtMostOnce)
CPPUNIT_TEST_SUITE_END()
implements test program's main() function while enabling customization
int run(int argc, char *argv[])
int main()
static void resetStream(std::ostringstream &dirty)
resets the given stream, including any formatting
CPPUNIT_TEST_SUITE_REGISTRATION(TestIoManip)
static std::string toStdString(const AsHex< Integer > &manipulator)
returns the result of printing the given manipulator