Brad Bishop | 96ff198 | 2019-08-19 13:50:42 -0400 | [diff] [blame^] | 1 | #! /usr/bin/env python3 |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 2 | # |
| 3 | # BitBake Toaster Implementation |
| 4 | # |
Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 5 | # SPDX-License-Identifier: GPL-2.0-only |
| 6 | # |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 7 | # Copyright (C) 2013-2016 Intel Corporation |
| 8 | # |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 9 | |
| 10 | from django.core.urlresolvers import reverse |
| 11 | from django.utils import timezone |
| 12 | from tests.browser.selenium_helpers import SeleniumTestCase |
| 13 | from tests.browser.selenium_helpers_base import Wait |
| 14 | from orm.models import Project, Build, Task, Recipe, Layer, Layer_Version |
| 15 | from bldcontrol.models import BuildRequest |
| 16 | |
| 17 | class TestMostRecentBuildsStates(SeleniumTestCase): |
| 18 | """ Test states update correctly in most recent builds area """ |
| 19 | |
| 20 | def _create_build_request(self): |
| 21 | project = Project.objects.get_or_create_default_project() |
| 22 | |
| 23 | now = timezone.now() |
| 24 | |
| 25 | build = Build.objects.create(project=project, build_name='fakebuild', |
| 26 | started_on=now, completed_on=now) |
| 27 | |
| 28 | return BuildRequest.objects.create(build=build, project=project, |
| 29 | state=BuildRequest.REQ_QUEUED) |
| 30 | |
| 31 | def _create_recipe(self): |
| 32 | """ Add a recipe to the database and return it """ |
| 33 | layer = Layer.objects.create() |
| 34 | layer_version = Layer_Version.objects.create(layer=layer) |
| 35 | return Recipe.objects.create(name='foo', layer_version=layer_version) |
| 36 | |
| 37 | def _check_build_states(self, build_request): |
| 38 | recipes_to_parse = 10 |
| 39 | url = reverse('all-builds') |
| 40 | self.get(url) |
| 41 | |
| 42 | build = build_request.build |
| 43 | base_selector = '[data-latest-build-result="%s"] ' % build.id |
| 44 | |
| 45 | # build queued; check shown as queued |
| 46 | selector = base_selector + '[data-build-state="Queued"]' |
| 47 | element = self.wait_until_visible(selector) |
| 48 | self.assertRegexpMatches(element.get_attribute('innerHTML'), |
| 49 | 'Build queued', 'build should show queued status') |
| 50 | |
| 51 | # waiting for recipes to be parsed |
| 52 | build.outcome = Build.IN_PROGRESS |
| 53 | build.recipes_to_parse = recipes_to_parse |
| 54 | build.recipes_parsed = 0 |
| 55 | |
| 56 | build_request.state = BuildRequest.REQ_INPROGRESS |
| 57 | build_request.save() |
| 58 | |
| 59 | self.get(url) |
| 60 | |
| 61 | selector = base_selector + '[data-build-state="Parsing"]' |
| 62 | element = self.wait_until_visible(selector) |
| 63 | |
| 64 | bar_selector = '#recipes-parsed-percentage-bar-%s' % build.id |
| 65 | bar_element = element.find_element_by_css_selector(bar_selector) |
| 66 | self.assertEqual(bar_element.value_of_css_property('width'), '0px', |
| 67 | 'recipe parse progress should be at 0') |
| 68 | |
| 69 | # recipes being parsed; check parse progress |
| 70 | build.recipes_parsed = 5 |
| 71 | build.save() |
| 72 | |
| 73 | self.get(url) |
| 74 | |
| 75 | element = self.wait_until_visible(selector) |
| 76 | bar_element = element.find_element_by_css_selector(bar_selector) |
| 77 | recipe_bar_updated = lambda driver: \ |
| 78 | bar_element.get_attribute('style') == 'width: 50%;' |
| 79 | msg = 'recipe parse progress bar should update to 50%' |
| 80 | element = Wait(self.driver).until(recipe_bar_updated, msg) |
| 81 | |
| 82 | # all recipes parsed, task started, waiting for first task to finish; |
| 83 | # check status is shown as "Tasks starting..." |
| 84 | build.recipes_parsed = recipes_to_parse |
| 85 | build.save() |
| 86 | |
| 87 | recipe = self._create_recipe() |
| 88 | task1 = Task.objects.create(build=build, recipe=recipe, |
| 89 | task_name='Lionel') |
| 90 | task2 = Task.objects.create(build=build, recipe=recipe, |
| 91 | task_name='Jeffries') |
| 92 | |
| 93 | self.get(url) |
| 94 | |
| 95 | selector = base_selector + '[data-build-state="Starting"]' |
| 96 | element = self.wait_until_visible(selector) |
| 97 | self.assertRegexpMatches(element.get_attribute('innerHTML'), |
| 98 | 'Tasks starting', 'build should show "tasks starting" status') |
| 99 | |
| 100 | # first task finished; check tasks progress bar |
| 101 | task1.order = 1 |
| 102 | task1.save() |
| 103 | |
| 104 | self.get(url) |
| 105 | |
| 106 | selector = base_selector + '[data-build-state="In Progress"]' |
| 107 | element = self.wait_until_visible(selector) |
| 108 | |
| 109 | bar_selector = '#build-pc-done-bar-%s' % build.id |
| 110 | bar_element = element.find_element_by_css_selector(bar_selector) |
| 111 | |
| 112 | task_bar_updated = lambda driver: \ |
| 113 | bar_element.get_attribute('style') == 'width: 50%;' |
| 114 | msg = 'tasks progress bar should update to 50%' |
| 115 | element = Wait(self.driver).until(task_bar_updated, msg) |
| 116 | |
| 117 | # last task finished; check tasks progress bar updates |
| 118 | task2.order = 2 |
| 119 | task2.save() |
| 120 | |
| 121 | self.get(url) |
| 122 | |
| 123 | element = self.wait_until_visible(selector) |
| 124 | bar_element = element.find_element_by_css_selector(bar_selector) |
| 125 | task_bar_updated = lambda driver: \ |
| 126 | bar_element.get_attribute('style') == 'width: 100%;' |
| 127 | msg = 'tasks progress bar should update to 100%' |
| 128 | element = Wait(self.driver).until(task_bar_updated, msg) |
| 129 | |
| 130 | def test_states_to_success(self): |
| 131 | """ |
| 132 | Test state transitions in the recent builds area for a build which |
| 133 | completes successfully. |
| 134 | """ |
| 135 | build_request = self._create_build_request() |
| 136 | |
| 137 | self._check_build_states(build_request) |
| 138 | |
| 139 | # all tasks complete and build succeeded; check success state shown |
| 140 | build = build_request.build |
| 141 | build.outcome = Build.SUCCEEDED |
| 142 | build.save() |
| 143 | |
| 144 | selector = '[data-latest-build-result="%s"] ' \ |
| 145 | '[data-build-state="Succeeded"]' % build.id |
| 146 | element = self.wait_until_visible(selector) |
| 147 | |
| 148 | def test_states_to_failure(self): |
| 149 | """ |
| 150 | Test state transitions in the recent builds area for a build which |
| 151 | completes in a failure. |
| 152 | """ |
| 153 | build_request = self._create_build_request() |
| 154 | |
| 155 | self._check_build_states(build_request) |
| 156 | |
| 157 | # all tasks complete and build succeeded; check fail state shown |
| 158 | build = build_request.build |
| 159 | build.outcome = Build.FAILED |
| 160 | build.save() |
| 161 | |
| 162 | selector = '[data-latest-build-result="%s"] ' \ |
| 163 | '[data-build-state="Failed"]' % build.id |
| 164 | element = self.wait_until_visible(selector) |
| 165 | |
| 166 | def test_states_cancelling(self): |
| 167 | """ |
| 168 | Test that most recent build area updates correctly for a build |
| 169 | which is cancelled. |
| 170 | """ |
| 171 | url = reverse('all-builds') |
| 172 | |
| 173 | build_request = self._create_build_request() |
| 174 | build = build_request.build |
| 175 | |
| 176 | # cancel the build |
| 177 | build_request.state = BuildRequest.REQ_CANCELLING |
| 178 | build_request.save() |
| 179 | |
| 180 | self.get(url) |
| 181 | |
| 182 | # check cancelling state |
| 183 | selector = '[data-latest-build-result="%s"] ' \ |
| 184 | '[data-build-state="Cancelling"]' % build.id |
| 185 | element = self.wait_until_visible(selector) |
| 186 | self.assertRegexpMatches(element.get_attribute('innerHTML'), |
| 187 | 'Cancelling the build', 'build should show "cancelling" status') |
| 188 | |
| 189 | # check cancelled state |
| 190 | build.outcome = Build.CANCELLED |
| 191 | build.save() |
| 192 | |
| 193 | self.get(url) |
| 194 | |
| 195 | selector = '[data-latest-build-result="%s"] ' \ |
| 196 | '[data-build-state="Cancelled"]' % build.id |
| 197 | element = self.wait_until_visible(selector) |
| 198 | self.assertRegexpMatches(element.get_attribute('innerHTML'), |
| 199 | 'Build cancelled', 'build should show "cancelled" status') |