diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 000000000..bee8a64b7 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/test/monkey-driver.py b/test/monkey-driver.py index 25c6422f4..eed7da0e7 100755 --- a/test/monkey-driver.py +++ b/test/monkey-driver.py @@ -2,6 +2,8 @@ import sys, getopt, yaml +from monkeyfarmer import Browser + def print_usage(): print('Usage:') print(' ' + sys.argv[0] + ' -m -t ') @@ -47,23 +49,68 @@ def get_indent(ctx): def print_test_plan_info(ctx, plan): print('Running test: [' + plan["group"] + '] ' + plan["title"]) +def assert_browser(ctx): + assert(ctx['browser'].started) + assert(not ctx['browser'].stopped) + def run_test_step_action_launch(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) + assert(ctx.get('browser') is None) + assert(ctx.get('windows') is None) + ctx['browser'] = Browser(monkey_cmd=[ctx["monkey"]], quiet=True) + assert_browser(ctx) + ctx['windows'] = dict() def run_test_step_action_window_new(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) + tag = step['tag'] + assert_browser(ctx) + assert(ctx['windows'].get(tag) is None) + ctx['windows'][tag] = ctx['browser'].new_window(url=step.get('url')) def run_test_step_action_window_close(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) + assert_browser(ctx) + tag = step['window'] + assert(ctx['windows'].get(tag) is not None) + win = ctx['windows'].pop(tag) + win.kill() + win.wait_until_dead() + assert(win.alive == False) def run_test_step_action_navigate(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) + assert_browser(ctx) + tag = step['window'] + win = ctx['windows'].get(tag) + assert(win is not None) + win.go(step['url']) def run_test_step_action_sleep_ms(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) def run_test_step_action_block(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) + conds = step['conditions'] + assert_browser(ctx) + + def conds_met(): + for cond in conds: + status = cond['status'] + window = cond['window'] + assert(status == "complete") # TODO: Add more status support? + if window == "*all*": + for win in ctx['windows'].items(): + if win.throbbing: + return False + else: + win = ctx['windows'][window] + if win.throbbing: + return False + return True + + while not conds_met(): + ctx['browser'].farmer.loop(once=True) def run_test_step_action_repeat(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) @@ -72,6 +119,28 @@ def run_test_step_action_repeat(ctx, step): run_test_step(ctx, step) ctx["depth"] -= 1 +def run_test_step_action_plot_check(ctx, step): + print(get_indent(ctx) + "Action: " + step["action"]) + assert_browser(ctx) + win = ctx['windows'][step['window']] + checks = step['checks'] + all_text = [] + bitmaps = [] + for plot in win.redraw(): + if plot[0] == 'TEXT': + all_text.extend(plot[6:]) + if plot[0] == 'BITMAP': + bitmaps.append(plot[1:]) + all_text = " ".join(all_text) + for check in checks: + if 'text-contains' in check.keys(): + print("Check {} in {}".format(repr(check['text-contains']),repr(all_text))) + assert(check['text-contains'] in all_text) + elif 'bitmap-count' in check.keys(): + assert(len(bitmaps) == int(check['bitmap-count'])) + else: + raise AssertionError("Unknown check: {}".format(repr(check))) + def run_test_step_action_timer_start(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) @@ -83,6 +152,10 @@ def run_test_step_action_timer_check(ctx, step): def run_test_step_action_quit(ctx, step): print(get_indent(ctx) + "Action: " + step["action"]) + assert_browser(ctx) + browser = ctx.pop('browser') + windows = ctx.pop('windows') + assert(browser.quit_and_wait()) step_handlers = { "launch": run_test_step_action_launch, @@ -95,6 +168,7 @@ step_handlers = { "timer-start": run_test_step_action_timer_start, "timer-stop": run_test_step_action_timer_stop, "timer-check": run_test_step_action_timer_check, + "plot-check": run_test_step_action_plot_check, "quit": run_test_step_action_quit, } @@ -111,9 +185,10 @@ def main(argv): ctx = {} path_monkey, path_test = parse_argv(argv) plan = load_test_plan(path_test) + ctx["monkey"] = path_monkey print_test_plan_info(ctx, plan) walk_test_plan(ctx, plan) # Some python weirdness to get to main(). if __name__ == "__main__": - main(sys.argv[1:]) \ No newline at end of file + main(sys.argv[1:]) diff --git a/test/monkey-tests/resource-scheme.yaml b/test/monkey-tests/resource-scheme.yaml index 58b0f5eff..791a79cd6 100644 --- a/test/monkey-tests/resource-scheme.yaml +++ b/test/monkey-tests/resource-scheme.yaml @@ -13,6 +13,8 @@ steps: - window: win1 status: complete - action: plot-check + window: win1 + checks: - text-contains: Not found - text-contains: Error 404 - action: navigate @@ -23,8 +25,10 @@ steps: - window: win1 status: complete - action: plot-check + window: win1 + checks: - bitmap-count: 1 - action: window-close - - window: win1 + window: win1 - action: quit diff --git a/frontends/monkey/farmer.py b/test/monkeyfarmer.py similarity index 85% rename from frontends/monkey/farmer.py rename to test/monkeyfarmer.py index b0bf04217..239a63e0e 100644 --- a/frontends/monkey/farmer.py +++ b/test/monkeyfarmer.py @@ -1,6 +1,4 @@ -#!/usr/bin/python3 - -# Copyright 2017 Daniel Silverstone +# Copyright 2017, 2018 Daniel Silverstone # # This file is part of NetSurf, http://www.netsurf-browser.org/ # @@ -32,11 +30,8 @@ import socket import subprocess import time -#monkey_cmd = ['./nsmonkey', '--accept_language=fr'] -monkey_cmd = ['./nsmonkey'] - class MonkeyFarmer(asyncore.dispatcher): - def __init__(self, online, quiet=False): + def __init__(self, monkey_cmd, online, quiet=False): (mine, monkeys) = socket.socketpair() asyncore.dispatcher.__init__(self, sock=mine) @@ -127,15 +122,18 @@ class MonkeyFarmer(asyncore.dispatcher): break class Browser: - def __init__(self, quiet=False): - self.farmer = MonkeyFarmer(online=self.on_monkey_line, quiet=quiet) + def __init__(self, monkey_cmd=["./nsmonkey"], quiet=False): + self.farmer = MonkeyFarmer(monkey_cmd=monkey_cmd, online=self.on_monkey_line, quiet=quiet) self.windows = {} self.current_draw_target = None self.started = False self.stopped = False self.launchurl = None + now = time.time() while not self.started: self.farmer.loop(once=True) + if (time.time() - now) > 1: + break def pass_options(self, *opts): if len(opts) > 0: @@ -220,6 +218,13 @@ class BrowserWindow: def kill(self): self.browser.farmer.tell_monkey("WINDOW DESTROY %s" % self.winid) + def wait_until_dead(self, timeout=1): + now = time.time() + while self.alive: + self.browser.farmer.loop(once=True) + if (time.time() - now) > timeout: + break + def go(self, url, referer = None): if referer is None: self.browser.farmer.tell_monkey("WINDOW GO %s %s" % ( @@ -339,47 +344,47 @@ class BrowserWindow: self.browser.farmer.loop(once=True) return self.plotted + +if __name__ == '__main__': + # Simple test is as follows... -# Simple test is as follows... - -browser = Browser(quiet=True) + browser = Browser(quiet=True) + win = browser.new_window() -win = browser.new_window() + fname = "test/js/inline-doc-write-simple.html" + full_fname = os.path.join(os.getcwd(), fname) -fname = "test/js/inline-doc-write-simple.html" -full_fname = os.path.join(os.getcwd(), fname) + browser.pass_options("--enable_javascript=0") + win.load_page("file://" + full_fname) -browser.pass_options("--enable_javascript=0") -win.load_page("file://" + full_fname) + print("Loaded, URL is {}".format(win.url)) -print("Loaded, URL is {}".format(win.url)) - -cmds = win.redraw() -print("Received {} plot commands".format(len(cmds))) -for cmd in cmds: - if cmd[0] == "TEXT": - x = cmd[2] - y = cmd[4] - rest = " ".join(cmd[6:]) - print("{} {} -> {}".format(x,y,rest)) + cmds = win.redraw() + print("Received {} plot commands".format(len(cmds))) + for cmd in cmds: + if cmd[0] == "TEXT": + x = cmd[2] + y = cmd[4] + rest = " ".join(cmd[6:]) + print("{} {} -> {}".format(x,y,rest)) -browser.pass_options("--enable_javascript=1") -win.load_page("file://" + full_fname) + browser.pass_options("--enable_javascript=1") + win.load_page("file://" + full_fname) -print("Loaded, URL is {}".format(win.url)) + print("Loaded, URL is {}".format(win.url)) -cmds = win.redraw() -print("Received {} plot commands".format(len(cmds))) -for cmd in cmds: - if cmd[0] == "TEXT": - x = cmd[2] - y = cmd[4] - rest = " ".join(cmd[6:]) - print("{} {} -> {}".format(x,y,rest)) + cmds = win.redraw() + print("Received {} plot commands".format(len(cmds))) + for cmd in cmds: + if cmd[0] == "TEXT": + x = cmd[2] + y = cmd[4] + rest = " ".join(cmd[6:]) + print("{} {} -> {}".format(x,y,rest)) -browser.quit_and_wait() + browser.quit_and_wait() -#print("Discussion was:") -#for line in browser.farmer.discussion: -# print("{} {}".format(line[0], line[1])) + #print("Discussion was:") + #for line in browser.farmer.discussion: + # print("{} {}".format(line[0], line[1]))