639 lines
15 KiB
Python
Executable file
639 lines
15 KiB
Python
Executable file
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
|
#
|
|
# 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.
|
|
#
|
|
|
|
import unittest
|
|
import sys
|
|
from pyparsing import ParseException
|
|
from pyparsing import restOfLine
|
|
|
|
try:
|
|
import fragments
|
|
except ImportError:
|
|
sys.path.append('../')
|
|
import fragments
|
|
|
|
from sdkconfig import SDKConfig
|
|
|
|
|
|
class FragmentTest(unittest.TestCase):
|
|
|
|
def parse(self, text):
|
|
self.parser.ignore("#" + restOfLine)
|
|
fragment = self.parser.parseString(text, parseAll=True)
|
|
return fragment[0]
|
|
|
|
|
|
class SectionsTest(FragmentTest):
|
|
|
|
def setUp(self):
|
|
self.parser = fragments.Sections.get_fragment_grammar()
|
|
|
|
def test_valid_entries(self):
|
|
valid_entries = """
|
|
[sections:test]
|
|
entries:
|
|
.section1
|
|
.section2
|
|
|
|
# Section 3 should not exist
|
|
# section3
|
|
.section4
|
|
|
|
# This is a comment
|
|
|
|
.section5
|
|
"""
|
|
|
|
sections = self.parse(valid_entries)
|
|
|
|
self.assertEqual("test", sections.name)
|
|
|
|
entries = sections.entries
|
|
|
|
expected = {
|
|
".section1",
|
|
".section2",
|
|
".section4",
|
|
".section5"
|
|
}
|
|
|
|
self.assertEqual(set(entries), expected)
|
|
|
|
def test_blank_entries(self):
|
|
blank_entries = """
|
|
[sections:test]
|
|
entries:
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(blank_entries)
|
|
|
|
def test_invalid_names(self):
|
|
with_spaces = """
|
|
[sections:invalid name 1]
|
|
entries:
|
|
"""
|
|
|
|
begins_with_number = """
|
|
[sections:2invalid_name]
|
|
entries:
|
|
"""
|
|
|
|
with_special_character = """
|
|
[sections:invalid_name~]
|
|
entries:
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(with_spaces)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(begins_with_number)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(with_special_character)
|
|
|
|
def test_non_existent_entries(self):
|
|
misspelled_entries_field = """
|
|
[sections:test]
|
|
entrie:
|
|
.section1
|
|
"""
|
|
|
|
missing_entries_field = """
|
|
[sections:test]
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(misspelled_entries_field)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(missing_entries_field)
|
|
|
|
def test_duplicate_entries(self):
|
|
duplicate_entries = """
|
|
[sections:test]
|
|
entries:
|
|
.section1
|
|
.section3
|
|
.section1
|
|
.section1
|
|
.section2
|
|
.section3
|
|
.section1
|
|
"""
|
|
|
|
sections = self.parse(duplicate_entries)
|
|
|
|
entries = sections.entries
|
|
|
|
expected = {
|
|
".section1",
|
|
".section2",
|
|
".section3",
|
|
}
|
|
|
|
self.assertEqual(set(entries), expected)
|
|
|
|
|
|
class SchemeTest(FragmentTest):
|
|
|
|
def setUp(self):
|
|
self.parser = fragments.Scheme.get_fragment_grammar()
|
|
|
|
def test_valid_entries(self):
|
|
valid_entries = """
|
|
[scheme:test]
|
|
entries:
|
|
sections1 -> target1
|
|
sections2 -> target2
|
|
"""
|
|
|
|
scheme = self.parse(valid_entries)
|
|
|
|
entries = scheme.entries
|
|
|
|
expected = {
|
|
("sections1", "target1"),
|
|
("sections2", "target2")
|
|
}
|
|
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_duplicate_same_mapping(self):
|
|
duplicate_entries = """
|
|
[scheme:duplicate_same_mapping]
|
|
entries:
|
|
sections1 -> target1
|
|
sections2 -> target2
|
|
sections1 -> target1
|
|
"""
|
|
|
|
scheme = self.parse(duplicate_entries)
|
|
|
|
entries = scheme.entries
|
|
|
|
expected = {
|
|
("sections1", "target1"),
|
|
("sections2", "target2")
|
|
}
|
|
|
|
self.assertEqual(len(entries), 2)
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_invalid_separator(self):
|
|
wrong_character = """
|
|
[scheme:test]
|
|
entries:
|
|
sections1, target1
|
|
"""
|
|
|
|
single_word = """
|
|
[scheme:test]
|
|
entries:
|
|
sections1
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(wrong_character)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(single_word)
|
|
|
|
def test_blank_entries(self):
|
|
blank_entries = """
|
|
[scheme:test]
|
|
entries:
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(blank_entries)
|
|
|
|
def test_non_existent_entries(self):
|
|
misspelled_entries_field = """
|
|
[scheme:test]
|
|
entrie:
|
|
section -> target
|
|
"""
|
|
|
|
missing_entries_field = """
|
|
[scheme:test]
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(misspelled_entries_field)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(missing_entries_field)
|
|
|
|
|
|
class MappingTest(FragmentTest):
|
|
|
|
def setUp(self):
|
|
self.parser = fragments.Mapping.get_fragment_grammar()
|
|
|
|
def parse_expression(self, expression):
|
|
parser = SDKConfig.get_expression_grammar()
|
|
return parser.parseString(expression, parseAll=True)
|
|
|
|
def test_valid_grammar(self):
|
|
valid_entries = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
obj:symbol (noflash)
|
|
# Comments should not matter
|
|
obj (noflash)
|
|
# Nor should whitespace
|
|
obj : symbol_2 ( noflash )
|
|
obj_2 ( noflash )
|
|
* (noflash)
|
|
"""
|
|
|
|
mapping = self.parse(valid_entries)
|
|
|
|
self.assertEqual("lib.a", mapping.archive)
|
|
self.assertEqual("lib_a", mapping.name)
|
|
|
|
entries = mapping.entries
|
|
|
|
expected = [("default", {
|
|
("obj", "symbol", "noflash"),
|
|
("obj", None, "noflash"),
|
|
("obj", "symbol_2", "noflash"),
|
|
("obj_2", None, "noflash"),
|
|
("*", None, "noflash")
|
|
})]
|
|
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_invalid_grammar(self):
|
|
with_fragment_name = """
|
|
[mapping:name]
|
|
archive: lib.a
|
|
entries:
|
|
obj:symbol (noflash)
|
|
"""
|
|
|
|
missing_archive = """
|
|
[mapping:name]
|
|
entries:
|
|
obj:symbol (noflash)
|
|
"""
|
|
|
|
misspelled_archive = """
|
|
[mapping:name]
|
|
archi: lib.a
|
|
entries:
|
|
obj:symbol (noflash)
|
|
"""
|
|
|
|
missing_entries = """
|
|
[mapping]
|
|
archive: lib.a
|
|
"""
|
|
|
|
misspelled_entries = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entrie:
|
|
obj:symbol (noflash)
|
|
"""
|
|
|
|
missing_symbols = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
obj: (noflash)
|
|
"""
|
|
|
|
missing_scheme_1 = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
obj: ()
|
|
"""
|
|
|
|
missing_scheme_2 = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
obj:symbol
|
|
"""
|
|
|
|
missing_entity = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
(noflash)
|
|
"""
|
|
|
|
wilcard_symbol = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
obj:* (noflash)
|
|
"""
|
|
|
|
empty_object_with_symbol = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
:symbol (noflash)
|
|
"""
|
|
|
|
wildcard_object_with_symbol = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
*:symbol (noflash)
|
|
"""
|
|
|
|
empty_definition = """
|
|
[mapping]
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(with_fragment_name)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(missing_archive)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(misspelled_archive)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(missing_entries)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(misspelled_entries)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(missing_symbols)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(missing_scheme_1)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(missing_scheme_2)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(missing_entity)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(wilcard_symbol)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(empty_object_with_symbol)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(wildcard_object_with_symbol)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(empty_definition)
|
|
|
|
def test_explicit_blank_default_w_others(self):
|
|
expl_blnk_w_oth = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: CONFIG_A = y
|
|
obj_a (noflash)
|
|
: default
|
|
"""
|
|
|
|
mapping = self.parse(expl_blnk_w_oth)
|
|
|
|
entries = mapping.entries
|
|
|
|
expected = [(entries[0][0], {
|
|
("obj_a", None, "noflash"),
|
|
}),
|
|
("default", set())]
|
|
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_implicit_blank_default_w_others(self):
|
|
impl_blnk_w_oth = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: CONFIG_A = y
|
|
obj_a (noflash)
|
|
"""
|
|
|
|
mapping = self.parse(impl_blnk_w_oth)
|
|
|
|
entries = mapping.entries
|
|
|
|
expected = [(entries[0][0], {
|
|
("obj_a", None, "noflash"),
|
|
}),
|
|
("default", set())]
|
|
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_explicit_blank_default(self):
|
|
expl_blnk_def = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: default
|
|
"""
|
|
mapping = self.parse(expl_blnk_def)
|
|
entries = mapping.entries
|
|
expected = [("default", set())]
|
|
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_implicit_blank_default(self):
|
|
impl_blnk_def = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: default
|
|
"""
|
|
mapping = self.parse(impl_blnk_def)
|
|
entries = mapping.entries
|
|
expected = [("default", set())]
|
|
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_multiple_entries(self):
|
|
multiple_entries = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: CONFIG_A = y
|
|
obj_a1 (noflash)
|
|
obj_a2 (noflash)
|
|
: CONFIG_B = y
|
|
obj_b1 (noflash)
|
|
obj_b2 (noflash)
|
|
obj_b3 (noflash)
|
|
: CONFIG_C = y
|
|
obj_c1 (noflash)
|
|
"""
|
|
|
|
mapping = self.parse(multiple_entries)
|
|
|
|
entries = mapping.entries
|
|
|
|
expected = [(entries[0][0], {
|
|
("obj_a1", None, "noflash"),
|
|
("obj_a2", None, "noflash"),
|
|
}),
|
|
(entries[1][0], {
|
|
("obj_b1", None, "noflash"),
|
|
("obj_b2", None, "noflash"),
|
|
("obj_b3", None, "noflash"),
|
|
}),
|
|
(entries[2][0], {
|
|
("obj_c1", None, "noflash"),
|
|
}),
|
|
("default", set())]
|
|
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_blank_entries(self):
|
|
blank_entries = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: CONFIG_A = y
|
|
obj_a (noflash)
|
|
: CONFIG_B = y
|
|
: CONFIG_C = y
|
|
obj_c (noflash)
|
|
: CONFIG_D = y
|
|
: CONFIG_E = y
|
|
: default
|
|
obj (noflash)
|
|
"""
|
|
|
|
mapping = self.parse(blank_entries)
|
|
|
|
entries = mapping.entries
|
|
|
|
expected = [(entries[0][0], {
|
|
("obj_a", None, "noflash")
|
|
}),
|
|
(entries[1][0], set()),
|
|
(entries[2][0], {
|
|
("obj_c", None, "noflash")
|
|
}),
|
|
(entries[3][0], set()),
|
|
(entries[4][0], set()),
|
|
("default", {
|
|
("obj", None, "noflash")
|
|
})]
|
|
|
|
self.assertEqual(entries, expected)
|
|
|
|
def test_blank_first_condition(self):
|
|
blank_first_condition = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
obj_a (noflash)
|
|
: CONFIG_B = y
|
|
obj_b (noflash)
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(blank_first_condition)
|
|
|
|
def test_nonlast_default(self):
|
|
nonlast_default_1 = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: default
|
|
obj_a (noflash)
|
|
: CONFIG_A = y
|
|
obj_A (noflash)
|
|
"""
|
|
|
|
nonlast_default_2 = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: CONFIG_A = y
|
|
obj_A (noflash)
|
|
: default
|
|
obj_a (noflash)
|
|
: CONFIG_B = y
|
|
obj_B (noflash)
|
|
"""
|
|
|
|
nonlast_default_3 = """
|
|
[mapping]
|
|
archive: lib.a
|
|
entries:
|
|
: CONFIG_A = y
|
|
obj_A (noflash)
|
|
:
|
|
obj_a (noflash)
|
|
: CONFIG_B = y
|
|
obj_B (noflash)
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(nonlast_default_1)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(nonlast_default_2)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(nonlast_default_3)
|
|
|
|
def test_duplicate_default(self):
|
|
duplicate_default_1 = """
|
|
archive: lib.a
|
|
entries:
|
|
: CONFIG_A = y
|
|
obj_A (noflash)
|
|
: default
|
|
obj_a (noflash)
|
|
: CONFIG_B = y
|
|
obj_B (noflash)
|
|
: default
|
|
obj_a (noflash)
|
|
"""
|
|
|
|
duplicate_default_2 = """
|
|
archive: lib.a
|
|
entries:
|
|
: CONFIG_A = y
|
|
obj_A (noflash)
|
|
: CONFIG_B = y
|
|
obj_a (noflash)
|
|
: default
|
|
obj_B (noflash)
|
|
:
|
|
obj_a (noflash)
|
|
"""
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(duplicate_default_1)
|
|
|
|
with self.assertRaises(ParseException):
|
|
self.parse(duplicate_default_2)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|