// ********************************************************************** // // 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 #include #include 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 ThrowerPtr; #ifdef _WIN32 string getIceHome() { vector buf(256); DWORD ret = GetEnvironmentVariableW(L"ICE_HOME", &buf[0], static_cast(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(ICE_STRING_VERSION); vector split; IceUtilInternal::splitString(v1, ".", split); string v2(split[0] + split[1]); size_t pos = 0; while((pos = str.find(v1, pos)) != string::npos) { str.replace(pos, v1.length(), v2); pos += v2.length(); } } #else vector splitLines(const string& str) { vector 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 buf(256); DWORD ret = GetEnvironmentVariableW(L"USE_BIN_DIST", &buf[0], static_cast(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 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 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; }