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 
33 TEST(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__)
147 TEST(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 
184 TEST(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 
225 TEST(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