// test_CSV.cpp (C) 2008 adolfo@di-mare.com /** \file test_CSV.cpp \brief Test ==> \c CSV. \author Adolfo Di Mare \date 2008. \author A11788 Jose David Hine Gomez \author A24444 Cristopher Rojas Salas \author A56254 Carlos Jose Watson Morua \author A61166 Adrian Ignacio Campos Oviedo \author A61196 Tabare Capitan Jimenez \author A71569 Sergio Esteban Castillo Segura \author A73869 Pablo Ignacio Matamoros Sanchez \author A74668 Erick Abdiel Orestes Chaves \author A76944 Alexander Vega Sanou */ #include "BUnit.h" #include "CSV_line.h" #define C_CSV // truco para que compile "CSV.c" /// Test ==> \c CSV. class test_CSV : public TestCase { public: test_CSV() {} ///< Constructor. bool run(); ///< Execute. private: void test_setData(); void test_op_data(); void test_trim(); void test_trimCSV(); void test_chop(); void test_istringstream(); void test_setQuotedCSV(); void test_getNextCSV(); // void test_rebuildDquote(); #ifdef C_CSV void test_trim_C(); void test_chop_C(); #endif }; /// Efectúa las pruebas. bool test_CSV::run() { test_setData(); test_op_data(); test_trim(); test_trimCSV(); test_chop(); test_istringstream(); test_setQuotedCSV(); test_getNextCSV(); // test_rebuildDquote(); #ifdef C_CSV test_trim_C(); test_chop_C(); #endif return wasSuccessful(); } #include // cout #include // basic_istringstream<> /// Cantidad de elementos del vector \c V[]. /// - DIM() no se puede implementar con plantillas... #define DIM(V) (sizeof(V) / sizeof(*V)) // *V == *(V+0) == V[0] /// Test ==> \c setData(). void test_CSV::test_setData() { {{ // test::setData() CSV_line csv; // 012 3 ...4. .......5. // // [,,a,b,"c,d","e f ""g"\r\n] csv.setData( ",,a,b,\"c,d\",\"e f \"\"g\"\r\n" ); assertTrue( csv[0] == "" ); // [] assertTrue( csv[1] == "" ); // [] assertTrue( csv[2] == "a" ); // [a] assertTrue( csv[3] == "b" ); // [b] assertTrue( csv[4] == "c,d" ); // [c,d] assertTrue( csv[5] == "e f \"g" ); // [e f "g] assertTrue( csv.size() == 6 ); }} if (true) { char* t[13]; std::string str; // 0 1 .2 ..3. ..4 ..5.. 6 ..7 ..8.. 9. ...10. ...11. .12 // ",",""," ", "", "" , " " ,6, 7, 8 ,9"," \r, ",",11,","x\r\n" t[0] = "\",\""; t[ 6] = "6"; t[1] = "\"\""; t[ 7] = " 7"; t[2] = "\" \""; t[ 8] = " 8 "; t[3] = " \"\""; t[ 9] = "9\""; t[4] = " \"\" "; t[10] = "\" \r, \""; t[5] = " \" \" "; t[11] = "\",11,\""; t[12] = "x\r\n"; for (int i=0; i<12; ++i) { str += t[i]; str += ','; } str += t[12]; CSV_line csv; csv.setData( str.data() , str.length() ); assertTrue( csv.size() == 13 ); assertTrue( csv[ 0] == "," ); assertTrue( csv[ 1] == "" ); assertTrue( csv[ 2] == " " ); for (int i=3; i<=9; ++i) { assertTrue_Msg( "t["+toString(i)+"] == ["+t[i]+"] ==> ["+csv[i]+']', t[i] == csv[i] ); } assertTrue( csv[10] == " \r, " ); assertTrue( csv[11] == ",11," ); assertTrue( csv[12] != "x\r\n" ); assertTrue( csv[12] == "x" ); } { using namespace std; string s; s += '"'; s += '"'; // s contiene 2 comillas: "" assertTrue( s == string("\"\"") ); // así es cómo se hace assertTrue( "" == string("""") ); // """" ==> "" "" ==> "" (concatenación de nulas) assertTrue( string("\"\"") != """" ); // """" es la hilera nula // std::cout << '[' << """" << ']' << std::endl; // graba [] } if (false) { // código viejo usado para ver qué está pasando char* t[13]; std::string str; CSV_line csv; // left-over code std::cout << std::endl << '[' << str << ']' << std::endl; std::cout << "csv.size() == " << unsigned(csv.size()) << std::endl; for (size_t i=0; i [" << s << ']' << std::endl; } for (int i=0; i<9; ++i) { assertTrue_Msg( "t["+toString(i)+"]["+t[i]+"] == ["+csv[i]+']', t[i] == csv[i] ); } { int i=0; std::cout << __LINE__ << " csv[" << i << "] == [" << csv[i] << ']' << std::endl; } } { // Las comillas de Pipino Cuevas std::string res; setQuotedCSV(res,"2"); assertTrue(res == "2" ); setQuotedCSV(res,"4,5"); assertTrue(res == "\"4,5\"" ); setQuotedCSV( res, "," ); assertTrue(res == "\",\""); // [","] setQuotedCSV( res, "2" ); assertTrue(res == "2"); // [2] setQuotedCSV( res, "" ); assertTrue(res == ""); // [] setQuotedCSV( res, "4,5" ); assertTrue(res == "\"4,5\""); // ["4,5"] } { // [," ... "" "3x,] CSV_line csv( ",\" ... \"\" \"3x,list" ); assertTrue( csv.size() == 3 ); assertTrue( csv[0] == "" ); assertTrue( csv[1] == "\" ... \"\" \"3x" ); assertTrue( csv[2] == "list" ); } { CSV_line csv( ",\".\r\n\"" ); assertTrue( csv.size() == 2 ); assertTrue( csv[0] == "" ); assertTrue( csv[1] == ".\r\n" ); } { // 0," ,,\r\n .. ",",,\r\n"",",123\r\n // 0 ...........1. .........2. ..3\r\n CSV_line csv; char * t[4]; std::string str; t[0] = "0"; // [0] t[1] = "\" ,,\r\n .. \""; // [" ,,\r\n .. "]; t[2] = "\",,\r\n\"\",\""; // [",,\r\n"","] ==> [,,\r\n",] t[3] = "123\r\n"; // [123] for (int i=0; i<=2; ++i) { str += t[i]; str += ','; } str += t[3]; csv.setData( str.data() , str.length() ); assertTrue( csv.size() == 4 ); assertTrue( csv.size() != 5 ); assertTrue( csv[0] == "0" ); assertTrue( csv[1] == " ,,\r\n .. " ); assertTrue( csv[2] == ",,\r\n\"," ); // ==> [,,\r\n\",] assertTrue( csv[3] == "123" ); assertTrue( csv[3] != "123\r\n" ); assertTrue( csv[3] != "123\r" ); } { CSV_line csv( "123\r\n" ); // [123\r\n ] assertTrue( csv[0] == "123" ); assertTrue( csv[0] != "123\r\n" ); assertTrue( csv[0] != "123\r" ); } { CSV_line csv( ", \" 3rd\" \r\n" ); // [, " 3rd" \r\n] assertTrue( csv[0] == "" ); assertTrue( csv[1] == " \" 3rd\" " ); // [ " 3rd" ] std::string copy = csv[1]; trimCSV( copy ); assertTrue( copy == " 3rd" ); // [3rd] } if (false) { // http://www.di-mare.com/adolfo/cursos/2008-1/p2-ea-3.htm const char * in[11]; const char * out[11]; in[ 0] = "\"zero\""; out[ 0] = "zero"; in[ 1] = ", \"if \"\" 1\" "; out[ 1] = " \"if \"\" 1\" "; in[ 2] = ", "; out[ 2] = " "; in[ 3] = ", \" 3xt\" \r\n"; out[ 3] = " \" 3xt\" "; in[ 4] = ",\"png\"\"\n\"\"\n"; out[ 4] = "png\"\n\""; in[ 5] = ",12345"; out[ 5] = "12345"; in[ 6] = ",\"\"\r\n"; out[ 6] = "\"\""; in[ 7] = ",12\r666\r\n"; out[ 7] = "12\r666"; in[ 8] = ",12\r\n"; out[ 8] = "12"; in[ 9] = ",\"con blanco\""; out[ 9] = "con blanco"; in[10] = ",\"con,coma\""; out[10] = "con,coma"; std::string str; for (int i=0; i<=10; ++i) { str += in[i]; } { std::vector VEC; VEC.clear(); // std::string csv; bool eol_CIN = false; // stop when the end of line is reached std::istringstream ist( str , std::ios::binary ); while ( /* ! eol_CIN && */ ! ist.fail() ) { // ! ist.eof() pitfall! eol_CIN = getNextCSV( csv, ist ); VEC.push_back( csv ); } // Using std::ios::binary ensures that no CR+LF chars are discarded for (int i=0; i<=10; ++i) { assertTrue_Msg( std::string()+in[i]+" ==> "+out[i] , VEC[i]==out[i] ); } } return; } { // A11788 CSV_line csv( "\"\"\"n\"" ); // ["""n"] assertTrue( csv[0] == "\"n" ); // ["n] assertTrue( csv.size() == 1 ); } { // A24444-A71569 const int N_COUT = 0; // Cantidad de valores de csv[] grabados en cout std::string s, str; // 0 1 2 3 4 5 6 // [,"\n","pa""pa","ce\nro", "el "" 1" , ,\n] str = ",\"\n\",\"pa\"\"pa\",\"ce\nro\", \"el \"\" 1\" , ,\n"; CSV_line csv; csv.setData( str.data() ); { assertTrue( csv[0] == "" ); assertTrue( csv[1] == "\n" ); assertTrue( csv[2] == "pa\"pa" ); assertTrue( csv[3] == "ce\nro" ); assertTrue( csv[4] == " \"el \"\" 1\" " ); assertTrue( csv[5] == " " ); assertTrue( csv[6] == "" ); assertTrue( csv.size() == 7 ); for ( int i=0; i CSV_line.operator[](). void test_CSV::test_op_data() { // A73869-A74668 {{ // test::op_data() CSV_line csv ("a,b,c,d,e,f,g"); { assertTrue(csv[0] == "a"); assertTrue(csv[1] == "b"); assertTrue(csv[2] == "c"); assertTrue(csv[3] == "d"); assertTrue(csv[4] == "e"); assertTrue(csv[5] == "f"); assertTrue( csv.size() == 7 ); } }} { // A73869-A74668 CSV_line csv2 ( "poll, m, ts, 08" ); { assertTrue(csv2[0] == "poll"); assertTrue(csv2[1] == " m"); assertTrue(csv2[2] == " ts"); assertTrue(csv2[3] == " 08"); assertTrue(csv2.size() == 4 ); } CSV_line csv3 ("fsd,ah,que,pi,som,b,aaana"); { assertTrue(csv3[0] == "fsd"); assertTrue(csv3[1] == "ah"); assertTrue(csv3[2] == "que"); assertTrue(csv3[3] == "pi"); assertTrue(csv3[4] == "som"); assertTrue(csv3[5] == "b"); assertTrue( csv3.size() == 7 ); } } } /// Test ==> \c setQuotedCSV(). void test_CSV::test_setQuotedCSV() { // A73869-A74668 {{ // test::setQuotedCSV() std::string res; setQuotedCSV( res, "," ); assertTrue( res == "\",\"" ); // [","] setQuotedCSV( res, "2" ); assertTrue( res == "2" ); // [2] setQuotedCSV( res, "" ); assertTrue( res == "" ); // [] setQuotedCSV( res, "4,5" ); assertTrue( res == "\"4,5\"" ); // ["4,5"] setQuotedCSV( res, "K\"" ); assertTrue( res == "\"K\"\"\"" ); // ["K"""] setQuotedCSV( res, "\r\n" ); assertTrue( res == "\"\r\n\"" ); // ["\r\n"] }} { // A24444-A71569 std::string dest, str; str = "valor1"; setQuotedCSV(dest, str); assertTrue( dest == "valor1" ); str = "valor 1"; setQuotedCSV(dest, str); assertTrue( dest == "\"valor 1\"" ); str = "valor,1"; setQuotedCSV(dest, str); assertTrue( dest == "\"valor,1\"" ); str = "valor\"1"; setQuotedCSV(dest, str); assertTrue( dest == "\"valor\"\"1\"" ); str = "valor,\"1\""; setQuotedCSV(dest, str); assertTrue( dest == "\"valor,\"\"1\"\"\"" ); } { // A56254 std::string res; setQuotedCSV( res, "" ); assertTrue( res == "" ); setQuotedCSV( res, "2" ); assertTrue( res == "2" ); setQuotedCSV( res, "4,5" ); assertTrue( res == "\"4,5\"" ); setQuotedCSV( res, "& _ ()" ); assertTrue( res == "\"& _ ()\"" ); } { // A61166 std::string res, str; res = str = "1 2 3 4 5 6"; { assertTrue ( res == "1 2 3 4 5 6" ); setQuotedCSV (res, str); assertTrue ( res != str ); assertTrue ( res == "\"1 2 3 4 5 6\"" ); } res = str = "1,2,3,4,5,6"; { assertTrue ( res == "1,2,3,4,5,6" ); setQuotedCSV (res, str); assertTrue ( res != str ); assertTrue ( res == "\"1,2,3,4,5,6\"" ); } res = str = "123\"456"; { assertTrue ( res == "123\"456" ); setQuotedCSV (res, str); assertTrue ( res != str ); assertTrue ( res == "\"123\"\"456\"" ); } res = str = "123456"; { assertTrue ( res == "123456" ); setQuotedCSV (res, str); assertTrue ( res == str ); assertTrue ( res == "123456" ); } res = str = "\""; { assertTrue ( res == "\"" ); setQuotedCSV (res, str); assertTrue ( res != str ); assertTrue ( res == "\"\"\"\"" ); } } } /// Test ==> \c getNextCSV(). void test_CSV::test_getNextCSV() { { // A73869-A74668 std::string prueba1 = "PSL,ITE,AMCY"; std::istringstream ist(prueba1); bool getn1 = getNextCSV(prueba1,ist); assertFalse (getn1); assertTrue (prueba1 == "PSL"); if (false) { { int error; //para inducir un error en CIN std::string res; std::cout << "Digite una letra para provocar un error"; std::cin >> error; bool fallo = getNextCSV(res,std::cin); assertTrue(!fallo); } { int error1; //para inducir un error en CIN std::string res1; std::cin >> error1; bool fallo1 = getNextCSV(res1,std::cin); assertTrue(!fallo1); } { int error2; //para inducir un error en CIN std::string res2; std::cin >> error2; bool fallo2 = getNextCSV(res2,std::cin); assertTrue(!fallo2); } { std::string prueba2 = "PSL\n"; std::istringstream ist2 (prueba2); bool getn1 = getNextCSV(prueba2,ist2); assertTrue (getn1); assertTrue (prueba2 == "PSL"); } } } { // A56254 std::string csv; { std::string str1 = "a"; std::istringstream ist1(str1); getNextCSV( csv, ist1 ); assertTrue( csv == "a" ); std::string str2 = "\"2,3\""; std::istringstream ist2(str2); getNextCSV( csv, ist2 ); assertTrue( csv == "2,3" ); std::string str3 = "\n"; std::istringstream ist3(str3); getNextCSV( csv, ist3 ); assertTrue( csv == "" ); } } } /// Test ==> \c trim(). void test_CSV::test_trim() { {{ // test::trim() std::string str; str = " a b "; trim(str); assertTrue( str == "a b" ); str = " a\nb "; trim(str); assertTrue( str == "a\nb" ); str = ""; trim(str); assertTrue( str == "" ); str = "\r\t\n "; trim(str); assertTrue( str == "" ); str = " a b "; trim(str); assertTrue( str == "a b" ); str = " ab " ; trim(str); assertTrue( str == "ab" ); }} } /// Test ==> \c trimCSV(). void test_CSV::test_trimCSV() { {{ // test::trimCSV() CSV_line csv("\"zero\", \"if \"\" 1\" , , \" 3xt\" \r\f"); std::string s; s=csv[0]; assertTrue( s == "zero" ); trimCSV(s); assertTrue( s == "zero" ); s=csv[1]; assertTrue( s == " \"if \"\" 1\" " ); trimCSV(s); assertTrue( s == "if \" 1" ); s=csv[2]; assertTrue( s == " " ); trimCSV(s); assertTrue( s == "" ); s=csv[3]; assertTrue( s == " \" 3xt\" \r\f" ); trimCSV(s); assertTrue( s == " 3xt" ); }} {{ // ["zero", "if "" 1" , , " 3xt" \r\n] CSV_line csv ("\"zero\", \"if \"\" 1\" , , \" 3xt\" \r\n"); std::vector cpy = csv; assertTrue( csv[0] == "zero" ); // [zero] assertTrue( csv[1] == " \"if \"\" 1\" " ); // [ "if "" 1" ] assertTrue( csv[2] == " " ); // [ ] assertTrue( csv[3] == " \" 3xt\" " ); // [ " 3xt" ] trimCSV( cpy[0] ); assertTrue( cpy[0] == "zero" ); // [zero] trimCSV( cpy[1] ); assertTrue( cpy[1] == "if \" 1" ); // [if " 1] trimCSV( cpy[2] ); assertTrue( cpy[2] == "" ); // [] trimCSV( cpy[3] ); assertTrue( cpy[3] == " 3xt" ); // [ 3xt] }} } #ifdef C_CSV #include "CSV.c" /// Test ==> \c trim() [C]. void test_CSV::test_trim_C() { #define googa std::cout << "trim(" << str << ")==> ["; std::cout << trim(str) << ']' << std::endl; {{ // test::trim_C() char str[20]; strcpy( str , " a b " ); assertTrue( strcmp( trim(str), "a b" ) == 0 ); strcpy( str , " a\nb " ); assertTrue( strcmp( trim(str), "a\nb") == 0 ); strcpy( str , "" ); assertTrue( strcmp( trim(str), "" ) == 0 ); strcpy( str , "\r\t\n " ); assertTrue( strcmp( trim(str), "" ) == 0 ); strcpy( str , " a b " ); assertTrue( strcmp( trim(str), "a b" ) == 0 ); strcpy( str , " ab " ); assertTrue( strcmp( trim(str), "ab" ) == 0 ); }} } /// Test ==> \c chop() [C]. void test_CSV::test_chop_C() { {{ // test::chop_C() char str[20]; char ch; strcpy( str , "12345") ; assertTrue( strcmp(str ,"12345")==0 ); chop(str,'0'); assertTrue( strcmp(str ,"12345")==0 ); for ( ch='5'; ch != '0'; --ch ) { assertTrue( str[strlen(str)-1] == ch ); chop(str,ch); } assertTrue( *str == 0 ); chop(str,'3'); assertTrue( *str == 0 ); }} } #endif /// Test ==> \c chop(). void test_CSV::test_chop() { {{ // test::chop() std::string str; char ch; str = "12345"; assertTrue( str == "12345" ); chop(str,'0'); assertTrue( str == "12345" ); for ( ch='5'; ch != '0'; --ch ) { assertTrue( str[str.size()-1] == ch ); chop(str,ch); } assertTrue( str == "" ); chop(str,'3'); assertTrue( str == "" ); }} } #include // basic_istringstream<> #ifdef English_dox /// Shows the correct way to read \c str usign \c sstream. /// - A \c basic_istringstream<> is used to read from \c str. /// - The result gets stored into \c res. /// - Reading is done using \c operator<<(). #endif #ifdef Spanish_dox /// Muestra la forma correcta de leer la hilera \c str usando \c sstream. /// - Se usa \c basic_istringstream<> para leer desde \c str. /// - El resultado leído se deposita en \c res. /// - La lectura se hace usando el operador \c operator<<(). #endif void mem_istring( std::string & res , std::string & str ) { // typedef basic_istringstream istringstream; { std::istringstream ist(str); // std::basic_istringstream ist(str); getNextCSV( res, ist ); } { res.clear(); std::basic_istringstream ist(str); // std::istringstream ist(str); char ch='%'; int i =0; while ( ! ist.eof() ) { // see http://www.horstmann.com/cpp/pitfalls.html ist >> ch; ++i; res += ch; ch = '!'; } // std::cout << '[' << res << ']' << '(' << i << ')' << std::endl; } { res.clear(); std::istringstream ist(str); // std::basic_istringstream ist(str); char ch='%'; int i =0; for (;;) { ist.get( ch ); ++i; if ( ist.eof() ) { // see http://www.horstmann.com/cpp/pitfalls.html break; } res += ch; ch = '!'; } // std::cout << '[' << res << ']' << '(' << i << ')' << std::endl; } { res.clear(); std::istringstream ist(str); // std::basic_istringstream ist(str); char ch='%'; int i =0; for (;;) { ist >> ch; ++i; if ( ist.eof() ) { // see http://www.horstmann.com/cpp/pitfalls.html break; } res += ch; ch = '!'; } // std::cout << '[' << res << ']' << '(' << i << ')' << std::endl; } } /// Test ==> \c istringstream(). void test_CSV::test_istringstream() { { std::string res, str = " 1 2 3 4 5 6 "; mem_istring( res , str ); assertTrue( res != "1234566" ); assertTrue( res != " 1 2 3 4 5 6 " ); assertTrue( res == "123456" ); } } #ifdef English_dox /// Main program that executes the tests. #endif #ifdef Spanish_dox /// Programa principal que ejecuta la prueba. #endif int main() { test_CSV tester; tester.run(); std::cout << tester.report(); return 0; } // EOF: test_CSV