-
Notifications
You must be signed in to change notification settings - Fork 792
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ci] Introduce a test orchestrator written in bazel #23505
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
9d846d6
[ci] Introduce a test orchestrator written in bazel
pamaury e906405
[ci,bazel] Add a script to do a test-tag-filter-like query
pamaury 072fd99
[ci] Reorganize FPGA tests and put common fpga job code in a template
pamaury 8e828bf
[sysrst_ctrl,sival] Move tests to FPGA SiVal ROM_EXT
pamaury 046356b
[bazel] Automatically tag all FPGA tests with 'fpga'
pamaury fb58259
[ci] Check that the FPGA jobs do not run duplicates and are exhaustive
pamaury 8a211ea
[rom_ext,e2e] Mark some tests are broken
pamaury 1c44deb
[tests] Mark rv_dm_mem_access_rv_dm_delayed_enable as broken
pamaury File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# Copyright lowRISC contributors (OpenTitan project). | ||
# Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
# Azure template for an FPGA test job. | ||
# This script runs an FPGA test job given the specified parameters. The job will | ||
# depend on the require bitstream and publish the results of the test as an artefact. | ||
|
||
parameters: | ||
# Name to display for the jobs. | ||
- name: display_name | ||
type: string | ||
# Name of the job that other jobs can rely depend on. | ||
- name: job_name | ||
type: string | ||
# Timeout for the job in minutes. | ||
- name: timeout | ||
type: number | ||
# Bazel tag filters for the tests. | ||
- name: tag_filters | ||
type: string | ||
# Bitstream to use. | ||
- name: bitstream | ||
type: string | ||
# Azure pool board to use. | ||
- name: board | ||
type: string | ||
# Opentitantool interface to use. | ||
- name: interface | ||
type: string | ||
# Name of the file that holds the target patterns. | ||
- name: target_pattern_file | ||
type: string | ||
default: $(Pipeline.Workspace)/target_pattern_file.txt | ||
|
||
jobs: | ||
- job: ${{ parameters.job_name }} | ||
displayName: ${{ parameters.display_name }} | ||
pool: | ||
name: $(fpga_pool) | ||
demands: BOARD -equals ${{ parameters.board }} | ||
timeoutInMinutes: ${{ parameters.timeout }} | ||
dependsOn: | ||
- ${{ parameters.bitstream }} | ||
- sw_build | ||
#condition: succeeded( ${{ parameters.bitstream }}, 'sw_build' ) | ||
condition: and(in(dependencies.${{ parameters.bitstream }}.result, 'Succeeded', 'SucceededWithIssues'), succeeded('sw_build')) | ||
steps: | ||
- template: ./checkout-template.yml | ||
- template: ./install-package-dependencies.yml | ||
- template: ./download-artifacts-template.yml | ||
parameters: | ||
downloadPartialBuildBinFrom: | ||
- ${{ parameters.bitstream }} | ||
- sw_build | ||
- template: ./load-bazel-cache-write-creds.yml | ||
# We run the update command twice to workaround an issue with udev on the container, | ||
# where rusb cannot dynamically update its device list in CI (udev is not completely | ||
# functional). If the device is in normal mode, the first thing that opentitantool | ||
# does is to switch it to DFU mode and wait until it reconnects. This reconnection is | ||
# never detected. But if we run the tool another time, the device list is queried again | ||
# and opentitantool can finish the update. The device will now reboot in normal mode | ||
# and work for the hyperdebug job. | ||
- ${{ if eq(parameters.interface, 'hyper310') }}: | ||
- bash: | | ||
ci/bazelisk.sh run \ | ||
//sw/host/opentitantool:opentitantool -- \ | ||
--interface=hyperdebug_dfu transport update-firmware \ | ||
|| ci/bazelisk.sh run \ | ||
//sw/host/opentitantool:opentitantool -- \ | ||
--interface=hyperdebug_dfu transport update-firmware || true | ||
displayName: "Update the hyperdebug firmware" | ||
- bash: | | ||
set -e | ||
. util/build_consts.sh | ||
module load "xilinx/vivado/$(VIVADO_VERSION)" | ||
# Execute a query to find all targets that match the test tags and store them in a file. | ||
ci/scripts/run-bazel-test-query.sh \ | ||
"${{ parameters.target_pattern_file }}" \ | ||
"${{ parameters.tag_filters }}",-manual,-broken,-skip_in_ci \ | ||
//... @manufacturer_test_hooks//... | ||
# Run FPGA tests. | ||
if [ -s "${{ parameters.target_pattern_file }}" ]; then | ||
ci/scripts/run-fpga-tests.sh "${{ parameters.interface }}" "${{ parameters.target_pattern_file }}" || { res=$?; echo "To reproduce failures locally, follow the instructions at https://opentitan.org/book/doc/getting_started/setup_fpga.html#reproducing-fpga-ci-failures-locally"; exit "${res}"; } | ||
else | ||
echo "No tests to run after filtering" | ||
fi | ||
displayName: Execute tests | ||
- template: ./publish-bazel-test-results.yml | ||
- publish: "${{ parameters.target_pattern_file }}" | ||
artifact: ${{ parameters.job_name }} | ||
displayName: "Upload target pattern file" | ||
condition: succeededOrFailed() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#!/bin/bash | ||
# Copyright lowRISC contributors (OpenTitan project). | ||
# Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
# Usage: | ||
# run-bazel-test-query.sh <out_file> <test_tag_filters> <targets...> | ||
# | ||
# This script will perform a bazel query to include all tests specified | ||
# by the <targets...> but filtered according to the <test_tag_filters> | ||
# using the same filter logic as bazel's --test_tag_filters. The resulting | ||
# list of targets in placed in <out_file> | ||
|
||
set -x | ||
set -e | ||
|
||
if [ $# -lt 3 ]; then | ||
echo >&2 "Usage: ./run-bazel-test-query.sh <out_file> <test_tag_filters> <targets...>" | ||
echo >&2 "E.g. ./run-bazel-test-query.sh all_tests.txt cw310_rom_tests,-manuf //..." | ||
exit 1 | ||
fi | ||
out_file="$1" | ||
test_tags="$2" | ||
shift | ||
shift | ||
|
||
# Parse the tag filters and separate the positive from the negative ones | ||
declare -a positive_tags | ||
declare -a negative_tags | ||
IFS=',' read -ra tag_array <<< "$test_tags" | ||
for tag in "${tag_array[@]}"; do | ||
if [ "${tag:0:1}" == "-" ]; then | ||
negative_tags+=( "${tag:1}" ) | ||
else | ||
positive_tags+=( "$tag" ) | ||
fi | ||
done | ||
# Now build a regular expression to match all tests that contain at least one positive tag. | ||
# Per the bazel query reference, when matching for attributes, the tags are converted to a | ||
# string of the form "[tag_1, tag_2, ...]", so for example "[rom, manuf, broken]" (note the | ||
# space after each comma). To make sure to match on entire tags, we look for the tag, | ||
# preceded either by "[" or a space, and followed by "]" or a comma. | ||
positive_tags_or=$(IFS="|"; echo "${positive_tags[*]}") | ||
negative_tags_or=$(IFS="|"; echo "${negative_tags[*]}") | ||
positive_regex="[\[ ](${positive_tags_or})[,\]]" | ||
negative_regex="[\[ ](${negative_tags_or})[,\]]" | ||
# List of targets | ||
targets=$(IFS="|"; echo "$*") | ||
targets="${targets/|/ union }" | ||
# Finally build the bazel query | ||
./ci/bazelisk.sh query \ | ||
--noimplicit_deps \ | ||
--noinclude_aspects \ | ||
--output=label \ | ||
"attr(\"tags\", \"${positive_regex}\", tests($targets)) except attr(\"tags\", \"${negative_regex}\", tests($targets))" \ | ||
>"${out_file}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Copyright lowRISC contributors (OpenTitan project). | ||
# Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
# Azure template for an FPGA test job verification. | ||
# This script downloads the target pattern file from all FPGA jobs that are | ||
# dependencies and performs some checks on them. | ||
|
||
parameters: | ||
# List of all FPGA jobs | ||
- name: 'fpga_jobs' | ||
type: object | ||
# Test tag filter to find all FPGA tests | ||
- name: 'fpga_tags' | ||
type: string | ||
|
||
jobs: | ||
- job: verify_fpga_jobs | ||
displayName: Verify FPGA jobs | ||
pool: | ||
vmImage: ubuntu-20.04 | ||
dependsOn: ${{ parameters.fpga_jobs }} | ||
# Run even if dependencies failed: some flaky tests might cause the job to fail | ||
# but we still want to verify the FPGA jobs. | ||
condition: succeededOrFailed() | ||
steps: | ||
- ${{ each job in parameters.fpga_jobs }}: | ||
- task: DownloadPipelineArtifact@2 | ||
inputs: | ||
buildType: current | ||
targetPath: '$(Pipeline.Workspace)/verify_fpga_jobs/${{ job }}' | ||
artifact: "${{ job }}" | ||
patterns: target_pattern_file.txt | ||
displayName: Download target pattern files from job ${{ job }} | ||
- bash: | | ||
ls -R $(Pipeline.Workspace)/verify_fpga_jobs | ||
- bash: | | ||
# Find and display all duplicates: | ||
# - for each target file and each line, print '<job_name> <target>' | ||
# - then sort by the target name | ||
# - then keep all duplicated lines | ||
pattern_files=$(find $(Pipeline.Workspace)/verify_fpga_jobs -name target_pattern_file.txt) | ||
awk '{ print(gensub(/.*\/(.+)\/target_pattern_file.txt/, "\\1", "g", FILENAME) " " $0) }' $pattern_files | sort -k2 | uniq -D -f1 > duplicates.txt | ||
if [ -s duplicates.txt ]; then | ||
echo "The following tests ran in two or more jobs:" | ||
cat duplicates.txt | ||
false | ||
fi | ||
displayName: Checking for duplicate test runs | ||
- bash: | | ||
# Find and display tests that did not run: | ||
./ci/scripts/run-bazel-test-query.sh all_fpga.txt "${{ parameters.fpga_tags }}",-manual,-broken,-skip_in_ci //... @manufacturer_test_hooks//... | ||
sort -o all_fpga.txt all_fpga.txt | ||
pattern_files=$(find $(Pipeline.Workspace)/verify_fpga_jobs -name target_pattern_file.txt) | ||
sort $pattern_files > all_run.txt | ||
comm -23 all_fpga.txt all_run.txt > missing.txt | ||
if [ -s missing.txt ]; then | ||
echo "The following tests did not run in any job:" | ||
cat missing.txt | ||
false | ||
fi | ||
displayName: Checking for missing test runs | ||
condition: succeededOrFailed() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Copyright lowRISC contributors (OpenTitan project). | ||
# Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
load("@bazel_skylib//lib:sets.bzl", "sets") | ||
|
||
# List of execution environments among which only one should run. The list | ||
# is sorted by priority: the first available will be picked. | ||
# | ||
# Important note: since only one of the those will be chosen, it is important | ||
# that every one of the execution environments be run in some CI job, otherwise | ||
# some tests will not run at all in CI. | ||
_ONLY_RUN_ONE_IN_CI_SORTED = [ | ||
"//hw/top_earlgrey:fpga_cw310_sival_rom_ext", | ||
"//hw/top_earlgrey:fpga_cw310_rom_ext", | ||
"//hw/top_earlgrey:fpga_cw310_sival", | ||
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys", | ||
"//hw/top_earlgrey:fpga_cw310_test_rom", | ||
"//hw/top_earlgrey:fpga_cw340_sival_rom_ext", | ||
"//hw/top_earlgrey:fpga_cw340_sival", | ||
"//hw/top_earlgrey:fpga_cw340_rom_ext", | ||
"//hw/top_earlgrey:fpga_cw340_rom_with_fake_keys", | ||
"//hw/top_earlgrey:fpga_cw340_test_rom", | ||
jwnrt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
] | ||
|
||
def ci_orchestrator(test_name, exec_envs): | ||
""" | ||
Given a list of execution environments, return the subset of this list | ||
that should be skipped in CI. | ||
""" | ||
exec_env_sets = sets.make(exec_envs) | ||
found_one = False | ||
skip_in_ci = [] | ||
for env in _ONLY_RUN_ONE_IN_CI_SORTED: | ||
if sets.contains(exec_env_sets, env): | ||
if found_one: | ||
skip_in_ci.append(env) | ||
found_one = True | ||
|
||
return skip_in_ci |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this logic be part of run-fpga-tests.sh?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer not because this way, we have two scripts for two different purposes: run-bazel-test-query does the query, and run-fpga-tests run the tests. You can more easily repurpose the scripts this way. Or I would make it third script if you really want to (run-fpga-tests-query).