From f8e95db6b0a3978327e68fa859b3e98537640e6e Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 17 Apr 2015 17:45:50 +1200 Subject: [PATCH] housekeeping: ++tests, coverage annotations --- libpathod/cmdline.py | 47 ++++++++++++++++++++++--------------- libpathod/pathoc.py | 2 +- libpathod/pathod.py | 2 +- libpathod/utils.py | 4 +--- test/test_cmdline.py | 56 ++++++++++++++++++++++++++++++++++++++++++++ test/tutils.py | 2 +- 6 files changed, 88 insertions(+), 25 deletions(-) create mode 100644 test/test_cmdline.py diff --git a/libpathod/cmdline.py b/libpathod/cmdline.py index 7a82a429d..6a10d951e 100644 --- a/libpathod/cmdline.py +++ b/libpathod/cmdline.py @@ -8,17 +8,17 @@ from . import pathoc, pathod, version, utils, language from netlib import http_uastrings -def go_pathoc(): +def args_pathoc(argv, stdout=sys.stdout, stderr=sys.stderr): preparser = argparse.ArgumentParser(add_help=False) preparser.add_argument( "--show-uas", dest="showua", action="store_true", default=False, help="Print user agent shortcuts and exit." ) - pa = preparser.parse_known_args()[0] + pa = preparser.parse_known_args(argv)[0] if pa.showua: - print "User agent strings:" + print >> stdout, "User agent strings:" for i in http_uastrings.UASTRINGS: - print " ", i[1], i[0] + print >> stdout, " ", i[1], i[0] sys.exit(0) parser = argparse.ArgumentParser( @@ -145,7 +145,7 @@ def go_pathoc(): help="Output in hexdump format" ) - args = parser.parse_args() + args = parser.parse_args(argv[1:]) args.port = None if ":" in args.host: @@ -153,7 +153,7 @@ def go_pathoc(): try: p = int(p) except ValueError: - parser.error("Invalid port in host spec: %s" % args.host) + return parser.error("Invalid port in host spec: %s" % args.host) args.host = h args.port = p @@ -163,16 +163,16 @@ def go_pathoc(): try: args.ignorecodes = [int(i) for i in args.ignorecodes.split(",") if i] except ValueError: - parser.error("Invalid return code specification: %s"%args.ignorecodes) + return parser.error("Invalid return code specification: %s"%args.ignorecodes) if args.connect_to: parts = args.connect_to.split(":") if len(parts) != 2: - parser.error("Invalid CONNECT specification: %s"%args.connect_to) + return parser.error("Invalid CONNECT specification: %s"%args.connect_to) try: parts[1] = int(parts[1]) except ValueError: - parser.error("Invalid CONNECT specification: %s"%args.connect_to) + return parser.error("Invalid CONNECT specification: %s"%args.connect_to) args.connect_to = parts else: args.connect_to = None @@ -185,14 +185,19 @@ def go_pathoc(): try: reqs.extend(language.parse_requests(r)) except language.ParseException, v: - print >> sys.stderr, "Error parsing request spec: %s"%v.msg - print >> sys.stderr, v.marked() + print >> stderr, "Error parsing request spec: %s"%v.msg + print >> stderr, v.marked() sys.exit(1) args.requests = reqs + return args + + +def go_pathoc(): # pragma: nocover + args = args_pathoc(sys.argv) pathoc.main(args) -def go_pathod(): +def args_pathod(argv, stdout=sys.stdout, stderr=sys.stderr): parser = argparse.ArgumentParser( description='A pathological HTTP/S daemon.' ) @@ -333,7 +338,7 @@ def go_pathod(): "-x", dest="hexdump", action="store_true", default=False, help="Log request/response in hexdump format" ) - args = parser.parse_args() + args = parser.parse_args(argv[1:]) certs = [] for i in args.ssl_certs: @@ -342,7 +347,7 @@ def go_pathod(): parts = ["*", parts[0]] parts[1] = os.path.expanduser(parts[1]) if not os.path.exists(parts[1]): - parser.error("Certificate file does not exist: %s"%parts[1]) + return parser.error("Certificate file does not exist: %s"%parts[1]) certs.append(parts) args.ssl_certs = certs @@ -350,7 +355,7 @@ def go_pathod(): for i in args.anchors: parts = utils.parse_anchor_spec(i) if not parts: - parser.error("Invalid anchor specification: %s"%i) + return parser.error("Invalid anchor specification: %s"%i) alst.append(parts) args.anchors = alst @@ -359,7 +364,7 @@ def go_pathod(): try: sizelimit = utils.parse_size(args.sizelimit) except ValueError, v: - parser.error(v) + return parser.error(v) args.sizelimit = sizelimit anchors = [] @@ -371,15 +376,19 @@ def go_pathod(): try: req = language.parse_response(spec) except language.ParseException, v: - print >> sys.stderr, "Error parsing anchor spec: %s"%v.msg - print >> sys.stderr, v.marked() + print >> stderr, "Error parsing anchor spec: %s"%v.msg + print >> stderr, v.marked() sys.exit(1) try: arex = re.compile(patt) except re.error: - print >> sys.stderr, "Invalid regex in anchor: %s" % patt + print >> stderr, "Invalid regex in anchor: %s" % patt sys.exit(1) anchors.append((arex, req)) args.anchors = anchors + return args + +def go_pathod(): # pragma: nocover + args = args_pathod(sys.argv) pathod.main(args) diff --git a/libpathod/pathoc.py b/libpathod/pathoc.py index d6b2c7a21..6c4a99ecf 100644 --- a/libpathod/pathoc.py +++ b/libpathod/pathoc.py @@ -223,7 +223,7 @@ class Pathoc(tcp.TCPClient): return True -def main(args): +def main(args): # pragma: nocover memo = set([]) trycount = 0 try: diff --git a/libpathod/pathod.py b/libpathod/pathod.py index 173773cfe..1506e7435 100644 --- a/libpathod/pathod.py +++ b/libpathod/pathod.py @@ -384,7 +384,7 @@ class Pathod(tcp.TCPServer): return self.log -def main(args): +def main(args): # pragma: nocover ssloptions = SSLOptions( cn = args.cn, confdir = args.confdir, diff --git a/libpathod/utils.py b/libpathod/utils.py index d4160a236..39e61eac4 100644 --- a/libpathod/utils.py +++ b/libpathod/utils.py @@ -112,7 +112,7 @@ class Data: data = Data(__name__) -def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): +def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): # pragma: nocover try: pid = os.fork() if pid > 0: @@ -136,5 +136,3 @@ def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) - - diff --git a/test/test_cmdline.py b/test/test_cmdline.py new file mode 100644 index 000000000..d1c79d77c --- /dev/null +++ b/test/test_cmdline.py @@ -0,0 +1,56 @@ +from libpathod import cmdline +import tutils +import cStringIO +import mock + + +def test_pathod(): + assert cmdline.args_pathod(["pathod"]) + + +@mock.patch("argparse.ArgumentParser.error") +def test_pathoc(perror): + assert cmdline.args_pathoc(["pathoc", "foo.com", "get:/"]) + s = cStringIO.StringIO() + tutils.raises(SystemExit, cmdline.args_pathoc, ["pathoc", "--show-uas"], s, s) + + a = cmdline.args_pathoc(["pathoc", "foo.com:8888", "get:/"]) + assert a.port == 8888 + + a = cmdline.args_pathoc(["pathoc", "foo.com:xxx", "get:/"]) + assert perror.called + perror.reset_mock() + + a = cmdline.args_pathoc(["pathoc", "-I", "10, 20", "foo.com:8888", "get:/"]) + assert a.ignorecodes == [10, 20] + + a = cmdline.args_pathoc(["pathoc", "-I", "xx, 20", "foo.com:8888", "get:/"]) + assert perror.called + perror.reset_mock() + + a = cmdline.args_pathoc(["pathoc", "-c", "foo:10", "foo.com:8888", "get:/"]) + assert a.connect_to == ["foo", 10] + + a = cmdline.args_pathoc(["pathoc", "-c", "foo", "foo.com:8888", "get:/"]) + assert perror.called + perror.reset_mock() + + a = cmdline.args_pathoc(["pathoc", "-c", "foo:bar", "foo.com:8888", "get:/"]) + assert perror.called + perror.reset_mock() + + a = cmdline.args_pathoc( + [ + "pathoc", + "foo.com:8888", + tutils.test_data.path("data/request") + ] + ) + assert len(a.requests) == 1 + + tutils.raises( + SystemExit, + cmdline.args_pathoc, + ["pathoc", "foo.com", "invalid"], + s, s + ) diff --git a/test/tutils.py b/test/tutils.py index 5876e5e6a..c1e55a613 100644 --- a/test/tutils.py +++ b/test/tutils.py @@ -104,7 +104,7 @@ def raises(exc, obj, *args, **kwargs): """ try: apply(obj, args, kwargs) - except Exception, v: + except (Exception, SystemExit), v: if isinstance(exc, basestring): if exc.lower() in str(v).lower(): return