diff options
Diffstat (limited to 'lib/toaster/tests/functional/functional_helpers.py')
-rw-r--r-- | lib/toaster/tests/functional/functional_helpers.py | 98 |
1 files changed, 57 insertions, 41 deletions
diff --git a/lib/toaster/tests/functional/functional_helpers.py b/lib/toaster/tests/functional/functional_helpers.py index 486078a61..7c20437d1 100644 --- a/lib/toaster/tests/functional/functional_helpers.py +++ b/lib/toaster/tests/functional/functional_helpers.py @@ -1,57 +1,65 @@ -#! /usr/bin/env python -# ex:ts=4:sw=4:sts=4:et -# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +#! /usr/bin/env python3 # # BitBake Toaster functional tests implementation # # Copyright (C) 2017 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. +# SPDX-License-Identifier: GPL-2.0-only # -# 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. import os import logging import subprocess import signal -import time import re from tests.browser.selenium_helpers_base import SeleniumTestCaseBase -from tests.builds.buildtest import load_build_environment +from selenium.webdriver.common.by import By +from selenium.common.exceptions import NoSuchElementException logger = logging.getLogger("toaster") +toaster_processes = [] class SeleniumFunctionalTestCase(SeleniumTestCaseBase): - wait_toaster_time = 5 + wait_toaster_time = 10 @classmethod def setUpClass(cls): # So that the buildinfo helper uses the test database' if os.environ.get('DJANGO_SETTINGS_MODULE', '') != \ 'toastermain.settings_test': - raise RuntimeError("Please initialise django with the tests settings: " \ + raise RuntimeError("Please initialise django with the tests settings: " "DJANGO_SETTINGS_MODULE='toastermain.settings_test'") - load_build_environment() + # Wait for any known toaster processes to exit + global toaster_processes + for toaster_process in toaster_processes: + try: + os.waitpid(toaster_process, os.WNOHANG) + except ChildProcessError: + pass # start toaster cmd = "bash -c 'source toaster start'" - p = subprocess.Popen( + start_process = subprocess.Popen( cmd, cwd=os.environ.get("BUILDDIR"), shell=True) - if p.wait() != 0: - raise RuntimeError("Can't initialize toaster") + toaster_processes = [start_process.pid] + if start_process.wait() != 0: + port_use = os.popen("lsof -i -P -n | grep '8000 (LISTEN)'").read().strip() + message = '' + if port_use: + process_id = port_use.split()[1] + process = os.popen(f"ps -o cmd= -p {process_id}").read().strip() + message = f"Port 8000 occupied by {process}" + raise RuntimeError(f"Can't initialize toaster. {message}") + + builddir = os.environ.get("BUILDDIR") + with open(os.path.join(builddir, '.toastermain.pid'), 'r') as f: + toaster_processes.append(int(f.read())) + with open(os.path.join(builddir, '.runbuilds.pid'), 'r') as f: + toaster_processes.append(int(f.read())) super(SeleniumFunctionalTestCase, cls).setUpClass() cls.live_server_url = 'http://localhost:8000/' @@ -60,22 +68,30 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase): def tearDownClass(cls): super(SeleniumFunctionalTestCase, cls).tearDownClass() - # XXX: source toaster stop gets blocked, to review why? - # from now send SIGTERM by hand - time.sleep(cls.wait_toaster_time) - builddir = os.environ.get("BUILDDIR") + global toaster_processes - with open(os.path.join(builddir, '.toastermain.pid'), 'r') as f: - toastermain_pid = int(f.read()) - os.kill(toastermain_pid, signal.SIGTERM) - with open(os.path.join(builddir, '.runbuilds.pid'), 'r') as f: - runbuilds_pid = int(f.read()) - os.kill(runbuilds_pid, signal.SIGTERM) + cmd = "bash -c 'source toaster stop'" + stop_process = subprocess.Popen( + cmd, + cwd=os.environ.get("BUILDDIR"), + shell=True) + # Toaster stop has been known to hang in these tests so force kill if it stalls + try: + if stop_process.wait(cls.wait_toaster_time) != 0: + raise Exception('Toaster stop process failed') + except Exception as e: + if e is subprocess.TimeoutExpired: + print('Toaster stop process took too long. Force killing toaster...') + else: + print('Toaster stop process failed. Force killing toaster...') + stop_process.kill() + for toaster_process in toaster_processes: + os.kill(toaster_process, signal.SIGTERM) def get_URL(self): rc=self.get_page_source() - project_url=re.search("(projectPageUrl\s:\s\")(.*)(\",)",rc) + project_url=re.search(r"(projectPageUrl\s:\s\")(.*)(\",)",rc) return project_url.group(2) @@ -86,8 +102,8 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase): """ try: table_element = self.get_table_element(table_id) - element = table_element.find_element_by_link_text(link_text) - except NoSuchElementException as e: + element = table_element.find_element(By.LINK_TEXT, link_text) + except NoSuchElementException: print('no element found') raise return element @@ -97,8 +113,8 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase): #return whole-table element element_xpath = "//*[@id='" + table_id + "']" try: - element = self.driver.find_element_by_xpath(element_xpath) - except NoSuchElementException as e: + element = self.driver.find_element(By.XPATH, element_xpath) + except NoSuchElementException: raise return element row = coordinate[0] @@ -107,8 +123,8 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase): #return whole-row element element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]" try: - element = self.driver.find_element_by_xpath(element_xpath) - except NoSuchElementException as e: + element = self.driver.find_element(By.XPATH, element_xpath) + except NoSuchElementException: return False return element #now we are looking for an element with specified X and Y @@ -116,7 +132,7 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase): element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]/td[" + str(column) + "]" try: - element = self.driver.find_element_by_xpath(element_xpath) - except NoSuchElementException as e: + element = self.driver.find_element(By.XPATH, element_xpath) + except NoSuchElementException: return False return element |