Skip to content

Commit

Permalink
Update examples CI (automatic test) (#78)
Browse files Browse the repository at this point in the history
* Fix exit code of bpftime cli

* Fix examples CI

* Fix CI

* Fix CI

* Fix CI

* Fix CI

* Update test-examples.yml

* Update test-examples.yml

* Update test-examples.yml

* Update run_example.py

* Update run_example.py

* Update run_example.py

* Update test-examples.yml

* Update run_example.py

* Update run_example.py

* Update test-examples.yml

* Update examples CI

* Fix CI

* Fix CI
  • Loading branch information
Officeyutong authored Nov 7, 2023
1 parent 1cfd4e9 commit cad5afc
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 42 deletions.
110 changes: 110 additions & 0 deletions .github/script/run_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import sys
import subprocess
import datetime
import select
from io import StringIO
import signal
import fcntl
import os
import time

SERVER_TIMEOUT = 30
AGENT_TIMEOUT = 30
SERVER_START_SIGNAL = "bpftime-syscall-server started"


def set_non_blocking(fd):
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)


def main():
(
executable,
victim,
expected_str,
bpftime_cli,
syscall_trace,
) = sys.argv[1:]
bashreadline_patch = "readline" in executable
# Run the syscall-server
server = subprocess.Popen(
" ".join([bpftime_cli, "load", executable]),
stdout=subprocess.PIPE,
text=False,
stderr=sys.stderr,
bufsize=0,
shell=True,
)
set_non_blocking(server.stdout)
server_ok = False
server_start_time = datetime.datetime.now()
while (
datetime.datetime.now() - server_start_time
).total_seconds() < SERVER_TIMEOUT:
if server.poll() is not None:
break
ready, _, _ = select.select([server.stdout], [], [], 0.01)
if ready:
line = server.stdout.readline().decode()
print("SERVER:", line, end="")
if SERVER_START_SIGNAL in line:
print("MONITOR: Server started!")
server_ok = True
break
if not server_ok:
print("Failed to start server!")
server.kill()
server.wait()
exit(1)
time.sleep(10)
# Start the agent
agent = subprocess.Popen(
" ".join(
[bpftime_cli, "start"]
+ (["-s", victim] if syscall_trace == "1" else [victim])
),
stdout=sys.stdout,
text=False,
stderr=sys.stderr,
stdin=subprocess.PIPE,
env={"SPDLOG_LEVEL": "info"},
shell=True,
)
agent_start_time = datetime.datetime.now()
agent_ok = False
buf = StringIO()
if bashreadline_patch:
# Currently it's difficult to test bashreadline
exit(0)
while (datetime.datetime.now() - agent_start_time).total_seconds() < AGENT_TIMEOUT:
# Check if server has expected output
if server.poll() is not None:
break
ready, _, _ = select.select([server.stdout], [], [], 0.01)
c = server.stdout.read()
if c:
c = c.decode()
buf.write(c)
print(c, end="")
if c == "\n":
buf.seek(0)
if expected_str in buf.getvalue():
# print("SERVER:", line, end="")
# if expected_str in line:
print(f"MONITOR: string `{expected_str}` found!")
agent_ok = True
break
agent.kill()
agent.wait()
server.kill()
server.wait()
if not agent_ok:
print("Failed to test, expected string not found!")
exit(1)
else:
exit(0)


if __name__ == "__main__":
main()
34 changes: 16 additions & 18 deletions .github/workflows/test-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,35 @@ jobs:
matrix:
examples:
- path: libbpf-tools/opensnoop
executable: opensnoop
executable: ./opensnoop
victim: ./victim
syscall_trace: true
expected_str: " 0 test.txt"
- path: libbpf-tools/statsnoop
executable: statsnoop
executable: ./statsnoop
victim: ./victim
syscall_trace: true
syscall_trace: true
expected_str: "victim 0 0 /sys"
- path: malloc
executable: malloc
executable: ./malloc
victim: ./victim
syscall_trace: false
expected_str: "malloc calls: "
- path: opensnoop
executable: opensnoop
executable: ./opensnoop
victim: ./victim
syscall_trace: false
syscall_trace: true
expected_str: " 0 test.txt"
- path: sslsniff
executable: sslsniff
executable: ./sslsniff
victim: /bin/wget https://www.google.com
syscall_trace: false
expected_str: "----- DATA -----"
- path: libbpf-tools/bashreadline
executable: readline
executable: ./readline
victim: /bin/bash
syscall_trace: false
expected_str: "info"

steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -94,18 +100,10 @@ jobs:
shell: "sudo /bin/bash -e {0}"
run: |
cd example/${{matrix.examples.path}}
timeout -s 2 30s sudo -E /home/runner/.bpftime/bpftime -i /home/runner/.bpftime load ./${{matrix.examples.executable}} || if [ $? = 124 ]; then exit 0; else exit $?; fi &
sleep 3s
ID1=$!
timeout -s 2 15s sudo -E /home/runner/.bpftime/bpftime -i /home/runner/.bpftime start -s ${{matrix.examples.victim}} || if [ $? = 124 ]; then exit 0; else exit $?; fi
fg $ID1 || true
sudo -E python3 /home/runner/work/bpftime/bpftime/.github/script/run_example.py ${{matrix.examples.executable}} "${{matrix.examples.victim}}" "${{matrix.examples.expected_str}}" "/home/runner/.bpftime/bpftime -i /home/runner/.bpftime" 1
- name: Test CLI - attach by running (uprobe)
if: '!matrix.examples.syscall_trace'
shell: "sudo /bin/bash -e {0}"
run: |
cd example/${{matrix.examples.path}}
timeout -s 2 30s sudo -E /home/runner/.bpftime/bpftime -i /home/runner/.bpftime load ./${{matrix.examples.executable}} || if [ $? = 124 ]; then exit 0; else exit $?; fi &
sleep 3s
ID1=$!
timeout -s 2 15s sudo -E /home/runner/.bpftime/bpftime -i /home/runner/.bpftime start ${{matrix.examples.victim}} || if [ $? = 124 ]; then exit 0; else exit $?; fi
fg $ID1 || true
sudo -E python3 /home/runner/work/bpftime/bpftime/.github/script/run_example.py ${{matrix.examples.executable}} "${{matrix.examples.victim}}" "${{matrix.examples.expected_str}}" "/home/runner/.bpftime/bpftime -i /home/runner/.bpftime" 0
1 change: 1 addition & 0 deletions example/libbpf-tools/bashreadline/readline.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ static void handle_event(void *ctx, int cpu, void *data, __u32 data_size)
strftime(ts, sizeof(ts), "%H:%m:%S", tm);

printf("%-9s %-7d %s\n", ts, e->pid, e->str);
fflush(stdout);
}

static void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt)
Expand Down
55 changes: 33 additions & 22 deletions example/libbpf-tools/gethostlatency/gethostlatency.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* 24-Mar-2021 Hengqi Chen Created this.
*/
#include <argp.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
Expand All @@ -22,8 +23,8 @@
#include "trace_helpers.h"
#include "uprobe_helpers.h"

#define PERF_BUFFER_PAGES 16
#define PERF_POLL_TIMEOUT_MS 100
#define PERF_BUFFER_PAGES 16
#define PERF_POLL_TIMEOUT_MS 100
#define warn(...) fprintf(stderr, __VA_ARGS__)

static volatile sig_atomic_t exiting = 0;
Expand All @@ -36,13 +37,13 @@ const char *argp_program_version = "gethostlatency 0.1";
const char *argp_program_bug_address =
"https://github.com/iovisor/bcc/tree/master/libbpf-tools";
const char argp_program_doc[] =
"Show latency for getaddrinfo/gethostbyname[2] calls.\n"
"\n"
"USAGE: gethostlatency [-h] [-p PID] [-l LIBC]\n"
"\n"
"EXAMPLES:\n"
" gethostlatency # time getaddrinfo/gethostbyname[2] calls\n"
" gethostlatency -p 1216 # only trace PID 1216\n";
"Show latency for getaddrinfo/gethostbyname[2] calls.\n"
"\n"
"USAGE: gethostlatency [-h] [-p PID] [-l LIBC]\n"
"\n"
"EXAMPLES:\n"
" gethostlatency # time getaddrinfo/gethostbyname[2] calls\n"
" gethostlatency -p 1216 # only trace PID 1216\n";

static const struct argp_option opts[] = {
{ "pid", 'p', "PID", 0, "Process ID to trace" },
Expand Down Expand Up @@ -85,7 +86,8 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
return 0;
}

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
static int libbpf_print_fn(enum libbpf_print_level level, const char *format,
va_list args)
{
if (level == LIBBPF_DEBUG && !verbose)
return 0;
Expand All @@ -107,8 +109,9 @@ static void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
time(&t);
tm = localtime(&t);
strftime(ts, sizeof(ts), "%H:%M:%S", tm);
printf("%-8s %-7d %-16s %-10.3f %-s\n",
ts, e->pid, e->comm, (double)e->time/1000000, e->host);
printf("%-8s %-7d %-16s %-10.3f %-s\n", ts, e->pid, e->comm,
(double)e->time / 1000000, e->host);
fflush(stdout);
}

static void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt)
Expand Down Expand Up @@ -148,7 +151,8 @@ static int get_libc_path(char *path)
return -1;
}

