# -*- Autotest -*- AT_BANNER([problem report]) ## ------- ## ## summary ## ## ------- ## AT_TESTFUN([summary], [[ #include "problem_report.h" #include "internal_libreport.h" #include int main(int argc, char **argv) { const char *const test_format_result[][2] = { { "%summary:: [abrt] trivial string", "[abrt] trivial string" }, { "%summary:: [abrt] %package%", "[abrt] libreport" }, { "%summary:: [abrt] %package%[[ : %crash_function%()]][[ : %does_not_exist%]][[ : %reason%]][[ TAINTED: %taint_flags%]]", "[abrt] libreport : run_event() : Killed by SIGSEGV" }, { "%summary:: [abrt] %package%[[ : %crash_function%[[ : %does_not_exist%]]()]][[ : %reason%]]", "[abrt] libreport : run_event() : Killed by SIGSEGV" }, { "%summary:: [abrt] %package%[[ : %does_not_exist%[[ : %crash_function%()]]]][[ : %reason%]]", "[abrt] libreport : Killed by SIGSEGV" }, { "%summary:: [[%does_not_exist%]][[%once_more%]][abrt] %package%", "[abrt] libreport" }, { "", "Killed by SIGSEGV" }, }; g_verbose = 3; problem_data_t *data = problem_data_new(); problem_data_add_text_noteditable(data, "package", "libreport"); problem_data_add_text_noteditable(data, "crash_function", "run_event"); problem_data_add_text_noteditable(data, "reason", "Killed by SIGSEGV"); for (size_t i = 0; i < sizeof(test_format_result)/sizeof(*test_format_result); ++i) { problem_formatter_t *pf = problem_formatter_new(); assert(!problem_formatter_load_string(pf, test_format_result[i][0])); problem_report_t *pr = NULL; assert(!problem_formatter_generate_report(pf, data, &pr)); assert(pr != NULL); const char *summary = problem_report_get_summary(pr); assert(summary != NULL); fprintf(stderr, "expected: '%s'\n", test_format_result[i][1]); fprintf(stderr, "result : '%s'\n", summary); assert(strcmp(test_format_result[i][1], summary) == 0); problem_report_free(pr); problem_formatter_free(pf); } problem_data_free(data); return 0; } ]]) ## ---------- ## ## desciption ## ## ---------- ## AT_TESTFUN([description], [[ #include "problem_report.h" #include "internal_libreport.h" #include #include "testsuite.h" int main(int argc, char **argv) { const char *const test_format_result[][2] = { { "\n"\ "\n"\ "\n"\ "Single line\n" "\n"\ "\n"\ "\n", "Single line\n" }, { "\n"\ "\n"\ "\n"\ "Comment:: %bare_comment" "\n"\ "\n"\ "\n"\ "Ad-hoc line\n" "\n"\ "\n"\ "\n"\ "Additional:: package,\\\n" "uuid,cwd\\\\" ",user_name" "\n"\ "\n", "Comment:\n" \ "Hello, world!\n" "\n"\ "\n"\ "Ad-hoc line\n" "\n"\ "\n"\ "\n"\ "Additional:\n"\ "package: libreport\n"\ "uuid: 123456789ABCDEF\n"\ "user_name: abrt\n", }, { ":: %bare_description", "I run will_segfault and\n"\ "it crashed as expected\n" }, { "User:: %bare_user_name,uid\n"\ "Additional info:: -uuid,%oneline,-comment,-package", "User:\n"\ "abrt\n"\ "uid: 69\n"\ "Additional info:\n"\ "analyzer: CCpp\n"\ "root: /var/run/mock/abrt\n"\ "type: CCpp\n" }, { ":: %reporter", NULL /* do no check results*/ }, { "Truncated backtrace:: %bare_%short_backtrace", "Truncated backtrace:\n" "Thread no. 0 (7 frames)\n" " #1 crash at will_segfault.c:19\n" " #2 varargs at will_segfault.c:31\n" " #3 inlined at will_segfault.c:40\n" " #4 f at will_segfault.c:45\n" " #5 callback at will_segfault.c:50\n" " #6 call_me_back at libwillcrash.c:8\n" " #7 recursive at will_segfault.c:59\n" }, }; g_verbose = 3; problem_data_t *data = problem_data_new(); problem_data_add_text_noteditable(data, "package", "libreport"); problem_data_add_text_noteditable(data, "analyzer", "CCpp"); problem_data_add_text_noteditable(data, "type", "CCpp"); problem_data_add_text_noteditable(data, "comment", "Hello, world!"); problem_data_add_text_noteditable(data, "uuid", "123456789ABCDEF"); problem_data_add_text_noteditable(data, "uid", "69"); problem_data_add_text_noteditable(data, "user_name", "abrt"); problem_data_add_text_noteditable(data, "root", "/var/run/mock/abrt"); problem_data_add_text_noteditable(data, "description", "I run will_segfault and\nit crashed as expected\n"); problem_data_add_text_noteditable(data, "backtrace", "Thread 1 (LWP 11865):\n"\ "#0 printf (__fmt=0x400acf \"Result: %d\\n\") at /usr/include/bits/stdio2.h:104\n"\ "No locals.\n"\ "#1 crash (p=p@entry=0x0) at will_segfault.c:19\n"\ "i = \n"\ "#2 0x0000000000400964 in varargs (num_args=1, num_args@entry=2) at will_segfault.c:31\n"\ "p = \n"\ "ap = {{gp_offset = 24, fp_offset = 32767, overflow_arg_area = 0x7fff4fc8a0c0, reg_save_area = 0x7fff4fc8a080}}\n"\ "#3 0x00000000004009be in inlined (p=0x0) at will_segfault.c:40\n"\ "num = 42\n"\ "#4 f (p=p@entry=0x0) at will_segfault.c:45\n"\ "No locals.\n"\ "#5 0x00000000004009e9 in callback (data=data@entry=0x0) at will_segfault.c:50\n"\ "No locals.\n"\ "#6 0x00000032f76006f9 in call_me_back (cb=cb@entry=0x4009e0 , data=data@entry=0x0) at libwillcrash.c:8\n"\ "res = \n"\ "#7 0x0000000000400a14 in recursive (i=i@entry=0) at will_segfault.c:59\n"\ "p = \n"\ "#8 0x0000000000400a00 in recursive (i=i@entry=1) at will_segfault.c:66\n"\ "No locals.\n"\ "#9 0x0000000000400a00 in recursive (i=i@entry=2) at will_segfault.c:66\n"\ "No locals.\n"\ "#10 0x0000000000400775 in main (argc=, argv=) at will_segfault.c:83\n"\ "No locals.\n"\ "From To Syms Read Shared Object Library\n"\ "0x00000032f76005f0 0x00000032f7600712 Yes /lib64/libwillcrash.so.0\n"\ "0x0000003245c1f4f0 0x0000003245d6aca4 Yes /lib64/libc.so.6\n"\ "0x0000003245800b10 0x000000324581b6d0 Yes /lib64/ld-linux-x86-64.so.2\n"\ "$1 = 0x0\n" "No symbol \"__glib_assert_msg\" in current context.\n"\ "rax 0xf 15\n"\ "rbx 0x0 0\n"\ "rcx 0x7ff96f752000 140709293531136\n"\ "rdx 0x3245fb9a40 215922481728\n"\ "rsi 0x7ff96f752000 140709293531136\n"\ "rdi 0x1 1\n"\ "rbp 0x400a30 0x400a30 <__libc_csu_init>\n"\ "rsp 0x7fff4fc8a050 0x7fff4fc8a050\n"\ "r8 0xffffffff 4294967295\n"\ "r9 0x0 0\n"\ "r10 0x22 34\n"\ "r11 0x246 582\n"\ "r12 0x40079f 4196255\n"\ "r13 0x7fff4fc8a210 140734531936784\n"\ "r14 0x0 0\n"\ "r15 0x0 0\n"\ "rip 0x4008ae 0x4008ae \n"\ "eflags 0x10246 [ PF ZF IF RF ]\n"\ "cs 0x33 51\n"\ "ss 0x2b 43\n"\ "ds 0x0 0\n"\ "es 0x0 0\n"\ "fs 0x0 0\n"\ "gs 0x0 0\n"\ "st0 0 (raw 0x00000000000000000000)\n"\ "st1 0 (raw 0x00000000000000000000)\n"\ "st2 0 (raw 0x00000000000000000000)\n"\ "st3 0 (raw 0x00000000000000000000)\n"\ "st4 0 (raw 0x00000000000000000000)\n"\ "st5 0 (raw 0x00000000000000000000)\n"\ "st6 0 (raw 0x00000000000000000000)\n"\ "st7 0 (raw 0x00000000000000000000)\n"\ "fctrl 0x37f 895\n"\ "fstat 0x0 0\n"\ "ftag 0xffff 65535\n"\ "fiseg 0x0 0\n"\ "fioff 0x0 0\n"\ "foseg 0x0 0\n"\ "fooff 0x0 0\n"\ "fop 0x0 0\n"\ "xmm0 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm1 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x2f }, v8_int16 = {0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f}, v4_int32 = {0x2f2f2f2f, 0x2f2f2f2f, 0x2f2f2f2f, 0x2f2f2f2f}, v2_int64 = {0x2f2f2f2f2f2f2f2f, 0x2f2f2f2f2f2f2f2f}, uint128 = 0x2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f}\n"\ "xmm2 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm3 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 , 0xff, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff00, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0xff00}, v2_int64 = {0x0, 0xff0000000000}, uint128 = 0x0000ff00000000000000000000000000}\n"\ "xmm4 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0xff0000, 0x0}, v2_int64 = {0x0, 0xff0000}, uint128 = 0x0000000000ff00000000000000000000}\n"\ "xmm5 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm6 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm7 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm8 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm9 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm10 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm11 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm12 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 , 0xff, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff}, v4_int32 = {0x0, 0x0, 0x0, 0xff0000}, v2_int64 = {0x0, 0xff000000000000}, uint128 = 0x00ff0000000000000000000000000000}\n"\ "xmm13 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm14 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm15 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "mxcsr 0x1f80 [ IM DM ZM OM UM PM ]\n"\ "Dump of assembler code for function crash:\n"\ " 0x00000000004008a0 <+0>: push %rbx\n"\ " 0x00000000004008a1 <+1>: mov %rdi,%rbx\n"\ " 0x00000000004008a4 <+4>: mov $0x400ac0,%edi\n"\ " 0x00000000004008a9 <+9>: callq 0x4006f0 \n"\ " => 0x00000000004008ae <+14>: mov (%rbx),%edx\n"\ " 0x00000000004008b0 <+16>: mov $0x400acf,%esi\n"\ " 0x00000000004008b5 <+21>: mov $0x1,%edi\n"\ " 0x00000000004008ba <+26>: xor %eax,%eax\n"\ " 0x00000000004008bc <+28>: callq 0x400740 <__printf_chk@plt>\n"\ " 0x00000000004008c1 <+33>: pop %rbx\n"\ " 0x00000000004008c2 <+34>: retq\n"\ "End of assembler dump.\n" ); for (size_t i = 0; i < sizeof(test_format_result)/sizeof(*test_format_result); ++i) { problem_formatter_t *pf = problem_formatter_new(); assert(!problem_formatter_load_string(pf, test_format_result[i][0])); problem_report_t *pr = NULL; assert(!problem_formatter_generate_report(pf, data, &pr)); assert(pr != NULL); const char *summary = problem_report_get_description(pr); assert(summary != NULL); if (test_format_result[i][1] != NULL) { fprintf(stderr, "####\n"); fprintf(stderr, "expected: '%s'\n", test_format_result[i][1]); fprintf(stderr, "====\n"); fprintf(stderr, "result : '%s'\n", summary); fprintf(stderr, "####\n"); TS_ASSERT_STRING_EQ(summary, test_format_result[i][1], "Correct summary"); } problem_report_free(pr); problem_formatter_free(pf); } problem_data_free(data); return 0; } ]]) ## --------------- ## ## short_backtrace ## ## --------------- ## AT_TESTFUN([short_backtrace], [[ #include "problem_report.h" #include "internal_libreport.h" #include #define BACKTRACE_CONTENT \ "Thread 1 (LWP 11865):\n"\ "#0 printf (__fmt=0x400acf \"Result: %d\\n\") at /usr/include/bits/stdio2.h:104\n"\ "No locals.\n"\ "#1 crash (p=p@entry=0x0) at will_segfault.c:19\n"\ "i = \n"\ "#2 0x0000000000400964 in varargs (num_args=1, num_args@entry=2) at will_segfault.c:31\n"\ "p = \n"\ "ap = {{gp_offset = 24, fp_offset = 32767, overflow_arg_area = 0x7fff4fc8a0c0, reg_save_area = 0x7fff4fc8a080}}\n"\ "#3 0x00000000004009be in inlined (p=0x0) at will_segfault.c:40\n"\ "num = 42\n"\ "#4 f (p=p@entry=0x0) at will_segfault.c:45\n"\ "No locals.\n"\ "#5 0x00000000004009e9 in callback (data=data@entry=0x0) at will_segfault.c:50\n"\ "No locals.\n"\ "#6 0x00000032f76006f9 in call_me_back (cb=cb@entry=0x4009e0 , data=data@entry=0x0) at libwillcrash.c:8\n"\ "res = \n"\ "#7 0x0000000000400a14 in recursive (i=i@entry=0) at will_segfault.c:59\n"\ "p = \n"\ "#8 0x0000000000400a00 in recursive (i=i@entry=1) at will_segfault.c:66\n"\ "No locals.\n"\ "#9 0x0000000000400a00 in recursive (i=i@entry=2) at will_segfault.c:66\n"\ "No locals.\n"\ "#10 0x0000000000400775 in main (argc=, argv=) at will_segfault.c:83\n"\ "No locals.\n"\ "From To Syms Read Shared Object Library\n"\ "0x00000032f76005f0 0x00000032f7600712 Yes /lib64/libwillcrash.so.0\n"\ "0x0000003245c1f4f0 0x0000003245d6aca4 Yes /lib64/libc.so.6\n"\ "0x0000003245800b10 0x000000324581b6d0 Yes /lib64/ld-linux-x86-64.so.2\n"\ "$1 = 0x0\n"\ "No symbol \"__glib_assert_msg\" in current context.\n"\ "rax 0xf 15\n"\ "rbx 0x0 0\n"\ "rcx 0x7ff96f752000 140709293531136\n"\ "rdx 0x3245fb9a40 215922481728\n"\ "rsi 0x7ff96f752000 140709293531136\n"\ "rdi 0x1 1\n"\ "rbp 0x400a30 0x400a30 <__libc_csu_init>\n"\ "rsp 0x7fff4fc8a050 0x7fff4fc8a050\n"\ "r8 0xffffffff 4294967295\n"\ "r9 0x0 0\n"\ "r10 0x22 34\n"\ "r11 0x246 582\n"\ "r12 0x40079f 4196255\n"\ "r13 0x7fff4fc8a210 140734531936784\n"\ "r14 0x0 0\n"\ "r15 0x0 0\n"\ "rip 0x4008ae 0x4008ae \n"\ "eflags 0x10246 [ PF ZF IF RF ]\n"\ "cs 0x33 51\n"\ "ss 0x2b 43\n"\ "ds 0x0 0\n"\ "es 0x0 0\n"\ "fs 0x0 0\n"\ "gs 0x0 0\n"\ "st0 0 (raw 0x00000000000000000000)\n"\ "st1 0 (raw 0x00000000000000000000)\n"\ "st2 0 (raw 0x00000000000000000000)\n"\ "st3 0 (raw 0x00000000000000000000)\n"\ "st4 0 (raw 0x00000000000000000000)\n"\ "st5 0 (raw 0x00000000000000000000)\n"\ "st6 0 (raw 0x00000000000000000000)\n"\ "st7 0 (raw 0x00000000000000000000)\n"\ "fctrl 0x37f 895\n"\ "fstat 0x0 0\n"\ "ftag 0xffff 65535\n"\ "fiseg 0x0 0\n"\ "fioff 0x0 0\n"\ "foseg 0x0 0\n"\ "fooff 0x0 0\n"\ "fop 0x0 0\n"\ "xmm0 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm1 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x2f }, v8_int16 = {0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f, 0x2f2f}, v4_int32 = {0x2f2f2f2f, 0x2f2f2f2f, 0x2f2f2f2f, 0x2f2f2f2f}, v2_int64 = {0x2f2f2f2f2f2f2f2f, 0x2f2f2f2f2f2f2f2f}, uint128 = 0x2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f}\n"\ "xmm2 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm3 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 , 0xff, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff00, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0xff00}, v2_int64 = {0x0, 0xff0000000000}, uint128 = 0x0000ff00000000000000000000000000}\n"\ "xmm4 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0xff0000, 0x0}, v2_int64 = {0x0, 0xff0000}, uint128 = 0x0000000000ff00000000000000000000}\n"\ "xmm5 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm6 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm7 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm8 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm9 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm10 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm11 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm12 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 , 0xff, 0x0}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff}, v4_int32 = {0x0, 0x0, 0x0, 0xff0000}, v2_int64 = {0x0, 0xff000000000000}, uint128 = 0x00ff0000000000000000000000000000}\n"\ "xmm13 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm14 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "xmm15 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 }, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}\n"\ "mxcsr 0x1f80 [ IM DM ZM OM UM PM ]\n"\ "Dump of assembler code for function crash:\n"\ " 0x00000000004008a0 <+0>: push %rbx\n"\ " 0x00000000004008a1 <+1>: mov %rdi,%rbx\n"\ " 0x00000000004008a4 <+4>: mov $0x400ac0,%edi\n"\ " 0x00000000004008a9 <+9>: callq 0x4006f0 \n"\ " => 0x00000000004008ae <+14>: mov (%rbx),%edx\n"\ " 0x00000000004008b0 <+16>: mov $0x400acf,%esi\n"\ " 0x00000000004008b5 <+21>: mov $0x1,%edi\n"\ " 0x00000000004008ba <+26>: xor %eax,%eax\n"\ " 0x00000000004008bc <+28>: callq 0x400740 <__printf_chk@plt>\n"\ " 0x00000000004008c1 <+33>: pop %rbx\n"\ " 0x00000000004008c2 <+34>: retq\n"\ "End of assembler dump.\n" #define CORE_BACKTRACE_CONTENT \ "{ \"signal\": 11\n"\ ", \"only_crash_thread\": true\n"\ ", \"stacktrace\":\n"\ " [ { \"crash_thread\": true\n"\ " , \"frames\":\n"\ " [ { \"address\": 93894060571040\n"\ " , \"build_id\": \"a4711308c3fe2f0699ea740b0fc13370629f52f2\"\n"\ " , \"build_id_offset\": 2464\n"\ " , \"function_name\": \"crash\"\n"\ " , \"file_name\": \"/usr/bin/will_segfault\"\n"\ " }\n"\ " , { \"address\": 93894060571239\n"\ " , \"build_id\": \"a4711308c3fe2f0699ea740b0fc13370629f52f2\"\n"\ " , \"build_id_offset\": 2663\n"\ " , \"function_name\": \"varargs\"\n"\ " , \"file_name\": \"/usr/bin/will_segfault\"\n"\ " }\n"\ " , { \"address\": 93894060571294\n"\ " , \"build_id\": \"a4711308c3fe2f0699ea740b0fc13370629f52f2\"\n"\ " , \"build_id_offset\": 2718\n"\ " , \"function_name\": \"f\"\n"\ " , \"file_name\": \"/usr/bin/will_segfault\"\n"\ " }\n"\ " , { \"address\": 93894060571337\n"\ " , \"build_id\": \"a4711308c3fe2f0699ea740b0fc13370629f52f2\"\n"\ " , \"build_id_offset\": 2761\n"\ " , \"function_name\": \"callback\"\n"\ " , \"file_name\": \"/usr/bin/will_segfault\"\n"\ " }\n"\ " , { \"address\": 140458064176825\n"\ " , \"build_id\": \"61ee70f1ceca4897eadb680f1afaa669782c53cf\"\n"\ " , \"build_id_offset\": 1721\n"\ " , \"function_name\": \"call_me_back\"\n"\ " , \"file_name\": \"/usr/lib64/libwillcrash.so.0.0.0\"\n"\ " }\n"\ " , { \"address\": 93894060571382\n"\ " , \"build_id\": \"a4711308c3fe2f0699ea740b0fc13370629f52f2\"\n"\ " , \"build_id_offset\": 2806\n"\ " , \"function_name\": \"recursive\"\n"\ " , \"file_name\": \"/usr/bin/will_segfault\"\n"\ " }\n"\ " , { \"address\": 93894060571360\n"\ " , \"build_id\": \"a4711308c3fe2f0699ea740b0fc13370629f52f2\"\n"\ " , \"build_id_offset\": 2784\n"\ " , \"function_name\": \"recursive\"\n"\ " , \"file_name\": \"/usr/bin/will_segfault\"\n"\ " }\n"\ " , { \"address\": 93894060571360\n"\ " , \"build_id\": \"a4711308c3fe2f0699ea740b0fc13370629f52f2\"\n"\ " , \"build_id_offset\": 2784\n"\ " , \"function_name\": \"recursive\"\n"\ " , \"file_name\": \"/usr/bin/will_segfault\"\n"\ " }\n"\ " , { \"address\": 93894060570663\n"\ " , \"build_id\": \"a4711308c3fe2f0699ea740b0fc13370629f52f2\"\n"\ " , \"build_id_offset\": 2087\n"\ " , \"function_name\": \"main\"\n"\ " , \"file_name\": \"/usr/bin/will_segfault\"\n"\ " } ]\n"\ " } ]\n"\ "}\n" typedef struct backtrace_result { const char *format; const char *result; int max_text_size; int max_frames; } backtrace_result_t; void check(problem_data_t *data, backtrace_result_t br) { problem_formatter_t *pf = problem_formatter_new(); assert(!problem_formatter_load_string(pf, br.format)); problem_report_t *pr = NULL; problem_report_settings_t report_settings = problem_formatter_get_settings(pf); if (br.max_frames >= 0) report_settings.prs_shortbt_max_frames = br.max_frames; if (br.max_text_size >= 0) report_settings.prs_shortbt_max_text_size = br.max_text_size; /* always short bt */ problem_formatter_set_settings(pf, report_settings); assert(!problem_formatter_generate_report(pf, data, &pr)); assert(pr != NULL); const char *summary = problem_report_get_description(pr); assert(summary != NULL); if (br.result != NULL) { fprintf(stderr, "####\n"); fprintf(stderr, "# max_text_size %d, max_frames %d\n", br.max_text_size, br.max_frames); fprintf(stderr, "expected: '%s'\n", br.result); fprintf(stderr, "====\n"); fprintf(stderr, "result : '%s'\n", summary); fprintf(stderr, "####\n"); assert(strcmp(br.result, summary) == 0); } problem_report_free(pr); problem_formatter_free(pf); } int main(int argc, char **argv) { g_verbose = 3; problem_data_t *data = problem_data_new(); problem_data_add_text_noteditable(data, "package", "libreport"); problem_data_add_text_noteditable(data, "analyzer", "CCpp"); problem_data_add_text_noteditable(data, "type", "CCpp"); problem_data_add_text_noteditable(data, "comment", "Hello, world!"); problem_data_add_text_noteditable(data, "uuid", "123456789ABCDEF"); problem_data_add_text_noteditable(data, "uid", "69"); problem_data_add_text_noteditable(data, "user_name", "abrt"); problem_data_add_text_noteditable(data, "root", "/var/run/mock/abrt"); problem_data_add_text_noteditable(data, "description", "I run will_segfault and\nit crashed as expected\n"); problem_data_add_text_noteditable(data, "core_backtrace", CORE_BACKTRACE_CONTENT); backtrace_result_t core_backtrace_result[] = { { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "#1 crash in /usr/bin/will_segfault\n" "#2 varargs in /usr/bin/will_segfault\n" "#3 f in /usr/bin/will_segfault\n" "#4 callback in /usr/bin/will_segfault\n" "#5 call_me_back in /usr/lib64/libwillcrash.so.0.0.0\n" "#6 recursive in /usr/bin/will_segfault\n" "#7 main in /usr/bin/will_segfault\n", .max_text_size = -1, .max_frames = -1 }, { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "#1 crash in /usr/bin/will_segfault\n" "#2 varargs in /usr/bin/will_segfault\n" "#3 f in /usr/bin/will_segfault\n" "#4 callback in /usr/bin/will_segfault\n" "#5 call_me_back in /usr/lib64/libwillcrash.so.0.0.0\n", .max_text_size = -1, .max_frames = 5 }, { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "#1 crash in /usr/bin/will_segfault\n", .max_text_size = -1, .max_frames = 1 }, { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "#1 crash in /usr/bin/will_segfault\n", .max_text_size = 0, .max_frames = 1 }, /* core_backtrase is always truncated */ { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "#1 crash in /usr/bin/will_segfault\n", .max_text_size = strlen(CORE_BACKTRACE_CONTENT) + 1, .max_frames = 1 }, }; /* if only core_backtrace exist, use it */ for (size_t i = 0; i < sizeof(core_backtrace_result)/sizeof(*core_backtrace_result); ++i) { check(data, core_backtrace_result[i]); } /* use backtrace, if core_backtrace and backtrace exist */ problem_data_add_text_noteditable(data, "backtrace", BACKTRACE_CONTENT); backtrace_result_t backtrace_result[] = { { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "Thread no. 0 (7 frames)\n" " #1 crash at will_segfault.c:19\n" " #2 varargs at will_segfault.c:31\n" " #3 inlined at will_segfault.c:40\n" " #4 f at will_segfault.c:45\n" " #5 callback at will_segfault.c:50\n" " #6 call_me_back at libwillcrash.c:8\n" " #7 recursive at will_segfault.c:59\n", .max_text_size = -1, .max_frames = -1 }, { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "Thread no. 0 (5 frames)\n" " #1 crash at will_segfault.c:19\n" " #2 varargs at will_segfault.c:31\n" " #3 inlined at will_segfault.c:40\n" " #4 f at will_segfault.c:45\n" " #5 callback at will_segfault.c:50\n", .max_text_size = -1, .max_frames = 5 }, { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "Thread no. 0 (1 frames)\n" " #1 crash at will_segfault.c:19\n", .max_text_size = -1, .max_frames = 1 }, { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n" "Thread no. 0 (1 frames)\n" " #1 crash at will_segfault.c:19\n", .max_text_size = 0, .max_frames = 1 }, { .format = "Truncated backtrace:: %bare_%short_backtrace", .result = "Truncated backtrace:\n"BACKTRACE_CONTENT, .max_text_size = strlen(BACKTRACE_CONTENT) + 1, .max_frames = 1 }, }; for (size_t i = 0; i < sizeof(backtrace_result)/sizeof(*backtrace_result); ++i) { check(data, backtrace_result[i]); } problem_data_free(data); return 0; } ]]) ## ------ ## ## attach ## ## ------ ## AT_TESTFUN([attach], [[ #include "problem_report.h" #include "internal_libreport.h" #include int main(int argc, char **argv) { g_verbose = 3; const char *fst[] = { "backtrace", "screenshot", "description", NULL }; struct test_case { const char *format; const char *const *files; } cases [] = { { .format = "%attach:: %multiline,%binary,-coredump", .files = fst, } }; problem_data_t *data = problem_data_new(); problem_data_add_text_noteditable(data, "package", "libreport"); problem_data_add_text_noteditable(data, "analyzer", "CCpp"); problem_data_add_text_noteditable(data, "type", "CCpp"); problem_data_add_text_noteditable(data, "comment", "Hello, world!"); problem_data_add_text_noteditable(data, "uuid", "123456789ABCDEF"); problem_data_add_text_noteditable(data, "uid", "69"); problem_data_add_text_noteditable(data, "user_name", "abrt"); problem_data_add_text_noteditable(data, "root", "/var/run/mock/abrt"); problem_data_add_text_noteditable(data, "description", "I run will_segfault and\nit crashed as expected\n"); problem_data_add_file(data, "coredump", "/what/ever/path/to/coredump"); problem_data_add_file(data, "screenshot", "/what/ever/path/to/screenshot"); problem_data_add_text_noteditable(data, "backtrace", "Thread 1 (LWP 11865):\n"\ "#0 printf (__fmt=0x400acf \"Result: %d\\n\") at /usr/include/bits/stdio2.h:104\n"\ "No locals.\n"\ "#1 crash (p=p@entry=0x0) at will_segfault.c:19\n"\ "i = \n"\ "#2 0x0000000000400964 in varargs (num_args=1, num_args@entry=2) at will_segfault.c:31\n"\ "p = \n"\ "ap = {{gp_offset = 24, fp_offset = 32767, overflow_arg_area = 0x7fff4fc8a0c0, reg_save_area = 0x7fff4fc8a080}}\n"\ "#3 0x00000000004009be in inlined (p=0x0) at will_segfault.c:40\n"\ "num = 42\n"\ "#4 f (p=p@entry=0x0) at will_segfault.c:45\n"\ "No locals.\n"\ "#5 0x00000000004009e9 in callback (data=data@entry=0x0) at will_segfault.c:50\n"\ "No locals.\n"\ "#6 0x00000032f76006f9 in call_me_back (cb=cb@entry=0x4009e0 , data=data@entry=0x0) at libwillcrash.c:8\n"\ "res = \n"\ "#7 0x0000000000400a14 in recursive (i=i@entry=0) at will_segfault.c:59\n"\ "p = \n"\ "#8 0x0000000000400a00 in recursive (i=i@entry=1) at will_segfault.c:66\n"\ "No locals.\n"\ "#9 0x0000000000400a00 in recursive (i=i@entry=2) at will_segfault.c:66\n"\ "No locals.\n"\ "#10 0x0000000000400775 in main (argc=, argv=) at will_segfault.c:83\n"\ "No locals.\n"); for (size_t i = 0; i < sizeof(cases)/sizeof(*cases); ++i) { fprintf(stderr, "%s", cases[i].format); problem_formatter_t *pf = problem_formatter_new(); assert(!problem_formatter_load_string(pf, cases[i].format)); problem_report_t *pr = NULL; assert(!problem_formatter_generate_report(pf, data, &pr)); assert(pr != NULL); const char *const *iter = cases[i].files; if (*iter != NULL) { assert(problem_report_get_attachments(pr)); } GList *clone = g_list_copy_deep(problem_report_get_attachments(pr), (GCopyFunc)xstrdup, NULL); while (*iter) { GList *item = g_list_find_custom(clone, *iter, (GCompareFunc)strcmp); if (item == NULL) { fprintf(stderr, "format: '%s'\n", cases[i].format); fprintf(stderr, "missing file: '%s'\n", *iter); abort(); } else { free(item->data); clone = g_list_delete_link(clone, item); } ++iter; } if (clone != NULL) { for (GList *iter = clone; iter; iter = g_list_next(iter)) { fprintf(stderr, "extra : '%s'\n", (const char *)iter->data); } abort(); } problem_report_free(pr); problem_formatter_free(pf); } problem_data_free(data); return 0; } ]]) ## -------------- ## ## custom_section ## ## -------------- ## AT_TESTFUN([custom_section], [[ #include "problem_report.h" #include "internal_libreport.h" #include int main(int argc, char **argv) { g_verbose = 3; struct test_case; struct test_case { const char *section_name; int section_flags; int retval_load; int retval_generate; const char *format; const char *output; } cases [] = { { .section_name = NULL, .section_flags = 0, .retval_load = 1, .retval_generate = 0, .format = "%additional_info::\n" ":: package,\\\n" "uuid,cwd\\\\" ",user_name" , .output = NULL, }, { .section_name = "additional_info", .section_flags = 0, .retval_load = 0, .retval_generate = 0, .format = "%additional_info::\n" ":: package,\\\n" "uuid,cwd\\\\" ",user_name" , .output = "package: libreport\n" "uuid: 0123456789ABCDEF\n" "user_name: abrt\n" , }, { .section_name = "additional_info", .section_flags = PFFF_REQUIRED, .retval_load = 1, .retval_generate = 0, .format = "%summary:: [abrt] %package%\n:: %reporter\n", .output = NULL, }, { .section_name = "additional_info", .section_flags = 0, .retval_load = 0, .retval_generate = 0, .format = "%summary:: [abrt] %package%\n:: %reporter\n", .output = "", }, { .section_name = "additional_info", .section_flags = 0, .retval_load = 0, .retval_generate = 0, .format = "%additional_info:: root\n" "Info:: package,\\\n" "uuid,cwd\\\\" ",user_name" , .output = "Info:\n" "package: libreport\n" "uuid: 0123456789ABCDEF\n" "user_name: abrt\n" , }, }; problem_data_t *data = problem_data_new(); problem_data_add_text_noteditable(data, "package", "libreport"); problem_data_add_text_noteditable(data, "crash_function", "run_event"); problem_data_add_text_noteditable(data, "reason", "Killed by SIGSEGV"); problem_data_add_text_noteditable(data, "uuid", "0123456789ABCDEF"); problem_data_add_text_noteditable(data, "user_name", "abrt"); for (size_t i = 0; i < sizeof(cases)/sizeof(*cases); ++i) { fprintf(stderr, "#### Test case %zd ####\n", i + 1); struct test_case *tcase = cases + i; problem_formatter_t *pf = problem_formatter_new(); if (tcase->section_name != NULL) { problem_formatter_add_section(pf, tcase->section_name, tcase->section_flags); } int r = problem_formatter_load_string(pf, tcase->format); if (r != tcase->retval_load) { fprintf(stderr, "Load : expected : %d , got : %d\n", tcase->retval_load, r); abort(); } if (tcase->retval_load != 0) { goto next_test_case; } problem_report_t *pr = NULL; r = problem_formatter_generate_report(pf, data, &pr); if (r != tcase->retval_generate) { fprintf(stderr, "Generaet : expected : %d , got : %d\n", tcase->retval_generate, r); abort(); } if (tcase->retval_generate != 0) { goto next_test_case; } const char *output = problem_report_get_section(pr, tcase->section_name); assert(output); if (strcmp(output, tcase->output) != 0) { fprintf(stderr, "expected:\n'%s'\n", tcase->output); fprintf(stderr, "result :\n'%s'\n", output); abort(); } problem_report_free(pr); next_test_case: problem_formatter_free(pf); fprintf(stderr, "#### Finished - Test case %zd ####\n", i + 1); } problem_data_free(data); return 0; } ]]) ## ------ ## ## sanity ## ## ------ ## AT_TESTFUN([sanity], [[ #include "problem_report.h" #include "internal_libreport.h" #include #include void assert_equal_strings(const char *res, const char *exp) { if ( (res == NULL && exp != NULL) || (res != NULL && exp == NULL) || ((res != NULL && exp != NULL) && strcmp(res, exp) != 0) ) { fprintf(stderr, "expected : '%s'\n", exp); fprintf(stderr, "result : '%s'\n", res); abort(); } } int main(int argc, char **argv) { g_verbose = 3; problem_formatter_t *pf = problem_formatter_new(); assert(problem_formatter_add_section(pf, "summary", 0) == -EEXIST); assert(problem_formatter_add_section(pf, "description", 0) == -EEXIST); assert(problem_formatter_add_section(pf, "attach", 0) == -EEXIST); assert(problem_formatter_add_section(pf, "additional_info", 0) == 0); assert(problem_formatter_add_section(pf, "additional_info", 0) == -EEXIST); problem_data_t *data = problem_data_new(); problem_data_add_text_noteditable(data, "package", "libreport"); problem_data_add_text_noteditable(data, "crash_function", "run_event"); problem_data_add_text_noteditable(data, "reason", "Killed by SIGSEGV"); problem_data_add_text_noteditable(data, "comment", "Hello, world!"); problem_data_add_text_noteditable(data, "root", "/var/run/mock/abrt"); problem_data_add_text_noteditable(data, "user_name", "abrt"); problem_data_add_file(data, "screenshot", "/what/ever/path/to/screenshot"); problem_formatter_load_string(pf, "%summary:: [abrt] %package% : %reason%\n\n" "Description:: %bare_comment\n\n" "%attach:: screenshot\n\n" "%additional_info::\n\n" "User:: root,user_name,uid\n\n\n" ); problem_report_t *pr = NULL; problem_formatter_generate_report(pf, data, &pr); assert_equal_strings(problem_report_get_summary(pr), "[abrt] libreport : Killed by SIGSEGV"); problem_report_buffer_printf(problem_report_get_buffer(pr, PR_SEC_SUMMARY), " - test"); assert_equal_strings(problem_report_get_summary(pr), "[abrt] libreport : Killed by SIGSEGV - test"); assert_equal_strings(problem_report_get_description(pr), "Description:\nHello, world!\n"); problem_report_buffer_printf(problem_report_get_buffer(pr, PR_SEC_DESCRIPTION), "Test line\n"); assert_equal_strings(problem_report_get_description(pr), "Description:\nHello, world!\nTest line\n"); assert_equal_strings(problem_report_get_section(pr, "additional_info"), "User:\n" "root: /var/run/mock/abrt\n" "user_name: abrt\n" ); problem_report_buffer_printf(problem_report_get_buffer(pr, "additional_info"), "uid: 42\n"); assert_equal_strings(problem_report_get_section(pr, "additional_info"), "User:\n" "root: /var/run/mock/abrt\n" "user_name: abrt\n" "uid: 42\n" ); problem_report_free(pr); problem_data_free(data); problem_formatter_free(pf); return 0; } ]])