STLUtilities_test.cpp

00001 /*
00002  *  Copyright (C) 2010  Regents of the University of Michigan
00003  *
00004  *   This program is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #include <string>
00018 #include "STLUtilities.h"
00019 
00020 //
00021 #define _STLUTILITIES_BENCHMARK_
00022 // This can turn on the benchmark of STLUtilities class and String class
00023 //
00024 #ifdef _STLUTILITIES_BENCHMARK_
00025 #include "../../karma/Performance.h"
00026 #include "Random.h"
00027 #include "StringBasics.h"
00028 #endif /* _STLUTILITIES_BENCHMARK_ */
00029 
00030 
00031 #include <gtest/gtest.h>
00032 
00033 TEST(STLUtilitiesTest, tSTLUtilitiesTest)
00034 {
00035 #if 0
00036     std::string test;
00037     std::string::iterator result;
00038 
00039     test = "445566";
00040     result = trimSequence(test, '5', true);
00041     EXPECT_EQ(result - test.begin() , 2);
00042 
00043     test = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00044     result = trimSequence(test, 'A', true);
00045     EXPECT_TRUE(result == test.begin());
00046 #endif
00047 
00048 
00049     using namespace STLUtilities; // for overloaded std::string << operator
00050 
00051     std::string toot;
00052 
00053     toot << "double: " << 0.123456 << " LL: " << -5LL << " UL: " << 999UL << " char: " << '!';
00054 
00055     EXPECT_TRUE(toot == "double: 0.123456 LL: -5 UL: 999 char: !");
00056 
00057 
00058     // same result as above using different methods
00059     toot.clear();
00060 
00061     append(toot, "double: ");
00062 
00063     append(toot, 0.123456);
00064 
00065     append(toot, " LL: ");
00066 
00067     append(toot, -5LL);
00068 
00069     append(toot, " UL: ");
00070 
00071     append(toot, 999UL);
00072 
00073     append(toot, " char: ");
00074 
00075     append(toot, (char) (' ' + 1));
00076 
00077     EXPECT_TRUE(toot == "double: 0.123456 LL: -5 UL: 999 char: !");
00078 
00079 
00080     toot.clear();
00081 
00082     std::vector<int> v;
00083     v.push_back(1);
00084     v.push_back(2);
00085     v.push_back(3);
00086     v.push_back(4);
00087     v.push_back(5);
00088 
00089     toot = "array: ";
00090     append(toot, v, "\t", true);
00091 
00092     EXPECT_TRUE(toot == "array: 0: 1\t1: 2\t2: 3\t3: 4\t4: 5");
00093 
00094     std::vector<std::string> tokens;
00095 
00096     Tokenize(tokens, "ab\tcd\tefg\thi\tjk", '\t');
00097     EXPECT_EQ(tokens.size(), 5U);
00098     EXPECT_TRUE(tokens[0] == "ab");
00099     EXPECT_TRUE(tokens[1] == "cd");
00100     EXPECT_TRUE(tokens[2] == "efg");
00101     EXPECT_TRUE(tokens[3] == "hi");
00102     EXPECT_TRUE(tokens[4] == "jk");
00103 
00104 
00105     Tokenize(tokens, "ab\tcd\tefg\thi\tjk\t", '\t');
00106     EXPECT_EQ(tokens.size(), 6U);
00107     EXPECT_TRUE(tokens[5] == "");
00108 
00109     // a single tab splits two empty fields, so should see two tokens here:
00110     Tokenize(tokens, "\t", '\t');
00111     EXPECT_EQ(tokens.size(), 2U);
00112 
00113 
00114     Tokenize(tokens, "bahbah", '\t');
00115     EXPECT_TRUE(tokens[0] == "bahbah");
00116     EXPECT_EQ(tokens.size(), 1U);
00117 
00118     //
00119     // no data on the line is the same as a single empty field.
00120     // the reason is we don't want to have a file with a single
00121     // column of data, but two separate values for .size().  Better
00122     // to let the caller simply say 'if tokens[0]==""'
00123     //
00124     Tokenize(tokens, "", '\t');
00125     EXPECT_TRUE(tokens[0] == "");
00126     EXPECT_EQ(tokens.size(), 1U);
00127 
00128 #if 0
00129     toot = "";
00130     append(toot, tokens, '\t');
00131     std::cout << toot << std::endl;
00132 
00133     exit(0);
00134 #endif
00135 }
00136 
00137 //
00138 // Variadic templates necessary for reasonable printf implementation
00139 // are only supported as an experimental feature that in theory is
00140 // subject to changes in the future draft standard for C++.
00141 // 
00142 // Only defined when the g++ option -std=c++0x is used.
00143 //
00144 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00145 TEST(STLUtilitiesTestPrintf, tSTLUtilitiesTestPrintf)
00146 {
00147     using namespace STLUtilities; // for overloaded std::string << operator
00148 
00149     std::string result;
00150 
00151     sprintf(result, "Hello, world!");
00152     EXPECT_TRUE(result=="Hello, world!");
00153 
00154     sprintf(result, "n = %20.5lXXX", 123ULL);
00155     EXPECT_TRUE(result=="n =                   7bXX");
00156 
00157     sprintf(result, "hello, world! %20sand boo", "well then");
00158     EXPECT_TRUE(result=="hello, world!            well thenand boo");
00159 
00160     sprintf(result, "addr = %08xXXX", 1234);
00161     EXPECT_TRUE(result=="addr = 000004d2XXX");
00162 
00163     sprintf(result, "Hello, world!! Imagine: %d!", 2345.1234);
00164     EXPECT_TRUE(result=="Hello, world!! Imagine: 2345.12!");
00165 
00166 }
00167 #endif
00168 
00169 #ifdef _STLUTILITIES_BENCHMARK_
00170 
00171 //
00172 // Compare StringBasics.h String with std::string and STLUtilities append methods
00173 //
00174 // NB: these are mostly inline with the exception of String::operator +(char c), which
00175 // is a function call, so as currently implemented, String is at a disadvantage.
00176 //
00177 // However, all of these potentially suffer from limitations in g++, as I've noticed
00178 // that it at times is unable to inline more than a few levels of nested functions
00179 // deep even if all are trivially short and inlined.
00180 //
00181 
00182 TEST(STLUtilitiesTestPrintf, Benchmark1) {
00183     using namespace STLUtilities; // for overloaded std::string << operator
00184 
00185     std::string result;
00186     Random random;
00187     int range = 'z' - 'A';
00188     unsigned int round = 1e6;
00189     Timing timing;
00190     random.Reset(0);
00191     timing.start();
00192     for (unsigned int i = 0; i < round; i++)
00193     {
00194         result << (char)('A' + ( random.NextInt() % range));
00195     }
00196     timing.end();
00197     std::cout << "STLUtilities " << round << " times takes " << timing.interval() << " second " << std::endl;
00198 
00199     String s;
00200     random.Reset(0);
00201     timing.start();
00202     for (unsigned int i = 0; i < round; i++)
00203     {
00204         s += (char)('A' + ( random.NextInt() % range));
00205     }
00206     timing.end();
00207     std::cout << "String " << round << " times takes " << timing.interval() << " second " << std::endl;
00208     EXPECT_EQ(result, s.c_str());
00209 
00210     std::string st;
00211     random.Reset(0);
00212     timing.start();
00213     for (unsigned int i = 0; i < round; i++)
00214     {
00215         st += (char)('A' + ( random.NextInt() % range));
00216     }
00217     timing.end();
00218     std::cout << "std::string " << round << " times takes " << timing.interval() << " second " << std::endl;
00219     EXPECT_EQ(result, st);
00220 
00221 }
00222 
00223 TEST(STLUtilitiesTestPrintf, Benchmark2) {
00224     using namespace STLUtilities; // for overloaded std::string << operator
00225 
00226     std::string result;
00227     Random random;
00228     unsigned int round = 1e6;
00229     Timing timing;
00230     timing.start();
00231     for (unsigned int i = 0; i < round; i++)
00232     {
00233         result = "";
00234         for(int j=0; j<15; j++) result << (char) 'A';
00235     }
00236     timing.end();
00237     std::cout << "STLUtilities " << round << " times takes " << timing.interval() << " second " << std::endl;
00238 
00239     String s;
00240     timing.start();
00241     for (unsigned int i = 0; i < round; i++)
00242     {
00243         s = "";
00244         for(int j=0; j<15; j++) s += 'A';
00245     }
00246     timing.end();
00247     std::cout << "String " << round << " times takes " << timing.interval() << " second " << std::endl;
00248     EXPECT_EQ(result, s.c_str());
00249 
00250     std::string st;
00251     timing.start();
00252     for (unsigned int i = 0; i < round; i++)
00253     {
00254         st = "";
00255         for(int j=0; j<15; j++) st += 'A';
00256     }
00257     timing.end();
00258     std::cout << "std::string " << round << " times takes " << timing.interval() << " second " << std::endl;
00259     EXPECT_EQ(result, st);
00260 }
00261 
00262 #endif /* _STLUTILITIES_BENCHMARK_ */
Generated on Wed Nov 17 15:38:29 2010 for StatGen Software by  doxygen 1.6.3