diff options
Diffstat (limited to 'btparser/tests/frame.at')
-rw-r--r-- | btparser/tests/frame.at | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/btparser/tests/frame.at b/btparser/tests/frame.at new file mode 100644 index 00000000..28c34ac5 --- /dev/null +++ b/btparser/tests/frame.at @@ -0,0 +1,615 @@ +# Checking the btparser. -*- Autotest -*- + +AT_BANNER([Frames]) + +## ------------- ## +## btp_frame_dup ## +## ------------- ## + +AT_TESTFUN([btp_frame_dup], +[[ +#include <lib/frame.h> +#include <lib/utils.h> +#include <assert.h> + +int main(void) +{ + struct btp_frame *frame1 = btp_frame_new();; + frame1->function_name = btp_strdup("test1"); + frame1->function_type = btp_strdup("type1"); + frame1->number = 10; + frame1->source_file = btp_strdup("file1"); + frame1->source_line = 11; + frame1->address = 12; + + struct btp_frame *frame0 = btp_frame_new();; + frame0->function_name = btp_strdup("test0"); + frame0->function_type = btp_strdup("type0"); + frame0->number = 13; + frame0->source_file = btp_strdup("file0"); + frame0->source_line = 14; + frame0->address = 15; + frame0->next = frame1; + + /* Test the duplication without siblings. */ + struct btp_frame *frame = btp_frame_dup(frame0, false); + assert(NULL == frame->next); + assert(frame->function_name != frame0->function_name); + assert(frame->function_type != frame0->function_type); + assert(frame->source_file != frame0->source_file); + assert(0 == btp_frame_cmp(frame, frame0, true)); + btp_frame_free(frame); + + /* Test the duplication with the siblings. */ + frame = btp_frame_dup(frame0, true); + assert(frame->function_name != frame0->function_name); + assert(frame->function_type != frame0->function_type); + assert(frame->source_file != frame0->source_file); + assert(0 == btp_frame_cmp(frame, frame0, true)); + assert(frame->next != frame1); + assert(0 == btp_frame_cmp(frame->next, frame1, true)); + btp_frame_free(frame->next); + btp_frame_free(frame); + + btp_frame_free(frame1); + btp_frame_free(frame0); + return 0; +} +]]) + +## --------------------------- ## +## btp_frame_parse_frame_start ## +## --------------------------- ## + +AT_TESTFUN([btp_frame_parse_frame_start], +[[ +#include <lib/frame.h> +#include <assert.h> + +/** + * @param input + * The input text stream. + * @param parsed_char_count + * The expected number of characters parsed (taken) from input. + * @param expected_frame_number + * The expected parsed frame number. + */ +void check(char *input, + int parsed_char_count, + unsigned expected_frame_number) +{ + int number; + char *old_input = input; + assert(parsed_char_count == btp_frame_parse_frame_start(&input, &number)); + if (0 < parsed_char_count) + { + assert(number == expected_frame_number); + assert(*input == '\0'); + } + else + { + /* Check that the pointer is not moved. */ + assert(old_input == input); + } +} + +int main(void) +{ + check("#10 " , 4, 10); + check("#0 " , 4, 0); + check("#99999 ", 8, 99999); + check("ab " , 0, 0); + check("#ab " , 0, 0); + check("#-9999 " , 0, 9999); + return 0; +} +]]) + +## --------------------------- ## +## btp_frame_parseadd_operator ## +## --------------------------- ## + +AT_TESTFUN([btp_frame_parseadd_operator], +[[ +#include <lib/frame.h> +#include <lib/strbuf.h> +#include <assert.h> +#include <string.h> + +void check(char *input, int parsed_length) +{ + printf("Testing '%s' -> %d\n", input, parsed_length); + char *old_input = input; + struct btp_strbuf *strbuf = btp_strbuf_new(); + assert(parsed_length == btp_frame_parseadd_operator(&input, strbuf)); + printf(" input = '%s', old_input = '%s'\n", input, old_input); + + /* Check that the input pointer was updated properly. */ + assert(*input == old_input[parsed_length]); + + /* Check that the strbuf has been modified accordingly to what was parsed. */ + assert(0 == strncmp(strbuf->buf, old_input, parsed_length)); + assert(strbuf->len == parsed_length); + + btp_strbuf_free(strbuf); +} + +int main(void) +{ + check("operator>", strlen("operator>")); + check("operator->", strlen("operator->")); + check("operator new", strlen("operator new")); + check("operator new[]", strlen("operator new[]")); + check("operator delete", strlen("operator delete")); + check("operator del", 0); + check("operator delete[] (test)", strlen("operator delete[]")); + /* Red Hat Bugzilla bug #542445 */ + check("cairo_add_operator (test)", 0); + return 0; +} +]]) + +## ----------------------------- ## +## btp_frame_parse_function_name ## +## ----------------------------- ## + +AT_TESTFUN([btp_frame_parse_function_name], +[[ +#include <lib/frame.h> +#include <lib/utils.h> +#include <lib/location.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +void check(bool success, char *input) +{ + /* Function name must be ended with a space. */ + char *input_with_space = btp_malloc(strlen(input) + 2); + strcpy(input_with_space, input); + input_with_space[strlen(input)] = ' '; + input_with_space[strlen(input) + 1] = '\0'; + + char *function_name = NULL, *function_type = NULL; + char *old_input_with_space = input_with_space; + printf("Parsing '%s'\n", input); + struct btp_location location; + btp_location_init(&location); + assert(success == btp_frame_parse_function_name(&input_with_space, + &function_name, + &function_type, + &location)); + + if (success) + { + assert(function_name); + printf("Function name '%s'\n", function_name); + assert(strcmp(function_name, input) == 0); + assert(function_type == NULL); + free(function_name); + assert(*input_with_space == ' '); + } + else + { + /* Check that the pointer is not moved. */ + assert(old_input_with_space == input_with_space); + } + + free(old_input_with_space); +} + +int main(void) +{ + check(true, "??"); + check(true, "IA__g_bookmark_file_to_file"); + check(true, "pthread_cond_timedwait@@GLIBC_2.3.2"); + check(true, "_pixman_walk_composite_region"); + check(true, "CairoOutputDev::tilingPatternFill"); + check(true, "sdr::(anonymous namespace)::ViewContact::~ViewContact"); + check(true, "operator==<nsIAtom, nsICSSPseudoClass>"); + return 0; +} +]]) + +## ---------------------------- ## +## btp_frame_skip_function_args ## +## ---------------------------- ## + +AT_TESTFUN([btp_frame_skip_function_args], +[[ +#include <lib/frame.h> +#include <lib/location.h> +#include <assert.h> + +void check(bool success, char *input) +{ + char *old_input = input; + struct btp_location location; + btp_location_init(&location); + assert(success == btp_frame_skip_function_args(&input, &location)); + if (success) + { + assert(*input == '\0'); + } + else + { + /* Check that the pointer is not moved. */ + assert(old_input == input); + } +} + +int main(void) +{ + /* minimal */ + check(true, "()"); + /* newline */ + check(true, "(\n" + "page=0x7f186003e280, \n" + "cairo=0x7f18600efd10, printing=0)"); + /* value optimized out */ + check(true, "(this=0x7f1860023400, DPI=<value optimized out>)"); + /* string */ + check(true, "(filename=0x18971b0 \"/home/jfclere/.recently-used.xbel\")"); + /* TODO: parentesis balance */ + return 0; +} +]]) + +## ----------------------------- ## +## btp_frame_parse_function_call ## +## ----------------------------- ## + +AT_TESTFUN([btp_frame_parse_function_call], +[[ +#include <lib/frame.h> +#include <lib/location.h> +#include <assert.h> +#include <stdlib.h> +void check(bool success, + char *input, + char *expected_function_name, + char *expected_function_type) +{ + char *old_input = input; + char *function_name, *function_type; + struct btp_location location; + btp_location_init(&location); + assert(success == btp_frame_parse_function_call(&input, + &function_name, + &function_type, + &location)); + if (success) + { + printf("Expected: '%s', got '%s'\n", expected_function_name, function_name); + assert(0 == strcmp(expected_function_name, function_name)); + assert((!expected_function_type && !function_type) || + 0 == strcmp(expected_function_type, function_type)); + assert(*input == '\0'); + free(function_name); + } + else + { + /* Check that the pointer is not moved. */ + assert(old_input == input); + } +} + +int main(void) +{ + /* minimal */ + check(true, "?? ()", "??", NULL); + check(true, "fsync ()", "fsync", NULL); + /* newlines */ + check(true, + "write_to_temp_file (\n" + "filename=0x18971b0 \"/home/jfclere/.recently-used.xbel\", \n" + "contents=<value optimized out>, length=29917, error=0x7fff3cbe4110)", + "write_to_temp_file", + NULL); + /* C++ */ + check(true, + "osgText::Font::GlyphTexture::apply(osg::State&) const ()", + "osgText::Font::GlyphTexture::apply(osg::State&) const", + NULL); + check(true, + "osgUtil::RenderStage::drawInner(osg::RenderInfo&, osgUtil::RenderLeaf*&, bool&) ()", + "osgUtil::RenderStage::drawInner(osg::RenderInfo&, osgUtil::RenderLeaf*&, bool&)", + NULL); + check(true, + "nsRegion::RgnRect::operator new ()", + "nsRegion::RgnRect::operator new", + NULL); + check(true, + "sigc::internal::slot_call0<sigc::bound_mem_functor0<void, Driver>, void>::call_it (this=0x6c)", + "sigc::internal::slot_call0<sigc::bound_mem_functor0<void, Driver>, void>::call_it", + NULL); + check(true, + "sigc::internal::slot_call0<sigc::bound_mem_functor0<void, GameWindow>, void>::call_it(sigc::internal::slot_rep*) ()", + "sigc::internal::slot_call0<sigc::bound_mem_functor0<void, GameWindow>, void>::call_it(sigc::internal::slot_rep*)", + NULL); + /* C++ operator< and templates */ + check(true, + "operator< <char, std::char_traits<char>, std::allocator<char> > (__s1=<value optimized out>)", + "operator< <char, std::char_traits<char>, std::allocator<char> >", + NULL); + /* C++ plain operator-> */ + check(true, "operator-> ()", "operator->", NULL); + /* Not an operator, but includes the keyword 'operator' (Red Hat Bugzilla bug #542445) */ + check(true, + "cairo_set_operator (cr=0x0, op=CAIRO_OPERATOR_OVER)", + "cairo_set_operator", + NULL); + /* type included */ + #define TYPE "void" + #define FUNCTION "boost::throw_exception<" \ + "boost::filesystem::basic_filesystem_error<" \ + "boost::filesystem::basic_path<" \ + "std::basic_string<" \ + "char, std::char_traits<char>, " \ + "std::allocator<char> >, " \ + "boost::filesystem::path_traits> > >" \ + "(boost::filesystem::basic_filesystem_error<" \ + "boost::filesystem::basic_path<" \ + "std::basic_string<char, std::char_traits<char>, " \ + "std::allocator<char> >, " \ + "boost::filesystem::path_traits> > const&)" + #define ARGS "()" + #define FUNCALL TYPE " " FUNCTION " " ARGS + check(true, FUNCALL, FUNCTION, TYPE); + return 0; +} +]]) + +## ----------------------------------- ## +## btp_frame_parse_address_in_function ## +## ----------------------------------- ## + +AT_TESTFUN([btp_frame_parse_address_in_function], +[[ +#include <lib/frame.h> +#include <lib/location.h> +#include <assert.h> +#include <stdlib.h> +void check(bool success, + char *input, + uint64_t expected_address, + char *expected_function) +{ + char *old_input = input; + char *function; + char *type; + uint64_t address; + struct btp_location location; + btp_location_init(&location); + assert(success == btp_frame_parse_address_in_function(&input, + &address, + &function, + &type, + &location)); + if (success) + { + assert(strcmp(function, expected_function) == 0); + assert(address == expected_address); + assert(*input == '\0'); + free(function); + free(type); + } + else + { + /* Check that the pointer is not moved. */ + assert(old_input == input); + } +} + +int main(void) +{ + /* minimal */ + check(true, "0x00ad0a91 in raise (sig=6)", 0xad0a91, "raise"); + /* longnum */ + check(true, "0xf00000322221730e in IA__g_bookmark_file_to_file (\n" + "filename=0x18971b0 \"/home/jfclere/.recently-used.xbel\", \n" + "error=0x7fff3cbe4160)", 0xf00000322221730eULL, + "IA__g_bookmark_file_to_file"); + return 0; +} +]]) + +## ----------------------------- ## +## btp_frame_parse_file_location ## +## ----------------------------- ## + +AT_TESTFUN([btp_frame_parse_file_location], +[[ +#include <lib/frame.h> +#include <lib/location.h> +#include <assert.h> +#include <stdlib.h> +void check(bool success, + char *input, + char *expected_file, + unsigned expected_line) +{ + char *old_input = input; + char *file; + unsigned line; + struct btp_location location; + btp_location_init(&location); + assert(success == btp_frame_parse_file_location(&input, + &file, + &line, + &location)); + if (success) + { + assert(strcmp(file, expected_file) == 0); + assert(line == expected_line); + assert(*input == '\0'); + free(file); + } + else + { + /* Check that the pointer is not moved. */ + assert(old_input == input); + } +} + +int main(void) +{ + /* Test with a newline and without a line number. */ + check(true, "\n at gtkrecentmanager.c", "gtkrecentmanager.c", -1); + + /* Test with a newline and with a line number. */ + check(true, "\n at gtkrecentmanager.c:1377", "gtkrecentmanager.c", 1377); + + /* Test without a newline and a file name with a dash and an upper letter. */ + check(true, + " at ../sysdeps/unix/syscall-template.S:82", + "../sysdeps/unix/syscall-template.S", + 82); + + /* A file name starting with an underscore: Red Hat Bugzilla bug #530678. */ + check(true, + " at _polkitauthenticationagent.c:885", + "_polkitauthenticationagent.c", + 885); + + return 0; +} +]]) + +## ---------------------- ## +## btp_frame_parse_header ## +## ---------------------- ## + +AT_TESTFUN([btp_frame_parse_header], +[[ +#include <lib/frame.h> +#include <lib/location.h> +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> + +void check(char *input, + struct btp_frame *expected_frame) +{ + printf("=================================================\n" + "Testing %s\n", + input); + + char *old_input = input; + struct btp_location location; + btp_location_init(&location); + struct btp_frame *frame = btp_frame_parse_header(&input, &location); + if (frame) + { + assert(*input == '\0'); + assert(btp_frame_cmp(frame, expected_frame, true) == 0); + btp_frame_free(frame); + } + else + { + printf(" - parsing failed: %d:%d %s\n", location.line, location.column, location.message); + + /* Check that the pointer is not moved. */ + assert(old_input == input); + assert(!expected_frame); + } +} + +int main(void) +{ + /* basic */ + struct btp_frame frame; + btp_frame_init(&frame); + frame.function_name = "fsync"; + frame.number = 1; + frame.source_file = "../sysdeps/unix/syscall-template.S"; + frame.source_line = 82; + frame.address = 0x322160e7fdULL; + check("#1 0x000000322160e7fd in fsync () at ../sysdeps/unix/syscall-template.S:82", &frame); + + /* C++ */ + btp_frame_init(&frame); + frame.function_name = "nsRegion::RgnRect::operator new"; + frame.number = 4; + frame.source_file = "nsRegion.cpp"; + frame.source_line = 214; + frame.address = 0x3f96d71056ULL; + check("#4 0x0000003f96d71056 in nsRegion::RgnRect::operator new ()\n" + " at nsRegion.cpp:214", &frame); + + /* Templates and no filename. */ + btp_frame_init(&frame); + frame.function_name = "sigc::internal::slot_call0<sigc::bound_mem_functor0<void, GameWindow>, void>::call_it(sigc::internal::slot_rep*)"; + frame.number = 15; + frame.address = 0x08201bdfULL; + check("#15 0x08201bdf in sigc::internal::slot_call0<sigc::bound_mem_functor0<void, GameWindow>," + " void>::call_it(sigc::internal::slot_rep*) ()", &frame); + + /* No address, just the function call. Red Hat Bugzilla bug #530678 */ + btp_frame_init(&frame); + frame.function_name = "handle_message"; + frame.number = 30; + frame.source_file = "_polkitauthenticationagent.c"; + frame.source_line = 885; + check("#30 handle_message (message=<value optimized out>,\n" + "interface=<value optimized out>) at _polkitauthenticationagent.c:885", &frame); + + return 0; +} +]]) + +## --------------- ## +## btp_frame_parse ## +## --------------- ## + +AT_TESTFUN([btp_frame_parse], +[[ +#include <lib/frame.h> +#include <lib/location.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +void check(char *input, + struct btp_frame *expected_frame, + char *expected_input) +{ + char *old_input = input; + struct btp_location location; + btp_location_init(&location); + struct btp_frame *frame = btp_frame_parse(&input, &location); + assert(input == expected_input); + if (frame) + { + assert(btp_frame_cmp(frame, expected_frame, true) == 0); + btp_frame_free(frame); + } + else + { + /* Check that the pointer is not moved. */ + assert(old_input == input); + assert(!expected_frame); + } +} + +int main(void) +{ + /* basic */ + struct btp_frame frame; + btp_frame_init(&frame); + frame.function_name = "fsync"; + frame.number = 1; + frame.source_file = "../sysdeps/unix/syscall-template.S"; + frame.source_line = 82; + frame.address = 0x322160e7fdULL; + char *c = "#1 0x000000322160e7fd in fsync () at ../sysdeps/unix/syscall-template.S:82\n" + "No locals."; + check(c, &frame, c + strlen(c)); + c = "#1 0x000000322160e7fd in fsync () at ../sysdeps/unix/syscall-template.S:82\n" + "No locals.\n" + "#2 0x003f4f3f in IA__g_main_loop_run (loop=0x90e2c50) at gmain.c:2799\n" + " self = 0x8b80038\n" + " __PRETTY_FUNCTION__ = \"IA__g_main_loop_run\"\n"; + check(c, &frame, strstr(c, "#2")); + return 0; +} +]]) |