NAME it shows version
RUN {{BPFTRACE}} --version
EXPECT_REGEX ^bpftrace v\d
TIMEOUT 1

NAME it shows usage with help flag
RUN {{BPFTRACE}} -h
EXPECT USAGE:
TIMEOUT 1

NAME it shows usage with bad flag
RUN {{BPFTRACE}} -idonotexist
EXPECT USAGE:
TIMEOUT 1
WILL_FAIL

NAME errors on non existent file
RUN {{BPFTRACE}} non_existent_file.bt
EXPECT ERROR: failed to open file 'non_existent_file.bt': No such file or directory
TIMEOUT 1
WILL_FAIL

NAME piped script
RUN {{BPFTRACE}} - < runtime/scripts/hello_world.bt
EXPECT hello world!
TIMEOUT 1

NAME it lists kprobes
RUN {{BPFTRACE}} -l | grep kprobes
EXPECT_REGEX kprobe:.*
TIMEOUT 1

NAME it lists tracepoints
RUN {{BPFTRACE}} -l | grep tracepoint
EXPECT_REGEX tracepoint:.*
TIMEOUT 1

NAME it lists software events
RUN {{BPFTRACE}} -l | grep software
EXPECT_REGEX software:.*
TIMEOUT 1

NAME it lists hardware events
RUN {{BPFTRACE}} -l | grep hardware
EXPECT_REGEX hardware:.*
TIMEOUT 1

NAME it lists fentry
RUN {{BPFTRACE}} -l | grep fentry
EXPECT_REGEX fentry:.*
REQUIRES_FEATURE btf
REQUIRES_FEATURE fentry
TIMEOUT 1

NAME it lists rawtracepoints
RUN {{BPFTRACE}} -l | grep rawtracepoint
EXPECT_REGEX rawtracepoint:.*
TIMEOUT 1

NAME it lists fentry params
RUN {{BPFTRACE}} -lv "fentry:*"
EXPECT_REGEX [ ]+[a-zA-Z_\*\s]+
REQUIRES_FEATURE btf
REQUIRES_FEATURE fentry
TIMEOUT 1

NAME it lists kprobes with regex filter
RUN {{BPFTRACE}} -l "kprobe:*"
EXPECT_REGEX kprobe:.*
TIMEOUT 1

NAME it lists kretprobes with regex filter
RUN {{BPFTRACE}} -l "kretprobe:*"
EXPECT_REGEX kretprobe:.*
TIMEOUT 1

NAME it lists uprobes with regex filter
RUN {{BPFTRACE}} -l "uprobe:./testprogs/syscall:*"
EXPECT_REGEX uprobe:.*
TIMEOUT 1

NAME it lists uretprobes with regex filter
RUN {{BPFTRACE}} -l "uretprobe:./testprogs/syscall:*"
EXPECT_REGEX uretprobe:.*
TIMEOUT 1

NAME it lists tracepoints with regex filter
RUN {{BPFTRACE}} -l "tracepoint:raw_syscalls:*"
EXPECT tracepoint:raw_syscalls:sys_exit
TIMEOUT 1

NAME it lists software events with regex filter
RUN {{BPFTRACE}} -l "software:*"
EXPECT software:cpu:
TIMEOUT 1

NAME it lists hardware events with regex filter
RUN {{BPFTRACE}} -l "hardware:*"
EXPECT hardware:cpu-cycles:
TIMEOUT 1

NAME it lists fentry events with regex filter
RUN {{BPFTRACE}} -l "fentry:*"
EXPECT_REGEX fentry:.*
REQUIRES_FEATURE btf
REQUIRES_FEATURE fentry
TIMEOUT 1

NAME it lists fexit events with regex filter
RUN {{BPFTRACE}} -l "fexit:*"
EXPECT_REGEX fexit:.*
REQUIRES_FEATURE btf
REQUIRES_FEATURE fentry
TIMEOUT 1

NAME it lists interval probes with regex filter
RUN {{BPFTRACE}} -l "interval:*"
EXPECT interval:hz:
EXPECT interval:us:
EXPECT interval:ms:
EXPECT interval:s:
TIMEOUT 1

NAME it lists profile probes with regex filter
RUN {{BPFTRACE}} -l "profile:*"
EXPECT profile:hz:
EXPECT profile:us:
EXPECT profile:ms:
EXPECT profile:s:
TIMEOUT 1

NAME listing with wildcarded probe type
RUN {{BPFTRACE}} -l "*ware:*"
EXPECT_REGEX hardware:.*
EXPECT_REGEX software:.*
TIMEOUT 1

NAME it lists rawtracepoint with regex filter
RUN {{BPFTRACE}} -l "rawtracepoint:*"
EXPECT_REGEX rawtracepoint:.*
TIMEOUT 1

NAME it only lists probes in the program
RUN {{BPFTRACE}} -l -e 'fentry:vmlinux:vfs_read { exit(); }'
EXPECT fentry:vmlinux:vfs_read
EXPECT_NONE fentry:vmlinux:vfs_write

NAME it lists uprobes in the program
RUN {{BPFTRACE}} -l -e 'uretprobe:*:uprobeFunction* { exit(); }' -p {{BEFORE_PID}}
EXPECT_REGEX uretprobe:[\S]+uprobe_test:uprobeFunction1
BEFORE ./testprogs/uprobe_test

NAME it lists multiple probes in the program
RUN {{BPFTRACE}} -l -e 'hardware:cache-misses:10 { exit(); } tracepoint:xdp:mem_connect { exit(); }'
EXPECT hardware:cache-misses:
EXPECT tracepoint:xdp:mem_connect

NAME it lists struct definitions
RUN {{BPFTRACE}} -lv 'struct task_struct'
EXPECT struct task_struct {
TIMEOUT 2

NAME it lists probes in a given file
RUN {{BPFTRACE}} -l runtime/scripts/interval_order.bt
EXPECT interval:ms:
EXPECT interval:s:
EXPECT interval:us:

NAME warning on non existent file
RUN {{BPFTRACE}} -l non_existent_file.bt
EXPECT WARNING: It appears that 'non_existent_file.bt' is a filename but the file does not exist. Treating 'non_existent_file.bt' as a search pattern.
TIMEOUT 1
WILL_FAIL

NAME pid fails validation with leading non-number
RUN {{BPFTRACE}} -p a1111 file.bt
EXPECT ERROR: Failed to parse pid: pid 'a1111' is not a valid decimal number
TIMEOUT 1
WILL_FAIL

NAME pid fails validation with non-number in between
RUN {{BPFTRACE}} -p 111a1 file.bt
EXPECT ERROR: Failed to parse pid: pid '111a1' is not a valid decimal number
TIMEOUT 1
WILL_FAIL

NAME pid fails validation with non-numeric argument
RUN {{BPFTRACE}} -p not_a_pid file.bt
EXPECT ERROR: Failed to parse pid: pid 'not_a_pid' is not a valid decimal number
TIMEOUT 1
WILL_FAIL

NAME pid outside of valid pid range
RUN {{BPFTRACE}} -p 5000000 file.bt
EXPECT ERROR: Failed to parse pid: pid '5000000' out of valid pid range [1,4194304]
TIMEOUT 1
WILL_FAIL

NAME libraries under /usr/include are in the search path
RUN {{BPFTRACE}} -e "$(echo "#include <sys/xattr.h>"; echo "BEGIN { exit(); }")" 2>&1
EXPECT_NONE file not found
REQUIRES ls /usr/include/sys/xattr.h
TIMEOUT 1

NAME non existent library include fails
RUN {{BPFTRACE}} -e "$(echo "#include <lol/no.h>"; echo "BEGIN { exit(); }")" 2>&1
EXPECT definitions.h:2:10: fatal error: 'lol/no.h' file not found
TIMEOUT 1
WILL_FAIL

NAME defines work
RUN {{BPFTRACE}} -e "$(echo '#define _UNDERSCORE 314'; echo 'BEGIN { printf("%d\n", _UNDERSCORE); exit(); }')"
EXPECT 314
TIMEOUT 1

NAME clear map
PROG BEGIN { @ = 1; @a[1] = 1; clear(@); clear(@a); printf("ok\n"); exit(); }
EXPECT ok
TIMEOUT 1

NAME clear count-map
PROG BEGIN { @ = count(); @a[1] = count(); clear(@); clear(@a); exit(); }
EXPECT @: 0
TIMEOUT 1

NAME delete map
PROG BEGIN { @ = 1; @a[1] = 1; @b[1, 2] = 2; delete(@); delete(@a, 1); delete(@b, (1, 2)); printf("ok\n"); exit(); }
EXPECT ok
TIMEOUT 1

NAME delete count-map
PROG BEGIN { @ = count(); @a[1] = count(); delete(@); delete(@a, 1); exit(); }
EXPECT @: 0
TIMEOUT 1

NAME delete deprecated
PROG BEGIN { @a[1] = 1; @b[2, "hi"] = 2; delete(@a[1]); delete(@b[2, "hi"]); exit(); }
EXPECT_NONE @a[1]: 1
EXPECT_NONE @b[2, hi]: 2
TIMEOUT 1

NAME increment/decrement map
PROG BEGIN { @x = 10; printf("%d", @x++); printf(" %d", ++@x); printf(" %d", @x--); printf(" %d\n", --@x); delete(@x); exit(); }
EXPECT 10 12 12 10
TIMEOUT 1

NAME parallel map access
RUN {{BPFTRACE}} runtime/scripts/parallel_map_access.bt --no-warnings
EXPECT SUCCESS
TIMEOUT 10

NAME increment/decrement variable
PROG BEGIN { $x = 10; printf("%d", $x++); printf(" %d", ++$x); printf(" %d", $x--); printf(" %d\n", --$x); exit(); }
EXPECT 10 12 12 10
TIMEOUT 1

NAME spawn child
RUN {{BPFTRACE}} -e 'i:ms:500 { printf("%d\n", cpid); }' -c './testprogs/syscall nanosleep 1e9'
EXPECT_REGEX [0-9]+
TIMEOUT 3

NAME info flag
RUN {{BPFTRACE}} --info
EXPECT_REGEX perf_event_array: yes
TIMEOUT 1

NAME basic while loop
PROG BEGIN { $a = 0; while ($a <= 100) { @=avg($a++) } exit(); }
EXPECT @: 50
REQUIRES_FEATURE loop

NAME disable warnings
RUN {{BPFTRACE}} --no-warnings -e 'BEGIN { @x = stats(10); print(@x, 2); clear(@x); exit();}' 2>&1| grep -c -E "WARNING|invalid option"
EXPECT_REGEX ^0$
TIMEOUT 1
WILL_FAIL

NAME kaddr fails
PROG BEGIN { print(kaddr("asdfzzzzzzz")) }
EXPECT ERROR: Failed to compile: Failed to resolve kernel symbol: asdfzzzzzzz
TIMEOUT 1
WILL_FAIL

NAME variable strings are memset
PROG BEGIN { $x = "xxxxx"; $x = "a"; @[$x] = 1; $y = "yyyyy"; $y = "a"; @[$y] = 1; printf("len: %d\n", len(@)); exit(); }
EXPECT len: 1
TIMEOUT 1

NAME map strings are memset
PROG BEGIN { @x = "xxxxx"; @x = "a"; @[@x] = 1; @y = "yyyyy"; @y = "a"; @[@y] = 1; printf("len: %d\n", len(@)); exit(); }
EXPECT len: 1
TIMEOUT 1

NAME print_per_cpu_map_vals
PROG BEGIN { @a = avg(5); @c = count(); @s = sum(5); @mn = min(1); @mx = max(-1); print((@a, @c, @s, @mn, @mx)); exit(); }
EXPECT (5, 1, 5, 1, -1)
TIMEOUT 3

NAME print large int
PROG BEGIN { $a = 10223372036854775807; print(($a)); exit(); }
EXPECT 10223372036854775807
TIMEOUT 1

NAME has_key exists
PROG BEGIN { @a[1] = 0; if (has_key(@a, 1)) { printf("ok\n"); } exit(); }
EXPECT ok

NAME has_key no_exists
PROG BEGIN { @a[1] = 0; if (has_key(@a, 2)) { printf("ok\n"); } exit(); }
EXPECT_NONE ok

NAME has_key complex tuple
PROG BEGIN { @a[1, ("hello", (int8)5)] = 0; if (has_key(@a, (1, ("hello", 5)))) { printf("ok\n"); } exit(); }
EXPECT ok

NAME has_key map value as key
PROG BEGIN { @g = 2; @a[2] = 0; if (has_key(@a, @g)) { printf("ok\n"); } exit(); }
EXPECT ok

NAME has_key map keys and values
PROG BEGIN { @a[1] = 1; @b[has_key(@a, 1)] = has_key(@a, 2); exit(); }
EXPECT @b[1]: 0

NAME has_key as a variable
PROG BEGIN { @a[1] = 1; $b = has_key(@a, 1); $c = has_key(@a, 2); print(($b, $c)); exit(); }
EXPECT (1, 0)

NAME exit code
PROG BEGIN { exit(69); }
RETURN_CODE 69
TIMEOUT 1
