blob: e0d48184ae13f2f185292b3ddad1796400f11884 [file] [log] [blame]
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import copy
from recipe_engine import recipe_api
class WebUtilsApi(recipe_api.RecipeApi):
"""Utilities to use when running flutter web engine tests."""
def firefox_driver(self, checkout):
"""Downloads the latest version of the Firefox web driver from CIPD."""
# Download the driver for Firefox.
firefox_driver_path = checkout.join('flutter', 'lib', 'web_ui',
'.dart_tool', 'drivers', 'firefox')
pkgdriver = self.m.cipd.EnsureFile()
pkgdriver.add_package(
'flutter_internal/browser-drivers/firefoxdriver-linux', 'latest')
self.m.cipd.ensure(firefox_driver_path, pkgdriver)
def chrome(self, checkout):
"""Downloads Chrome from CIPD.
The chrome version to be used will be read from a file on the repo side.
"""
browser_lock_yaml_file = checkout.join('flutter', 'lib', 'web_ui', 'dev',
'browser_lock.yaml')
with self.m.context(cwd=checkout):
result = self.m.yaml.read(
'read browser lock yaml',
browser_lock_yaml_file,
self.m.json.output(),
)
browser_lock_content = result.json.output
platform = self.m.platform.name.capitalize()
binary = browser_lock_content['chrome'][platform]
chrome_path = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'chrome', '%s' % binary)
# Using the binary number since the repos side file uses binary names.
# See: flutter/engine/blob/master/lib/web_ui/dev/browser_lock.yaml
# Chrome also uses these binary numbers for archiving different versions.
chrome_pkg = self.m.cipd.EnsureFile()
chrome_pkg.add_package('flutter_internal/browsers/chrome/${platform}',
binary)
self.m.cipd.ensure(chrome_path, chrome_pkg)
def chrome_driver(self, checkout):
"""Downloads Chrome web driver from CIPD.
The driver version to be used will be read from a file on the repo side.
"""
# Get driver version from the engine repo.
# See: flutter/engine/blob/master/lib/web_ui/dev/browser_lock.yaml
browser_lock_yaml_file = checkout.join('flutter', 'lib', 'web_ui', 'dev',
'browser_lock.yaml')
with self.m.context(cwd=checkout):
result = self.m.yaml.read(
'read browser lock yaml',
browser_lock_yaml_file,
self.m.json.output(),
)
browser_lock_content = result.json.output
version = browser_lock_content['required_driver_version']['chrome']
chrome_driver_path = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'drivers', 'chrome', '%s' % version)
chrome_pkgdriver = self.m.cipd.EnsureFile()
chrome_pkgdriver.add_package(
'flutter_internal/browser-drivers/chrome/${platform}',
'latest-%s' % version)
self.m.cipd.ensure(chrome_driver_path, chrome_pkgdriver)
def clone_goldens_repo(self, checkout):
"""Clone the repository that keeps golden files.
The repository name and the reference SHA will be read from a file on the
repo side.
"""
builder_root = self.m.path['cache'].join('builder')
goldens = builder_root.join('goldens')
self.m.file.ensure_directory('mkdir goldens', goldens)
golden_yaml_file = checkout.join('flutter', 'lib', 'web_ui', 'dev',
'goldens_lock.yaml')
with self.m.context(cwd=builder_root):
# Use golden_lock.yaml file to read url of the goldens repository and
# the revision number to checkout.
# https://github.com/flutter/engine/blob/master/lib/web_ui/dev/goldens_lock.yaml
# This file is used by web engine developers. The engine developers update
# the flutter/goldens.git repo when they need changes. Later change the
# revision number on this file.
result = self.m.yaml.read(
'read yaml',
golden_yaml_file,
self.m.json.output(),
)
# The content of the file is expected to be:
#
# repository: https://github.com/flutter/goldens.git
# revision: b6efc75885c23f0b5c485d8bd659ed339feec9ec
golden_lock_content = result.json.output
repo = golden_lock_content['repository']
revision_number = golden_lock_content['revision']
with self.m.context(cwd=goldens):
self.m.git.checkout(
repo,
dir_path=goldens,
ref=revision_number,
recursive=True,
set_got_revision=True)
golden_files = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'goldens')
self.m.file.copytree('copy goldens', goldens, golden_files)
def upload_failing_goldens(self, checkout, browser):
"""Upload the failed goldens files to a gcs bucket.
Parse the logs to determine which golden tests are failed. Upload expected
and actual golden files to a gcs bucket. Display links to html pages where
developer can compare actual vs expected images.
"""
logs_path = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'test_results')
tests_info_file_path = logs_path.join('info.txt')
self.m.file.write_text(
'write info file',
tests_info_file_path,
'tests for %s' % self.m.platform.name,
'tests for windows',
)
if not self.m.properties.get(
'gcs_goldens_bucket') or self.m.runtime.is_experimental:
# This is to avoid trying to upload files when 'gcs_goldens_bucket' is
# missing or when running from led.
return
bucket_id = self.m.buildbucket.build.id
self.m.gsutil.upload(
bucket=self.m.properties['gcs_goldens_bucket'],
source=logs_path,
dest='%s/%s/%s' % ('web_engine', bucket_id, browser),
link_name='archive goldens',
args=['-r'],
multithreaded=True,
name='upload goldens %s' % bucket_id,
unauthenticated_url=True)
html_files = self.m.file.glob_paths(
'html goldens',
source=logs_path,
pattern='*.html',
test_data=['a.html'])
with self.m.step.nest('Failed golden links') as presentation:
for html_file in html_files:
base_name = self.m.path.basename(html_file)
url = 'https://storage.googleapis.com/%s/web_engine/%s/%s/%s' % (
self.m.properties['gcs_goldens_bucket'], bucket_id, browser,
base_name)
presentation.links[base_name] = url
def prepare_dependencies(self, checkout):
"""Install all the required dependencies for a given felt test."""
deps = self.m.properties.get('dependencies', [])
available_deps = {
'chrome': self.chrome,
'chrome_driver': self.chrome_driver,
'firefox_driver': self.firefox_driver,
'goldens_repo': self.clone_goldens_repo,
}
for dep in deps:
dep_funct = available_deps.get(dep)
if not dep_funct:
raise ValueError('Dependency %s not available.' % dep)
dep_funct(checkout)