1fc3fe1c2SSimon Glass# 2fc3fe1c2SSimon Glass# Copyright (c) 2012 The Chromium OS Authors. 3fc3fe1c2SSimon Glass# 41a459660SWolfgang Denk# SPDX-License-Identifier: GPL-2.0+ 5fc3fe1c2SSimon Glass# 6fc3fe1c2SSimon Glass 7fc3fe1c2SSimon Glassimport os 8fc3fe1c2SSimon Glassimport shutil 9fc3fe1c2SSimon Glassimport sys 10fc3fe1c2SSimon Glassimport tempfile 11fc3fe1c2SSimon Glassimport time 12fc3fe1c2SSimon Glassimport unittest 13fc3fe1c2SSimon Glass 14fc3fe1c2SSimon Glass# Bring in the patman libraries 15fc3fe1c2SSimon Glassour_path = os.path.dirname(os.path.realpath(__file__)) 16fc3fe1c2SSimon Glasssys.path.append(os.path.join(our_path, '../patman')) 17fc3fe1c2SSimon Glass 18fc3fe1c2SSimon Glassimport board 19fc3fe1c2SSimon Glassimport bsettings 20fc3fe1c2SSimon Glassimport builder 21fc3fe1c2SSimon Glassimport control 22fc3fe1c2SSimon Glassimport command 23fc3fe1c2SSimon Glassimport commit 24*6208fcefSSimon Glassimport terminal 25fc3fe1c2SSimon Glassimport toolchain 26fc3fe1c2SSimon Glass 27fc3fe1c2SSimon Glasserrors = [ 28fc3fe1c2SSimon Glass '''main.c: In function 'main_loop': 29fc3fe1c2SSimon Glassmain.c:260:6: warning: unused variable 'joe' [-Wunused-variable] 30fc3fe1c2SSimon Glass''', 31*6208fcefSSimon Glass '''main.c: In function 'main_loop2': 32fc3fe1c2SSimon Glassmain.c:295:2: error: 'fred' undeclared (first use in this function) 33fc3fe1c2SSimon Glassmain.c:295:2: note: each undeclared identifier is reported only once for each function it appears in 34fc3fe1c2SSimon Glassmake[1]: *** [main.o] Error 1 35fc3fe1c2SSimon Glassmake: *** [common/libcommon.o] Error 2 36fc3fe1c2SSimon GlassMake failed 37fc3fe1c2SSimon Glass''', 38*6208fcefSSimon Glass '''main.c: In function 'main_loop3': 39fc3fe1c2SSimon Glassmain.c:280:6: warning: unused variable 'mary' [-Wunused-variable] 40fc3fe1c2SSimon Glass''', 41fc3fe1c2SSimon Glass '''powerpc-linux-ld: warning: dot moved backwards before `.bss' 42fc3fe1c2SSimon Glasspowerpc-linux-ld: warning: dot moved backwards before `.bss' 43fc3fe1c2SSimon Glasspowerpc-linux-ld: u-boot: section .text lma 0xfffc0000 overlaps previous sections 44fc3fe1c2SSimon Glasspowerpc-linux-ld: u-boot: section .rodata lma 0xfffef3ec overlaps previous sections 45fc3fe1c2SSimon Glasspowerpc-linux-ld: u-boot: section .reloc lma 0xffffa400 overlaps previous sections 46fc3fe1c2SSimon Glasspowerpc-linux-ld: u-boot: section .data lma 0xffffcd38 overlaps previous sections 47fc3fe1c2SSimon Glasspowerpc-linux-ld: u-boot: section .u_boot_cmd lma 0xffffeb40 overlaps previous sections 48fc3fe1c2SSimon Glasspowerpc-linux-ld: u-boot: section .bootpg lma 0xfffff198 overlaps previous sections 49fc3fe1c2SSimon Glass''' 50fc3fe1c2SSimon Glass] 51fc3fe1c2SSimon Glass 52fc3fe1c2SSimon Glass 53fc3fe1c2SSimon Glass# hash, subject, return code, list of errors/warnings 54fc3fe1c2SSimon Glasscommits = [ 55fc3fe1c2SSimon Glass ['1234', 'upstream/master, ok', 0, []], 56fc3fe1c2SSimon Glass ['5678', 'Second commit, a warning', 0, errors[0:1]], 57fc3fe1c2SSimon Glass ['9012', 'Third commit, error', 1, errors[0:2]], 58fc3fe1c2SSimon Glass ['3456', 'Fourth commit, warning', 0, [errors[0], errors[2]]], 59fc3fe1c2SSimon Glass ['7890', 'Fifth commit, link errors', 1, [errors[0], errors[3]]], 60fc3fe1c2SSimon Glass ['abcd', 'Sixth commit, fixes all errors', 0, []] 61fc3fe1c2SSimon Glass] 62fc3fe1c2SSimon Glass 63fc3fe1c2SSimon Glassboards = [ 64e19d5781SSimon Glass ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 1', 'board0', ''], 65e19d5781SSimon Glass ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 2', 'board1', ''], 66e19d5781SSimon Glass ['Active', 'powerpc', 'powerpc', '', 'Tester', 'PowerPC board 1', 'board2', ''], 67e19d5781SSimon Glass ['Active', 'powerpc', 'mpc5xx', '', 'Tester', 'PowerPC board 2', 'board3', ''], 68e19d5781SSimon Glass ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''], 69fc3fe1c2SSimon Glass] 70fc3fe1c2SSimon Glass 71fc3fe1c2SSimon Glassclass Options: 72fc3fe1c2SSimon Glass """Class that holds build options""" 73fc3fe1c2SSimon Glass pass 74fc3fe1c2SSimon Glass 75fc3fe1c2SSimon Glassclass TestBuild(unittest.TestCase): 76fc3fe1c2SSimon Glass """Test buildman 77fc3fe1c2SSimon Glass 78fc3fe1c2SSimon Glass TODO: Write tests for the rest of the functionality 79fc3fe1c2SSimon Glass """ 80fc3fe1c2SSimon Glass def setUp(self): 81fc3fe1c2SSimon Glass # Set up commits to build 82fc3fe1c2SSimon Glass self.commits = [] 83fc3fe1c2SSimon Glass sequence = 0 84fc3fe1c2SSimon Glass for commit_info in commits: 85fc3fe1c2SSimon Glass comm = commit.Commit(commit_info[0]) 86fc3fe1c2SSimon Glass comm.subject = commit_info[1] 87fc3fe1c2SSimon Glass comm.return_code = commit_info[2] 88fc3fe1c2SSimon Glass comm.error_list = commit_info[3] 89fc3fe1c2SSimon Glass comm.sequence = sequence 90fc3fe1c2SSimon Glass sequence += 1 91fc3fe1c2SSimon Glass self.commits.append(comm) 92fc3fe1c2SSimon Glass 93fc3fe1c2SSimon Glass # Set up boards to build 94fc3fe1c2SSimon Glass self.boards = board.Boards() 95fc3fe1c2SSimon Glass for brd in boards: 96fc3fe1c2SSimon Glass self.boards.AddBoard(board.Board(*brd)) 97fc3fe1c2SSimon Glass self.boards.SelectBoards([]) 98fc3fe1c2SSimon Glass 99fc3fe1c2SSimon Glass # Set up the toolchains 100fc3fe1c2SSimon Glass bsettings.Setup() 101fc3fe1c2SSimon Glass self.toolchains = toolchain.Toolchains() 102fc3fe1c2SSimon Glass self.toolchains.Add('arm-linux-gcc', test=False) 103fc3fe1c2SSimon Glass self.toolchains.Add('sparc-linux-gcc', test=False) 104fc3fe1c2SSimon Glass self.toolchains.Add('powerpc-linux-gcc', test=False) 105fc3fe1c2SSimon Glass self.toolchains.Add('gcc', test=False) 106fc3fe1c2SSimon Glass 107*6208fcefSSimon Glass # Avoid sending any output 108*6208fcefSSimon Glass terminal.SetPrintTestMode() 109*6208fcefSSimon Glass self._col = terminal.Color() 110*6208fcefSSimon Glass 111fc3fe1c2SSimon Glass def Make(self, commit, brd, stage, *args, **kwargs): 112fc3fe1c2SSimon Glass result = command.CommandResult() 113fc3fe1c2SSimon Glass boardnum = int(brd.target[-1]) 114fc3fe1c2SSimon Glass result.return_code = 0 115fc3fe1c2SSimon Glass result.stderr = '' 116fc3fe1c2SSimon Glass result.stdout = ('This is the test output for board %s, commit %s' % 117fc3fe1c2SSimon Glass (brd.target, commit.hash)) 118fc3fe1c2SSimon Glass if boardnum >= 1 and boardnum >= commit.sequence: 119fc3fe1c2SSimon Glass result.return_code = commit.return_code 120fc3fe1c2SSimon Glass result.stderr = ''.join(commit.error_list) 121fc3fe1c2SSimon Glass if stage == 'build': 122fc3fe1c2SSimon Glass target_dir = None 123fc3fe1c2SSimon Glass for arg in args: 124fc3fe1c2SSimon Glass if arg.startswith('O='): 125fc3fe1c2SSimon Glass target_dir = arg[2:] 126fc3fe1c2SSimon Glass 127fc3fe1c2SSimon Glass if not os.path.isdir(target_dir): 128fc3fe1c2SSimon Glass os.mkdir(target_dir) 129fc3fe1c2SSimon Glass 130fc3fe1c2SSimon Glass result.combined = result.stdout + result.stderr 131fc3fe1c2SSimon Glass return result 132fc3fe1c2SSimon Glass 133*6208fcefSSimon Glass def assertSummary(self, text, arch, plus, boards, ok=False): 134*6208fcefSSimon Glass col = self._col 135*6208fcefSSimon Glass expected_colour = col.GREEN if ok else col.RED 136*6208fcefSSimon Glass expect = '%10s: ' % arch 137*6208fcefSSimon Glass # TODO(sjg@chromium.org): If plus is '', we shouldn't need this 138*6208fcefSSimon Glass expect += col.Color(expected_colour, plus) 139*6208fcefSSimon Glass expect += ' ' 140*6208fcefSSimon Glass for board in boards: 141*6208fcefSSimon Glass expect += col.Color(expected_colour, ' %s' % board) 142*6208fcefSSimon Glass self.assertEqual(text, expect) 143*6208fcefSSimon Glass 144*6208fcefSSimon Glass def testOutput(self): 145*6208fcefSSimon Glass """Test basic builder operation and output 146*6208fcefSSimon Glass 147*6208fcefSSimon Glass This does a line-by-line verification of the summary output. 148*6208fcefSSimon Glass """ 149fc3fe1c2SSimon Glass output_dir = tempfile.mkdtemp() 150fc3fe1c2SSimon Glass if not os.path.isdir(output_dir): 151fc3fe1c2SSimon Glass os.mkdir(output_dir) 152fc3fe1c2SSimon Glass build = builder.Builder(self.toolchains, output_dir, None, 1, 2, 153fc3fe1c2SSimon Glass checkout=False, show_unknown=False) 154fc3fe1c2SSimon Glass build.do_make = self.Make 155fc3fe1c2SSimon Glass board_selected = self.boards.GetSelectedDict() 156fc3fe1c2SSimon Glass 157e5a0e5d8SSimon Glass build.BuildBoards(self.commits, board_selected, keep_outputs=False, 158e5a0e5d8SSimon Glass verbose=False) 159*6208fcefSSimon Glass lines = terminal.GetPrintTestLines() 160*6208fcefSSimon Glass count = 0 161*6208fcefSSimon Glass for line in lines: 162*6208fcefSSimon Glass if line.text.strip(): 163*6208fcefSSimon Glass count += 1 164*6208fcefSSimon Glass 165*6208fcefSSimon Glass # We should get one starting message, then an update for every commit 166*6208fcefSSimon Glass # built. 167*6208fcefSSimon Glass self.assertEqual(count, len(commits) * len(boards) + 1) 168b2ea7ab2SSimon Glass build.SetDisplayOptions(show_errors=True); 169b2ea7ab2SSimon Glass build.ShowSummary(self.commits, board_selected) 170*6208fcefSSimon Glass lines = terminal.GetPrintTestLines() 171*6208fcefSSimon Glass self.assertEqual(lines[0].text, '01: %s' % commits[0][1]) 172*6208fcefSSimon Glass self.assertEqual(lines[1].text, '02: %s' % commits[1][1]) 173*6208fcefSSimon Glass 174*6208fcefSSimon Glass # We expect all archs to fail 175*6208fcefSSimon Glass col = terminal.Color() 176*6208fcefSSimon Glass self.assertSummary(lines[2].text, 'sandbox', '+', ['board4']) 177*6208fcefSSimon Glass self.assertSummary(lines[3].text, 'arm', '+', ['board1']) 178*6208fcefSSimon Glass self.assertSummary(lines[4].text, 'powerpc', '+', ['board2', 'board3']) 179*6208fcefSSimon Glass 180*6208fcefSSimon Glass # Now we should have the compiler warning 181*6208fcefSSimon Glass self.assertEqual(lines[5].text, 'w+%s' % 182*6208fcefSSimon Glass errors[0].rstrip().replace('\n', '\nw+')) 183*6208fcefSSimon Glass self.assertEqual(lines[5].colour, col.MAGENTA) 184*6208fcefSSimon Glass 185*6208fcefSSimon Glass self.assertEqual(lines[6].text, '03: %s' % commits[2][1]) 186*6208fcefSSimon Glass self.assertSummary(lines[7].text, 'sandbox', '+', ['board4']) 187*6208fcefSSimon Glass self.assertSummary(lines[8].text, 'arm', '', ['board1'], ok=True) 188*6208fcefSSimon Glass self.assertSummary(lines[9].text, 'powerpc', '+', ['board2', 'board3']) 189*6208fcefSSimon Glass 190*6208fcefSSimon Glass # Compiler error 191*6208fcefSSimon Glass self.assertEqual(lines[10].text, '+%s' % 192*6208fcefSSimon Glass errors[1].rstrip().replace('\n', '\n+')) 193*6208fcefSSimon Glass 194*6208fcefSSimon Glass self.assertEqual(lines[11].text, '04: %s' % commits[3][1]) 195*6208fcefSSimon Glass self.assertSummary(lines[12].text, 'sandbox', '', ['board4'], ok=True) 196*6208fcefSSimon Glass self.assertSummary(lines[13].text, 'powerpc', '', ['board2', 'board3'], 197*6208fcefSSimon Glass ok=True) 198*6208fcefSSimon Glass 199*6208fcefSSimon Glass # Compile error fixed 200*6208fcefSSimon Glass self.assertEqual(lines[14].text, '-%s' % 201*6208fcefSSimon Glass errors[1].rstrip().replace('\n', '\n-')) 202*6208fcefSSimon Glass self.assertEqual(lines[14].colour, col.GREEN) 203*6208fcefSSimon Glass 204*6208fcefSSimon Glass self.assertEqual(lines[15].text, 'w+%s' % 205*6208fcefSSimon Glass errors[2].rstrip().replace('\n', '\nw+')) 206*6208fcefSSimon Glass self.assertEqual(lines[15].colour, col.MAGENTA) 207*6208fcefSSimon Glass 208*6208fcefSSimon Glass self.assertEqual(lines[16].text, '05: %s' % commits[4][1]) 209*6208fcefSSimon Glass self.assertSummary(lines[17].text, 'sandbox', '+', ['board4']) 210*6208fcefSSimon Glass self.assertSummary(lines[18].text, 'powerpc', '', ['board3'], ok=True) 211*6208fcefSSimon Glass 212*6208fcefSSimon Glass # The second line of errors[3] is a duplicate, so buildman will drop it 213*6208fcefSSimon Glass expect = errors[3].rstrip().split('\n') 214*6208fcefSSimon Glass expect = [expect[0]] + expect[2:] 215*6208fcefSSimon Glass self.assertEqual(lines[19].text, '+%s' % 216*6208fcefSSimon Glass '\n'.join(expect).replace('\n', '\n+')) 217*6208fcefSSimon Glass 218*6208fcefSSimon Glass self.assertEqual(lines[20].text, 'w-%s' % 219*6208fcefSSimon Glass errors[2].rstrip().replace('\n', '\nw-')) 220*6208fcefSSimon Glass 221*6208fcefSSimon Glass self.assertEqual(lines[21].text, '06: %s' % commits[5][1]) 222*6208fcefSSimon Glass self.assertSummary(lines[22].text, 'sandbox', '', ['board4'], ok=True) 223*6208fcefSSimon Glass 224*6208fcefSSimon Glass # The second line of errors[3] is a duplicate, so buildman will drop it 225*6208fcefSSimon Glass expect = errors[3].rstrip().split('\n') 226*6208fcefSSimon Glass expect = [expect[0]] + expect[2:] 227*6208fcefSSimon Glass self.assertEqual(lines[23].text, '-%s' % 228*6208fcefSSimon Glass '\n'.join(expect).replace('\n', '\n-')) 229*6208fcefSSimon Glass 230*6208fcefSSimon Glass self.assertEqual(lines[24].text, 'w-%s' % 231*6208fcefSSimon Glass errors[0].rstrip().replace('\n', '\nw-')) 232*6208fcefSSimon Glass 233*6208fcefSSimon Glass self.assertEqual(len(lines), 25) 234fc3fe1c2SSimon Glass 235fc3fe1c2SSimon Glass def _testGit(self): 236fc3fe1c2SSimon Glass """Test basic builder operation by building a branch""" 237fc3fe1c2SSimon Glass base_dir = tempfile.mkdtemp() 238fc3fe1c2SSimon Glass if not os.path.isdir(base_dir): 239fc3fe1c2SSimon Glass os.mkdir(base_dir) 240fc3fe1c2SSimon Glass options = Options() 241fc3fe1c2SSimon Glass options.git = os.getcwd() 242fc3fe1c2SSimon Glass options.summary = False 243fc3fe1c2SSimon Glass options.jobs = None 244fc3fe1c2SSimon Glass options.dry_run = False 245fc3fe1c2SSimon Glass #options.git = os.path.join(base_dir, 'repo') 246fc3fe1c2SSimon Glass options.branch = 'test-buildman' 247fc3fe1c2SSimon Glass options.force_build = False 248fc3fe1c2SSimon Glass options.list_tool_chains = False 249fc3fe1c2SSimon Glass options.count = -1 250fc3fe1c2SSimon Glass options.git_dir = None 251fc3fe1c2SSimon Glass options.threads = None 252fc3fe1c2SSimon Glass options.show_unknown = False 253fc3fe1c2SSimon Glass options.quick = False 254fc3fe1c2SSimon Glass options.show_errors = False 255fc3fe1c2SSimon Glass options.keep_outputs = False 256fc3fe1c2SSimon Glass args = ['tegra20'] 257fc3fe1c2SSimon Glass control.DoBuildman(options, args) 258fc3fe1c2SSimon Glass 2596131beabSSimon Glass def testBoardSingle(self): 2606131beabSSimon Glass """Test single board selection""" 2616131beabSSimon Glass self.assertEqual(self.boards.SelectBoards(['sandbox']), 2626131beabSSimon Glass {'all': 1, 'sandbox': 1}) 2636131beabSSimon Glass 2646131beabSSimon Glass def testBoardArch(self): 2656131beabSSimon Glass """Test single board selection""" 2666131beabSSimon Glass self.assertEqual(self.boards.SelectBoards(['arm']), 2676131beabSSimon Glass {'all': 2, 'arm': 2}) 2686131beabSSimon Glass 2696131beabSSimon Glass def testBoardArchSingle(self): 2706131beabSSimon Glass """Test single board selection""" 2716131beabSSimon Glass self.assertEqual(self.boards.SelectBoards(['arm sandbox']), 2726131beabSSimon Glass {'all': 3, 'arm': 2, 'sandbox' : 1}) 2736131beabSSimon Glass 2746131beabSSimon Glass def testBoardArchSingleMultiWord(self): 2756131beabSSimon Glass """Test single board selection""" 2766131beabSSimon Glass self.assertEqual(self.boards.SelectBoards(['arm', 'sandbox']), 2776131beabSSimon Glass {'all': 3, 'arm': 2, 'sandbox' : 1}) 2786131beabSSimon Glass 2796131beabSSimon Glass def testBoardSingleAnd(self): 2806131beabSSimon Glass """Test single board selection""" 2816131beabSSimon Glass self.assertEqual(self.boards.SelectBoards(['Tester & arm']), 2826131beabSSimon Glass {'all': 2, 'Tester&arm': 2}) 2836131beabSSimon Glass 2846131beabSSimon Glass def testBoardTwoAnd(self): 2856131beabSSimon Glass """Test single board selection""" 2866131beabSSimon Glass self.assertEqual(self.boards.SelectBoards(['Tester', '&', 'arm', 2876131beabSSimon Glass 'Tester' '&', 'powerpc', 2886131beabSSimon Glass 'sandbox']), 2896131beabSSimon Glass {'all': 5, 'Tester&powerpc': 2, 'Tester&arm': 2, 2906131beabSSimon Glass 'sandbox' : 1}) 2916131beabSSimon Glass 2926131beabSSimon Glass def testBoardAll(self): 2936131beabSSimon Glass """Test single board selection""" 2946131beabSSimon Glass self.assertEqual(self.boards.SelectBoards([]), {'all': 5}) 2956131beabSSimon Glass 2966131beabSSimon Glass def testBoardRegularExpression(self): 2976131beabSSimon Glass """Test single board selection""" 2986131beabSSimon Glass self.assertEqual(self.boards.SelectBoards(['T.*r&^Po']), 2996131beabSSimon Glass {'T.*r&^Po': 2, 'all': 2}) 3006131beabSSimon Glass 3016131beabSSimon Glass def testBoardDuplicate(self): 3026131beabSSimon Glass """Test single board selection""" 3036131beabSSimon Glass self.assertEqual(self.boards.SelectBoards(['sandbox sandbox', 3046131beabSSimon Glass 'sandbox']), 3056131beabSSimon Glass {'all': 1, 'sandbox': 1}) 3066131beabSSimon Glass 307fc3fe1c2SSimon Glassif __name__ == "__main__": 308fc3fe1c2SSimon Glass unittest.main() 309