teuthology 1.1.0__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scripts/describe.py +1 -0
- scripts/dispatcher.py +55 -26
- scripts/exporter.py +18 -0
- scripts/lock.py +1 -1
- scripts/node_cleanup.py +58 -0
- scripts/openstack.py +9 -9
- scripts/results.py +12 -11
- scripts/schedule.py +4 -0
- scripts/suite.py +57 -16
- scripts/supervisor.py +44 -0
- scripts/update_inventory.py +10 -4
- teuthology/__init__.py +24 -26
- teuthology/beanstalk.py +4 -3
- teuthology/config.py +16 -6
- teuthology/contextutil.py +18 -14
- teuthology/describe_tests.py +25 -18
- teuthology/dispatcher/__init__.py +210 -35
- teuthology/dispatcher/supervisor.py +140 -58
- teuthology/exceptions.py +43 -0
- teuthology/exporter.py +347 -0
- teuthology/kill.py +76 -81
- teuthology/lock/cli.py +3 -3
- teuthology/lock/ops.py +135 -61
- teuthology/lock/query.py +61 -44
- teuthology/ls.py +1 -1
- teuthology/misc.py +61 -75
- teuthology/nuke/__init__.py +12 -353
- teuthology/openstack/__init__.py +4 -3
- teuthology/openstack/openstack-centos-7.0-user-data.txt +1 -1
- teuthology/openstack/openstack-centos-7.1-user-data.txt +1 -1
- teuthology/openstack/openstack-centos-7.2-user-data.txt +1 -1
- teuthology/openstack/openstack-debian-8.0-user-data.txt +1 -1
- teuthology/openstack/openstack-opensuse-42.1-user-data.txt +1 -1
- teuthology/openstack/openstack-teuthology.cron +0 -1
- teuthology/orchestra/cluster.py +49 -7
- teuthology/orchestra/connection.py +16 -5
- teuthology/orchestra/console.py +111 -50
- teuthology/orchestra/daemon/cephadmunit.py +17 -4
- teuthology/orchestra/daemon/state.py +8 -1
- teuthology/orchestra/daemon/systemd.py +4 -4
- teuthology/orchestra/opsys.py +30 -11
- teuthology/orchestra/remote.py +405 -338
- teuthology/orchestra/run.py +3 -3
- teuthology/packaging.py +19 -16
- teuthology/provision/__init__.py +30 -10
- teuthology/provision/cloud/openstack.py +12 -6
- teuthology/provision/cloud/util.py +1 -2
- teuthology/provision/downburst.py +4 -3
- teuthology/provision/fog.py +68 -20
- teuthology/provision/openstack.py +5 -4
- teuthology/provision/pelagos.py +1 -1
- teuthology/repo_utils.py +43 -13
- teuthology/report.py +57 -35
- teuthology/results.py +5 -3
- teuthology/run.py +13 -14
- teuthology/run_tasks.py +27 -43
- teuthology/schedule.py +4 -3
- teuthology/scrape.py +28 -22
- teuthology/suite/__init__.py +74 -45
- teuthology/suite/build_matrix.py +34 -24
- teuthology/suite/fragment-merge.lua +105 -0
- teuthology/suite/matrix.py +31 -2
- teuthology/suite/merge.py +175 -0
- teuthology/suite/placeholder.py +6 -9
- teuthology/suite/run.py +175 -100
- teuthology/suite/util.py +64 -218
- teuthology/task/__init__.py +1 -1
- teuthology/task/ansible.py +101 -32
- teuthology/task/buildpackages.py +2 -2
- teuthology/task/ceph_ansible.py +13 -6
- teuthology/task/cephmetrics.py +2 -1
- teuthology/task/clock.py +33 -14
- teuthology/task/exec.py +18 -0
- teuthology/task/hadoop.py +2 -2
- teuthology/task/install/__init__.py +29 -7
- teuthology/task/install/bin/adjust-ulimits +16 -0
- teuthology/task/install/bin/daemon-helper +114 -0
- teuthology/task/install/bin/stdin-killer +263 -0
- teuthology/task/install/deb.py +1 -1
- teuthology/task/install/rpm.py +17 -5
- teuthology/task/install/util.py +3 -3
- teuthology/task/internal/__init__.py +41 -10
- teuthology/task/internal/edit_sudoers.sh +10 -0
- teuthology/task/internal/lock_machines.py +2 -9
- teuthology/task/internal/redhat.py +31 -1
- teuthology/task/internal/syslog.py +31 -8
- teuthology/task/kernel.py +152 -145
- teuthology/task/lockfile.py +1 -1
- teuthology/task/mpi.py +10 -10
- teuthology/task/pcp.py +1 -1
- teuthology/task/selinux.py +16 -8
- teuthology/task/ssh_keys.py +4 -4
- teuthology/task/tests/__init__.py +137 -77
- teuthology/task/tests/test_fetch_coredumps.py +116 -0
- teuthology/task/tests/test_run.py +4 -4
- teuthology/timer.py +3 -3
- teuthology/util/loggerfile.py +19 -0
- teuthology/util/scanner.py +159 -0
- teuthology/util/sentry.py +52 -0
- teuthology/util/time.py +52 -0
- teuthology-1.2.0.data/scripts/adjust-ulimits +16 -0
- teuthology-1.2.0.data/scripts/daemon-helper +114 -0
- teuthology-1.2.0.data/scripts/stdin-killer +263 -0
- teuthology-1.2.0.dist-info/METADATA +89 -0
- teuthology-1.2.0.dist-info/RECORD +174 -0
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/WHEEL +1 -1
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/entry_points.txt +3 -2
- scripts/nuke.py +0 -47
- scripts/worker.py +0 -37
- teuthology/nuke/actions.py +0 -456
- teuthology/openstack/test/__init__.py +0 -0
- teuthology/openstack/test/openstack-integration.py +0 -286
- teuthology/openstack/test/test_config.py +0 -35
- teuthology/openstack/test/test_openstack.py +0 -1695
- teuthology/orchestra/test/__init__.py +0 -0
- teuthology/orchestra/test/integration/__init__.py +0 -0
- teuthology/orchestra/test/integration/test_integration.py +0 -94
- teuthology/orchestra/test/test_cluster.py +0 -240
- teuthology/orchestra/test/test_connection.py +0 -106
- teuthology/orchestra/test/test_console.py +0 -217
- teuthology/orchestra/test/test_opsys.py +0 -404
- teuthology/orchestra/test/test_remote.py +0 -185
- teuthology/orchestra/test/test_run.py +0 -286
- teuthology/orchestra/test/test_systemd.py +0 -54
- teuthology/orchestra/test/util.py +0 -12
- teuthology/test/__init__.py +0 -0
- teuthology/test/fake_archive.py +0 -107
- teuthology/test/fake_fs.py +0 -92
- teuthology/test/integration/__init__.py +0 -0
- teuthology/test/integration/test_suite.py +0 -86
- teuthology/test/task/__init__.py +0 -205
- teuthology/test/task/test_ansible.py +0 -624
- teuthology/test/task/test_ceph_ansible.py +0 -176
- teuthology/test/task/test_console_log.py +0 -88
- teuthology/test/task/test_install.py +0 -337
- teuthology/test/task/test_internal.py +0 -57
- teuthology/test/task/test_kernel.py +0 -243
- teuthology/test/task/test_pcp.py +0 -379
- teuthology/test/task/test_selinux.py +0 -35
- teuthology/test/test_config.py +0 -189
- teuthology/test/test_contextutil.py +0 -68
- teuthology/test/test_describe_tests.py +0 -316
- teuthology/test/test_email_sleep_before_teardown.py +0 -81
- teuthology/test/test_exit.py +0 -97
- teuthology/test/test_get_distro.py +0 -47
- teuthology/test/test_get_distro_version.py +0 -47
- teuthology/test/test_get_multi_machine_types.py +0 -27
- teuthology/test/test_job_status.py +0 -60
- teuthology/test/test_ls.py +0 -48
- teuthology/test/test_misc.py +0 -391
- teuthology/test/test_nuke.py +0 -290
- teuthology/test/test_packaging.py +0 -763
- teuthology/test/test_parallel.py +0 -28
- teuthology/test/test_repo_utils.py +0 -225
- teuthology/test/test_report.py +0 -77
- teuthology/test/test_results.py +0 -155
- teuthology/test/test_run.py +0 -239
- teuthology/test/test_safepath.py +0 -55
- teuthology/test/test_schedule.py +0 -45
- teuthology/test/test_scrape.py +0 -167
- teuthology/test/test_timer.py +0 -80
- teuthology/test/test_vps_os_vers_parameter_checking.py +0 -84
- teuthology/test/test_worker.py +0 -303
- teuthology/worker.py +0 -354
- teuthology-1.1.0.dist-info/METADATA +0 -76
- teuthology-1.1.0.dist-info/RECORD +0 -213
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/LICENSE +0 -0
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/top_level.txt +0 -0
teuthology/test/test_run.py
DELETED
@@ -1,239 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
import docopt
|
3
|
-
|
4
|
-
from unittest.mock import patch, call, Mock
|
5
|
-
|
6
|
-
from teuthology import run
|
7
|
-
from scripts import run as scripts_run
|
8
|
-
|
9
|
-
|
10
|
-
class TestRun(object):
|
11
|
-
""" Tests for teuthology.run """
|
12
|
-
|
13
|
-
@patch("teuthology.log.setLevel")
|
14
|
-
@patch("teuthology.setup_log_file")
|
15
|
-
@patch("os.mkdir")
|
16
|
-
def test_set_up_logging(self, m_mkdir, m_setup_log_file, m_setLevel):
|
17
|
-
run.set_up_logging(True, "path/to/archive")
|
18
|
-
m_mkdir.assert_called_with("path/to/archive")
|
19
|
-
m_setup_log_file.assert_called_with("path/to/archive/teuthology.log")
|
20
|
-
assert m_setLevel.called
|
21
|
-
|
22
|
-
# because of how we import things, mock merge_configs from run - where it's used
|
23
|
-
# see: http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch
|
24
|
-
@patch("teuthology.run.merge_configs")
|
25
|
-
def test_setup_config(self, m_merge_configs):
|
26
|
-
config = {"job_id": 1, "foo": "bar"}
|
27
|
-
m_merge_configs.return_value = config
|
28
|
-
result = run.setup_config(["some/config.yaml"])
|
29
|
-
assert m_merge_configs.called
|
30
|
-
assert result["job_id"] == "1"
|
31
|
-
assert result["foo"] == "bar"
|
32
|
-
|
33
|
-
@patch("teuthology.run.merge_configs")
|
34
|
-
def test_setup_config_targets_ok(self, m_merge_configs):
|
35
|
-
config = {"targets": list(range(4)), "roles": list(range(2))}
|
36
|
-
m_merge_configs.return_value = config
|
37
|
-
result = run.setup_config(["some/config.yaml"])
|
38
|
-
assert result["targets"] == [0, 1, 2, 3]
|
39
|
-
assert result["roles"] == [0, 1]
|
40
|
-
|
41
|
-
@patch("teuthology.run.merge_configs")
|
42
|
-
def test_setup_config_targets_invalid(self, m_merge_configs):
|
43
|
-
config = {"targets": range(2), "roles": range(4)}
|
44
|
-
m_merge_configs.return_value = config
|
45
|
-
with pytest.raises(AssertionError):
|
46
|
-
run.setup_config(["some/config.yaml"])
|
47
|
-
|
48
|
-
@patch("teuthology.run.open")
|
49
|
-
def test_write_initial_metadata(self, m_open):
|
50
|
-
config = {"job_id": "123", "foo": "bar"}
|
51
|
-
run.write_initial_metadata(
|
52
|
-
"some/archive/dir",
|
53
|
-
config,
|
54
|
-
"the_name",
|
55
|
-
"the_description",
|
56
|
-
"the_owner",
|
57
|
-
)
|
58
|
-
expected = [
|
59
|
-
call('some/archive/dir/pid', 'w'),
|
60
|
-
call('some/archive/dir/owner', 'w'),
|
61
|
-
call('some/archive/dir/orig.config.yaml', 'w'),
|
62
|
-
call('some/archive/dir/info.yaml', 'w')
|
63
|
-
]
|
64
|
-
assert m_open.call_args_list == expected
|
65
|
-
|
66
|
-
def test_get_machine_type(self):
|
67
|
-
result = run.get_machine_type(None, {"machine-type": "the_machine_type"})
|
68
|
-
assert result == "the_machine_type"
|
69
|
-
|
70
|
-
def test_get_summary(self):
|
71
|
-
result = run.get_summary("the_owner", "the_description")
|
72
|
-
assert result == {"owner": "the_owner", "description": "the_description", "success": True}
|
73
|
-
result = run.get_summary("the_owner", None)
|
74
|
-
assert result == {"owner": "the_owner", "success": True}
|
75
|
-
|
76
|
-
def test_validate_tasks_invalid(self):
|
77
|
-
config = {"tasks": [{"kernel": "can't be here"}]}
|
78
|
-
with pytest.raises(AssertionError) as excinfo:
|
79
|
-
run.validate_tasks(config)
|
80
|
-
assert excinfo.value.args[0].startswith("kernel installation")
|
81
|
-
|
82
|
-
def test_validate_task_no_tasks(self):
|
83
|
-
result = run.validate_tasks({})
|
84
|
-
assert result == []
|
85
|
-
|
86
|
-
def test_validate_tasks_valid(self):
|
87
|
-
expected = [{"foo": "bar"}, {"bar": "foo"}]
|
88
|
-
result = run.validate_tasks({"tasks": expected})
|
89
|
-
assert result == expected
|
90
|
-
|
91
|
-
def test_validate_tasks_is_list(self):
|
92
|
-
with pytest.raises(AssertionError) as excinfo:
|
93
|
-
run.validate_tasks({"tasks": {"foo": "bar"}})
|
94
|
-
assert excinfo.value.args[0].startswith("Expected list")
|
95
|
-
|
96
|
-
def test_get_initial_tasks_invalid(self):
|
97
|
-
with pytest.raises(AssertionError) as excinfo:
|
98
|
-
run.get_initial_tasks(True, {"targets": "can't be here",
|
99
|
-
"roles": "roles" }, "machine_type")
|
100
|
-
assert excinfo.value.args[0].startswith("You cannot")
|
101
|
-
|
102
|
-
def test_get_inital_tasks(self):
|
103
|
-
config = {"roles": range(2), "kernel": "the_kernel", "use_existing_cluster": False}
|
104
|
-
result = run.get_initial_tasks(True, config, "machine_type")
|
105
|
-
assert {"internal.lock_machines": (2, "machine_type")} in result
|
106
|
-
assert {"kernel": "the_kernel"} in result
|
107
|
-
# added because use_existing_cluster == False
|
108
|
-
assert {'internal.vm_setup': None} in result
|
109
|
-
assert {'internal.buildpackages_prep': None} in result
|
110
|
-
|
111
|
-
@patch("teuthology.run.fetch_qa_suite")
|
112
|
-
def test_fetch_tasks_if_needed(self, m_fetch_qa_suite):
|
113
|
-
config = {"suite_path": "/some/suite/path", "suite_branch": "feature_branch",
|
114
|
-
"suite_sha1": "commit"}
|
115
|
-
m_fetch_qa_suite.return_value = "/some/other/suite/path"
|
116
|
-
result = run.fetch_tasks_if_needed(config)
|
117
|
-
m_fetch_qa_suite.assert_called_with("feature_branch", commit="commit")
|
118
|
-
assert result == "/some/other/suite/path"
|
119
|
-
|
120
|
-
@patch("teuthology.run.get_status")
|
121
|
-
@patch("teuthology.run.nuke")
|
122
|
-
@patch("yaml.safe_dump")
|
123
|
-
@patch("teuthology.report.try_push_job_info")
|
124
|
-
@patch("teuthology.run.email_results")
|
125
|
-
@patch("teuthology.run.open")
|
126
|
-
@patch("sys.exit")
|
127
|
-
def test_report_outcome(self, m_sys_exit, m_open, m_email_results, m_try_push_job_info, m_safe_dump, m_nuke, m_get_status):
|
128
|
-
m_get_status.return_value = "fail"
|
129
|
-
fake_ctx = Mock()
|
130
|
-
summary = {"failure_reason": "reasons"}
|
131
|
-
summary_dump = "failure_reason: reasons\n"
|
132
|
-
config = {"nuke-on-error": True, "email-on-error": True}
|
133
|
-
config_dump = "nuke-on-error: true\nemail-on-error: true\n"
|
134
|
-
m_safe_dump.side_effect = [None, summary_dump, config_dump]
|
135
|
-
run.report_outcome(config, "the/archive/path", summary, fake_ctx)
|
136
|
-
assert m_nuke.called
|
137
|
-
m_try_push_job_info.assert_called_with(config, summary)
|
138
|
-
m_open.assert_called_with("the/archive/path/summary.yaml", "w")
|
139
|
-
assert m_email_results.called
|
140
|
-
assert m_open.called
|
141
|
-
assert m_sys_exit.called
|
142
|
-
|
143
|
-
@patch("teuthology.run.set_up_logging")
|
144
|
-
@patch("teuthology.run.setup_config")
|
145
|
-
@patch("teuthology.run.get_user")
|
146
|
-
@patch("teuthology.run.write_initial_metadata")
|
147
|
-
@patch("teuthology.report.try_push_job_info")
|
148
|
-
@patch("teuthology.run.get_machine_type")
|
149
|
-
@patch("teuthology.run.get_summary")
|
150
|
-
@patch("yaml.safe_dump")
|
151
|
-
@patch("teuthology.run.validate_tasks")
|
152
|
-
@patch("teuthology.run.get_initial_tasks")
|
153
|
-
@patch("teuthology.run.fetch_tasks_if_needed")
|
154
|
-
@patch("teuthology.run.run_tasks")
|
155
|
-
@patch("teuthology.run.report_outcome")
|
156
|
-
def test_main(self, m_report_outcome, m_run_tasks, m_fetch_tasks_if_needed, m_get_initial_tasks, m_validate_tasks,
|
157
|
-
m_safe_dump, m_get_summary, m_get_machine_type, m_try_push_job_info, m_write_initial_metadata,
|
158
|
-
m_get_user, m_setup_config, m_set_up_logging):
|
159
|
-
""" This really should be an integration test of some sort. """
|
160
|
-
config = {"job_id": 1}
|
161
|
-
m_setup_config.return_value = config
|
162
|
-
m_get_machine_type.return_value = "machine_type"
|
163
|
-
doc = scripts_run.__doc__
|
164
|
-
args = docopt.docopt(doc, [
|
165
|
-
"--verbose",
|
166
|
-
"--archive", "some/archive/dir",
|
167
|
-
"--description", "the_description",
|
168
|
-
"--lock",
|
169
|
-
"--os-type", "os_type",
|
170
|
-
"--os-version", "os_version",
|
171
|
-
"--block",
|
172
|
-
"--name", "the_name",
|
173
|
-
"--suite-path", "some/suite/dir",
|
174
|
-
"path/to/config.yml",
|
175
|
-
])
|
176
|
-
m_get_user.return_value = "the_owner"
|
177
|
-
m_get_summary.return_value = dict(success=True, owner="the_owner", description="the_description")
|
178
|
-
m_validate_tasks.return_value = ['task3']
|
179
|
-
m_get_initial_tasks.return_value = ['task1', 'task2']
|
180
|
-
m_fetch_tasks_if_needed.return_value = "some/suite/dir"
|
181
|
-
run.main(args)
|
182
|
-
m_set_up_logging.assert_called_with(True, "some/archive/dir")
|
183
|
-
m_setup_config.assert_called_with(["path/to/config.yml"])
|
184
|
-
m_write_initial_metadata.assert_called_with(
|
185
|
-
"some/archive/dir",
|
186
|
-
config,
|
187
|
-
"the_name",
|
188
|
-
"the_description",
|
189
|
-
"the_owner"
|
190
|
-
)
|
191
|
-
m_try_push_job_info.assert_called_with(config, dict(status='running'))
|
192
|
-
m_get_machine_type.assert_called_with(None, config)
|
193
|
-
m_get_summary.assert_called_with("the_owner", "the_description")
|
194
|
-
m_get_initial_tasks.assert_called_with(True, config, "machine_type")
|
195
|
-
m_fetch_tasks_if_needed.assert_called_with(config)
|
196
|
-
assert m_report_outcome.called
|
197
|
-
args, kwargs = m_run_tasks.call_args
|
198
|
-
fake_ctx = kwargs["ctx"]._conf
|
199
|
-
# fields that must be in ctx for the tasks to behave
|
200
|
-
expected_ctx = ["verbose", "archive", "description", "owner", "lock", "machine_type", "os_type", "os_version",
|
201
|
-
"block", "name", "suite_path", "config", "summary"]
|
202
|
-
for key in expected_ctx:
|
203
|
-
assert key in fake_ctx
|
204
|
-
assert isinstance(fake_ctx["config"], dict)
|
205
|
-
assert isinstance(fake_ctx["summary"], dict)
|
206
|
-
assert "tasks" in fake_ctx["config"]
|
207
|
-
# ensures that values missing in args are added with the correct value
|
208
|
-
assert fake_ctx["owner"] == "the_owner"
|
209
|
-
assert fake_ctx["machine_type"] == "machine_type"
|
210
|
-
# ensures os_type and os_version are property overwritten
|
211
|
-
assert fake_ctx["config"]["os_type"] == "os_type"
|
212
|
-
assert fake_ctx["config"]["os_version"] == "os_version"
|
213
|
-
|
214
|
-
def test_get_teuthology_command(self):
|
215
|
-
doc = scripts_run.__doc__
|
216
|
-
args = docopt.docopt(doc, [
|
217
|
-
"--archive", "some/archive/dir",
|
218
|
-
"--description", "the_description",
|
219
|
-
"--lock",
|
220
|
-
"--block",
|
221
|
-
"--name", "the_name",
|
222
|
-
"--suite-path", "some/suite/dir",
|
223
|
-
"path/to/config.yml", "path/to/config2.yaml",
|
224
|
-
])
|
225
|
-
result = run.get_teuthology_command(args)
|
226
|
-
result = result.split()
|
227
|
-
expected = [
|
228
|
-
"teuthology",
|
229
|
-
"path/to/config.yml", "path/to/config2.yaml",
|
230
|
-
"--suite-path", "some/suite/dir",
|
231
|
-
"--lock",
|
232
|
-
"--description", "the_description",
|
233
|
-
"--name", "the_name",
|
234
|
-
"--block",
|
235
|
-
"--archive", "some/archive/dir",
|
236
|
-
]
|
237
|
-
assert len(result) == len(expected)
|
238
|
-
for arg in expected:
|
239
|
-
assert arg in result
|
teuthology/test/test_safepath.py
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
from teuthology import safepath
|
2
|
-
|
3
|
-
class TestSafepath(object):
|
4
|
-
def test_simple(self):
|
5
|
-
got = safepath.munge('foo')
|
6
|
-
assert got == 'foo'
|
7
|
-
|
8
|
-
def test_empty(self):
|
9
|
-
# really odd corner case
|
10
|
-
got = safepath.munge('')
|
11
|
-
assert got == '_'
|
12
|
-
|
13
|
-
def test_slash(self):
|
14
|
-
got = safepath.munge('/')
|
15
|
-
assert got == '_'
|
16
|
-
|
17
|
-
def test_slashslash(self):
|
18
|
-
got = safepath.munge('//')
|
19
|
-
assert got == '_'
|
20
|
-
|
21
|
-
def test_absolute(self):
|
22
|
-
got = safepath.munge('/evil')
|
23
|
-
assert got == 'evil'
|
24
|
-
|
25
|
-
def test_absolute_subdir(self):
|
26
|
-
got = safepath.munge('/evil/here')
|
27
|
-
assert got == 'evil/here'
|
28
|
-
|
29
|
-
def test_dot_leading(self):
|
30
|
-
got = safepath.munge('./foo')
|
31
|
-
assert got == 'foo'
|
32
|
-
|
33
|
-
def test_dot_middle(self):
|
34
|
-
got = safepath.munge('evil/./foo')
|
35
|
-
assert got == 'evil/foo'
|
36
|
-
|
37
|
-
def test_dot_trailing(self):
|
38
|
-
got = safepath.munge('evil/foo/.')
|
39
|
-
assert got == 'evil/foo'
|
40
|
-
|
41
|
-
def test_dotdot(self):
|
42
|
-
got = safepath.munge('../evil/foo')
|
43
|
-
assert got == '_./evil/foo'
|
44
|
-
|
45
|
-
def test_dotdot_subdir(self):
|
46
|
-
got = safepath.munge('evil/../foo')
|
47
|
-
assert got == 'evil/_./foo'
|
48
|
-
|
49
|
-
def test_hidden(self):
|
50
|
-
got = safepath.munge('.evil')
|
51
|
-
assert got == '_evil'
|
52
|
-
|
53
|
-
def test_hidden_subdir(self):
|
54
|
-
got = safepath.munge('foo/.evil')
|
55
|
-
assert got == 'foo/_evil'
|
teuthology/test/test_schedule.py
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
from teuthology.schedule import build_config
|
2
|
-
from teuthology.misc import get_user
|
3
|
-
|
4
|
-
|
5
|
-
class TestSchedule(object):
|
6
|
-
basic_args = {
|
7
|
-
'--verbose': False,
|
8
|
-
'--owner': 'OWNER',
|
9
|
-
'--description': 'DESC',
|
10
|
-
'--email': 'EMAIL',
|
11
|
-
'--first-in-suite': False,
|
12
|
-
'--last-in-suite': True,
|
13
|
-
'--name': 'NAME',
|
14
|
-
'--worker': 'tala',
|
15
|
-
'--timeout': '6',
|
16
|
-
'--priority': '99',
|
17
|
-
# TODO: make this work regardless of $PWD
|
18
|
-
#'<conf_file>': ['../../examples/3node_ceph.yaml',
|
19
|
-
# '../../examples/3node_rgw.yaml'],
|
20
|
-
}
|
21
|
-
|
22
|
-
def test_basic(self):
|
23
|
-
expected = {
|
24
|
-
'description': 'DESC',
|
25
|
-
'email': 'EMAIL',
|
26
|
-
'first_in_suite': False,
|
27
|
-
'last_in_suite': True,
|
28
|
-
'machine_type': 'tala',
|
29
|
-
'name': 'NAME',
|
30
|
-
'owner': 'OWNER',
|
31
|
-
'priority': 99,
|
32
|
-
'results_timeout': '6',
|
33
|
-
'verbose': False,
|
34
|
-
'tube': 'tala',
|
35
|
-
}
|
36
|
-
|
37
|
-
job_dict = build_config(self.basic_args)
|
38
|
-
assert job_dict == expected
|
39
|
-
|
40
|
-
def test_owner(self):
|
41
|
-
args = self.basic_args
|
42
|
-
args['--owner'] = None
|
43
|
-
job_dict = build_config(self.basic_args)
|
44
|
-
assert job_dict['owner'] == 'scheduled_%s' % get_user()
|
45
|
-
|
teuthology/test/test_scrape.py
DELETED
@@ -1,167 +0,0 @@
|
|
1
|
-
from __future__ import with_statement
|
2
|
-
|
3
|
-
import os
|
4
|
-
import shutil
|
5
|
-
import tempfile
|
6
|
-
import yaml
|
7
|
-
from teuthology import scrape
|
8
|
-
|
9
|
-
class FakeResultDir(object):
|
10
|
-
"""Mocks a Result Directory"""
|
11
|
-
|
12
|
-
def __init__(self,
|
13
|
-
failure_reason="Dummy reason",
|
14
|
-
assertion="FAILED assert 1 == 2\n",
|
15
|
-
blank_backtrace=False
|
16
|
-
):
|
17
|
-
self.failure_reason = failure_reason
|
18
|
-
self.assertion = assertion
|
19
|
-
self.blank_backtrace = blank_backtrace
|
20
|
-
self.path = tempfile.mkdtemp()
|
21
|
-
|
22
|
-
with open(os.path.join(self.path, "config.yaml"), "w") as f:
|
23
|
-
yaml.dump({"description": "Dummy test"}, f)
|
24
|
-
|
25
|
-
with open(os.path.join(self.path, "summary.yaml"), "w") as f:
|
26
|
-
yaml.dump({
|
27
|
-
"success": "false",
|
28
|
-
"failure_reason": self.failure_reason
|
29
|
-
}, f)
|
30
|
-
|
31
|
-
with open(os.path.join(self.path, "teuthology.log"), "w") as f:
|
32
|
-
if not self.blank_backtrace:
|
33
|
-
f.write(" ceph version 1000\n")
|
34
|
-
f.write(".stderr: Dummy error\n")
|
35
|
-
f.write(self.assertion)
|
36
|
-
f.write(" NOTE: a copy of the executable dummy text\n")
|
37
|
-
|
38
|
-
def __enter__(self):
|
39
|
-
return self
|
40
|
-
|
41
|
-
def __exit__(self, exc_typ, exc_val, exc_tb):
|
42
|
-
shutil.rmtree(self.path)
|
43
|
-
|
44
|
-
class TestScrape(object):
|
45
|
-
"""Tests for teuthology.scrape"""
|
46
|
-
|
47
|
-
def test_grep(self):
|
48
|
-
with FakeResultDir() as d:
|
49
|
-
filepath = os.path.join(d.path, "scrapetest.txt")
|
50
|
-
with open(filepath, 'w') as f:
|
51
|
-
f.write("Ceph is an open-source software storage platform\n\
|
52
|
-
Teuthology is used for testing.")
|
53
|
-
|
54
|
-
#System level grep is called
|
55
|
-
value1 = scrape.grep(filepath, "software")
|
56
|
-
value2 = scrape.grep(filepath, "device")
|
57
|
-
|
58
|
-
assert value1 ==\
|
59
|
-
['Ceph is an open-source software storage platform', '']
|
60
|
-
assert value2 == []
|
61
|
-
|
62
|
-
def test_job(self):
|
63
|
-
with FakeResultDir() as d:
|
64
|
-
job = scrape.Job(d.path, 1)
|
65
|
-
assert job.get_success() == "false"
|
66
|
-
assert job.get_assertion() == "FAILED assert 1 == 2"
|
67
|
-
assert job.get_last_tlog_line() ==\
|
68
|
-
b"NOTE: a copy of the executable dummy text"
|
69
|
-
assert job.get_failure_reason() == "Dummy reason"
|
70
|
-
|
71
|
-
def test_timeoutreason(self):
|
72
|
-
with FakeResultDir(failure_reason=\
|
73
|
-
"status 124: timeout '123 /home/ubuntu/cephtest/workunit.client.0/cephtool/test.sh'") as d:
|
74
|
-
job = scrape.Job(d.path, 1)
|
75
|
-
assert scrape.TimeoutReason.could_be(job)
|
76
|
-
assert scrape.TimeoutReason(job).match(job)
|
77
|
-
|
78
|
-
def test_deadreason(self):
|
79
|
-
with FakeResultDir() as d:
|
80
|
-
job = scrape.Job(d.path, 1)
|
81
|
-
#Summary is present
|
82
|
-
#So this cannot be a DeadReason
|
83
|
-
assert not scrape.DeadReason.could_be(job)
|
84
|
-
|
85
|
-
def test_lockdepreason(self):
|
86
|
-
lkReason = None
|
87
|
-
with FakeResultDir(assertion=\
|
88
|
-
"FAILED assert common/lockdep reason\n") as d:
|
89
|
-
job = scrape.Job(d.path, 1)
|
90
|
-
assert scrape.LockdepReason.could_be(job)
|
91
|
-
|
92
|
-
lkReason = scrape.LockdepReason(job)
|
93
|
-
#Backtraces of same jobs must match 100%
|
94
|
-
assert lkReason.match(job)
|
95
|
-
with FakeResultDir(blank_backtrace=True) as d:
|
96
|
-
#Corresponding to 0% match
|
97
|
-
assert not lkReason.match(scrape.Job(d.path, 2))
|
98
|
-
|
99
|
-
def test_assertionreason(self):
|
100
|
-
with FakeResultDir() as d:
|
101
|
-
job = scrape.Job(d.path, 1)
|
102
|
-
assert scrape.AssertionReason.could_be(job)
|
103
|
-
|
104
|
-
def test_genericreason(self):
|
105
|
-
d1 = FakeResultDir(blank_backtrace=True)
|
106
|
-
d2 = FakeResultDir(failure_reason="Dummy dummy")
|
107
|
-
d3 = FakeResultDir()
|
108
|
-
|
109
|
-
job1 = scrape.Job(d1.path, 1)
|
110
|
-
job2 = scrape.Job(d2.path, 2)
|
111
|
-
job3 = scrape.Job(d3.path, 3)
|
112
|
-
|
113
|
-
reason = scrape.GenericReason(job3)
|
114
|
-
|
115
|
-
assert reason.match(job2)
|
116
|
-
assert not reason.match(job1)
|
117
|
-
|
118
|
-
shutil.rmtree(d1.path)
|
119
|
-
shutil.rmtree(d2.path)
|
120
|
-
shutil.rmtree(d3.path)
|
121
|
-
|
122
|
-
def test_valgrindreason(self):
|
123
|
-
vreason = None
|
124
|
-
with FakeResultDir(
|
125
|
-
failure_reason="saw valgrind issues",
|
126
|
-
assertion="2014-08-22T20:07:18.668 ERROR:tasks.ceph:saw valgrind issue <kind>Leak_DefinitelyLost</kind> in /var/log/ceph/valgrind/osd.3.log.gz\n"
|
127
|
-
) as d:
|
128
|
-
job = scrape.Job(d.path, 1)
|
129
|
-
assert scrape.ValgrindReason.could_be(job)
|
130
|
-
|
131
|
-
vreason = scrape.ValgrindReason(job)
|
132
|
-
assert vreason.match(job)
|
133
|
-
|
134
|
-
def test_give_me_a_reason(self):
|
135
|
-
with FakeResultDir() as d:
|
136
|
-
job = scrape.Job(d.path, 1)
|
137
|
-
|
138
|
-
assert type(scrape.give_me_a_reason(job)) == scrape.AssertionReason
|
139
|
-
|
140
|
-
#Test the lockdep ordering
|
141
|
-
with FakeResultDir(assertion=\
|
142
|
-
"FAILED assert common/lockdep reason\n") as d:
|
143
|
-
job = scrape.Job(d.path, 1)
|
144
|
-
assert type(scrape.give_me_a_reason(job)) == scrape.LockdepReason
|
145
|
-
|
146
|
-
def test_scraper(self):
|
147
|
-
d = FakeResultDir()
|
148
|
-
os.mkdir(os.path.join(d.path, "test"))
|
149
|
-
shutil.move(
|
150
|
-
os.path.join(d.path, "config.yaml"),
|
151
|
-
os.path.join(d.path, "test", "config.yaml")
|
152
|
-
)
|
153
|
-
shutil.move(
|
154
|
-
os.path.join(d.path, "summary.yaml"),
|
155
|
-
os.path.join(d.path, "test", "summary.yaml")
|
156
|
-
)
|
157
|
-
shutil.move(
|
158
|
-
os.path.join(d.path, "teuthology.log"),
|
159
|
-
os.path.join(d.path, "test", "teuthology.log")
|
160
|
-
)
|
161
|
-
|
162
|
-
scrape.Scraper(d.path).analyze()
|
163
|
-
|
164
|
-
#scrape.log should be created
|
165
|
-
assert os.path.exists(os.path.join(d.path, "scrape.log"))
|
166
|
-
|
167
|
-
shutil.rmtree(d.path)
|
teuthology/test/test_timer.py
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
from teuthology import timer
|
2
|
-
|
3
|
-
from unittest.mock import MagicMock, patch, mock_open
|
4
|
-
from time import time
|
5
|
-
|
6
|
-
|
7
|
-
class TestTimer(object):
|
8
|
-
def test_data_empty(self):
|
9
|
-
self.timer = timer.Timer()
|
10
|
-
assert self.timer.data == dict()
|
11
|
-
|
12
|
-
def test_data_one_mark(self):
|
13
|
-
self.timer = timer.Timer()
|
14
|
-
# Avoid failing if ~1ms elapses between these two calls
|
15
|
-
self.timer.precision = 2
|
16
|
-
self.timer.mark()
|
17
|
-
assert len(self.timer.data['marks']) == 1
|
18
|
-
assert self.timer.data['marks'][0]['interval'] == 0
|
19
|
-
assert self.timer.data['marks'][0]['message'] == ''
|
20
|
-
|
21
|
-
def test_data_five_marks(self):
|
22
|
-
self.timer = timer.Timer()
|
23
|
-
for i in range(5):
|
24
|
-
self.timer.mark(str(i))
|
25
|
-
assert len(self.timer.data['marks']) == 5
|
26
|
-
assert [m['message'] for m in self.timer.data['marks']] == \
|
27
|
-
['0', '1', '2', '3', '4']
|
28
|
-
|
29
|
-
def test_intervals(self):
|
30
|
-
fake_time = MagicMock()
|
31
|
-
with patch('teuthology.timer.time.time', fake_time):
|
32
|
-
self.timer = timer.Timer()
|
33
|
-
now = start_time = fake_time.return_value = time()
|
34
|
-
intervals = [0, 1, 1, 2, 3, 5, 8]
|
35
|
-
for i in intervals:
|
36
|
-
now += i
|
37
|
-
fake_time.return_value = now
|
38
|
-
self.timer.mark(str(i))
|
39
|
-
|
40
|
-
summed_intervals = [sum(intervals[:x + 1]) for x in range(len(intervals))]
|
41
|
-
result_intervals = [m['interval'] for m in self.timer.data['marks']]
|
42
|
-
assert result_intervals == summed_intervals
|
43
|
-
assert self.timer.data['start'] == \
|
44
|
-
self.timer.get_datetime_string(start_time)
|
45
|
-
assert self.timer.data['end'] == \
|
46
|
-
self.timer.get_datetime_string(start_time + summed_intervals[-1])
|
47
|
-
assert [m['message'] for m in self.timer.data['marks']] == \
|
48
|
-
[str(i) for i in intervals]
|
49
|
-
assert self.timer.data['elapsed'] == summed_intervals[-1]
|
50
|
-
|
51
|
-
def test_write(self):
|
52
|
-
_path = '/path'
|
53
|
-
_safe_dump = MagicMock(name='safe_dump')
|
54
|
-
with patch('teuthology.timer.yaml.safe_dump', _safe_dump):
|
55
|
-
with patch('teuthology.timer.open', mock_open(), create=True) as _open:
|
56
|
-
self.timer = timer.Timer(path=_path)
|
57
|
-
assert self.timer.path == _path
|
58
|
-
self.timer.write()
|
59
|
-
_open.assert_called_once_with(_path, 'w')
|
60
|
-
_safe_dump.assert_called_once_with(
|
61
|
-
dict(),
|
62
|
-
_open.return_value.__enter__.return_value,
|
63
|
-
default_flow_style=False,
|
64
|
-
)
|
65
|
-
|
66
|
-
def test_sync(self):
|
67
|
-
_path = '/path'
|
68
|
-
_safe_dump = MagicMock(name='safe_dump')
|
69
|
-
with patch('teuthology.timer.yaml.safe_dump', _safe_dump):
|
70
|
-
with patch('teuthology.timer.open', mock_open(), create=True) as _open:
|
71
|
-
self.timer = timer.Timer(path=_path, sync=True)
|
72
|
-
assert self.timer.path == _path
|
73
|
-
assert self.timer.sync is True
|
74
|
-
self.timer.mark()
|
75
|
-
_open.assert_called_once_with(_path, 'w')
|
76
|
-
_safe_dump.assert_called_once_with(
|
77
|
-
self.timer.data,
|
78
|
-
_open.return_value.__enter__.return_value,
|
79
|
-
default_flow_style=False,
|
80
|
-
)
|
@@ -1,84 +0,0 @@
|
|
1
|
-
from unittest.mock import patch, Mock
|
2
|
-
|
3
|
-
import teuthology.lock.util
|
4
|
-
from teuthology import provision
|
5
|
-
|
6
|
-
|
7
|
-
class TestVpsOsVersionParamCheck(object):
|
8
|
-
|
9
|
-
def setup(self):
|
10
|
-
self.fake_ctx = Mock()
|
11
|
-
self.fake_ctx.machine_type = 'vps'
|
12
|
-
self.fake_ctx.num_to_lock = 1
|
13
|
-
self.fake_ctx.lock = False
|
14
|
-
|
15
|
-
def fake_downburst_executable():
|
16
|
-
return ''
|
17
|
-
|
18
|
-
self.fake_downburst_executable = fake_downburst_executable
|
19
|
-
|
20
|
-
def test_ubuntu_precise(self):
|
21
|
-
self.fake_ctx.os_type = 'ubuntu'
|
22
|
-
self.fake_ctx.os_version = 'precise'
|
23
|
-
with patch.multiple(
|
24
|
-
provision.downburst,
|
25
|
-
downburst_executable=self.fake_downburst_executable,
|
26
|
-
):
|
27
|
-
check_value = teuthology.lock.util.vps_version_or_type_valid(
|
28
|
-
self.fake_ctx.machine_type,
|
29
|
-
self.fake_ctx.os_type,
|
30
|
-
self.fake_ctx.os_version)
|
31
|
-
|
32
|
-
assert check_value
|
33
|
-
|
34
|
-
def test_ubuntu_number(self):
|
35
|
-
self.fake_ctx.os_type = 'ubuntu'
|
36
|
-
self.fake_ctx.os_version = '12.04'
|
37
|
-
with patch.multiple(
|
38
|
-
provision.downburst,
|
39
|
-
downburst_executable=self.fake_downburst_executable,
|
40
|
-
):
|
41
|
-
check_value = teuthology.lock.util.vps_version_or_type_valid(
|
42
|
-
self.fake_ctx.machine_type,
|
43
|
-
self.fake_ctx.os_type,
|
44
|
-
self.fake_ctx.os_version)
|
45
|
-
assert check_value
|
46
|
-
|
47
|
-
def test_mixup(self):
|
48
|
-
self.fake_ctx.os_type = '6.5'
|
49
|
-
self.fake_ctx.os_version = 'rhel'
|
50
|
-
with patch.multiple(
|
51
|
-
provision.downburst,
|
52
|
-
downburst_executable=self.fake_downburst_executable,
|
53
|
-
):
|
54
|
-
check_value = teuthology.lock.util.vps_version_or_type_valid(
|
55
|
-
self.fake_ctx.machine_type,
|
56
|
-
self.fake_ctx.os_type,
|
57
|
-
self.fake_ctx.os_version)
|
58
|
-
assert not check_value
|
59
|
-
|
60
|
-
def test_bad_type(self):
|
61
|
-
self.fake_ctx.os_type = 'aardvark'
|
62
|
-
self.fake_ctx.os_version = '6.5'
|
63
|
-
with patch.multiple(
|
64
|
-
provision.downburst,
|
65
|
-
downburst_executable=self.fake_downburst_executable,
|
66
|
-
):
|
67
|
-
check_value = teuthology.lock.util.vps_version_or_type_valid(
|
68
|
-
self.fake_ctx.machine_type,
|
69
|
-
self.fake_ctx.os_type,
|
70
|
-
self.fake_ctx.os_version)
|
71
|
-
assert not check_value
|
72
|
-
|
73
|
-
def test_bad_version(self):
|
74
|
-
self.fake_ctx.os_type = 'rhel'
|
75
|
-
self.fake_ctx.os_version = 'vampire_bat'
|
76
|
-
with patch.multiple(
|
77
|
-
provision.downburst,
|
78
|
-
downburst_executable=self.fake_downburst_executable,
|
79
|
-
):
|
80
|
-
check_value = teuthology.lock.util.vps_version_or_type_valid(
|
81
|
-
self.fake_ctx.machine_type,
|
82
|
-
self.fake_ctx.os_type,
|
83
|
-
self.fake_ctx.os_version)
|
84
|
-
assert not check_value
|