1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2012 The Chromium OS Authors.
12 from buildman import board
13 from buildman import bsettings
14 from buildman import builder
15 from buildman import cfgutil
16 from buildman import control
17 from buildman import toolchain
18 from patman import commit
19 from patman import command
20 from patman import terminal
21 from patman import test_util
22 from patman import tools
27 # Buildman settings file
36 migration = '''===================== WARNING ======================
37 This board does not use CONFIG_DM. CONFIG_DM will be
38 compulsory starting with the v2020.01 release.
39 Failure to update may result in board removal.
40 See doc/driver-model/migration.rst for more info.
41 ====================================================
45 '''main.c: In function 'main_loop':
46 main.c:260:6: warning: unused variable 'joe' [-Wunused-variable]
48 '''main.c: In function 'main_loop2':
49 main.c:295:2: error: 'fred' undeclared (first use in this function)
50 main.c:295:2: note: each undeclared identifier is reported only once for each function it appears in
51 make[1]: *** [main.o] Error 1
52 make: *** [common/libcommon.o] Error 2
55 '''arch/arm/dts/socfpga_arria10_socdk_sdmmc.dtb: Warning \
56 (avoid_unnecessary_addr_size): /clocks: unnecessary #address-cells/#size-cells \
57 without "ranges" or child "reg" property
59 '''powerpc-linux-ld: warning: dot moved backwards before `.bss'
60 powerpc-linux-ld: warning: dot moved backwards before `.bss'
61 powerpc-linux-ld: u-boot: section .text lma 0xfffc0000 overlaps previous sections
62 powerpc-linux-ld: u-boot: section .rodata lma 0xfffef3ec overlaps previous sections
63 powerpc-linux-ld: u-boot: section .reloc lma 0xffffa400 overlaps previous sections
64 powerpc-linux-ld: u-boot: section .data lma 0xffffcd38 overlaps previous sections
65 powerpc-linux-ld: u-boot: section .u_boot_cmd lma 0xffffeb40 overlaps previous sections
66 powerpc-linux-ld: u-boot: section .bootpg lma 0xfffff198 overlaps previous sections
68 '''In file included from %(basedir)sarch/sandbox/cpu/cpu.c:9:0:
69 %(basedir)sarch/sandbox/include/asm/state.h:44:0: warning: "xxxx" redefined [enabled by default]
70 %(basedir)sarch/sandbox/include/asm/state.h:43:0: note: this is the location of the previous definition
71 %(basedir)sarch/sandbox/cpu/cpu.c: In function 'do_reset':
72 %(basedir)sarch/sandbox/cpu/cpu.c:27:1: error: unknown type name 'blah'
73 %(basedir)sarch/sandbox/cpu/cpu.c:28:12: error: expected declaration specifiers or '...' before numeric constant
74 make[2]: *** [arch/sandbox/cpu/cpu.o] Error 1
75 make[1]: *** [arch/sandbox/cpu] Error 2
76 make[1]: *** Waiting for unfinished jobs....
77 In file included from %(basedir)scommon/board_f.c:55:0:
78 %(basedir)sarch/sandbox/include/asm/state.h:44:0: warning: "xxxx" redefined [enabled by default]
79 %(basedir)sarch/sandbox/include/asm/state.h:43:0: note: this is the location of the previous definition
80 make: *** [sub-make] Error 2
85 # hash, subject, return code, list of errors/warnings
87 ['1234', 'upstream/master, migration warning', 0, []],
88 ['5678', 'Second commit, a warning', 0, errors[0:1]],
89 ['9012', 'Third commit, error', 1, errors[0:2]],
90 ['3456', 'Fourth commit, warning', 0, [errors[0], errors[2]]],
91 ['7890', 'Fifth commit, link errors', 1, [errors[0], errors[3]]],
92 ['abcd', 'Sixth commit, fixes all errors', 0, []],
93 ['ef01', 'Seventh commit, fix migration, check directory suppression', 1,
98 ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 1', 'board0', ''],
99 ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 2', 'board1', ''],
100 ['Active', 'powerpc', 'powerpc', '', 'Tester', 'PowerPC board 1', 'board2', ''],
101 ['Active', 'powerpc', 'mpc83xx', '', 'Tester', 'PowerPC board 2', 'board3', ''],
102 ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''],
107 OUTCOME_OK, OUTCOME_WARN, OUTCOME_ERR = range(3)
110 """Class that holds build options"""
113 class TestBuild(unittest.TestCase):
116 TODO: Write tests for the rest of the functionality
119 # Set up commits to build
122 for commit_info in commits:
123 comm = commit.Commit(commit_info[0])
124 comm.subject = commit_info[1]
125 comm.return_code = commit_info[2]
126 comm.error_list = commit_info[3]
128 comm.error_list += [migration]
129 comm.sequence = sequence
131 self.commits.append(comm)
133 # Set up boards to build
134 self.boards = board.Boards()
136 self.boards.AddBoard(board.Board(*brd))
137 self.boards.SelectBoards([])
139 # Add some test settings
140 bsettings.Setup(None)
141 bsettings.AddFile(settings_data)
143 # Set up the toolchains
144 self.toolchains = toolchain.Toolchains()
145 self.toolchains.Add('arm-linux-gcc', test=False)
146 self.toolchains.Add('sparc-linux-gcc', test=False)
147 self.toolchains.Add('powerpc-linux-gcc', test=False)
148 self.toolchains.Add('gcc', test=False)
150 # Avoid sending any output
151 terminal.SetPrintTestMode()
152 self._col = terminal.Color()
154 self.base_dir = tempfile.mkdtemp()
155 if not os.path.isdir(self.base_dir):
156 os.mkdir(self.base_dir)
159 shutil.rmtree(self.base_dir)
161 def Make(self, commit, brd, stage, *args, **kwargs):
162 result = command.CommandResult()
163 boardnum = int(brd.target[-1])
164 result.return_code = 0
166 result.stdout = ('This is the test output for board %s, commit %s' %
167 (brd.target, commit.hash))
168 if ((boardnum >= 1 and boardnum >= commit.sequence) or
169 boardnum == 4 and commit.sequence == 6):
170 result.return_code = commit.return_code
171 result.stderr = (''.join(commit.error_list)
172 % {'basedir' : self.base_dir + '/.bm-work/00/'})
173 elif commit.sequence < 6:
174 result.stderr = migration
176 result.combined = result.stdout + result.stderr
179 def assertSummary(self, text, arch, plus, boards, outcome=OUTCOME_ERR):
181 expected_colour = (col.GREEN if outcome == OUTCOME_OK else
182 col.YELLOW if outcome == OUTCOME_WARN else col.RED)
183 expect = '%10s: ' % arch
184 # TODO(sjg@chromium.org): If plus is '', we shouldn't need this
185 expect += ' ' + col.Color(expected_colour, plus)
188 expect += col.Color(expected_colour, ' %s' % board)
189 self.assertEqual(text, expect)
191 def _SetupTest(self, echo_lines=False, threads=1, **kwdisplay_args):
192 """Set up the test by running a build and summary
195 echo_lines: True to echo lines to the terminal to aid test
197 kwdisplay_args: Dict of arguemnts to pass to
198 Builder.SetDisplayOptions()
201 Iterator containing the output lines, each a PrintLine() object
203 build = builder.Builder(self.toolchains, self.base_dir, None, threads,
204 2, checkout=False, show_unknown=False)
205 build.do_make = self.Make
206 board_selected = self.boards.GetSelectedDict()
208 # Build the boards for the pre-defined commits and warnings/errors
209 # associated with each. This calls our Make() to inject the fake output.
210 build.BuildBoards(self.commits, board_selected, keep_outputs=False,
212 lines = terminal.GetPrintTestLines()
215 if line.text.strip():
218 # We should get two starting messages, an update for every commit built
219 # and a summary message
220 self.assertEqual(count, len(commits) * len(boards) + 3)
221 build.SetDisplayOptions(**kwdisplay_args);
222 build.ShowSummary(self.commits, board_selected)
224 terminal.EchoPrintTestLines()
225 return iter(terminal.GetPrintTestLines())
227 def _CheckOutput(self, lines, list_error_boards=False,
228 filter_dtb_warnings=False,
229 filter_migration_warnings=False):
230 """Check for expected output from the build summary
233 lines: Iterator containing the lines returned from the summary
234 list_error_boards: Adjust the check for output produced with the
235 --list-error-boards flag
236 filter_dtb_warnings: Adjust the check for output produced with the
237 --filter-dtb-warnings flag
239 def add_line_prefix(prefix, boards, error_str, colour):
240 """Add a prefix to each line of a string
242 The training \n in error_str is removed before processing
245 prefix: String prefix to add
246 error_str: Error string containing the lines
247 colour: Expected colour for the line. Note that the board list,
248 if present, always appears in magenta
251 New string where each line has the prefix added
253 lines = error_str.strip().splitlines()
257 expect = self._col.Color(colour, prefix + '(')
258 expect += self._col.Color(self._col.MAGENTA, boards,
260 expect += self._col.Color(colour, ') %s' % line)
262 expect = self._col.Color(colour, prefix + line)
263 new_lines.append(expect)
264 return '\n'.join(new_lines)
266 col = terminal.Color()
267 boards01234 = ('board0 board1 board2 board3 board4'
268 if list_error_boards else '')
269 boards1234 = 'board1 board2 board3 board4' if list_error_boards else ''
270 boards234 = 'board2 board3 board4' if list_error_boards else ''
271 boards34 = 'board3 board4' if list_error_boards else ''
272 boards4 = 'board4' if list_error_boards else ''
274 # Upstream commit: migration warnings only
275 self.assertEqual(next(lines).text, '01: %s' % commits[0][1])
277 if not filter_migration_warnings:
278 self.assertSummary(next(lines).text, 'arm', 'w+',
279 ['board0', 'board1'], outcome=OUTCOME_WARN)
280 self.assertSummary(next(lines).text, 'powerpc', 'w+',
281 ['board2', 'board3'], outcome=OUTCOME_WARN)
282 self.assertSummary(next(lines).text, 'sandbox', 'w+', ['board4'],
283 outcome=OUTCOME_WARN)
285 self.assertEqual(next(lines).text,
286 add_line_prefix('+', boards01234, migration, col.RED))
288 # Second commit: all archs should fail with warnings
289 self.assertEqual(next(lines).text, '02: %s' % commits[1][1])
291 if filter_migration_warnings:
292 self.assertSummary(next(lines).text, 'arm', 'w+',
293 ['board1'], outcome=OUTCOME_WARN)
294 self.assertSummary(next(lines).text, 'powerpc', 'w+',
295 ['board2', 'board3'], outcome=OUTCOME_WARN)
296 self.assertSummary(next(lines).text, 'sandbox', 'w+', ['board4'],
297 outcome=OUTCOME_WARN)
299 # Second commit: The warnings should be listed
300 self.assertEqual(next(lines).text,
301 add_line_prefix('w+', boards1234, errors[0], col.YELLOW))
303 # Third commit: Still fails
304 self.assertEqual(next(lines).text, '03: %s' % commits[2][1])
305 if filter_migration_warnings:
306 self.assertSummary(next(lines).text, 'arm', '',
307 ['board1'], outcome=OUTCOME_OK)
308 self.assertSummary(next(lines).text, 'powerpc', '+',
309 ['board2', 'board3'])
310 self.assertSummary(next(lines).text, 'sandbox', '+', ['board4'])
312 # Expect a compiler error
313 self.assertEqual(next(lines).text,
314 add_line_prefix('+', boards234, errors[1], col.RED))
316 # Fourth commit: Compile errors are fixed, just have warning for board3
317 self.assertEqual(next(lines).text, '04: %s' % commits[3][1])
318 if filter_migration_warnings:
319 expect = '%10s: ' % 'powerpc'
320 expect += ' ' + col.Color(col.GREEN, '')
322 expect += col.Color(col.GREEN, ' %s' % 'board2')
323 expect += ' ' + col.Color(col.YELLOW, 'w+')
325 expect += col.Color(col.YELLOW, ' %s' % 'board3')
326 self.assertEqual(next(lines).text, expect)
328 self.assertSummary(next(lines).text, 'powerpc', 'w+',
329 ['board2', 'board3'], outcome=OUTCOME_WARN)
330 self.assertSummary(next(lines).text, 'sandbox', 'w+', ['board4'],
331 outcome=OUTCOME_WARN)
333 # Compile error fixed
334 self.assertEqual(next(lines).text,
335 add_line_prefix('-', boards234, errors[1], col.GREEN))
337 if not filter_dtb_warnings:
340 add_line_prefix('w+', boards34, errors[2], col.YELLOW))
343 self.assertEqual(next(lines).text, '05: %s' % commits[4][1])
344 if filter_migration_warnings:
345 self.assertSummary(next(lines).text, 'powerpc', '', ['board3'],
347 self.assertSummary(next(lines).text, 'sandbox', '+', ['board4'])
349 # The second line of errors[3] is a duplicate, so buildman will drop it
350 expect = errors[3].rstrip().split('\n')
351 expect = [expect[0]] + expect[2:]
352 expect = '\n'.join(expect)
353 self.assertEqual(next(lines).text,
354 add_line_prefix('+', boards4, expect, col.RED))
356 if not filter_dtb_warnings:
359 add_line_prefix('w-', boards34, errors[2], col.CYAN))
362 self.assertEqual(next(lines).text, '06: %s' % commits[5][1])
363 if filter_migration_warnings:
364 self.assertSummary(next(lines).text, 'sandbox', '', ['board4'],
367 self.assertSummary(next(lines).text, 'sandbox', 'w+', ['board4'],
368 outcome=OUTCOME_WARN)
370 # The second line of errors[3] is a duplicate, so buildman will drop it
371 expect = errors[3].rstrip().split('\n')
372 expect = [expect[0]] + expect[2:]
373 expect = '\n'.join(expect)
374 self.assertEqual(next(lines).text,
375 add_line_prefix('-', boards4, expect, col.GREEN))
376 self.assertEqual(next(lines).text,
377 add_line_prefix('w-', boards4, errors[0], col.CYAN))
380 self.assertEqual(next(lines).text, '07: %s' % commits[6][1])
381 if filter_migration_warnings:
382 self.assertSummary(next(lines).text, 'sandbox', '+', ['board4'])
384 self.assertSummary(next(lines).text, 'arm', '', ['board0', 'board1'],
386 self.assertSummary(next(lines).text, 'powerpc', '',
387 ['board2', 'board3'], outcome=OUTCOME_OK)
388 self.assertSummary(next(lines).text, 'sandbox', '+', ['board4'])
390 # Pick out the correct error lines
391 expect_str = errors[4].rstrip().replace('%(basedir)s', '').split('\n')
392 expect = expect_str[3:8] + [expect_str[-1]]
393 expect = '\n'.join(expect)
394 if not filter_migration_warnings:
397 add_line_prefix('-', boards01234, migration, col.GREEN))
399 self.assertEqual(next(lines).text,
400 add_line_prefix('+', boards4, expect, col.RED))
402 # Now the warnings lines
403 expect = [expect_str[0]] + expect_str[10:12] + [expect_str[9]]
404 expect = '\n'.join(expect)
405 self.assertEqual(next(lines).text,
406 add_line_prefix('w+', boards4, expect, col.YELLOW))
408 def testOutput(self):
409 """Test basic builder operation and output
411 This does a line-by-line verification of the summary output.
413 lines = self._SetupTest(show_errors=True)
414 self._CheckOutput(lines, list_error_boards=False,
415 filter_dtb_warnings=False)
417 def testErrorBoards(self):
418 """Test output with --list-error-boards
420 This does a line-by-line verification of the summary output.
422 lines = self._SetupTest(show_errors=True, list_error_boards=True)
423 self._CheckOutput(lines, list_error_boards=True)
425 def testFilterDtb(self):
426 """Test output with --filter-dtb-warnings
428 This does a line-by-line verification of the summary output.
430 lines = self._SetupTest(show_errors=True, filter_dtb_warnings=True)
431 self._CheckOutput(lines, filter_dtb_warnings=True)
433 def testFilterMigration(self):
434 """Test output with --filter-migration-warnings
436 This does a line-by-line verification of the summary output.
438 lines = self._SetupTest(show_errors=True,
439 filter_migration_warnings=True)
440 self._CheckOutput(lines, filter_migration_warnings=True)
442 def testSingleThread(self):
443 """Test operation without threading"""
444 lines = self._SetupTest(show_errors=True, threads=0)
445 self._CheckOutput(lines, list_error_boards=False,
446 filter_dtb_warnings=False)
449 """Test basic builder operation by building a branch"""
451 options.git = os.getcwd()
452 options.summary = False
454 options.dry_run = False
455 #options.git = os.path.join(self.base_dir, 'repo')
456 options.branch = 'test-buildman'
457 options.force_build = False
458 options.list_tool_chains = False
460 options.git_dir = None
461 options.threads = None
462 options.show_unknown = False
463 options.quick = False
464 options.show_errors = False
465 options.keep_outputs = False
467 control.DoBuildman(options, args)
469 def testBoardSingle(self):
470 """Test single board selection"""
471 self.assertEqual(self.boards.SelectBoards(['sandbox']),
472 ({'all': ['board4'], 'sandbox': ['board4']}, []))
474 def testBoardArch(self):
475 """Test single board selection"""
476 self.assertEqual(self.boards.SelectBoards(['arm']),
477 ({'all': ['board0', 'board1'],
478 'arm': ['board0', 'board1']}, []))
480 def testBoardArchSingle(self):
481 """Test single board selection"""
482 self.assertEqual(self.boards.SelectBoards(['arm sandbox']),
483 ({'sandbox': ['board4'],
484 'all': ['board0', 'board1', 'board4'],
485 'arm': ['board0', 'board1']}, []))
488 def testBoardArchSingleMultiWord(self):
489 """Test single board selection"""
490 self.assertEqual(self.boards.SelectBoards(['arm', 'sandbox']),
491 ({'sandbox': ['board4'],
492 'all': ['board0', 'board1', 'board4'],
493 'arm': ['board0', 'board1']}, []))
495 def testBoardSingleAnd(self):
496 """Test single board selection"""
497 self.assertEqual(self.boards.SelectBoards(['Tester & arm']),
498 ({'Tester&arm': ['board0', 'board1'],
499 'all': ['board0', 'board1']}, []))
501 def testBoardTwoAnd(self):
502 """Test single board selection"""
503 self.assertEqual(self.boards.SelectBoards(['Tester', '&', 'arm',
504 'Tester' '&', 'powerpc',
506 ({'sandbox': ['board4'],
507 'all': ['board0', 'board1', 'board2', 'board3',
509 'Tester&powerpc': ['board2', 'board3'],
510 'Tester&arm': ['board0', 'board1']}, []))
512 def testBoardAll(self):
513 """Test single board selection"""
514 self.assertEqual(self.boards.SelectBoards([]),
515 ({'all': ['board0', 'board1', 'board2', 'board3',
518 def testBoardRegularExpression(self):
519 """Test single board selection"""
520 self.assertEqual(self.boards.SelectBoards(['T.*r&^Po']),
521 ({'all': ['board2', 'board3'],
522 'T.*r&^Po': ['board2', 'board3']}, []))
524 def testBoardDuplicate(self):
525 """Test single board selection"""
526 self.assertEqual(self.boards.SelectBoards(['sandbox sandbox',
528 ({'all': ['board4'], 'sandbox': ['board4']}, []))
529 def CheckDirs(self, build, dirname):
530 self.assertEqual('base%s' % dirname, build._GetOutputDir(1))
531 self.assertEqual('base%s/fred' % dirname,
532 build.GetBuildDir(1, 'fred'))
533 self.assertEqual('base%s/fred/done' % dirname,
534 build.GetDoneFile(1, 'fred'))
535 self.assertEqual('base%s/fred/u-boot.sizes' % dirname,
536 build.GetFuncSizesFile(1, 'fred', 'u-boot'))
537 self.assertEqual('base%s/fred/u-boot.objdump' % dirname,
538 build.GetObjdumpFile(1, 'fred', 'u-boot'))
539 self.assertEqual('base%s/fred/err' % dirname,
540 build.GetErrFile(1, 'fred'))
542 def testOutputDir(self):
543 build = builder.Builder(self.toolchains, BASE_DIR, None, 1, 2,
544 checkout=False, show_unknown=False)
545 build.commits = self.commits
546 build.commit_count = len(self.commits)
547 subject = self.commits[1].subject.translate(builder.trans_valid_chars)
548 dirname ='/%02d_g%s_%s' % (2, commits[1][0], subject[:20])
549 self.CheckDirs(build, dirname)
551 def testOutputDirCurrent(self):
552 build = builder.Builder(self.toolchains, BASE_DIR, None, 1, 2,
553 checkout=False, show_unknown=False)
555 build.commit_count = 0
556 self.CheckDirs(build, '/current')
558 def testOutputDirNoSubdirs(self):
559 build = builder.Builder(self.toolchains, BASE_DIR, None, 1, 2,
560 checkout=False, show_unknown=False,
563 build.commit_count = 0
564 self.CheckDirs(build, '')
566 def testToolchainAliases(self):
567 self.assertTrue(self.toolchains.Select('arm') != None)
568 with self.assertRaises(ValueError):
569 self.toolchains.Select('no-arch')
570 with self.assertRaises(ValueError):
571 self.toolchains.Select('x86')
573 self.toolchains = toolchain.Toolchains()
574 self.toolchains.Add('x86_64-linux-gcc', test=False)
575 self.assertTrue(self.toolchains.Select('x86') != None)
577 self.toolchains = toolchain.Toolchains()
578 self.toolchains.Add('i386-linux-gcc', test=False)
579 self.assertTrue(self.toolchains.Select('x86') != None)
581 def testToolchainDownload(self):
582 """Test that we can download toolchains"""
584 with test_util.capture_sys_output() as (stdout, stderr):
585 url = self.toolchains.LocateArchUrl('arm')
586 self.assertRegexpMatches(url, 'https://www.kernel.org/pub/tools/'
587 'crosstool/files/bin/x86_64/.*/'
588 'x86_64-gcc-.*-nolibc[-_]arm-.*linux-gnueabi.tar.xz')
590 def testGetEnvArgs(self):
591 """Test the GetEnvArgs() function"""
592 tc = self.toolchains.Select('arm')
593 self.assertEqual('arm-linux-',
594 tc.GetEnvArgs(toolchain.VAR_CROSS_COMPILE))
595 self.assertEqual('', tc.GetEnvArgs(toolchain.VAR_PATH))
596 self.assertEqual('arm',
597 tc.GetEnvArgs(toolchain.VAR_ARCH))
598 self.assertEqual('', tc.GetEnvArgs(toolchain.VAR_MAKE_ARGS))
600 self.toolchains.Add('/path/to/x86_64-linux-gcc', test=False)
601 tc = self.toolchains.Select('x86')
602 self.assertEqual('/path/to',
603 tc.GetEnvArgs(toolchain.VAR_PATH))
604 tc.override_toolchain = 'clang'
605 self.assertEqual('HOSTCC=clang CC=clang',
606 tc.GetEnvArgs(toolchain.VAR_MAKE_ARGS))
608 def testPrepareOutputSpace(self):
610 tools.write_file(os.path.join(base_dir, fname), b'')
612 base_dir = tempfile.mkdtemp()
614 # Add various files that we want removed and left alone
615 to_remove = ['01_g0982734987_title', '102_g92bf_title',
616 '01_g2938abd8_title']
617 to_leave = ['something_else', '01-something.patch', '01_another']
618 for name in to_remove + to_leave:
621 build = builder.Builder(self.toolchains, base_dir, None, 1, 2)
622 build.commits = self.commits
623 build.commit_count = len(commits)
624 result = set(build._GetOutputSpaceRemovals())
625 expected = set([os.path.join(base_dir, f) for f in to_remove])
626 self.assertEqual(expected, result)
628 def test_adjust_cfg_nop(self):
629 """check various adjustments of config that are nops"""
630 # enable an enabled CONFIG
633 cfgutil.adjust_cfg_line('CONFIG_FRED=y', {'FRED':'FRED'})[0])
635 # disable a disabled CONFIG
637 '# CONFIG_FRED is not set',
638 cfgutil.adjust_cfg_line(
639 '# CONFIG_FRED is not set', {'FRED':'~FRED'})[0])
641 # use the adjust_cfg_lines() function
644 cfgutil.adjust_cfg_lines(['CONFIG_FRED=y'], {'FRED':'FRED'}))
646 ['# CONFIG_FRED is not set'],
647 cfgutil.adjust_cfg_lines(['CONFIG_FRED=y'], {'FRED':'~FRED'}))
649 # handling an empty line
650 self.assertEqual('#', cfgutil.adjust_cfg_line('#', {'FRED':'~FRED'})[0])
652 def test_adjust_cfg(self):
653 """check various adjustments of config"""
656 '# CONFIG_FRED is not set',
657 cfgutil.adjust_cfg_line('CONFIG_FRED=1' , {'FRED':'~FRED'})[0])
659 # enable a disabled CONFIG
662 cfgutil.adjust_cfg_line(
663 '# CONFIG_FRED is not set', {'FRED':'FRED'})[0])
665 # enable a CONFIG that doesn't exist
668 cfgutil.adjust_cfg_lines([], {'FRED':'FRED'}))
670 # disable a CONFIG that doesn't exist
672 ['# CONFIG_FRED is not set'],
673 cfgutil.adjust_cfg_lines([], {'FRED':'~FRED'}))
675 # disable a value CONFIG
677 '# CONFIG_FRED is not set',
678 cfgutil.adjust_cfg_line('CONFIG_FRED="fred"' , {'FRED':'~FRED'})[0])
680 # setting a value CONFIG
682 'CONFIG_FRED="fred"',
683 cfgutil.adjust_cfg_line('# CONFIG_FRED is not set' ,
684 {'FRED':'FRED="fred"'})[0])
686 # changing a value CONFIG
688 'CONFIG_FRED="fred"',
689 cfgutil.adjust_cfg_line('CONFIG_FRED="ernie"' ,
690 {'FRED':'FRED="fred"'})[0])
692 # setting a value for a CONFIG that doesn't exist
694 ['CONFIG_FRED="fred"'],
695 cfgutil.adjust_cfg_lines([], {'FRED':'FRED="fred"'}))
697 def test_convert_adjust_cfg_list(self):
698 """Check conversion of the list of changes into a dict"""
699 self.assertEqual({}, cfgutil.convert_list_to_dict(None))
705 'ALICE':'ALICE="alice"',
709 'ANNA':'ANNA="anna"',
711 actual = cfgutil.convert_list_to_dict(
712 ['FRED', '~MARY', 'JOHN=0x123', 'ALICE="alice"',
713 'CONFIG_AMY', '~CONFIG_ABE', 'CONFIG_MARK=0x456',
714 'CONFIG_ANNA="anna"'])
715 self.assertEqual(expect, actual)
717 def test_check_cfg_file(self):
718 """Test check_cfg_file detects conflicts as expected"""
719 # Check failure to disable CONFIG
720 result = cfgutil.check_cfg_lines(['CONFIG_FRED=1'], {'FRED':'~FRED'})
721 self.assertEqual([['~FRED', 'CONFIG_FRED=1']], result)
723 result = cfgutil.check_cfg_lines(
724 ['CONFIG_FRED=1', 'CONFIG_MARY="mary"'], {'FRED':'~FRED'})
725 self.assertEqual([['~FRED', 'CONFIG_FRED=1']], result)
727 result = cfgutil.check_cfg_lines(
728 ['CONFIG_FRED=1', 'CONFIG_MARY="mary"'], {'MARY':'~MARY'})
729 self.assertEqual([['~MARY', 'CONFIG_MARY="mary"']], result)
731 # Check failure to enable CONFIG
732 result = cfgutil.check_cfg_lines(
733 ['# CONFIG_FRED is not set'], {'FRED':'FRED'})
734 self.assertEqual([['FRED', '# CONFIG_FRED is not set']], result)
736 # Check failure to set CONFIG value
737 result = cfgutil.check_cfg_lines(
738 ['# CONFIG_FRED is not set', 'CONFIG_MARY="not"'],
739 {'MARY':'MARY="mary"', 'FRED':'FRED'})
741 ['FRED', '# CONFIG_FRED is not set'],
742 ['MARY="mary"', 'CONFIG_MARY="not"']], result)
744 # Check failure to add CONFIG value
745 result = cfgutil.check_cfg_lines([], {'MARY':'MARY="mary"'})
747 ['MARY="mary"', 'Missing expected line: CONFIG_MARY="mary"']], result)
750 if __name__ == "__main__":