blob: 64e16e33a1c2515d197787faebf7eac26d81a668 [file] [log] [blame]
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
import logging
import os
import common
# Path to the local checkout of the fw-testing-configs repo
_CONFIG_DIR = os.path.abspath(os.path.join(
os.path.dirname(os.path.realpath(__file__)), os.pardir,
'fw-testing-configs'))
def _get_config_dir():
"""
Return the path to the directory containing platform config files.
We prefer to use _CONFIG_DIR itself, i.e. the Autotest checkout of
the fw-testing-configs repository. However, if that directory cannot
be found, then instead use the old configs/ directory.
"""
assert os.path.isdir(_CONFIG_DIR)
return _CONFIG_DIR
def _get_config_filepath(platform):
"""Find the JSON file containing the platform's config"""
return os.path.join(_get_config_dir(), '%s.json' % platform)
def _has_config_file(platform):
"""Determine whether the platform has a config file"""
return os.path.isfile(_get_config_filepath(platform))
def _load_config(platform):
"""Load the platform's JSON config into a dict"""
fp = _get_config_filepath(platform)
with open(fp) as config_file:
return json.load(config_file)
class Config(object):
"""Configuration for FAFT tests.
This object is meant to be the interface to all configuration required
by FAFT tests, including device specific overrides.
It gets the values from the JSON files in _CONFIG_DIR.
Default values are declared in the DEFAULTS.json.
Platform-specific overrides come from <platform>.json.
If the platform has model-specific overrides, then those take precedence
over the platform's config.
If the platform inherits overrides from a parent platform, then the child
platform's overrides take precedence over the parent's.
@ivar platform: string containing the board name being tested.
@ivar model: string containing the model name being tested
"""
def __init__(self, platform, model=None):
"""Initialize an object with FAFT settings.
Load JSON in order of importance (model, platform, parent/s, DEFAULTS).
@param platform: The name of the platform being tested.
"""
self._precedence_list = []
self._precedence_names = []
# Loadthe most specific JSON config possible by splitting
# `platform` at its '_' and reversing ([::-1]).
# For example, veyron_minnie should load minnie.json.
# octopus_fleex should look for fleex.json. It doesn't exist, so
# instead it loads octopus.json.
for p in platform.rsplit('_', 1)[::-1]:
p = p.lower().replace('-', '_')
if _has_config_file(p):
self.platform = p
break
else:
self.platform = platform.replace('-','_')
if _has_config_file(self.platform):
platform_config = _load_config(self.platform)
self._add_cfg_to_precedence(self.platform, platform_config)
model_configs = platform_config.get('models', {})
model_config = model_configs.get(model, None)
if model_config is not None:
self._add_cfg_to_precedence(
'MODEL:%s' % model, model_config, prepend=True)
logging.debug('Using model override for %s', model)
parent_platform = self._precedence_list[-1].get('parent', None)
while parent_platform is not None:
parent_config = _load_config(parent_platform)
self._add_cfg_to_precedence(parent_platform, parent_config)
parent_platform = self._precedence_list[-1].get('parent', None)
else:
logging.debug(
'No platform config file found at %s. Using default.',
_get_config_filepath(self.platform))
default_config = _load_config('DEFAULTS')
self._add_cfg_to_precedence('DEFAULTS', default_config)
# Set attributes
all_attributes = self._precedence_list[-1].keys()
self.attributes = {}
self.attributes['platform'] = self.platform
for attribute in all_attributes:
if attribute.endswith('.DOC') or attribute == 'models':
continue
for config_dict in self._precedence_list:
if attribute in config_dict:
self.attributes[attribute] = config_dict[attribute]
break
def _add_cfg_to_precedence(self, cfg_name, cfg, prepend=False):
"""Add a configuration to self._precedence_list.
@ivar cfg_name: The name of the config.
@ivar cfg: The config dict.
@ivar prepend: If true, add to the beginning of self._precedence_list.
Otherwise, add it to the end.
"""
position = 0 if prepend else len(self._precedence_list)
self._precedence_list.insert(position, cfg)
self._precedence_names.insert(position, cfg_name)
def __getattr__(self, attr):
if attr in self.attributes:
return self.attributes[attr]
raise AttributeError('FAFT config has no attribute named %s' % attr)
def __str__(self):
str_list = []
str_list.append('----------[ FW Testing Config Variables ]----------')
str_list.append('--- Precedence list: %s ---' % self._precedence_names)
for attr in sorted(self.attributes):
str_list.append(' %s: %s' % (attr, self.attributes[attr]))
str_list.append('---------------------------------------------------')
return '\n'.join(str_list)