Skip to content

Commit cd0facf

Browse files
committed
WIP: test_process: Add tests for process
Although some of the properties are underspecified (links from the docstrings). Signed-off-by: W. Trevor King <wking@tremily.us>
1 parent fc67675 commit cd0facf

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed

test/test_process.py

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# Copyright 2016 W. Trevor King <wking@tremily.us>
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os.path
16+
import re
17+
import unittest
18+
19+
from . import util
20+
21+
22+
class TestProcess(unittest.TestCase):
23+
ENVIRONMENT_VARIABLE_KEY_INVALID_REGEX = re.compile('[^a-zA-Z0-9_]')
24+
25+
@util.skip_if_unrecognized_version
26+
def test_process(self):
27+
"""process (object, required).
28+
29+
This is currently underspecified [1,2], but I expect it to be
30+
required [3].
31+
32+
[1]: https://github.com/opencontainers/runtime-spec/blob/v1.0.0-rc1/config.md#process-configuration
33+
[2]: https://github.com/opencontainers/runtime-spec/blob/v0.5.0/config.md#process-configuration
34+
[3]: https://github.com/opencontainers/runtime-spec/pull/489
35+
"""
36+
self.assertIn(
37+
'process', sorted(util.CONFIG_JSON.keys()),
38+
'process is not set')
39+
process = util.CONFIG_JSON['process']
40+
self.assertTrue(isinstance(process, dict), 'process is not an object')
41+
42+
@util.skip_if_unrecognized_version
43+
@unittest.skipUnless(
44+
isinstance(util.CONFIG_JSON.get('process'), dict),
45+
'cannot validate process.terminal without a process object')
46+
def test_terminal(self):
47+
"""terminal (bool, optional).
48+
49+
[1]: https://github.com/opencontainers/runtime-spec/blob/v1.0.0-rc1/config.md#process-configuration
50+
[2]: https://github.com/opencontainers/runtime-spec/blob/v0.5.0/config.md#process-configuration
51+
"""
52+
process = util.CONFIG_JSON['process']
53+
if 'terminal' in process:
54+
terminal = process['terminal']
55+
self.assertIn(
56+
terminal, [True, False], 'process.terminal is not a boolean')
57+
58+
@util.skip_if_unrecognized_version
59+
@unittest.skipUnless(
60+
isinstance(util.CONFIG_JSON.get('process'), dict),
61+
'cannot validate process.cwd without a process object')
62+
@util.skip_unless_path_separator_matches
63+
def test_cwd(self):
64+
"""cwd (string, required).
65+
66+
From the spec [1,2]:
67+
68+
This value MUST be an absolute path.
69+
70+
[1]: https://github.com/opencontainers/runtime-spec/blob/v1.0.0-rc1/config.md#process-configuration
71+
[2]: https://github.com/opencontainers/runtime-spec/blob/v0.5.0/config.md#process-configuration
72+
"""
73+
process = util.CONFIG_JSON['process']
74+
self.assertIn('cwd', sorted(process.keys()), 'process.cwd is not set')
75+
cwd = process['cwd']
76+
self.assertTrue(
77+
os.path.isabs(cwd), 'process.cwd MUST be an absolute path')
78+
79+
@util.skip_if_unrecognized_version
80+
@unittest.skipUnless(
81+
isinstance(util.CONFIG_JSON.get('process'), dict),
82+
'cannot validate process.env without a process object')
83+
def test_env(self):
84+
"""env (array of strings, optional).
85+
86+
From the spec [1,2]:
87+
88+
Elements in the array are specified as Strings in the form
89+
"KEY=value". The left hand side must consist solely of
90+
letters, digits, and underscores _ as outlined in IEEE Std
91+
1003.1-2001.
92+
93+
I'd rather punt to POSIX [3] (which is less strict), but the
94+
pull request for that is still in flight.
95+
96+
[1]: https://github.com/opencontainers/runtime-spec/blob/v1.0.0-rc1/config.md#process-configuration
97+
[2]: https://github.com/opencontainers/runtime-spec/blob/v0.5.0/config.md#process-configuration
98+
[3]: https://github.com/opencontainers/runtime-spec/pull/427#issuecomment-220530504
99+
"""
100+
process = util.CONFIG_JSON['process']
101+
if 'env' in process:
102+
env = process['env']
103+
self.assertTrue(
104+
isinstance(env, list), 'process.env is not an array')
105+
for i, env_var in enumerate(env):
106+
with self.subTest(i=i, environment_variable=env_var):
107+
self.assertTrue(
108+
isinstance(env_var, str),
109+
'process.env[{}] ({}) is not a string'
110+
.format(i, env_var))
111+
# the only POSIX requirement is an equals sign
112+
self.assertTrue(
113+
'=' in env_var,
114+
'process.env[{}] ({}) does not contain an equals sign'
115+
.format(i, env_var))
116+
# additional restrictions from the OCI spec
117+
key = env_var.split('=', 1)[0]
118+
match = self.ENVIRONMENT_VARIABLE_KEY_INVALID_REGEX.search(
119+
key)
120+
if match:
121+
invalid_character = match.group(0)
122+
raise self.failureException(
123+
"process.env[{}]'s key ({}) contains an invalid "
124+
'character: {!r}'
125+
.format(i, key, invalid_character))
126+
127+
@util.skip_if_unrecognized_version
128+
@unittest.skipUnless(
129+
isinstance(util.CONFIG_JSON.get('process'), dict),
130+
'cannot validate process.args without a process object')
131+
def test_args(self):
132+
"""args (array of strings, required).
133+
134+
From the spec [1,2]:
135+
136+
The executable is the first element and MUST be available at
137+
the given path inside of the rootfs. If the executable path
138+
is not an absolute path then the search $PATH is interpreted
139+
to find the executable.
140+
141+
v0.5.0 used 'must' instead of 'MUST', but that was accidental
142+
[3].
143+
144+
I don't see how "MUST be available at the given path" squares
145+
with "If the executable path is not an absolute path then
146+
search $PATH". And that's not how execvp works anyway (it
147+
walks PATH only if there *no* separators in the the file [4]).
148+
I expect we want to punt all of this to POSIX [5], so for now
149+
I only check that args is an array of strings with at least
150+
one element.
151+
152+
[1]: https://github.com/opencontainers/runtime-spec/blob/v1.0.0-rc1/config.md#process-configuration
153+
[2]: https://github.com/opencontainers/runtime-spec/blob/v0.5.0/config.md#process-configuration
154+
[3]: https://github.com/opencontainers/runtime-spec/pull/438
155+
[4]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/execvp.html
156+
[5]: https://github.com/opencontainers/runtime-spec/pull/427#issuecomment-220530504
157+
"""
158+
process = util.CONFIG_JSON['process']
159+
self.assertIn(
160+
'args', sorted(process.keys()), 'process.args is not set')
161+
args = process['args']
162+
self.assertTrue(isinstance(args, list), 'process.args is not an array')
163+
self.assertTrue(
164+
len(args) > 0, 'process.args must have at least one element')
165+
for i, arg in enumerate(args):
166+
with self.subTest(i=i, argument=arg):
167+
self.assertTrue(
168+
isinstance(arg, str),
169+
'process.args[{}] ({}) is not a string'.format(i, arg))

0 commit comments

Comments
 (0)