From 5349144c87862dadabcb4120302e8f6c88434951 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Fri, 27 Jan 2017 19:09:59 +0000 Subject: [PATCH 1/7] TestEnv: Don't use root on Local target --- libs/utils/env.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/utils/env.py b/libs/utils/env.py index 4660b2c7e..d92b29bdc 100644 --- a/libs/utils/env.py +++ b/libs/utils/env.py @@ -442,7 +442,9 @@ class TestEnv(ShareState): self.target = devlib.LocalLinuxTarget( platform = platform, load_default_modules = False, - modules = self.__modules) + modules = self.__modules, + # TODO Configure this in target_conf ? + connection_settings = {'unrooted': True}) else: raise ValueError('Config error: not supported [platform] type {}'\ .format(platform_type)) -- GitLab From 39434ddcd5048bf5ab796f2403b36d3b6138f07c Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Fri, 27 Jan 2017 19:10:23 +0000 Subject: [PATCH 2/7] Executor: Don't mount tmpfs for run dir if we don't have root --- libs/utils/executor.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/libs/utils/executor.py b/libs/utils/executor.py index 3d469c77f..3596179a2 100644 --- a/libs/utils/executor.py +++ b/libs/utils/executor.py @@ -89,6 +89,7 @@ class Executor(): # Initialize globals self._default_cgroup = None self._cgroup = None + self._old_selinux_mode = None # Setup logging self._log = logging.getLogger('Executor') @@ -229,24 +230,30 @@ class Executor(): self._log.debug('Setup RT-App run folder [%s]...', self.te.run_dir) self.target.execute('[ -d {0} ] || mkdir {0}'\ .format(self.te.run_dir)) - self.target.execute( + + if self.target.is_rooted: + self.target.execute( 'grep schedtest /proc/mounts || '\ ' mount -t tmpfs -o size=1024m {} {}'\ .format('schedtest', self.te.run_dir), as_root=True) - # tmpfs mounts have an SELinux context with "tmpfs" as the type (while - # other files we create have "shell_data_file"). That prevents non-root - # users from creating files in tmpfs mounts. For now, just put SELinux - # in permissive mode to get around that. - try: - # First, save the old SELinux mode - self._old_selinux_mode = self.target.execute('getenforce') - except TargetError: - # Probably the target doesn't have SELinux. No problem. - self._old_selinux_mode = None + + # tmpfs mounts have an SELinux context with "tmpfs" as the type + # (while other files we create have "shell_data_file"). That + # prevents non-root users from creating files in tmpfs mounts. For + # now, just put SELinux in permissive mode to get around that. + try: + # First, save the old SELinux mode + self._old_selinux_mode = self.target.execute('getenforce') + except TargetError: + # Probably the target doesn't have SELinux. No problem. + pass + else: + + self._log.warning('Setting target SELinux in permissive mode') + self.target.execute('setenforce 0', as_root=True) else: - self._log.warning('Setting target SELinux in permissive mode') - self.target.execute('setenforce 0', as_root=True) + self._log.warning('Not mounting tempfs because no root') def _setup_cpufreq(self, tc): if 'cpufreq' not in tc: -- GitLab From 7f713e61582afbbfe1fe6d375029194c513aab6a Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Tue, 31 Jan 2017 18:42:00 +0000 Subject: [PATCH 3/7] Add simple self-test for Executor --- tests/lisa/test_executor.py | 123 ++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tests/lisa/test_executor.py diff --git a/tests/lisa/test_executor.py b/tests/lisa/test_executor.py new file mode 100644 index 000000000..60758f89c --- /dev/null +++ b/tests/lisa/test_executor.py @@ -0,0 +1,123 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2016, ARM Limited and contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import namedtuple +import shutil +import os +from unittest import TestCase + +from mock import patch, Mock, MagicMock, call + +import devlib + +from env import TestEnv +from executor import Executor + +class SetUpTarget(TestCase): + def setUp(self): + self.res_dir='test_{}'.format(self.__class__.__name__) + self.te = TestEnv(target_conf={ + 'platform': 'host', + # TODO: can't calibrate rt-app on local targets because they're + # probably intel_pstate and/or no root. Calibration requires setting + # performance governor. + 'rtapp-calib': {i: 100 for i in range(4)}, + 'modules': ['cgroups'], + }, + test_conf={ + 'results_dir': self.res_dir + }, force_new=True) + +mock_freezer = namedtuple('MockController', ['name'])('freezer') +class MockCgroupsModule(devlib.module.Module): + name = 'cgroups' + list_subsystems = Mock(return_value=[mock_freezer]) + freeze = Mock() + @staticmethod + def probe(target): + return True + +devlib.module.register_module(MockCgroupsModule) + +example_wl = { + "type" : "rt-app", + "conf" : { + "class" : "profile", + "params" : { + "mytask" : { + "kind" : "Periodic", + "params" : { + "duty_cycle_pct": 10, + "duration_s": 1, + }, + }, + }, + } +} + +class TestMagicSmoke(SetUpTarget): + def test_files_created(self): + conf_name = 'myconf' + wl_name = 'mywl' + results_dir = os.path.join( + self.te.LISA_HOME, + 'results', + self.res_dir, + 'rtapp:{}:{}'.format(conf_name, wl_name)) + if os.path.isdir(results_dir): + shutil.rmtree(results_dir) + + experiments_conf = { + 'confs': [{ + 'tag': conf_name + }], + "wloads" : { + wl_name : example_wl, + }, + } + + executor = Executor(self.te, experiments_conf) + executor.run() + + self.assertTrue( + os.path.isdir(results_dir), + 'Expected to find a directory at {}'.format(results_dir)) + + result_1_dir = os.path.join(results_dir, '1') + self.assertTrue( + os.path.isdir(result_1_dir), + 'Expected to find a directory at {}'.format(result_1_dir)) + +class TestFreezeUserspace(SetUpTarget): + def test_freeze_userspace(self): + experiments_conf = { + 'confs': [{ + 'tag': 'with_freeze', + 'flags': ['freeze_userspace'], + }], + "wloads" : { + 'my_wl' : example_wl, + }, + } + + freezer_mock = self.te.target.cgroups.freeze + + executor = Executor(self.te, experiments_conf) + executor.run() + + self.assertListEqual(freezer_mock.mock_calls, + [call(['init', 'systemd', 'sh', 'ssh']), + call(thaw=True)]) -- GitLab From 05f344b7a05cd1b1184fece8c75dc1a533bc3b41 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Fri, 3 Feb 2017 16:15:08 +0000 Subject: [PATCH 4/7] test_executor: Improve and add broken wload method --- tests/lisa/test_executor.py | 42 ++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/tests/lisa/test_executor.py b/tests/lisa/test_executor.py index 60758f89c..5eed1ab80 100644 --- a/tests/lisa/test_executor.py +++ b/tests/lisa/test_executor.py @@ -25,6 +25,7 @@ import devlib from env import TestEnv from executor import Executor +import wlgen class SetUpTarget(TestCase): def setUp(self): @@ -45,7 +46,7 @@ mock_freezer = namedtuple('MockController', ['name'])('freezer') class MockCgroupsModule(devlib.module.Module): name = 'cgroups' list_subsystems = Mock(return_value=[mock_freezer]) - freeze = Mock() + freeze = Mock(name='Cgroups_freeze') @staticmethod def probe(target): return True @@ -101,8 +102,24 @@ class TestMagicSmoke(SetUpTarget): os.path.isdir(result_1_dir), 'Expected to find a directory at {}'.format(result_1_dir)) +class InterceptedRTA(wlgen.RTA): + pre_callback = None + def run(self, *args, **kwargs): + self.pre_callback() + super(InterceptedRTA, self).run(*args, **kwargs) + +class BrokenRTAException(Exception): + pass + +class BrokenRTA(wlgen.RTA): + pre_callback = None + def run(self, *args, **kwargs): + self.pre_callback() + self._log.warning('\n\nInjecting workload failure\n') + raise BrokenRTAException('INJECTED WORKLOAD FAILURE') + class TestFreezeUserspace(SetUpTarget): - def test_freeze_userspace(self): + def _do_freezer_test(self): experiments_conf = { 'confs': [{ 'tag': 'with_freeze', @@ -114,10 +131,25 @@ class TestFreezeUserspace(SetUpTarget): } freezer_mock = self.te.target.cgroups.freeze + freezer_mock.reset_mock() + + def assert_frozen(rta): + freezer_mock.assert_called_once_with( + ['init', 'systemd', 'sh', 'ssh']) + freezer_mock.reset_mock() + + print wlgen.RTA + wlgen.RTA.pre_callback = assert_frozen executor = Executor(self.te, experiments_conf) executor.run() - self.assertListEqual(freezer_mock.mock_calls, - [call(['init', 'systemd', 'sh', 'ssh']), - call(thaw=True)]) + freezer_mock.assert_called_once_with(thaw=True) + + @patch('wlgen.RTA', InterceptedRTA) + def test_freeze_userspace(self): + self._do_freezer_test() + + @patch('wlgen.RTA', BrokenRTA) + def test_freeze_userspace_broken(self): + self._do_freezer_test() -- GitLab From b23976557952192d0d634c10a153a5481de73315 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Tue, 14 Feb 2017 14:56:20 +0000 Subject: [PATCH 5/7] test_executor: Reduce workload length to speed up tests --- tests/lisa/test_executor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lisa/test_executor.py b/tests/lisa/test_executor.py index 5eed1ab80..aa7f79c72 100644 --- a/tests/lisa/test_executor.py +++ b/tests/lisa/test_executor.py @@ -62,7 +62,7 @@ example_wl = { "kind" : "Periodic", "params" : { "duty_cycle_pct": 10, - "duration_s": 1, + "duration_s": 0.2, }, }, }, -- GitLab From 523d8e49b56674b33e2c3f757bde6738b5b45681 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Tue, 14 Feb 2017 14:56:40 +0000 Subject: [PATCH 6/7] test_executor: Add tests for task names It's important that the tasks are named correctly as some tests expect to be able to filter by the names of tasks created by their workload --- tests/lisa/test_executor.py | 62 +++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/lisa/test_executor.py b/tests/lisa/test_executor.py index aa7f79c72..b5413c020 100644 --- a/tests/lisa/test_executor.py +++ b/tests/lisa/test_executor.py @@ -15,6 +15,7 @@ # limitations under the License. # from collections import namedtuple +from copy import deepcopy import shutil import os from unittest import TestCase @@ -69,6 +70,67 @@ example_wl = { } } +class TestTaskNames(SetUpTarget): + """Tests for the names of workload tasks created by the Executor""" + + def run_and_assert_task_names(self, experiments_conf, expected_tasks): + executor = Executor(self.te, experiments_conf) + executor.run() + [experiment] = executor.experiments + tasks = experiment.wload.tasks.keys() + self.assertSetEqual(set(expected_tasks), set(tasks)) + + def test_single_task_noprefix(self): + experiments_conf = { + 'confs': [{ + 'tag': 'myconf' + }], + "wloads" : { + 'mywl': example_wl + }, + } + + self.run_and_assert_task_names(experiments_conf, ['task_mytask']) + + def test_single_task_prefix(self): + wlspec = deepcopy(example_wl) + + wlspec['conf']['prefix'] = 'PREFIX' + + print wlspec + + experiments_conf = { + 'confs': [{ + 'tag': 'myconf' + }], + "wloads" : { + 'mywl': wlspec + }, + } + + self.run_and_assert_task_names(experiments_conf, ['PREFIXmytask']) + + def test_multiple_task(self): + wlspec = deepcopy(example_wl) + num_tasks = 5 + + wlspec['conf']['params']['mytask']['tasks'] = num_tasks + + print wlspec + + experiments_conf = { + 'confs': [{ + 'tag': 'myconf' + }], + "wloads" : { + 'mywl': wlspec + }, + } + + exp_names = ['task_mytask_{}'.format(i) for i in range(num_tasks)] + self.run_and_assert_task_names(experiments_conf, exp_names) + + class TestMagicSmoke(SetUpTarget): def test_files_created(self): conf_name = 'myconf' -- GitLab From 992de79c0efdcadb3889f48031e2253b9e519420 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Tue, 14 Feb 2017 14:57:18 +0000 Subject: [PATCH 7/7] [necessary?] test_executor: Add get_rta_results_dir method --- tests/lisa/test_executor.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/lisa/test_executor.py b/tests/lisa/test_executor.py index b5413c020..4b945602f 100644 --- a/tests/lisa/test_executor.py +++ b/tests/lisa/test_executor.py @@ -132,14 +132,16 @@ class TestTaskNames(SetUpTarget): class TestMagicSmoke(SetUpTarget): + def get_rta_results_dir(self, conf_name, wl_name): + return os.path.join(self.te.LISA_HOME, 'results', self.res_dir, + 'rtapp:{}:{}'.format(conf_name, wl_name)) + def test_files_created(self): + """Test that we can run experiments and get output files""" conf_name = 'myconf' wl_name = 'mywl' - results_dir = os.path.join( - self.te.LISA_HOME, - 'results', - self.res_dir, - 'rtapp:{}:{}'.format(conf_name, wl_name)) + + results_dir = self.get_rta_results_dir(conf_name, wl_name) if os.path.isdir(results_dir): shutil.rmtree(results_dir) -- GitLab