##// END OF EJS Templates
tests: reduced memory footprint on subprocession tests....
ergo -
r638:be949416 default
parent child Browse files
Show More
@@ -1,132 +1,155 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2019 RhodeCode GmbH
2 # Copyright (C) 2014-2019 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 General Public License as published by
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 import io
18 import io
19 import os
19 import os
20 import sys
20 import sys
21
21
22 import pytest
22 import pytest
23
23
24 from vcsserver import subprocessio
24 from vcsserver import subprocessio
25
25
26
26
27 class KindaFilelike(object): # pragma: no cover
28
29 def __init__(self, data, size):
30 chunks = size / len(data)
31
32 self.stream = self._get_stream(data, chunks)
33
34 def _get_stream(self, data, chunks):
35 for x in xrange(chunks):
36 yield data
37
38 def read(self, n):
39
40 buffer_stream = ''
41 for chunk in self.stream:
42 buffer_stream += chunk
43 if len(buffer_stream) >= n:
44 break
45
46 # self.stream = self.bytes[n:]
47 return buffer_stream
48
49
27 @pytest.fixture(scope='module')
50 @pytest.fixture(scope='module')
28 def environ():
51 def environ():
29 """Delete coverage variables, as they make the tests fail."""
52 """Delete coverage variables, as they make the tests fail."""
30 env = dict(os.environ)
53 env = dict(os.environ)
31 for key in env.keys():
54 for key in env.keys():
32 if key.startswith('COV_CORE_'):
55 if key.startswith('COV_CORE_'):
33 del env[key]
56 del env[key]
34
57
35 return env
58 return env
36
59
37
60
38 def _get_python_args(script):
61 def _get_python_args(script):
39 return [sys.executable, '-c', 'import sys; import time; import shutil; ' + script]
62 return [sys.executable, '-c', 'import sys; import time; import shutil; ' + script]
40
63
41
64
42 def test_raise_exception_on_non_zero_return_code(environ):
65 def test_raise_exception_on_non_zero_return_code(environ):
43 args = _get_python_args('sys.exit(1)')
66 args = _get_python_args('sys.exit(1)')
44 with pytest.raises(EnvironmentError):
67 with pytest.raises(EnvironmentError):
45 list(subprocessio.SubprocessIOChunker(args, shell=False, env=environ))
68 list(subprocessio.SubprocessIOChunker(args, shell=False, env=environ))
46
69
47
70
48 def test_does_not_fail_on_non_zero_return_code(environ):
71 def test_does_not_fail_on_non_zero_return_code(environ):
49 args = _get_python_args('sys.exit(1)')
72 args = _get_python_args('sys.exit(1)')
50 output = ''.join(
73 output = ''.join(
51 subprocessio.SubprocessIOChunker(
74 subprocessio.SubprocessIOChunker(
52 args, shell=False, fail_on_return_code=False, env=environ
75 args, shell=False, fail_on_return_code=False, env=environ
53 )
76 )
54 )
77 )
55
78
56 assert output == ''
79 assert output == ''
57
80
58
81
59 def test_raise_exception_on_stderr(environ):
82 def test_raise_exception_on_stderr(environ):
60 args = _get_python_args('sys.stderr.write("X"); time.sleep(1);')
83 args = _get_python_args('sys.stderr.write("X"); time.sleep(1);')
61 with pytest.raises(EnvironmentError) as excinfo:
84 with pytest.raises(EnvironmentError) as excinfo:
62 list(subprocessio.SubprocessIOChunker(args, shell=False, env=environ))
85 list(subprocessio.SubprocessIOChunker(args, shell=False, env=environ))
63
86
64 assert 'exited due to an error:\nX' in str(excinfo.value)
87 assert 'exited due to an error:\nX' in str(excinfo.value)
65
88
66
89
67 def test_does_not_fail_on_stderr(environ):
90 def test_does_not_fail_on_stderr(environ):
68 args = _get_python_args('sys.stderr.write("X"); time.sleep(1);')
91 args = _get_python_args('sys.stderr.write("X"); time.sleep(1);')
69 output = ''.join(
92 output = ''.join(
70 subprocessio.SubprocessIOChunker(
93 subprocessio.SubprocessIOChunker(
71 args, shell=False, fail_on_stderr=False, env=environ
94 args, shell=False, fail_on_stderr=False, env=environ
72 )
95 )
73 )
96 )
74
97
75 assert output == ''
98 assert output == ''
76
99
77
100
78 @pytest.mark.parametrize('size', [1, 10 ** 5])
101 @pytest.mark.parametrize('size', [1, 10 ** 5])
79 def test_output_with_no_input(size, environ):
102 def test_output_with_no_input(size, environ):
80 print(type(environ))
103 print(type(environ))
81 data = 'X'
104 data = 'X'
82 args = _get_python_args('sys.stdout.write("%s" * %d)' % (data, size))
105 args = _get_python_args('sys.stdout.write("%s" * %d)' % (data, size))
83 output = ''.join(subprocessio.SubprocessIOChunker(args, shell=False, env=environ))
106 output = ''.join(subprocessio.SubprocessIOChunker(args, shell=False, env=environ))
84
107
85 assert output == data * size
108 assert output == data * size
86
109
87
110
88 @pytest.mark.parametrize('size', [1, 10 ** 5])
111 @pytest.mark.parametrize('size', [1, 10 ** 5])
89 def test_output_with_no_input_does_not_fail(size, environ):
112 def test_output_with_no_input_does_not_fail(size, environ):
90 data = 'X'
113 data = 'X'
91 args = _get_python_args('sys.stdout.write("%s" * %d); sys.exit(1)' % (data, size))
114 args = _get_python_args('sys.stdout.write("%s" * %d); sys.exit(1)' % (data, size))
92 output = ''.join(
115 output = ''.join(
93 subprocessio.SubprocessIOChunker(
116 subprocessio.SubprocessIOChunker(
94 args, shell=False, fail_on_return_code=False, env=environ
117 args, shell=False, fail_on_return_code=False, env=environ
95 )
118 )
96 )
119 )
97
120
98 print("{} {}".format(len(data * size), len(output)))
121 print("{} {}".format(len(data * size), len(output)))
99 assert output == data * size
122 assert output == data * size
100
123
101
124
102 @pytest.mark.parametrize('size', [1, 10 ** 5])
125 @pytest.mark.parametrize('size', [1, 10 ** 5])
103 def test_output_with_input(size, environ):
126 def test_output_with_input(size, environ):
104 data = 'X' * size
127 data_len = size
105 inputstream = io.BytesIO(data)
128 inputstream = KindaFilelike('X', size)
129
106 # This acts like the cat command.
130 # This acts like the cat command.
107 args = _get_python_args('shutil.copyfileobj(sys.stdin, sys.stdout)')
131 args = _get_python_args('shutil.copyfileobj(sys.stdin, sys.stdout)')
108 output = ''.join(
132 output = ''.join(
109 subprocessio.SubprocessIOChunker(
133 subprocessio.SubprocessIOChunker(
110 args, shell=False, inputstream=inputstream, env=environ
134 args, shell=False, inputstream=inputstream, env=environ
111 )
135 )
112 )
136 )
113
137
114 print("{} {}".format(len(data * size), len(output)))
138 assert len(output) == data_len
115 assert output == data
116
139
117
140
118 @pytest.mark.parametrize('size', [1, 10 ** 5])
141 @pytest.mark.parametrize('size', [1, 10 ** 5])
119 def test_output_with_input_skipping_iterator(size, environ):
142 def test_output_with_input_skipping_iterator(size, environ):
120 data = 'X' * size
143 data_len = size
121 inputstream = io.BytesIO(data)
144 inputstream = KindaFilelike('X', size)
145
122 # This acts like the cat command.
146 # This acts like the cat command.
123 args = _get_python_args('shutil.copyfileobj(sys.stdin, sys.stdout)')
147 args = _get_python_args('shutil.copyfileobj(sys.stdin, sys.stdout)')
124
148
125 # Note: assigning the chunker makes sure that it is not deleted too early
149 # Note: assigning the chunker makes sure that it is not deleted too early
126 chunker = subprocessio.SubprocessIOChunker(
150 chunker = subprocessio.SubprocessIOChunker(
127 args, shell=False, inputstream=inputstream, env=environ
151 args, shell=False, inputstream=inputstream, env=environ
128 )
152 )
129 output = ''.join(chunker.output)
153 output = ''.join(chunker.output)
130
154
131 print("{} {}".format(len(data * size), len(output)))
155 assert len(output) == data_len
132 assert output == data
General Comments 0
You need to be logged in to leave comments. Login now