NAME pid
PROG i:ms:1 { printf("SUCCESS %d\n", pid); exit(); }
EXPECT_REGEX SUCCESS [0-9][0-9]*
TIMEOUT 5

NAME tid
PROG i:ms:1 { printf("SUCCESS %d\n", tid); exit(); }
EXPECT_REGEX SUCCESS [0-9][0-9]*
TIMEOUT 5

NAME uid
PROG i:ms:1 { printf("SUCCESS %d\n", uid); exit(); }
EXPECT_REGEX SUCCESS [0-9][0-9]*
TIMEOUT 5

NAME gid
PROG i:ms:1 { printf("SUCCESS %d\n", gid); exit(); }
EXPECT_REGEX SUCCESS [0-9][0-9]*
TIMEOUT 5

NAME nsecs
PROG i:ms:1 { printf("SUCCESS %llu\n", nsecs); exit(); }
EXPECT_REGEX SUCCESS [0-9]+
TIMEOUT 5

NAME elapsed
PROG i:ms:1 { printf("SUCCESS %llu\n", elapsed); exit(); }
EXPECT_REGEX SUCCESS [0-9]+
TIMEOUT 5

NAME numaid
PROG i:ms:1 { printf("SUCCESS %lu\n", numaid); exit(); }
EXPECT_REGEX SUCCESS [0-9]+
TIMEOUT 5

NAME cpu
PROG i:ms:1 { printf("SUCCESS %lu\n", cpu); exit(); }
EXPECT_REGEX SUCCESS [0-9]+
TIMEOUT 5

NAME comm
PROG BEGIN { printf("SUCCESS %s\n", comm); exit(); }
EXPECT SUCCESS bpftrace
TIMEOUT 5

NAME kstack
PROG BEGIN { printf("%s\n", kstack); exit(); }
EXPECT Attaching 1 probe...
TIMEOUT 5

NAME ustack
PROG BEGIN { printf("%s\n", ustack); exit(); }
EXPECT Attaching 1 probe...
TIMEOUT 5

NAME arg
PROG k:vfs_read { printf("SUCCESS %p\n", arg0); exit(); }
EXPECT_REGEX ^SUCCESS 0x[0-9a-f]+$
TIMEOUT 5
AFTER ./testprogs/syscall read

NAME retval
PROG kretprobe:vfs_read { printf("SUCCESS %d\n", retval); exit(); }
EXPECT_REGEX SUCCESS .*
TIMEOUT 5
AFTER ./testprogs/syscall read

NAME func_kprobe
PROG k:vfs_read { printf("func: '%s'\n", func); exit(); }
EXPECT func: 'vfs_read'
TIMEOUT 5
AFTER ./testprogs/syscall read

NAME func_kretprobe
PROG kr:vfs_read { printf("func: '%s'\n", func); exit(); }
EXPECT func: 'vfs_read'
TIMEOUT 5
REQUIRES_FEATURE get_func_ip
AFTER ./testprogs/syscall read

NAME func_uprobe
PROG uprobe:./testprogs/uprobe_symres:test { printf("func: '%s'\n", func); exit(); }
EXPECT func: 'test'
AFTER ./testprogs/uprobe_symres
TIMEOUT 5

NAME func_uretprobe
PROG uretprobe:./testprogs/uprobe_symres:test { printf("func: '%s'\n", func); exit(); }
# Kernels from v5.15 to v6.5 include the get_func_ip helper, but it does not
# work for uretprobes: it will always return 0.
EXPECT_REGEX ^func: 'test'$|^func: '0'$
AFTER ./testprogs/uprobe_symres
TIMEOUT 5
REQUIRES_FEATURE get_func_ip

# Disabled, since BCC code it depends on is prone to race condition,
# (https://github.com/iovisor/bcc/pull/4319#issuecomment-1321731687)
NAME func_uprobe_symcache_preload
ENV BPFTRACE_CACHE_USER_SYMBOLS=PER_PID
PROG uprobe:./testprogs/uprobe_symres_exited_process:test { print(func); exit(); }
EXPECT test
BEFORE ./testprogs/uprobe_symres_exited_process
TIMEOUT 5
REQUIRES bash -c "exit 1"

NAME func_uprobe_elf_symtable
ENV BPFTRACE_CACHE_USER_SYMBOLS=PER_PROGRAM
PROG uprobe:./testprogs/uprobe_symres_exited_process:test { print(func); exit(); }
EXPECT test
AFTER ./testprogs/disable_aslr ./testprogs/uprobe_symres_exited_process
TIMEOUT 5

NAME username
PROG i:ms:1 { printf("SUCCESS %s\n", username); exit(); }
EXPECT_REGEX SUCCESS .*
TIMEOUT 5

NAME probe
PROG k:do_nanosleep { printf("SUCCESS %s\n", probe); exit(); }
EXPECT SUCCESS kprobe:do_nanosleep
TIMEOUT 5
AFTER ./testprogs/syscall nanosleep 1e8

NAME begin probe
PROG BEGIN { printf("%s", probe);exit(); } END{printf("-%s\n", probe); }
EXPECT_REGEX ^BEGIN-END$
TIMEOUT 5
AFTER ./testprogs/syscall nanosleep 1e8

NAME curtask
PROG i:ms:1 { printf("SUCCESS %p\n", curtask); exit(); }
EXPECT_REGEX SUCCESS 0x[0-9a-f]+
TIMEOUT 5

NAME curtask_field
PROG struct task_struct {int x;} i:ms:1 { printf("SUCCESS %d\n", curtask->x); exit(); }
EXPECT_REGEX SUCCESS -?[0-9][0-9]*
TIMEOUT 5

NAME rand
PROG i:ms:1 { printf("SUCCESS %lu\n", rand); exit(); }
EXPECT_REGEX SUCCESS [0-9]+
TIMEOUT 5

NAME cgroup
PROG i:ms:1 { printf("SUCCESS %llu\n", cgroup); exit(); }
EXPECT_REGEX SUCCESS [0-9]+
TIMEOUT 5
MIN_KERNEL 4.18

NAME ctx
PROG struct x {unsigned long x}; i:ms:1 { printf("SUCCESS %lu\n", ((struct x*)ctx)->x); exit(); }
EXPECT_REGEX SUCCESS [0-9]+
TIMEOUT 5

NAME cat
PROG i:ms:1 { cat("/proc/loadavg"); exit(); }
EXPECT_REGEX ^([0-9]+\.[0-9]+ ?)+.*$
TIMEOUT 5

NAME cat limited output
ENV BPFTRACE_MAX_CAT_BYTES=1
PROG i:ms:1 { cat("/proc/loadavg"); exit(); }
EXPECT_REGEX ^[0-9]$
TIMEOUT 5

NAME cat format str
PROG i:ms:1 { $s = "loadavg"; cat("/proc/%s", $s); exit(); }
EXPECT_REGEX ^([0-9]+\.[0-9]+ ?)+.*$
TIMEOUT 5

NAME log size too small
ENV BPFTRACE_LOG_SIZE=0
RUN {{BPFTRACE}} -e 'BEGIN { if (str($1) == str($2)) { printf("%s\n", str($1)); exit() } }' "hello" "hello"
EXPECT ERROR: Error loading program: BEGIN (try -v)
TIMEOUT 5
WILL_FAIL

NAME increase log size
ENV BPFTRACE_LOG_SIZE=10000000
RUN {{BPFTRACE}} -e 'BEGIN { if (str($1) == str($2)) { printf("%s\n", str($1)); exit() } }' "hello" "hello"
EXPECT hello
TIMEOUT 5

NAME cat "no such file"
PROG i:ms:1 { cat("/does/not/exist/file"); exit(); }
EXPECT ERROR: failed to open file '/does/not/exist/file': No such file or directory
TIMEOUT 5

NAME sizeof
PROG struct Foo { int x; char c; } BEGIN { $x = 1; printf("%d %d %d %d %d\n", sizeof(struct Foo), sizeof((*(struct Foo*)0).x), sizeof((*(struct Foo*)0).c), sizeof(1 == 1), sizeof($x)); exit(); }
EXPECT 8 4 1 8 8
TIMEOUT 5

NAME sizeof_ints
PROG BEGIN { printf("%d %d %d %d %d %d\n", sizeof(uint8), sizeof(int8), sizeof(uint16), sizeof(int16), sizeof(uint32), sizeof(int32)); exit(); }
EXPECT 1 1 2 2 4 4
TIMEOUT 5

# printf only takes 7 args
NAME sizeof_ints_pt2
PROG BEGIN { printf("%d %d\n", sizeof(uint64), sizeof(int64)); exit(); }
EXPECT 8 8
TIMEOUT 5

NAME sizeof_btf
PROG BEGIN { printf("size=%d\n", sizeof(struct task_struct)); exit(); }
EXPECT_REGEX ^size=
TIMEOUT 5
REQUIRES_FEATURE btf

NAME offsetof
PROG struct Foo { int x; long l; char c; } BEGIN { printf("%ld\n", offsetof(struct Foo, x)); exit(); }
EXPECT_REGEX ^0$
TIMEOUT 5

NAME print args in kfunc
PROG kfunc:vfs_open { print(args); exit(); }
EXPECT_REGEX { .path = 0x[0-9a-f]+, .file = 0x[0-9a-f]+ }
REQUIRES_FEATURE kfunc
TIMEOUT 5
AFTER ./testprogs/syscall open

NAME args in kfunc store in map
PROG kfunc:vfs_open { @= args; exit(); }
EXPECT_REGEX @: { .path = 0x[0-9a-f]+, .file = 0x[0-9a-f]+ }
REQUIRES_FEATURE kfunc
TIMEOUT 5
AFTER ./testprogs/syscall open

NAME args in kfunc as a map key
PROG kfunc:vfs_open { @[args] = 1; exit(); }
EXPECT_REGEX @[{.path=0x[0-9a-f]+,.file=0x[0-9a-f]+}]: 1
REQUIRES_FEATURE kfunc
TIMEOUT 5
AFTER ./testprogs/syscall open

NAME args in uprobe print
PROG uprobe:./testprogs/uprobe_test:uprobeFunction1 { print(args); exit(); }
EXPECT_REGEX { .n = 0x[0-9a-f]+, .c = 120 }
REQUIRES_FEATURE dwarf
TIMEOUT 5
BEFORE ./testprogs/uprobe_test

NAME args in uprobe store in map
PROG uprobe:./testprogs/uprobe_test:uprobeFunction1 { @ = args; exit(); }
EXPECT_REGEX @: { .n = 0x[0-9a-f]+, .c = 120 }
REQUIRES_FEATURE dwarf
TIMEOUT 5
BEFORE ./testprogs/uprobe_test

NAME args in uprobe store in map and access field
PROG uprobe:./testprogs/uprobe_test:uprobeFunction1 { @ = args; print(@.c); exit(); }
EXPECT 120
REQUIRES_FEATURE dwarf
TIMEOUT 5
BEFORE ./testprogs/uprobe_test

NAME args in uprobe as a map key
PROG uprobe:./testprogs/uprobe_test:uprobeFunction1 { @[args] = 1; exit(); }
EXPECT_REGEX @[{.n=0x[0-9a-f]+,.c=120}]: 1
REQUIRES_FEATURE dwarf
TIMEOUT 5
BEFORE ./testprogs/uprobe_test

NAME jiffies
PROG i:ms:1 { printf("SUCCESS %llu\n", jiffies); exit(); }
EXPECT_REGEX SUCCESS [0-9]+
REQUIRES_FEATURE jiffies64
TIMEOUT 5
MIN_KERNEL 5.9
