Skip to content

Commit a7f8fae

Browse files
authored
Merge pull request ARM-software#238 from bjackman/lisa-test-interface-change
Executor & LisaTest interface change
2 parents 0778550 + 5f18308 commit a7f8fae

11 files changed

+1162
-812
lines changed

ipynb/profiling/kernel_functions_profiling.ipynb

Lines changed: 363 additions & 208 deletions
Large diffs are not rendered by default.

ipynb/tutorial/04_ExecutorUsage.ipynb

Lines changed: 424 additions & 152 deletions
Large diffs are not rendered by default.

ipynb/utils/executor_example.ipynb

Lines changed: 161 additions & 170 deletions
Large diffs are not rendered by default.

libs/utils/executor.py

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@
3434
level=logging.INFO,
3535
datefmt='%I:%M:%S')
3636

37-
# Add support for Test Environment configuration
38-
from env import TestEnv
39-
4037
# Add JSON parsing support
4138
from conf import JsonConf
4239

@@ -49,7 +46,7 @@
4946

5047
class Executor():
5148

52-
def __init__(self, target_conf=None, tests_conf=None):
49+
def __init__(self, test_env, experiments_conf):
5350
"""
5451
Tests Executor
5552
@@ -58,73 +55,78 @@ def __init__(self, target_conf=None, tests_conf=None):
5855
- a target configuration
5956
- a worload to execute
6057
61-
The executor module can be configured to run a set of workloads
62-
(wloads) in each different target configuration of a specified set
63-
(confs). These wloads and confs can be specified by the "tests_config"
64-
input dictionary.
58+
The executor module can be configured to run a set of workloads (wloads)
59+
in each different target configuration of a specified set (confs). These
60+
wloads and confs can be specified by the "experiments_conf" input
61+
dictionary. Each (workload, conf, iteration) tuple is called an
62+
"experiment".
6563
6664
All the results generated by each experiment will be collected a result
6765
folder which is named according to this template:
6866
results/<test_id>/<wltype>:<conf>:<wload>/<run_id>
6967
where:
70-
- <test_id> : the "tid" defined by the tests_config, or a timestamp
68+
- <test_id> : the "tid" defined by the experiments_conf, or a timestamp
7169
based folder in case "tid" is not specified
7270
- <wltype> : the class of workload executed, e.g. rtapp or sched_perf
7371
- <conf> : the identifier of one of the specified configurations
7472
- <wload> : the identified of one of the specified workload
7573
- <run_id> : the progressive execution number from 1 up to the
7674
specified iterations
75+
76+
After the workloads have been run, the Executor object's `experiments`
77+
attribute is a list of Experiment objects. The `out_dir` attribute of
78+
these objects can be used to find the results of the experiment.
7779
"""
7880

7981
# Initialize globals
8082
self._default_cgroup = None
8183
self._cgroup = None
8284

8385
# Setup test configuration
84-
if isinstance(tests_conf, dict):
86+
if isinstance(experiments_conf, dict):
8587
logging.info('%14s - Loading custom (inline) test configuration',
8688
'Target')
87-
self._tests_conf = tests_conf
88-
elif isinstance(tests_conf, str):
89+
self._experiments_conf = experiments_conf
90+
elif isinstance(experiments_conf, str):
8991
logging.info('%14s - Loading custom (file) test configuration',
9092
'Target')
91-
json_conf = JsonConf(tests_conf)
92-
self._tests_conf = json_conf.load()
93+
json_conf = JsonConf(experiments_conf)
94+
self._experiments_conf = json_conf.load()
9395
else:
94-
raise ValueError('test_conf must be either a dictionary or a filepath')
96+
raise ValueError(
97+
'experiments_conf must be either a dictionary or a filepath')
9598

9699
# Check for mandatory configurations
97-
if 'confs' not in self._tests_conf or not self._tests_conf['confs']:
100+
if not self._experiments_conf.get('confs', None):
98101
raise ValueError(
99102
'Configuration error: missing \'conf\' definitions')
100-
if 'wloads' not in self._tests_conf or not self._tests_conf['wloads']:
103+
if not self._experiments_conf.get('wloads', None):
101104
raise ValueError(
102105
'Configuration error: missing \'wloads\' definitions')
103106

104-
# Setup devlib to access the configured target
105-
self.te = TestEnv(target_conf, tests_conf)
107+
self.te = test_env
106108
self.target = self.te.target
107109

108-
self._iterations = self._tests_conf.get('iterations', 1)
110+
self._iterations = self._experiments_conf.get('iterations', 1)
109111
# Compute total number of experiments
110112
self._exp_count = self._iterations \
111-
* len(self._tests_conf['wloads']) \
112-
* len(self._tests_conf['confs'])
113+
* len(self._experiments_conf['wloads']) \
114+
* len(self._experiments_conf['confs'])
113115

114116
self._print_section('Executor', 'Experiments configuration')
115117

116118
logging.info('%14s - Configured to run:', 'Executor')
117119

