/*-*- C++ -*-*/ /*****************************************************************************\ * Copyright (c) 2004 Mark Aylett * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, sublicense, and/or sell copies of the Software, and to permit * * persons to whom the Software is furnished to do so, subject to the * * following conditions: * * * * The above copyright notice and this permission notice shall be included * * in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN * * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * * USE OR OTHER DEALINGS IN THE SOFTWARE. * \*****************************************************************************/ static const char rcsid[] = "$Id: mar_test_cpp.cpp,v 1.16 2004/12/14 13:09:23 marayl Exp $"; #include #include #include #include #include // SUNWspro8 does not seem to find mktemp when cstdlib is included (using // stlport4). #include #if !defined(WIN32) #include #else // WIN32 #include #endif // WIN32 #define MAR_PAIR(k, d) { k, d, sizeof(d) } #define MAR_STR1 "abcdefghijklmnopqrstuvwxyz" #define MAR_STR2 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" namespace { const char str1[] = MAR_STR1; const size_t str1Len(sizeof(str1) - 1); const char str2[] = MAR_STR2; const size_t str2Len(sizeof(str2) - 1); const mar_pair_t pairs[] = { MAR_PAIR("familyname", "Aylett"), MAR_PAIR("givenname", "Mark"), MAR_PAIR("gender", "Male") }; const size_t metapairs(sizeof(pairs) / sizeof(pairs[0])); class error :public std::exception { char line_[5 + 10 + 1]; public: explicit error(unsigned int l) { std::strstream s(line_, sizeof(line_)); s << "Line " << l << std::ends; } const char* what() const MAR_NOTHROW { return line_; } }; void checkmeta(mar::archive& ar) { if (metapairs != mar::metapairs(ar)) throw error(__LINE__); for (size_t j(0); metapairs > j; ++j) { mar::pair pair; mar::meta(ar, pair, j); if (0 != strcmp(pair.key(), pairs[j].key_)) throw error(__LINE__); if (pair.size() != pairs[j].size_) throw error(__LINE__); if (0 != memcmp(pair.data(), pairs[j].data_, pairs[j].size_)) throw error(__LINE__); } for (size_t k(0); metapairs > k; ++k) { size_t size; const void* data = mar::meta(ar, pairs[k].key_, size); if (size != pairs[k].size_) throw error(__LINE__); if (0 != memcmp(data, pairs[k].data_, pairs[k].size_)) throw error(__LINE__); } for (size_t l(0); metapairs > l; ++l) { mar::key k; if (!mar::tokey(ar, k, l)) throw error(__LINE__); if (k != pairs[l].key_) throw error(__LINE__); } } void metatest(mar::archive ar) { for (size_t i(0); metapairs > i; ++i) mar::setmeta(ar, mar::pair(pairs[i])); checkmeta(ar); size_t ord(mar::unsetmeta(ar, pairs[1].key_).first); if (1 != ord) throw error(__LINE__); try { mar::meta(ar, pairs[1].key_); throw error(__LINE__); } catch (...) { } mar::removepairs(ar); if (0 != mar::metapairs(ar)) throw error(__LINE__); } void metatest(const char* dst, const char* src) { metatest(mar::create()); metatest(mar::open(dst, mar::rdwr | mar::creat, 0664)); } void usertest(mar::archive ar) { mar::setuser(ar, str1); size_t size; const void* user = mar::user(ar, size); if (size != str1Len) throw error(__LINE__); if (0 != memcmp(user, str1, size)) throw error(__LINE__); } void usertest(const char* dst, const char* src) { usertest(mar::create()); usertest(mar::open(dst, mar::rdwr | mar::creat, 0664)); } void inserttest(mar::archive ar, const char* src) { mar::insert(ar, src); size_t size; const void* user = mar::user(ar, size); if (size != str1Len) throw error(__LINE__); if (0 != memcmp(user, str1, size)) throw error(__LINE__); } void inserttest(const char* dst, const char* src) { std::ofstream strm(src, std::ios::out | std::ios::trunc | std::ios::binary); if (!strm) throw error(__LINE__); strm << str1 << std::flush; strm.close(); inserttest(mar::create(), src); inserttest(mar::open(dst, mar::rdwr | mar::creat, 0664), src); } void extracttest(const char* dst, mar::archive ar) { mar::setuser(ar, str1); mar::extract(ar, dst); std::ifstream strm(dst, std::ios::in | std::ios::binary); char buf[str1Len]; strm.read(buf, str1Len); if (0 != memcmp(buf, str1, str1Len)) throw error(__LINE__); } void extracttest(const char* dst, const char* src) { extracttest(dst, mar::create()); extracttest(dst, mar::open(src, mar::rdwr | mar::creat, 0664)); } void copytest(mar::archive ar) { mar::setuser(ar, str1); mar::archive dst(mar::create()); mar::copy(dst, ar); size_t size; const void* user = mar::user(dst, size); if (size != str1Len) throw error(__LINE__); if (0 != memcmp(user, str1, size)) throw error(__LINE__); } void copytest(const char* dst, const char* src) { copytest(mar::create()); copytest(mar::open(src, mar::rdwr | mar::creat, 0664)); } void opencopytest(const char* dst, const char* src) { mar::archive ar(mar::open(src, mar::wronly | mar::creat, 0664)); mar::setuser(ar, str1); ar.release(); ar = mar::opencopy(dst, src); size_t size; const void* user = mar::user(ar, size); if (size != str1Len) throw error(__LINE__); if (0 != memcmp(user, str1, size)) throw error(__LINE__); } void iteratortest(mar::archive ar) { mar::index index(ar); for (size_t i(0); metapairs > i; ++i) index.setmeta(mar::pair(pairs[i])); checkmeta(ar); if ((size_t)(index.end() - index.begin()) != metapairs) throw error(__LINE__); for (size_t j(0); metapairs > j; ++j) if (index.begin()[j] != pairs[j].key_) throw error(__LINE__); mar::index::const_reverse_iterator itR(index.rbegin()), endR(index.rend()); for (; itR != endR; ++itR) { size_t ord(mar::toord(itR)); if (*itR != pairs[ord].key_) throw error(__LINE__); if (0 != memcmp(index.meta(itR), pairs[ord].data_, pairs[ord].size_)) throw error(__LINE__); } mar::index::const_iterator it(index.find("givenname")); if (it == index.end()) throw error(__LINE__); if (0 != memcmp(index.meta(it), pairs[1].data_, pairs[1].size_)) throw error(__LINE__); if (index.find("badkey") != index.end()) throw error(__LINE__); } void iteratortest(const char* dst, const char* src) { iteratortest(mar::create()); iteratortest(mar::open(dst, mar::rdwr | mar::creat, 0664)); } void streamtest(mar::archive ar) { mar::iostream strm(ar); strm << str1 << str2; strm << std::endl; strm.seekg(str1Len); std::string out; std::getline(strm, out); if (out != str2) throw error(__LINE__); } void streamtest(const char* dst, const char* src) { streamtest(mar::create()); streamtest(mar::open(dst, mar::rdwr | mar::creat, 0664)); } struct test { const char* name_; void (*test_)(const char*, const char*); } tests[] = { { "meta functions", metatest }, { "user functions", usertest }, { "insert function", inserttest }, { "extract function", extracttest }, { "copy function", copytest }, { "opencopy function", opencopytest }, { "iterator class", iteratortest }, { "stream class", streamtest } }; bool run(const test& t, const char* dst, const char* src) { bool result(true); try { std::cout << "Testing " << t.name_ << "... "; (*t.test_)(dst, src); std::cout << "OK\n"; } catch (const std::exception& e) { std::cout << "Error: " << e.what() << std::endl; result = false; } catch (...) { std::cout << "Error: Unknown exception\n"; result = false; } unlink(dst); unlink(src); return result; } } int main(int argc, char* argv[]) { static const size_t total(sizeof(tests) / sizeof(tests[0])); char dst[] = "dst.XXXXXX"; char src[] = "src.XXXXXX"; if (!mktemp(dst) || !mktemp(src)) { std::cerr << "Failed to generate temporary names\n"; return 1; } size_t failed(0); for (size_t i(0); total > i; ++i) if (!run(tests[i], dst, src)) ++failed; if (failed) { std::cout << failed << " out of " << total << " tests FAILED\n"; return 1; } std::cout << "All tests PASSED\n"; return 0; }