Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/b34a52e4b97b3606b4d93a6291874620c3e3a676
...commit
http://git.netsurf-browser.org/netsurf.git/commit/b34a52e4b97b3606b4d93a6291874620c3e3a676
...tree
http://git.netsurf-browser.org/netsurf.git/tree/b34a52e4b97b3606b4d93a6291874620c3e3a676
The branch, master has been updated
via b34a52e4b97b3606b4d93a6291874620c3e3a676 (commit)
via 94bba97a455fdf22d65bb4e503da0f5a24743dd3 (commit)
from 7cc1f1bfc09653479ae8bb0db0f2ce5a7d19bd0a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=b34a52e4b97b3606b4d93a6291874620c3e3a676
commit b34a52e4b97b3606b4d93a6291874620c3e3a676
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
More monkey stuff
diff --git a/frontends/monkey/farmer.py b/frontends/monkey/farmer.py
deleted file mode 100644
index b0bf042..0000000
--- a/frontends/monkey/farmer.py
+++ /dev/null
@@ -1,385 +0,0 @@
-#!/usr/bin/python3
-
-# Copyright 2017 Daniel Silverstone <[email protected]>
-#
-# This file is part of NetSurf, http://www.netsurf-browser.org/
-#
-# NetSurf is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# NetSurf is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-"""
-Monkey Farmer
-
-The monkey farmer is a wrapper around `nsmonkey` which can be used to simplify
-access to the monkey behaviours and ultimately to write useful tests in an
-expressive but not overcomplicated DSLish way. Tests are, ultimately, still
-Python code.
-
-"""
-
-import asyncore
-import os
-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):
- (mine, monkeys) = socket.socketpair()
-
- asyncore.dispatcher.__init__(self, sock=mine)
-
- self.monkey = subprocess.Popen(
- monkey_cmd,
- stdin=monkeys,
- stdout=monkeys,
- close_fds=[mine])
-
- monkeys.close()
-
- self.buffer = b""
- self.incoming = b""
- self.lines = []
- self.scheduled = []
- self.deadmonkey = False
- self.online = online
- self.quiet = quiet
- self.discussion = []
-
- def handle_connect(self):
- pass
-
- def handle_read(self):
- got = self.recv(8192)
- if not got:
- self.deadmonkey = True
- return
- self.incoming += got
- if b"\n" in self.incoming:
- lines = self.incoming.split(b"\n")
- self.incoming = lines.pop()
- self.lines = lines
-
- def writable(self):
- return (len(self.buffer) > 0)
-
- def handle_write(self):
- sent = self.send(self.buffer)
- self.buffer = self.buffer[sent:]
-
- def tell_monkey(self, *args):
- cmd = (" ".join(args))
- if not self.quiet:
- print(">>> {}".format(cmd))
- self.discussion.append((">",cmd))
- cmd = cmd + "\n"
- self.buffer += cmd.encode('utf-8')
-
- def monkey_says(self, line):
- line = line.decode('utf-8')
- if not self.quiet:
- print("<<< {}".format(line))
- self.discussion.append(("<", line))
- self.online(line)
-
- def schedule_event(self, event, secs=None, when=None):
- assert(secs is not None or when is not None)
- if when is None:
- when = time.time() + secs
- self.scheduled.append((when, event))
- self.scheduled.sort(lambda a,b: cmp(a[0],b[0]))
-
- def unschedule_event(self, event):
- self.scheduled = [x for x in self.scheduled if x[1] != event]
-
- def loop(self, once=False):
- if len(self.lines) > 0:
- self.monkey_says(self.lines.pop(0))
- if once:
- return
- while not self.deadmonkey:
- now = time.time()
- while len(self.scheduled) > 0 and now >= self.scheduled[0][0]:
- func = self.scheduled[0][1]
- self.scheduled.pop(0)
- func(self)
- now = time.time()
- if len(self.scheduled) > 0:
- next = self.scheduled[0][0]
- asyncore.loop(timeout=next-now, count=1)
- else:
- asyncore.loop(count=1)
- if len(self.lines) > 0:
- self.monkey_says(self.lines.pop(0))
- if once:
- break
-
-class Browser:
- def __init__(self, quiet=False):
- self.farmer = MonkeyFarmer(online=self.on_monkey_line, quiet=quiet)
- self.windows = {}
- self.current_draw_target = None
- self.started = False
- self.stopped = False
- self.launchurl = None
- while not self.started:
- self.farmer.loop(once=True)
-
- def pass_options(self, *opts):
- if len(opts) > 0:
- self.farmer.tell_monkey("OPTIONS " + (" ".join(opts)))
-
- def on_monkey_line(self, line):
- parts = line.split(" ")
- handler = getattr(self, "handle_" + parts[0], None)
- if handler is not None:
- handler(*parts[1:])
-
- def quit(self):
- self.farmer.tell_monkey("QUIT")
-
- def quit_and_wait(self):
- self.quit()
- self.farmer.loop()
- return self.stopped
-
- def handle_GENERIC(self, what, *args):
- if what == 'STARTED':
- self.started = True
- elif what == 'FINISHED':
- self.stopped = True
- elif what == 'LAUNCH':
- self.launchurl = args[1]
- else:
- # TODO: Nothing for now?
- pass
-
- def handle_WINDOW(self, action, _win, winid, *args):
- if action == "NEW":
- new_win = BrowserWindow(self, winid, *args)
- self.windows[winid] = new_win
- else:
- win = self.windows.get(winid, None)
- if win is None:
- print(" Unknown window id {}".format(winid))
- else:
- win.handle(action, *args)
-
- def handle_PLOT(self, *args):
- if self.current_draw_target is not None:
- self.current_draw_target.handle_plot(*args)
-
- def new_window(self, url=None):
- if url is None:
- self.farmer.tell_monkey("WINDOW NEW")
- else:
- self.farmer.tell_monkey("WINDOW NEW %s" % url)
- wins_known = set(self.windows.keys())
- while len(set(self.windows.keys()).difference(wins_known)) == 0:
- self.farmer.loop(once=True)
- poss_wins = set(self.windows.keys()).difference(wins_known)
- return self.windows[poss_wins.pop()]
-
-
-class BrowserWindow:
- def __init__(self, browser, winid, _for, coreid, _existing, otherid,
_newtab, newtab, _clone, clone):
- self.alive = True
- self.browser = browser
- self.winid = winid
- self.coreid = coreid
- self.existing = browser.windows.get(otherid, None)
- self.newtab = newtab == "TRUE"
- self.clone = clone == "TRUE"
- self.width = 0
- self.height = 0
- self.title = ""
- self.throbbing = False
- self.scrollx = 0
- self.scrolly = 0
- self.content_width = 0
- self.content_height = 0
- self.status = ""
- self.pointer = ""
- self.scale = 1.0
- self.url = ""
- self.plotted = []
- self.plotting = False
-
- def kill(self):
- self.browser.farmer.tell_monkey("WINDOW DESTROY %s" % self.winid)
-
- def go(self, url, referer = None):
- if referer is None:
- self.browser.farmer.tell_monkey("WINDOW GO %s %s" % (
- self.winid, url))
- else:
- self.browser.farmer.tell_monkey("WINDOW GO %s %s %s" % (
- self.winid, url, referer))
- self.wait_start_loading()
-
- def reload(self):
- self.browser.farmer.tell_monkey("WINDOW RELOAD %s" % self.winid)
-
- def handle(self, action, *args):
- handler = getattr(self, "handle_window_" + action, None)
- if handler is not None:
- handler(*args)
-
- def handle_window_SIZE(self, _width, width, _height, height):
- self.width = int(width)
- self.height = int(height)
-
- def handle_window_DESTROY(self):
- self.alive = False
-
- def handle_window_TITLE(self, _str, *title):
- self.title = " ".join(title)
-
- def handle_window_REDRAW(self):
- pass
-
- def handle_window_GET_DIMENSIONS(self, _width, width, _height, height):
- self.width = width
- self.height = height
-
- def handle_window_NEW_CONTENT(self):
- pass
-
- def handle_window_NEW_ICON(self):
- pass
-
- def handle_window_START_THROBBER(self):
- self.throbbing = True
-
- def handle_window_STOP_THROBBER(self):
- self.throbbing = False
-
- def handle_window_SET_SCROLL(self, _x, x, _y, y):
- self.scrollx = int(x)
- self.scrolly = int(y)
-
- def handle_window_UPDATE_BOX(self, _x, x, _y, y, _width, width, _height,
height):
- x = int(x)
- y = int(y)
- width = int(width)
- height = int(height)
- pass
-
- def handle_window_UPDATE_EXTENT(self, _width, width, _height, height):
- self.content_width = int(width)
- self.content_height = int(height)
-
- def handle_window_SET_STATUS(self, _str, *status):
- self.status = (" ".join(status))
-
- def handle_window_SET_POINTER(self, _ptr, ptr):
- self.pointer = ptr
-
- def handle_window_SET_SCALE(self, _scale, scale):
- self.scale = float(scale)
-
- def handle_window_SET_URL(self, _url, url):
- self.url = url
-
- def handle_window_GET_SCROLL(self, _x, x, _y, y):
- self.scrollx = int(x)
- self.scrolly = int(y)
-
- def handle_window_SCROLL_START(self):
- self.scrollx = 0
- self.scrolly = 0
-
- def handle_window_REDRAW(self, act):
- if act == "START":
- self.browser.current_draw_target = self
- self.plotted = []
- self.plotting = True
- else:
- self.browser.current_draw_target = None
- self.plotting = False
-
- def load_page(self, url=None, referer=None):
- if url is not None:
- self.go(url, referer)
- self.wait_loaded()
-
- def wait_start_loading(self):
- while not self.throbbing:
- self.browser.farmer.loop(once=True)
-
- def wait_loaded(self):
- self.wait_start_loading()
- while self.throbbing:
- self.browser.farmer.loop(once=True)
-
- def handle_plot(self, *args):
- self.plotted.append(args)
-
- def redraw(self, coords=None):
- if coords is None:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s" % self.winid)
- else:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s %s" % (
- self.winid, (" ".join(coords))))
- while not self.plotting:
- self.browser.farmer.loop(once=True)
- while self.plotting:
- self.browser.farmer.loop(once=True)
- return self.plotted
-
-
-# Simple test is as follows...
-
-browser = Browser(quiet=True)
-
-win = browser.new_window()
-
-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)
-
-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))
-
-
-browser.pass_options("--enable_javascript=1")
-win.load_page("file://" + full_fname)
-
-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))
-
-browser.quit_and_wait()
-
-#print("Discussion was:")
-#for line in browser.farmer.discussion:
-# print("{} {}".format(line[0], line[1]))
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..bee8a64
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1 @@
+__pycache__
diff --git a/test/monkey-driver.py b/test/monkey-driver.py
index 25c6422..eed7da0 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 <path to monkey> -t <path to test>')
@@ -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 58b0f5e..791a79c 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/test/monkeyfarmer.py b/test/monkeyfarmer.py
new file mode 100644
index 0000000..239a63e
--- /dev/null
+++ b/test/monkeyfarmer.py
@@ -0,0 +1,390 @@
+# Copyright 2017, 2018 Daniel Silverstone <[email protected]>
+#
+# This file is part of NetSurf, http://www.netsurf-browser.org/
+#
+# NetSurf is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# NetSurf is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Monkey Farmer
+
+The monkey farmer is a wrapper around `nsmonkey` which can be used to simplify
+access to the monkey behaviours and ultimately to write useful tests in an
+expressive but not overcomplicated DSLish way. Tests are, ultimately, still
+Python code.
+
+"""
+
+import asyncore
+import os
+import socket
+import subprocess
+import time
+
+class MonkeyFarmer(asyncore.dispatcher):
+ def __init__(self, monkey_cmd, online, quiet=False):
+ (mine, monkeys) = socket.socketpair()
+
+ asyncore.dispatcher.__init__(self, sock=mine)
+
+ self.monkey = subprocess.Popen(
+ monkey_cmd,
+ stdin=monkeys,
+ stdout=monkeys,
+ close_fds=[mine])
+
+ monkeys.close()
+
+ self.buffer = b""
+ self.incoming = b""
+ self.lines = []
+ self.scheduled = []
+ self.deadmonkey = False
+ self.online = online
+ self.quiet = quiet
+ self.discussion = []
+
+ def handle_connect(self):
+ pass
+
+ def handle_read(self):
+ got = self.recv(8192)
+ if not got:
+ self.deadmonkey = True
+ return
+ self.incoming += got
+ if b"\n" in self.incoming:
+ lines = self.incoming.split(b"\n")
+ self.incoming = lines.pop()
+ self.lines = lines
+
+ def writable(self):
+ return (len(self.buffer) > 0)
+
+ def handle_write(self):
+ sent = self.send(self.buffer)
+ self.buffer = self.buffer[sent:]
+
+ def tell_monkey(self, *args):
+ cmd = (" ".join(args))
+ if not self.quiet:
+ print(">>> {}".format(cmd))
+ self.discussion.append((">",cmd))
+ cmd = cmd + "\n"
+ self.buffer += cmd.encode('utf-8')
+
+ def monkey_says(self, line):
+ line = line.decode('utf-8')
+ if not self.quiet:
+ print("<<< {}".format(line))
+ self.discussion.append(("<", line))
+ self.online(line)
+
+ def schedule_event(self, event, secs=None, when=None):
+ assert(secs is not None or when is not None)
+ if when is None:
+ when = time.time() + secs
+ self.scheduled.append((when, event))
+ self.scheduled.sort(lambda a,b: cmp(a[0],b[0]))
+
+ def unschedule_event(self, event):
+ self.scheduled = [x for x in self.scheduled if x[1] != event]
+
+ def loop(self, once=False):
+ if len(self.lines) > 0:
+ self.monkey_says(self.lines.pop(0))
+ if once:
+ return
+ while not self.deadmonkey:
+ now = time.time()
+ while len(self.scheduled) > 0 and now >= self.scheduled[0][0]:
+ func = self.scheduled[0][1]
+ self.scheduled.pop(0)
+ func(self)
+ now = time.time()
+ if len(self.scheduled) > 0:
+ next = self.scheduled[0][0]
+ asyncore.loop(timeout=next-now, count=1)
+ else:
+ asyncore.loop(count=1)
+ if len(self.lines) > 0:
+ self.monkey_says(self.lines.pop(0))
+ if once:
+ break
+
+class Browser:
+ 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:
+ self.farmer.tell_monkey("OPTIONS " + (" ".join(opts)))
+
+ def on_monkey_line(self, line):
+ parts = line.split(" ")
+ handler = getattr(self, "handle_" + parts[0], None)
+ if handler is not None:
+ handler(*parts[1:])
+
+ def quit(self):
+ self.farmer.tell_monkey("QUIT")
+
+ def quit_and_wait(self):
+ self.quit()
+ self.farmer.loop()
+ return self.stopped
+
+ def handle_GENERIC(self, what, *args):
+ if what == 'STARTED':
+ self.started = True
+ elif what == 'FINISHED':
+ self.stopped = True
+ elif what == 'LAUNCH':
+ self.launchurl = args[1]
+ else:
+ # TODO: Nothing for now?
+ pass
+
+ def handle_WINDOW(self, action, _win, winid, *args):
+ if action == "NEW":
+ new_win = BrowserWindow(self, winid, *args)
+ self.windows[winid] = new_win
+ else:
+ win = self.windows.get(winid, None)
+ if win is None:
+ print(" Unknown window id {}".format(winid))
+ else:
+ win.handle(action, *args)
+
+ def handle_PLOT(self, *args):
+ if self.current_draw_target is not None:
+ self.current_draw_target.handle_plot(*args)
+
+ def new_window(self, url=None):
+ if url is None:
+ self.farmer.tell_monkey("WINDOW NEW")
+ else:
+ self.farmer.tell_monkey("WINDOW NEW %s" % url)
+ wins_known = set(self.windows.keys())
+ while len(set(self.windows.keys()).difference(wins_known)) == 0:
+ self.farmer.loop(once=True)
+ poss_wins = set(self.windows.keys()).difference(wins_known)
+ return self.windows[poss_wins.pop()]
+
+
+class BrowserWindow:
+ def __init__(self, browser, winid, _for, coreid, _existing, otherid,
_newtab, newtab, _clone, clone):
+ self.alive = True
+ self.browser = browser
+ self.winid = winid
+ self.coreid = coreid
+ self.existing = browser.windows.get(otherid, None)
+ self.newtab = newtab == "TRUE"
+ self.clone = clone == "TRUE"
+ self.width = 0
+ self.height = 0
+ self.title = ""
+ self.throbbing = False
+ self.scrollx = 0
+ self.scrolly = 0
+ self.content_width = 0
+ self.content_height = 0
+ self.status = ""
+ self.pointer = ""
+ self.scale = 1.0
+ self.url = ""
+ self.plotted = []
+ self.plotting = False
+
+ 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" % (
+ self.winid, url))
+ else:
+ self.browser.farmer.tell_monkey("WINDOW GO %s %s %s" % (
+ self.winid, url, referer))
+ self.wait_start_loading()
+
+ def reload(self):
+ self.browser.farmer.tell_monkey("WINDOW RELOAD %s" % self.winid)
+
+ def handle(self, action, *args):
+ handler = getattr(self, "handle_window_" + action, None)
+ if handler is not None:
+ handler(*args)
+
+ def handle_window_SIZE(self, _width, width, _height, height):
+ self.width = int(width)
+ self.height = int(height)
+
+ def handle_window_DESTROY(self):
+ self.alive = False
+
+ def handle_window_TITLE(self, _str, *title):
+ self.title = " ".join(title)
+
+ def handle_window_REDRAW(self):
+ pass
+
+ def handle_window_GET_DIMENSIONS(self, _width, width, _height, height):
+ self.width = width
+ self.height = height
+
+ def handle_window_NEW_CONTENT(self):
+ pass
+
+ def handle_window_NEW_ICON(self):
+ pass
+
+ def handle_window_START_THROBBER(self):
+ self.throbbing = True
+
+ def handle_window_STOP_THROBBER(self):
+ self.throbbing = False
+
+ def handle_window_SET_SCROLL(self, _x, x, _y, y):
+ self.scrollx = int(x)
+ self.scrolly = int(y)
+
+ def handle_window_UPDATE_BOX(self, _x, x, _y, y, _width, width, _height,
height):
+ x = int(x)
+ y = int(y)
+ width = int(width)
+ height = int(height)
+ pass
+
+ def handle_window_UPDATE_EXTENT(self, _width, width, _height, height):
+ self.content_width = int(width)
+ self.content_height = int(height)
+
+ def handle_window_SET_STATUS(self, _str, *status):
+ self.status = (" ".join(status))
+
+ def handle_window_SET_POINTER(self, _ptr, ptr):
+ self.pointer = ptr
+
+ def handle_window_SET_SCALE(self, _scale, scale):
+ self.scale = float(scale)
+
+ def handle_window_SET_URL(self, _url, url):
+ self.url = url
+
+ def handle_window_GET_SCROLL(self, _x, x, _y, y):
+ self.scrollx = int(x)
+ self.scrolly = int(y)
+
+ def handle_window_SCROLL_START(self):
+ self.scrollx = 0
+ self.scrolly = 0
+
+ def handle_window_REDRAW(self, act):
+ if act == "START":
+ self.browser.current_draw_target = self
+ self.plotted = []
+ self.plotting = True
+ else:
+ self.browser.current_draw_target = None
+ self.plotting = False
+
+ def load_page(self, url=None, referer=None):
+ if url is not None:
+ self.go(url, referer)
+ self.wait_loaded()
+
+ def wait_start_loading(self):
+ while not self.throbbing:
+ self.browser.farmer.loop(once=True)
+
+ def wait_loaded(self):
+ self.wait_start_loading()
+ while self.throbbing:
+ self.browser.farmer.loop(once=True)
+
+ def handle_plot(self, *args):
+ self.plotted.append(args)
+
+ def redraw(self, coords=None):
+ if coords is None:
+ self.browser.farmer.tell_monkey("WINDOW REDRAW %s" % self.winid)
+ else:
+ self.browser.farmer.tell_monkey("WINDOW REDRAW %s %s" % (
+ self.winid, (" ".join(coords))))
+ while not self.plotting:
+ self.browser.farmer.loop(once=True)
+ while self.plotting:
+ self.browser.farmer.loop(once=True)
+ return self.plotted
+
+
+if __name__ == '__main__':
+ # Simple test is as follows...
+
+ browser = Browser(quiet=True)
+ win = browser.new_window()
+
+ 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)
+
+ 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))
+
+
+ browser.pass_options("--enable_javascript=1")
+ win.load_page("file://" + full_fname)
+
+ 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))
+
+ browser.quit_and_wait()
+
+ #print("Discussion was:")
+ #for line in browser.farmer.discussion:
+ # print("{} {}".format(line[0], line[1]))
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=94bba97a455fdf22d65bb4e503da0f5a24743dd3
commit 94bba97a455fdf22d65bb4e503da0f5a24743dd3
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
Remove redundant redraw method
diff --git a/frontends/monkey/farmer.py b/frontends/monkey/farmer.py
index 80bc8e6..b0bf042 100644
--- a/frontends/monkey/farmer.py
+++ b/frontends/monkey/farmer.py
@@ -232,13 +232,6 @@ class BrowserWindow:
def reload(self):
self.browser.farmer.tell_monkey("WINDOW RELOAD %s" % self.winid)
- def redraw(self, coords=None):
- if coords is None:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s" % self.winid)
- else:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s %s" % (
- self.winid, (" ".join(coords))))
-
def handle(self, action, *args):
handler = getattr(self, "handle_window_" + action, None)
if handler is not None:
-----------------------------------------------------------------------
Summary of changes:
test/.gitignore | 1 +
test/monkey-driver.py | 77 +++++++++++++++-
test/monkey-tests/resource-scheme.yaml | 6 +-
frontends/monkey/farmer.py => test/monkeyfarmer.py | 96 ++++++++++----------
4 files changed, 129 insertions(+), 51 deletions(-)
create mode 100644 test/.gitignore
rename frontends/monkey/farmer.py => test/monkeyfarmer.py (85%)
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..bee8a64
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1 @@
+__pycache__
diff --git a/test/monkey-driver.py b/test/monkey-driver.py
index 25c6422..eed7da0 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 <path to monkey> -t <path to test>')
@@ -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 58b0f5e..791a79c 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 80bc8e6..239a63e 100644
--- a/frontends/monkey/farmer.py
+++ b/test/monkeyfarmer.py
@@ -1,6 +1,4 @@
-#!/usr/bin/python3
-
-# Copyright 2017 Daniel Silverstone <[email protected]>
+# Copyright 2017, 2018 Daniel Silverstone <[email protected]>
#
# 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" % (
@@ -232,13 +237,6 @@ class BrowserWindow:
def reload(self):
self.browser.farmer.tell_monkey("WINDOW RELOAD %s" % self.winid)
- def redraw(self, coords=None):
- if coords is None:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s" % self.winid)
- else:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s %s" % (
- self.winid, (" ".join(coords))))
-
def handle(self, action, *args):
handler = getattr(self, "handle_window_" + action, None)
if handler is not None:
@@ -346,47 +344,47 @@ class BrowserWindow:
self.browser.farmer.loop(once=True)
return self.plotted
-
-# Simple test is as follows...
-
-browser = Browser(quiet=True)
-win = browser.new_window()
+if __name__ == '__main__':
+ # Simple test is as follows...
+
+ browser = Browser(quiet=True)
+ 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]))
--
NetSurf Browser
_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org