testIoManip.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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 
18 class TestIoManip: public CPPUNIT_NS::TestFixture
19 {
24 
25 protected:
26  void testAsHex();
27  void testAtMostOnce();
28 };
29 
31 
33 static void
34 resetStream(std::ostringstream &dirty)
35 {
36  std::ostringstream clean;
37  dirty.swap(clean);
38 }
39 
41 template <typename Integer>
42 static std::string
43 toStdString(const AsHex<Integer> &manipulator)
44 {
45  std::ostringstream os;
46  os << manipulator;
47  return os.str();
48 }
49 
50 void
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 
158 void
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 
186 int
187 main(int argc, char *argv[])
188 {
189  return TestProgram().run(argc, argv);
190 }
191 
static void resetStream(std::ostringstream &dirty)
resets the given stream, including any formatting
Definition: testIoManip.cc:34
static std::string toStdString(const AsHex< Integer > &manipulator)
returns the result of printing the given manipulator
Definition: testIoManip.cc:43
implements test program's main() function while enabling customization
Definition: unitTestMain.h:25
const A & max(A const &lhs, A const &rhs)
int run(int argc, char *argv[])
Definition: unitTestMain.h:44
CPPUNIT_TEST(testAsHex)
int main(int argc, char *argv[])
Definition: testIoManip.cc:187
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
Definition: IoManip.h:169
void testAtMostOnce()
Definition: testIoManip.cc:159
CPPUNIT_TEST_SUITE_REGISTRATION(TestIoManip)
CPPUNIT_TEST_SUITE(TestIoManip)
void testAsHex()
Definition: testIoManip.cc:51
CPPUNIT_TEST_SUITE_END()
Definition: IoManip.h:111
const A & min(A const &lhs, A const &rhs)

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors