From e4e83ec17cb49281829c36745473e033627ee670 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 30 Mar 2016 17:31:20 +0200 Subject: [PATCH] test.lua: Port `test_clang` to Lua --- tests/lua/test_clang.lua | 332 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 tests/lua/test_clang.lua diff --git a/tests/lua/test_clang.lua b/tests/lua/test_clang.lua new file mode 100644 index 0000000..b472ef8 --- /dev/null +++ b/tests/lua/test_clang.lua @@ -0,0 +1,332 @@ +require("test_helper") + +TestClang = {} + +function TestClang:test_probe_read1() + local text = [[ +#include +#include +int count_sched(struct pt_regs *ctx, struct task_struct *prev) { + pid_t p = prev->pid; + return (p != -1); +} +]] + local b = BPF:new{text=text, debug=0} + local fn = b:load_func("count_sched", 'BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_probe_read2() + local text = [[ +#include +#include +int count_foo(struct pt_regs *ctx, unsigned long a, unsigned long b) { + return (a != b); +} +]] + local b = BPF:new{text=text, debug=0} + local fn = b:load_func("count_foo", 'BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_probe_read_keys() + local text = [[ +#include +#include +BPF_HASH(start, struct request *); +int do_request(struct pt_regs *ctx, struct request *req) { + u64 ts = bpf_ktime_get_ns(); + start.update(&req, &ts); + return 0; +} + +int do_completion(struct pt_regs *ctx, struct request *req) { + u64 *tsp = start.lookup(&req); + if (tsp != 0) { + start.delete(&req); + } + return 0; +} + ]] + local b = BPF:new{text=text, debug=0} + local fns = b:load_funcs('BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_sscanf() + local text = [[ +BPF_TABLE("hash", int, struct { u64 a; u64 b; u32 c:18; u32 d:14; struct { u32 a; u32 b; } s; }, stats, 10); + +int foo(void *ctx) { + return 0; +} +]] + local b = BPF:new{text=text, debug=0} + local fn = b:load_func("foo", 'BPF_PROG_TYPE_KPROBE') + local t = b:get_table("stats") + local s1 = t:key_sprintf(2) + + assert_equals(s1, "0x2") + + local s2 = t:leaf_sprintf({{2, 3, 4, 1, {5, 6}}}) + local l = t:leaf_scanf(s2) + + assert_equals(tonumber(l.a), 2) + assert_equals(tonumber(l.b), 3) + assert_equals(tonumber(l.c), 4) + assert_equals(tonumber(l.d), 1) + assert_equals(tonumber(l.s.a), 5) + assert_equals(tonumber(l.s.b), 6) +end + +function TestClang:test_sscanf_array() + local text = [[ BPF_TABLE("hash", int, struct { u32 a[3]; u32 b; }, stats, 10); ]] + + local b = BPF:new{text=text, debug=0} + local t = b:get_table("stats") + + local s1 = t:key_sprintf(2) + assert_equals(s1, "0x2") + + local s2 = t:leaf_sprintf({{{1, 2, 3}, 4}}) + assert_equals(s2, "{ [ 0x1 0x2 0x3 ] 0x4 }") + + local l = t:leaf_scanf(s2) + assert_equals(l.a[0], 1) + assert_equals(l.a[1], 2) + assert_equals(l.a[2], 3) + assert_equals(l.b, 4) +end + +function TestClang:test_iosnoop() + local text = [[ +#include +#include + +struct key_t { + struct request *req; +}; + +BPF_TABLE("hash", struct key_t, u64, start, 1024); +int do_request(struct pt_regs *ctx, struct request *req) { + struct key_t key = {}; + + bpf_trace_printk("traced start %d\\n", req->__data_len); + + return 0; +} +]] + + local b = BPF:new{text=text, debug=0} + local fn = b:load_func("do_request", 'BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_blk_start_request() + local text = [[ +#include +#include +int do_request(struct pt_regs *ctx, int req) { + bpf_trace_printk("req ptr: 0x%x\n", req); + return 0; +} +]] + local b = BPF:new{text=text, debug=0} + local fn = b:load_func("do_request", 'BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_bpf_hash() + local text = [[ +BPF_HASH(table1); +BPF_HASH(table2, u32); +BPF_HASH(table3, u32, int); +]] + local b = BPF:new{text=text, debug=0} +end + +function TestClang:test_consecutive_probe_read() + local text = [[ +#include +#include +BPF_HASH(table1, struct super_block *); +int trace_entry(struct pt_regs *ctx, struct file *file) { + if (!file) return 0; + struct vfsmount *mnt = file->f_path.mnt; + if (mnt) { + struct super_block *k = mnt->mnt_sb; + u64 zero = 0; + table1.update(&k, &zero); + k = mnt->mnt_sb; + table1.update(&k, &zero); + } + + return 0; +} +]] + local b = BPF:new{text=text, debug=0} + local fn = b:load_func("trace_entry", 'BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_nested_probe_read() + local text = [[ +#include +int trace_entry(struct pt_regs *ctx, struct file *file) { + if (!file) return 0; + const char *name = file->f_path.dentry->d_name.name; + bpf_trace_printk("%s\\n", name); + return 0; +} +]] + local b = BPF:new{text=text, debug=0} + local fn = b:load_func("trace_entry", 'BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_char_array_probe() + local b = BPF:new{text=[[#include +int kprobe__blk_update_request(struct pt_regs *ctx, struct request *req) { + bpf_trace_printk("%s\\n", req->rq_disk->disk_name); + return 0; +}]]} +end + +function TestClang:test_probe_read_helper() + local b = BPF:new{text=[[ +#include +static void print_file_name(struct file *file) { + if (!file) return; + const char *name = file->f_path.dentry->d_name.name; + bpf_trace_printk("%s\\n", name); +} +static void print_file_name2(int unused, struct file *file) { + print_file_name(file); +} +int trace_entry1(struct pt_regs *ctx, struct file *file) { + print_file_name(file); + return 0; +} +int trace_entry2(struct pt_regs *ctx, int unused, struct file *file) { + print_file_name2(unused, file); + return 0; +} +]]} + local fn1 = b:load_func("trace_entry1", 'BPF_PROG_TYPE_KPROBE') + local fn2 = b:load_func("trace_entry2", 'BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_probe_struct_assign() + local b = BPF:new{text = [[ +#include +struct args_t { + const char *filename; + int flags; + int mode; +}; +int kprobe__sys_open(struct pt_regs *ctx, const char *filename, + int flags, int mode) { + struct args_t args = {}; + args.filename = filename; + args.flags = flags; + args.mode = mode; + bpf_trace_printk("%s\\n", args.filename); + return 0; +}; +]]} +end + +function TestClang:test_task_switch() + local b = BPF:new{text=[[ +#include +#include +struct key_t { + u32 prev_pid; + u32 curr_pid; +}; +BPF_TABLE("hash", struct key_t, u64, stats, 1024); +int kprobe__finish_task_switch(struct pt_regs *ctx, struct task_struct *prev) { + struct key_t key = {}; + u64 zero = 0, *val; + key.curr_pid = bpf_get_current_pid_tgid(); + key.prev_pid = prev->pid; + + val = stats.lookup_or_init(&key, &zero); + (*val)++; + return 0; +} +]]} +end + +function TestClang:test_probe_simple_assign() + local b = BPF:new{text=[[ +#include +#include +struct leaf { size_t size; }; +BPF_HASH(simple_map, u32, struct leaf); +int kprobe____kmalloc(struct pt_regs *ctx, size_t size) { + u32 pid = bpf_get_current_pid_tgid(); + struct leaf* leaf = simple_map.lookup(&pid); + if (leaf) + leaf->size += size; + return 0; +}]]} +end + +function TestClang:test_unop_probe_read() + local text = [[ +#include +int trace_entry(struct pt_regs *ctx, struct request *req) { + if (!(req->bio->bi_rw & 1)) + return 1; + if (((req->bio->bi_rw))) + return 1; + return 0; +} +]] + local b = BPF:new{text=text} + local fn = b:load_func("trace_entry", 'BPF_PROG_TYPE_KPROBE') +end + +function TestClang:test_complex_leaf_types() + local text = [[ +struct list; +struct list { + struct list *selfp; + struct list *another_selfp; + struct list *selfp_array[2]; +}; +struct empty { +}; +union emptyu { + struct empty *em1; + struct empty em2; + struct empty em3; + struct empty em4; +}; +BPF_TABLE("array", int, struct list, t1, 1); +BPF_TABLE("array", int, struct list *, t2, 1); +BPF_TABLE("array", int, union emptyu, t3, 1); +]] + local b = BPF:new{text=text} + local ffi = require("ffi") + + -- TODO: ptrs? + assert_equals(ffi.sizeof(b:get_table("t3").c_leaf), 8) +end + +function TestClang:test_cflags() + local text = [[ +#ifndef MYFLAG +#error "MYFLAG not set as expected" +#endif +]] + local b = BPF:new{text=text, cflags={"-DMYFLAG"}} +end + +function TestClang:test_exported_maps() + local b1 = BPF{text=[[BPF_TABLE_PUBLIC("hash", int, int, table1, 10);]]} + local b2 = BPF{text=[[BPF_TABLE("extern", int, int, table1, 10);]]} +end + +function TestClang:test_syntax_error() + assert_error_msg_contains( + "failed to compile BPF module", + BPF.new, + BPF, {text=[[int failure(void *ctx) { if (); return 0; }]]}) +end + +os.exit(LuaUnit.run()) -- 2.7.4