diff options
Diffstat (limited to 'cpp/test/IceUtil/stacktrace/Client.cpp')
-rw-r--r-- | cpp/test/IceUtil/stacktrace/Client.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/cpp/test/IceUtil/stacktrace/Client.cpp b/cpp/test/IceUtil/stacktrace/Client.cpp new file mode 100644 index 00000000000..53edbaf4ec2 --- /dev/null +++ b/cpp/test/IceUtil/stacktrace/Client.cpp @@ -0,0 +1,261 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/StringUtil.h> +#include <TestCommon.h> + +#include <fstream> + +using namespace IceUtil; +using namespace std; + +#if defined(__GNUC__) && !defined(__sun) && !defined(__FreeBSD__) && !defined(__MINGW32__) && \ + !(defined(__ARMEL__) && defined(__linux)) +# define HAS_STACK_TRACES +#endif + +#if defined(_WIN32) && !defined(ICE_OS_WINRT) && !defined(__MINGW32__) +# define HAS_STACK_TRACES +#endif + +namespace IceUtilInternal +{ +extern bool ICE_UTIL_API printStackTraces; +} + +namespace +{ +class Thrower : public IceUtil::Shared +{ +public: + + Thrower() : _idx(0) + { + } + + void first() + { + _idx++; + second(); + } + + void second() + { + _idx++; + third(); + } + + void third() + { + _idx++; + forth(); + } + + void forth() + { + _idx++; + fifth(); + } + + void fifth() + { + _idx++; + throw IceUtil::NullHandleException(__FILE__, __LINE__); + } + +private: + + int _idx; +}; +typedef IceUtil::Handle<Thrower> ThrowerPtr; + +#ifdef _WIN32 +string +getIceHome() +{ + vector<wchar_t> buf(256); + DWORD ret = GetEnvironmentVariableW(L"ICE_HOME", &buf[0], static_cast<DWORD>(buf.size())); + string iceHome = (ret > 0 && ret < buf.size()) ? IceUtil::wstringToString(&buf[0]) : string(""); + if(!iceHome.empty()) + { + return iceHome; + } + else + { + HKEY hKey; + + string key = string("SOFTWARE\\ZeroC\\Ice ") + ICE_STRING_VERSION; + const wstring keyName = IceUtil::stringToWstring(key); + + if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + { + return ""; + } + + WCHAR buf[512]; + DWORD bufSize = sizeof(buf); + if(RegQueryValueExW(hKey, L"InstallDir", 0, NULL, (LPBYTE)buf, &bufSize) != ERROR_SUCCESS) + { + return ""; + } + return IceUtil::wstringToString(wstring(buf)); + } +} +#endif + +#if defined(__APPLE__) +void +standardizeVersion(string& str) +{ + string v1("3.6.1"); + string v2("36"); + size_t pos = 0; + while((pos = str.find(v1, pos)) != string::npos) + { + str.replace(pos, v1.length(), v2); + pos += v2.length(); + } +} +#else +vector<string> +splitLines(const string& str) +{ + vector<string> result; + istringstream is(str); + string line; + while(std::getline(is, line)) { + result.push_back(line); + }; + return result; +} +#endif +} + +int main(int argc, char* argv[]) +{ +#ifdef HAS_STACK_TRACES + + bool optimized = false; +#ifdef NDEBUG + optimized = true; +#endif + +#if defined(_WIN32) + bool binDist = false; + vector<wchar_t> buf(256); + DWORD ret = GetEnvironmentVariableW(L"USE_BIN_DIST", &buf[0], static_cast<DWORD>(buf.size())); + string valstr = (ret > 0 && ret < buf.size()) ? IceUtil::wstringToString(&buf[0]) : string(""); + binDist = valstr == "yes"; + + if(binDist) + { + // + // For Windows we only run the test against bindist if PDBs were installed + // + string pdb = getIceHome() + "\\bin\\icebox.pdb"; + if(!ifstream(pdb)) + { + cout << "Test requires PDBs to be installed" << endl; + return EXIT_SUCCESS; + } + } + else if(optimized) + { + // + // Only support debug srcdist Windows builds + // + return EXIT_SUCCESS; + } +#endif + + cout << "checking stacktrace... "; + + IceUtilInternal::printStackTraces = true; + + string filename = "StackTrace."; + +#if defined(__APPLE__) + bool binDist = false; + const char* s = getenv("USE_BIN_DIST"); + if(s && *s != '\0') + { + binDist = string(s) == "yes"; + } + + if(binDist && !optimized) + { + filename += "debug-release"; + } + else if(optimized) +#else + if(optimized) +#endif + { + filename += "release"; +#if defined(_MSC_VER) && (_MSC_VER == 1800) + filename += "-vc120"; +#endif + } + else + { + filename += "debug"; + } + +#if defined(_WIN32) + filename += ".Win32"; +#elif defined(__APPLE__) + filename += ".OSX"; +#else + filename += ".Linux"; +#endif + + ifstream ifs(filename.c_str()); + stringstream sstr; + sstr << ifs.rdbuf(); +#if defined(__APPLE__) + string expected = sstr.str(); + standardizeVersion(expected); +#else + vector<string> expected = splitLines(sstr.str()); +#endif + + ThrowerPtr thrower = new Thrower(); + try + { + thrower->first(); + } + catch(const IceUtil::Exception& ex) + { + string stack = ex.ice_stackTrace(); +#ifdef __APPLE__ + standardizeVersion(stack); + if(expected.size() < stack.size()) + { + test(stack.compare(0, expected.size(), expected) == 0); + } + else + { + test(stack == expected); + } +#else + vector<string> actual = splitLines(stack); + test(expected.size() <= actual.size()); + for(size_t i = 0; i < expected.size(); ++i) + { + test(actual[i].find(expected[i]) != string::npos); + } +#endif + } + cout << "ok" << endl; +#else + cout << "Test not supported on this platform" << endl; +#endif + + return EXIT_SUCCESS; +} |