From 18a4456397d0b4b1275ac2c8ab393d041176e949 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 8 Jun 2015 16:03:33 +0200 Subject: refactor cmdline tests --- test/test_cmdline.py | 155 -------------------------------------------- test/test_pathoc_cmdline.py | 62 ++++++++++++++++++ test/test_pathod_cmdline.py | 104 +++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 155 deletions(-) delete mode 100644 test/test_cmdline.py create mode 100644 test/test_pathoc_cmdline.py create mode 100644 test/test_pathod_cmdline.py (limited to 'test') diff --git a/test/test_cmdline.py b/test/test_cmdline.py deleted file mode 100644 index c1b55608..00000000 --- a/test/test_cmdline.py +++ /dev/null @@ -1,155 +0,0 @@ -from libpathod import cmdline -import tutils -import cStringIO -import mock - - -@mock.patch("argparse.ArgumentParser.error") -def test_pathod(perror): - assert cmdline.args_pathod(["pathod"]) - - a = cmdline.args_pathod( - [ - "pathod", - "--cert", - tutils.test_data.path("data/testkey.pem") - ] - ) - assert a.ssl_certs - - a = cmdline.args_pathod( - [ - "pathod", - "--cert", - "nonexistent" - ] - ) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathod( - [ - "pathod", - "-a", - "foo=200" - ] - ) - assert a.anchors - - a = cmdline.args_pathod( - [ - "pathod", - "-a", - "foo=" + tutils.test_data.path("data/response") - ] - ) - assert a.anchors - - a = cmdline.args_pathod( - [ - "pathod", - "-a", - "?=200" - ] - ) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathod( - [ - "pathod", - "-a", - "foo" - ] - ) - assert perror.called - perror.reset_mock() - - s = cStringIO.StringIO() - tutils.raises( - SystemExit, - cmdline.args_pathod, - ["pathod", "-a", "foo=."], - s, - s - ) - - a = cmdline.args_pathod( - [ - "pathod", - "--limit-size", - "200k" - ] - ) - assert a.sizelimit - - a = cmdline.args_pathod( - [ - "pathod", - "--limit-size", - "q" - ] - ) - assert perror.called - perror.reset_mock() - - -@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(list(a.requests)) == 1 - - a = cmdline.args_pathod( - [ - "pathod", - "-c", - "?" - ] - ) - assert perror.called - perror.reset_mock() - - tutils.raises( - SystemExit, - cmdline.args_pathoc, - ["pathoc", "foo.com", "invalid"], - s, s - ) diff --git a/test/test_pathoc_cmdline.py b/test/test_pathoc_cmdline.py new file mode 100644 index 00000000..03c83844 --- /dev/null +++ b/test/test_pathoc_cmdline.py @@ -0,0 +1,62 @@ +from libpathod import pathoc_cmdline as cmdline +import tutils +import cStringIO +import mock + + +@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", "foo.com", "get:/", "--http2"]) + assert a.use_http2 == True + + a = cmdline.args_pathoc(["pathoc", "foo.com", "get:/", "--http2-skip-connection-preface"]) + assert a.use_http2 == True + assert a.http2_skip_connection_preface == True + + 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(list(a.requests)) == 1 + + tutils.raises( + SystemExit, + cmdline.args_pathoc, + ["pathoc", "foo.com", "invalid"], + s, s + ) diff --git a/test/test_pathod_cmdline.py b/test/test_pathod_cmdline.py new file mode 100644 index 00000000..590bb56b --- /dev/null +++ b/test/test_pathod_cmdline.py @@ -0,0 +1,104 @@ +from libpathod import pathod_cmdline as cmdline +import tutils +import cStringIO +import mock + + +@mock.patch("argparse.ArgumentParser.error") +def test_pathod(perror): + assert cmdline.args_pathod(["pathod"]) + + a = cmdline.args_pathod( + [ + "pathod", + "--cert", + tutils.test_data.path("data/testkey.pem") + ] + ) + assert a.ssl_certs + + a = cmdline.args_pathod( + [ + "pathod", + "--cert", + "nonexistent" + ] + ) + assert perror.called + perror.reset_mock() + + a = cmdline.args_pathod( + [ + "pathod", + "-a", + "foo=200" + ] + ) + assert a.anchors + + a = cmdline.args_pathod( + [ + "pathod", + "-a", + "foo=" + tutils.test_data.path("data/response") + ] + ) + assert a.anchors + + a = cmdline.args_pathod( + [ + "pathod", + "-a", + "?=200" + ] + ) + assert perror.called + perror.reset_mock() + + a = cmdline.args_pathod( + [ + "pathod", + "-a", + "foo" + ] + ) + assert perror.called + perror.reset_mock() + + s = cStringIO.StringIO() + tutils.raises( + SystemExit, + cmdline.args_pathod, + ["pathod", "-a", "foo=."], + s, + s + ) + + a = cmdline.args_pathod( + [ + "pathod", + "--limit-size", + "200k" + ] + ) + assert a.sizelimit + + a = cmdline.args_pathod( + [ + "pathod", + "--limit-size", + "q" + ] + ) + assert perror.called + perror.reset_mock() + + a = cmdline.args_pathod( + [ + "pathod", + "-c", + "?" + ] + ) + assert perror.called + perror.reset_mock() -- cgit v1.2.3 From b7c8021407965cd97bcc8051ddb0692145401cbf Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 8 Jun 2015 17:12:01 +0200 Subject: http2: using http2 implies SSL --- test/test_pathoc_cmdline.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'test') diff --git a/test/test_pathoc_cmdline.py b/test/test_pathoc_cmdline.py index 03c83844..6c070aed 100644 --- a/test/test_pathoc_cmdline.py +++ b/test/test_pathoc_cmdline.py @@ -31,9 +31,11 @@ def test_pathoc(perror): a = cmdline.args_pathoc(["pathoc", "foo.com", "get:/", "--http2"]) assert a.use_http2 == True + assert a.ssl == True a = cmdline.args_pathoc(["pathoc", "foo.com", "get:/", "--http2-skip-connection-preface"]) assert a.use_http2 == True + assert a.ssl == True assert a.http2_skip_connection_preface == True a = cmdline.args_pathoc(["pathoc", "-c", "foo", "foo.com:8888", "get:/"]) -- cgit v1.2.3 From 0bc8fa1d0d4f2730311b9fc934a8fcdaae07ab66 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 8 Jun 2015 15:28:24 +0200 Subject: http2: add pathoc and language tests --- test/test_language_http2.py | 75 +++++++++++++++++++++++++++++++++++++++++++++ test/test_pathoc.py | 62 +++++++++++++++++++++++++++++++++++-- 2 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 test/test_language_http2.py (limited to 'test') diff --git a/test/test_language_http2.py b/test/test_language_http2.py new file mode 100644 index 00000000..de3e5cf9 --- /dev/null +++ b/test/test_language_http2.py @@ -0,0 +1,75 @@ +import cStringIO + +from libpathod import language +from libpathod.language import http2, base +import netlib +import tutils + + +def parse_request(s): + return language.parse_pathoc(s, True).next() + + +class TestRequest: + def test_nonascii(self): + tutils.raises("ascii", parse_request, "get:\xf0") + + def test_err(self): + tutils.raises(language.ParseException, parse_request, 'GET') + + def test_simple(self): + r = parse_request('GET:"/foo"') + assert r.method.string() == "GET" + assert r.path.string() == "/foo" + r = parse_request('GET:/foo') + assert r.path.string() == "/foo" + + def test_multiple(self): + r = list(language.parse_pathoc("GET:/ PUT:/")) + assert r[0].method.string() == "GET" + assert r[1].method.string() == "PUT" + assert len(r) == 2 + + l = """ + GET + "/foo" + + PUT + + "/foo + + + + bar" + """ + r = list(language.parse_pathoc(l, True)) + assert len(r) == 2 + assert r[0].method.string() == "GET" + assert r[1].method.string() == "PUT" + + l = """ + get:"http://localhost:9999/p/200" + get:"http://localhost:9999/p/200" + """ + r = list(language.parse_pathoc(l, True)) + assert len(r) == 2 + assert r[0].method.string() == "GET" + assert r[1].method.string() == "GET" + + def test_render(self): + s = cStringIO.StringIO() + r = parse_request("GET:'/foo'") + assert language.serve( + r, + s, + language.Settings( + request_host = "foo.com", + protocol = netlib.http2.HTTP2Protocol(None) + ) + ) + + def test_spec(self): + def rt(s): + s = parse_request(s).spec() + assert parse_request(s).spec() == s + rt("get:/foo") diff --git a/test/test_pathoc.py b/test/test_pathoc.py index c00c7d53..28514378 100644 --- a/test/test_pathoc.py +++ b/test/test_pathoc.py @@ -1,8 +1,9 @@ import json import cStringIO import re +from mock import Mock -from netlib import tcp, http +from netlib import tcp, http, http2 from libpathod import pathoc, test, version, pathod, language import tutils @@ -86,8 +87,9 @@ class _TestDaemon: class TestDaemonSSL(_TestDaemon): ssl = True ssloptions = pathod.SSLOptions( - request_client_cert=True, - sans = ["test1.com", "test2.com"] + request_client_cert = True, + sans = ["test1.com", "test2.com"], + alpn_select = http2.HTTP2Protocol.ALPN_PROTO_H2, ) def test_sni(self): @@ -119,6 +121,14 @@ class TestDaemonSSL(_TestDaemon): d = json.loads(r.content) assert d["log"][0]["request"]["clientcert"]["keyinfo"] + def test_http2_without_ssl(self): + c = pathoc.Pathoc( + ("127.0.0.1", self.d.port), + use_http2 = True, + ssl = False, + ) + tutils.raises(NotImplementedError, c.connect) + class TestDaemon(_TestDaemon): ssl = False @@ -216,3 +226,49 @@ class TestDaemon(_TestDaemon): "HTTP/1.1 200 OK\r\n" ) c.http_connect(to) + + +class TestDaemonHTTP2(_TestDaemon): + ssl = True + ssloptions = pathod.SSLOptions( + alpn_select = http2.HTTP2Protocol.ALPN_PROTO_H2, + ) + + def test_http2(self): + c = pathoc.Pathoc( + ("127.0.0.1", self.d.port), + use_http2 = True, + ssl = True, + ) + assert isinstance(c.protocol, http2.HTTP2Protocol) + + c = pathoc.Pathoc( + ("127.0.0.1", self.d.port), + ) + assert c.protocol == None # TODO: change if other protocols get implemented + + def test_http2_alpn(self): + c = pathoc.Pathoc( + ("127.0.0.1", self.d.port), + ssl = True, + use_http2 = True, + http2_skip_connection_preface = True, + ) + + tmp_convert_to_ssl = c.convert_to_ssl + c.convert_to_ssl = Mock() + c.convert_to_ssl.side_effect = tmp_convert_to_ssl + c.connect() + + _, kwargs = c.convert_to_ssl.call_args + assert set(kwargs['alpn_protos']) == set([b'http1.1', b'h2']) + + def test_request(self): + c = pathoc.Pathoc( + ("127.0.0.1", self.d.port), + ssl = True, + use_http2 = True, + ) + c.connect() + resp = c.request("get:/api/info") + assert tuple(json.loads(resp.content)["version"]) == version.IVERSION -- cgit v1.2.3 From 30fbf57e4b72e3947c323d98aee7b2d44663e33c Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Fri, 12 Jun 2015 13:41:04 +0200 Subject: delay pathod parsing until needed This allows us to use different languages based on runtime env. --- test/test_pathoc.py | 2 +- test/test_pathod_cmdline.py | 19 ------------------- test/tutils.py | 2 +- 3 files changed, 2 insertions(+), 21 deletions(-) (limited to 'test') diff --git a/test/test_pathoc.py b/test/test_pathoc.py index 28514378..e1e1fe97 100644 --- a/test/test_pathoc.py +++ b/test/test_pathoc.py @@ -23,7 +23,7 @@ class _TestDaemon: ssloptions = self.ssloptions, staticdir = tutils.test_data.path("data"), anchors = [ - (re.compile("/anchor/.*"), language.parse_pathod("202")) + (re.compile("/anchor/.*"), "202") ] ) diff --git a/test/test_pathod_cmdline.py b/test/test_pathod_cmdline.py index 590bb56b..829c4b32 100644 --- a/test/test_pathod_cmdline.py +++ b/test/test_pathod_cmdline.py @@ -65,15 +65,6 @@ def test_pathod(perror): assert perror.called perror.reset_mock() - s = cStringIO.StringIO() - tutils.raises( - SystemExit, - cmdline.args_pathod, - ["pathod", "-a", "foo=."], - s, - s - ) - a = cmdline.args_pathod( [ "pathod", @@ -92,13 +83,3 @@ def test_pathod(perror): ) assert perror.called perror.reset_mock() - - a = cmdline.args_pathod( - [ - "pathod", - "-c", - "?" - ] - ) - assert perror.called - perror.reset_mock() diff --git a/test/tutils.py b/test/tutils.py index c56c60d4..60c0765a 100644 --- a/test/tutils.py +++ b/test/tutils.py @@ -27,7 +27,7 @@ class DaemonTests(object): klass.d = test.Daemon( staticdir=test_data.path("data"), anchors=[ - (re.compile("/anchor/.*"), language.parse_pathod("202:da")) + (re.compile("/anchor/.*"), "202:da") ], ssl = klass.ssl, ssloptions = so, -- cgit v1.2.3 From a0d8afd0fcc3c678da0dc956c5a80d4e07d5ac3e Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Thu, 11 Jun 2015 16:13:22 +0200 Subject: http2: add request-response to pathod --- test/test_language_http2.py | 3 ++- test/test_pathoc.py | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/test_language_http2.py b/test/test_language_http2.py index de3e5cf9..3c751fd1 100644 --- a/test/test_language_http2.py +++ b/test/test_language_http2.py @@ -1,5 +1,6 @@ import cStringIO +from netlib import tcp from libpathod import language from libpathod.language import http2, base import netlib @@ -64,7 +65,7 @@ class TestRequest: s, language.Settings( request_host = "foo.com", - protocol = netlib.http2.HTTP2Protocol(None) + protocol = netlib.http2.HTTP2Protocol(tcp.TCPClient(('localhost', 1234))) ) ) diff --git a/test/test_pathoc.py b/test/test_pathoc.py index e1e1fe97..d39f9275 100644 --- a/test/test_pathoc.py +++ b/test/test_pathoc.py @@ -230,9 +230,6 @@ class TestDaemon(_TestDaemon): class TestDaemonHTTP2(_TestDaemon): ssl = True - ssloptions = pathod.SSLOptions( - alpn_select = http2.HTTP2Protocol.ALPN_PROTO_H2, - ) def test_http2(self): c = pathoc.Pathoc( @@ -270,5 +267,5 @@ class TestDaemonHTTP2(_TestDaemon): use_http2 = True, ) c.connect() - resp = c.request("get:/api/info") - assert tuple(json.loads(resp.content)["version"]) == version.IVERSION + resp = c.request("get:/p/200") + assert resp.status_code == "200" -- cgit v1.2.3 From 408b4ffef0a784bea7ec08c252e757bca6e28134 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 16 Jun 2015 13:52:41 +0200 Subject: http2: implement Headers for request & response improve test coverage fix super ctor call fix legacy httpversion simpliy SSLInfo without ALPN --- test/test_language_http2.py | 111 ++++++++++++++++++++++++++++++++++++++++++-- test/test_pathod.py | 14 +++++- test/tutils.py | 6 ++- 3 files changed, 123 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/test/test_language_http2.py b/test/test_language_http2.py index 3c751fd1..0be42253 100644 --- a/test/test_language_http2.py +++ b/test/test_language_http2.py @@ -10,8 +10,29 @@ import tutils def parse_request(s): return language.parse_pathoc(s, True).next() +def parse_response(s): + return language.parse_pathod(s, True).next() + +def default_settings(): + return language.Settings( + request_host = "foo.com", + protocol = netlib.http2.HTTP2Protocol(tcp.TCPClient(('localhost', 1234))) + ) + + +def test_make_error_response(): + d = cStringIO.StringIO() + s = http2.make_error_response("foo", "bar") + language.serve(s, d, default_settings()) + class TestRequest: + def test_cached_values(self): + req = parse_request("get:/") + req_id = id(req) + assert req_id == id(req.resolve(default_settings())) + assert req.values(default_settings()) == req.values(default_settings()) + def test_nonascii(self): tutils.raises("ascii", parse_request, "get:\xf0") @@ -57,16 +78,31 @@ class TestRequest: assert r[0].method.string() == "GET" assert r[1].method.string() == "GET" - def test_render(self): + def test_render_simple(self): s = cStringIO.StringIO() r = parse_request("GET:'/foo'") assert language.serve( r, s, - language.Settings( - request_host = "foo.com", - protocol = netlib.http2.HTTP2Protocol(tcp.TCPClient(('localhost', 1234))) - ) + default_settings(), + ) + + def test_render_with_headers(self): + s = cStringIO.StringIO() + r = parse_request('GET:/foo:h"foo"="bar"') + assert language.serve( + r, + s, + default_settings(), + ) + + def test_render_with_body(self): + s = cStringIO.StringIO() + r = parse_request("GET:'/foo':bfoobar") + assert language.serve( + r, + s, + default_settings(), ) def test_spec(self): @@ -74,3 +110,68 @@ class TestRequest: s = parse_request(s).spec() assert parse_request(s).spec() == s rt("get:/foo") + + +class TestResponse: + def test_cached_values(self): + res = parse_response("200") + res_id = id(res) + assert res_id == id(res.resolve(default_settings())) + assert res.values(default_settings()) == res.values(default_settings()) + + def test_nonascii(self): + tutils.raises("ascii", parse_response, "200:\xf0") + + def test_err(self): + tutils.raises(language.ParseException, parse_response, 'GET:/') + + def test_simple(self): + r = parse_response('200') + assert r.code.string() == "200" + assert len(r.headers) == 0 + + r = parse_response('200:h"foo"="bar"') + assert r.code.string() == "200" + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("foo", "bar") + assert r.body == None + + r = parse_response('200:h"foo"="bar":bfoobar:h"bla"="fasel"') + assert r.code.string() == "200" + assert len(r.headers) == 2 + assert r.headers[0].values(default_settings()) == ("foo", "bar") + assert r.headers[1].values(default_settings()) == ("bla", "fasel") + assert r.body.string() == "foobar" + + def test_render_simple(self): + s = cStringIO.StringIO() + r = parse_response('200') + assert language.serve( + r, + s, + default_settings(), + ) + + def test_render_with_headers(self): + s = cStringIO.StringIO() + r = parse_response('200:h"foo"="bar"') + assert language.serve( + r, + s, + default_settings(), + ) + + def test_render_with_body(self): + s = cStringIO.StringIO() + r = parse_response('200:bfoobar') + assert language.serve( + r, + s, + default_settings(), + ) + + def test_spec(self): + def rt(s): + s = parse_response(s).spec() + assert parse_response(s).spec() == s + rt("200:bfoobar") diff --git a/test/test_pathod.py b/test/test_pathod.py index f85ef38d..1a3a5004 100644 --- a/test/test_pathod.py +++ b/test/test_pathod.py @@ -1,7 +1,7 @@ import sys import cStringIO from libpathod import pathod, version -from netlib import tcp, http +from netlib import tcp, http, http2 import tutils @@ -269,3 +269,15 @@ class TestDaemonSSL(CommonTests): r, _ = self.pathoc([r"get:/p/202"]) assert r[0].status_code == 202 assert self.d.last_log()["cipher"][1] > 0 + +class TestHTTP2(tutils.DaemonTests): + force_http2 = True + ssl = True + noweb = True + noapi = True + nohang = True + + def test_http2(self): + r, _ = self.pathoc(["GET:/"], ssl=True, use_http2=True) + print(r) + assert r[0].status_code == "800" diff --git a/test/tutils.py b/test/tutils.py index 60c0765a..2184ade5 100644 --- a/test/tutils.py +++ b/test/tutils.py @@ -73,7 +73,8 @@ class DaemonTests(object): timeout=None, connect_to=None, ssl=None, - ws_read_limit=None + ws_read_limit=None, + use_http2=False, ): """ Returns a (messages, text log) tuple. @@ -86,7 +87,8 @@ class DaemonTests(object): ssl=ssl, ws_read_limit=ws_read_limit, timeout = timeout, - fp = logfp + fp = logfp, + use_http2 = use_http2, ) c.connect(connect_to) ret = [] -- cgit v1.2.3