libStatGen Software 1
STLUtilities_test.cpp
1/*
2 * Copyright (C) 2010 Regents of the University of Michigan
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17#include <string>
18#include "STLUtilities.h"
19
20//
21#define _STLUTILITIES_BENCHMARK_
22// This can turn on the benchmark of STLUtilities class and String class
23//
24#ifdef _STLUTILITIES_BENCHMARK_
25#include "Performance.h"
26#include "Random.h"
27#include "StringBasics.h"
28#endif /* _STLUTILITIES_BENCHMARK_ */
29
30
31#include <gtest/gtest.h>
32
33TEST(STLUtilitiesTest, tSTLUtilitiesTest)
34{
35#if 0
36 std::string test;
37 std::string::iterator result;
38
39 test = "445566";
40 result = trimSequence(test, '5', true);
41 EXPECT_EQ(result - test.begin() , 2);
42
43 test = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
44 result = trimSequence(test, 'A', true);
45 EXPECT_TRUE(result == test.begin());
46#endif
47
48
49 using namespace STLUtilities; // for overloaded std::string << operator
50
51 std::string toot;
52
53 toot << "double: " << 0.123456 << " LL: " << -5LL << " UL: " << 999UL << " char: " << '!';
54
55 EXPECT_TRUE(toot == "double: 0.123456 LL: -5 UL: 999 char: !");
56
57
58 // same result as above using different methods
59 toot.clear();
60
61 append(toot, "double: ");
62
63 append(toot, 0.123456);
64
65 append(toot, " LL: ");
66
67 append(toot, -5LL);
68
69 append(toot, " UL: ");
70
71 append(toot, 999UL);
72
73 append(toot, " char: ");
74
75 append(toot, (char) (' ' + 1));
76
77 EXPECT_TRUE(toot == "double: 0.123456 LL: -5 UL: 999 char: !");
78
79
80 toot.clear();
81
82 std::vector<int> v;
83 v.push_back(1);
84 v.push_back(2);
85 v.push_back(3);
86 v.push_back(4);
87 v.push_back(5);
88
89 toot = "array: ";
90 append(toot, v, "\t", true);
91
92 EXPECT_TRUE(toot == "array: 0: 1\t1: 2\t2: 3\t3: 4\t4: 5");
93
94 std::vector<std::string> tokens;
95
96 Tokenize(tokens, "ab\tcd\tefg\thi\tjk", '\t');
97 EXPECT_EQ(tokens.size(), 5U);
98 EXPECT_TRUE(tokens[0] == "ab");
99 EXPECT_TRUE(tokens[1] == "cd");
100 EXPECT_TRUE(tokens[2] == "efg");
101 EXPECT_TRUE(tokens[3] == "hi");
102 EXPECT_TRUE(tokens[4] == "jk");
103
104
105 Tokenize(tokens, "ab\tcd\tefg\thi\tjk\t", '\t');
106 EXPECT_EQ(tokens.size(), 6U);
107 EXPECT_TRUE(tokens[5] == "");
108
109 // a single tab splits two empty fields, so should see two tokens here:
110 Tokenize(tokens, "\t", '\t');
111 EXPECT_EQ(tokens.size(), 2U);
112 EXPECT_TRUE(tokens[0] == "");
113 EXPECT_TRUE(tokens[1] == "");
114
115
116 Tokenize(tokens, "bahbah", '\t');
117 EXPECT_EQ(tokens.size(), 1U);
118 EXPECT_TRUE(tokens[0] == "bahbah");
119
120 //
121 // no data on the line is the same as a single empty field.
122 // the reason is we don't want to have a file with a single
123 // column of data, but two separate values for .size(). Better
124 // to let the caller simply say 'if tokens[0]==""'
125 //
126 Tokenize(tokens, "", '\t');
127 EXPECT_EQ(tokens.size(), 1U);
128 EXPECT_TRUE(tokens[0] == "");
129
130#if 0
131 toot = "";
132 append(toot, tokens, '\t');
133 std::cout << toot << std::endl;
134
135 exit(0);
136#endif
137}
138
139//
140// Variadic templates necessary for reasonable printf implementation
141// are only supported as an experimental feature that in theory is
142// subject to changes in the future draft standard for C++.
143//
144// Only defined when the g++ option -std=c++0x is used.
145//
146#if defined(__GXX_EXPERIMENTAL_CXX0X__)
147TEST(STLUtilitiesTestPrintf, tSTLUtilitiesTestPrintf)
148{
149 using namespace STLUtilities; // for overloaded std::string << operator
150
151 std::string result;
152
153 sprintf(result, "Hello, world!");
154 EXPECT_TRUE(result=="Hello, world!");
155
156 sprintf(result, "n = %20.5lXXX", 123ULL);
157 EXPECT_TRUE(result=="n = 7bXX");
158
159 sprintf(result, "hello, world! %20sand boo", "well then");
160 EXPECT_TRUE(result=="hello, world! well thenand boo");
161
162 sprintf(result, "addr = %08xXXX", 1234);
163 EXPECT_TRUE(result=="addr = 000004d2XXX");
164
165 sprintf(result, "Hello, world!! Imagine: %d!", 2345.1234);
166 EXPECT_TRUE(result=="Hello, world!! Imagine: 2345.12!");
167
168}
169#endif
170
171#ifdef _STLUTILITIES_BENCHMARK_
172
173//
174// Compare StringBasics.h String with std::string and STLUtilities append methods
175//
176// NB: these are mostly inline with the exception of String::operator +(char c), which
177// is a function call, so as currently implemented, String is at a disadvantage.
178//
179// However, all of these potentially suffer from limitations in g++, as I've noticed
180// that it at times is unable to inline more than a few levels of nested functions
181// deep even if all are trivially short and inlined.
182//
183
184TEST(STLUtilitiesTestPrintf, Benchmark1) {
185 using namespace STLUtilities; // for overloaded std::string << operator
186
187 std::string result;
188 Random random;
189 int range = 'z' - 'A';
190 unsigned int round = 1e6;
191 Timing timing;
192 random.Reset(0);
193 timing.start();
194 for (unsigned int i = 0; i < round; i++)
195 {
196 result << (char)('A' + ( random.NextInt() % range));
197 }
198 timing.end();
199 std::cout << "STLUtilities " << round << " times takes " << timing.interval() << " second " << std::endl;
200
201 String s;
202 random.Reset(0);
203 timing.start();
204 for (unsigned int i = 0; i < round; i++)
205 {
206 s += (char)('A' + ( random.NextInt() % range));
207 }
208 timing.end();
209 std::cout << "String " << round << " times takes " << timing.interval() << " second " << std::endl;
210 EXPECT_EQ(result, s.c_str());
211
212 std::string st;
213 random.Reset(0);
214 timing.start();
215 for (unsigned int i = 0; i < round; i++)
216 {
217 st += (char)('A' + ( random.NextInt() % range));
218 }
219 timing.end();
220 std::cout << "std::string " << round << " times takes " << timing.interval() << " second " << std::endl;
221 EXPECT_EQ(result, st);
222
223}
224
225TEST(STLUtilitiesTestPrintf, Benchmark2) {
226 using namespace STLUtilities; // for overloaded std::string << operator
227
228 std::string result;
229 Random random;
230 unsigned int round = 1e6;
231 Timing timing;
232 timing.start();
233 for (unsigned int i = 0; i < round; i++)
234 {
235 result = "";
236 for(int j=0; j<15; j++) result << (char) 'A';
237 }
238 timing.end();
239 std::cout << "STLUtilities " << round << " times takes " << timing.interval() << " second " << std::endl;
240
241 String s;
242 timing.start();
243 for (unsigned int i = 0; i < round; i++)
244 {
245 s = "";
246 for(int j=0; j<15; j++) s += 'A';
247 }
248 timing.end();
249 std::cout << "String " << round << " times takes " << timing.interval() << " second " << std::endl;
250 EXPECT_EQ(result, s.c_str());
251
252 std::string st;
253 timing.start();
254 for (unsigned int i = 0; i < round; i++)
255 {
256 st = "";
257 for(int j=0; j<15; j++) st += 'A';
258 }
259 timing.end();
260 std::cout << "std::string " << round << " times takes " << timing.interval() << " second " << std::endl;
261 EXPECT_EQ(result, st);
262}
263
264#endif /* _STLUTILITIES_BENCHMARK_ */
Definition: Random.h:73
double interval()
Return time interval between start() and end()
Definition: Performance.h:60
This file is inspired by the poor quality of string support in STL for what should be trivial capabil...
std::string & append(std::string &s, float f)
use std streams API to do float conversion to string, then append it.
Definition: STLUtilities.h:50