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 kprobes with glob matching
RUN {{BPFTRACE}} -l 'kprobe*'
EXPECT_REGEX kprobe:.*
TIMEOUT 1

NAME it lists kprobes with verbose mode
RUN {{BPFTRACE}} -lv kprobe:*
EXPECT_REGEX [ ]+[a-zA-Z_\*\s]+
REQUIRES_FEATURE btf
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 rawtracepoint params
RUN {{BPFTRACE}} -lv "rawtracepoint:*"
EXPECT_REGEX [ ]+[a-zA-Z_\*\s]+
REQUIRES_FEATURE btf
TIMEOUT 1

# The BTF FUNC_PROTOs for rawtracepoint params have an unnecessary initial
# void * and a retval that can't be used so make sure they are not
# included in the listing output
NAME it doesn't list the first rawtracepoint param or retval
RUN {{BPFTRACE}} -lv "rawtracepoint:consume_skb"
EXPECT_NONE void * __data
EXPECT_NONE int retval
REQUIRES_FEATURE btf
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 lists iter with regex filter
RUN {{BPFTRACE}} -l "iter:*"
EXPECT_REGEX iter:.*
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: invalid integer: a1111
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: invalid trailing bytes: 111a1
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: invalid integer: not_a_pid
TIMEOUT 1
WILL_FAIL

NAME pid outside of valid pid range
RUN {{BPFTRACE}} -p 5000000 file.bt
EXPECT ERROR: Pid out of range: 5000000
TIMEOUT 1
WILL_FAIL

NAME libraries under /usr/include are in the search path
RUN {{BPFTRACE}} -e "$(echo "#include <sys/xattr.h>"; echo "begin { }")" 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 { }")" 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); }')"
EXPECT 314
TIMEOUT 1

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

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

NAME delete map
PROG begin { @ = 1; @a[1] = 1; @b[1, 2] = 2; if (delete(@)) { printf("ok1\n"); } delete(@a, 1); if (delete(@b, (1, 2))) { printf("ok2\n"); } if (!delete(@b, (5, 6))) { printf("ok3\n"); } }
EXPECT ok1
EXPECT ok2
EXPECT ok3
TIMEOUT 1

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

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

NAME bad delete warning
PROG begin { @a[1] = 1; delete(@a, 2); }
EXPECT stdin:1:20-33: WARNING: Can't delete map element because it does not exist.
TIMEOUT 1

NAME bad delete no warning
PROG begin { @a[1] = 1; $x = delete(@a, 2); if (1 && !delete(@a, 3)) {} }
EXPECT_NONE stdin:1:20-33: WARNING: Can't delete map element because it does not exist.
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); }
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);  }
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 ringbuf: yes
TIMEOUT 1

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

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

NAME kaddr fails
PROG begin { print(kaddr("asdfzzzzzzz")) }
EXPECT stdin:1:9-35: ERROR: Failed to resolve kernel symbol: asdfzzzzzzz
       begin { print(kaddr("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(@));  }
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(@));  }
EXPECT len: 1
TIMEOUT 1

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

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

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

NAME has_key no_exists
PROG begin { @a[1] = 0; if (has_key(@a, 2)) { printf("ok\n"); }  }
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"); }  }
EXPECT ok

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

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

NAME block expression
PROG begin { let $a = { let $b = 1; $b }; print($a);  }
EXPECT 1
