xref: /OK3568_Linux_fs/kernel/tools/testing/kunit/kunit_config.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun#
3*4882a593Smuzhiyun# Builds a .config from a kunitconfig.
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun# Copyright (C) 2019, Google LLC.
6*4882a593Smuzhiyun# Author: Felix Guo <felixguoxiuping@gmail.com>
7*4882a593Smuzhiyun# Author: Brendan Higgins <brendanhiggins@google.com>
8*4882a593Smuzhiyun
9*4882a593Smuzhiyunimport collections
10*4882a593Smuzhiyunimport re
11*4882a593Smuzhiyun
12*4882a593SmuzhiyunCONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
13*4882a593SmuzhiyunCONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$'
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunKconfigEntryBase = collections.namedtuple('KconfigEntryBase', ['name', 'value'])
16*4882a593Smuzhiyun
17*4882a593Smuzhiyunclass KconfigEntry(KconfigEntryBase):
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun	def __str__(self) -> str:
20*4882a593Smuzhiyun		if self.value == 'n':
21*4882a593Smuzhiyun			return r'# CONFIG_%s is not set' % (self.name)
22*4882a593Smuzhiyun		else:
23*4882a593Smuzhiyun			return r'CONFIG_%s=%s' % (self.name, self.value)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun
26*4882a593Smuzhiyunclass KconfigParseError(Exception):
27*4882a593Smuzhiyun	"""Error parsing Kconfig defconfig or .config."""
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun
30*4882a593Smuzhiyunclass Kconfig(object):
31*4882a593Smuzhiyun	"""Represents defconfig or .config specified using the Kconfig language."""
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun	def __init__(self):
34*4882a593Smuzhiyun		self._entries = []
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun	def entries(self):
37*4882a593Smuzhiyun		return set(self._entries)
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun	def add_entry(self, entry: KconfigEntry) -> None:
40*4882a593Smuzhiyun		self._entries.append(entry)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun	def is_subset_of(self, other: 'Kconfig') -> bool:
43*4882a593Smuzhiyun		for a in self.entries():
44*4882a593Smuzhiyun			found = False
45*4882a593Smuzhiyun			for b in other.entries():
46*4882a593Smuzhiyun				if a.name != b.name:
47*4882a593Smuzhiyun					continue
48*4882a593Smuzhiyun				if a.value != b.value:
49*4882a593Smuzhiyun					return False
50*4882a593Smuzhiyun				found = True
51*4882a593Smuzhiyun			if a.value != 'n' and found == False:
52*4882a593Smuzhiyun				return False
53*4882a593Smuzhiyun		return True
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun	def write_to_file(self, path: str) -> None:
56*4882a593Smuzhiyun		with open(path, 'w') as f:
57*4882a593Smuzhiyun			for entry in self.entries():
58*4882a593Smuzhiyun				f.write(str(entry) + '\n')
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun	def parse_from_string(self, blob: str) -> None:
61*4882a593Smuzhiyun		"""Parses a string containing KconfigEntrys and populates this Kconfig."""
62*4882a593Smuzhiyun		self._entries = []
63*4882a593Smuzhiyun		is_not_set_matcher = re.compile(CONFIG_IS_NOT_SET_PATTERN)
64*4882a593Smuzhiyun		config_matcher = re.compile(CONFIG_PATTERN)
65*4882a593Smuzhiyun		for line in blob.split('\n'):
66*4882a593Smuzhiyun			line = line.strip()
67*4882a593Smuzhiyun			if not line:
68*4882a593Smuzhiyun				continue
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun			match = config_matcher.match(line)
71*4882a593Smuzhiyun			if match:
72*4882a593Smuzhiyun				entry = KconfigEntry(match.group(1), match.group(2))
73*4882a593Smuzhiyun				self.add_entry(entry)
74*4882a593Smuzhiyun				continue
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun			empty_match = is_not_set_matcher.match(line)
77*4882a593Smuzhiyun			if empty_match:
78*4882a593Smuzhiyun				entry = KconfigEntry(empty_match.group(1), 'n')
79*4882a593Smuzhiyun				self.add_entry(entry)
80*4882a593Smuzhiyun				continue
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun			if line[0] == '#':
83*4882a593Smuzhiyun				continue
84*4882a593Smuzhiyun			else:
85*4882a593Smuzhiyun				raise KconfigParseError('Failed to parse: ' + line)
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun	def read_from_file(self, path: str) -> None:
88*4882a593Smuzhiyun		with open(path, 'r') as f:
89*4882a593Smuzhiyun			self.parse_from_string(f.read())
90