Add exhaustive test of all CLI examples
+import re
+
import siliconcompiler
def do_cli_test(args, monkeypatch, switchlist=None):
@@ -60,3 +62,77 @@ def test_limited_switchlist(monkeypatch):
assert chip.get('option', 'loglevel') == 'DEBUG'
assert chip.get('arg', 'flow', 'foo') == ['bar']
+
+def _cast(val, sctype):
+ if sctype.startswith('['):
+ # TODO: doesn't handle examples w/ multiple list items (we do not have
+ # currently)
+ subtype = sctype.strip('[]')
+ return [_cast(val.strip('[]'), subtype)]
+ elif sctype.startswith('('):
+ vals = val.strip('()').split(',')
+ subtypes = sctype.strip('()').split(',')
+ return tuple(_cast(v.strip(), subtype.strip()) for v, subtype in zip(vals, subtypes))
+ elif sctype == 'float':
+ return float(val)
+ elif sctype == 'int':
+ return int(val)
+ elif sctype == 'bool':
+ return bool(val)
+ else:
+ # everything else (str, file, dir) is treated like a string
+ return val
+
+def test_cli_examples(monkeypatch):
+ # Need to mock this function, since our cfg CLI example will try to call it
+ # on a fake manifest.
+ def _mock_read_manifest(chip, manifest, clobber=False, clear=False):
+ # nop
+ pass
+ monkeypatch.setattr(siliconcompiler.Chip, 'read_manifest', _mock_read_manifest)
+
+ chip = siliconcompiler.Chip('test')
+ for keypath in chip.getkeys():
+ examples = chip.get(*keypath, field='example')
+ for example in examples:
+ if not example.startswith('cli'):
+ continue
+
+ match = re.match(r'cli\: (\S+)(?:\s(.*))?', example)
+ assert match is not None, f'Invalid CLI example: {example}'
+
+ switch, value = match.groups()
+ if value is None:
+ value = ''
+
+ if len(value.split(' ')) > 1:
+ assert value[0] == "'" and value[-1] == "'", f'Multi-word value must be surrounded by quotes: {example}'
+ value = value.strip("'")
+
+ default_count = keypath.count('default')
+ assert len(value.split(' ')) >= default_count + 1, f'Not enough values to fill in default keys: {keypath}'
+ *free_keys, expected_val = value.split(' ', default_count)
+ typestr = chip.get(*keypath, field='type')
+ replaced_keypath = [free_keys.pop(0) if key == 'default' else key for key in keypath]
+
+ # Special cases
+ if keypath == ['option', 'optmode']:
+ expected_val = switch.lstrip('-')
+ elif keypath == ['option', 'define']:
+ expected_val = switch[len('-D'):]
+ elif switch.startswith('+incdir+'):
+ expected_val = switch[len('+incdir+'):]
+ elif switch.startswith('+libext+'):
+ expected_val = switch[len('+libext+'):]
+
+ args = ['sc', switch]
+ if value:
+ args.append(value)
+
+ c = do_cli_test(args, monkeypatch)
+
+ if expected_val:
+ assert c.get(*replaced_keypath) == _cast(expected_val, typestr)
+ else:
+ assert typestr == 'bool', 'Implicit value only alowed for boolean'
+ assert c.get(*replaced_keypath) == True
