Skip to content

Commit 5c2ef85

Browse files
committed
stuff
1 parent 20d7352 commit 5c2ef85

File tree

1 file changed

+42
-30
lines changed

1 file changed

+42
-30
lines changed

tools/crash_test.py

100644100755
Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@
88
import traceback
99
import zipfile
1010

11-
class CrashTest:
11+
if os.name == "nt":
12+
EXE = '.exe'
13+
else:
14+
EXE = ""
15+
16+
def PathJoin(*paths):
17+
p = os.path.join(*paths)
18+
if EXE:
19+
p = p.replace("\\", "/") # for WSL
20+
return p
21+
22+
class Test:
1223
def __init__(self, name):
1324
self.name = name
1425

@@ -37,13 +48,13 @@ def Go(self):
3748
self.End()
3849
return self.status == "PASSED"
3950

40-
class BreakpadCrashTest(CrashTest):
51+
class BreakpadCrashTest(Test):
4152
def __init__(self, module, engine, tprefix, fault):
4253
super().__init__(module + "." + fault)
4354
self.engine = engine
4455
self.tprefix = tprefix
4556
self.fault = fault
46-
self.dir = os.path.join(TEMP_DIR, self.name)
57+
self.dir = PathJoin(TEMP_DIR, self.name)
4758
try:
4859
shutil.rmtree(self.dir)
4960
except FileNotFoundError:
@@ -71,14 +82,14 @@ def Do(self):
7182
"+delay 20f echo CRASHTEST_END",
7283
"+delay 40f quit"],
7384
stderr=subprocess.PIPE, check=bool(self.tprefix))
74-
dumps = os.listdir(os.path.join(self.dir, "crashdump"))
85+
dumps = os.listdir(PathJoin(self.dir, "crashdump"))
7586
assert len(dumps) == 1, dumps
76-
dump = os.path.join(self.dir, "crashdump", dumps[0])
77-
sw_out = os.path.join(TEMP_DIR, self.name + "_stackwalk.log")
87+
dump = PathJoin(self.dir, "crashdump", dumps[0])
88+
sw_out = PathJoin(TEMP_DIR, self.name + "_stackwalk.log")
7889
with open(sw_out, "a+") as sw_f:
7990
print(f"Extracting stack trace to '{sw_out}'...")
8091
sw_f.truncate()
81-
subprocess.run(Virtualize([os.path.join(BREAKPAD_DIR, "src/processor/minidump_stackwalk"), dump, SYMBOL_DIR]), check=True, stdout=sw_f, stderr=subprocess.STDOUT)
92+
subprocess.run(Virtualize([PathJoin(BREAKPAD_DIR, "src/processor/minidump_stackwalk"), dump, SYMBOL_DIR]), check=True, stdout=sw_f, stderr=subprocess.STDOUT)
8293
sw_f.seek(0)
8394
sw = sw_f.read()
8495
TRACE_FUNC = "InjectFaultCmd::Run"
@@ -106,9 +117,9 @@ def ModulePath(module):
106117
"sgame": f"sgame-{NACL_ARCH}.nexe",
107118
"cgame": f"cgame-{NACL_ARCH}.nexe",
108119
}[module]
109-
return os.path.join(GAME_BUILD_DIR, base)
120+
return PathJoin(GAME_DIR, base)
110121

