1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2012 The Chromium OS Authors.
12 from buildman import board
13 from buildman import boards
14 from buildman import bsettings
15 from buildman import builder
16 from buildman import cfgutil
17 from buildman import control
18 from buildman import toolchain
19 from patman import commit
20 from u_boot_pylib import command
21 from u_boot_pylib import terminal
22 from u_boot_pylib import test_util
23 from u_boot_pylib import tools
28 # Buildman settings file
37 migration = '''===================== WARNING ======================
38 This board does not use CONFIG_DM. CONFIG_DM will be
39 compulsory starting with the v2020.01 release.
40 Failure to update may result in board removal.
41 See doc/develop/driver-model/migration.rst for more info.
42 ====================================================
46 '''main.c: In function 'main_loop':
47 main.c:260:6: warning: unused variable 'joe' [-Wunused-variable]
49 '''main.c: In function 'main_loop2':
50 main.c:295:2: error: 'fred' undeclared (first use in this function)
51 main.c:295:2: note: each undeclared identifier is reported only once for each function it appears in
52 make[1]: *** [main.o] Error 1
53 make: *** [common/libcommon.o] Error 2
56 '''arch/arm/dts/socfpga_arria10_socdk_sdmmc.dtb: Warning \
57 (avoid_unnecessary_addr_size): /clocks: unnecessary #address-cells/#size-cells \
58 without "ranges" or child "reg" property
60 '''powerpc-linux-ld: warning: dot moved backwards before `.bss'
61 powerpc-linux-ld: warning: dot moved backwards before `.bss'
62 powerpc-linux-ld: u-boot: section .text lma 0xfffc0000 overlaps previous sections
63 powerpc-linux-ld: u-boot: section .rodata lma 0xfffef3ec overlaps previous sections
64 powerpc-linux-ld: u-boot: section .reloc lma 0xffffa400 overlaps previous sections
65 powerpc-linux-ld: u-boot: section .data lma 0xffffcd38 overlaps previous sections
66 powerpc-linux-ld: u-boot: section .u_boot_cmd lma 0xffffeb40 overlaps previous sections
67 powerpc-linux-ld: u-boot: section .bootpg lma 0xfffff198 overlaps previous sections
69 '''In file included from %(basedir)sarch/sandbox/cpu/cpu.c:9:0:
70 %(basedir)sarch/sandbox/include/asm/state.h:44:0: warning: "xxxx" redefined [enabled by default]
71 %(basedir)sarch/sandbox/include/asm/state.h:43:0: note: this is the location of the previous definition
72 %(basedir)sarch/sandbox/cpu/cpu.c: In function 'do_reset':
73 %(basedir)sarch/sandbox/cpu/cpu.c:27:1: error: unknown type name 'blah'
74 %(basedir)sarch/sandbox/cpu/cpu.c:28:12: error: expected declaration specifiers or '...' before numeric constant
75 make[2]: *** [arch/sandbox/cpu/cpu.o] Error 1
76 make[1]: *** [arch/sandbox/cpu] Error 2
77 make[1]: *** Waiting for unfinished jobs....
78 In file included from %(basedir)scommon/board_f.c:55:0:
79 %(basedir)sarch/sandbox/include/asm/state.h:44:0: warning: "xxxx" redefined [enabled by default]
80 %(basedir)sarch/sandbox/include/asm/state.h:43:0: note: this is the location of the previous definition
81 make: *** [sub-make] Error 2
86 # hash, subject, return code, list of errors/warnings
88 ['1234', 'upstream/master, migration warning', 0, []],
89 ['5678', 'Second commit, a warning', 0, errors[0:1]],
90 ['9012', 'Third commit, error', 1, errors[0:2]],
91 ['3456', 'Fourth commit, warning', 0, [errors[0], errors[2]]],
92 ['7890', 'Fifth commit, link errors', 1, [errors[0], errors[3]]],
93 ['abcd', 'Sixth commit, fixes all errors', 0, []],
94 ['ef01', 'Seventh commit, fix migration, check directory suppression', 1,
99 ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 1', 'board0', ''],
100 ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 2', 'board1', ''],
101 ['Active', 'powerpc', 'powerpc', '', 'Tester', 'PowerPC board 1', 'board2', ''],
102 ['Active', 'powerpc', 'mpc83xx', '', 'Tester', 'PowerPC board 2', 'board3', ''],
103 ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''],
108 OUTCOME_OK, OUTCOME_WARN, OUTCOME_ERR = range(3)
111 """Class that holds build options"""
114 class TestBuild(unittest.TestCase):
117 TODO: Write tests for the rest of the functionality
120 # Set up commits to build
123 for commit_info in commits:
124 comm = commit.Commit(commit_info[0])
125 comm.subject = commit_info[1]
126 comm.return_code = commit_info[2]
127 comm.error_list = commit_info[3]
129 comm.error_list += [migration]
130 comm.sequence = sequence
132 self.commits.append(comm)
134 # Set up boards to build
135 self.brds = boards.Boards()
137 self.brds.add_board(board.Board(*brd))
138 self.brds.select_boards([])
140 # Add some test settings
141 bsettings.setup(None)
142 bsettings.add_file(settings_data)
144 # Set up the toolchains
145 self.toolchains = toolchain.Toolchains()
146 self.toolchains.Add('arm-linux-gcc', test=False)
147 self.toolchains.Add('sparc-linux-gcc', test=False)
148 self.toolchains.Add('powerpc-linux-gcc', test=False)
149 self.toolchains.Add('gcc', test=False)
151 # Avoid sending any output
152 terminal.set_print_test_mode()
153 self._col = terminal.Color()
155 self.base_dir = tempfile.mkdtemp()
156 if not os.path.isdir(self.base_dir):
157 os.mkdir(self.base_dir)
160 shutil.rmtree(self.base_dir)
162 def Make(self, commit, brd, stage, *args, **kwargs):
163 result = command.CommandResult()
164 boardnum = int(brd.target[-1])
165 result.return_code = 0
167 result.stdout = ('This is the test output for board %s, commit %s' %
168 (brd.target, commit.hash))
169 if ((boardnum >= 1 and boardnum >= commit.sequence) or
170 boardnum == 4 and commit.sequence == 6):
171 result.return_code = commit.return_code
172 result.stderr = (''.join(commit.error_list)
173 % {'basedir' : self.base_dir + '/.bm-work/00/'})
174 elif commit.sequence < 6:
175 result.stderr = migration
177 result.combined = result.stdout + result.stderr
180 def assertSummary(self, text, arch, plus, brds, outcome=OUTCOME_ERR):
182 expected_colour = (col.GREEN if outcome == OUTCOME_OK else
183 col.YELLOW if outcome == OUTCOME_WARN else col.RED)
184 expect = '%10s: ' % arch
185 # TODO(sjg@chromium.org): If plus is '', we shouldn't need this
186 expect += ' ' + col.build(expected_colour, plus)
189 expect += col.build(expected_colour, ' %s' % brd)
190 self.assertEqual(text, expect)
192 def _SetupTest(self, echo_lines=False, threads=1, **kwdisplay_args):
193 """Set up the test by running a build and summary
196 echo_lines: True to echo lines to the terminal to aid test
198 kwdisplay_args: Dict of arguemnts to pass to
199 Builder.SetDisplayOptions()
202 Iterator containing the output lines, each a PrintLine() object
204 build = builder.Builder(self.toolchains, self.base_dir, None, threads,
205 2, checkout=False, show_unknown=False)
206 build.do_make = self.Make
207 board_selected = self.brds.get_selected_dict()
209 # Build the boards for the pre-defined commits and warnings/errors
210 # associated with each. This calls our Make() to inject the fake output.
211 build.build_boards(self.commits, board_selected, keep_outputs=False,
213 lines = terminal.get_print_test_lines()
216 if line.text.strip():
219 # We should get two starting messages, an update for every commit built
220 # and a summary message
221 self.assertEqual(count, len(commits) * len(BOARDS) + 3)
222 build.set_display_options(**kwdisplay_args);
223 build.show_summary(self.commits, board_selected)
225 terminal.echo_print_test_lines()
226 return iter(terminal.get_print_test_lines())
228 def _CheckOutput(self, lines, list_error_boards=False,
229 filter_dtb_warnings=False,
230 filter_migration_warnings=False):
231 """Check for expected output from the build summary
234 lines: Iterator containing the lines returned from the summary
235 list_error_boards: Adjust the check for output produced with the
236 --list-error-boards flag
237 filter_dtb_warnings: Adjust the check for output produced with the
238 --filter-dtb-warnings flag
240 def add_line_prefix(prefix, brds, error_str, colour):
241 """Add a prefix to each line of a string
243 The training \n in error_str is removed before processing
246 prefix: String prefix to add
247 error_str: Error string containing the lines
248 colour: Expected colour for the line. Note that the board list,
249 if present, always appears in magenta
252 New string where each line has the prefix added
254 lines = error_str.strip().splitlines()
258 expect = self._col.build(colour, prefix + '(')
259 expect += self._col.build(self._col.MAGENTA, brds,
261 expect += self._col.build(colour, ') %s' % line)
263 expect = self._col.build(colour, prefix + line)
264 new_lines.append(expect)
265 return '\n'.join(new_lines)
267 col = terminal.Color()
268 boards01234 = ('board0 board1 board2 board3 board4'
269 if list_error_boards else '')
270 boards1234 = 'board1 board2 board3 board4' if list_error_boards else ''
271 boards234 = 'board2 board3 board4' if list_error_boards else ''
272 boards34 = 'board3 board4' if list_error_boards else ''
273 boards4 = 'board4' if list_error_boards else ''
275 # Upstream commit: migration warnings only
276 self.assertEqual(next(lines).text, '01: %s' % commits[0][1])
278 if not filter_migration_warnings:
279 self.assertSummary(next(lines).text, 'arm', 'w+',
280 ['board0', 'board1'], outcome=OUTCOME_WARN)
281 self.assertSummary(next(lines).text, 'powerpc', 'w+',
282 ['board2', 'board3'], outcome=OUTCOME_WARN)
283 self.assertSummary(next(lines).text, 'sandbox', 'w+', ['board4'],
284 outcome=OUTCOME_WARN)
286 self.assertEqual(next(lines).text,
287 add_line_prefix('+', boards01234, migration, col.RED))
289 # Second commit: all archs should fail with warnings
290 self.assertEqual(next(lines).text, '02: %s' % commits[1][1])
292 if filter_migration_warnings:
293 self.assertSummary(next(lines).text, 'arm', 'w+',
294 ['board1'], outcome=OUTCOME_WARN)
295 self.assertSummary(next(lines).text, 'powerpc', 'w+',
296 ['board2', 'board3'], outcome=OUTCOME_WARN)
297 self.assertSummary(next(lines).text, 'sandbox', 'w+', ['board4'],
298 outcome=OUTCOME_WARN)
300 # Second commit: The warnings should be listed
301 self.assertEqual(next(lines).text,
302 add_line_prefix('w+', boards1234, errors[0], col.YELLOW))
304 # Third commit: Still fails
305 self.assertEqual(next(lines).text, '03: %s' % commits[2][1])
306 if filter_migration_warnings:
307 self.assertSummary(next(lines).text, 'arm', '',
308 ['board1'], outcome=OUTCOME_OK)
309 self.assertSummary(next(lines).text, 'powerpc', '+',
310 ['board2', 'board3'])
311 self.assertSummary(next(lines).text, 'sandbox', '+', ['board4'])
313 # Expect a compiler error
314 self.assertEqual(next(lines).text,
315 add_line_prefix('+', boards234, errors[1], col.RED))
317 # Fourth commit: Compile errors are fixed, just have warning for board3
318 self.assertEqual(next(lines).text, '04: %s' % commits[3][1])
319 if filter_migration_warnings:
320 expect = '%10s: ' % 'powerpc'
321 expect += ' ' + col.build(col.GREEN, '')
323 expect += col.build(col.GREEN, ' %s' % 'board2')
324 expect += ' ' + col.build(col.YELLOW, 'w+')
326 expect += col.build(col.YELLOW, ' %s' % 'board3')
327 self.assertEqual(next(lines).text, expect)
329 self.assertSummary(next(lines).text, 'powerpc', 'w+',
330 ['board2', 'board3'], outcome=OUTCOME_WARN)
331 self.assertSummary(next(lines).text, 'sandbox', 'w+', ['board4'],
332 outcome=OUTCOME_WARN)
334 # Compile error fixed
335 self.assertEqual(next(lines).text,
336 add_line_prefix('-', boards234, errors[1], col.GREEN))
338 if not filter_dtb_warnings:
341 add_line_prefix('w+', boards34, errors[2], col.YELLOW))
344 self.assertEqual(next(lines).text, '05: %s' % commits[4][1])
345 if filter_migration_warnings:
346 self.assertSummary(next(lines).text, 'powerpc', '', ['board3'],
348 self.assertSummary(next(lines).text, 'sandbox', '+', ['board4'])
350 # The second line of errors[3] is a duplicate, so buildman will drop it
351 expect = errors[3].rstrip().split('\n')
352 expect = [expect[0]] + expect[2:]
353 expect = '\n'.join(expect)
354 self.assertEqual(next(lines).text,
355 add_line_prefix('+', boards4, expect, col.RED))
357 if not filter_dtb_warnings:
360 add_line_prefix('w-', boards34, errors[2], col.CYAN))
363 self.assertEqual(next(lines).text, '06: %s' % commits[5][1])
364 if filter_migration_warnings:
365 self.assertSummary(next(lines).text, 'sandbox', '', ['board4'],
368 self.assertSummary(next(lines).text, 'sandbox', 'w+', ['board4'],
369 outcome=OUTCOME_WARN)
371 # The second line of errors[3] is a duplicate, so buildman will drop it
372 expect = errors[3].rstrip().split('\n')
373 expect = [expect[0]] + expect[2:]
374 expect = '\n'.join(expect)
375 self.assertEqual(next(lines).text,
376 add_line_prefix('-', boards4, expect, col.GREEN))
377 self.assertEqual(next(lines).text,
378 add_line_prefix('w-', boards4, errors[0], col.CYAN))
381 self.assertEqual(next(lines).text, '07: %s' % commits[6][1])
382 if filter_migration_warnings:
383 self.assertSummary(next(lines).text, 'sandbox', '+', ['board4'])
385 self.assertSummary(next(lines).text, 'arm', '', ['board0', 'board1'],
387 self.assertSummary(next(lines).text, 'powerpc', '',
388 ['board2', 'board3'], outcome=OUTCOME_OK)
389 self.assertSummary(next(lines).text, 'sandbox', '+', ['board4'])
391 # Pick out the correct error lines
392 expect_str = errors[4].rstrip().replace('%(basedir)s', '').split('\n')
393 expect = expect_str[3:8] + [expect_str[-1]]
394 expect = '\n'.join(expect)
395 if not filter_migration_warnings:
398 add_line_prefix('-', boards01234, migration, col.GREEN))
400 self.assertEqual(next(lines).text,
401 add_line_prefix('+', boards4, expect, col.RED))
403 # Now the warnings lines
404 expect = [expect_str[0]] + expect_str[10:12] + [expect_str[9]]
405 expect = '\n'.join(expect)
406 self.assertEqual(next(lines).text,
407 add_line_prefix('w+', boards4, expect, col.YELLOW))
409 def testOutput(self):
410 """Test basic builder operation and output
412 This does a line-by-line verification of the summary output.
414 lines = self._SetupTest(show_errors=True)
415 self._CheckOutput(lines, list_error_boards=False,
416 filter_dtb_warnings=False)
418 def testErrorBoards(self):
419 """Test output with --list-error-boards
421 This does a line-by-line verification of the summary output.
423 lines = self._SetupTest(show_errors=True, list_error_boards=True)
424 self._CheckOutput(lines, list_error_boards=True)
426 def testFilterDtb(self):
427 """Test output with --filter-dtb-warnings
429 This does a line-by-line verification of the summary output.
431 lines = self._SetupTest(show_errors=True, filter_dtb_warnings=True)
432 self._CheckOutput(lines, filter_dtb_warnings=True)
434 def testFilterMigration(self):
435 """Test output with --filter-migration-warnings
437 This does a line-by-line verification of the summary output.
439 lines = self._SetupTest(show_errors=True,
440 filter_migration_warnings=True)
441 self._CheckOutput(lines, filter_migration_warnings=True)
443 def testSingleThread(self):
444 """Test operation without threading"""
445 lines = self._SetupTest(show_errors=True, threads=0)
446 self._CheckOutput(lines, list_error_boards=False,
447 filter_dtb_warnings=False)
450 """Test basic builder operation by building a branch"""
452 options.git = os.getcwd()
453 options.summary = False
455 options.dry_run = False
456 #options.git = os.path.join(self.base_dir, 'repo')
457 options.branch = 'test-buildman'
458 options.force_build = False
459 options.list_tool_chains = False
461 options.git_dir = None
462 options.threads = None
463 options.show_unknown = False
464 options.quick = False
465 options.show_errors = False
466 options.keep_outputs = False
468 control.do_buildman(options, args)
470 def testBoardSingle(self):
471 """Test single board selection"""
472 self.assertEqual(self.brds.select_boards(['sandbox']),
473 ({'all': ['board4'], 'sandbox': ['board4']}, []))
475 def testBoardArch(self):
476 """Test single board selection"""
477 self.assertEqual(self.brds.select_boards(['arm']),
478 ({'all': ['board0', 'board1'],
479 'arm': ['board0', 'board1']}, []))
481 def testBoardArchSingle(self):
482 """Test single board selection"""
483 self.assertEqual(self.brds.select_boards(['arm sandbox']),
484 ({'sandbox': ['board4'],
485 'all': ['board0', 'board1', 'board4'],
486 'arm': ['board0', 'board1']}, []))
489 def testBoardArchSingleMultiWord(self):
490 """Test single board selection"""
491 self.assertEqual(self.brds.select_boards(['arm', 'sandbox']),
492 ({'sandbox': ['board4'],
493 'all': ['board0', 'board1', 'board4'],
494 'arm': ['board0', 'board1']}, []))
496 def testBoardSingleAnd(self):
497 """Test single board selection"""
498 self.assertEqual(self.brds.select_boards(['Tester & arm']),
499 ({'Tester&arm': ['board0', 'board1'],
500 'all': ['board0', 'board1']}, []))
502 def testBoardTwoAnd(self):
503 """Test single board selection"""
504 self.assertEqual(self.brds.select_boards(['Tester', '&', 'arm',
505 'Tester' '&', 'powerpc',
507 ({'sandbox': ['board4'],
508 'all': ['board0', 'board1', 'board2', 'board3',
510 'Tester&powerpc': ['board2', 'board3'],
511 'Tester&arm': ['board0', 'board1']}, []))
513 def testBoardAll(self):
514 """Test single board selection"""
515 self.assertEqual(self.brds.select_boards([]),
516 ({'all': ['board0', 'board1', 'board2', 'board3',
519 def testBoardRegularExpression(self):
520 """Test single board selection"""
521 self.assertEqual(self.brds.select_boards(['T.*r&^Po']),
522 ({'all': ['board2', 'board3'],
523 'T.*r&^Po': ['board2', 'board3']}, []))
525 def testBoardDuplicate(self):
526 """Test single board selection"""
527 self.assertEqual(self.brds.select_boards(['sandbox sandbox',
529 ({'all': ['board4'], 'sandbox': ['board4']}, []))
530 def CheckDirs(self, build, dirname):
531 self.assertEqual('base%s' % dirname, build.get_output_dir(1))
532 self.assertEqual('base%s/fred' % dirname,
533 build.get_build_dir(1, 'fred'))
534 self.assertEqual('base%s/fred/done' % dirname,
535 build.get_done_file(1, 'fred'))
536 self.assertEqual('base%s/fred/u-boot.sizes' % dirname,
537 build.get_func_sizes_file(1, 'fred', 'u-boot'))
538 self.assertEqual('base%s/fred/u-boot.objdump' % dirname,
539 build.get_objdump_file(1, 'fred', 'u-boot'))
540 self.assertEqual('base%s/fred/err' % dirname,
541 build.get_err_file(1, 'fred'))
543 def testOutputDir(self):
544 build = builder.Builder(self.toolchains, BASE_DIR, None, 1, 2,
545 checkout=False, show_unknown=False)
546 build.commits = self.commits
547 build.commit_count = len(self.commits)
548 subject = self.commits[1].subject.translate(builder.trans_valid_chars)
549 dirname ='/%02d_g%s_%s' % (2, commits[1][0], subject[:20])
550 self.CheckDirs(build, dirname)
552 def testOutputDirCurrent(self):
553 build = builder.Builder(self.toolchains, BASE_DIR, None, 1, 2,
554 checkout=False, show_unknown=False)
556 build.commit_count = 0
557 self.CheckDirs(build, '/current')
559 def testOutputDirNoSubdirs(self):
560 build = builder.Builder(self.toolchains, BASE_DIR, None, 1, 2,
561 checkout=False, show_unknown=False,
564 build.commit_count = 0
565 self.CheckDirs(build, '')
567 def testToolchainAliases(self):
568 self.assertTrue(self.toolchains.Select('arm') != None)
569 with self.assertRaises(ValueError):
570 self.toolchains.Select('no-arch')
571 with self.assertRaises(ValueError):
572 self.toolchains.Select('x86')
574 self.toolchains = toolchain.Toolchains()
575 self.toolchains.Add('x86_64-linux-gcc', test=False)
576 self.assertTrue(self.toolchains.Select('x86') != None)
578 self.toolchains = toolchain.Toolchains()
579 self.toolchains.Add('i386-linux-gcc', test=False)
580 self.assertTrue(self.toolchains.Select('x86') != None)
582 def testToolchainDownload(self):
583 """Test that we can download toolchains"""
585 with test_util.capture_sys_output() as (stdout, stderr):
586 url = self.toolchains.LocateArchUrl('arm')
587 self.assertRegexpMatches(url, 'https://www.kernel.org/pub/tools/'
588 'crosstool/files/bin/x86_64/.*/'
589 'x86_64-gcc-.*-nolibc[-_]arm-.*linux-gnueabi.tar.xz')
591 def testGetEnvArgs(self):
592 """Test the GetEnvArgs() function"""
593 tc = self.toolchains.Select('arm')
594 self.assertEqual('arm-linux-',
595 tc.GetEnvArgs(toolchain.VAR_CROSS_COMPILE))
596 self.assertEqual('', tc.GetEnvArgs(toolchain.VAR_PATH))
597 self.assertEqual('arm',
598 tc.GetEnvArgs(toolchain.VAR_ARCH))
599 self.assertEqual('', tc.GetEnvArgs(toolchain.VAR_MAKE_ARGS))
601 self.toolchains.Add('/path/to/x86_64-linux-gcc', test=False)
602 tc = self.toolchains.Select('x86')
603 self.assertEqual('/path/to',
604 tc.GetEnvArgs(toolchain.VAR_PATH))
605 tc.override_toolchain = 'clang'
606 self.assertEqual('HOSTCC=clang CC=clang',
607 tc.GetEnvArgs(toolchain.VAR_MAKE_ARGS))
609 def testPrepareOutputSpace(self):
611 tools.write_file(os.path.join(base_dir, fname), b'')
613 base_dir = tempfile.mkdtemp()
615 # Add various files that we want removed and left alone
616 to_remove = ['01_g0982734987_title', '102_g92bf_title',
617 '01_g2938abd8_title']
618 to_leave = ['something_else', '01-something.patch', '01_another']
619 for name in to_remove + to_leave:
622 build = builder.Builder(self.toolchains, base_dir, None, 1, 2)
623 build.commits = self.commits
624 build.commit_count = len(commits)
625 result = set(build._get_output_space_removals())
626 expected = set([os.path.join(base_dir, f) for f in to_remove])
627 self.assertEqual(expected, result)
629 def test_adjust_cfg_nop(self):
630 """check various adjustments of config that are nops"""
631 # enable an enabled CONFIG
634 cfgutil.adjust_cfg_line('CONFIG_FRED=y', {'FRED':'FRED'})[0])
636 # disable a disabled CONFIG
638 '# CONFIG_FRED is not set',
639 cfgutil.adjust_cfg_line(
640 '# CONFIG_FRED is not set', {'FRED':'~FRED'})[0])
642 # use the adjust_cfg_lines() function
645 cfgutil.adjust_cfg_lines(['CONFIG_FRED=y'], {'FRED':'FRED'}))
647 ['# CONFIG_FRED is not set'],
648 cfgutil.adjust_cfg_lines(['CONFIG_FRED=y'], {'FRED':'~FRED'}))
650 # handling an empty line
651 self.assertEqual('#', cfgutil.adjust_cfg_line('#', {'FRED':'~FRED'})[0])
653 def test_adjust_cfg(self):
654 """check various adjustments of config"""
657 '# CONFIG_FRED is not set',
658 cfgutil.adjust_cfg_line('CONFIG_FRED=1' , {'FRED':'~FRED'})[0])
660 # enable a disabled CONFIG
663 cfgutil.adjust_cfg_line(
664 '# CONFIG_FRED is not set', {'FRED':'FRED'})[0])
666 # enable a CONFIG that doesn't exist
669 cfgutil.adjust_cfg_lines([], {'FRED':'FRED'}))
671 # disable a CONFIG that doesn't exist
673 ['# CONFIG_FRED is not set'],
674 cfgutil.adjust_cfg_lines([], {'FRED':'~FRED'}))
676 # disable a value CONFIG
678 '# CONFIG_FRED is not set',
679 cfgutil.adjust_cfg_line('CONFIG_FRED="fred"' , {'FRED':'~FRED'})[0])
681 # setting a value CONFIG
683 'CONFIG_FRED="fred"',
684 cfgutil.adjust_cfg_line('# CONFIG_FRED is not set' ,
685 {'FRED':'FRED="fred"'})[0])
687 # changing a value CONFIG
689 'CONFIG_FRED="fred"',
690 cfgutil.adjust_cfg_line('CONFIG_FRED="ernie"' ,
691 {'FRED':'FRED="fred"'})[0])
693 # setting a value for a CONFIG that doesn't exist
695 ['CONFIG_FRED="fred"'],
696 cfgutil.adjust_cfg_lines([], {'FRED':'FRED="fred"'}))
698 def test_convert_adjust_cfg_list(self):
699 """Check conversion of the list of changes into a dict"""
700 self.assertEqual({}, cfgutil.convert_list_to_dict(None))
706 'ALICE':'ALICE="alice"',
710 'ANNA':'ANNA="anna"',
712 actual = cfgutil.convert_list_to_dict(
713 ['FRED', '~MARY', 'JOHN=0x123', 'ALICE="alice"',
714 'CONFIG_AMY', '~CONFIG_ABE', 'CONFIG_MARK=0x456',
715 'CONFIG_ANNA="anna"'])
716 self.assertEqual(expect, actual)
718 def test_check_cfg_file(self):
719 """Test check_cfg_file detects conflicts as expected"""
720 # Check failure to disable CONFIG
721 result = cfgutil.check_cfg_lines(['CONFIG_FRED=1'], {'FRED':'~FRED'})
722 self.assertEqual([['~FRED', 'CONFIG_FRED=1']], result)
724 result = cfgutil.check_cfg_lines(
725 ['CONFIG_FRED=1', 'CONFIG_MARY="mary"'], {'FRED':'~FRED'})
726 self.assertEqual([['~FRED', 'CONFIG_FRED=1']], result)
728 result = cfgutil.check_cfg_lines(
729 ['CONFIG_FRED=1', 'CONFIG_MARY="mary"'], {'MARY':'~MARY'})
730 self.assertEqual([['~MARY', 'CONFIG_MARY="mary"']], result)
732 # Check failure to enable CONFIG
733 result = cfgutil.check_cfg_lines(
734 ['# CONFIG_FRED is not set'], {'FRED':'FRED'})
735 self.assertEqual([['FRED', '# CONFIG_FRED is not set']], result)
737 # Check failure to set CONFIG value
738 result = cfgutil.check_cfg_lines(
739 ['# CONFIG_FRED is not set', 'CONFIG_MARY="not"'],
740 {'MARY':'MARY="mary"', 'FRED':'FRED'})
742 ['FRED', '# CONFIG_FRED is not set'],
743 ['MARY="mary"', 'CONFIG_MARY="not"']], result)
745 # Check failure to add CONFIG value
746 result = cfgutil.check_cfg_lines([], {'MARY':'MARY="mary"'})
748 ['MARY="mary"', 'Missing expected line: CONFIG_MARY="mary"']], result)
751 if __name__ == "__main__":