static int attach_uprobes(struct gethostlatency_bpf *obj, struct bpf_link *links[])
static int attach_uprobes(struct gethostlatency_bpf *obj,
struct bpf_link *links[])
{
int err;
char libc_path[PATH_MAX] = {};
Expand All @@ -166,13 +170,15 @@ static int attach_uprobes(struct gethostlatency_bpf *obj, struct bpf_link *links
return -1;
}
links[0] = bpf_program__attach_uprobe(obj->progs.handle_entry, false,
target_pid ?: -1, libc_path, func_off);
target_pid ?: -1, libc_path,
func_off);
if (!links[0]) {
warn("failed to attach getaddrinfo: %d\n", -errno);
return -1;
}
links[1] = bpf_program__attach_uprobe(obj->progs.handle_return, true,
target_pid ?: -1, libc_path, func_off);
target_pid ?: -1, libc_path,
func_off);
if (!links[1]) {
warn("failed to attach getaddrinfo: %d\n", -errno);
return -1;
Expand All @@ -184,13 +190,15 @@ static int attach_uprobes(struct gethostlatency_bpf *obj, struct bpf_link *links
return -1;
}
links[2] = bpf_program__attach_uprobe(obj->progs.handle_entry, false,
target_pid ?: -1, libc_path, func_off);
target_pid ?: -1, libc_path,
func_off);
if (!links[2]) {
warn("failed to attach gethostbyname: %d\n", -errno);
return -1;
}
links[3] = bpf_program__attach_uprobe(obj->progs.handle_return, true,
target_pid ?: -1, libc_path, func_off);
target_pid ?: -1, libc_path,
func_off);
if (!links[3]) {
warn("failed to attach gethostbyname: %d\n", -errno);
return -1;
Expand All @@ -202,13 +210,15 @@ static int attach_uprobes(struct gethostlatency_bpf *obj, struct bpf_link *links
return -1;
}
links[4] = bpf_program__attach_uprobe(obj->progs.handle_entry, false,
target_pid ?: -1, libc_path, func_off);
target_pid ?: -1, libc_path,
func_off);
if (!links[4]) {
warn("failed to attach gethostbyname2: %d\n", -errno);
return -1;
}
links[5] = bpf_program__attach_uprobe(obj->progs.handle_return, true,
target_pid ?: -1, libc_path, func_off);
target_pid ?: -1, libc_path,
func_off);
if (!links[5]) {
warn("failed to attach gethostbyname2: %d\n", -errno);
return -1;
Expand Down Expand Up @@ -238,7 +248,8 @@ int main(int argc, char **argv)

err = ensure_core_btf(&open_opts);
if (err) {
fprintf(stderr, "failed to fetch necessary BTF for CO-RE: %s\n", strerror(-err));
fprintf(stderr, "failed to fetch necessary BTF for CO-RE: %s\n",
strerror(-err));
return 1;
}

Expand Down Expand Up @@ -274,8 +285,8 @@ int main(int argc, char **argv)
goto cleanup;
}

printf("%-8s %-7s %-16s %-10s %-s\n",
"TIME", "PID", "COMM", "LATms", "HOST");
printf("%-8s %-7s %-16s %-10s %-s\n", "TIME", "PID", "COMM", "LATms",
"HOST");

while (!exiting) {
err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
Expand Down
2 changes: 2 additions & 0 deletions example/libbpf-tools/opensnoop/opensnoop.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <bpf/bpf.h>
#include "opensnoop.h"
#include "opensnoop.skel.h"
#include <stdio.h>

/* Tune the buffer size and wakeup rate. These settings cope with roughly
* 50k opens/sec.
Expand Down Expand Up @@ -229,6 +230,7 @@ void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
sps_cnt += 9;
}
printf("%s\n", e->fname);
fflush(stdout);

}

Expand Down
3 changes: 2 additions & 1 deletion example/libbpf-tools/statsnoop/statsnoop.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// Based on statsnoop(8) from BCC by Brendan Gregg.
// 09-May-2021 Hengqi Chen Created this.
#include <argp.h>
#include <stdio.h>
#include <errno.h>
#include <linux/limits.h>
#include <signal.h>
Expand Down Expand Up @@ -118,6 +119,7 @@ static void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
}
printf("%-7d %-20s %-4d %-4d %-s\n", e->pid, e->comm, fd, err,
e->pathname);
fflush(stdout);
}

static void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt)
Expand Down Expand Up @@ -152,7 +154,6 @@ int main(int argc, char **argv)
obj->rodata->target_pid = target_pid;
obj->rodata->trace_failed_only = trace_failed_only;


err = statsnoop_bpf__load(obj);
if (err) {
warn("failed to load BPF object: %d\n", err);
Expand Down
1 change: 1 addition & 0 deletions example/malloc/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ static int print_stat(struct malloc_bpf *obj)
}
prev_key = &key;
}
fflush(stdout);
return err;
}

Expand Down
2 changes: 2 additions & 0 deletions example/opensnoop/opensnoop.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <bpf/bpf.h>
#include "opensnoop.h"
#include "opensnoop.skel.h"
#include <stdio.h>

/* Tune the buffer size and wakeup rate. These settings cope with roughly
* 50k opens/sec.
Expand Down Expand Up @@ -225,6 +226,7 @@ static int handle_event_rb(void *ctx, void *data, size_t data_sz)
sps_cnt += 9;
}
printf("%s\n", e->fname);
fflush(stdout);
return 0;
}

Expand Down
Loading

0 comments on commit cad5afc

Please sign in to comment.