1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# Copyright 2018 The ChromiumOS Authors 3*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 4*760c253cSXin Li# found in the LICENSE file. 5*760c253cSXin Li 6*760c253cSXin Li"""Unittest for buildbot_utils.py.""" 7*760c253cSXin Li 8*760c253cSXin Li 9*760c253cSXin Liimport time 10*760c253cSXin Liimport unittest 11*760c253cSXin Lifrom unittest.mock import patch 12*760c253cSXin Li 13*760c253cSXin Lifrom cros_utils import buildbot_utils 14*760c253cSXin Lifrom cros_utils import command_executer 15*760c253cSXin Li 16*760c253cSXin Li 17*760c253cSXin Liclass TrybotTest(unittest.TestCase): 18*760c253cSXin Li """Test for CommandExecuter class.""" 19*760c253cSXin Li 20*760c253cSXin Li tryjob_out = ( 21*760c253cSXin Li '[{"buildbucket_id": "8952721143823688176", "build_config": ' 22*760c253cSXin Li '"cave-llvm-toolchain-tryjob", "url": ' 23*760c253cSXin Li # pylint: disable=line-too-long 24*760c253cSXin Li '"http://cros-goldeneye/chromeos/healthmonitoring/buildDetails?buildbucketId=8952721143823688176"}]' 25*760c253cSXin Li ) 26*760c253cSXin Li 27*760c253cSXin Li GSUTILS_LS = "\n".join( 28*760c253cSXin Li [ 29*760c253cSXin Li "gs://chromeos-image-archive/{0}/R78-12421.0.0/", 30*760c253cSXin Li "gs://chromeos-image-archive/{0}/R78-12422.0.0/", 31*760c253cSXin Li "gs://chromeos-image-archive/{0}/R78-12423.0.0/", 32*760c253cSXin Li ] 33*760c253cSXin Li ) 34*760c253cSXin Li 35*760c253cSXin Li GSUTILS_LS_RECIPE = "\n".join( 36*760c253cSXin Li [ 37*760c253cSXin Li "gs://chromeos-image-archive/{0}/R83-12995.0.0-30031-8885075268947031/", 38*760c253cSXin Li "gs://chromeos-image-archive/{0}/R83-13003.0.0-30196-8884755532184725/", 39*760c253cSXin Li "gs://chromeos-image-archive/{0}/R83-13003.0.0-30218-8884712858556419/", 40*760c253cSXin Li ] 41*760c253cSXin Li ) 42*760c253cSXin Li 43*760c253cSXin Li buildresult_out = ( 44*760c253cSXin Li '{"8952721143823688176": {"status": "pass", "artifacts_url":' 45*760c253cSXin Li '"gs://chromeos-image-archive/trybot-elm-release-tryjob/R67-10468.0.0-' 46*760c253cSXin Li 'b20789"}}' 47*760c253cSXin Li ) 48*760c253cSXin Li 49*760c253cSXin Li buildbucket_id = "8952721143823688176" 50*760c253cSXin Li counter_1 = 10 51*760c253cSXin Li 52*760c253cSXin Li def testGetTrybotImage(self): 53*760c253cSXin Li with patch.object(buildbot_utils, "SubmitTryjob") as mock_submit: 54*760c253cSXin Li with patch.object(buildbot_utils, "PeekTrybotImage") as mock_peek: 55*760c253cSXin Li with patch.object(time, "sleep", return_value=None): 56*760c253cSXin Li 57*760c253cSXin Li def peek(_chromeos_root, _buildbucket_id): 58*760c253cSXin Li self.counter_1 -= 1 59*760c253cSXin Li if self.counter_1 >= 0: 60*760c253cSXin Li return ("running", "") 61*760c253cSXin Li return ( 62*760c253cSXin Li "pass", 63*760c253cSXin Li "gs://chromeos-image-archive/trybot-elm-release-tryjob/" 64*760c253cSXin Li "R67-10468.0.0-b20789", 65*760c253cSXin Li ) 66*760c253cSXin Li 67*760c253cSXin Li mock_peek.side_effect = peek 68*760c253cSXin Li mock_submit.return_value = self.buildbucket_id 69*760c253cSXin Li 70*760c253cSXin Li # sync 71*760c253cSXin Li buildbucket_id, image = buildbot_utils.GetTrybotImage( 72*760c253cSXin Li "/tmp", "falco-release-tryjob", [] 73*760c253cSXin Li ) 74*760c253cSXin Li self.assertEqual(buildbucket_id, self.buildbucket_id) 75*760c253cSXin Li self.assertEqual( 76*760c253cSXin Li "trybot-elm-release-tryjob/" "R67-10468.0.0-b20789", 77*760c253cSXin Li image, 78*760c253cSXin Li ) 79*760c253cSXin Li 80*760c253cSXin Li # async 81*760c253cSXin Li buildbucket_id, image = buildbot_utils.GetTrybotImage( 82*760c253cSXin Li "/tmp", "falco-release-tryjob", [], asynchronous=True 83*760c253cSXin Li ) 84*760c253cSXin Li self.assertEqual(buildbucket_id, self.buildbucket_id) 85*760c253cSXin Li self.assertEqual(" ", image) 86*760c253cSXin Li 87*760c253cSXin Li def testSubmitTryjob(self): 88*760c253cSXin Li with patch.object( 89*760c253cSXin Li command_executer.CommandExecuter, "RunCommandWOutput" 90*760c253cSXin Li ) as mocked_run: 91*760c253cSXin Li mocked_run.return_value = (0, self.tryjob_out, "") 92*760c253cSXin Li buildbucket_id = buildbot_utils.SubmitTryjob( 93*760c253cSXin Li "/", "falco-release-tryjob", [], [] 94*760c253cSXin Li ) 95*760c253cSXin Li self.assertEqual(buildbucket_id, self.buildbucket_id) 96*760c253cSXin Li 97*760c253cSXin Li def testPeekTrybotImage(self): 98*760c253cSXin Li with patch.object( 99*760c253cSXin Li command_executer.CommandExecuter, "RunCommandWOutput" 100*760c253cSXin Li ) as mocked_run: 101*760c253cSXin Li # pass 102*760c253cSXin Li mocked_run.return_value = (0, self.buildresult_out, "") 103*760c253cSXin Li status, image = buildbot_utils.PeekTrybotImage( 104*760c253cSXin Li "/", self.buildbucket_id 105*760c253cSXin Li ) 106*760c253cSXin Li self.assertEqual("pass", status) 107*760c253cSXin Li self.assertEqual( 108*760c253cSXin Li "gs://chromeos-image-archive/trybot-elm-release-tryjob/" 109*760c253cSXin Li "R67-10468.0.0-b20789", 110*760c253cSXin Li image, 111*760c253cSXin Li ) 112*760c253cSXin Li 113*760c253cSXin Li # running 114*760c253cSXin Li mocked_run.return_value = (1, "", "") 115*760c253cSXin Li status, image = buildbot_utils.PeekTrybotImage( 116*760c253cSXin Li "/", self.buildbucket_id 117*760c253cSXin Li ) 118*760c253cSXin Li self.assertEqual("running", status) 119*760c253cSXin Li self.assertEqual(None, image) 120*760c253cSXin Li 121*760c253cSXin Li # fail 122*760c253cSXin Li buildresult_fail = self.buildresult_out.replace('"pass"', '"fail"') 123*760c253cSXin Li mocked_run.return_value = (0, buildresult_fail, "") 124*760c253cSXin Li status, image = buildbot_utils.PeekTrybotImage( 125*760c253cSXin Li "/", self.buildbucket_id 126*760c253cSXin Li ) 127*760c253cSXin Li self.assertEqual("fail", status) 128*760c253cSXin Li self.assertEqual( 129*760c253cSXin Li "gs://chromeos-image-archive/trybot-elm-release-tryjob/" 130*760c253cSXin Li "R67-10468.0.0-b20789", 131*760c253cSXin Li image, 132*760c253cSXin Li ) 133*760c253cSXin Li 134*760c253cSXin Li def testParseTryjobBuildbucketId(self): 135*760c253cSXin Li buildbucket_id = buildbot_utils.ParseTryjobBuildbucketId( 136*760c253cSXin Li self.tryjob_out 137*760c253cSXin Li ) 138*760c253cSXin Li self.assertEqual(buildbucket_id, self.buildbucket_id) 139*760c253cSXin Li 140*760c253cSXin Li def testGetLatestImageValid(self): 141*760c253cSXin Li with patch.object( 142*760c253cSXin Li command_executer.CommandExecuter, "ChrootRunCommandWOutput" 143*760c253cSXin Li ) as mocked_run: 144*760c253cSXin Li with patch.object( 145*760c253cSXin Li buildbot_utils, "DoesImageExist" 146*760c253cSXin Li ) as mocked_imageexist: 147*760c253cSXin Li IMAGE_DIR = "lulu-release" 148*760c253cSXin Li mocked_run.return_value = ( 149*760c253cSXin Li 0, 150*760c253cSXin Li self.GSUTILS_LS.format(IMAGE_DIR), 151*760c253cSXin Li "", 152*760c253cSXin Li ) 153*760c253cSXin Li mocked_imageexist.return_value = True 154*760c253cSXin Li image = buildbot_utils.GetLatestImage("", IMAGE_DIR) 155*760c253cSXin Li self.assertEqual(image, f"{IMAGE_DIR}/R78-12423.0.0") 156*760c253cSXin Li 157*760c253cSXin Li def testGetLatestImageInvalid(self): 158*760c253cSXin Li with patch.object( 159*760c253cSXin Li command_executer.CommandExecuter, "ChrootRunCommandWOutput" 160*760c253cSXin Li ) as mocked_run: 161*760c253cSXin Li with patch.object( 162*760c253cSXin Li buildbot_utils, "DoesImageExist" 163*760c253cSXin Li ) as mocked_imageexist: 164*760c253cSXin Li IMAGE_DIR = "kefka-release" 165*760c253cSXin Li mocked_run.return_value = ( 166*760c253cSXin Li 0, 167*760c253cSXin Li self.GSUTILS_LS.format(IMAGE_DIR), 168*760c253cSXin Li "", 169*760c253cSXin Li ) 170*760c253cSXin Li mocked_imageexist.return_value = False 171*760c253cSXin Li image = buildbot_utils.GetLatestImage("", IMAGE_DIR) 172*760c253cSXin Li self.assertIsNone(image) 173*760c253cSXin Li 174*760c253cSXin Li def testGetLatestRecipeImageValid(self): 175*760c253cSXin Li with patch.object( 176*760c253cSXin Li command_executer.CommandExecuter, "ChrootRunCommandWOutput" 177*760c253cSXin Li ) as mocked_run: 178*760c253cSXin Li with patch.object( 179*760c253cSXin Li buildbot_utils, "DoesImageExist" 180*760c253cSXin Li ) as mocked_imageexist: 181*760c253cSXin Li IMAGE_DIR = "lulu-llvm-next-nightly" 182*760c253cSXin Li mocked_run.return_value = ( 183*760c253cSXin Li 0, 184*760c253cSXin Li self.GSUTILS_LS_RECIPE.format(IMAGE_DIR), 185*760c253cSXin Li "", 186*760c253cSXin Li ) 187*760c253cSXin Li mocked_imageexist.return_value = True 188*760c253cSXin Li image = buildbot_utils.GetLatestRecipeImage("", IMAGE_DIR) 189*760c253cSXin Li self.assertEqual( 190*760c253cSXin Li image, 191*760c253cSXin Li f"{IMAGE_DIR}/R83-13003.0.0-30218-8884712858556419", 192*760c253cSXin Li ) 193*760c253cSXin Li 194*760c253cSXin Li def testGetLatestRecipeImageInvalid(self): 195*760c253cSXin Li with patch.object( 196*760c253cSXin Li command_executer.CommandExecuter, "ChrootRunCommandWOutput" 197*760c253cSXin Li ) as mocked_run: 198*760c253cSXin Li with patch.object( 199*760c253cSXin Li buildbot_utils, "DoesImageExist" 200*760c253cSXin Li ) as mocked_imageexist: 201*760c253cSXin Li IMAGE_DIR = "kefka-llvm-next-nightly" 202*760c253cSXin Li mocked_run.return_value = ( 203*760c253cSXin Li 0, 204*760c253cSXin Li self.GSUTILS_LS_RECIPE.format(IMAGE_DIR), 205*760c253cSXin Li "", 206*760c253cSXin Li ) 207*760c253cSXin Li mocked_imageexist.return_value = False 208*760c253cSXin Li image = buildbot_utils.GetLatestRecipeImage("", IMAGE_DIR) 209*760c253cSXin Li self.assertIsNone(image) 210*760c253cSXin Li 211*760c253cSXin Li def testGetLatestRecipeImageTwodays(self): 212*760c253cSXin Li with patch.object( 213*760c253cSXin Li command_executer.CommandExecuter, "ChrootRunCommandWOutput" 214*760c253cSXin Li ) as mocked_run: 215*760c253cSXin Li with patch.object( 216*760c253cSXin Li buildbot_utils, "DoesImageExist" 217*760c253cSXin Li ) as mocked_imageexist: 218*760c253cSXin Li IMAGE_DIR = "lulu-llvm-next-nightly" 219*760c253cSXin Li mocked_run.return_value = ( 220*760c253cSXin Li 0, 221*760c253cSXin Li self.GSUTILS_LS_RECIPE.format(IMAGE_DIR), 222*760c253cSXin Li "", 223*760c253cSXin Li ) 224*760c253cSXin Li mocked_imageexist.side_effect = [False, False, True] 225*760c253cSXin Li image = buildbot_utils.GetLatestRecipeImage("", IMAGE_DIR) 226*760c253cSXin Li self.assertIsNone(image) 227*760c253cSXin Li mocked_imageexist.side_effect = [False, True, True] 228*760c253cSXin Li image = buildbot_utils.GetLatestRecipeImage("", IMAGE_DIR) 229*760c253cSXin Li self.assertEqual( 230*760c253cSXin Li image, 231*760c253cSXin Li f"{IMAGE_DIR}/R83-13003.0.0-30196-8884755532184725", 232*760c253cSXin Li ) 233*760c253cSXin Li 234*760c253cSXin Li 235*760c253cSXin Liif __name__ == "__main__": 236*760c253cSXin Li unittest.main() 237