diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | README | 4 | ||||
-rw-r--r-- | tests/test-command.c | 265 | ||||
-rw-r--r-- | tests/test-expand.c | 25 | ||||
-rw-r--r-- | uzbl-core.c | 30 | ||||
-rw-r--r-- | uzbl-core.h | 16 |
6 files changed, 289 insertions, 59 deletions
@@ -41,9 +41,13 @@ uzbl-browser: uzbl-core PREFIX?=$(DESTDIR)/usr/local +# the 'tests' target can never be up to date +.PHONY: tests +force: + # When compiling unit tests, compile uzbl as a library first -tests: uzbl-core.o uzbl-events.o - $(CC) -DUZBL_LIBRARY -shared -Wl uzbl-core.o uzbl-events.o -o ./tests/libuzbl-core.so +tests: ${OBJ} force + $(CC) -shared -Wl ${OBJ} -o ./tests/libuzbl-core.so cd ./tests/; $(MAKE) test: uzbl-core @@ -84,8 +84,8 @@ If you made changes to the configuration at runtime, these are not pased on to t Uzbl-browser will read commands via standard input, named fifo pipe (if `fifo_dir` is set) and IPC socket (when `socket_dir` is set). For convenience, uzbl can also be instructed to read commands from a file on startup by using the `-c` option. Indeed, the config file is nothing more than a list of commands. -Each command starts with the name of the command, which must be the first thing on a line; preceding whitespace is not allowed. -A command is terminated by a newline. Empty lines and lines that start with the hash sign are ignored by the parser. Command names are always written in lowercase. +Each command starts with the name of the command or an uzbl variable that expands to it. A command is terminated by a newline. +Empty lines and lines that start with the hash sign are ignored by the parser. Command names are always written in lowercase. The following commands are recognized: diff --git a/tests/test-command.c b/tests/test-command.c index 2a226b2..239803c 100644 --- a/tests/test-command.c +++ b/tests/test-command.c @@ -27,33 +27,274 @@ extern UzblCore uzbl; +#define INSTANCE_NAME "testing" + +#define ASSERT_EVENT(EF, STR) { read_event(ef); \ + g_assert_cmpstr("EVENT [" INSTANCE_NAME "] " STR "\n", ==, ef->event_buffer); } + +struct EventFixture +{ + /* uzbl's end of the socketpair */ + int uzbl_sock; + + /* the test framework's end of the socketpair */ + int test_sock; + char event_buffer[1024]; +}; + +void +read_event (struct EventFixture *ef) { + int r = read(ef->test_sock, ef->event_buffer, 1023); \ + ef->event_buffer[r] = 0; +} + +void +assert_no_event (struct EventFixture *ef) { + fd_set rfds; + + FD_ZERO(&rfds); + FD_SET(ef->test_sock, &rfds); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + /* check if there's any data waiting */ + int res = select(ef->test_sock + 1, &rfds, NULL, NULL, &timeout); + + if(res == 0) { + /* timeout expired, there was no event */ + + /* success */ + return; + } else if(res == -1) { + /* mechanical failure */ + perror("select():"); + assert(0); + } else { + /* there was an event. display it. */ + read_event(ef); + g_assert_cmpstr("", ==, ef->event_buffer); + } +} + +void +event_fixture_setup(struct EventFixture *ef, const void* data) +{ + (void) data; + + int socks[2]; + + /* make some sockets, fresh for every test */ + if(socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1) + { + perror("socketpair() failed"); + g_assert(0); + } + + ef->uzbl_sock = socks[0]; + ef->test_sock = socks[1]; + + /* attach uzbl_sock to uzbl's event dispatcher. */ + uzbl.comm.socket_path = "/tmp/some-nonexistant-socket"; + + GIOChannel *iochan = g_io_channel_unix_new(ef->uzbl_sock); + g_io_channel_set_encoding(iochan, NULL, NULL); + + if(!uzbl.comm.connect_chan) + uzbl.comm.connect_chan = g_ptr_array_new(); + if(!uzbl.comm.client_chan) + uzbl.comm.client_chan = g_ptr_array_new(); + g_ptr_array_add(uzbl.comm.client_chan, (gpointer)iochan); +} + void -test_keycmd (void) { - add_binding("insert", "set insert_mode = 1"); - add_binding("command", "set insert_mode = 0"); +event_fixture_teardown(struct EventFixture *ef, const void *data) +{ + (void) data; - /* the 'keycmd' command */ - parse_command("keycmd", "insert", NULL); + /* there should be no events left waiting */ + assert_no_event(ef); - g_assert_cmpint(1, ==, uzbl.behave.forward_keys); - g_assert_cmpstr("", ==, uzbl.state.keycmd); + /* clean up the io channel we opened for uzbl */ + GIOChannel *iochan = g_ptr_array_index(uzbl.comm.client_chan, 0); + remove_socket_from_array(iochan); + + /* close the sockets so that nothing sticks around between tests */ + close(ef->uzbl_sock); + close(ef->test_sock); +} + +/* actual tests begin here */ + +void +test_event (struct EventFixture *ef, const void *data) { + (void) data; - /* setting the keycmd variable directly, equivalent to the 'keycmd' comand */ - set_var_value("keycmd", "command"); + parse_cmd_line("event", NULL); + assert_no_event(ef); - g_assert_cmpint(0, ==, uzbl.behave.forward_keys); - g_assert_cmpstr("", ==, uzbl.state.keycmd); + /* a simple event can be sent */ + parse_cmd_line("event event_type arg u ments", NULL); + ASSERT_EVENT(ef, "EVENT_TYPE arg u ments"); + + /* arguments to event should be expanded */ + parse_cmd_line("event event_type @(echo expansion)@ test", NULL); + ASSERT_EVENT(ef, "EVENT_TYPE expansion test"); + + /* "request" is just an alias for "event" */ + parse_cmd_line("request event_type arg u ments", NULL); + ASSERT_EVENT(ef, "EVENT_TYPE arg u ments"); +} + + +void +test_set_variable (struct EventFixture *ef, const void *data) { + (void) data; + + /* set a string */ + parse_cmd_line("set status_message = A Simple Testing Message", NULL); + ASSERT_EVENT(ef, "VARIABLE_SET status_message str A Simple Testing Message"); + g_assert_cmpstr("A Simple Testing Message", ==, uzbl.gui.sbar.msg); + + /* set an int */ + parse_cmd_line("set forward_keys = 0", NULL); + ASSERT_EVENT(ef, "VARIABLE_SET forward_keys int 0"); + g_assert_cmpint(0, ==, uzbl.behave.forward_keys); + + /* set a float */ + parse_cmd_line("set zoom_level = 0.25", NULL); + ASSERT_EVENT(ef, "VARIABLE_SET zoom_level float 0.250000"); + g_assert_cmpfloat(0.25, ==, uzbl.behave.zoom_level); + + /* set a constant int (nothing should happen) */ + int old_major = uzbl.info.webkit_major; + parse_cmd_line("set WEBKIT_MAJOR = 100", NULL); + assert_no_event(ef); + g_assert_cmpint(old_major, ==, uzbl.info.webkit_major); + + /* set a constant str (nothing should happen) */ + GString *old_arch = g_string_new(uzbl.info.arch); + parse_cmd_line("set ARCH_UZBL = A Lisp Machine", NULL); + assert_no_event(ef); + g_assert_cmpstr(g_string_free(old_arch, FALSE), ==, uzbl.info.arch); + + /* set a custom variable */ + parse_cmd_line("set nonexistant_variable = Some Value", NULL); + ASSERT_EVENT(ef, "VARIABLE_SET nonexistant_variable str Some Value"); + uzbl_cmdprop *c = g_hash_table_lookup(uzbl.comm.proto_var, "nonexistant_variable"); + g_assert_cmpstr("Some Value", ==, *c->ptr.s); + + /* set a custom variable with expansion */ + parse_cmd_line("set an_expanded_variable = Test @(echo expansion)@", NULL); + ASSERT_EVENT(ef, "VARIABLE_SET an_expanded_variable str Test expansion"); + c = g_hash_table_lookup(uzbl.comm.proto_var, "an_expanded_variable"); + g_assert_cmpstr("Test expansion", ==, *c->ptr.s); +} + +void +test_print (void) { + GString *result = g_string_new(""); + + /* a simple message can be returned as a result */ + parse_cmd_line("print A simple test", result); + g_assert_cmpstr("A simple test", ==, result->str); + + /* arguments to print should be expanded */ + parse_cmd_line("print A simple @(echo expansion)@ test", result); + g_assert_cmpstr("A simple expansion test", ==, result->str); + + g_string_free(result, TRUE); +} + +void +test_scroll (void) { + gtk_adjustment_set_lower(uzbl.gui.bar_v, 0); + gtk_adjustment_set_upper(uzbl.gui.bar_v, 100); + gtk_adjustment_set_page_size(uzbl.gui.bar_v, 5); + + /* scroll_end should scroll it to upper - page_size */ + parse_cmd_line("scroll_end", NULL); + g_assert_cmpfloat(gtk_adjustment_get_value(uzbl.gui.bar_v), ==, 95); + + /* scroll_begin should scroll it to lower */ + parse_cmd_line("scroll_begin", NULL); + g_assert_cmpfloat(gtk_adjustment_get_value(uzbl.gui.bar_v), ==, 0); + + /* scroll_vert can scroll by pixels */ + parse_cmd_line("scroll_vert 15", NULL); + g_assert_cmpfloat(gtk_adjustment_get_value(uzbl.gui.bar_v), ==, 15); + + parse_cmd_line("scroll_vert -10", NULL); + g_assert_cmpfloat(gtk_adjustment_get_value(uzbl.gui.bar_v), ==, 5); + + /* scroll_vert can scroll by a percentage of the page size */ + parse_cmd_line("scroll_vert 100%", NULL); + g_assert_cmpfloat(gtk_adjustment_get_value(uzbl.gui.bar_v), ==, 10); + + parse_cmd_line("scroll_vert -150%", NULL); + g_assert_cmpfloat(gtk_adjustment_get_value(uzbl.gui.bar_v), ==, 2.5); + + /* scroll_horz behaves basically the same way. */ +} + +void +test_toggle_status (void) { + g_assert(!uzbl.behave.show_status); + + /* status bar can be toggled on */ + parse_cmd_line("toggle_status", NULL); + g_assert(uzbl.behave.show_status); + + /* status bar can be toggled back off */ + parse_cmd_line("toggle_status", NULL); + g_assert(!uzbl.behave.show_status); +} + +void +test_sync_sh (void) { + parse_cmd_line("sync_sh 'echo Test echo.'", NULL); + g_assert_cmpstr("Test echo.\n", ==, uzbl.comm.sync_stdout); +} + +void +test_js (void) { + GString *result = g_string_new(""); + + /* simple javascript can be evaluated and returned */ + parse_cmd_line("js ('x' + 345).toUpperCase()", result); + g_assert_cmpstr("X345", ==, result->str); + + /* uzbl commands can be run from javascript */ + uzbl.gui.sbar.msg = "Test message"; + parse_cmd_line("js Uzbl.run('print @status_message').toUpperCase();", result); + g_assert_cmpstr("TEST MESSAGE", ==, result->str); + + g_string_free(result, TRUE); } int main (int argc, char *argv[]) { + /* set up tests */ g_type_init(); g_test_init(&argc, &argv, NULL); - g_test_add_func("/test-command/keycmd", test_keycmd); + g_test_add("/test-command/set-variable", struct EventFixture, NULL, event_fixture_setup, test_set_variable, event_fixture_teardown); + g_test_add("/test-command/event", struct EventFixture, NULL, event_fixture_setup, test_event, event_fixture_teardown); + + g_test_add_func("/test-command/print", test_print); + g_test_add_func("/test-command/scroll", test_scroll); + g_test_add_func("/test-command/toggle-status", test_toggle_status); + g_test_add_func("/test-command/sync-sh", test_sync_sh); + g_test_add_func("/test-command/js", test_js); + + /* set up uzbl */ initialize(argc, argv); + uzbl.state.instance_name = INSTANCE_NAME; + uzbl.behave.shell_cmd = "sh -c"; + return g_test_run(); } diff --git a/tests/test-expand.c b/tests/test-expand.c index f01e5c7..428ee23 100644 --- a/tests/test-expand.c +++ b/tests/test-expand.c @@ -52,14 +52,6 @@ test_LOAD_PROGRESS (void) { } void -test_LOAD_PROGRESSBAR (void) { - uzbl.gui.sbar.progress_w = 4; - progress_change_cb(NULL, 75, NULL); - - g_assert_cmpstr(expand("@LOAD_PROGRESSBAR", 0), ==, "===ยท"); -} - -void test_TITLE (void) { uzbl.gui.main_title = "Lorem Ipsum"; g_assert_cmpstr(expand("@TITLE", 0), ==, "Lorem Ipsum"); @@ -78,15 +70,6 @@ test_NAME (void) { } void -test_MODE (void) { - set_var_value("forward_keys", "0"); - g_assert_cmpstr(expand("@MODE", 0), ==, "C"); - - set_var_value("forward_keys", "1"); - g_assert_cmpstr(expand("@MODE", 0), ==, "I"); -} - -void test_status_message (void) { uzbl.gui.sbar.msg = "Hello from frosty Edmonton!"; g_assert_cmpstr(expand("@status_message", 0), ==, "Hello from frosty Edmonton!"); @@ -124,8 +107,7 @@ test_cmd_useragent_simple (void) { g_string_append(expected, itos(WEBKIT_MICRO_VERSION)); g_string_append(expected, ")"); - set_var_value("useragent", "Uzbl (Webkit @WEBKIT_MAJOR.@WEBKIT_MINOR.@WEBKIT_MICRO)"); - g_assert_cmpstr(uzbl.net.useragent, ==, g_string_free(expected, FALSE)); + g_assert_cmpstr(expand("Uzbl (Webkit @WEBKIT_MAJOR.@WEBKIT_MINOR.@WEBKIT_MICRO)", 0), ==, g_string_free(expected, FALSE)); } void @@ -157,8 +139,7 @@ test_cmd_useragent_full (void) { g_string_append(expected, uzbl.info.commit); g_string_append(expected, ")"); - set_var_value("useragent", "Uzbl (Webkit @WEBKIT_MAJOR.@WEBKIT_MINOR.@WEBKIT_MICRO) (@(uname -s)@ @(uname -n)@ @(uname -r)@ @(uname -v)@ @(uname -m)@ [@ARCH_UZBL]) (Commit @COMMIT)"); - g_assert_cmpstr(uzbl.net.useragent, ==, g_string_free(expected, FALSE)); + g_assert_cmpstr(expand("Uzbl (Webkit @WEBKIT_MAJOR.@WEBKIT_MINOR.@WEBKIT_MICRO) (@(uname -s)@ @(uname -n)@ @(uname -r)@ @(uname -v)@ @(uname -m)@ [@ARCH_UZBL]) (Commit @COMMIT)", 0), ==, g_string_free(expected, FALSE)); } void @@ -213,11 +194,9 @@ main (int argc, char *argv[]) { g_test_add_func("/test-expand/@status_message", test_status_message); g_test_add_func("/test-expand/@uri", test_uri); g_test_add_func("/test-expand/@LOAD_PROGRESS", test_LOAD_PROGRESS); - g_test_add_func("/test-expand/@LOAD_PROGRESSBAR", test_LOAD_PROGRESSBAR); g_test_add_func("/test-expand/@TITLE", test_TITLE); g_test_add_func("/test-expand/@SELECTED_URI", test_SELECTED_URI); g_test_add_func("/test-expand/@NAME", test_NAME); - g_test_add_func("/test-expand/@MODE", test_MODE); g_test_add_func("/test-expand/@WEBKIT_*", test_WEBKIT_VERSION); g_test_add_func("/test-expand/@ARCH_UZBL", test_ARCH_UZBL); g_test_add_func("/test-expand/@COMMIT", test_COMMIT); diff --git a/uzbl-core.c b/uzbl-core.c index 3b8c407..1097710 100644 --- a/uzbl-core.c +++ b/uzbl-core.c @@ -70,18 +70,6 @@ XDG_Var XDG[] = }; /* associate command names to their properties */ -enum ptr_type {TYPE_INT, TYPE_STR, TYPE_FLOAT}; -typedef struct { - enum ptr_type type; - union { - int *i; - float *f; - gchar **s; - } ptr; - int dump; - int writeable; - /*@null@*/ void (*func)(void); -} uzbl_cmdprop; /* abbreviations to help keep the table's width humane */ #define PTR_V_STR(var, d, fun) { .ptr.s = &(var), .type = TYPE_STR, .dump = d, .writeable = 1, .func = fun } @@ -2319,7 +2307,17 @@ initialize(int argc, char *argv[]) { commands_hash (); create_var_to_name_hash(); + create_mainbar(); + create_browser(); + + uzbl.gui.scbar_v = (GtkScrollbar*) gtk_vscrollbar_new (NULL); + uzbl.gui.bar_v = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_v); + + uzbl.gui.scbar_h = (GtkScrollbar*) gtk_hscrollbar_new (NULL); + uzbl.gui.bar_h = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_h); + + gtk_widget_set_scroll_adjustments ((GtkWidget*) uzbl.gui.web_view, uzbl.gui.bar_h, uzbl.gui.bar_v); } void @@ -2371,8 +2369,6 @@ main (int argc, char* argv[]) { uzbl.gui.vbox = gtk_vbox_new (FALSE, 0); - create_mainbar(); - /* initial packing */ gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.scrolled_win, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (uzbl.gui.vbox), uzbl.gui.mainbar, FALSE, TRUE, 0); @@ -2409,12 +2405,6 @@ main (int argc, char* argv[]) { printf("commit: %s\n", uzbl.info.commit); } - uzbl.gui.scbar_v = (GtkScrollbar*) gtk_vscrollbar_new (NULL); - uzbl.gui.bar_v = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_v); - uzbl.gui.scbar_h = (GtkScrollbar*) gtk_hscrollbar_new (NULL); - uzbl.gui.bar_h = gtk_range_get_adjustment((GtkRange*) uzbl.gui.scbar_h); - gtk_widget_set_scroll_adjustments ((GtkWidget*) uzbl.gui.web_view, uzbl.gui.bar_h, uzbl.gui.bar_v); - /* Check uzbl is in window mode before getting/setting geometry */ if (uzbl.gui.main_window) { if(uzbl.gui.geometry) diff --git a/uzbl-core.h b/uzbl-core.h index ea78f20..1bab39f 100644 --- a/uzbl-core.h +++ b/uzbl-core.h @@ -217,6 +217,19 @@ typedef struct { gchar* default_value; } XDG_Var; +/* uzbl variables */ +enum ptr_type {TYPE_INT, TYPE_STR, TYPE_FLOAT}; +typedef struct { + enum ptr_type type; + union { + int *i; + float *f; + gchar **s; + } ptr; + int dump; + int writeable; + /*@null@*/ void (*func)(void); +} uzbl_cmdprop; /* Functions */ char * @@ -421,6 +434,9 @@ event(WebKitWebView *page, GArray *argv, GString *result); void init_connect_socket(); +gboolean +remove_socket_from_array(GIOChannel *chan); + void menu_add(WebKitWebView *page, GArray *argv, GString *result); |