mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-02-07 13:41:24 +00:00
Unit tests
This commit is contained in:
parent
02138c60cc
commit
e258999e0a
1
wlauto/tests/data/test-agenda-bad-syntax.yaml
Normal file
1
wlauto/tests/data/test-agenda-bad-syntax.yaml
Normal file
@ -0,0 +1 @@
|
|||||||
|
[ewqh
|
1
wlauto/tests/data/test-agenda-not-dict.yaml
Normal file
1
wlauto/tests/data/test-agenda-not-dict.yaml
Normal file
@ -0,0 +1 @@
|
|||||||
|
Test
|
@ -24,6 +24,7 @@ from nose.tools import assert_equal, assert_in, raises
|
|||||||
|
|
||||||
from wlauto.core.agenda import Agenda
|
from wlauto.core.agenda import Agenda
|
||||||
from wlauto.exceptions import ConfigError
|
from wlauto.exceptions import ConfigError
|
||||||
|
from wlauto.utils.serializer import SerializerSyntaxError
|
||||||
|
|
||||||
|
|
||||||
YAML_TEST_FILE = os.path.join(os.path.dirname(__file__), 'data', 'test-agenda.yaml')
|
YAML_TEST_FILE = os.path.join(os.path.dirname(__file__), 'data', 'test-agenda.yaml')
|
||||||
@ -35,7 +36,7 @@ workloads:
|
|||||||
test: 1
|
test: 1
|
||||||
"""
|
"""
|
||||||
invalid_agenda = StringIO(invalid_agenda_text)
|
invalid_agenda = StringIO(invalid_agenda_text)
|
||||||
invalid_agenda.name = 'invalid1'
|
invalid_agenda.name = 'invalid1.yaml'
|
||||||
|
|
||||||
duplicate_agenda_text = """
|
duplicate_agenda_text = """
|
||||||
global:
|
global:
|
||||||
@ -49,13 +50,13 @@ workloads:
|
|||||||
workload_name: andebench
|
workload_name: andebench
|
||||||
"""
|
"""
|
||||||
duplicate_agenda = StringIO(duplicate_agenda_text)
|
duplicate_agenda = StringIO(duplicate_agenda_text)
|
||||||
duplicate_agenda.name = 'invalid2'
|
duplicate_agenda.name = 'invalid2.yaml'
|
||||||
|
|
||||||
short_agenda_text = """
|
short_agenda_text = """
|
||||||
workloads: [antutu, linpack, andebench]
|
workloads: [antutu, linpack, andebench]
|
||||||
"""
|
"""
|
||||||
short_agenda = StringIO(short_agenda_text)
|
short_agenda = StringIO(short_agenda_text)
|
||||||
short_agenda.name = 'short'
|
short_agenda.name = 'short.yaml'
|
||||||
|
|
||||||
default_ids_agenda_text = """
|
default_ids_agenda_text = """
|
||||||
workloads:
|
workloads:
|
||||||
@ -69,7 +70,7 @@ workloads:
|
|||||||
- vellamo
|
- vellamo
|
||||||
"""
|
"""
|
||||||
default_ids_agenda = StringIO(default_ids_agenda_text)
|
default_ids_agenda = StringIO(default_ids_agenda_text)
|
||||||
default_ids_agenda.name = 'default_ids'
|
default_ids_agenda.name = 'default_ids.yaml'
|
||||||
|
|
||||||
sectioned_agenda_text = """
|
sectioned_agenda_text = """
|
||||||
sections:
|
sections:
|
||||||
@ -91,7 +92,7 @@ workloads:
|
|||||||
- nenamark
|
- nenamark
|
||||||
"""
|
"""
|
||||||
sectioned_agenda = StringIO(sectioned_agenda_text)
|
sectioned_agenda = StringIO(sectioned_agenda_text)
|
||||||
sectioned_agenda.name = 'sectioned'
|
sectioned_agenda.name = 'sectioned.yaml'
|
||||||
|
|
||||||
dup_sectioned_agenda_text = """
|
dup_sectioned_agenda_text = """
|
||||||
sections:
|
sections:
|
||||||
@ -105,7 +106,7 @@ workloads:
|
|||||||
- nenamark
|
- nenamark
|
||||||
"""
|
"""
|
||||||
dup_sectioned_agenda = StringIO(dup_sectioned_agenda_text)
|
dup_sectioned_agenda = StringIO(dup_sectioned_agenda_text)
|
||||||
dup_sectioned_agenda.name = 'dup-sectioned'
|
dup_sectioned_agenda.name = 'dup-sectioned.yaml'
|
||||||
|
|
||||||
caps_agenda_text = """
|
caps_agenda_text = """
|
||||||
config:
|
config:
|
||||||
@ -120,17 +121,17 @@ workloads:
|
|||||||
name: linpack
|
name: linpack
|
||||||
"""
|
"""
|
||||||
caps_agenda = StringIO(caps_agenda_text)
|
caps_agenda = StringIO(caps_agenda_text)
|
||||||
caps_agenda.name = 'caps'
|
caps_agenda.name = 'caps.yaml'
|
||||||
|
|
||||||
bad_syntax_agenda_text = """
|
bad_syntax_agenda_text = """
|
||||||
config:
|
config:
|
||||||
# tab on the following line
|
# tab on the following line
|
||||||
reboot_policy: never
|
reboot_policy: never
|
||||||
workloads:
|
workloads:
|
||||||
- antutu
|
- antutu
|
||||||
"""
|
"""
|
||||||
bad_syntax_agenda = StringIO(bad_syntax_agenda_text)
|
bad_syntax_agenda = StringIO(bad_syntax_agenda_text)
|
||||||
bad_syntax_agenda.name = 'bad_syntax'
|
bad_syntax_agenda.name = 'bad_syntax.yaml'
|
||||||
|
|
||||||
section_ids_test_text = """
|
section_ids_test_text = """
|
||||||
config:
|
config:
|
||||||
@ -145,7 +146,7 @@ sections:
|
|||||||
- id: bar
|
- id: bar
|
||||||
"""
|
"""
|
||||||
section_ids_agenda = StringIO(section_ids_test_text)
|
section_ids_agenda = StringIO(section_ids_test_text)
|
||||||
section_ids_agenda.name = 'section_ids'
|
section_ids_agenda.name = 'section_ids.yaml'
|
||||||
|
|
||||||
|
|
||||||
class AgendaTest(TestCase):
|
class AgendaTest(TestCase):
|
||||||
@ -154,42 +155,18 @@ class AgendaTest(TestCase):
|
|||||||
agenda = Agenda(YAML_TEST_FILE)
|
agenda = Agenda(YAML_TEST_FILE)
|
||||||
assert_equal(len(agenda.workloads), 4)
|
assert_equal(len(agenda.workloads), 4)
|
||||||
|
|
||||||
def test_duplicate_id(self):
|
|
||||||
try:
|
|
||||||
Agenda(duplicate_agenda)
|
|
||||||
except ConfigError, e:
|
|
||||||
assert_in('duplicate', e.message.lower()) # pylint: disable=E1101
|
|
||||||
else:
|
|
||||||
raise Exception('ConfigError was not raised for an agenda with duplicate ids.')
|
|
||||||
|
|
||||||
def test_yaml_missing_field(self):
|
def test_yaml_missing_field(self):
|
||||||
try:
|
try:
|
||||||
Agenda(invalid_agenda_text)
|
Agenda(invalid_agenda)
|
||||||
except ConfigError, e:
|
except ConfigError, e:
|
||||||
assert_in('workload name', e.message)
|
assert_in('workload name', e.message)
|
||||||
else:
|
else:
|
||||||
raise Exception('ConfigError was not raised for an invalid agenda.')
|
raise Exception('ConfigError was not raised for an invalid agenda.')
|
||||||
|
|
||||||
def test_defaults(self):
|
|
||||||
agenda = Agenda(short_agenda)
|
|
||||||
assert_equal(len(agenda.workloads), 3)
|
|
||||||
assert_equal(agenda.workloads[0].workload_name, 'antutu')
|
|
||||||
assert_equal(agenda.workloads[0].id, '1')
|
|
||||||
|
|
||||||
def test_default_id_assignment(self):
|
|
||||||
agenda = Agenda(default_ids_agenda)
|
|
||||||
assert_equal(agenda.workloads[0].id, '2')
|
|
||||||
assert_equal(agenda.workloads[3].id, '3')
|
|
||||||
|
|
||||||
def test_sections(self):
|
|
||||||
agenda = Agenda(sectioned_agenda)
|
|
||||||
assert_equal(agenda.sections[0].workloads[0].workload_name, 'antutu')
|
|
||||||
assert_equal(agenda.sections[1].runtime_parameters['dp'], 'three')
|
|
||||||
|
|
||||||
@raises(ConfigError)
|
@raises(ConfigError)
|
||||||
def test_dup_sections(self):
|
def test_dup_sections(self):
|
||||||
Agenda(dup_sectioned_agenda)
|
Agenda(dup_sectioned_agenda)
|
||||||
|
|
||||||
@raises(ConfigError)
|
@raises(SerializerSyntaxError)
|
||||||
def test_bad_syntax(self):
|
def test_bad_syntax(self):
|
||||||
Agenda(bad_syntax_agenda)
|
Agenda(bad_syntax_agenda)
|
||||||
|
292
wlauto/tests/test_configuration.py
Normal file
292
wlauto/tests/test_configuration.py
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
# pylint: disable=R0201
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from nose.tools import assert_equal, assert_is
|
||||||
|
from mock.mock import MagicMock, Mock
|
||||||
|
|
||||||
|
from wlauto.exceptions import ConfigError
|
||||||
|
from wlauto.core.configuration.tree import Node
|
||||||
|
from wlauto.core.configuration.configuration import (ConfigurationPoint, Configuration,
|
||||||
|
JobsConfiguration)
|
||||||
|
|
||||||
|
# A1
|
||||||
|
# / \
|
||||||
|
# B1 B2
|
||||||
|
# / \ / \
|
||||||
|
# C1 C2 C3 C4
|
||||||
|
# \
|
||||||
|
# D1
|
||||||
|
a1 = Node("A1")
|
||||||
|
b1 = a1.add_section("B1")
|
||||||
|
b2 = a1.add_section("B2")
|
||||||
|
c1 = b1.add_section("C1")
|
||||||
|
c2 = b1.add_section("C2")
|
||||||
|
c3 = b2.add_section("C3")
|
||||||
|
c4 = b2.add_section("C4")
|
||||||
|
d1 = c2.add_section("D1")
|
||||||
|
|
||||||
|
|
||||||
|
class NodeTest(TestCase):
|
||||||
|
|
||||||
|
def test_node(self):
|
||||||
|
node = Node(1)
|
||||||
|
assert_equal(node.config, 1)
|
||||||
|
assert_is(node.parent, None)
|
||||||
|
assert_equal(node.workloads, [])
|
||||||
|
assert_equal(node.children, [])
|
||||||
|
|
||||||
|
def test_add_workload(self):
|
||||||
|
node = Node(1)
|
||||||
|
node.add_workload(2)
|
||||||
|
assert_equal(node.workloads, [2])
|
||||||
|
|
||||||
|
def test_add_section(self):
|
||||||
|
node = Node(1)
|
||||||
|
new_node = node.add_section(2)
|
||||||
|
assert_equal(len(node.children), 1)
|
||||||
|
assert_is(node.children[0], new_node)
|
||||||
|
assert_is(new_node.parent, node)
|
||||||
|
assert_equal(node.is_leaf, False)
|
||||||
|
assert_equal(new_node.is_leaf, True)
|
||||||
|
|
||||||
|
def test_descendants(self):
|
||||||
|
for got, expected in zip(b1.descendants(), [c1, d1, c2]):
|
||||||
|
print "GOT:{} EXPECTED:{}".format(got.config, expected.config)
|
||||||
|
assert_is(got, expected)
|
||||||
|
print "----"
|
||||||
|
for got, expected in zip(a1.descendants(), [c1, d1, c2, b1, c3, c4, b2]):
|
||||||
|
print "GOT:{} EXPECTED:{}".format(got.config, expected.config)
|
||||||
|
assert_is(got, expected)
|
||||||
|
|
||||||
|
def test_ancestors(self):
|
||||||
|
for got, expected in zip(d1.ancestors(), [c2, b1, a1]):
|
||||||
|
print "GOT:{} EXPECTED:{}".format(got.config, expected.config)
|
||||||
|
assert_is(got, expected)
|
||||||
|
for _ in a1.ancestors():
|
||||||
|
raise Exception("A1 is the root, it shouldn't have ancestors")
|
||||||
|
|
||||||
|
def test_leaves(self):
|
||||||
|
for got, expected in zip(a1.leaves(), [c1, d1, c3, c4]):
|
||||||
|
print "GOT:{} EXPECTED:{}".format(got.config, expected.config)
|
||||||
|
assert_is(got, expected)
|
||||||
|
print "----"
|
||||||
|
for got, expected in zip(d1.leaves(), [d1]):
|
||||||
|
print "GOT:{} EXPECTED:{}".format(got.config, expected.config)
|
||||||
|
assert_is(got, expected)
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigurationPointTest(TestCase):
|
||||||
|
|
||||||
|
def test_match(self):
|
||||||
|
cp1 = ConfigurationPoint("test1", aliases=["foo", "bar"])
|
||||||
|
cp2 = ConfigurationPoint("test2", aliases=["fizz", "buzz"])
|
||||||
|
|
||||||
|
assert_equal(cp1.match("test1"), True)
|
||||||
|
assert_equal(cp1.match("foo"), True)
|
||||||
|
assert_equal(cp1.match("bar"), True)
|
||||||
|
assert_equal(cp1.match("fizz"), False)
|
||||||
|
assert_equal(cp1.match("NOT VALID"), False)
|
||||||
|
|
||||||
|
assert_equal(cp2.match("test2"), True)
|
||||||
|
assert_equal(cp2.match("fizz"), True)
|
||||||
|
assert_equal(cp2.match("buzz"), True)
|
||||||
|
assert_equal(cp2.match("foo"), False)
|
||||||
|
assert_equal(cp2.match("NOT VALID"), False)
|
||||||
|
|
||||||
|
def test_set_value(self):
|
||||||
|
cp1 = ConfigurationPoint("test", default="hello")
|
||||||
|
cp2 = ConfigurationPoint("test", mandatory=True)
|
||||||
|
cp3 = ConfigurationPoint("test", mandatory=True, default="Hello")
|
||||||
|
cp4 = ConfigurationPoint("test", default=["hello"], merge=True, kind=list)
|
||||||
|
cp5 = ConfigurationPoint("test", kind=int)
|
||||||
|
cp6 = ConfigurationPoint("test5", kind=list, allowed_values=[1, 2, 3, 4, 5])
|
||||||
|
|
||||||
|
mock = Mock()
|
||||||
|
mock.name = "ConfigurationPoint Unit Test"
|
||||||
|
|
||||||
|
# Testing defaults and basic functionality
|
||||||
|
cp1.set_value(mock)
|
||||||
|
assert_equal(mock.test, "hello")
|
||||||
|
cp1.set_value(mock, value="there")
|
||||||
|
assert_equal(mock.test, "there")
|
||||||
|
|
||||||
|
# Testing mandatory flag
|
||||||
|
err_msg = 'No values specified for mandatory parameter "test" in ' \
|
||||||
|
'ConfigurationPoint Unit Test'
|
||||||
|
with self.assertRaisesRegexp(ConfigError, err_msg):
|
||||||
|
cp2.set_value(mock)
|
||||||
|
cp3.set_value(mock) # Should ignore mandatory
|
||||||
|
assert_equal(mock.test, "Hello")
|
||||||
|
|
||||||
|
# Testing Merging - not in depth that is done in the unit test for merge_config
|
||||||
|
cp4.set_value(mock, value=["there"])
|
||||||
|
assert_equal(mock.test, ["Hello", "there"])
|
||||||
|
|
||||||
|
# Testing type conversion
|
||||||
|
cp5.set_value(mock, value="100")
|
||||||
|
assert_equal(isinstance(mock.test, int), True)
|
||||||
|
msg = 'Bad value "abc" for test; must be an integer'
|
||||||
|
with self.assertRaisesRegexp(ConfigError, msg):
|
||||||
|
cp5.set_value(mock, value="abc")
|
||||||
|
|
||||||
|
# Testing that validation is not called when no value is set
|
||||||
|
# if it is it will error because it cannot iterate over None
|
||||||
|
cp6.set_value(mock)
|
||||||
|
|
||||||
|
def test_validation(self):
|
||||||
|
def is_even(value):
|
||||||
|
if value % 2:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
cp1 = ConfigurationPoint("test", kind=int, allowed_values=[1, 2, 3, 4, 5])
|
||||||
|
cp2 = ConfigurationPoint("test", kind=list, allowed_values=[1, 2, 3, 4, 5])
|
||||||
|
cp3 = ConfigurationPoint("test", kind=int, constraint=is_even)
|
||||||
|
cp4 = ConfigurationPoint("test", kind=list, mandatory=True, allowed_values=[1, 99])
|
||||||
|
mock = MagicMock()
|
||||||
|
mock.name = "ConfigurationPoint Validation Unit Test"
|
||||||
|
|
||||||
|
# Test allowed values
|
||||||
|
cp1.validate_value(mock.name, 1)
|
||||||
|
with self.assertRaises(ConfigError):
|
||||||
|
cp1.validate_value(mock.name, 100)
|
||||||
|
with self.assertRaises(ConfigError):
|
||||||
|
cp1.validate_value(mock.name, [1, 2, 3])
|
||||||
|
|
||||||
|
# Test allowed values for lists
|
||||||
|
cp2.validate_value(mock.name, [1, 2, 3])
|
||||||
|
with self.assertRaises(ConfigError):
|
||||||
|
cp2.validate_value(mock.name, [1, 2, 100])
|
||||||
|
|
||||||
|
# Test constraints
|
||||||
|
cp3.validate_value(mock.name, 2)
|
||||||
|
cp3.validate_value(mock.name, 4)
|
||||||
|
cp3.validate_value(mock.name, 6)
|
||||||
|
msg = '"3" failed constraint validation for "test" in "ConfigurationPoint' \
|
||||||
|
' Validation Unit Test".'
|
||||||
|
with self.assertRaisesRegexp(ConfigError, msg):
|
||||||
|
cp3.validate_value(mock.name, 3)
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
ConfigurationPoint("test", constraint=100)
|
||||||
|
|
||||||
|
# Test "validate" methods
|
||||||
|
mock.test = None
|
||||||
|
# Mandatory config point not set
|
||||||
|
with self.assertRaises(ConfigError):
|
||||||
|
cp4.validate(mock)
|
||||||
|
cp1.validate(mock) # cp1 doesnt have mandatory set
|
||||||
|
cp4.set_value(mock, value=[99])
|
||||||
|
cp4.validate(mock)
|
||||||
|
|
||||||
|
def test_get_type_name(self):
|
||||||
|
def dummy():
|
||||||
|
pass
|
||||||
|
types = [str, list, int, dummy]
|
||||||
|
names = ["str", "list", "integer", "dummy"]
|
||||||
|
for kind, name in zip(types, names):
|
||||||
|
cp = ConfigurationPoint("test", kind=kind)
|
||||||
|
assert_equal(cp.get_type_name(), name)
|
||||||
|
|
||||||
|
|
||||||
|
# Subclass just to add some config points to use in testing
|
||||||
|
class TestConfiguration(Configuration):
|
||||||
|
name = "Test Config"
|
||||||
|
__configuration = [
|
||||||
|
ConfigurationPoint("test1", default="hello"),
|
||||||
|
ConfigurationPoint("test2", mandatory=True),
|
||||||
|
ConfigurationPoint("test3", default=["hello"], merge=True, kind=list),
|
||||||
|
ConfigurationPoint("test4", kind=int, default=123),
|
||||||
|
ConfigurationPoint("test5", kind=list, allowed_values=[1, 2, 3, 4, 5]),
|
||||||
|
]
|
||||||
|
configuration = {cp.name: cp for cp in __configuration}
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigurationTest(TestCase):
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
# Test loading defaults
|
||||||
|
cfg = TestConfiguration()
|
||||||
|
expected = {
|
||||||
|
"test1": "hello",
|
||||||
|
"test2": None,
|
||||||
|
"test3": ["hello"],
|
||||||
|
"test4": 123,
|
||||||
|
"test5": None,
|
||||||
|
}
|
||||||
|
# If a cfg point is not set an attribute with value None should still be created
|
||||||
|
for name, value in expected.iteritems():
|
||||||
|
assert_equal(getattr(cfg, name), value)
|
||||||
|
|
||||||
|
# Testing pre finalization "set"
|
||||||
|
cfg.set("test1", "there")
|
||||||
|
assert_equal(cfg.test1, "there") # pylint: disable=E1101
|
||||||
|
with self.assertRaisesRegexp(ConfigError, 'Unknown Test Config configuration "nope"'):
|
||||||
|
cfg.set("nope", 123)
|
||||||
|
|
||||||
|
# Testing setting values from a dict
|
||||||
|
new_values = {
|
||||||
|
"test1": "This",
|
||||||
|
"test2": "is",
|
||||||
|
"test3": ["a"],
|
||||||
|
"test4": 7357,
|
||||||
|
"test5": [5],
|
||||||
|
}
|
||||||
|
cfg.update_config(new_values)
|
||||||
|
new_values["test3"] = ["hello", "a"] # This cfg point has merge == True
|
||||||
|
for k, v in new_values.iteritems():
|
||||||
|
assert_equal(getattr(cfg, k), v)
|
||||||
|
|
||||||
|
# Test finalization
|
||||||
|
|
||||||
|
# This is a madatory cfg point so finalization should fail
|
||||||
|
cfg.configuration["test2"].set_value(cfg, value=None, check_mandatory=False)
|
||||||
|
msg = 'No value specified for mandatory parameter "test2" in Test Config'
|
||||||
|
with self.assertRaisesRegexp(ConfigError, msg):
|
||||||
|
cfg.finalize()
|
||||||
|
assert_equal(cfg._finalized, False) # pylint: disable=W0212
|
||||||
|
|
||||||
|
# Valid finalization
|
||||||
|
cfg.set("test2", "is")
|
||||||
|
cfg.finalize()
|
||||||
|
assert_equal(cfg._finalized, True) # pylint: disable=W0212
|
||||||
|
|
||||||
|
# post finalization set should failed
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
cfg.set("test2", "is")
|
||||||
|
|
||||||
|
|
||||||
|
class JobsConfigurationTest(TestCase):
|
||||||
|
|
||||||
|
def test_set_global_config(self):
|
||||||
|
jc = JobsConfiguration()
|
||||||
|
|
||||||
|
jc.set_global_config("workload_name", "test")
|
||||||
|
assert_equal(jc.root_node.config.workload_name, "test")
|
||||||
|
# Aliased names (e.g. "name") should be resolved by the parser
|
||||||
|
# before being passed here.
|
||||||
|
|
||||||
|
with self.assertRaises(ConfigError):
|
||||||
|
jc.set_global_config("unknown", "test")
|
||||||
|
|
||||||
|
jc.finalise_global_config()
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
jc.set_global_config("workload_name", "test")
|
||||||
|
|
||||||
|
def test_tree_manipulation(self):
|
||||||
|
jc = JobsConfiguration()
|
||||||
|
|
||||||
|
workloads = [123, "hello", True]
|
||||||
|
for w in workloads:
|
||||||
|
jc.add_workload(w)
|
||||||
|
assert_equal(jc.root_node.workloads, workloads)
|
||||||
|
|
||||||
|
jc.add_section("section", workloads)
|
||||||
|
assert_equal(jc.root_node.children[0].config, "section")
|
||||||
|
assert_equal(jc.root_node.workloads, workloads)
|
||||||
|
|
||||||
|
def test_generate_job_specs(self):
|
||||||
|
|
||||||
|
# disable_instruments
|
||||||
|
# only_run_ids
|
231
wlauto/tests/test_parsers.py
Normal file
231
wlauto/tests/test_parsers.py
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
import os
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from nose.tools import assert_equal # pylint: disable=E0611
|
||||||
|
from mock.mock import Mock, MagicMock, call
|
||||||
|
|
||||||
|
from wlauto.exceptions import ConfigError
|
||||||
|
from wlauto.core.configuration.parsers import (get_aliased_param,
|
||||||
|
_load_file, ConfigParser, EnvironmentVarsParser,
|
||||||
|
CommandLineArgsParser)
|
||||||
|
from wlauto.core.configuration import (WAConfiguration, RunConfiguration, JobsConfiguration,
|
||||||
|
PluginCache)
|
||||||
|
from wlauto.utils.types import toggle_set
|
||||||
|
|
||||||
|
|
||||||
|
class TestFunctions(TestCase):
|
||||||
|
|
||||||
|
def test_load_file(self):
|
||||||
|
# This does not test read_pod
|
||||||
|
|
||||||
|
# Non-existant file
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
_load_file("THIS-IS-NOT-A-FILE", "test file")
|
||||||
|
base_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
# Top level entry not a dict
|
||||||
|
with self.assertRaisesRegexp(ConfigError, r".+ does not contain a valid test file structure; top level must be a dict\."):
|
||||||
|
_load_file(os.path.join(base_path, "data", "test-agenda-not-dict.yaml"), "test file")
|
||||||
|
|
||||||
|
# Yaml syntax error
|
||||||
|
with self.assertRaisesRegexp(ConfigError, r"Error parsing test file .+: Syntax Error on line 1"):
|
||||||
|
_load_file(os.path.join(base_path, "data", "test-agenda-bad-syntax.yaml"), "test file")
|
||||||
|
|
||||||
|
# Ideal case
|
||||||
|
_load_file(os.path.join(base_path, "data", "test-agenda.yaml"), "test file")
|
||||||
|
|
||||||
|
def test_get_aliased_param(self):
|
||||||
|
# Ideal case
|
||||||
|
d_correct = {"workload_parameters": [1, 2, 3],
|
||||||
|
"instruments": [2, 3, 4],
|
||||||
|
"some_other_param": 1234}
|
||||||
|
assert_equal(get_aliased_param(d_correct, [
|
||||||
|
'workload_parameters',
|
||||||
|
'workload_params',
|
||||||
|
'params'
|
||||||
|
], default=[], pop=False), [1, 2, 3])
|
||||||
|
|
||||||
|
# Two aliases for the same parameter given
|
||||||
|
d_duplicate = {"workload_parameters": [1, 2, 3],
|
||||||
|
"workload_params": [2, 3, 4]}
|
||||||
|
with self.assertRaises(ConfigError):
|
||||||
|
get_aliased_param(d_duplicate, [
|
||||||
|
'workload_parameters',
|
||||||
|
'workload_params',
|
||||||
|
'params'
|
||||||
|
], default=[])
|
||||||
|
|
||||||
|
# Empty dict
|
||||||
|
d_none = {}
|
||||||
|
assert_equal(get_aliased_param(d_none, [
|
||||||
|
'workload_parameters',
|
||||||
|
'workload_params',
|
||||||
|
'params'
|
||||||
|
], default=[]), [])
|
||||||
|
|
||||||
|
# Aliased parameter not present in dict
|
||||||
|
d_not_present = {"instruments": [2, 3, 4],
|
||||||
|
"some_other_param": 1234}
|
||||||
|
assert_equal(get_aliased_param(d_not_present, [
|
||||||
|
'workload_parameters',
|
||||||
|
'workload_params',
|
||||||
|
'params'
|
||||||
|
], default=1), 1)
|
||||||
|
|
||||||
|
# Testing pop functionality
|
||||||
|
assert_equal("workload_parameters" in d_correct, True)
|
||||||
|
get_aliased_param(d_correct, [
|
||||||
|
'workload_parameters',
|
||||||
|
'workload_params',
|
||||||
|
'params'
|
||||||
|
], default=[])
|
||||||
|
assert_equal("workload_parameters" in d_correct, False)
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfigParser(TestCase):
|
||||||
|
|
||||||
|
def test_error_cases(self):
|
||||||
|
wa_config = Mock(spec=WAConfiguration)
|
||||||
|
wa_config.configuration = WAConfiguration.configuration
|
||||||
|
run_config = Mock(spec=RunConfiguration)
|
||||||
|
run_config.configuration = RunConfiguration.configuration
|
||||||
|
config_parser = ConfigParser(wa_config,
|
||||||
|
run_config,
|
||||||
|
Mock(spec=JobsConfiguration),
|
||||||
|
Mock(spec=PluginCache))
|
||||||
|
|
||||||
|
# "run_name" can only be in agenda config sections
|
||||||
|
#' and is handled by AgendaParser
|
||||||
|
err = 'Error in "Unit test":\n' \
|
||||||
|
'"run_name" can only be specified in the config section of an agenda'
|
||||||
|
with self.assertRaisesRegexp(ConfigError, err):
|
||||||
|
config_parser.load({"run_name": "test"}, "Unit test")
|
||||||
|
|
||||||
|
# Instrument and result_processor lists in the same config cannot
|
||||||
|
# have conflicting entries.
|
||||||
|
err = 'Error in "Unit test":\n' \
|
||||||
|
'"instrumentation" and "result_processors" have conflicting entries:'
|
||||||
|
with self.assertRaisesRegexp(ConfigError, err):
|
||||||
|
config_parser.load({"instruments": ["one", "two", "three"],
|
||||||
|
"result_processors": ["~one", "~two", "~three"]},
|
||||||
|
"Unit test")
|
||||||
|
|
||||||
|
def test_config_points(self):
|
||||||
|
wa_config = Mock(spec=WAConfiguration)
|
||||||
|
wa_config.configuration = WAConfiguration.configuration
|
||||||
|
|
||||||
|
run_config = Mock(spec=RunConfiguration)
|
||||||
|
run_config.configuration = RunConfiguration.configuration
|
||||||
|
|
||||||
|
jobs_config = Mock(spec=JobsConfiguration)
|
||||||
|
plugin_cache = Mock(spec=PluginCache)
|
||||||
|
config_parser = ConfigParser(wa_config, run_config, jobs_config, plugin_cache)
|
||||||
|
|
||||||
|
cfg = {
|
||||||
|
"assets_repository": "/somewhere/",
|
||||||
|
"logging": "verbose",
|
||||||
|
"project": "some project",
|
||||||
|
"project_stage": "stage 1",
|
||||||
|
"iterations": 9001,
|
||||||
|
"workload_name": "name"
|
||||||
|
}
|
||||||
|
config_parser.load(cfg, "Unit test")
|
||||||
|
wa_config.set.assert_has_calls([
|
||||||
|
call("assets_repository", "/somewhere/"),
|
||||||
|
call("logging", "verbose")
|
||||||
|
], any_order=True)
|
||||||
|
run_config.set.assert_has_calls([
|
||||||
|
call("project", "some project"),
|
||||||
|
call("project_stage", "stage 1")
|
||||||
|
], any_order=True)
|
||||||
|
print jobs_config.set_global_config.call_args_list
|
||||||
|
jobs_config.set_global_config.assert_has_calls([
|
||||||
|
call("iterations", 9001),
|
||||||
|
call("workload_name", "name"),
|
||||||
|
call("instrumentation", toggle_set()),
|
||||||
|
call("instrumentation", toggle_set())
|
||||||
|
], any_order=True)
|
||||||
|
|
||||||
|
# Test setting global instruments including a non-conflicting duplicate ("two")
|
||||||
|
jobs_config.reset_mock()
|
||||||
|
instruments_and_result_processors = {
|
||||||
|
"instruments": ["one", "two"],
|
||||||
|
"result_processors": ["two", "three"]
|
||||||
|
}
|
||||||
|
config_parser.load(instruments_and_result_processors, "Unit test")
|
||||||
|
jobs_config.set_global_config.assert_has_calls([
|
||||||
|
call("instrumentation", toggle_set(["one", "two"])),
|
||||||
|
call("instrumentation", toggle_set(["two", "three"]))
|
||||||
|
], any_order=True)
|
||||||
|
|
||||||
|
# Testing a empty config
|
||||||
|
jobs_config.reset_mock()
|
||||||
|
config_parser.load({}, "Unit test")
|
||||||
|
jobs_config.set_global_config.assert_has_calls([], any_order=True)
|
||||||
|
wa_config.set.assert_has_calls([], any_order=True)
|
||||||
|
run_config.set.assert_has_calls([], any_order=True)
|
||||||
|
|
||||||
|
|
||||||
|
class TestEnvironmentVarsParser(TestCase):
|
||||||
|
|
||||||
|
def test_environmentvarsparser(self):
|
||||||
|
wa_config = Mock(spec=WAConfiguration)
|
||||||
|
calls = [call('user_directory', '/testdir'),
|
||||||
|
call('plugin_paths', ['/test', '/some/other/path', '/testy/mc/test/face'])]
|
||||||
|
|
||||||
|
# Valid env vars
|
||||||
|
valid_environ = {"WA_USER_DIRECTORY": "/testdir",
|
||||||
|
"WA_PLUGIN_PATHS": "/test:/some/other/path:/testy/mc/test/face"}
|
||||||
|
EnvironmentVarsParser(wa_config, valid_environ)
|
||||||
|
wa_config.set.assert_has_calls(calls)
|
||||||
|
|
||||||
|
# Alternative env var name
|
||||||
|
wa_config.reset_mock()
|
||||||
|
alt_valid_environ = {"WA_USER_DIRECTORY": "/testdir",
|
||||||
|
"WA_EXTENSION_PATHS": "/test:/some/other/path:/testy/mc/test/face"}
|
||||||
|
EnvironmentVarsParser(wa_config, alt_valid_environ)
|
||||||
|
wa_config.set.assert_has_calls(calls)
|
||||||
|
|
||||||
|
# Test that WA_EXTENSION_PATHS gets merged with WA_PLUGIN_PATHS.
|
||||||
|
# Also checks that other enviroment variables don't cause errors
|
||||||
|
wa_config.reset_mock()
|
||||||
|
calls = [call('user_directory', '/testdir'),
|
||||||
|
call('plugin_paths', ['/test', '/some/other/path']),
|
||||||
|
call('plugin_paths', ['/testy/mc/test/face'])]
|
||||||
|
ext_and_plgin = {"WA_USER_DIRECTORY": "/testdir",
|
||||||
|
"WA_PLUGIN_PATHS": "/test:/some/other/path",
|
||||||
|
"WA_EXTENSION_PATHS": "/testy/mc/test/face",
|
||||||
|
"RANDOM_VAR": "random_value"}
|
||||||
|
EnvironmentVarsParser(wa_config, ext_and_plgin)
|
||||||
|
# If any_order=True then the calls can be in any order, but they must all appear
|
||||||
|
wa_config.set.assert_has_calls(calls, any_order=True)
|
||||||
|
|
||||||
|
# No WA enviroment variables present
|
||||||
|
wa_config.reset_mock()
|
||||||
|
EnvironmentVarsParser(wa_config, {"RANDOM_VAR": "random_value"})
|
||||||
|
wa_config.set.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
class TestCommandLineArgsParser(TestCase):
|
||||||
|
wa_config = Mock(spec=WAConfiguration)
|
||||||
|
run_config = Mock(spec=RunConfiguration)
|
||||||
|
jobs_config = Mock(spec=JobsConfiguration)
|
||||||
|
|
||||||
|
cmd_args = MagicMock(
|
||||||
|
verbosity=1,
|
||||||
|
output_directory="my_results",
|
||||||
|
instruments_to_disable=["abc", "def", "ghi"],
|
||||||
|
only_run_ids=["wk1", "s1_wk4"],
|
||||||
|
some_other_setting="value123"
|
||||||
|
)
|
||||||
|
CommandLineArgsParser(cmd_args, wa_config, run_config, jobs_config)
|
||||||
|
wa_config.set.assert_has_calls([call("verbosity", 1)], any_order=True)
|
||||||
|
run_config.set.assert_has_calls([call("output_directory", "my_results")], any_order=True)
|
||||||
|
jobs_config.disable_instruments.assert_has_calls([
|
||||||
|
call(toggle_set(["~abc", "~def", "~ghi"]))
|
||||||
|
], any_order=True)
|
||||||
|
jobs_config.only_run_ids.assert_has_calls([call(["wk1", "s1_wk4"])], any_order=True)
|
||||||
|
|
||||||
|
|
||||||
|
class TestAgendaParser(TestCase):
|
||||||
|
pass
|
@ -21,7 +21,7 @@ from nose.tools import raises, assert_equal, assert_not_equal # pylint: disable
|
|||||||
|
|
||||||
from wlauto.utils.android import check_output
|
from wlauto.utils.android import check_output
|
||||||
from wlauto.utils.misc import merge_dicts, merge_lists, TimeoutError
|
from wlauto.utils.misc import merge_dicts, merge_lists, TimeoutError
|
||||||
from wlauto.utils.types import list_or_integer, list_or_bool, caseless_string, arguments, enable_disable_list
|
from wlauto.utils.types import list_or_integer, list_or_bool, caseless_string, arguments, toggle_set
|
||||||
|
|
||||||
|
|
||||||
class TestCheckOutput(TestCase):
|
class TestCheckOutput(TestCase):
|
||||||
@ -89,10 +89,10 @@ class TestTypes(TestCase):
|
|||||||
['--foo', '7', '--bar', 'fizz buzz'])
|
['--foo', '7', '--bar', 'fizz buzz'])
|
||||||
assert_equal(arguments(['test', 42]), ['test', '42'])
|
assert_equal(arguments(['test', 42]), ['test', '42'])
|
||||||
|
|
||||||
def enable_disable_list_test():
|
def toggle_set_test():
|
||||||
|
|
||||||
a = enable_disable_list(['qaz', 'qwert', 'asd', '~fgh', '~seb'])
|
a = toggle_set(['qaz', 'qwert', 'asd', '~fgh', '~seb'])
|
||||||
b = enable_disable_list(['qaz', 'xyz', '~asd', 'fgh', '~seb'])
|
b = toggle_set(['qaz', 'xyz', '~asd', 'fgh', '~seb'])
|
||||||
|
|
||||||
a_into_b = ['qaz', 'xyz', '~seb', 'qwert', 'asd', '~fgh']
|
a_into_b = ['qaz', 'xyz', '~seb', 'qwert', 'asd', '~fgh']
|
||||||
assert_equal(a.merge_into(b), a_into_b)
|
assert_equal(a.merge_into(b), a_into_b)
|
||||||
@ -104,3 +104,6 @@ class TestTypes(TestCase):
|
|||||||
|
|
||||||
assert_equal(a.values(), ['qaz', 'qwert', 'asd'])
|
assert_equal(a.values(), ['qaz', 'qwert', 'asd'])
|
||||||
assert_equal(b.merge_with(a).values(), ['qaz', 'xyz', 'qwert', 'asd'])
|
assert_equal(b.merge_with(a).values(), ['qaz', 'xyz', 'qwert', 'asd'])
|
||||||
|
|
||||||
|
assert_equal(a.values(), ['qaz', 'qwert', 'asd'])
|
||||||
|
assert_equal(a.conflicts_with(b), ['~asd', '~fgh'])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user