196ff1984SBrad Bishop#! /usr/bin/env python3 2eb8dc403SDave Cobbley# 3eb8dc403SDave Cobbley# BitBake Toaster Implementation 4eb8dc403SDave Cobbley# 5eb8dc403SDave Cobbley# Copyright (C) 2016 Intel Corporation 6eb8dc403SDave Cobbley# 7c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only 8eb8dc403SDave Cobbley# 9eb8dc403SDave Cobbley# Tests were part of openembedded-core oe selftest Authored by: Lucian Musat 10eb8dc403SDave Cobbley# Ionut Chisanovici, Paul Eggleton and Cristian Iorga 11eb8dc403SDave Cobbley 12eb8dc403SDave Cobbleyimport os 13*169d7bccSPatrick Williamsimport pytest 14eb8dc403SDave Cobbley 15eb8dc403SDave Cobbleyfrom django.db.models import Q 16eb8dc403SDave Cobbley 17eb8dc403SDave Cobbleyfrom orm.models import Target_Image_File, Target_Installed_Package, Task 18eb8dc403SDave Cobbleyfrom orm.models import Package_Dependency, Recipe_Dependency, Build 19eb8dc403SDave Cobbleyfrom orm.models import Task_Dependency, Package, Target, Recipe 20eb8dc403SDave Cobbleyfrom orm.models import CustomImagePackage 21eb8dc403SDave Cobbley 22eb8dc403SDave Cobbleyfrom tests.builds.buildtest import BuildTest 23eb8dc403SDave Cobbley 24*169d7bccSPatrick Williams@pytest.mark.order(4) 25*169d7bccSPatrick Williams@pytest.mark.django_db(True) 26eb8dc403SDave Cobbleyclass BuildCoreImageMinimal(BuildTest): 27eb8dc403SDave Cobbley """Build core-image-minimal and test the results""" 28eb8dc403SDave Cobbley 29eb8dc403SDave Cobbley def setUp(self): 30*169d7bccSPatrick Williams self.completed_build = self.target_already_built("core-image-minimal") 31eb8dc403SDave Cobbley 32eb8dc403SDave Cobbley # Check if build name is unique - tc_id=795 33eb8dc403SDave Cobbley def test_Build_Unique_Name(self): 34eb8dc403SDave Cobbley all_builds = Build.objects.all().count() 35eb8dc403SDave Cobbley distinct_builds = Build.objects.values('id').distinct().count() 36eb8dc403SDave Cobbley self.assertEqual(distinct_builds, 37eb8dc403SDave Cobbley all_builds, 38eb8dc403SDave Cobbley msg='Build name is not unique') 39eb8dc403SDave Cobbley 40eb8dc403SDave Cobbley # Check if build cooker log path is unique - tc_id=819 41eb8dc403SDave Cobbley def test_Build_Unique_Cooker_Log_Path(self): 42eb8dc403SDave Cobbley distinct_path = Build.objects.values( 43eb8dc403SDave Cobbley 'cooker_log_path').distinct().count() 44eb8dc403SDave Cobbley total_builds = Build.objects.values('id').count() 45eb8dc403SDave Cobbley self.assertEqual(distinct_path, 46eb8dc403SDave Cobbley total_builds, 47eb8dc403SDave Cobbley msg='Build cooker log path is not unique') 48eb8dc403SDave Cobbley 49eb8dc403SDave Cobbley # Check task order sequence for one build - tc=825 50eb8dc403SDave Cobbley def test_Task_Order_Sequence(self): 51eb8dc403SDave Cobbley cnt_err = [] 52eb8dc403SDave Cobbley tasks = Task.objects.filter( 53eb8dc403SDave Cobbley Q(build=self.completed_build), 54eb8dc403SDave Cobbley ~Q(order=None), 55eb8dc403SDave Cobbley ~Q(task_name__contains='_setscene') 56eb8dc403SDave Cobbley ).values('id', 'order').order_by("order") 57eb8dc403SDave Cobbley 58eb8dc403SDave Cobbley cnt_tasks = 0 59eb8dc403SDave Cobbley for task in tasks: 60eb8dc403SDave Cobbley cnt_tasks += 1 61eb8dc403SDave Cobbley if (task['order'] != cnt_tasks): 62eb8dc403SDave Cobbley cnt_err.append(task['id']) 63eb8dc403SDave Cobbley self.assertEqual( 64eb8dc403SDave Cobbley len(cnt_err), 0, msg='Errors for task id: %s' % cnt_err) 65eb8dc403SDave Cobbley 66eb8dc403SDave Cobbley # Check if disk_io matches the difference between EndTimeIO and 67eb8dc403SDave Cobbley # StartTimeIO in build stats - tc=828 68eb8dc403SDave Cobbley # def test_Task_Disk_IO_TC828(self): 69eb8dc403SDave Cobbley 70eb8dc403SDave Cobbley # Check if outcome = 2 (SSTATE) then sstate_result must be 3 (RESTORED) - 71eb8dc403SDave Cobbley # tc=832 72eb8dc403SDave Cobbley def test_Task_If_Outcome_2_Sstate_Result_Must_Be_3(self): 73eb8dc403SDave Cobbley tasks = Task.objects.filter(outcome=2).values('id', 'sstate_result') 74eb8dc403SDave Cobbley cnt_err = [] 75eb8dc403SDave Cobbley for task in tasks: 76eb8dc403SDave Cobbley if (task['sstate_result'] != 3): 77eb8dc403SDave Cobbley cnt_err.append(task['id']) 78eb8dc403SDave Cobbley 79eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 80eb8dc403SDave Cobbley 0, 81eb8dc403SDave Cobbley msg='Errors for task id: %s' % cnt_err) 82eb8dc403SDave Cobbley 83eb8dc403SDave Cobbley # Check if outcome = 1 (COVERED) or 3 (EXISTING) then sstate_result must 84eb8dc403SDave Cobbley # be 0 (SSTATE_NA) - tc=833 85eb8dc403SDave Cobbley def test_Task_If_Outcome_1_3_Sstate_Result_Must_Be_0(self): 86eb8dc403SDave Cobbley tasks = Task.objects.filter( 87eb8dc403SDave Cobbley outcome__in=(Task.OUTCOME_COVERED, 88eb8dc403SDave Cobbley Task.OUTCOME_PREBUILT)).values('id', 89eb8dc403SDave Cobbley 'task_name', 90eb8dc403SDave Cobbley 'sstate_result') 91eb8dc403SDave Cobbley cnt_err = [] 92eb8dc403SDave Cobbley for task in tasks: 93eb8dc403SDave Cobbley if (task['sstate_result'] != Task.SSTATE_NA and 94eb8dc403SDave Cobbley task['sstate_result'] != Task.SSTATE_MISS): 95eb8dc403SDave Cobbley cnt_err.append({'id': task['id'], 96eb8dc403SDave Cobbley 'name': task['task_name'], 97eb8dc403SDave Cobbley 'sstate_result': task['sstate_result']}) 98eb8dc403SDave Cobbley 99eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 100eb8dc403SDave Cobbley 0, 101eb8dc403SDave Cobbley msg='Errors for task id: %s' % cnt_err) 102eb8dc403SDave Cobbley 103eb8dc403SDave Cobbley # Check if outcome is 0 (SUCCESS) or 4 (FAILED) then sstate_result must be 104eb8dc403SDave Cobbley # 0 (NA), 1 (MISS) or 2 (FAILED) - tc=834 105eb8dc403SDave Cobbley def test_Task_If_Outcome_0_4_Sstate_Result_Must_Be_0_1_2(self): 106eb8dc403SDave Cobbley tasks = Task.objects.filter( 107eb8dc403SDave Cobbley outcome__in=(0, 4)).values('id', 'sstate_result') 108eb8dc403SDave Cobbley cnt_err = [] 109eb8dc403SDave Cobbley 110eb8dc403SDave Cobbley for task in tasks: 111eb8dc403SDave Cobbley if (task['sstate_result'] not in [0, 1, 2]): 112eb8dc403SDave Cobbley cnt_err.append(task['id']) 113eb8dc403SDave Cobbley 114eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 115eb8dc403SDave Cobbley 0, 116eb8dc403SDave Cobbley msg='Errors for task id: %s' % cnt_err) 117eb8dc403SDave Cobbley 118eb8dc403SDave Cobbley # Check if task_executed = TRUE (1), script_type must be 0 (CODING_NA), 2 119eb8dc403SDave Cobbley # (CODING_PYTHON), 3 (CODING_SHELL) - tc=891 120eb8dc403SDave Cobbley def test_Task_If_Task_Executed_True_Script_Type_0_2_3(self): 121eb8dc403SDave Cobbley tasks = Task.objects.filter( 122eb8dc403SDave Cobbley task_executed=1).values('id', 'script_type') 123eb8dc403SDave Cobbley cnt_err = [] 124eb8dc403SDave Cobbley 125eb8dc403SDave Cobbley for task in tasks: 126eb8dc403SDave Cobbley if (task['script_type'] not in [0, 2, 3]): 127eb8dc403SDave Cobbley cnt_err.append(task['id']) 128eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 129eb8dc403SDave Cobbley 0, 130eb8dc403SDave Cobbley msg='Errors for task id: %s' % cnt_err) 131eb8dc403SDave Cobbley 132eb8dc403SDave Cobbley # Check if task_executed = TRUE (1), outcome must be 0 (SUCCESS) or 4 133eb8dc403SDave Cobbley # (FAILED) - tc=836 134eb8dc403SDave Cobbley def test_Task_If_Task_Executed_True_Outcome_0_4(self): 135eb8dc403SDave Cobbley tasks = Task.objects.filter(task_executed=1).values('id', 'outcome') 136eb8dc403SDave Cobbley cnt_err = [] 137eb8dc403SDave Cobbley 138eb8dc403SDave Cobbley for task in tasks: 139eb8dc403SDave Cobbley if (task['outcome'] not in [0, 4]): 140eb8dc403SDave Cobbley cnt_err.append(task['id']) 141eb8dc403SDave Cobbley 142eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 143eb8dc403SDave Cobbley 0, 144eb8dc403SDave Cobbley msg='Errors for task id: %s' % cnt_err) 145eb8dc403SDave Cobbley 146eb8dc403SDave Cobbley # Check if task_executed = FALSE (0), script_type must be 0 - tc=890 147eb8dc403SDave Cobbley def test_Task_If_Task_Executed_False_Script_Type_0(self): 148eb8dc403SDave Cobbley tasks = Task.objects.filter( 149eb8dc403SDave Cobbley task_executed=0).values('id', 'script_type') 150eb8dc403SDave Cobbley cnt_err = [] 151eb8dc403SDave Cobbley 152eb8dc403SDave Cobbley for task in tasks: 153eb8dc403SDave Cobbley if (task['script_type'] != 0): 154eb8dc403SDave Cobbley cnt_err.append(task['id']) 155eb8dc403SDave Cobbley 156eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 157eb8dc403SDave Cobbley 0, 158eb8dc403SDave Cobbley msg='Errors for task id: %s' % cnt_err) 159eb8dc403SDave Cobbley 160eb8dc403SDave Cobbley # Check if task_executed = FALSE (0) and build outcome = SUCCEEDED (0), 161eb8dc403SDave Cobbley # task outcome must be 1 (COVERED), 2 (CACHED), 3 (PREBUILT), 5 (EMPTY) - 162eb8dc403SDave Cobbley # tc=837 163eb8dc403SDave Cobbley def test_Task_If_Task_Executed_False_Outcome_1_2_3_5(self): 164eb8dc403SDave Cobbley builds = Build.objects.filter(outcome=0).values('id') 165eb8dc403SDave Cobbley cnt_err = [] 166eb8dc403SDave Cobbley for build in builds: 167eb8dc403SDave Cobbley tasks = Task.objects.filter( 168eb8dc403SDave Cobbley build=build['id'], task_executed=0).values('id', 'outcome') 169eb8dc403SDave Cobbley for task in tasks: 170eb8dc403SDave Cobbley if (task['outcome'] not in [1, 2, 3, 5]): 171eb8dc403SDave Cobbley cnt_err.append(task['id']) 172eb8dc403SDave Cobbley 173eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 174eb8dc403SDave Cobbley 0, 175eb8dc403SDave Cobbley msg='Errors for task id: %s' % cnt_err) 176eb8dc403SDave Cobbley 177eb8dc403SDave Cobbley # Key verification - tc=888 178eb8dc403SDave Cobbley def test_Target_Installed_Package(self): 179eb8dc403SDave Cobbley rows = Target_Installed_Package.objects.values('id', 180eb8dc403SDave Cobbley 'target_id', 181eb8dc403SDave Cobbley 'package_id') 182eb8dc403SDave Cobbley cnt_err = [] 183eb8dc403SDave Cobbley 184eb8dc403SDave Cobbley for row in rows: 185eb8dc403SDave Cobbley target = Target.objects.filter(id=row['target_id']).values('id') 186eb8dc403SDave Cobbley package = Package.objects.filter(id=row['package_id']).values('id') 187eb8dc403SDave Cobbley if (not target or not package): 188eb8dc403SDave Cobbley cnt_err.append(row['id']) 189eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 190eb8dc403SDave Cobbley 0, 191eb8dc403SDave Cobbley msg='Errors for target installed package id: %s' % 192eb8dc403SDave Cobbley cnt_err) 193eb8dc403SDave Cobbley 194eb8dc403SDave Cobbley # Key verification - tc=889 195eb8dc403SDave Cobbley def test_Task_Dependency(self): 196eb8dc403SDave Cobbley rows = Task_Dependency.objects.values('id', 197eb8dc403SDave Cobbley 'task_id', 198eb8dc403SDave Cobbley 'depends_on_id') 199eb8dc403SDave Cobbley cnt_err = [] 200eb8dc403SDave Cobbley for row in rows: 201eb8dc403SDave Cobbley task_id = Task.objects.filter(id=row['task_id']).values('id') 202eb8dc403SDave Cobbley depends_on_id = Task.objects.filter( 203eb8dc403SDave Cobbley id=row['depends_on_id']).values('id') 204eb8dc403SDave Cobbley if (not task_id or not depends_on_id): 205eb8dc403SDave Cobbley cnt_err.append(row['id']) 206eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 207eb8dc403SDave Cobbley 0, 208eb8dc403SDave Cobbley msg='Errors for task dependency id: %s' % cnt_err) 209eb8dc403SDave Cobbley 210eb8dc403SDave Cobbley # Check if build target file_name is populated only if is_image=true AND 211eb8dc403SDave Cobbley # orm_build.outcome=0 then if the file exists and its size matches 212eb8dc403SDave Cobbley # the file_size value. Need to add the tc in the test run 213eb8dc403SDave Cobbley def test_Target_File_Name_Populated(self): 214*169d7bccSPatrick Williams cnt_err = [] 215eb8dc403SDave Cobbley builds = Build.objects.filter(outcome=0).values('id') 216eb8dc403SDave Cobbley for build in builds: 217eb8dc403SDave Cobbley targets = Target.objects.filter( 218eb8dc403SDave Cobbley build_id=build['id'], is_image=1).values('id') 219eb8dc403SDave Cobbley for target in targets: 220eb8dc403SDave Cobbley target_files = Target_Image_File.objects.filter( 221eb8dc403SDave Cobbley target_id=target['id']).values('id', 222eb8dc403SDave Cobbley 'file_name', 223eb8dc403SDave Cobbley 'file_size') 224eb8dc403SDave Cobbley for file_info in target_files: 225eb8dc403SDave Cobbley target_id = file_info['id'] 226eb8dc403SDave Cobbley target_file_name = file_info['file_name'] 227eb8dc403SDave Cobbley target_file_size = file_info['file_size'] 228eb8dc403SDave Cobbley if (not target_file_name or not target_file_size): 229eb8dc403SDave Cobbley cnt_err.append(target_id) 230eb8dc403SDave Cobbley else: 231eb8dc403SDave Cobbley if (not os.path.exists(target_file_name)): 232eb8dc403SDave Cobbley cnt_err.append(target_id) 233eb8dc403SDave Cobbley else: 234eb8dc403SDave Cobbley if (os.path.getsize(target_file_name) != 235eb8dc403SDave Cobbley target_file_size): 236eb8dc403SDave Cobbley cnt_err.append(target_id) 237eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 0, 238eb8dc403SDave Cobbley msg='Errors for target image file id: %s' % 239eb8dc403SDave Cobbley cnt_err) 240eb8dc403SDave Cobbley 241eb8dc403SDave Cobbley # Key verification - tc=884 242eb8dc403SDave Cobbley def test_Package_Dependency(self): 243eb8dc403SDave Cobbley cnt_err = [] 244eb8dc403SDave Cobbley deps = Package_Dependency.objects.values( 245eb8dc403SDave Cobbley 'id', 'package_id', 'depends_on_id') 246eb8dc403SDave Cobbley for dep in deps: 247eb8dc403SDave Cobbley if (dep['package_id'] == dep['depends_on_id']): 248eb8dc403SDave Cobbley cnt_err.append(dep['id']) 249eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 0, 250eb8dc403SDave Cobbley msg='Errors for package dependency id: %s' % cnt_err) 251eb8dc403SDave Cobbley 252eb8dc403SDave Cobbley # Recipe key verification, recipe name does not depends on a recipe having 253eb8dc403SDave Cobbley # the same name - tc=883 254eb8dc403SDave Cobbley def test_Recipe_Dependency(self): 255eb8dc403SDave Cobbley deps = Recipe_Dependency.objects.values( 256eb8dc403SDave Cobbley 'id', 'recipe_id', 'depends_on_id') 257eb8dc403SDave Cobbley cnt_err = [] 258eb8dc403SDave Cobbley for dep in deps: 259eb8dc403SDave Cobbley if (not dep['recipe_id'] or not dep['depends_on_id']): 260eb8dc403SDave Cobbley cnt_err.append(dep['id']) 261eb8dc403SDave Cobbley else: 262eb8dc403SDave Cobbley name = Recipe.objects.filter( 263eb8dc403SDave Cobbley id=dep['recipe_id']).values('name') 264eb8dc403SDave Cobbley dep_name = Recipe.objects.filter( 265eb8dc403SDave Cobbley id=dep['depends_on_id']).values('name') 266eb8dc403SDave Cobbley if (name == dep_name): 267eb8dc403SDave Cobbley cnt_err.append(dep['id']) 268eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 0, 269eb8dc403SDave Cobbley msg='Errors for recipe dependency id: %s' % cnt_err) 270eb8dc403SDave Cobbley 271eb8dc403SDave Cobbley # Check if package name does not start with a number (0-9) - tc=846 272eb8dc403SDave Cobbley def test_Package_Name_For_Number(self): 273eb8dc403SDave Cobbley packages = Package.objects.filter(~Q(size=-1)).values('id', 'name') 274eb8dc403SDave Cobbley cnt_err = [] 275eb8dc403SDave Cobbley for package in packages: 276eb8dc403SDave Cobbley if (package['name'][0].isdigit() is True): 277eb8dc403SDave Cobbley cnt_err.append(package['id']) 278eb8dc403SDave Cobbley self.assertEqual( 279eb8dc403SDave Cobbley len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err) 280eb8dc403SDave Cobbley 281eb8dc403SDave Cobbley # Check if package version starts with a number (0-9) - tc=847 282eb8dc403SDave Cobbley def test_Package_Version_Starts_With_Number(self): 283eb8dc403SDave Cobbley packages = Package.objects.filter( 284eb8dc403SDave Cobbley ~Q(size=-1)).values('id', 'version') 285eb8dc403SDave Cobbley cnt_err = [] 286eb8dc403SDave Cobbley for package in packages: 287eb8dc403SDave Cobbley if (package['version'][0].isdigit() is False): 288eb8dc403SDave Cobbley cnt_err.append(package['id']) 289eb8dc403SDave Cobbley self.assertEqual( 290eb8dc403SDave Cobbley len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err) 291eb8dc403SDave Cobbley 292eb8dc403SDave Cobbley # Check if package revision starts with 'r' - tc=848 293eb8dc403SDave Cobbley def test_Package_Revision_Starts_With_r(self): 294eb8dc403SDave Cobbley packages = Package.objects.filter( 295eb8dc403SDave Cobbley ~Q(size=-1)).values('id', 'revision') 296eb8dc403SDave Cobbley cnt_err = [] 297eb8dc403SDave Cobbley for package in packages: 298eb8dc403SDave Cobbley if (package['revision'][0].startswith("r") is False): 299eb8dc403SDave Cobbley cnt_err.append(package['id']) 300eb8dc403SDave Cobbley self.assertEqual( 301eb8dc403SDave Cobbley len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err) 302eb8dc403SDave Cobbley 303eb8dc403SDave Cobbley # Check the validity of the package build_id 304eb8dc403SDave Cobbley # TC must be added in test run 305eb8dc403SDave Cobbley def test_Package_Build_Id(self): 306eb8dc403SDave Cobbley packages = Package.objects.filter( 307eb8dc403SDave Cobbley ~Q(size=-1)).values('id', 'build_id') 308eb8dc403SDave Cobbley cnt_err = [] 309eb8dc403SDave Cobbley for package in packages: 310eb8dc403SDave Cobbley build_id = Build.objects.filter( 311eb8dc403SDave Cobbley id=package['build_id']).values('id') 312eb8dc403SDave Cobbley if (not build_id): 313eb8dc403SDave Cobbley # They have no build_id but if they are 314eb8dc403SDave Cobbley # CustomImagePackage that's expected 315eb8dc403SDave Cobbley try: 316eb8dc403SDave Cobbley CustomImagePackage.objects.get(pk=package['id']) 317eb8dc403SDave Cobbley except CustomImagePackage.DoesNotExist: 318eb8dc403SDave Cobbley cnt_err.append(package['id']) 319eb8dc403SDave Cobbley 320eb8dc403SDave Cobbley self.assertEqual(len(cnt_err), 321eb8dc403SDave Cobbley 0, 322eb8dc403SDave Cobbley msg="Errors for package id: %s they have no build" 323eb8dc403SDave Cobbley "associated with them" % cnt_err) 324eb8dc403SDave Cobbley 325eb8dc403SDave Cobbley # Check the validity of package recipe_id 326eb8dc403SDave Cobbley # TC must be added in test run 327eb8dc403SDave Cobbley def test_Package_Recipe_Id(self): 328eb8dc403SDave Cobbley packages = Package.objects.filter( 329eb8dc403SDave Cobbley ~Q(size=-1)).values('id', 'recipe_id') 330eb8dc403SDave Cobbley cnt_err = [] 331eb8dc403SDave Cobbley for package in packages: 332eb8dc403SDave Cobbley recipe_id = Recipe.objects.filter( 333eb8dc403SDave Cobbley id=package['recipe_id']).values('id') 334eb8dc403SDave Cobbley if (not recipe_id): 335eb8dc403SDave Cobbley cnt_err.append(package['id']) 336eb8dc403SDave Cobbley self.assertEqual( 337eb8dc403SDave Cobbley len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err) 338eb8dc403SDave Cobbley 339eb8dc403SDave Cobbley # Check if package installed_size field is not null 340eb8dc403SDave Cobbley # TC must be aded in test run 341eb8dc403SDave Cobbley def test_Package_Installed_Size_Not_NULL(self): 342eb8dc403SDave Cobbley packages = Package.objects.filter( 343eb8dc403SDave Cobbley installed_size__isnull=True).values('id') 344eb8dc403SDave Cobbley cnt_err = [] 345eb8dc403SDave Cobbley for package in packages: 346eb8dc403SDave Cobbley cnt_err.append(package['id']) 347eb8dc403SDave Cobbley self.assertEqual( 348eb8dc403SDave Cobbley len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err) 349eb8dc403SDave Cobbley 350eb8dc403SDave Cobbley def test_custom_packages_generated(self): 351eb8dc403SDave Cobbley """Test if there is a corresponding generated CustomImagePackage""" 352eb8dc403SDave Cobbley """ for each of the packages generated""" 353eb8dc403SDave Cobbley missing_packages = [] 354eb8dc403SDave Cobbley 355eb8dc403SDave Cobbley for package in Package.objects.all(): 356eb8dc403SDave Cobbley try: 357eb8dc403SDave Cobbley CustomImagePackage.objects.get(name=package.name) 358eb8dc403SDave Cobbley except CustomImagePackage.DoesNotExist: 359eb8dc403SDave Cobbley missing_packages.append(package.name) 360eb8dc403SDave Cobbley 361eb8dc403SDave Cobbley self.assertEqual(len(missing_packages), 0, 362eb8dc403SDave Cobbley "Some package were created from the build but their" 363eb8dc403SDave Cobbley " corresponding CustomImagePackage was not found") 364