18 """this module contains base classes and utilities for integration with running |
18 """this module contains base classes and utilities for integration with running |
19 http server |
19 http server |
20 """ |
20 """ |
21 from __future__ import print_function |
21 from __future__ import print_function |
22 |
22 |
23 |
|
24 |
|
25 import random |
23 import random |
26 import threading |
24 import threading |
27 import socket |
25 import socket |
28 |
26 |
29 from six.moves import range, http_client |
27 from six.moves import range, http_client |
30 from six.moves.urllib.parse import urlparse |
28 from six.moves.urllib.parse import urlparse |
31 |
29 |
32 |
30 |
33 from cubicweb.devtools.testlib import CubicWebTC |
31 from cubicweb.devtools.testlib import CubicWebTC |
34 from cubicweb.devtools import ApptestConfiguration |
|
35 |
32 |
36 |
33 |
37 def get_available_port(ports_scan): |
34 def get_available_port(ports_scan): |
38 """return the first available port from the given ports range |
35 """return the first available port from the given ports range |
39 |
36 |
51 ports_scan = list(ports_scan) |
48 ports_scan = list(ports_scan) |
52 random.shuffle(ports_scan) # lower the chance of race condition |
49 random.shuffle(ports_scan) # lower the chance of race condition |
53 for port in ports_scan: |
50 for port in ports_scan: |
54 try: |
51 try: |
55 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
52 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
56 sock = s.connect(("localhost", port)) |
53 s.connect(("localhost", port)) |
57 except socket.error as err: |
54 except socket.error as err: |
58 if err.args[0] in (111, 106): |
55 if err.args[0] in (111, 106): |
59 return port |
56 return port |
60 finally: |
57 finally: |
61 s.close() |
58 s.close() |
78 """Log the current http session for the provided credential |
75 """Log the current http session for the provided credential |
79 |
76 |
80 If no user is provided, admin connection are used. |
77 If no user is provided, admin connection are used. |
81 """ |
78 """ |
82 if user is None: |
79 if user is None: |
83 user = self.admlogin |
80 user = self.admlogin |
84 passwd = self.admpassword |
81 passwd = self.admpassword |
85 if passwd is None: |
82 if passwd is None: |
86 passwd = user |
83 passwd = user |
87 response = self.web_get("login?__login=%s&__password=%s" % |
84 response = self.web_get("login?__login=%s&__password=%s" % |
88 (user, passwd)) |
85 (user, passwd)) |
92 return True |
89 return True |
93 |
90 |
94 def web_logout(self, user='admin', pwd=None): |
91 def web_logout(self, user='admin', pwd=None): |
95 """Log out current http user""" |
92 """Log out current http user""" |
96 if self._ident_cookie is not None: |
93 if self._ident_cookie is not None: |
97 response = self.web_get('logout') |
94 self.web_get('logout') |
98 self._ident_cookie = None |
95 self._ident_cookie = None |
99 |
96 |
100 def web_request(self, path='', method='GET', body=None, headers=None): |
97 def web_request(self, path='', method='GET', body=None, headers=None): |
101 """Return an http_client.HTTPResponse object for the specified path |
98 """Return an http_client.HTTPResponse object for the specified path |
102 |
99 |
107 if self._ident_cookie is not None: |
104 if self._ident_cookie is not None: |
108 assert 'Cookie' not in headers |
105 assert 'Cookie' not in headers |
109 headers['Cookie'] = self._ident_cookie |
106 headers['Cookie'] = self._ident_cookie |
110 self._web_test_cnx.request(method, '/' + path, headers=headers, body=body) |
107 self._web_test_cnx.request(method, '/' + path, headers=headers, body=body) |
111 response = self._web_test_cnx.getresponse() |
108 response = self._web_test_cnx.getresponse() |
112 response.body = response.read() # to chain request |
109 response.body = response.read() # to chain request |
113 response.read = lambda : response.body |
110 response.read = lambda: response.body |
114 return response |
111 return response |
115 |
112 |
116 def web_get(self, path='', body=None, headers=None): |
113 def web_get(self, path='', body=None, headers=None): |
117 return self.web_request(path=path, body=body, headers=headers) |
114 return self.web_request(path=path, body=body, headers=headers) |
118 |
115 |
119 def setUp(self): |
116 def setUp(self): |
120 super(_CubicWebServerTC, self).setUp() |
117 super(_CubicWebServerTC, self).setUp() |
121 port = self.config['port'] or get_available_port(self.ports_range) |
118 port = self.config['port'] or get_available_port(self.ports_range) |
122 self.config.global_set_option('port', port) # force rewrite here |
119 self.config.global_set_option('port', port) # force rewrite here |
123 self.config.global_set_option('base-url', 'http://127.0.0.1:%d/' % port) |
120 self.config.global_set_option('base-url', 'http://127.0.0.1:%d/' % port) |
124 # call load_configuration again to let the config reset its datadir_url |
121 # call load_configuration again to let the config reset its datadir_url |
125 self.config.load_configuration() |
122 self.config.load_configuration() |
126 self.start_server() |
123 self.start_server() |
127 |
124 |