Skip to content

Commit

Permalink
tests: add pyda attach tests, fix bin/pyda
Browse files Browse the repository at this point in the history
  • Loading branch information
ndrewh committed Dec 17, 2024
1 parent ab5c9c1 commit b54543b
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 5 deletions.
2 changes: 1 addition & 1 deletion bin/pyda
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash

ROOT=$(dirname "$0")/../
ASAN_OPTIONS=$ASAN_OPTIONS:detect_leaks=0 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PYTHONHOME/lib/ PYDA_SCRIPT=$1 exec $DYNAMORIO_HOME/bin64/drrun -stack_size 1024K -c $ROOT/build/pyda_core/libtool.so ${@:2}
PYDA_NO_ATTACH=1 ASAN_OPTIONS=$ASAN_OPTIONS:detect_leaks=0 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PYTHONHOME/lib/ PYDA_SCRIPT=$1 exec $DYNAMORIO_HOME/bin64/drrun -stack_size 1024K -c $ROOT/build/pyda_core/libtool.so ${@:2}
41 changes: 37 additions & 4 deletions tests/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Optional, Callable
from pathlib import Path
from tempfile import TemporaryDirectory
import os
import os, time

from argparse import ArgumentParser

Expand All @@ -19,6 +19,7 @@ class ExpectedResult:
@dataclass
class RunOpts:
no_pty: bool = False
attach: bool = False

def output_checker(stdout: bytes, stderr: bytes) -> bool:
try:
Expand Down Expand Up @@ -252,6 +253,27 @@ def no_warnings_or_errors(stdout: bytes, stderr: bytes) -> bool:
lambda o, e: o.count(b"child status 0") == 1,
]
)),

("test_attach", "test_longrunning.c", "../examples/ltrace_multithreaded.py", RunOpts(attach=True), ExpectedResult(
retcode=0,
checkers=[
output_checker,
no_warnings_or_errors,
lambda o, e: o.count(b"[thread 1] sleep") in range(5, 12),
]
)),

("test_attach_multithread", "test_longrunning_multithread.c", "../examples/ltrace_multithreaded.py", RunOpts(attach=True), ExpectedResult(
retcode=0,
checkers=[
output_checker,
no_warnings_or_errors,
lambda o, e: o.count(b"pthread_join") in [9, 10], # first call may happen before attach
lambda o, e: o.count(b"snprintf") == 10,
lambda o, e: all((o.count(f"[thread {i}] gettimeofday".encode('utf-8')) in range(5, 12) for i in range(2, 12))),
lambda o, e: all((o.count(f"thread_entry for {i}".encode('utf-8')) == 1 for i in range(2, 12))),
]
)),
]

def main():
Expand All @@ -277,6 +299,7 @@ def main():
if not res:
exit(1)

TIMEOUT = 15
def run_test(c_file, python_file, run_opts, expected_result, test_name, debug, ntrials):
# Compile to temporary directory
with TemporaryDirectory() as tmpdir:
Expand All @@ -298,9 +321,19 @@ def run_test(c_file, python_file, run_opts, expected_result, test_name, debug, n
for trial in range(ntrials):
result_str = ""
try:
result = subprocess.run(f"pyda {p_path.resolve()} -- {c_exe.resolve()}", env=env, stdin=subprocess.DEVNULL, shell=True, timeout=15, capture_output=True)
stdout = result.stdout
stderr = result.stderr
if not run_opts.attach:
result = subprocess.run(f"pyda {p_path.resolve()} -- {c_exe.resolve()}", env=env, stdin=subprocess.DEVNULL, shell=True, timeout=TIMEOUT, capture_output=True)
stdout = result.stdout
stderr = result.stderr
else:
# Attach mode: Launch the process and then attach to it
proc = subprocess.Popen([c_exe.resolve()], env=env, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
time.sleep(0.5)
result = subprocess.Popen(f"pyda-attach {p_path.resolve()} {proc.pid}", env=env, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL)

stdout, stderr = proc.communicate(timeout=TIMEOUT)
result.wait(timeout=TIMEOUT)

if expected_result.hang:
result_str += " Expected test to hang, but it did not\n"
except subprocess.TimeoutExpired as err:
Expand Down
21 changes: 21 additions & 0 deletions tests/test_longrunning.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

#include <unistd.h>
#include <sys/time.h>

unsigned long timems() {
struct timeval start;
gettimeofday(&start, NULL);
return (start.tv_sec * 1000000 + start.tv_usec) / 1000;
}
int main() {
printf("Hello from long running test\n");

unsigned long start = timems();
while (timems() - start < 10000) {
sleep(1);
}

char *buf = malloc(100);
snprintf(buf, 100, "Finished longrunning test\n");
printf("%s", buf);
}
40 changes: 40 additions & 0 deletions tests/test_longrunning_multithread.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <stdint.h>
#include <pthread.h>

unsigned long timems() {
struct timeval start;
gettimeofday(&start, NULL);
return (start.tv_sec * 1000000 + start.tv_usec) / 1000;
}

void* thread(void *tid) {
unsigned int t = (unsigned int)(unsigned long)tid;
printf("Hello from long running test %u\n", t);
unsigned long start = timems();
while (timems() - start < 10000) {
sleep(1);
}
char *buf = malloc(100);
snprintf(buf, 100, "Finished longrunning test %u\n", t);
printf("%s", buf);
return NULL;
}

int main() {
pthread_t threads[10];
for (int i=0; i<10; i++) {
pthread_create(&threads[i], 0, thread, (void*)(uintptr_t)i);
}

for (int i=0; i<10; i++) {
void *ret;
pthread_join(threads[i], &ret);
}


}

0 comments on commit b54543b

Please sign in to comment.