111-
class ModuleCrashTests(CrashTest):
122+
class ModuleCrashTests(Test):
112123
def __init__(self, module, engine=None):
113124
super().__init__(module)
114125
self.engine = engine
@@ -131,7 +142,7 @@ def Do(self):
131142
target = ModulePath(module)
132143
assert os.path.isfile(target), target
133144
print(f"Symbolizing '{target}'...")
134-
subprocess.check_call(Virtualize([os.path.join(BREAKPAD_DIR, "symbolize.py"),
145+
subprocess.check_call(Virtualize([PathJoin(BREAKPAD_DIR, "symbolize.py"),
135146
"--symbol-directory", SYMBOL_DIR, target]))
136147

137148
self.Verify(BreakpadCrashTest(module, engine, tprefix, "segfault").Go())
@@ -143,52 +154,53 @@ def Do(self):
143154
self.Verify(BreakpadCrashTest(module, engine, tprefix, "throw").Go())
144155

145156
def ArgParser(usage=None):
146-
ap = argparse.ArgumentParser(usage=usage)
157+
ap = argparse.ArgumentParser(
158+
usage=usage,
159+
description="Verify that Breakpad toolchain can produce usable stack traces."
160+
" A Daemon build must be found in the current directory. Also Breakpad's tools must be built in its source tree."
161+
" If a symbols zip is found in the current directory, enter release validation mode: prebuilt symbols are used and VM type defaults to 0 (NaCl from paks)."
162+
" Otherwise, enter end-to-end mode: symbols are produced from the binaries and VM type defaults to 1 (NaCl from PWD). In this mode you will likely need to provide pak paths via --daemon-args.")
163+
ap.add_argument("--game-dir", type=str, default=".", help="Path to Daemon (+ gamelogic) binaries")
147164
ap.add_argument("--breakpad-dir", type=str, default=BREAKPAD_DIR, help=r"Path to Breakpad repo containing built dump_syms and stackwalk binaries. It may be a \\wsl.localhost\ path on Windows hosts in order to symbolize NaCl.")
148165
ap.add_argument("--give-up", action="store_true", help="Stop after first test failure")
149166
ap.add_argument("--nacl-arch", type=str, choices=["amd64", "i686", "armhf"], default="amd64") # TODO auto-detect?
150167
ap.add_argument("module", nargs="*",
151168
default="server", # bogus default needed due to buggy argparse
152169
choices=["dummyapp", "server", "ttyclient", "client",
153-
"cgame", "ttyclient:cgame", "client:cgame",
154-
"sgame", "server:sgame", "ttyclient:sgame", "client:sgame"])
170+
"cgame", "ttyclient:cgame", "client:cgame",
171+
"sgame", "server:sgame", "ttyclient:sgame", "client:sgame"])
155172
return ap
156173

157-
BREAKPAD_DIR = os.path.abspath(os.path.join(
174+
BREAKPAD_DIR = os.path.abspath(PathJoin(
158175
os.path.dirname(os.path.realpath(__file__)), "../libs/breakpad"))
159-
GAME_BUILD_DIR = '.' # WSL calls rely on relative paths
160-
TEMP_DIR = os.path.join(GAME_BUILD_DIR, "crashtest-tmp")
161-
SYMBOL_DIR = os.path.join(TEMP_DIR, "symbols")
162-
163-
os.makedirs(TEMP_DIR, exist_ok=True)
164-
os.makedirs(SYMBOL_DIR, exist_ok=True)
165176

166-
if os.name == "nt":
167-
EXE = '.exe'
168-
else:
169-
EXE = ""
170-
171-
ap = ArgParser(usage=ArgParser().format_usage().rstrip().removeprefix("usage: ")
172-
+ " [--daemon-args ARGS...]")
177+
ap = ArgParser(
178+
usage=ArgParser().format_usage().rstrip().removeprefix("usage: ") + " [--daemon-args ARGS...]")
173179
ap.add_argument("--daemon-args", nargs=argparse.REMAINDER, default=[],
174180
help="Extra arguments for Daemon (e.g. -pakpath)")
175181
pa = ap.parse_args(sys.argv[1:])
182+
GAME_DIR = pa.game_dir
176183
BREAKPAD_DIR = pa.breakpad_dir
177184
GIVE_UP = pa.give_up
178185
DAEMON_USER_ARGS = pa.daemon_args
179186
NACL_ARCH = pa.nacl_arch
180-
SYMBOL_ZIPS = [p for p in os.listdir(GAME_BUILD_DIR) if p.startswith("symbols") and p.endswith(".zip")]
187+
SYMBOL_ZIPS = [p for p in os.listdir(GAME_DIR) if p.startswith("symbols") and p.endswith(".zip")]
181188
modules = pa.module
182189
if isinstance(modules, str):
183190
modules = ["server", "ttyclient", "sgame", "cgame"]
184191

192+
TEMP_DIR = "crashtest-tmp" # WSL relies on this being relative
193+
SYMBOL_DIR = PathJoin(TEMP_DIR, "symbols")
194+
os.makedirs(TEMP_DIR, exist_ok=True)
195+
os.makedirs(SYMBOL_DIR, exist_ok=True)
196+
185197
if SYMBOL_ZIPS:
186198
print("Symbol zip(s) detected. Using release validation mode with pre-built symbols")
187199
for z in SYMBOL_ZIPS:
188-
with zipfile.ZipFile(z, 'r') as z:
200+
with zipfile.ZipFile(PathJoin(GAME_DIR, z), 'r') as z:
189201
z.extractall(SYMBOL_DIR)
190202
else:
191-
print("No symbol zip detected. Using end2end Breakpad tooling test mode with dump_syms")
203+
print("No symbol zip detected. Using end-to-end Breakpad tooling test mode with dump_syms")
192204

193205
passed = True
194206
for module in modules:

0 commit comments

Comments
 (0)