bitbake: lib/toaster: Fix missing new files from previous commits
(Bitbake rev: f77e6f21a2cc57a3fcb5970437e55cfae39849a3) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
5b61fa04a3
commit
aa2d945423
|
@ -0,0 +1,118 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('orm', '0009_target_package_manifest_path'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='releaselayersourcepriority',
|
||||||
|
unique_together=set([]),
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='releaselayersourcepriority',
|
||||||
|
name='layer_source',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='releaselayersourcepriority',
|
||||||
|
name='release',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='ImportedLayerSource',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='LayerIndexLayerSource',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='LocalLayerSource',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='recipe',
|
||||||
|
name='layer_source',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='recipe',
|
||||||
|
name='up_id',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='layer',
|
||||||
|
name='up_date',
|
||||||
|
field=models.DateTimeField(default=django.utils.timezone.now, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='layer_version',
|
||||||
|
name='layer_source',
|
||||||
|
field=models.IntegerField(default=0, choices=[(0, 'local'), (1, 'layerindex'), (2, 'imported'), (3, 'build')]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='layer_version',
|
||||||
|
name='up_date',
|
||||||
|
field=models.DateTimeField(default=django.utils.timezone.now, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='branch',
|
||||||
|
unique_together=set([]),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='layer',
|
||||||
|
unique_together=set([]),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='layer_version',
|
||||||
|
unique_together=set([]),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='layerversiondependency',
|
||||||
|
unique_together=set([]),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='machine',
|
||||||
|
unique_together=set([]),
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='ReleaseLayerSourcePriority',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='branch',
|
||||||
|
name='layer_source',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='branch',
|
||||||
|
name='up_id',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='layer',
|
||||||
|
name='layer_source',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='layer',
|
||||||
|
name='up_id',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='layer_version',
|
||||||
|
name='up_id',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='layerversiondependency',
|
||||||
|
name='layer_source',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='layerversiondependency',
|
||||||
|
name='up_id',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='machine',
|
||||||
|
name='layer_source',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='machine',
|
||||||
|
name='up_id',
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,17 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('orm', '0010_delete_layer_source_references'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='LayerSource',
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,62 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
|
||||||
|
def branch_to_release(apps, schema_editor):
|
||||||
|
Layer_Version = apps.get_model('orm', 'Layer_Version')
|
||||||
|
Release = apps.get_model('orm', 'Release')
|
||||||
|
|
||||||
|
print("Converting all layer version up_branches to releases")
|
||||||
|
# Find all the layer versions which have an upbranch and convert them to
|
||||||
|
# the release that they're for.
|
||||||
|
for layer_version in Layer_Version.objects.filter(
|
||||||
|
Q(release=None) & ~Q(up_branch=None)):
|
||||||
|
try:
|
||||||
|
# HEAD and local are equivalent
|
||||||
|
if "HEAD" in layer_version.up_branch.name:
|
||||||
|
release = Release.objects.get(name="local")
|
||||||
|
layer_version.commit = "HEAD"
|
||||||
|
layer_version.branch = "HEAD"
|
||||||
|
else:
|
||||||
|
release = Release.objects.get(
|
||||||
|
name=layer_version.up_branch.name)
|
||||||
|
|
||||||
|
layer_version.release = release
|
||||||
|
layer_version.save()
|
||||||
|
except Exception as e:
|
||||||
|
print("Couldn't work out an appropriate release for %s "
|
||||||
|
"the up_branch was %s "
|
||||||
|
"user the django admin interface to correct it" %
|
||||||
|
(layer_version.layer.name, layer_version.up_branch.name))
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('orm', '0011_delete_layersource'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='layer_version',
|
||||||
|
name='release',
|
||||||
|
field=models.ForeignKey(to='orm.Release', default=None, null=True),
|
||||||
|
),
|
||||||
|
migrations.RunPython(branch_to_release,
|
||||||
|
reverse_code=migrations.RunPython.noop),
|
||||||
|
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='layer_version',
|
||||||
|
name='up_branch',
|
||||||
|
),
|
||||||
|
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='Branch',
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,218 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# ex:ts=4:sw=4:sts=4:et
|
||||||
|
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||||
|
#
|
||||||
|
# BitBake Toaster Implementation
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013-2016 Intel Corporation
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License version 2 as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# The Wait class and some of SeleniumDriverHelper and SeleniumTestCase are
|
||||||
|
# modified from Patchwork, released under the same licence terms as Toaster:
|
||||||
|
# https://github.com/dlespiau/patchwork/blob/master/patchwork/tests.browser.py
|
||||||
|
|
||||||
|
"""
|
||||||
|
Helper methods for creating Toaster Selenium tests which run within
|
||||||
|
the context of Django unit tests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||||
|
from selenium import webdriver
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||||
|
from selenium.common.exceptions import NoSuchElementException, \
|
||||||
|
StaleElementReferenceException, TimeoutException
|
||||||
|
|
||||||
|
def create_selenium_driver(browser='chrome'):
|
||||||
|
# set default browser string based on env (if available)
|
||||||
|
env_browser = os.environ.get('TOASTER_TESTS_BROWSER')
|
||||||
|
if env_browser:
|
||||||
|
browser = env_browser
|
||||||
|
|
||||||
|
if browser == 'chrome':
|
||||||
|
return webdriver.Chrome(
|
||||||
|
service_args=["--verbose", "--log-path=selenium.log"]
|
||||||
|
)
|
||||||
|
elif browser == 'firefox':
|
||||||
|
return webdriver.Firefox()
|
||||||
|
elif browser == 'marionette':
|
||||||
|
capabilities = DesiredCapabilities.FIREFOX
|
||||||
|
capabilities['marionette'] = True
|
||||||
|
return webdriver.Firefox(capabilities=capabilities)
|
||||||
|
elif browser == 'ie':
|
||||||
|
return webdriver.Ie()
|
||||||
|
elif browser == 'phantomjs':
|
||||||
|
return webdriver.PhantomJS()
|
||||||
|
else:
|
||||||
|
msg = 'Selenium driver for browser %s is not available' % browser
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
|
class Wait(WebDriverWait):
|
||||||
|
"""
|
||||||
|
Subclass of WebDriverWait with predetermined timeout and poll
|
||||||
|
frequency. Also deals with a wider variety of exceptions.
|
||||||
|
"""
|
||||||
|
_TIMEOUT = 10
|
||||||
|
_POLL_FREQUENCY = 0.5
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(Wait, self).__init__(driver, self._TIMEOUT, self._POLL_FREQUENCY)
|
||||||
|
|
||||||
|
def until(self, method, message=''):
|
||||||
|
"""
|
||||||
|
Calls the method provided with the driver as an argument until the
|
||||||
|
return value is not False.
|
||||||
|
"""
|
||||||
|
|
||||||
|
end_time = time.time() + self._timeout
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
value = method(self._driver)
|
||||||
|
if value:
|
||||||
|
return value
|
||||||
|
except NoSuchElementException:
|
||||||
|
pass
|
||||||
|
except StaleElementReferenceException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
time.sleep(self._poll)
|
||||||
|
if time.time() > end_time:
|
||||||
|
break
|
||||||
|
|
||||||
|
raise TimeoutException(message)
|
||||||
|
|
||||||
|
def until_not(self, method, message=''):
|
||||||
|
"""
|
||||||
|
Calls the method provided with the driver as an argument until the
|
||||||
|
return value is False.
|
||||||
|
"""
|
||||||
|
|
||||||
|
end_time = time.time() + self._timeout
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
value = method(self._driver)
|
||||||
|
if not value:
|
||||||
|
return value
|
||||||
|
except NoSuchElementException:
|
||||||
|
return True
|
||||||
|
except StaleElementReferenceException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
time.sleep(self._poll)
|
||||||
|
if time.time() > end_time:
|
||||||
|
break
|
||||||
|
|
||||||
|
raise TimeoutException(message)
|
||||||
|
|
||||||
|
class SeleniumTestCaseBase(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
NB StaticLiveServerTestCase is used as the base test case so that
|
||||||
|
static files are served correctly in a Selenium test run context; see
|
||||||
|
https://docs.djangoproject.com/en/1.9/ref/contrib/staticfiles/#specialized-test-case-to-support-live-testing
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
""" Create a webdriver driver at the class level """
|
||||||
|
|
||||||
|
super(SeleniumTestCaseBase, cls).setUpClass()
|
||||||
|
|
||||||
|
# instantiate the Selenium webdriver once for all the test methods
|
||||||
|
# in this test case
|
||||||
|
cls.driver = create_selenium_driver()
|
||||||
|
cls.driver.maximize_window()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
""" Clean up webdriver driver """
|
||||||
|
|
||||||
|
cls.driver.quit()
|
||||||
|
super(SeleniumTestCaseBase, cls).tearDownClass()
|
||||||
|
|
||||||
|
def get(self, url):
|
||||||
|
"""
|
||||||
|
Selenium requires absolute URLs, so convert Django URLs returned
|
||||||
|
by resolve() or similar to absolute ones and get using the
|
||||||
|
webdriver instance.
|
||||||
|
|
||||||
|
url: a relative URL
|
||||||
|
"""
|
||||||
|
abs_url = '%s%s' % (self.live_server_url, url)
|
||||||
|
self.driver.get(abs_url)
|
||||||
|
|
||||||
|
def find(self, selector):
|
||||||
|
""" Find single element by CSS selector """
|
||||||
|
return self.driver.find_element_by_css_selector(selector)
|
||||||
|
|
||||||
|
def find_all(self, selector):
|
||||||
|
""" Find all elements matching CSS selector """
|
||||||
|
return self.driver.find_elements_by_css_selector(selector)
|
||||||
|
|
||||||
|
def element_exists(self, selector):
|
||||||
|
"""
|
||||||
|
Return True if one element matching selector exists,
|
||||||
|
False otherwise
|
||||||
|
"""
|
||||||
|
return len(self.find_all(selector)) == 1
|
||||||
|
|
||||||
|
def focused_element(self):
|
||||||
|
""" Return the element which currently has focus on the page """
|
||||||
|
return self.driver.switch_to.active_element
|
||||||
|
|
||||||
|
def wait_until_present(self, selector):
|
||||||
|
""" Wait until element matching CSS selector is on the page """
|
||||||
|
is_present = lambda driver: self.find(selector)
|
||||||
|
msg = 'An element matching "%s" should be on the page' % selector
|
||||||
|
element = Wait(self.driver).until(is_present, msg)
|
||||||
|
return element
|
||||||
|
|
||||||
|
def wait_until_visible(self, selector):
|
||||||
|
""" Wait until element matching CSS selector is visible on the page """
|
||||||
|
is_visible = lambda driver: self.find(selector).is_displayed()
|
||||||
|
msg = 'An element matching "%s" should be visible' % selector
|
||||||
|
Wait(self.driver).until(is_visible, msg)
|
||||||
|
return self.find(selector)
|
||||||
|
|
||||||
|
def wait_until_focused(self, selector):
|
||||||
|
""" Wait until element matching CSS selector has focus """
|
||||||
|
is_focused = \
|
||||||
|
lambda driver: self.find(selector) == self.focused_element()
|
||||||
|
msg = 'An element matching "%s" should be focused' % selector
|
||||||
|
Wait(self.driver).until(is_focused, msg)
|
||||||
|
return self.find(selector)
|
||||||
|
|
||||||
|
def enter_text(self, selector, value):
|
||||||
|
""" Insert text into element matching selector """
|
||||||
|
# note that keyup events don't occur until the element is clicked
|
||||||
|
# (in the case of <input type="text"...>, for example), so simulate
|
||||||
|
# user clicking the element before inserting text into it
|
||||||
|
field = self.click(selector)
|
||||||
|
|
||||||
|
field.send_keys(value)
|
||||||
|
return field
|
||||||
|
|
||||||
|
def click(self, selector):
|
||||||
|
""" Click on element which matches CSS selector """
|
||||||
|
element = self.wait_until_visible(selector)
|
||||||
|
element.click()
|
||||||
|
return element
|
||||||
|
|
||||||
|
def get_page_source(self):
|
||||||
|
""" Get raw HTML for the current page """
|
||||||
|
return self.driver.page_source
|
Loading…
Reference in New Issue