libStatGen Software  1
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 "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     EXPECT_TRUE(tokens[0] == "");
00113     EXPECT_TRUE(tokens[1] == "");
00114 
00115 
00116     Tokenize(tokens, "bahbah", '\t');
00117     EXPECT_EQ(tokens.size(), 1U);
00118     EXPECT_TRUE(tokens[0] == "bahbah");
00119 
00120     //
00121     // no data on the line is the same as a single empty field.
00122     // the reason is we don't want to have a file with a single
00123     // column of data, but two separate values for .size().  Better
00124     // to let the caller simply say 'if tokens[0]==""'
00125     //
00126     Tokenize(tokens, "", '\t');
00127     EXPECT_EQ(tokens.size(), 1U);
00128     EXPECT_TRUE(tokens[0] == "");
00129 
00130 #if 0
00131     toot = "";
00132     append(toot, tokens, '\t');
00133     std::cout << toot << std::endl;
00134 
00135     exit(0);
00136 #endif
00137 }
00138 
00139 //
00140 // Variadic templates necessary for reasonable printf implementation
00141 // are only supported as an experimental feature that in theory is
00142 // subject to changes in the future draft standard for C++.
00143 // 
00144 // Only defined when the g++ option -std=c++0x is used.
00145 //
00146 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00147 TEST(STLUtilitiesTestPrintf, tSTLUtilitiesTestPrintf)
00148 {
00149     using namespace STLUtilities; // for overloaded std::string << operator
00150 
00151     std::string result;
00152 
00153     sprintf(result, "Hello, world!");
00154     EXPECT_TRUE(result=="Hello, world!");
00155 
00156     sprintf(result, "n = %20.5lXXX", 123ULL);
00157     EXPECT_TRUE(result=="n =                   7bXX");
00158 
00159     sprintf(result, "hello, world! %20sand boo", "well then");
00160     EXPECT_TRUE(result=="hello, world!            well thenand boo");
00161 
00162     sprintf(result, "addr = %08xXXX", 1234);
00163     EXPECT_TRUE(result=="addr = 000004d2XXX");
00164 
00165     sprintf(result, "Hello, world!! Imagine: %d!", 2345.1234);
00166     EXPECT_TRUE(result=="Hello, world!! Imagine: 2345.12!");
00167 
00168 }
00169 #endif
00170 
00171 #ifdef _STLUTILITIES_BENCHMARK_
00172 
00173 //
00174 // Compare StringBasics.h String with std::string and STLUtilities append methods
00175 //
00176 // NB: these are mostly inline with the exception of String::operator +(char c), which
00177 // is a function call, so as currently implemented, String is at a disadvantage.
00178 //
00179 // However, all of these potentially suffer from limitations in g++, as I've noticed
00180 // that it at times is unable to inline more than a few levels of nested functions
00181 // deep even if all are trivially short and inlined.
00182 //
00183 
00184 TEST(STLUtilitiesTestPrintf, Benchmark1) {
00185     using namespace STLUtilities; // for overloaded std::string << operator
00186 
00187     std::string result;
00188     Random random;
00189     int range = 'z' - 'A';
00190     unsigned int round = 1e6;
00191     Timing timing;
00192     random.Reset(0);
00193     timing.start();
00194     for (unsigned int i = 0; i < round; i++)
00195     {
00196         result << (char)('A' + ( random.NextInt() % range));
00197     }
00198     timing.end();
00199     std::cout << "STLUtilities " << round << " times takes " << timing.interval() << " second " << std::endl;
00200 
00201     String s;
00202     random.Reset(0);
00203     timing.start();
00204     for (unsigned int i = 0; i < round; i++)
00205     {
00206         s += (char)('A' + ( random.NextInt() % range));
00207     }
00208     timing.end();
00209     std::cout << "String " << round << " times takes " << timing.interval() << " second " << std::endl;
00210     EXPECT_EQ(result, s.c_str());
00211 
00212     std::string st;
00213     random.Reset(0);
00214     timing.start();
00215     for (unsigned int i = 0; i < round; i++)
00216     {
00217         st += (char)('A' + ( random.NextInt() % range));
00218     }
00219     timing.end();
00220     std::cout << "std::string " << round << " times takes " << timing.interval() << " second " << std::endl;
00221     EXPECT_EQ(result, st);
00222 
00223 }
00224 
00225 TEST(STLUtilitiesTestPrintf, Benchmark2) {
00226     using namespace STLUtilities; // for overloaded std::string << operator
00227 
00228     std::string result;
00229     Random random;
00230     unsigned int round = 1e6;
00231     Timing timing;
00232     timing.start();
00233     for (unsigned int i = 0; i < round; i++)
00234     {
00235         result = "";
00236         for(int j=0; j<15; j++) result << (char) 'A';
00237     }
00238     timing.end();
00239     std::cout << "STLUtilities " << round << " times takes " << timing.interval() << " second " << std::endl;
00240 
00241     String s;
00242     timing.start();
00243     for (unsigned int i = 0; i < round; i++)
00244     {
00245         s = "";
00246         for(int j=0; j<15; j++) s += 'A';
00247     }
00248     timing.end();
00249     std::cout << "String " << round << " times takes " << timing.interval() << " second " << std::endl;
00250     EXPECT_EQ(result, s.c_str());
00251 
00252     std::string st;
00253     timing.start();
00254     for (unsigned int i = 0; i < round; i++)
00255     {
00256         st = "";
00257         for(int j=0; j<15; j++) st += 'A';
00258     }
00259     timing.end();
00260     std::cout << "std::string " << round << " times takes " << timing.interval() << " second " << std::endl;
00261     EXPECT_EQ(result, st);
00262 }
00263 
00264 #endif /* _STLUTILITIES_BENCHMARK_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends