NAME printf
PROG i:ms:1 { printf("hi!\n"); exit();}
EXPECT hi!
TIMEOUT 5

NAME printf_long_fmt
PROG i:ms:1 { printf("hi abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcbaabcdefghijklmnopqrstuvwxyz!\n"); exit();}
EXPECT ^hi abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcbaabcdefghijklmnopqrstuvwxyz!
TIMEOUT 5

NAME printf_argument
PROG i:ms:1 { printf("value: %dms100\n", 100); exit();}
EXPECT value: 100ms100
TIMEOUT 5

NAME printf_llu
PROG BEGIN { @start = nsecs; } i:s:1 { printf("Elapsed time: %llus\n", (nsecs - @start)/1000000000); clear(@start); exit();}
EXPECT Elapsed time: 1s
TIMEOUT 5

NAME printf_argument_alignment
RUN {{BPFTRACE}} -e 'struct Foo { int a; char b[10]; } uprobe:testprogs/uprobe_test:function2 { $foo = (struct Foo *)arg0; $foo2 = (struct Foo *)arg1; printf("%d %s %d %s\n", $foo->a, $foo->b, $foo2->a, $foo2->b) }' -c ./testprogs/uprobe_test
EXPECT 123 hello 456 world
TIMEOUT 5

NAME printf_more_arguments
PROG BEGIN { printf("%dst: %sa; %dnd: %sb;; %drd: %sc;;; %dth: %sd;;;;\\n", 1, "a", 2, "ab", 3, "abc", 4, "abcd"); exit(); }
EXPECT 1st: aa; 2nd: abb;; 3rd: abcc;;; 4th: abcdd;;;;
TIMEOUT 5

NAME time
PROG i:ms:1 { time("%H:%M:%S\n"); exit();}
EXPECT [0-9]*:[0-9]*:[0-9]*
TIMEOUT 5

NAME time_short
PROG i:ms:1 { time("%H-%M:%S\n"); exit();}
EXPECT [0-9]*-[0-9]*
TIMEOUT 5

NAME join
RUN {{BPFTRACE}} --unsafe -e 'i:ms:1 { system("echo 'A'"); } kprobe:sys_execve { join(arg1); exit();}'
EXPECT A
TIMEOUT 5

NAME join_delim
RUN {{BPFTRACE}} --unsafe -e 'i:ms:1 { system("echo 'A'"); } kprobe:sys_execve { join(arg1, ","); exit();}'
EXPECT A
TIMEOUT 5

NAME str
PROG t:syscalls:sys_enter_execve { printf("P: %s\n", str(args->filename)); exit();}
AFTER ./testprogs/syscall execve /bin/ls
EXPECT P: /*.
TIMEOUT 5

NAME buf
RUN {{BPFTRACE}} -e 'struct MyStruct { const char* a; char b[4]; uint8_t c[4]; int d[4]; uint16_t e[4]; uint64_t f[4] }; u:./testprogs/complex_struct:func { $s = (struct MyStruct *)arg0; printf("P: %r-%r-%r-%r-%r-%r\n", buf($s->a, 4), buf($s->b, 4), buf($s->c), buf($s->d), buf($s->e), buf($s->f)); exit(); }' -c ./testprogs/complex_struct
EXPECT P: \\x09\\x08\\x07\\x06-\\x05\\x04\\x03\\x02-\\x01\\x02\\x03\\x04-\\x05\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x08\\x00\\x00\\x00-\\x09\\x00\\x0a\\x00\\x0b\\x00\\x0c\\x00-\\x0d\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00
TIMEOUT 5
ARCH x86_64|ppc64le|aarch64

NAME buf
RUN {{BPFTRACE}} -e 'struct MyStruct { const char* a; char b[4]; uint8_t c[4]; int d[4]; uint16_t e[4]; uint64_t f[4] }; u:./testprogs/complex_struct:func { $s = (struct MyStruct *)arg0; printf("P: %r-%r-%r-%r-%r-%r\n", buf($s->a, 4), buf($s->b, 4), buf($s->c), buf($s->d), buf($s->e), buf($s->f)); exit(); }' -c ./testprogs/complex_struct
EXPECT P: \\x09\\x08\\x07\\x06-\\x05\\x04\\x03\\x02-\\x01\\x02\\x03\\x04-\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x08-\\x00\\x09\\x00\\x0a\\x00\\x0b\\x00\\x0c-\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0d\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10
TIMEOUT 5
ARCH s390x|ppc64

NAME buf_map_key
PROG i:ms:100 { @[buf("ok_key", 6)] = 1; exit(); }
EXPECT @\[ok_key\]: 1
TIMEOUT 5

NAME buf_map_multikey
PROG BEGIN { @[buf("ok_key", 8), 1] = hist(1); exit(); }
EXPECT @\[ok_key\\x00\\x00\, 1]
TIMEOUT 5

NAME buf_hist_map_key
PROG BEGIN { @[buf("ok_key", 8)] = hist(1); exit(); }
EXPECT @\[ok_key\\x00\\x00\]
TIMEOUT 5

NAME buf_map_value
PROG i:ms:100 { @ = buf("ok_value", 8); exit(); }
EXPECT @: ok_value
TIMEOUT 5

NAME ksym
PROG kprobe:do_nanosleep { printf("%s\n", ksym(reg("ip"))); exit();}
EXPECT do_nanosleep
TIMEOUT 5
ARCH x86_64
AFTER ./testprogs/syscall nanosleep 1e8

NAME ksym
PROG kprobe:do_nanosleep { printf("%s\n", ksym(reg("pswaddr"))); exit();}
EXPECT do_nanosleep
TIMEOUT 5
ARCH s390x
AFTER ./testprogs/syscall nanosleep 1e8

NAME ksym
PROG kprobe:do_nanosleep { printf("%s\n", ksym(reg("pc"))); exit();}
EXPECT do_nanosleep
TIMEOUT 5
ARCH aarch64
AFTER ./testprogs/syscall nanosleep 1e8

NAME ksym
PROG kprobe:do_nanosleep { printf("%s\n", ksym(reg("nip"))); exit();}
EXPECT do_nanosleep
TIMEOUT 5
ARCH ppc64|ppc64le
AFTER ./testprogs/syscall nanosleep 1e8

NAME system
RUN {{BPFTRACE}} --unsafe -e 'i:ms:100 { system("echo 'ok_system'"); exit();}'
EXPECT ok_system
TIMEOUT 5

NAME system_more_args
RUN {{BPFTRACE}} --unsafe -e 'i:ms:100 { system("echo %d %d %d %d %d %d %d", 1, 2, 3, 4, 5, 6, 7); exit();}'
EXPECT 1 2 3 4 5 6 7
TIMEOUT 5

NAME count
PROG i:ms:100 { @ = count(); exit();}
EXPECT @:\s[0-9]+
TIMEOUT 5

NAME sum
PROG kprobe:vfs_read { @bytes[comm] = sum(arg2); exit();}
EXPECT @.*\[.*\]\:\s[0-9]*
TIMEOUT 5
AFTER ./testprogs/syscall read

NAME avg
PROG kprobe:vfs_read { @bytes[comm] = avg(arg2); exit();}
EXPECT @.*\[.*\]\:\s[0-9]*
TIMEOUT 5
AFTER ./testprogs/syscall read

NAME min
PROG kprobe:vfs_read { @bytes[comm] = min(arg2); exit();}
EXPECT @.*\[.*\]\:\s[0-9]*
TIMEOUT 5
AFTER ./testprogs/syscall read

NAME max
PROG kprobe:vfs_read { @bytes[comm] = max(arg2); exit();}
EXPECT @.*\[.*\]\:\s[0-9]*
AFTER ./testprogs/syscall read
TIMEOUT 5

NAME stats
PROG kprobe:vfs_read { @bytes[comm] = stats(arg2); exit();}
EXPECT @.*\[.*\]\:\scount\s[0-9]*\,\saverage\s[0-9]*\,\stotal\s[0-9]*
TIMEOUT 5
AFTER ./testprogs/syscall read

NAME hist
PROG kretprobe:vfs_read { @bytes = hist(retval); exit();}
EXPECT @bytes: *\n[\[(].*
AFTER ./testprogs/syscall read
TIMEOUT 5

NAME lhist
PROG kretprobe:vfs_read { @bytes = lhist(retval, 0, 10000, 1000); exit()}
EXPECT @bytes: *\n[\[(].*
TIMEOUT 5
AFTER ./testprogs/syscall read

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

NAME kstack perf mode
PROG k:do_nanosleep { printf("SUCCESS '$test' %s\n", kstack(perf, 1)); exit(); }
EXPECT SUCCESS kstack
TIMEOUT 5
AFTER ./testprogs/syscall nanosleep  1e8


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

NAME cat
PROG i:ms:1 { cat("/proc/uptime"); exit();}
EXPECT [0-9]*.[0-9]* [0-9]*.[0-9]*
TIMEOUT 5

NAME cat_more_args
PROG i:ms:1 { cat("/%s%s%s%s/%s%s%s", "p", "r", "o", "c", "u", "p", "time"); exit();}
EXPECT [0-9]*.[0-9]* [0-9]*.[0-9]*
TIMEOUT 5

NAME uaddr
RUN {{BPFTRACE}} -e 'uprobe:testprogs/uprobe_test:function1 { printf("0x%lx -- 0x%lx\n", *uaddr("GLOBAL_A"), *uaddr("GLOBAL_C")); exit(); }' -c ./testprogs/uprobe_test
EXPECT 0x55555555 -- 0x33333333
TIMEOUT 5

NAME ntop static ip
PROG i:ms:100 { printf("IP: %s, %s, %s, %s\n", ntop(1), ntop(0x0100007f), ntop(0xffff0000), ntop(0x0000ffff)); exit() }
EXPECT IP: 1.0.0.0, 127.0.0.1, 0.0.255.255, 255.255.0.0
ARCH x86_64|aarch64|ppc64le
TIMEOUT 5

NAME ntop static ip
PROG i:ms:100 { printf("IP: %s, %s, %s, %s\n", ntop(0x01000000), ntop(0x7f000001), ntop(0x0000ffff), ntop(0xffff0000)); exit() }
EXPECT IP: 1.0.0.0, 127.0.0.1, 0.0.255.255, 255.255.0.0
ARCH s390x|ppc64
TIMEOUT 5

NAME usym
PROG i:ms:100 { @=usym(1); @a=@; exit(); }
EXPECT ^@a: 0x1$
TIMEOUT 5

NAME print_non_map
PROG BEGIN { $x = 5; print($x); exit() }
EXPECT 5
TIMEOUT 1

NAME print_non_map_builtin
PROG BEGIN { print(comm); exit() }
EXPECT bpftrace
TIMEOUT 1

NAME print_non_map_tuple
PROG BEGIN { $t = (1, 2, "string"); print($t); exit() }
EXPECT (1, 2, string)
TIMEOUT 1

NAME print_non_map_array
PROG struct A { int x[4]; } uprobe:./testprogs/array_access:test_struct { $a = ((struct A *) arg0)->x; print($a); exit(); }
EXPECT \[1,2,3,4\]
TIMEOUT 5
AFTER ./testprogs/array_access

NAME print_non_map_multi_dimensional_array
PROG struct B { int y[2][2]; } uprobe:./testprogs/array_access:test_struct { $b = ((struct B *) arg1)->y; print($b); exit(); }
EXPECT \[\[5,6\],\[7,8\]\]
TIMEOUT 5
AFTER ./testprogs/array_access

NAME print_non_map_struct
PROG struct Foo { int m; int n; } uprobe:./testprogs/simple_struct:func { $f = *((struct Foo *) arg0); print($f); exit(); }
EXPECT { .m = 2, .n = 3 }
TIMEOUT 5
AFTER ./testprogs/simple_struct

NAME strftime
PROG BEGIN { $ts = strftime("%m/%d/%y", nsecs); printf("%s\n", $ts); exit(); }
EXPECT [0-9]{2}\/[0-9]{2}\/[0-9]{2}
TIMEOUT 5

NAME strftime_as_map_key
PROG BEGIN { @[strftime("%m/%d/%y", nsecs)] = 1; exit();}
EXPECT \[[0-9]{2}\/[0-9]{2}\/[0-9]{2}\]: 1
TIMEOUT 5

NAME strftime_as_map_value
PROG BEGIN { @[nsecs] = strftime("%m/%d/%y", nsecs); exit();}
EXPECT @\[[0-9]*\]: [0-9]{2}\/[0-9]{2}\/[0-9]{2}
TIMEOUT 5

# Output two microsecond timestamps, 123000 nsecs apart. Use python to evaluate and verify there's a 123us delta
#
# Note we add a `1` before the timestamp b/c leading zeros (eg `0123`) is invalid integer in python.
NAME strftime_microsecond_extension
RUN {{BPFTRACE}} -e 'BEGIN { printf("%s - %s\n", strftime("1%f", 1000123000), strftime("1%f", 0)); exit(); }' | tail -n +2 | xargs -I{} python -c "print({})"
EXPECT 123
TIMEOUT 1

# Similar to above test but test that rolling over past 1s works as expected
NAME strftime_microsecond_extension_rollover
RUN {{BPFTRACE}} -e 'BEGIN { printf("%s - %s\n", strftime("1%f", 1000000123000), strftime("1%f", 0)); exit(); }' | tail -n +2 | xargs -I{} python -c "print({})"
EXPECT 123
TIMEOUT 1

NAME print_avg_map_args
PROG BEGIN { print("BEGIN"); @["a"] = avg(10); @["b"] = avg(20); @["c"] = avg(30); @["d"] = avg(40); print(@, 2, 10); print("END"); clear(@); exit(); }
EXPECT BEGIN\n@\[c\]: 3\n@\[d\]: 4\n\nEND
TIMEOUT 1

NAME print_avg_map_with_large_top
PROG BEGIN { print("BEGIN"); @["a"] = avg(10); @["b"] = avg(20); @["c"] = avg(30); @["d"] = avg(40); print(@, 10, 10); print("END"); clear(@); exit(); }
EXPECT BEGIN\n@\[a\]: 1\n@\[b\]: 2\n@\[c\]: 3\n@\[d\]: 4\n\nEND
TIMEOUT 1

NAME print_hist_with_top_arg
PROG BEGIN { print("BEGIN"); @[1] = hist(10); @[2] = hist(20); @[3] = hist(30); print(@, 2); print("END"); clear(@); exit(); }
EXPECT BEGIN\n@\[2\]:(.*\n)+@\[3\]:(.*\n)+END
TIMEOUT 1

NAME print_hist_with_large_top_arg
PROG BEGIN { print("BEGIN"); @[1] = hist(10); @[2] = hist(20); @[3] = hist(30); print(@, 10); print("END"); clear(@); exit(); }
EXPECT BEGIN\n@\[1\]:(.*\n)+@\[2\]:(.*\n)+@\[3\]:(.*\n)+END
TIMEOUT 1

NAME path
RUN {{BPFTRACE}} -ve 'kfunc:filp_close { $f = path(args->filp->f_path); if (!strncmp($f, "/tmp/bpftrace_runtime_test_syscall_gen_read_temp", 49)) { printf("OK\n"); exit(); } }'
EXPECT OK
REQUIRES_FEATURE dpath
TIMEOUT 5
AFTER ./testprogs/syscall read

NAME macaddr
RUN {{BPFTRACE}} -e 'struct MyStruct { const char* ignore; char mac[6]; }; u:./testprogs/complex_struct:func { $s = ((struct MyStruct *)arg0); printf("P: %s\n", macaddr($s->mac)); exit(); }' -c ./testprogs/complex_struct
EXPECT P: 05:04:03:02:01:02
TIMEOUT 5

NAME macaddr as map key
RUN {{BPFTRACE}} -e 'struct MyStruct { const char* ignore; char mac[6]; }; u:./testprogs/complex_struct:func { $s = ((struct MyStruct *)arg0); @[macaddr($s->mac)] = 1; exit(); }' -c ./testprogs/complex_struct
EXPECT @\[05:04:03:02:01:02\]: 1
TIMEOUT 5

NAME macaddr as map value
RUN {{BPFTRACE}} -e 'struct MyStruct { const char* ignore; char mac[6]; }; u:./testprogs/complex_struct:func { $s = ((struct MyStruct *)arg0); @[1] = macaddr($s->mac); exit(); }' -c ./testprogs/complex_struct
EXPECT \[1\]: 05:04:03:02:01:02
TIMEOUT 5

NAME iter:task
PROG iter:task { printf("OK"); }
EXPECT OK
REQUIRES_FEATURE iter:task
TIMEOUT 5

NAME iter:task_file
PROG iter:task_file { printf("OK"); }
EXPECT OK
REQUIRES_FEATURE iter:task_file
TIMEOUT 5
