1
0
forked from 0ad/0ad
0ad/source/lib/sysdep/win/tests/test_wdbg_sym.h
janwas f3b3e0be6e # big refactor of error display code. fixes crash in release-mode selftest
* debug_write_crashlog and debug_dump_stack are now responsible for
detecting reentrancy (reported via new ERR_REENTERED error code).
* export debug_error_message_build to allow unit test of stack dumper
* split+clean up debug_display_error to allow this.
* error_description_r now returns buf for convenience
* ia32: fix typo causing disassembly to fail
* wdbg_sym: bugfix causing incorrect debug_walk_stack return value.
prevent recursive locking, provide locked version of
debug_resolve_symbol. add skip_this_frame for convenience.

refs #130

This was SVN commit r4067.
2006-07-07 01:22:23 +00:00

260 lines
8.2 KiB
C++

// note: this is more of an on-demand display of the stack trace than
// self-test of it.
// TODO: compare against known-good result?
// problem: results may differ by compiler (e.g. due to differing STL)
#include "lib/self_test.h"
#include "lib/sysdep/win/win_internal.h" // HWND
#include "lib/debug.h" // no wdbg_sym interface needed
#include "lib/sysdep/sysdep.h"
#include "lib/sysdep/win/win_internal.h"
#include <queue>
#include <deque>
#include <list>
#include <map>
#include <stack>
class TestWdbgSym : public CxxTest::TestSuite
{
#pragma optimize("", off)
static void m_test_array()
{
struct Small
{
int i1;
int i2;
};
struct Large
{
double d1;
double d2;
double d3;
double d4;
};
Large large_array_of_large_structs[8] = { { 0.0,0.0,0.0,0.0 } }; UNUSED2(large_array_of_large_structs);
Large small_array_of_large_structs[2] = { { 0.0,0.0,0.0,0.0 } }; UNUSED2(small_array_of_large_structs);
Small large_array_of_small_structs[8] = { { 1,2 } }; UNUSED2(large_array_of_small_structs);
Small small_array_of_small_structs[2] = { { 1,2 } }; UNUSED2(small_array_of_small_structs);
int ints[] = { 1,2,3,4,5 }; UNUSED2(ints);
wchar_t chars[] = { 'w','c','h','a','r','s',0 }; UNUSED2(chars);
// note: prefer simple error (which also generates stack trace) to
// exception, because it is guaranteed to work (no issues with the
// debugger swallowing exceptions).
//DISPLAY_ERROR(L"wdbg_sym self test: check if stack trace below is ok.");
//RaiseException(0xf001,0,0,0);
// note: we don't want any kind of dialog to be raised, because
// this test now always runs. therefore, just make sure a decent
// amount of text (not just "(failed)" error messages) was produced.
//
// however, we can't call debug_dump_stack directly because
// it'd be reentered if an actual error comes up.
// therefore, use debug_display_error with DE_HIDE_DIALOG.
// unfortunately this means we can no longer get at the error text.
// a sanity check of the text length has been added to debug_display_error
ErrorMessageMem emm = {0,0,0};
const wchar_t* text = debug_error_message_build(L"dummy", 0,0,0, 0,0, &emm);
TS_ASSERT(wcslen(text) > 500);
debug_error_message_free(&emm);
}
// also used by test_stl as an element type
struct Nested
{
int nested_member;
struct Nested* self_ptr;
};
static void m_test_udt()
{
Nested nested = { 123 }; nested.self_ptr = &nested;
typedef struct
{
u8 s1;
u8 s2;
char s3;
}
Small;
Small small__ = { 0x55, 0xaa, -1 }; UNUSED2(small__);
struct Large
{
u8 large_member_u8;
std::string large_member_string;
double large_member_double;
}
large = { 0xff, "large struct string", 123456.0 }; UNUSED2(large);
class Base
{
int base_int;
std::wstring base_wstring;
public:
Base()
: base_int(123), base_wstring(L"base wstring")
{
}
};
class Derived : private Base
{
double derived_double;
public:
Derived()
: derived_double(-1.0)
{
}
}
derived;
m_test_array();
}
// STL containers and their contents
static void m_test_stl()
{
std::vector<std::wstring> v_wstring;
v_wstring.push_back(L"ws1"); v_wstring.push_back(L"ws2");
std::deque<int> d_int;
d_int.push_back(1); d_int.push_back(2); d_int.push_back(3);
std::deque<std::string> d_string;
d_string.push_back("a"); d_string.push_back("b"); d_string.push_back("c");
std::list<float> l_float;
l_float.push_back(0.1f); l_float.push_back(0.2f); l_float.push_back(0.3f); l_float.push_back(0.4f);
std::map<std::string, int> m_string_int;
m_string_int.insert(std::make_pair<std::string,int>("s5", 5));
m_string_int.insert(std::make_pair<std::string,int>("s6", 6));
m_string_int.insert(std::make_pair<std::string,int>("s7", 7));
std::map<int, std::string> m_int_string;
m_int_string.insert(std::make_pair<int,std::string>(1, "s1"));
m_int_string.insert(std::make_pair<int,std::string>(2, "s2"));
m_int_string.insert(std::make_pair<int,std::string>(3, "s3"));
std::map<int, int> m_int_int;
m_int_int.insert(std::make_pair<int,int>(1, 1));
m_int_int.insert(std::make_pair<int,int>(2, 2));
m_int_int.insert(std::make_pair<int,int>(3, 3));
STL_HASH_MAP<std::string, int> hm_string_int;
hm_string_int.insert(std::make_pair<std::string,int>("s5", 5));
hm_string_int.insert(std::make_pair<std::string,int>("s6", 6));
hm_string_int.insert(std::make_pair<std::string,int>("s7", 7));
STL_HASH_MAP<int, std::string> hm_int_string;
hm_int_string.insert(std::make_pair<int,std::string>(1, "s1"));
hm_int_string.insert(std::make_pair<int,std::string>(2, "s2"));
hm_int_string.insert(std::make_pair<int,std::string>(3, "s3"));
STL_HASH_MAP<int, int> hm_int_int;
hm_int_int.insert(std::make_pair<int,int>(1, 1));
hm_int_int.insert(std::make_pair<int,int>(2, 2));
hm_int_int.insert(std::make_pair<int,int>(3, 3));
std::set<uintptr_t> s_uintptr;
s_uintptr.insert(0x123); s_uintptr.insert(0x456);
// empty
std::deque<u8> d_u8_empty;
std::list<Nested> l_nested_empty;
std::map<double,double> m_double_empty;
std::multimap<int,u8> mm_int_empty;
std::set<uint> s_uint_empty;
std::multiset<char> ms_char_empty;
std::vector<double> v_double_empty;
std::queue<double> q_double_empty;
std::stack<double> st_double_empty;
#if HAVE_STL_HASH
STL_HASH_MAP<double,double> hm_double_empty;
STL_HASH_MULTIMAP<double,std::wstring> hmm_double_empty;
STL_HASH_SET<double> hs_double_empty;
STL_HASH_MULTISET<double> hms_double_empty;
#endif
#if HAVE_STL_SLIST
STL_SLIST<double> sl_double_empty;
#endif
std::string str_empty;
std::wstring wstr_empty;
m_test_udt();
// uninitialized
std::deque<u8> d_u8_uninit;
std::list<Nested> l_nested_uninit;
std::map<double,double> m_double_uninit;
std::multimap<int,u8> mm_int_uninit;
std::set<uint> s_uint_uninit;
std::multiset<char> ms_char_uninit;
std::vector<double> v_double_uninit;
std::queue<double> q_double_uninit;
std::stack<double> st_double_uninit;
#if HAVE_STL_HASH
STL_HASH_MAP<double,double> hm_double_uninit;
STL_HASH_MULTIMAP<double,std::wstring> hmm_double_uninit;
STL_HASH_SET<double> hs_double_uninit;
STL_HASH_MULTISET<double> hms_double_uninit;
#endif
#if HAVE_STL_SLIST
STL_SLIST<double> sl_double_uninit;
#endif
std::string str_uninit;
std::wstring wstr_uninit;
}
// also exercises all basic types because we need to display some values
// anyway (to see at a glance whether symbol engine addrs are correct)
static void m_test_addrs(int p_int, double p_double, char* p_pchar, uintptr_t p_uintptr)
{
debug_printf("\nTEST_ADDRS\n");
uint l_uint = 0x1234;
bool l_bool = true; UNUSED2(l_bool);
wchar_t l_wchars[] = L"wchar string";
enum TestEnum { VAL1=1, VAL2=2 } l_enum = VAL1;
u8 l_u8s[] = { 1,2,3,4 };
void (*l_funcptr)(void) = m_test_stl;
static double s_double = -2.718;
static char s_chars[] = {'c','h','a','r','s',0};
static void (*s_funcptr)(int, double, char*, uintptr_t) = m_test_addrs;
static void* s_ptr = (void*)(uintptr_t)0x87654321;
static HDC s_hdc = (HDC)0xff0;
debug_printf("p_int addr=%p val=%d\n", &p_int, p_int);
debug_printf("p_double addr=%p val=%g\n", &p_double, p_double);
debug_printf("p_pchar addr=%p val=%s\n", &p_pchar, p_pchar);
debug_printf("p_uintptr addr=%p val=%lu\n", &p_uintptr, p_uintptr);
debug_printf("l_uint addr=%p val=%u\n", &l_uint, l_uint);
debug_printf("l_wchars addr=%p val=%ws\n", &l_wchars, l_wchars);
debug_printf("l_enum addr=%p val=%d\n", &l_enum, l_enum);
debug_printf("l_u8s addr=%p val=%d\n", &l_u8s, l_u8s);
debug_printf("l_funcptr addr=%p val=%p\n", &l_funcptr, l_funcptr);
m_test_stl();
int uninit_int; UNUSED2(uninit_int);
float uninit_float; UNUSED2(uninit_float);
double uninit_double; UNUSED2(uninit_double);
bool uninit_bool; UNUSED2(uninit_bool);
HWND uninit_hwnd; UNUSED2(uninit_hwnd);
}
#pragma optimize("", on)
public:
void test_stack_trace()
{
m_test_addrs(123, 3.1415926535897932384626, "pchar string", 0xf00d);
}
};