toaster: Fixes and clean ups
cover toaster: Fixes and clean ups
Hi,
This is series is available on the poky-contrib repository branch michaelw/toaster/tests_fixes_and_clean_ups
Note: this removes the tts contrib directory which is redundant.
The following changes since commit ef627ab364d52fe19994c94c1a78fbe21620a32c:
local.conf.sample.extended: remove RM_OLD_IMAGE (2016-10-19 17:07:41 +0100)
are available in the git repository at:
git://git.yoctoproject.org/poky-contrib ed/toaster/submit/michaelw/toaster/tests_fixes_and_clean_ups
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=ed/toaster/submit/michaelw/toaster/tests_fixes_and_clean_ups
Michael Wood (8):
toaster: views Tests fix all pyflake identified issues
toaster: Move views tests to main testing module
toaster: Delete useless bldcontrol/test
toaster: Remove contrib tts
toaster: test browser test_layerdetails_page add wait_until_visible
toaster: orm models Handle run builds process not yet running
toaster: tests builds Update buildtest
toaster: tests builds test_core_image_min Clean ups
lib/toaster/bldcontrol/tests.py | 141 --
lib/toaster/contrib/README | 6 -
lib/toaster/contrib/tts/README | 41 -
lib/toaster/contrib/tts/TODO | 9 -
lib/toaster/contrib/tts/config.py | 98 -
lib/toaster/contrib/tts/launcher.py | 101 -
lib/toaster/contrib/tts/recv.py | 56 -
lib/toaster/contrib/tts/runner.py | 222 --
lib/toaster/contrib/tts/settings.json | 5 -
lib/toaster/contrib/tts/shellutils.py | 141 --
lib/toaster/contrib/tts/tests.py | 115 -
.../contrib/tts/toasteruitest/run_toastertests.py | 155 --
.../tts/toasteruitest/toaster_automation_test.py | 2376 --------------------
.../contrib/tts/toasteruitest/toaster_test.cfg | 25 -
lib/toaster/contrib/tts/urlcheck.py | 53 -
lib/toaster/contrib/tts/urllist.py | 39 -
lib/toaster/orm/models.py | 8 +-
.../tests/browser/test_layerdetails_page.py | 3 +-
lib/toaster/tests/builds/buildtest.py | 129 +-
lib/toaster/tests/builds/test_core_image_min.py | 50 +-
lib/toaster/tests/views/README | 4 +
.../tts/log/.create => tests/views/__init__.py} | 0
.../tests.py => tests/views/test_views.py} | 95 +-
23 files changed, 160 insertions(+), 3712 deletions(-)
delete mode 100644 bitbake/lib/toaster/bldcontrol/tests.py
delete mode 100644 bitbake/lib/toaster/contrib/README
delete mode 100644 bitbake/lib/toaster/contrib/tts/README
delete mode 100644 bitbake/lib/toaster/contrib/tts/TODO
delete mode 100644 bitbake/lib/toaster/contrib/tts/config.py
delete mode 100755 bitbake/lib/toaster/contrib/tts/launcher.py
delete mode 100755 bitbake/lib/toaster/contrib/tts/recv.py
delete mode 100755 bitbake/lib/toaster/contrib/tts/runner.py
delete mode 100644 bitbake/lib/toaster/contrib/tts/settings.json
delete mode 100644 bitbake/lib/toaster/contrib/tts/shellutils.py
delete mode 100644 bitbake/lib/toaster/contrib/tts/tests.py
delete mode 100755 bitbake/lib/toaster/contrib/tts/toasteruitest/run_toastertests.py
delete mode 100755 bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py
delete mode 100644 bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_test.cfg
delete mode 100644 bitbake/lib/toaster/contrib/tts/urlcheck.py
delete mode 100644 bitbake/lib/toaster/contrib/tts/urllist.py
create mode 100644 bitbake/lib/toaster/tests/views/README
rename bitbake/lib/toaster/{contrib/tts/log/.create => tests/views/__init__.py} (100%)
rename bitbake/lib/toaster/{toastergui/tests.py => tests/views/test_views.py} (89%)Signature · 1 line
2.1.4
PATCH 1/8 toaster: views Tests fix all pyflake identified issues
From: Michael Wood <[email protected]>
--- lib/toaster/toastergui/tests.py | 95 ++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 48 deletions(-)
lib/toaster/toastergui/tests.py +47 -48
@@ -24,31 +24,26 @@ from django.test import TestCase from django.test.client import RequestFactory from django.core.urlresolvers import reverse -from django.utils import timezone from django.db.models import Q -from orm.models import Project, Release, BitbakeVersion, Package, LogMessage -from orm.models import LayerSource, Layer, Build -from orm.models import Layer_Version, Recipe, Machine, ProjectLayer, Target -from orm.models import CustomImageRecipe, ProjectVariable +from orm.models import Project, Package +from orm.models import Layer_Version, Recipe +from orm.models import CustomImageRecipe from orm.models import CustomImagePackage -import toastermain import inspect import toastergui from toastergui.tables import SoftwareRecipesTable import json -from datetime import timedelta from bs4 import BeautifulSoup -import re import string -import json PROJECT_NAME = "test project" PROJECT_NAME2 = "test project 2" CLI_BUILDS_PROJECT_NAME = 'Command line builds' + class ViewTests(TestCase): """Tests to verify view APIs."""
@@ -75,7 +70,8 @@ class ViewTests(TestCase): url = reverse('all-projects') response = self.client.get(url, {"format": "json"}, follow=True) self.assertEqual(response.status_code, 200) - self.assertTrue(response['Content-Type'].startswith('application/json')) + self.assertTrue(response['Content-Type'].startswith( + 'application/json')) data = json.loads(response.content.decode('utf-8'))
@@ -98,13 +94,13 @@ class ViewTests(TestCase): urls = [layers_url, prj_url, reverse('xhr_recipestypeahead', args=(self.project.id,)), - reverse('xhr_machinestypeahead', args=(self.project.id,)), - ] + reverse('xhr_machinestypeahead', args=(self.project.id,))] def basic_reponse_check(response, url): """Check data structure of http response.""" self.assertEqual(response.status_code, 200) - self.assertTrue(response['Content-Type'].startswith('application/json')) + self.assertTrue(response['Content-Type'].startswith( + 'application/json')) data = json.loads(response.content.decode('utf-8'))
@@ -133,7 +129,6 @@ class ViewTests(TestCase): return False - for url in urls: results = False
@@ -149,31 +144,31 @@ class ViewTests(TestCase): def test_xhr_import_layer(self): """Test xhr_importlayer API""" - #Test for importing an already existing layer - args = {'vcs_url' : "git://git.example.com/test", - 'name' : "base-layer", + # Test for importing an already existing layer + args = {'vcs_url': "git://git.example.com/test", + 'name': "base-layer", 'git_ref': "c12b9596afd236116b25ce26dbe0d793de9dc7ce", 'project_id': self.project.id, 'local_source_dir': "", - 'dir_path' : "/path/in/repository"} + 'dir_path': "/path/in/repository"} response = self.client.post(reverse('xhr_importlayer'), args) data = json.loads(response.content.decode('utf-8')) self.assertEqual(response.status_code, 200) self.assertEqual(data["error"], "ok") - #Test to verify import of a layer successful + # Test to verify import of a layer successful args['name'] = "meta-oe" response = self.client.post(reverse('xhr_importlayer'), args) data = json.loads(response.content.decode('utf-8')) self.assertTrue(data["error"], "ok") - #Test for html tag in the data + # Test for html tag in the data args['<'] = "testing html tag" response = self.client.post(reverse('xhr_importlayer'), args) data = json.loads(response.content.decode('utf-8')) self.assertNotEqual(data["error"], "ok") - #Empty data passed + # Empty data passed args = {} response = self.client.post(reverse('xhr_importlayer'), args) data = json.loads(response.content.decode('utf-8'))
@@ -232,15 +227,14 @@ class ViewTests(TestCase): "info": {'id': self.customr.id, 'name': self.customr.name, 'base_recipe_id': self.recipe1.id, - 'project_id': self.project.id, - } - } - self.assertEqual(json.loads(response.content.decode('utf-8')), expected) + 'project_id': self.project.id}} + self.assertEqual(json.loads(response.content.decode('utf-8')), + expected) def test_xhr_custom_del(self): """Test deleting custom recipe""" name = "to be deleted" - recipe = CustomImageRecipe.objects.create(\ + recipe = CustomImageRecipe.objects.create( name=name, project=self.project, base_recipe=self.recipe1, file_path="/tmp/testing",
@@ -259,7 +253,8 @@ class ViewTests(TestCase): url = reverse('xhr_customrecipe_id', args=(recipe.id,)) response = self.client.delete(url) self.assertEqual(response.status_code, 200) - self.assertNotEqual(json.loads(response.content.decode('utf-8'))["error"], "ok") + self.assertNotEqual(json.loads( + response.content.decode('utf-8'))["error"], "ok") def test_xhr_custom_packages(self): """Test adding and deleting package to a custom recipe"""
@@ -280,7 +275,8 @@ class ViewTests(TestCase): response = self.client.delete(del_url) self.assertEqual(response.status_code, 200) - self.assertEqual(json.loads(response.content.decode('utf-8')), {"error": "ok"}) + self.assertEqual(json.loads(response.content.decode('utf-8')), + {"error": "ok"}) all_packages = self.customr.get_all_packages().values_list('pk', flat=True)
@@ -292,7 +288,8 @@ class ViewTests(TestCase): response = self.client.delete(del_url) self.assertEqual(response.status_code, 200) - self.assertNotEqual(json.loads(response.content.decode('utf-8'))["error"], "ok") + self.assertNotEqual(json.loads( + response.content.decode('utf-8'))["error"], "ok") def test_xhr_custom_packages_err(self): """Test error conditions of xhr_customrecipe_packages"""
@@ -303,8 +300,9 @@ class ViewTests(TestCase): for method in (self.client.put, self.client.delete): response = method(url) self.assertEqual(response.status_code, 200) - self.assertNotEqual(json.loads(response.content.decode('utf-8')), - {"error": "ok"}) + self.assertNotEqual(json.loads( + response.content.decode('utf-8')), + {"error": "ok"}) def test_download_custom_recipe(self): """Download the recipe file generated for the custom image"""
@@ -490,27 +488,28 @@ class ViewTests(TestCase): # filter string to pass as the option # This is the name of the filter:action # e.g. project_filter:not_in_project - filter_string = "%s:%s" % (column['filter_name'], - filter_action['action_name']) + filter_string = "%s:%s" % ( + column['filter_name'], + filter_action['action_name']) # Now get the data with the filter applied filtered_data = get_data(table_cls(), - {"filter" : filter_string}) + {"filter": filter_string}) # date range filter actions can't specify the # number of results they return, so their count is 0 - if filter_action['count'] != None: - self.assertEqual(len(filtered_data['rows']), - int(filter_action['count']), - "We added a table filter for %s but " - "the number of rows returned was not " - "what the filter info said there " - "would be" % name) - + if filter_action['count'] is not None: + self.assertEqual( + len(filtered_data['rows']), + int(filter_action['count']), + "We added a table filter for %s but " + "the number of rows returned was not " + "what the filter info said there " + "would be" % name) # Test search functionality on the table something_found = False for search in list(string.ascii_letters): - search_data = get_data(table_cls(), {'search' : search}) + search_data = get_data(table_cls(), {'search': search}) if len(search_data['rows']) > 0: something_found = True
@@ -521,20 +520,20 @@ class ViewTests(TestCase): " was found for the search of table %s" % name) # Test the limit functionality on the table - limited_data = get_data(table_cls(), {'limit' : "1"}) + limited_data = get_data(table_cls(), {'limit': "1"}) self.assertEqual(len(limited_data['rows']), 1, "Limit 1 set on table %s but not 1 row returned" % name) # Test the pagination functionality on the table - page_one_data = get_data(table_cls(), {'limit' : "1", + page_one_data = get_data(table_cls(), {'limit': "1", "page": "1"})['rows'][0] - page_two_data = get_data(table_cls(), {'limit' : "1", + page_two_data = get_data(table_cls(), {'limit': "1", "page": "2"})['rows'][0] self.assertNotEqual(page_one_data, page_two_data, - "Changed page on table %s but first row is the " - "same as the previous page" % name) + "Changed page on table %s but first row is" + " the same as the previous page" % name)
Signature · 1 line
2.1.4
PATCH 2/8 toaster: Move views tests to main testing module
From: Michael Wood <[email protected]>
Consolidating all the tests to live in the same place to make them more discoverable and consistent as well as not cluttering up the django app directory.
---
lib/toaster/tests/views/README | 4 ++++
lib/toaster/tests/views/__init__.py | 0
lib/toaster/{toastergui/tests.py => tests/views/test_views.py} | 0
3 files changed, 4 insertions(+)
create mode 100644 bitbake/lib/toaster/tests/views/README
create mode 100644 bitbake/lib/toaster/tests/views/__init__.py
rename bitbake/lib/toaster/{toastergui/tests.py => tests/views/test_views.py} (100%)lib/toaster/tests/views/README new file +4 -0
@@ -0,0 +1,4 @@ + +Django unit tests to verify classes and functions based on django Views + +To run just these tests use ./manage.py test tests.views
lib/toaster/tests/views/__init__.py new file +0 -0
lib/toaster/tests/views/test_views.py renamed from lib/toaster/toastergui/tests.py +0 -0
Signature · 1 line
2.1.4
PATCH 3/8 toaster: Delete useless bldcontrol/test
In reply to Ed BartoshFrom: Michael Wood <[email protected]>
It doesn't work nor does it test anything useful
--- lib/toaster/bldcontrol/tests.py | 141 ---------------------------------------- 1 file changed, 141 deletions(-) delete mode 100644 bitbake/lib/toaster/bldcontrol/tests.py
lib/toaster/bldcontrol/tests.py deleted +0 -141
@@ -1,141 +0,0 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" - -from django.test import TestCase - -from bldcontrol.bbcontroller import BitbakeController, BuildSetupException -from bldcontrol.localhostbecontroller import LocalhostBEController -from bldcontrol.models import BuildEnvironment, BuildRequest -from bldcontrol.management.commands.runbuilds import Command - -import socket -import subprocess -import os - -# standard poky data hardcoded for testing -BITBAKE_LAYER = type('bitbake_info', (object,), { "giturl": "git://git.yoctoproject.org/poky.git", "dirpath": "", "commit": "HEAD"}) -POKY_LAYERS = [ - type('poky_info', (object,), { "name": "meta", "giturl": "git://git.yoctoproject.org/poky.git", "dirpath": "meta", "commit": "HEAD"}), - type('poky_info', (object,), { "name": "meta-yocto", "giturl": "git://git.yoctoproject.org/poky.git", "dirpath": "meta-yocto", "commit": "HEAD"}), - type('poky_info', (object,), { "name": "meta-yocto-bsp", "giturl": "git://git.yoctoproject.org/poky.git", "dirpath": "meta-yocto-bsp", "commit": "HEAD"}), - ] - - - -# we have an abstract test class designed to ensure that the controllers use a single interface -# specific controller tests only need to override the _getBuildEnvironment() method - -test_sourcedir = os.getenv("TTS_SOURCE_DIR") -test_builddir = os.getenv("TTS_BUILD_DIR") -test_address = os.getenv("TTS_TEST_ADDRESS", "localhost") - -if test_sourcedir == None or test_builddir == None or test_address == None: - raise Exception("Please set TTTS_SOURCE_DIR, TTS_BUILD_DIR and TTS_TEST_ADDRESS") - -# The bb server will expect a toaster-pre.conf file to exist. If it doesn't exit then we make -# an empty one here. -open(test_builddir + 'conf/toaster-pre.conf', 'a').close() - -class BEControllerTests(object): - - def _serverForceStop(self, bc): - err = bc._shellcmd("netstat -tapn 2>/dev/null | grep 8200 | awk '{print $7}' | sort -fu | cut -d \"/\" -f 1 | grep -v -- - | tee /dev/fd/2 | xargs -r kill") - self.assertTrue(err == '', "bitbake server pid %s not stopped" % err) - - def test_serverStartAndStop(self): - obe = self._getBuildEnvironment() - bc = self._getBEController(obe) - try: - # setting layers, skip any layer info - bc.setLayers(BITBAKE_LAYER, POKY_LAYERS) - except NotImplementedError: - print("Test skipped due to command not implemented yet") - return True - # We are ok with the exception as we're handling the git already exists - except BuildSetupException: - pass - - bc.pokydirname = test_sourcedir - bc.islayerset = True - - hostname = test_address.split("@")[-1] - - # test start server and stop - bc.startBBServer() - - self.assertFalse(socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex((hostname, int(bc.be.bbport))), "Server not answering") - - self._serverForceStop(bc) - - def test_getBBController(self): - obe = self._getBuildEnvironment() - bc = self._getBEController(obe) - layerSet = False - try: - # setting layers, skip any layer info - layerSet = bc.setLayers(BITBAKE_LAYER, POKY_LAYERS) - except NotImplementedError: - print("Test skipped due to command not implemented yet") - return True - # We are ok with the exception as we're handling the git already exists - except BuildSetupException: - pass - - bc.pokydirname = test_sourcedir - bc.islayerset = True - - bbc = bc.getBBController() - self.assertTrue(isinstance(bbc, BitbakeController)) - - self._serverForceStop(bc) - -class LocalhostBEControllerTests(TestCase, BEControllerTests): - def __init__(self, *args): - super(LocalhostBEControllerTests, self).__init__(*args) - - - def _getBuildEnvironment(self): - return BuildEnvironment.objects.create( - lock = BuildEnvironment.LOCK_FREE, - betype = BuildEnvironment.TYPE_LOCAL, - address = test_address, - sourcedir = test_sourcedir, - builddir = test_builddir ) - - def _getBEController(self, obe): - return LocalhostBEController(obe) - -class RunBuildsCommandTests(TestCase): - def test_bec_select(self): - """ - Tests that we can find and lock a build environment - """ - - obe = BuildEnvironment.objects.create(lock = BuildEnvironment.LOCK_FREE, betype = BuildEnvironment.TYPE_LOCAL) - command = Command() - bec = command._selectBuildEnvironment() - - # make sure we select the object we've just built - self.assertTrue(bec.be.id == obe.id, "Environment is not properly selected") - # we have a locked environment - self.assertTrue(bec.be.lock == BuildEnvironment.LOCK_LOCK, "Environment is not locked") - # no more selections possible here - self.assertRaises(IndexError, command._selectBuildEnvironment) - - def test_br_select(self): - from orm.models import Project, Release, BitbakeVersion, Branch - p = Project.objects.create_project("test", Release.objects.get_or_create(name = "HEAD", bitbake_version = BitbakeVersion.objects.get_or_create(name="HEAD", branch=Branch.objects.get_or_create(name="HEAD"))[0])[0]) - obr = BuildRequest.objects.create(state = BuildRequest.REQ_QUEUED, project = p) - command = Command() - br = command._selectBuildRequest() - - # make sure we select the object we've just built - self.assertTrue(obr.id == br.id, "Request is not properly selected") - # we have a locked environment - self.assertTrue(br.state == BuildRequest.REQ_INPROGRESS, "Request is not updated") - # no more selections possible here - self.assertRaises(IndexError, command._selectBuildRequest)
Signature · 1 line
2.1.4
PATCH 4/8 toaster: Remove contrib tts
In reply to Ed BartoshFrom: Michael Wood <[email protected]>
Remove the "Toaster test system". We don't need a home brew test "framework" as the django test runner is more than adequate. None of these tests here are currently working and have been obsoleted by the work done on unit and browser tests in ./tests/.
--- lib/toaster/contrib/README | 6 - lib/toaster/contrib/tts/README | 41 - lib/toaster/contrib/tts/TODO | 9 - lib/toaster/contrib/tts/config.py | 98 - lib/toaster/contrib/tts/launcher.py | 101 - lib/toaster/contrib/tts/log/.create | 0 lib/toaster/contrib/tts/recv.py | 56 - lib/toaster/contrib/tts/runner.py | 222 -- lib/toaster/contrib/tts/settings.json | 5 - lib/toaster/contrib/tts/shellutils.py | 141 -- lib/toaster/contrib/tts/tests.py | 115 - .../contrib/tts/toasteruitest/run_toastertests.py | 155 -- .../tts/toasteruitest/toaster_automation_test.py | 2376 -------------------- .../contrib/tts/toasteruitest/toaster_test.cfg | 25 - lib/toaster/contrib/tts/urlcheck.py | 53 - lib/toaster/contrib/tts/urllist.py | 39 - 16 files changed, 3442 deletions(-) delete mode 100644 bitbake/lib/toaster/contrib/README delete mode 100644 bitbake/lib/toaster/contrib/tts/README delete mode 100644 bitbake/lib/toaster/contrib/tts/TODO delete mode 100644 bitbake/lib/toaster/contrib/tts/config.py delete mode 100755 bitbake/lib/toaster/contrib/tts/launcher.py delete mode 100644 bitbake/lib/toaster/contrib/tts/log/.create delete mode 100755 bitbake/lib/toaster/contrib/tts/recv.py delete mode 100755 bitbake/lib/toaster/contrib/tts/runner.py delete mode 100644 bitbake/lib/toaster/contrib/tts/settings.json delete mode 100644 bitbake/lib/toaster/contrib/tts/shellutils.py delete mode 100644 bitbake/lib/toaster/contrib/tts/tests.py delete mode 100755 bitbake/lib/toaster/contrib/tts/toasteruitest/run_toastertests.py delete mode 100755 bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py delete mode 100644 bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_test.cfg delete mode 100644 bitbake/lib/toaster/contrib/tts/urlcheck.py delete mode 100644 bitbake/lib/toaster/contrib/tts/urllist.py
lib/toaster/contrib/README deleted +0 -6
@@ -1,6 +0,0 @@ -contrib directory for toaster - -This directory holds code that works with Toaster, without being an integral part of the Toaster project. -It is intended for testing code, testing fixtures, tools for Toaster, etc. - -NOTE: This directory is NOT a Python module.
lib/toaster/contrib/tts/README deleted +0 -41
41 lines not on this page · raw message
lib/toaster/contrib/tts/TODO deleted +0 -9
@@ -1,9 +0,0 @@ -We need to implement tests: - -automated link checker; currently -$ linkchecker -t 1000 -F csv http://localhost:8000/ - -integrate the w3c-validation service; currently -$ python urlcheck.py - -
lib/toaster/contrib/tts/config.py deleted +0 -98
98 lines not on this page · raw message
lib/toaster/contrib/tts/launcher.py deleted +0 -101
101 lines not on this page · raw message
lib/toaster/contrib/tts/log/.create deleted +0 -0
lib/toaster/contrib/tts/recv.py deleted +0 -56
56 lines not on this page · raw message
lib/toaster/contrib/tts/runner.py deleted +0 -222
222 lines not on this page · raw message
lib/toaster/contrib/tts/settings.json deleted +0 -5
@@ -1,5 +0,0 @@ -{ - "repo": "[email protected]:poky-contrib", - "localclone": "/home/ddalex/ssd/yocto/poky", - "workdir": "/home/ddalex/ssd/yocto" -}
lib/toaster/contrib/tts/shellutils.py deleted +0 -141
141 lines not on this page · raw message
lib/toaster/contrib/tts/tests.py deleted +0 -115
115 lines not on this page · raw message
lib/toaster/contrib/tts/toasteruitest/run_toastertests.py deleted +0 -155
155 lines not on this page · raw message
lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py deleted +0 -2376
2,051 lines not on this page · raw message
lib/toaster/contrib/tts/toasteruitest/toaster_test.cfg deleted +0 -25
Lines of this file are not shown. View the raw message.
lib/toaster/contrib/tts/urlcheck.py deleted +0 -53
53 lines not on this page · raw message
lib/toaster/contrib/tts/urllist.py deleted +0 -39
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.1.4
Part of the diff is not shown here. View the raw message.
PATCH 5/8 toaster: test browser test_layerdetails_page add wait_until_visible
In reply to Ed BartoshFrom: Michael Wood <[email protected]>
Add an additional wait_until_visible for the save buttons as firefox animates this into view so slowly we get a race on them being visible
--- lib/toaster/tests/browser/test_layerdetails_page.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
lib/toaster/tests/browser/test_layerdetails_page.py +2 -1
@@ -91,9 +91,10 @@ class TestLayerDetailsPage(SeleniumTestCase): for btn in self.find_all("dd .glyphicon-edit"): btn.click() - # Wait for the inputs to become visible + # Wait for the inputs to become visible after animation self.wait_until_visible("#layer-git input[type=text]") self.wait_until_visible("dd textarea") + self.wait_until_visible("dd .change-btn") # Edit each value for inputs in self.find_all("#layer-git input[type=text]") + \
Signature · 1 line
2.1.4
PATCH 6/8 toaster: orm models Handle run builds process not yet running
In reply to Ed BartoshFrom: Michael Wood <[email protected]>
During tests we may want to call the runbuilds process manually for example when doing a "one shot" approach rather than a long running process during tests.
--- lib/toaster/orm/models.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
lib/toaster/orm/models.py +6 -2
@@ -1741,8 +1741,12 @@ def invalidate_cache(**kwargs): def signal_runbuilds(): """Send SIGUSR1 to runbuilds process""" - with open(os.path.join(os.getenv('BUILDDIR'), '.runbuilds.pid')) as pidf: - os.kill(int(pidf.read()), SIGUSR1) + try: + with open(os.path.join(os.getenv('BUILDDIR'), + '.runbuilds.pid')) as pidf: + os.kill(int(pidf.read()), SIGUSR1) + except FileNotFoundError: + logger.info("Stopping existing runbuilds: no current process found") django.db.models.signals.post_save.connect(invalidate_cache) django.db.models.signals.post_delete.connect(invalidate_cache)
Signature · 1 line
2.1.4
PATCH 7/8 toaster: tests builds Update buildtest
In reply to Ed BartoshFrom: Michael Wood <[email protected]>
Now that we're using fixtures for configuration just load these instead of trying to search for a toasterconf json file.
Also for convenience add the ability for the tests to source the build environment script. To use this test make sure that directories are in the same layout as poky.
--- lib/toaster/tests/builds/buildtest.py | 129 +++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 48 deletions(-)
lib/toaster/tests/builds/buildtest.py +81 -48
@@ -24,16 +24,18 @@ import sys import time import unittest -from orm.models import Project, Release, ProjectTarget, Build +from orm.models import Project, Release, ProjectTarget, Build, ProjectVariable from bldcontrol.models import BuildEnvironment -from bldcontrol.management.commands.loadconf import Command\ - as LoadConfigCommand - from bldcontrol.management.commands.runbuilds import Command\ as RunBuildsCommand +from django.core.management import call_command + import subprocess +import logging + +logger = logging.getLogger("toaster") # We use unittest.TestCase instead of django.test.TestCase because we don't # want to wrap everything in a database transaction as an external process
@@ -43,63 +45,92 @@ import subprocess class BuildTest(unittest.TestCase): PROJECT_NAME = "Testbuild" + BUILDDIR = "/tmp/build/" def build(self, target): # So that the buildinfo helper uses the test database' self.assertEqual( os.environ.get('DJANGO_SETTINGS_MODULE', ''), - 'toastermain.settings-test', + 'toastermain.settings_test', "Please initialise django with the tests settings: " - "DJANGO_SETTINGS_MODULE='toastermain.settings-test'") + "DJANGO_SETTINGS_MODULE='toastermain.settings_test'") - if self.target_already_built(target): - return + built = self.target_already_built(target) + if built: + return built - # Take a guess at the location of the toasterconf - poky_toaster_conf = '../../../meta-poky/conf/toasterconf.json' - oe_toaster_conf = '../../../meta/conf/toasterconf.json' - env_toaster_conf = os.environ.get('TOASTER_CONF') + call_command('loaddata', 'settings.xml', app_label="orm") + call_command('loaddata', 'poky.xml', app_label="orm") - config_file = None - if env_toaster_conf: - config_file = env_toaster_conf + current_builddir = os.environ.get("BUILDDIR") + if current_builddir: + BuildTest.BUILDDIR = current_builddir else: - if os.path.exists(poky_toaster_conf): - config_file = poky_toaster_conf - elif os.path.exists(oe_toaster_conf): - config_file = oe_toaster_conf - - self.assertIsNotNone(config_file, - "Default locations for toasterconf not found" - "please set $TOASTER_CONF manually") - - # Setup the release information and default layers - print("\nImporting file: %s" % config_file) - os.environ['TOASTER_CONF'] = config_file - LoadConfigCommand()._import_layer_config(config_file) - - os.environ['TOASTER_DIR'] = \ - os.path.abspath(os.environ['BUILDDIR'] + "/../") - - os.environ['BBBASEDIR'] = \ - subprocess.check_output('which bitbake', shell=True) + # Setup a builddir based on default layout + # bitbake inside openebedded-core + oe_init_build_env_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + os.pardir, + os.pardir, + os.pardir, + os.pardir, + os.pardir, + 'oe-init-build-env' + ) + if not os.path.exists(oe_init_build_env_path): + raise Exception("We had no BUILDDIR set and couldn't " + "find oe-init-build-env to set this up " + "ourselves please run oe-init-build-env " + "before running these tests") + + oe_init_build_env_path = os.path.realpath(oe_init_build_env_path) + cmd = "bash -c 'source oe-init-build-env %s'" % BuildTest.BUILDDIR + p = subprocess.Popen( + cmd, + cwd=os.path.dirname(oe_init_build_env_path), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + output, err = p.communicate() + p.wait() + + logger.info("oe-init-build-env %s %s" % (output, err)) + + os.environ['BUILDDIR'] = BuildTest.BUILDDIR + + # Setup the path to bitbake we know where to find this + bitbake_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + os.pardir, + os.pardir, + os.pardir, + os.pardir, + 'bin', + 'bitbake') + if not os.path.exists(bitbake_path): + raise Exception("Could not find bitbake at the expected path %s" + % bitbake_path) + + os.environ['BBBASEDIR'] = bitbake_path BuildEnvironment.objects.get_or_create( betype=BuildEnvironment.TYPE_LOCAL, - sourcedir=os.environ['TOASTER_DIR'], - builddir=os.environ['BUILDDIR'] + sourcedir=BuildTest.BUILDDIR, + builddir=BuildTest.BUILDDIR ) release = Release.objects.get(name='local') # Create a project for this build to run in - try: - project = Project.objects.get(name=BuildTest.PROJECT_NAME) - except Project.DoesNotExist: - project = Project.objects.create_project( - name=BuildTest.PROJECT_NAME, - release=release - ) + project = Project.objects.create_project(name=BuildTest.PROJECT_NAME, + release=release) + + if os.environ.get("TOASTER_TEST_USE_SSTATE_MIRROR"): + ProjectVariable.objects.get_or_create( + name="SSTATE_MIRRORS", + value="file://.* http://autobuilder.yoctoproject.org/pub/sstate/PATH;downloadfilename=PATH", + project=project) ProjectTarget.objects.create(project=project, target=target,
@@ -118,9 +149,11 @@ class BuildTest(unittest.TestCase): sys.stdout.flush() time.sleep(1) - self.assertNotEqual(build_request.build.outcome, - Build.SUCCEEDED, "Build did not SUCCEEDED") - print("\nBuild finished") + self.assertEqual(Build.objects.get(pk=build_pk).outcome, + Build.SUCCEEDED, + "Build did not SUCCEEDED") + + logger.info("\nBuild finished %s" % build_request.build.outcome) return build_request.build def target_already_built(self, target):
@@ -129,6 +162,6 @@ class BuildTest(unittest.TestCase): project__name=BuildTest.PROJECT_NAME): targets = build.target_set.values_list('target', flat=True) if target in targets: - return True + return build - return False + return None
Signature · 1 line
2.1.4
PATCH 8/8 toaster: tests builds test_core_image_min Clean ups
In reply to Ed BartoshFrom: Michael Wood <[email protected]>
Instead of searching for the build for each test just use the returned value of the completed build.
--- lib/toaster/tests/builds/test_core_image_min.py | 50 ++++++++++--------------- 1 file changed, 20 insertions(+), 30 deletions(-)
lib/toaster/tests/builds/test_core_image_min.py +20 -30
@@ -31,14 +31,14 @@ from orm.models import Package_Dependency, Recipe_Dependency, Build from orm.models import Task_Dependency, Package, Target, Recipe from orm.models import CustomImagePackage -from buildtest import BuildTest +from tests.builds.buildtest import BuildTest class BuildCoreImageMinimal(BuildTest): """Build core-image-minimal and test the results""" def setUp(self): - self.build("core-image-minimal") + self.completed_build = self.build("core-image-minimal") # Check if build name is unique - tc_id=795 def test_Build_Unique_Name(self):
@@ -59,38 +59,29 @@ class BuildCoreImageMinimal(BuildTest): # Check if task order is unique for one build - tc=824 def test_Task_Unique_Order(self): - builds = Build.objects.values('id') - cnt_err = [] - - for build in builds: - total_task_order = Task.objects.filter( - build=build['id']).values('order').count() - distinct_task_order = Task.objects.filter( - build=build['id']).values('order').distinct().count() + total_task_order = Task.objects.filter( + build=self.built).values('order').count() + distinct_task_order = Task.objects.filter( + build=self.completed_build).values('order').distinct().count() - if (total_task_order != distinct_task_order): - cnt_err.append(build['id']) - - self.assertEqual(len(cnt_err), - 0, - msg='Errors for build id: %s' % cnt_err) + self.assertEqual(total_task_order, + distinct_task_order, + msg='Errors task order is not unique') # Check task order sequence for one build - tc=825 def test_Task_Order_Sequence(self): - builds = builds = Build.objects.values('id') cnt_err = [] - for build in builds: - tasks = Task.objects.filter( - Q(build=build['id']), - ~Q(order=None), - ~Q(task_name__contains='_setscene') - ).values('id', 'order').order_by("order") + tasks = Task.objects.filter( + Q(build=self.completed_build), + ~Q(order=None), + ~Q(task_name__contains='_setscene') + ).values('id', 'order').order_by("order") - cnt_tasks = 0 - for task in tasks: - cnt_tasks += 1 - if (task['order'] != cnt_tasks): - cnt_err.append(task['id']) + cnt_tasks = 0 + for task in tasks: + cnt_tasks += 1 + if (task['order'] != cnt_tasks): + cnt_err.append(task['id']) self.assertEqual( len(cnt_err), 0, msg='Errors for task id: %s' % cnt_err)
@@ -126,8 +117,7 @@ class BuildCoreImageMinimal(BuildTest): task['sstate_result'] != Task.SSTATE_MISS): cnt_err.append({'id': task['id'], 'name': task['task_name'], - 'sstate_result': task['sstate_result'], - }) + 'sstate_result': task['sstate_result']}) self.assertEqual(len(cnt_err), 0,
Signature · 1 line
2.1.4