##// END OF EJS Templates
svn: fixed test
super-admin -
r5179:a31fb4ad default
parent child Browse files
Show More
@@ -1,207 +1,207 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 import io
19 import io
20
20
21 import pytest
21 import pytest
22 from mock import patch, Mock
22 from mock import patch, Mock
23
23
24 from rhodecode.lib.middleware.simplesvn import SimpleSvn, SimpleSvnApp
24 from rhodecode.lib.middleware.simplesvn import SimpleSvn, SimpleSvnApp
25 from rhodecode.lib.utils import get_rhodecode_base_path
25 from rhodecode.lib.utils import get_rhodecode_base_path
26
26
27
27
28 class TestSimpleSvn(object):
28 class TestSimpleSvn(object):
29 @pytest.fixture(autouse=True)
29 @pytest.fixture(autouse=True)
30 def simple_svn(self, baseapp, request_stub):
30 def simple_svn(self, baseapp, request_stub):
31 base_path = get_rhodecode_base_path()
31 base_path = get_rhodecode_base_path()
32 self.app = SimpleSvn(
32 self.app = SimpleSvn(
33 config={'auth_ret_code': '', 'base_path': base_path},
33 config={'auth_ret_code': '', 'base_path': base_path},
34 registry=request_stub.registry)
34 registry=request_stub.registry)
35
35
36 def test_get_config(self):
36 def test_get_config(self):
37 extras = {'foo': 'FOO', 'bar': 'BAR'}
37 extras = {'foo': 'FOO', 'bar': 'BAR'}
38 config = self.app._create_config(extras, repo_name='test-repo')
38 config = self.app._create_config(extras, repo_name='test-repo')
39 assert config == extras
39 assert config == extras
40
40
41 @pytest.mark.parametrize(
41 @pytest.mark.parametrize(
42 'method', ['OPTIONS', 'PROPFIND', 'GET', 'REPORT'])
42 'method', ['OPTIONS', 'PROPFIND', 'GET', 'REPORT'])
43 def test_get_action_returns_pull(self, method):
43 def test_get_action_returns_pull(self, method):
44 environment = {'REQUEST_METHOD': method}
44 environment = {'REQUEST_METHOD': method}
45 action = self.app._get_action(environment)
45 action = self.app._get_action(environment)
46 assert action == 'pull'
46 assert action == 'pull'
47
47
48 @pytest.mark.parametrize(
48 @pytest.mark.parametrize(
49 'method', [
49 'method', [
50 'MKACTIVITY', 'PROPPATCH', 'PUT', 'CHECKOUT', 'MKCOL', 'MOVE',
50 'MKACTIVITY', 'PROPPATCH', 'PUT', 'CHECKOUT', 'MKCOL', 'MOVE',
51 'COPY', 'DELETE', 'LOCK', 'UNLOCK', 'MERGE'
51 'COPY', 'DELETE', 'LOCK', 'UNLOCK', 'MERGE'
52 ])
52 ])
53 def test_get_action_returns_push(self, method):
53 def test_get_action_returns_push(self, method):
54 environment = {'REQUEST_METHOD': method}
54 environment = {'REQUEST_METHOD': method}
55 action = self.app._get_action(environment)
55 action = self.app._get_action(environment)
56 assert action == 'push'
56 assert action == 'push'
57
57
58 @pytest.mark.parametrize(
58 @pytest.mark.parametrize(
59 'path, expected_name', [
59 'path, expected_name', [
60 ('/hello-svn', 'hello-svn'),
60 ('/hello-svn', 'hello-svn'),
61 ('/hello-svn/', 'hello-svn'),
61 ('/hello-svn/', 'hello-svn'),
62 ('/group/hello-svn/', 'group/hello-svn'),
62 ('/group/hello-svn/', 'group/hello-svn'),
63 ('/group/hello-svn/!svn/vcc/default', 'group/hello-svn'),
63 ('/group/hello-svn/!svn/vcc/default', 'group/hello-svn'),
64 ])
64 ])
65 def test_get_repository_name(self, path, expected_name):
65 def test_get_repository_name(self, path, expected_name):
66 environment = {'PATH_INFO': path}
66 environment = {'PATH_INFO': path}
67 name = self.app._get_repository_name(environment)
67 name = self.app._get_repository_name(environment)
68 assert name == expected_name
68 assert name == expected_name
69
69
70 def test_get_repository_name_subfolder(self, backend_svn):
70 def test_get_repository_name_subfolder(self, backend_svn):
71 repo = backend_svn.repo
71 repo = backend_svn.repo
72 environment = {
72 environment = {
73 'PATH_INFO': '/{}/path/with/subfolders'.format(repo.repo_name)}
73 'PATH_INFO': '/{}/path/with/subfolders'.format(repo.repo_name)}
74 name = self.app._get_repository_name(environment)
74 name = self.app._get_repository_name(environment)
75 assert name == repo.repo_name
75 assert name == repo.repo_name
76
76
77 def test_create_wsgi_app(self):
77 def test_create_wsgi_app(self):
78 with patch.object(SimpleSvn, '_is_svn_enabled') as mock_method:
78 with patch.object(SimpleSvn, '_is_svn_enabled') as mock_method:
79 mock_method.return_value = False
79 mock_method.return_value = False
80 with patch('rhodecode.lib.middleware.simplesvn.DisabledSimpleSvnApp') as (
80 with patch('rhodecode.lib.middleware.simplesvn.DisabledSimpleSvnApp') as (
81 wsgi_app_mock):
81 wsgi_app_mock):
82 config = Mock()
82 config = Mock()
83 wsgi_app = self.app._create_wsgi_app(
83 wsgi_app = self.app._create_wsgi_app(
84 repo_path='', repo_name='', config=config)
84 repo_path='', repo_name='', config=config)
85
85
86 wsgi_app_mock.assert_called_once_with(config)
86 wsgi_app_mock.assert_called_once_with(config)
87 assert wsgi_app == wsgi_app_mock()
87 assert wsgi_app == wsgi_app_mock()
88
88
89 def test_create_wsgi_app_when_enabled(self):
89 def test_create_wsgi_app_when_enabled(self):
90 with patch.object(SimpleSvn, '_is_svn_enabled') as mock_method:
90 with patch.object(SimpleSvn, '_is_svn_enabled') as mock_method:
91 mock_method.return_value = True
91 mock_method.return_value = True
92 with patch('rhodecode.lib.middleware.simplesvn.SimpleSvnApp') as (
92 with patch('rhodecode.lib.middleware.simplesvn.SimpleSvnApp') as (
93 wsgi_app_mock):
93 wsgi_app_mock):
94 config = Mock()
94 config = Mock()
95 wsgi_app = self.app._create_wsgi_app(
95 wsgi_app = self.app._create_wsgi_app(
96 repo_path='', repo_name='', config=config)
96 repo_path='', repo_name='', config=config)
97
97
98 wsgi_app_mock.assert_called_once_with(config)
98 wsgi_app_mock.assert_called_once_with(config)
99 assert wsgi_app == wsgi_app_mock()
99 assert wsgi_app == wsgi_app_mock()
100
100
101
101
102 class TestSimpleSvnApp(object):
102 class TestSimpleSvnApp(object):
103 data = '<xml></xml>'
103 data = b'<xml></xml>'
104 path = '/group/my-repo'
104 path = '/group/my-repo'
105 wsgi_input = io.StringIO(data)
105 wsgi_input = io.BytesIO(data)
106 environment = {
106 environment = {
107 'HTTP_DAV': (
107 'HTTP_DAV': (
108 'http://subversion.tigris.org/xmlns/dav/svn/depth,'
108 'http://subversion.tigris.org/xmlns/dav/svn/depth,'
109 ' http://subversion.tigris.org/xmlns/dav/svn/mergeinfo'),
109 ' http://subversion.tigris.org/xmlns/dav/svn/mergeinfo'),
110 'HTTP_USER_AGENT': 'SVN/1.8.11 (x86_64-linux) serf/1.3.8',
110 'HTTP_USER_AGENT': 'SVN/1.8.11 (x86_64-linux) serf/1.3.8',
111 'REQUEST_METHOD': 'OPTIONS',
111 'REQUEST_METHOD': 'OPTIONS',
112 'PATH_INFO': path,
112 'PATH_INFO': path,
113 'wsgi.input': wsgi_input,
113 'wsgi.input': wsgi_input,
114 'CONTENT_TYPE': 'text/xml',
114 'CONTENT_TYPE': 'text/xml',
115 'CONTENT_LENGTH': '130'
115 'CONTENT_LENGTH': '130'
116 }
116 }
117
117
118 def setup_method(self, method):
118 def setup_method(self, method):
119 self.host = 'http://localhost/'
119 self.host = 'http://localhost/'
120 base_path = get_rhodecode_base_path()
120 base_path = get_rhodecode_base_path()
121 self.app = SimpleSvnApp(
121 self.app = SimpleSvnApp(
122 config={'subversion_http_server_url': self.host,
122 config={'subversion_http_server_url': self.host,
123 'base_path': base_path})
123 'base_path': base_path})
124
124
125 def test_get_request_headers_with_content_type(self):
125 def test_get_request_headers_with_content_type(self):
126 expected_headers = {
126 expected_headers = {
127 'Dav': self.environment['HTTP_DAV'],
127 'Dav': self.environment['HTTP_DAV'],
128 'User-Agent': self.environment['HTTP_USER_AGENT'],
128 'User-Agent': self.environment['HTTP_USER_AGENT'],
129 'Content-Type': self.environment['CONTENT_TYPE'],
129 'Content-Type': self.environment['CONTENT_TYPE'],
130 'Content-Length': self.environment['CONTENT_LENGTH']
130 'Content-Length': self.environment['CONTENT_LENGTH']
131 }
131 }
132 headers = self.app._get_request_headers(self.environment)
132 headers = self.app._get_request_headers(self.environment)
133 assert headers == expected_headers
133 assert headers == expected_headers
134
134
135 def test_get_request_headers_without_content_type(self):
135 def test_get_request_headers_without_content_type(self):
136 environment = self.environment.copy()
136 environment = self.environment.copy()
137 environment.pop('CONTENT_TYPE')
137 environment.pop('CONTENT_TYPE')
138 expected_headers = {
138 expected_headers = {
139 'Dav': environment['HTTP_DAV'],
139 'Dav': environment['HTTP_DAV'],
140 'Content-Length': self.environment['CONTENT_LENGTH'],
140 'Content-Length': self.environment['CONTENT_LENGTH'],
141 'User-Agent': environment['HTTP_USER_AGENT'],
141 'User-Agent': environment['HTTP_USER_AGENT'],
142 }
142 }
143 request_headers = self.app._get_request_headers(environment)
143 request_headers = self.app._get_request_headers(environment)
144 assert request_headers == expected_headers
144 assert request_headers == expected_headers
145
145
146 def test_get_response_headers(self):
146 def test_get_response_headers(self):
147 headers = {
147 headers = {
148 'Connection': 'keep-alive',
148 'Connection': 'keep-alive',
149 'Keep-Alive': 'timeout=5, max=100',
149 'Keep-Alive': 'timeout=5, max=100',
150 'Transfer-Encoding': 'chunked',
150 'Transfer-Encoding': 'chunked',
151 'Content-Encoding': 'gzip',
151 'Content-Encoding': 'gzip',
152 'MS-Author-Via': 'DAV',
152 'MS-Author-Via': 'DAV',
153 'SVN-Supported-Posts': 'create-txn-with-props'
153 'SVN-Supported-Posts': 'create-txn-with-props'
154 }
154 }
155 expected_headers = [
155 expected_headers = [
156 ('MS-Author-Via', 'DAV'),
156 ('MS-Author-Via', 'DAV'),
157 ('SVN-Supported-Posts', 'create-txn-with-props'),
157 ('SVN-Supported-Posts', 'create-txn-with-props'),
158 ]
158 ]
159 response_headers = self.app._get_response_headers(headers)
159 response_headers = self.app._get_response_headers(headers)
160 assert sorted(response_headers) == sorted(expected_headers)
160 assert sorted(response_headers) == sorted(expected_headers)
161
161
162 @pytest.mark.parametrize('svn_http_url, path_info, expected_url', [
162 @pytest.mark.parametrize('svn_http_url, path_info, expected_url', [
163 ('http://localhost:8200', '/repo_name', 'http://localhost:8200/repo_name'),
163 ('http://localhost:8200', '/repo_name', 'http://localhost:8200/repo_name'),
164 ('http://localhost:8200///', '/repo_name', 'http://localhost:8200/repo_name'),
164 ('http://localhost:8200///', '/repo_name', 'http://localhost:8200/repo_name'),
165 ('http://localhost:8200', '/group/repo_name', 'http://localhost:8200/group/repo_name'),
165 ('http://localhost:8200', '/group/repo_name', 'http://localhost:8200/group/repo_name'),
166 ('http://localhost:8200/', '/group/repo_name', 'http://localhost:8200/group/repo_name'),
166 ('http://localhost:8200/', '/group/repo_name', 'http://localhost:8200/group/repo_name'),
167 ('http://localhost:8200/prefix', '/repo_name', 'http://localhost:8200/prefix/repo_name'),
167 ('http://localhost:8200/prefix', '/repo_name', 'http://localhost:8200/prefix/repo_name'),
168 ('http://localhost:8200/prefix', 'repo_name', 'http://localhost:8200/prefix/repo_name'),
168 ('http://localhost:8200/prefix', 'repo_name', 'http://localhost:8200/prefix/repo_name'),
169 ('http://localhost:8200/prefix', '/group/repo_name', 'http://localhost:8200/prefix/group/repo_name')
169 ('http://localhost:8200/prefix', '/group/repo_name', 'http://localhost:8200/prefix/group/repo_name')
170 ])
170 ])
171 def test_get_url(self, svn_http_url, path_info, expected_url):
171 def test_get_url(self, svn_http_url, path_info, expected_url):
172 url = self.app._get_url(svn_http_url, path_info)
172 url = self.app._get_url(svn_http_url, path_info)
173 assert url == expected_url
173 assert url == expected_url
174
174
175 def test_call(self):
175 def test_call(self):
176 start_response = Mock()
176 start_response = Mock()
177 response_mock = Mock()
177 response_mock = Mock()
178 response_mock.headers = {
178 response_mock.headers = {
179 'Content-Encoding': 'gzip',
179 'Content-Encoding': 'gzip',
180 'MS-Author-Via': 'DAV',
180 'MS-Author-Via': 'DAV',
181 'SVN-Supported-Posts': 'create-txn-with-props'
181 'SVN-Supported-Posts': 'create-txn-with-props'
182 }
182 }
183 response_mock.status_code = 200
183 response_mock.status_code = 200
184 response_mock.reason = 'OK'
184 response_mock.reason = 'OK'
185 with patch('rhodecode.lib.middleware.simplesvn.requests.request') as (
185 with patch('rhodecode.lib.middleware.simplesvn.requests.request') as (
186 request_mock):
186 request_mock):
187 request_mock.return_value = response_mock
187 request_mock.return_value = response_mock
188 self.app(self.environment, start_response)
188 self.app(self.environment, start_response)
189
189
190 expected_url = '{}{}'.format(self.host.strip('/'), self.path)
190 expected_url = f'{self.host.strip("/")}{self.path}'
191 expected_request_headers = {
191 expected_request_headers = {
192 'Dav': self.environment['HTTP_DAV'],
192 'Dav': self.environment['HTTP_DAV'],
193 'User-Agent': self.environment['HTTP_USER_AGENT'],
193 'User-Agent': self.environment['HTTP_USER_AGENT'],
194 'Content-Type': self.environment['CONTENT_TYPE'],
194 'Content-Type': self.environment['CONTENT_TYPE'],
195 'Content-Length': self.environment['CONTENT_LENGTH']
195 'Content-Length': self.environment['CONTENT_LENGTH']
196 }
196 }
197 expected_response_headers = [
197 expected_response_headers = [
198 ('SVN-Supported-Posts', 'create-txn-with-props'),
198 ('SVN-Supported-Posts', 'create-txn-with-props'),
199 ('MS-Author-Via', 'DAV'),
199 ('MS-Author-Via', 'DAV'),
200 ]
200 ]
201 request_mock.assert_called_once_with(
201 request_mock.assert_called_once_with(
202 self.environment['REQUEST_METHOD'], expected_url,
202 self.environment['REQUEST_METHOD'], expected_url,
203 data=self.data, headers=expected_request_headers, stream=False)
203 data=self.data, headers=expected_request_headers, stream=False)
204 response_mock.iter_content.assert_called_once_with(chunk_size=1024)
204 response_mock.iter_content.assert_called_once_with(chunk_size=1024)
205 args, _ = start_response.call_args
205 args, _ = start_response.call_args
206 assert args[0] == '200 OK'
206 assert args[0] == '200 OK'
207 assert sorted(args[1]) == sorted(expected_response_headers)
207 assert sorted(args[1]) == sorted(expected_response_headers)
General Comments 0
You need to be logged in to leave comments. Login now