118120
logging.info('%14s - %3d target configurations:',
119-
'Executor', len(self._tests_conf['confs']))
120-
target_confs = [conf['tag'] for conf in self._tests_conf['confs']]
121+
'Executor', len(self._experiments_conf['confs']))
122+
target_confs = [conf['tag'] for conf in self._experiments_conf['confs']]
121123
target_confs = ', '.join(target_confs)
122124
logging.info('%14s - %s', 'Executor', target_confs)
123125

124126
logging.info('%14s - %3d workloads (%d iterations each)',
125-
'Executor', len(self._tests_conf['wloads']),
127+
'Executor', len(self._experiments_conf['wloads']),
126128
self._iterations)
127-
wload_confs = ', '.join(self._tests_conf['wloads'])
129+
wload_confs = ', '.join(self._experiments_conf['wloads'])
128130
logging.info('%14s - %s', 'Executor', wload_confs)
129131

130132
logging.info('%14s - Total: %d experiments',
@@ -140,11 +142,11 @@ def run(self):
140142

141143
# Run all the configured experiments
142144
exp_idx = 0
143-
for tc in self._tests_conf['confs']:
145+
for tc in self._experiments_conf['confs']:
144146
# TARGET: configuration
145147
if not self._target_configure(tc):
146148
continue
147-
for wl_idx in self._tests_conf['wloads']:
149+
for wl_idx in self._experiments_conf['wloads']:
148150
# TEST: configuration
149151
wload, test_dir = self._wload_init(tc, wl_idx)
150152
for itr_idx in range(1, self._iterations + 1):
@@ -502,7 +504,7 @@ def _wload_init(self, tc, wl_idx):
502504
tc_idx = tc['tag']
503505

504506
# Configure the test workload
505-
wlspec = self._tests_conf['wloads'][wl_idx]
507+
wlspec = self._experiments_conf['wloads'][wl_idx]
506508
wload = self._wload_conf(wl_idx, wlspec)
507509

508510
# Keep track of platform configuration

libs/utils/test.py

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,37 @@
2424
from devlib.utils.misc import memoized
2525
import wrapt
2626

27+
from env import TestEnv
2728
from executor import Executor
2829

2930
class LisaTest(unittest.TestCase):
30-
"""A base class for LISA defined tests"""
31+
"""
32+
A base class for LISA tests
33+
34+
This class is intended to be subclassed in order to create automated tests
35+
for LISA. It sets up the TestEnv and Executor and provides convenience
36+
methods for making assertions on results.
37+
38+
Subclasses should provide a test_conf to configure the TestEnv and an
39+
experiments_conf to configure the executor.
40+
41+
Tests whose behaviour is dependent on target parameters, for example
42+
presence of cpufreq governors or number of CPUs, can override
43+
_getExperimentsConf to generate target-dependent experiments.
44+
45+
Example users of this class can be found under LISA's tests/ directory.
46+
"""
47+
48+
test_conf = None
49+
"""Override this with a dictionary or JSON path to configure the TestEnv"""
50+
51+
experiments_conf = None
52+
"""Override this with a dictionary to configure the Executor"""
3153

3254
@classmethod
33-
def _init(cls, conf, *args, **kwargs):
55+
def _init(cls, *args, **kwargs):
3456
"""
35-
Base class to run LISA test experiments
57+
Set up logging and trigger running experiments
3658
"""
3759

3860
cls.logger = logging.getLogger('test')
@@ -41,18 +63,39 @@ def _init(cls, conf, *args, **kwargs):
4163
cls.logger.setLevel(kwargs['loglevel'])
4264
kwargs.pop('loglevel')
4365

44-
cls.conf = conf
45-
4666
cls._runExperiments()
4767

68+
@classmethod
69+
def _getTestConf(cls):
70+
if cls.test_conf is None:
71+
raise NotImplementedError("Override `test_conf` attribute")
72+
return cls.test_conf
73+
74+
@classmethod
75+
def _getExperimentsConf(cls, test_env):
76+
"""
77+
Get the experiments_conf used to configure the Executor
78+
79+
This method receives the initialized TestEnv as a parameter, so
80+
subclasses can override it to configure workloads or target confs in a
81+
manner dependent on the target. If not overridden, just returns the
82+
experiments_conf attribute.
83+
"""
84+
if cls.experiments_conf is None:
85+
raise NotImplementedError("Override `experiments_conf` attribute")
86+
return cls.experiments_conf
87+
4888
@classmethod
4989
def _runExperiments(cls):
5090
"""
5191
Default experiments execution engine
5292
"""
5393

5494
cls.logger.info("%14s - Setup tests execution engine...", "LisaTest")
55-
cls.executor = Executor(tests_conf = cls.conf);
95+
test_env = TestEnv(test_conf=cls._getTestConf())
96+
97+
experiments_conf = cls._getExperimentsConf(test_env)
98+
cls.executor = Executor(test_env, experiments_conf)
5699

57100
# Alias executor objects to make less verbose tests code
58101
cls.te = cls.executor.te

tests/eas/acceptance.config

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)