diff options
author | Rouli <rouli.net@gmail.com> | 2013-03-18 14:24:13 +0200 |
---|---|---|
committer | Rouli <rouli.net@gmail.com> | 2013-03-18 14:24:13 +0200 |
commit | c94aadcb0ee5e7aab8acc46a0e4ac7d02a28df6f (patch) | |
tree | 1e62785d669d86f6e551a99b9debfe445389bd48 /test | |
parent | b6cae7cd2d0105d6a6fe9d35864d0f9b7c5f8924 (diff) | |
parent | 5c33f6784b4ba34dd9825ea7e3070cdf0b2b4621 (diff) | |
download | mitmproxy-c94aadcb0ee5e7aab8acc46a0e4ac7d02a28df6f.tar.gz mitmproxy-c94aadcb0ee5e7aab8acc46a0e4ac7d02a28df6f.tar.bz2 mitmproxy-c94aadcb0ee5e7aab8acc46a0e4ac7d02a28df6f.zip |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'test')
-rw-r--r-- | test/data/htpasswd | 1 | ||||
-rw-r--r-- | test/data/htpasswd.invalid | 1 | ||||
-rwxr-xr-x | test/fuzzing/go_proxy | 22 | ||||
-rw-r--r-- | test/test_authentication.py | 58 | ||||
-rw-r--r-- | test/test_console_common.py | 10 | ||||
-rw-r--r-- | test/test_controller.py | 12 | ||||
-rw-r--r-- | test/test_dump.py | 18 | ||||
-rw-r--r-- | test/test_flow.py | 32 | ||||
-rw-r--r-- | test/test_fuzzing.py | 39 | ||||
-rw-r--r-- | test/test_proxy.py | 91 | ||||
-rw-r--r-- | test/test_server.py | 169 | ||||
-rw-r--r-- | test/tservers.py | 102 |
12 files changed, 410 insertions, 145 deletions
diff --git a/test/data/htpasswd b/test/data/htpasswd new file mode 100644 index 00000000..54c95b8c --- /dev/null +++ b/test/data/htpasswd @@ -0,0 +1 @@ +test:$apr1$/LkYxy3x$WI4.YbiJlu537jLGEW2eu1 diff --git a/test/data/htpasswd.invalid b/test/data/htpasswd.invalid new file mode 100644 index 00000000..257cc564 --- /dev/null +++ b/test/data/htpasswd.invalid @@ -0,0 +1 @@ +foo diff --git a/test/fuzzing/go_proxy b/test/fuzzing/go_proxy new file mode 100755 index 00000000..c9b6aef6 --- /dev/null +++ b/test/fuzzing/go_proxy @@ -0,0 +1,22 @@ +#!/bin/sh +# Assuming: +# mitmproxy/mitmdump is running on port 8080 in straight proxy mode. +# pathod is running on port 9999 + +BASE_HTTP="/Users/aldo/git/public/pathod/pathoc -Tt 1 -eo -I 200,400,405,502 -p 8080 localhost " +#$BASE_HTTP -n 10000 "get:'http://localhost:9999':ir,@1" +#$BASE_HTTP -n 100 "get:'http://localhost:9999':dr" +#$BASE_HTTP -n 10000 "get:'http://localhost:9999/p/200:ir,@300.0 + + +# Assuming: +# mitmproxy/mitmdump is running on port 8080 in straight proxy mode. +# pathod with SSL enabled is running on port 9999 + +BASE_HTTPS="/Users/aldo/git/public/pathod/pathoc -sc localhost:9999 -Tt 1 -eo -I 200,400,404,405,502,800 -p 8080 localhost " +$BASE_HTTPS -en 10000 "get:'/p/200:b@10:ir,@1'" +#$BASE_HTTPS -en 10000 "get:'/p/200:ir,@1'" + +#$BASE_HTTPS -n 100 "get:'/p/200:dr'" +#$BASE_HTTPS -n 10000 "get:'/p/200:ir,@3000'" +#$BASE_HTTPS -n 10000 "get:'/p/200:ir,\"\\n\"'" diff --git a/test/test_authentication.py b/test/test_authentication.py deleted file mode 100644 index f7a5ecd3..00000000 --- a/test/test_authentication.py +++ /dev/null @@ -1,58 +0,0 @@ -import binascii -from libmproxy import authentication -from netlib import odict -import tutils - - -class TestNullProxyAuth: - def test_simple(self): - na = authentication.NullProxyAuth(authentication.PermissivePasswordManager()) - assert not na.auth_challenge_headers() - assert na.authenticate("foo") - na.clean({}) - - -class TestBasicProxyAuth: - def test_simple(self): - ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test") - h = odict.ODictCaseless() - assert ba.auth_challenge_headers() - assert not ba.authenticate(h) - - def test_parse_auth_value(self): - ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test") - vals = ("basic", "foo", "bar") - assert ba.parse_auth_value(ba.unparse_auth_value(*vals)) == vals - tutils.raises(ValueError, ba.parse_auth_value, "") - tutils.raises(ValueError, ba.parse_auth_value, "foo bar") - - v = "basic " + binascii.b2a_base64("foo") - tutils.raises(ValueError, ba.parse_auth_value, v) - - def test_authenticate_clean(self): - ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test") - - hdrs = odict.ODictCaseless() - vals = ("basic", "foo", "bar") - hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)] - assert ba.authenticate(hdrs) - - ba.clean(hdrs) - assert not ba.AUTH_HEADER in hdrs - - - hdrs[ba.AUTH_HEADER] = [""] - assert not ba.authenticate(hdrs) - - hdrs[ba.AUTH_HEADER] = ["foo"] - assert not ba.authenticate(hdrs) - - vals = ("foo", "foo", "bar") - hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)] - assert not ba.authenticate(hdrs) - - ba = authentication.BasicProxyAuth(authentication.PasswordManager(), "test") - vals = ("basic", "foo", "bar") - hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)] - assert not ba.authenticate(hdrs) - diff --git a/test/test_console_common.py b/test/test_console_common.py new file mode 100644 index 00000000..29bf7b84 --- /dev/null +++ b/test/test_console_common.py @@ -0,0 +1,10 @@ +import libmproxy.console.common as common +from libmproxy import utils, flow, encoding +import tutils + + +def test_format_flow(): + f = tutils.tflow_full() + assert common.format_flow(f, True) + assert common.format_flow(f, True, hostheader=True) + assert common.format_flow(f, True, extended=True) diff --git a/test/test_controller.py b/test/test_controller.py new file mode 100644 index 00000000..f6d6b5eb --- /dev/null +++ b/test/test_controller.py @@ -0,0 +1,12 @@ +import mock +from libmproxy import controller + + +class TestMaster: + def test_default_handler(self): + m = controller.Master(None) + msg = mock.MagicMock() + m.handle(msg) + assert msg.reply.call_count == 1 + + diff --git a/test/test_dump.py b/test/test_dump.py index 5d3f9133..94d0b195 100644 --- a/test/test_dump.py +++ b/test/test_dump.py @@ -1,6 +1,5 @@ import os from cStringIO import StringIO -import libpry from libmproxy import dump, flow, proxy import tutils import mock @@ -13,8 +12,10 @@ def test_strfuncs(): t = tutils.treq() t.client_conn = None t.stickycookie = True - assert "stickycookie" in dump.str_request(t) - assert "replay" in dump.str_request(t) + assert "stickycookie" in dump.str_request(t, False) + assert "stickycookie" in dump.str_request(t, True) + assert "replay" in dump.str_request(t, False) + assert "replay" in dump.str_request(t, True) class TestDumpMaster: @@ -65,7 +66,7 @@ class TestDumpMaster: cs = StringIO() o = dump.Options(server_replay="nonexistent", kill=True) - libpry.raises(dump.DumpError, dump.DumpMaster, None, o, None, outfile=cs) + tutils.raises(dump.DumpError, dump.DumpMaster, None, o, None, outfile=cs) with tutils.tmpdir() as t: p = os.path.join(t, "rep") @@ -90,7 +91,7 @@ class TestDumpMaster: self._flowfile(p) assert "GET" in self._dummy_cycle(0, None, "", verbosity=1, rfile=p) - libpry.raises( + tutils.raises( dump.DumpError, self._dummy_cycle, 0, None, "", verbosity=1, rfile="/nonexistent" ) @@ -101,7 +102,6 @@ class TestDumpMaster: def test_options(self): o = dump.Options(verbosity = 2) assert o.verbosity == 2 - libpry.raises(AttributeError, dump.Options, nonexistent = 2) def test_filter(self): assert not "GET" in self._dummy_cycle(1, "~u foo", "", verbosity=1) @@ -131,7 +131,7 @@ class TestDumpMaster: assert len(list(flow.FlowReader(open(p)).stream())) == 1 def test_write_err(self): - libpry.raises( + tutils.raises( dump.DumpError, self._dummy_cycle, 1, @@ -149,11 +149,11 @@ class TestDumpMaster: assert "XREQUEST" in ret assert "XRESPONSE" in ret assert "XCLIENTDISCONNECT" in ret - libpry.raises( + tutils.raises( dump.DumpError, self._dummy_cycle, 1, None, "", script="nonexistent" ) - libpry.raises( + tutils.raises( dump.DumpError, self._dummy_cycle, 1, None, "", script="starterr.py" ) diff --git a/test/test_flow.py b/test/test_flow.py index 6aa898ad..fce4e98a 100644 --- a/test/test_flow.py +++ b/test/test_flow.py @@ -498,6 +498,23 @@ class TestSerialize: fm.load_flows(r) assert len(s._flow_list) == 6 + def test_filter(self): + sio = StringIO() + fl = filt.parse("~c 200") + w = flow.FilteredFlowWriter(sio, fl) + + f = tutils.tflow_full() + f.response.code = 200 + w.add(f) + + f = tutils.tflow_full() + f.response.code = 201 + w.add(f) + + sio.seek(0) + r = flow.FlowReader(sio) + assert len(list(r.stream())) + def test_error(self): sio = StringIO() @@ -723,7 +740,7 @@ class TestFlowMaster: fm = flow.FlowMaster(None, s) tf = tutils.tflow_full() - fm.start_stream(file(p, "ab")) + fm.start_stream(file(p, "ab"), None) fm.handle_request(tf.request) fm.handle_response(tf.response) fm.stop_stream() @@ -731,7 +748,7 @@ class TestFlowMaster: assert r()[0].response tf = tutils.tflow_full() - fm.start_stream(file(p, "ab")) + fm.start_stream(file(p, "ab"), None) fm.handle_request(tf.request) fm.shutdown() @@ -766,6 +783,17 @@ class TestRequest: r.content = flow.CONTENT_MISSING assert not r._assemble() + def test_get_url(self): + h = flow.ODictCaseless() + h["test"] = ["test"] + c = flow.ClientConnect(("addr", 2222)) + r = flow.Request(c, (1, 1), "host", 22, "https", "GET", "/", h, "content") + assert r.get_url() == "https://host:22/" + assert r.get_url(hostheader=True) == "https://host:22/" + r.headers["Host"] = ["foo.com"] + assert r.get_url() == "https://host:22/" + assert r.get_url(hostheader=True) == "https://foo.com:22/" + def test_path_components(self): h = flow.ODictCaseless() c = flow.ClientConnect(("addr", 2222)) diff --git a/test/test_fuzzing.py b/test/test_fuzzing.py new file mode 100644 index 00000000..ba7b751c --- /dev/null +++ b/test/test_fuzzing.py @@ -0,0 +1,39 @@ +import tservers + +""" + A collection of errors turned up by fuzzing. Errors are integrated here + after being fixed to check for regressions. +""" + +class TestFuzzy(tservers.HTTPProxTest): + def test_idna_err(self): + req = r'get:"http://localhost:%s":i10,"\xc6"' + p = self.pathoc() + assert p.request(req%self.server.port).status_code == 400 + + def test_nullbytes(self): + req = r'get:"http://localhost:%s":i19,"\x00"' + p = self.pathoc() + assert p.request(req%self.server.port).status_code == 400 + + def test_invalid_ports(self): + req = 'get:"http://localhost:999999"' + p = self.pathoc() + assert p.request(req).status_code == 400 + + def test_invalid_ipv6_url(self): + req = 'get:"http://localhost:%s":i13,"["' + p = self.pathoc() + assert p.request(req%self.server.port).status_code == 400 + + def test_invalid_upstream(self): + req = r"get:'http://localhost:%s/p/200:i10,\'+\''" + p = self.pathoc() + assert p.request(req%self.server.port).status_code == 502 + + def test_upstream_disconnect(self): + req = r'200:d0:h"Date"="Sun, 03 Mar 2013 04:00:00 GMT"' + p = self.pathod(req) + assert p.status_code == 400 + + diff --git a/test/test_proxy.py b/test/test_proxy.py index 3995b393..5828d077 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -1,4 +1,5 @@ -from libmproxy import proxy, flow +import argparse +from libmproxy import proxy, flow, cmdline import tutils from libpathod import test from netlib import http, tcp @@ -22,7 +23,6 @@ def test_app_registry(): r.port = 81 assert not ar.get(r) - r = tutils.treq() r.host = "domain2" r.port = 80 @@ -59,3 +59,90 @@ class TestServerConnection: sc.connection.close = mock.Mock(side_effect=IOError) sc.terminate() + +class MockParser: + def __init__(self): + self.err = None + + def error(self, e): + self.err = e + + def __repr__(self): + return "ParseError(%s)"%self.err + + +class TestProcessProxyOptions: + def p(self, *args): + parser = argparse.ArgumentParser() + cmdline.common_options(parser) + opts = parser.parse_args(args=args) + m = MockParser() + return m, proxy.process_proxy_options(m, opts) + + def assert_err(self, err, *args): + m, p = self.p(*args) + assert err.lower() in m.err.lower() + + def assert_noerr(self, *args): + m, p = self.p(*args) + assert p + return p + + def test_simple(self): + assert self.p() + + def test_cert(self): + self.assert_noerr("--cert", tutils.test_data.path("data/testkey.pem")) + self.assert_err("does not exist", "--cert", "nonexistent") + + def test_confdir(self): + with tutils.tmpdir() as confdir: + self.assert_noerr("--confdir", confdir) + + @mock.patch("libmproxy.platform.resolver", None) + def test_no_transparent(self): + self.assert_err("transparent mode not supported", "-T") + + @mock.patch("libmproxy.platform.resolver") + def test_transparent_reverse(self, o): + self.assert_err("can't set both", "-P", "reverse", "-T") + self.assert_noerr("-T") + assert o.call_count == 1 + self.assert_err("invalid reverse proxy", "-P", "reverse") + self.assert_noerr("-P", "http://localhost") + + def test_certs(self): + with tutils.tmpdir() as confdir: + self.assert_noerr("--client-certs", confdir) + self.assert_err("directory does not exist", "--client-certs", "nonexistent") + + self.assert_noerr("--dummy-certs", confdir) + self.assert_err("directory does not exist", "--dummy-certs", "nonexistent") + + def test_auth(self): + p = self.assert_noerr("--nonanonymous") + assert p.authenticator + + p = self.assert_noerr("--htpasswd", tutils.test_data.path("data/htpasswd")) + assert p.authenticator + self.assert_err("invalid htpasswd file", "--htpasswd", tutils.test_data.path("data/htpasswd.invalid")) + + p = self.assert_noerr("--singleuser", "test:test") + assert p.authenticator + self.assert_err("invalid single-user specification", "--singleuser", "test") + + +class TestProxyServer: + def test_err(self): + parser = argparse.ArgumentParser() + cmdline.common_options(parser) + opts = parser.parse_args(args=[]) + tutils.raises("error starting proxy server", proxy.ProxyServer, opts, 1) + + +class TestDummyServer: + def test_simple(self): + d = proxy.DummyServer(None) + d.start_slave() + d.shutdown() + diff --git a/test/test_server.py b/test/test_server.py index 034fab41..f12fbcee 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -1,6 +1,6 @@ import socket, time import mock -from netlib import tcp +from netlib import tcp, http_auth, http from libpathod import pathoc import tutils, tservers from libmproxy import flow, proxy @@ -13,11 +13,7 @@ from libmproxy import flow, proxy for a 200 response. """ -class SanityMixin: - def test_http(self): - assert self.pathod("304").status_code == 304 - assert self.master.state.view - +class CommonMixin: def test_large(self): assert len(self.pathod("200:b@50k").content) == 1024*50 @@ -40,27 +36,30 @@ class SanityMixin: self.master.replay_request(l, block=True) assert l.error + def test_http(self): + f = self.pathod("304") + assert f.status_code == 304 -class TestHTTP(tservers.HTTPProxTest, SanityMixin): - def test_app(self): - p = self.pathoc() - ret = p.request("get:'http://testapp/'") - assert ret[1] == 200 - assert ret[4] == "testapp" - - def test_app_err(self): - p = self.pathoc() - ret = p.request("get:'http://errapp/'") - assert ret[1] == 500 - assert "ValueError" in ret[4] + l = self.master.state.view[0] + assert l.request.client_conn.address + assert "host" in l.request.headers + assert l.response.code == 304 def test_invalid_http(self): t = tcp.TCPClient("127.0.0.1", self.proxy.port) t.connect() - t.wfile.write("invalid\n\n") + t.wfile.write("invalid\r\n\r\n") t.wfile.flush() assert "Bad Request" in t.rfile.readline() + +class TestHTTP(tservers.HTTPProxTest, CommonMixin): + def test_app_err(self): + p = self.pathoc() + ret = p.request("get:'http://errapp/'") + assert ret.status_code == 500 + assert "ValueError" in ret.content + def test_invalid_connect(self): t = tcp.TCPClient("127.0.0.1", self.proxy.port) t.connect() @@ -71,16 +70,7 @@ class TestHTTP(tservers.HTTPProxTest, SanityMixin): def test_upstream_ssl_error(self): p = self.pathoc() ret = p.request("get:'https://localhost:%s/'"%self.server.port) - assert ret[1] == 400 - - def test_http(self): - f = self.pathod("304") - assert f.status_code == 304 - - l = self.master.state.view[0] - assert l.request.client_conn.address - assert "host" in l.request.headers - assert l.response.code == 304 + assert ret.status_code == 400 def test_connection_close(self): # Add a body, so we have a content-length header, which combined with @@ -116,7 +106,7 @@ class TestHTTP(tservers.HTTPProxTest, SanityMixin): # within our read loop. with mock.patch("libmproxy.proxy.ProxyHandler.read_request") as m: m.side_effect = IOError("error!") - tutils.raises("empty reply", self.pathod, "304") + tutils.raises("server disconnect", self.pathod, "304") def test_get_connection_switching(self): def switched(l): @@ -132,30 +122,101 @@ class TestHTTP(tservers.HTTPProxTest, SanityMixin): def test_get_connection_err(self): p = self.pathoc() ret = p.request("get:'http://localhost:0'") - assert ret[1] == 502 + assert ret.status_code == 502 + + def test_blank_leading_line(self): + p = self.pathoc() + req = "get:'%s/p/201':i0,'\r\n'" + assert p.request(req%self.server.urlbase).status_code == 201 + + def test_invalid_headers(self): + p = self.pathoc() + req = p.request("get:'http://foo':h':foo'='bar'") + assert req.status_code == 400 -class TestHTTPS(tservers.HTTPProxTest, SanityMixin): +class TestHTTPAuth(tservers.HTTPProxTest): + authenticator = http_auth.BasicProxyAuth(http_auth.PassManSingleUser("test", "test"), "realm") + def test_auth(self): + assert self.pathod("202").status_code == 407 + p = self.pathoc() + ret = p.request(""" + get + 'http://localhost:%s/p/202' + h'%s'='%s' + """%( + self.server.port, + http_auth.BasicProxyAuth.AUTH_HEADER, + http.assemble_http_basic_auth("basic", "test", "test") + )) + assert ret.status_code == 202 + + +class TestHTTPConnectSSLError(tservers.HTTPProxTest): + certfile = True + def test_go(self): + p = self.pathoc() + req = "connect:'localhost:%s'"%self.proxy.port + assert p.request(req).status_code == 200 + assert p.request(req).status_code == 400 + + +class TestHTTPS(tservers.HTTPProxTest, CommonMixin): ssl = True clientcerts = True def test_clientcert(self): f = self.pathod("304") + assert f.status_code == 304 assert self.server.last_log()["request"]["clientcert"]["keyinfo"] + def test_sni(self): + f = self.pathod("304", sni="testserver.com") + assert f.status_code == 304 + l = self.server.last_log() + assert self.server.last_log()["request"]["sni"] == "testserver.com" -class TestHTTPSCertfile(tservers.HTTPProxTest, SanityMixin): + def test_error_post_connect(self): + p = self.pathoc() + assert p.request("get:/:i0,'invalid\r\n\r\n'").status_code == 400 + + +class TestHTTPSNoUpstream(tservers.HTTPProxTest, CommonMixin): + ssl = True + no_upstream_cert = True + def test_cert_gen_error(self): + f = self.pathoc_raw() + f.connect((u"foo..bar".encode("utf8"), 0)) + f.request("get:/") + assert "dummy cert" in "".join(self.proxy.log) + + +class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin): ssl = True certfile = True def test_certfile(self): assert self.pathod("304") -class TestReverse(tservers.ReverseProxTest, SanityMixin): +class TestReverse(tservers.ReverseProxTest, CommonMixin): reverse = True -class TestTransparent(tservers.TransparentProxTest, SanityMixin): - transparent = True +class TestTransparent(tservers.TransparentProxTest, CommonMixin): + ssl = False + + +class TestTransparentSSL(tservers.TransparentProxTest, CommonMixin): + ssl = True + def test_sni(self): + f = self.pathod("304", sni="testserver.com") + assert f.status_code == 304 + l = self.server.last_log() + assert self.server.last_log()["request"]["sni"] == "testserver.com" + + def test_sslerr(self): + p = pathoc.Pathoc("localhost", self.proxy.port) + p.connect() + assert p.request("get:/").status_code == 400 class TestProxy(tservers.HTTPProxTest): @@ -216,8 +277,7 @@ class MasterFakeResponse(tservers.TestMaster): class TestFakeResponse(tservers.HTTPProxTest): masterclass = MasterFakeResponse - def test_kill(self): - p = self.pathoc() + def test_fake(self): f = self.pathod("200") assert "header_response" in f.headers.keys() @@ -231,8 +291,7 @@ class MasterKillRequest(tservers.TestMaster): class TestKillRequest(tservers.HTTPProxTest): masterclass = MasterKillRequest def test_kill(self): - p = self.pathoc() - tutils.raises("empty reply", self.pathod, "200") + tutils.raises("server disconnect", self.pathod, "200") # Nothing should have hit the server assert not self.server.last_log() @@ -245,8 +304,34 @@ class MasterKillResponse(tservers.TestMaster): class TestKillResponse(tservers.HTTPProxTest): masterclass = MasterKillResponse def test_kill(self): - p = self.pathoc() - tutils.raises("empty reply", self.pathod, "200") + tutils.raises("server disconnect", self.pathod, "200") # The server should have seen a request assert self.server.last_log() + +class EResolver(tservers.TResolver): + def original_addr(self, sock): + return None + + +class TestTransparentResolveError(tservers.TransparentProxTest): + resolver = EResolver + def test_resolve_error(self): + assert self.pathod("304").status_code == 502 + + + +class MasterIncomplete(tservers.TestMaster): + def handle_request(self, m): + resp = tutils.tresp() + resp.content = flow.CONTENT_MISSING + m.reply(resp) + + +class TestIncompleteResponse(tservers.HTTPProxTest): + masterclass = MasterIncomplete + def test_incomplete(self): + assert self.pathod("200").status_code == 502 + + + diff --git a/test/tservers.py b/test/tservers.py index 998ad6c6..0c2f8c2f 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -1,6 +1,5 @@ import threading, Queue import flask -import human_curl as hurl import libpathod.test, libpathod.pathoc from libmproxy import proxy, flow, controller import tutils @@ -28,7 +27,7 @@ class TestMaster(flow.FlowMaster): state = flow.State() flow.FlowMaster.__init__(self, s, state) self.testq = testq - self.log = [] + self.clear_log() def handle_request(self, m): flow.FlowMaster.handle_request(self, m) @@ -38,6 +37,9 @@ class TestMaster(flow.FlowMaster): flow.FlowMaster.handle_response(self, m) m.reply() + def clear_log(self): + self.log = [] + def handle_log(self, l): self.log.append(l.msg) l.reply() @@ -69,7 +71,8 @@ class ProxTestBase: ssl = None clientcerts = False certfile = None - + no_upstream_cert = False + authenticator = None masterclass = TestMaster @classmethod def setupAll(cls): @@ -78,7 +81,9 @@ class ProxTestBase: cls.server2 = libpathod.test.Daemon(ssl=cls.ssl) pconf = cls.get_proxy_config() config = proxy.ProxyConfig( + no_upstream_cert = cls.no_upstream_cert, cacert = tutils.test_data.path("data/serverkey.pem"), + authenticator = cls.authenticator, **pconf ) tmaster = cls.masterclass(cls.tqueue, config) @@ -96,7 +101,10 @@ class ProxTestBase: cls.server2.shutdown() def setUp(self): + self.master.clear_log() self.master.state.clear() + self.server.clear_log() + self.server2.clear_log() @property def scheme(self): @@ -122,24 +130,31 @@ class ProxTestBase: class HTTPProxTest(ProxTestBase): - def pathoc(self, connect_to = None): + def pathoc_raw(self): + return libpathod.pathoc.Pathoc("127.0.0.1", self.proxy.port) + + def pathoc(self, sni=None): """ Returns a connected Pathoc instance. """ - p = libpathod.pathoc.Pathoc("localhost", self.proxy.port) - p.connect(connect_to) + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl, sni=sni) + if self.ssl: + p.connect(("127.0.0.1", self.server.port)) + else: + p.connect() return p - def pathod(self, spec): + def pathod(self, spec, sni=None): """ - Constructs a pathod request, with the appropriate base and proxy. + Constructs a pathod GET request, with the appropriate base and proxy. """ - return hurl.get( - self.server.urlbase + "/p/" + spec, - proxy=self.proxies, - validate_cert=False, - #debug=hurl.utils.stdout_debug - ) + p = self.pathoc(sni=sni) + spec = spec.encode("string_escape") + if self.ssl: + q = "get:'/p/%s'"%spec + else: + q = "get:'%s/p/%s'"%(self.server.urlbase, spec) + return p.request(q) class TResolver: @@ -152,25 +167,39 @@ class TResolver: class TransparentProxTest(ProxTestBase): ssl = None + resolver = TResolver @classmethod def get_proxy_config(cls): d = ProxTestBase.get_proxy_config() + if cls.ssl: + ports = [cls.server.port, cls.server2.port] + else: + ports = [] d["transparent_proxy"] = dict( - resolver = TResolver(cls.server.port), - sslports = [] + resolver = cls.resolver(cls.server.port), + sslports = ports ) return d - def pathod(self, spec): + def pathod(self, spec, sni=None): """ - Constructs a pathod request, with the appropriate base and proxy. + Constructs a pathod GET request, with the appropriate base and proxy. """ - r = hurl.get( - "http://127.0.0.1:%s"%self.proxy.port + "/p/" + spec, - validate_cert=False, - #debug=hurl.utils.stdout_debug - ) - return r + if self.ssl: + p = self.pathoc(sni=sni) + q = "get:'/p/%s'"%spec + else: + p = self.pathoc() + q = "get:'/p/%s'"%spec + return p.request(q) + + def pathoc(self, sni=None): + """ + Returns a connected Pathoc instance. + """ + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl, sni=sni) + p.connect() + return p class ReverseProxTest(ProxTestBase): @@ -185,14 +214,23 @@ class ReverseProxTest(ProxTestBase): ) return d - def pathod(self, spec): + def pathoc(self, sni=None): """ - Constructs a pathod request, with the appropriate base and proxy. + Returns a connected Pathoc instance. """ - r = hurl.get( - "http://127.0.0.1:%s"%self.proxy.port + "/p/" + spec, - validate_cert=False, - #debug=hurl.utils.stdout_debug - ) - return r + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl, sni=sni) + p.connect() + return p + + def pathod(self, spec, sni=None): + """ + Constructs a pathod GET request, with the appropriate base and proxy. + """ + if self.ssl: + p = self.pathoc(sni=sni) + q = "get:'/p/%s'"%spec + else: + p = self.pathoc() + q = "get:'/p/%s'"%spec + return p.request(q) |