pilo::i32_t functional_test_constructor_3_char(void* param) { M_UNUSED(param); const char* str = "1234567890"; size_t len = pilo::core::string::string_util::length(str); pilo::core::string::fixed_astring<32> str0(str, len); pilo::core::string::fixed_astring<64> str1(str0); if (str0.size() != str1.length()) { return -1; } if (::memcmp(str0.c_str(), str1.c_str(), (len + 1)*sizeof(char)) != 0) { return -2; } const char* cstr2 = "012345678901234567890123456789"; len = pilo::core::string::string_util::length(cstr2); pilo::core::string::fixed_astring<112> str2(cstr2); pilo::core::string::fixed_astring<32> str3(str2); if (str3.size() != len) { return -3; } if (::memcmp(str3.c_str(), str2.c_str(), (len + 1) * sizeof(char)) != 0) { return -4; } return 0; }
int main() { std::cout<< "hello, this is mystring plugin" << std::endl; MyString str0("AAA"); std::cout << "str0="<< str0 << std::endl; MyString str1(NULL); std::cout << "str1="<< str1 << std::endl; //MyString str2; // compile error, cause lacking of default constructor //std::cout << "str2="<< str2 << std::endl; str0 += "BBB"; std::cout << "str0="<< str0 << std::endl; MyString str3("CCC"); str0 += str3; std::cout << "str0="<< str0 << std::endl; MyString str4("DDD"); MyString str5("DDD"); std::cout << "str4==str5:"<< ((str4==str5)? "true":"false") << std::endl; std::vector<MyString> vec; vec.push_back(MyString("aaa")); vec.push_back(MyString("bbb")); std::cout << "vec:"<< vec[0] << ", " << vec[1] << std::endl; return 0; }
pilo::i32_t functional_test_constructor_4_char(void* param) { M_UNUSED(param); std::string stdstr0 = "012345678901234567890123456789"; pilo::core::string::fixed_astring<31> str0(stdstr0); if (stdstr0.length() != stdstr0.length()) { return -1; } if (::memcmp(stdstr0.c_str(), str0.c_str(), str0.size()) != 0) { return -2; } std::string stdstr1 = "0123456789"; pilo::core::string::fixed_astring<11> str3 = stdstr1; if (::memcmp(str3.c_str(), "0123456789", 11) != 0) { return -9; } if (str3.length() != 10) { return -10; } return 0; }
pilo::i32_t functional_test_constructor_2_char(void* param) { M_UNUSED(param); char str_buffer[MC_STR0_SIZE + 1]; pilo::core::string::string_util::set(str_buffer, '1', MC_STR0_SIZE); pilo::core::string::fixed_astring<MC_STR0_SIZE + 1> str0(str_buffer, MC_STR0_SIZE); if (str0.size() != MC_STR0_SIZE) { return -1; } if (::memcmp(str_buffer, str0.c_str(), sizeof(str_buffer) != 0)) { return -2; } pilo::core::string::fixed_astring<10> str2("1234567890", 10); if (::memcmp(str2.c_str(), "1234567890", 11) != 0) { return -9; } if (str2.length() != 10) { return -10; } return 0; }
pilo::i32_t functional_test_constructor_1_char(void* param) { M_UNUSED(param); char str_buffer[MC_STR0_SIZE]; pilo::core::string::string_util::m_set(str_buffer, 0, MF_COUNT_OF(str_buffer)); pilo::core::string::string_util::m_set(str_buffer, 1, MF_COUNT_OF(str_buffer) - 1); str_buffer[0] = '$'; str_buffer[MC_STR0_SIZE - 2] = '#'; pilo::core::string::fixed_astring<MC_STR0_SIZE> str0(str_buffer); if (str0.length() != 8191) { return -1; } if (str0.size() != 8191) { return -2; } if (str0.empty()) { return -4; } if (str0.front() != '$') { return -5; } if (str0.back() != '#') { return -6; } if (::memcmp(str0.c_str(), str_buffer, MC_STR0_SIZE) != 0) { return -7; } pilo::core::string::fixed_astring<MC_STR0_SIZE> str1(""); if (str1.length() != 0) { return -8; } pilo::core::string::fixed_astring<10> str2 = "1234567890"; if (::memcmp(str2.c_str(), "1234567890", 11) != 0) { return -9; } return 0; }
void testSplit(int& iRet) { LIST_AString names; AString str0("path0/path1/path2"); str0.split(names, '/'); ASSERT_UNIT_TEST(names.size() == 3, "AString::split", "0", iRet); LIST_AString::iterator it = names.begin(); ASSERT_UNIT_TEST(!(*it).compare("path0"), "AString::split", "1", iRet); ++it; ASSERT_UNIT_TEST(!(*it).compare("path1"), "AString::split", "2", iRet); ++it; ASSERT_UNIT_TEST(!(*it).compare("path2"), "AString::split", "3", iRet); ++it; ASSERT_UNIT_TEST(it == names.end(), "AString::split", "3a", iRet); str0.assign("\\\\\\\\path0\\\\\\path1\\\\path2\\"); names.clear(); str0.split(names, '\\'); ASSERT_UNIT_TEST(names.size() == 3, "AString::split", "4", iRet); it = names.begin(); ASSERT_UNIT_TEST(!(*it).compare("path0"), "AString::split", "5", iRet); ++it; ASSERT_UNIT_TEST(!(*it).compare("path1"), "AString::split", "6", iRet); ++it; ASSERT_UNIT_TEST(!(*it).compare("path2"), "AString::split", "7", iRet); ++it; ASSERT_UNIT_TEST(it == names.end(), "AString::split", "8", iRet); str0.assign("_path0_path1_path2"); names.clear(); str0.split(names, '_'); ASSERT_UNIT_TEST(names.size() == 3, "AString::split", "9", iRet); it = names.begin(); ASSERT_UNIT_TEST(!(*it).compare("path0"), "AString::split", "10", iRet); ++it; ASSERT_UNIT_TEST(!(*it).compare("path1"), "AString::split", "11", iRet); ++it; ASSERT_UNIT_TEST(!(*it).compare("path2"), "AString::split", "12", iRet); ++it; ASSERT_UNIT_TEST(it == names.end(), "AString::split", "13", iRet); }
void testTrim(int& iRet) { //a_Trimming routines AString str0("ABCDEFG"); str0.stripLeading("CBA"); ASSERT_UNIT_TEST(!str0.compare("DEFG"), "AString::stripLeading", "0", iRet); str0 = ".&.A.4.1."; str0.stripLeading(".&%@.41AB"); ASSERT_UNIT_TEST(str0.isEmpty(), "AString::stripLeading", "1", iRet); str0 = "ABC123"; str0.stripLeading(" "); ASSERT_UNIT_TEST(str0 == "ABC123", "AString::stripLeading", "2", iRet); str0 = " "; str0.stripLeading(" "); ASSERT_UNIT_TEST(str0.isEmpty(), "AString::stripLeading", "3", iRet); str0 = "1"; str0.stripLeading(" "); ASSERT_UNIT_TEST(str0 == "1", "AString::stripLeading", "4", iRet); str0 = "12\t3.4 5 . \t "; str0.stripTrailing(" .\t"); ASSERT_UNIT_TEST(!str0.compare("12\t3.4 5"), "AString::stripTrailing", "0", iRet); str0 = ".&.A.4.1."; str0.stripTrailing(".&%@.41AB"); ASSERT_UNIT_TEST(str0.isEmpty(), "AString::stripTrailing", "1", iRet); str0 = " "; str0.stripTrailing(" "); ASSERT_UNIT_TEST(str0.isEmpty(), "AString::stripTrailing", "2", iRet); str0 = "ABC123"; str0.stripTrailing(" "); ASSERT_UNIT_TEST(str0 == "ABC123", "AString::stripTrailing", "3", iRet); str0 = "1"; str0.stripTrailing(" "); ASSERT_UNIT_TEST(str0 == "1", "AString::stripTrailing", "4", iRet); str0 = "172.20.24.34"; str0.stripEntire("."); ASSERT_UNIT_TEST(str0 == "172202434", "AString::stripEntire", "0", iRet); str0 = "How now brown cow?"; str0.stripEntire("ow"); ASSERT_UNIT_TEST(str0 == "H n brn c?", "AString::stripEntire", "1", iRet); }
int CTest::test_caseInsensitiveButCasePreserving(int argc, char* argv[]) { AutoPtr<IRawHeaders> h; CRawHeaders::New((IRawHeaders**)&h); String str0("Content-Type"); String str1("text/plain"); h->Add(str0, str1); // Case-insensitive: String strOut; h->Get(str0, &strOut); Boolean flag = strOut.Equals(str1); assert(flag == TRUE); String str2("Content-type"); h->Get(str2, &strOut); flag = strOut.Equals(str1); assert(flag == TRUE); String str3("content-type"); h->Get(str3, &strOut); flag = strOut.Equals(str1); assert(flag == TRUE); String str4("CONTENT-TYPE"); h->Get(str4, &strOut); flag = strOut.Equals(str1); assert(flag == TRUE); // ...but case-preserving: AutoPtr<IMap> innerMap; h->ToMultimap((IMap**)&innerMap); AutoPtr<ISet> keyset; innerMap->KeySet((ISet**)&keyset); AutoPtr<ArrayOf<IInterface*> > array; keyset->ToArray((ArrayOf<IInterface*>**)&array); AutoPtr<ICharSequence> cs = (ICharSequence*)ICharSequence::Probe((*array)[0]); String str5(String("Content-Type")); cs->ToString(&strOut); flag = strOut.Equals(str5); assert(flag == TRUE); // We differ from the RI in that the Map we return is also case-insensitive. // Our behavior seems more consistent. (And code that works on the RI will work on Android.) // AutoPtr<ICharSequence> cs1; // CString::New(String("Content-Type"), (ICharSequence**)&cs1); // AutoPtr<IInterface> value; // innerMap->Get(cs1, (IInterface**)&value); // assertEquals(Arrays.asList("text/plain"), h.toMultimap().get("Content-Type")); // assertEquals(Arrays.asList("text/plain"), h.toMultimap().get("Content-type")); // RI fails this. }
static void test_static_string_equal() { my_static_string_t str0("hello"); my_static_string_t str0b("hello"); my_static_string_t str1("hello!"); my_static_string_t str2("hell"); my_static_string_t a("a"); my_static_string_t b("b"); UF_TEST(str0 == str0b); UF_TEST(!(str0 == str1)); UF_TEST(str0 != str1); UF_TEST(str0 != str2); UF_TEST( a < b); UF_TEST(!(a < a)); UF_TEST(!(b < a)); }
TEST(EditDistanceBitParallelTest, CalculateEditDistance) { typedef edit_distance_bit_parallel::EditDistanceBitParallel<uint8_t, uint64_t> TestEditDistanceBitParallel; TestEditDistanceBitParallel::Char alphabet_size = 4; TestEditDistanceBitParallel::Char str0_values[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; std::vector<TestEditDistanceBitParallel::Char> str0(&str0_values[0], &str0_values[0] + sizeof(str0_values) / sizeof(str0_values[0])); TestEditDistanceBitParallel::Char str1_values[] = { 0, 0, 2, 3, 0, 1, 2, 3 }; std::vector<TestEditDistanceBitParallel::Char> str1(&str1_values[0], &str1_values[0] + sizeof(str1_values) / sizeof(str1_values[0])); std::vector<TestEditDistanceBitParallel::Word> str0_p_eq(alphabet_size, 0); TestEditDistanceBitParallel editdistance_bit_parallel; editdistance_bit_parallel.BuildPeq(&str0[0], str0.size(), &str0_p_eq[0]); TestEditDistanceBitParallel::Distance distance = editdistance_bit_parallel.CalculateEditDistance( &str0_p_eq[0], &str1[0], str1.size()); EXPECT_EQ(1, distance); }
pilo::i32_t functional_test_constructor_6_char(void* param) { M_UNUSED(param); float fv1 = -789.123f; pilo::core::string::fixed_astring<32> str0(fv1); float fv2 = (float) ::atof(str0.c_str()); if (fv1 != fv2) { return -1; } double dv1 = -789.123456f; pilo::core::string::fixed_astring<32> str1(dv1); double dv2 = (float) ::atof(str1.c_str()); if (dv1 != dv2) { return -1; } return 0; }
// The copy constructor used to be broken for headers with multiple values. // http://code.google.com/p/android/issues/detail?id=6722 int CTest::test_copyConstructor(int argc, char* argv[]) { AutoPtr<IRawHeaders> h1; CRawHeaders::New((IRawHeaders**)&h1); String str0("key"); String str1("value1"); String str2("value2"); h1->Add(str0, str1); h1->Add(str0, str2); AutoPtr<IMap> objMap; h1->ToMultimap((IMap**)&objMap); AutoPtr<IRawHeaders> h2; AutoPtr<IRawHeadersHelper> rawHeadersHelper; CRawHeadersHelper::AcquireSingleton((IRawHeadersHelper**)&rawHeadersHelper); rawHeadersHelper->FromMultimap(objMap, (IRawHeaders**)&h2); Int32 length; h2->Length(&length); assert(2 == length); String strOut; h2->GetFieldName(0, &strOut); Boolean flag = strOut.Equals(str0); assert(flag == TRUE); h2->GetValue(0, &strOut); flag = strOut.Equals(str1); assert(flag == TRUE); h2->GetFieldName(1, &strOut); flag = strOut.Equals(str0); assert(flag == TRUE); h2->GetValue(1, &strOut); flag = strOut.Equals(str2); assert(flag == TRUE); }
pilo::i32_t functional_test_constructor_5_char(void* param) { M_UNUSED(param); pilo::core::string::fixed_astring<10> str0(1234567); if (str0.size() != 7) { return -1; } pilo::core::string::fixed_astring<10> str1 = 987654321; if (str1.size() != 9) { return -3; } str1 = str0; if (str1.size() != 7) { return -1; } pilo::core::string::fixed_astring<11> stri64(9876543210LL); if (stri64.size() != 10) { return -1; } pilo::u64_t u64vv= 19876543210U; pilo::core::string::fixed_astring<12> stru64(u64vv); if (stru64.size() != 11) { return -1; } return 0; }
void parseOptions(int argc, char *org_argv[], IObjContainer &ioc) { GetOpt opt; opt.opterr=0; int copt; std::string str0("null"); std::string str1; // std::vector<std::string> inputFilename; std::vector<std::string> outputFilename; // working with std::string is preferred std::vector<std::string> argv; for( int i=0 ; i < argc ; ++i) argv.push_back( org_argv[i] ); // read options from file? readOptions(argv); int sz=argv.size(); // printing is split, so remember bool isPrintTest=false; // getopt expects char*[]. char **pargv = new char* [sz+1] ; for( int i=0 ; i < sz ; ++i ) pargv[i] = const_cast<char*>(argv[i].c_str()); while( (copt = opt.getopt(sz, pargv, "f:p:t:v:<--cpu-time><--help><--post><--printTest>")) != -1 ) { if( opt.longOption > 0 ) str0=opt.longOption; if( opt.longOption && str0 == "--help" ) { Base::help(); // CellStatistics::help(); FD_interface::help(); InFile::help(); // Oper::help(); // OutFile::help(); QA::help(); // TimeControl::help(); exit(1); } if( opt.longOption && str0 == "--cpu-time" ) { isCPU_time=true; continue; } if( opt.longOption && str0 == "--post" ) { isPostProc=true; continue; } if( opt.longOption && str0 == "--printTest" ) { isPrintTest=true; continue; } switch ( copt ) { case 'f': ::NC_FILENAME = opt.optarg ; break; case 'p': ::NC_PATH = opt.optarg ; break; case 't': ::TABLE_PATH = opt.optarg ; break; default: // description(); break; } } // Note: pargv are pointers to argv items. std::vector<std::string> aargv; for( int i=opt.optind ; i < sz ; ++i) aargv.push_back( pargv[i] ); argv = aargv ; delete[] pargv ; // parse argv for instructions of making objects // and their linkage. Parse parse(argv); std::vector<std::vector<std::string> > linkList = parse.getLinkList(); if( isPrintTest ) parse.printList(); // exits // objects are created makeObject(linkList, ioc); // apply parameters to objects setObjProperties(linkList, ioc); linkObj(linkList, ioc); scanGdRelation(linkList, ioc); return ; }
bool Consistency::check(Variable &dataVar, std::string entryID) { // return value is true, when there is not a project table, yet. // Search the project table for an entry // matching the varname and frequency (account also rotated). // Open project table. Mode: read std::string str0(projectTableFile.getFile()); std::ifstream ifs(str0.c_str(), std::ios::in); if( !ifs.is_open() ) // file does not exist return true; // causes writing of a new entry size_t sz_PV = entryID.size(); std::string t_md; bool notFound=true; while( getline(ifs, str0) ) { if( str0.substr(0,sz_PV) != entryID ) continue; // found a valid entry notFound=false; t_md = hdhC::stripSides(str0) ; // read aux-lines while( getline(ifs, str0) ) { str0 = hdhC::stripSides(str0) ; if( str0.substr(0,4) != "aux=" ) goto BREAK ; // found the end of the entry t_md += '\n'; t_md += str0 ; } } if(notFound) return true; // entry not found BREAK: // close the project table ifs.close(); // get meta data info from the file std::string f_md; getMetaData(dataVar, entryID, f_md); // Comparison of meta-data from the project table and the file, respectively. // Note that the direct comparison fails because of different spaces. // Deviating distribution of auxiliaries and attributes is tolerated. // Use index-vector for book-keeping. // Meaning: x=split, t=file, t=table, a=attribute, eq=(att-name,att-value) Split splt_xt(t_md, '\n'); Split splt_xf(f_md, '\n'); size_t xt_sz=splt_xt.size(); size_t xf_sz=splt_xf.size(); std::vector<std::string> xf; for( size_t i=0 ; i < xf_sz ; ++i ) xf.push_back( hdhC::stripSides(splt_xf[i]) ); std::vector<std::string> xt; for( size_t i=0 ; i < xt_sz ; ++i ) xt.push_back( hdhC::stripSides(splt_xt[i]) ); // simple test for identity if( xt_sz == xf_sz ) { bool is=true; for( size_t i=0 ; i < xt_sz ; ++i ) { if( xt[i] != xf[i] ) { is=false ; break; } } if( is ) return false; } // store indexes std::vector<int> xf_ix; for( size_t i=0 ; i < xf_sz ; ++i ) xf_ix.push_back( i ); std::vector<int> xt_ix; for( size_t i=0 ; i < xt_sz ; ++i ) xt_ix.push_back( i ); // At first, test whether total auxiliary entries are identical. for( size_t i=0 ; i < xt_sz ; ++i ) { for( size_t j=0 ; j < xf_sz ; ++j ) { // only test strings for indexes still to be checked if( xt_ix[i] > -1 && xf_ix[i] > -1 && xf[j] == xt[i] ) { xt_ix[i] = -1; xf_ix[j] = -1; break; } } } Split xf_a; // meta-data from file xf_a.setSeparator(','); Split xt_a; // from the table xt_a.setSeparator(','); Split xf_eq; xf_eq.setSeparator('='); Split xt_eq; xt_eq.setSeparator('='); bool isMissAux; for( size_t ixt=0 ; ixt < xt_ix.size() ; ++ixt ) { int jt=xt_ix[ixt]; if( jt < 0 ) continue; // passed already a check isMissAux=true; //split at comma xt_a = xt[jt] ; for( size_t ixf=0 ; ixf < xf_ix.size() ; ++ixf ) { int jf=xf_ix[ixf]; if( jf < 0 ) continue; // passed already a check //split at comma xf_a = xf[jf] ; // compare the names of the auxiliaries if( xf_a[0] != xt_a[0] ) continue; isMissAux=false; // scan the attributes for( size_t ita=1 ; ita < xt_a.size() ; ++ita ) { // split at '=' xt_eq = xt_a[ita] ; bool isAttMissing=true; for( size_t ifa=1 ; ifa < xf_a.size() ; ++ifa ) { // split at '=' xf_eq = xf_a[ifa] ; if( xt_eq[0] == xf_eq[0] ) // found identical attribute names { isAttMissing=false; if( xt_eq[1] == xf_eq[1] ) // found identical values break; // try the next attribute // this is a very special one for time: one wit separator T and/or Z // the other one without std::string auxName; if( xt_a[0].substr(0,4) == "aux=" ) auxName = xt_a[0].substr(4) ; else auxName = xt_a[0] ; if( auxName == "time" ) { Split x_tt(xt_eq[1]," TZ",true) ; Split x_ff(xf_eq[1]," TZ",true) ; if( x_tt.size() == x_ff.size() ) { bool is=true; for(size_t c=0 ; c < x_tt.size() ; ++c ) if( x_tt[c] != x_ff[c] ) is=false; if(is) break; } } // different values --> annotation status=true; std::string key("8_8"); if( notes->inq( key, dataVar.name ) ) { std::string capt; if( xt_a[0].substr(0,4) == "aux=" ) { capt = "auxiliary "; capt += hdhC::tf_var(auxName, hdhC::colon) ; } else capt += hdhC::tf_var(xt_a[0], hdhC::colon) ; if( xt_eq[0] == "values" ) capt += "data has changed"; else { capt += xt_eq[0] ; capt += " has changed from"; capt += hdhC::tf_val(xt_eq[1]) ; capt += " to"; capt += hdhC::tf_val(xf_eq[1]) ; } capt += " across experiment or sub-temporal files"; (void) notes->operate(capt) ; notes->setCheckMetaStr( "FAIL" ); } break; // try next } } if( isAttMissing ) { status=true; std::string key("8_7"); if( notes->inq( key, dataVar.name ) ) { std::string capt; if( xt_a[0].substr(0,4) == "aux=" ) { capt = "auxiliary "; capt += hdhC::tf_var(xt_a[0].substr(4), hdhC::colon) ; } else capt += hdhC::tf_var(xt_a[0], hdhC::colon) ; if( xt_eq[0] == "values" ) capt += "no data"; else { capt += hdhC::tf_att(xt_eq[0]); capt += "is missing " ; } if( qa->currQARec ) capt += "across sub-temporal files"; else capt += "across experiments"; (void) notes->operate(capt) ; notes->setCheckMetaStr( "FAIL" ); } } } } if( isMissAux ) { status=true; std::string key("8_4"); if( notes->inq( key, dataVar.name ) ) { std::string capt; if( xt_a[0].substr(0,4) == "aux=" ) { capt = "auxiliary "; capt += hdhC::tf_var(xt_a[0].substr(4), hdhC::colon) ; } else capt += hdhC::tf_var(xt_a[0], hdhC::colon) ; capt += "missing across experiments or sub-temporal files"; (void) notes->operate(capt) ; notes->setCheckMetaStr( "FAIL" ); } } } // test for missing attributes in the table (reversed for-loops) bool isAddAux=true; for( size_t ixf=0 ; ixf < xf_ix.size() ; ++ixf ) { int jf=xf_ix[ixf]; if( jf < 0 ) continue; // passed already a check isAddAux=true; //split at comma xf_a = xf[jf] ; for( size_t ixt=0 ; ixt < xt_ix.size() ; ++ixt ) { int jt=xt_ix[ixt]; if( jt < 0 ) continue; // passed already a check //split at comma xt_a = xt[jt] ; // compare the names of the auxiliaries if( xf_a[0] != xt_a[0] ) continue; // found identical auxiliaries isAddAux=false; // scan the attributes for( size_t ifa=1 ; ifa < xf_a.size() ; ++ifa ) { // split at '=' xf_eq = xf_a[ifa] ; bool isAddAtt=true; for( size_t ita=1 ; ita < xt_a.size() ; ++ita ) { // split at '=' xt_eq = xt_a[ita] ; if( xt_eq[0] == xf_eq[0] ) // found identical attribute names { isAddAtt=false; break; } } if( isAddAtt ) { status=true; // additional attribute of auxiliary in the file std::string key("8_6"); if( notes->inq( key, dataVar.name ) ) { std::string capt; if( xt_a[0].substr(0,4) == "aux=" ) { capt = "auxiliary "; capt += hdhC::tf_var(xf_a[0].substr(4), hdhC::colon) ; } else capt += hdhC::tf_var(xf_a[0], hdhC::colon) ; if( xt_eq[0] == "values" ) { capt += "additional data across experiments or sub-temporal files"; } else { capt += hdhC::tf_att(xf_eq[0]); capt += "is new across experiments or sub-temporal files"; } (void) notes->operate(capt) ; notes->setCheckMetaStr( "FAIL" ); } } } } if( isAddAux ) { status=true; std::string key("8_5"); if( notes->inq( key, dataVar.name) ) { std::string capt("additional auxiliary "); if( xf_a[0].size() > 4 ) capt += hdhC::tf_var(xf_a[0].substr(4)) ; else capt += hdhC::tf_var(xf_a[0]) ; capt += "across experiments or sub-temporal files"; (void) notes->operate(capt) ; notes->setCheckMetaStr( "FAIL" ); } } } return false; }