2024-08-12 11:33:28 -03:00
#!/usr/bin/env bash
set -e
DIR = " $( cd " $( dirname " ${ BASH_SOURCE [0] } " ) " && pwd ) "
2024-08-15 19:12:40 -03:00
# shellcheck source=/dev/null
2026-04-23 11:10:23 -03:00
. " ${ DIR } /Utils/shell_include.sh "
2024-08-15 19:12:40 -03:00
2024-10-09 02:23:42 -03:00
ensure_ladybird_source_dir
WPT_SOURCE_DIR = ${ WPT_SOURCE_DIR :- " ${ LADYBIRD_SOURCE_DIR } /Tests/LibWeb/WPT/wpt " }
WPT_REPOSITORY_URL = ${ WPT_REPOSITORY_URL :- "https://github.com/web-platform-tests/wpt.git" }
2025-07-19 12:45:08 -03:00
BUILD_PRESET = ${ BUILD_PRESET :- Release }
2024-10-09 02:32:11 -03:00
BUILD_DIR = $( get_build_dir " $BUILD_PRESET " )
2025-07-15 16:14:07 -03:00
TMPDIR = ${ TMPDIR :- /tmp }
2025-04-24 12:36:10 -03:00
: " ${ TRY_SHOW_LOGFILES_IN_TMUX : =false } "
: " ${ SHOW_LOGFILES : =true } "
: " ${ SHOW_PROGRESS : =true } "
: " ${ PARALLEL_INSTANCES : =1 } "
if " $SHOW_PROGRESS " ; then
SHOW_LOGFILES = true
TRY_SHOW_LOGFILES_IN_TMUX = false
fi
sudo_and_ask( ) {
local prompt
prompt = " $1 " ; shift
if [ -z " $prompt " ] ; then
prompt = " Running ' ${ * } ' as root, please enter password for %p: "
else
prompt = " $prompt ; please enter password for %p: "
fi
sudo --prompt= " $prompt " " ${ @ } "
}
2024-08-15 19:14:04 -03:00
default_binary_path( ) {
if [ " $( uname -s) " = "Darwin" ] ; then
2024-10-21 20:31:05 -03:00
echo " ${ BUILD_DIR } /bin/Ladybird.app/Contents/MacOS "
2024-08-15 19:14:04 -03:00
else
2024-10-21 20:31:05 -03:00
echo " ${ BUILD_DIR } /bin "
2024-08-15 19:14:04 -03:00
fi
}
2024-10-09 02:32:11 -03:00
2024-10-29 06:33:11 -03:00
ladybird_git_hash( ) {
pushd " ${ LADYBIRD_SOURCE_DIR } " > /dev/null
git rev-parse --short HEAD
popd > /dev/null
}
2025-04-24 12:36:10 -03:00
run_dir_path( ) {
i = " $1 " ; shift
local runpath = " ${ BUILD_DIR } /wpt/run. $i "
echo " $runpath "
}
ensure_run_dir( ) {
i = " $1 " ; shift
local runpath
runpath = " $( run_dir_path " $i " ) "
if [ ! -d " $runpath " ] ; then
mkdir -p " $runpath /upper " " $runpath /work " " $runpath /merged "
# shellcheck disable=SC2140
sudo_and_ask " Mounting overlayfs on $runpath " mount -t overlay overlay -o lowerdir = " ${ WPT_SOURCE_DIR } " ,upperdir= " $runpath /upper " ,workdir= " $runpath /work " " $runpath /merged "
fi
echo " $runpath /merged "
}
2024-08-15 19:14:04 -03:00
LADYBIRD_BINARY = ${ LADYBIRD_BINARY :- " $( default_binary_path) /Ladybird " }
WEBDRIVER_BINARY = ${ WEBDRIVER_BINARY :- " $( default_binary_path) /WebDriver " }
2025-06-06 21:11:13 -03:00
TEST_WEB_BINARY = ${ TEST_WEB_BINARY :- " ${ BUILD_DIR } /bin/test-web " }
2024-08-15 19:12:40 -03:00
WPT_PROCESSES = ${ WPT_PROCESSES :- $( get_number_of_processing_units) }
2024-08-12 11:33:28 -03:00
WPT_CERTIFICATES = (
2025-05-02 16:08:02 -03:00
"tools/certs/cacert.pem"
2024-08-12 11:33:28 -03:00
)
2025-06-06 16:42:12 -03:00
WPT_ARGS = (
" --binary= ${ LADYBIRD_BINARY } "
" --webdriver-binary= ${ WEBDRIVER_BINARY } "
2025-05-02 16:08:02 -03:00
"--install-webdriver"
"--webdriver-arg=--force-cpu-painting"
2025-10-15 09:17:37 -03:00
"--webdriver-arg=--default-time-zone=UTC"
2026-02-17 15:47:21 -03:00
"--webdriver-arg=--expose-experimental-interfaces"
2025-05-02 16:08:02 -03:00
"--no-pause-after-test"
2025-07-07 06:49:22 -03:00
"--install-fonts"
2025-05-02 16:08:02 -03:00
" ${ EXTRA_WPT_ARGS [@] } "
2024-08-12 11:33:28 -03:00
)
2025-06-21 01:04:20 -03:00
IMPORT_ARGS = ( )
2025-05-08 08:40:07 -03:00
WPT_LOG_ARGS = ( )
2024-08-12 11:33:28 -03:00
ARG0 = $0
print_help( ) {
2025-05-02 16:08:02 -03:00
NAME = $( basename " $ARG0 " )
cat <<EOF
2024-08-12 11:33:28 -03:00
Usage: $NAME COMMAND [ OPTIONS..] [ TESTS...]
Supported COMMANDs:
update: Update the Web Platform Tests repository.
run: $NAME run [ OPTIONS...] [ TESTS...]
Run the Web Platform Tests.
compare: $NAME compare [ OPTIONS...] LOG_FILE [ TESTS...]
Run the Web Platform Tests comparing the results to the expectations in LOG_FILE.
2024-12-09 08:37:43 -03:00
import: $NAME import [ PATHS...]
2024-11-02 03:03:22 -03:00
Fetch the given test file( s) from https://wpt.live/ and create an in-tree test and expectation files.
2024-12-09 08:05:57 -03:00
list-tests: $NAME list-tests [ PATHS..]
List the tests in the given PATHS.
2025-04-24 12:36:10 -03:00
clean: $NAME clean
2026-01-02 07:29:39 -03:00
Clean up the extra resources and directories ( if any leftover) created by this script ( Linux only) .
2025-07-15 16:14:07 -03:00
bisect: $NAME bisect BAD_COMMIT GOOD_COMMIT [ TESTS...]
Find the first commit where a given set of tests produce unexpected results.
2025-04-24 12:36:10 -03:00
Env vars:
EXTRA_WPT_ARGS: Extra arguments for the wpt command, placed at the end; array, default empty
TRY_SHOW_LOGFILES_IN_TMUX: Whether to show split logs in tmux; true or false, default false
SHOW_LOGFILES: Whether to show logs at all; true or false, default true
SHOW_PROGRESS: Whether to show the progress of the tests, default true
implies SHOW_LOGFILES = true and TRY_SHOW_LOGFILES_IN_TMUX = false
Options for this script:
--show-window
Disable headless mode
--debug-process PROC_NAME
Enable debugging for the PROC_NAME ladybird process
--parallel-instances N
Enable running in chunked mode with N parallel instances
N = 0 to auto-enable if possible
N = 1 to disable chunked mode ( default)
N>1 to enable chunked mode with explicit process count
--log PATH
Alias for --log-raw PATH
--log-( raw| unittest| xunit| html| mach| tbpl| grouped| chromium| wptreport| wptscreenshot) PATH
Enable the given wpt log option with the given PATH
2024-08-12 11:33:28 -03:00
Examples:
$NAME update
Updates the Web Platform Tests repository.
$NAME run
Run all of the Web Platform Tests.
$NAME run --log expectations.log css dom
Run the Web Platform Tests in the 'css' and 'dom' directories and save the output to expectations.log.
2024-09-13 19:50:16 -03:00
$NAME run --log-wptreport expectations.json --log-wptscreenshot expectations.db css dom
Run the Web Platform Tests in the 'css' and 'dom' directories; save the output in wptreport format to expectations.json and save screenshots to expectations.db.
2025-04-24 12:36:10 -03:00
$NAME run --parallel-instances 0 --log-wptreport expectations.json --log-wptscreenshot expectations.db css dom
Run the Web Platform Tests in the 'css' and 'dom' directories in chunked mode; save the output in wptreport format to expectations.json and save screenshots to expectations.db.
2024-12-12 08:47:39 -03:00
$NAME run --debug-process WebContent http://wpt.live/dom/historical.html
Run the 'dom/historical.html' test, attaching the debugger to the WebContent process when the browser is launched.
2024-08-12 11:33:28 -03:00
$NAME compare expectations.log
Run all of the Web Platform Tests comparing the results to the expectations in before.log.
$NAME compare --log results.log expectations.log css/CSS2
Run the Web Platform Tests in the 'css/CSS2' directory, comparing the results to the expectations in expectations.log; output the results to results.log.
2024-11-02 03:03:22 -03:00
$NAME import html/dom/aria-attribute-reflection.html
Import the test from https://wpt.live/html/dom/aria-attribute-reflection.html into the Ladybird test suite.
2025-06-21 01:04:20 -03:00
$NAME import --force html/dom/aria-attribute-reflection.html
Import the test from https://wpt.live/html/dom/aria-attribute-reflection.html into the Ladybird test suite, redownloading any files that already exist.
2024-12-09 08:05:57 -03:00
$NAME list-tests css/CSS2 dom
Show a list of all tests in the 'css/CSS2' and 'dom' directories.
2024-08-12 11:33:28 -03:00
EOF
}
usage( ) {
>& 2 print_help
exit 1
}
CMD = $1
[ -n " $CMD " ] || usage
shift
if [ " $CMD " = "--help" ] || [ " $CMD " = "help" ] ; then
print_help
exit 0
fi
2024-10-21 20:31:05 -03:00
set_logging_flags( )
{
[ -n " ${ 1 } " ] || usage;
[ -n " ${ 2 } " ] || usage;
log_type = " ${ 1 } "
2025-04-24 12:36:10 -03:00
log_name = " ${ 2 } "
2024-10-21 20:31:05 -03:00
2025-05-08 08:40:07 -03:00
WPT_LOG_ARGS += ( " ${ log_type } " " ${ log_name } " )
2024-10-21 20:31:05 -03:00
}
2024-10-14 16:54:36 -03:00
headless = 1
2024-08-12 11:33:28 -03:00
ARG = $1
2025-04-24 12:36:10 -03:00
while [ [ " $ARG " = ~ ^( --show-window| --debug-process| --parallel-instances| ( --log( -( raw| unittest| xunit| html| mach| tbpl| grouped| chromium| wptreport| wptscreenshot) ) ?) ) $ ] ] ; do
2024-09-13 19:50:16 -03:00
case " $ARG " in
2024-10-14 16:54:36 -03:00
--show-window)
headless = 0
2024-10-21 20:31:05 -03:00
; ;
2024-12-12 08:47:39 -03:00
--debug-process)
process_name = " ${ 2 } "
shift
WPT_ARGS += ( " --webdriver-arg=--debug-process= ${ process_name } " )
; ;
2024-09-13 19:50:16 -03:00
--log)
2024-10-21 20:31:05 -03:00
set_logging_flags "--log-raw" " ${ 2 } "
shift
2024-09-13 19:50:16 -03:00
; ;
2025-04-24 12:36:10 -03:00
--parallel-instances)
PARALLEL_INSTANCES = " ${ 2 } "
shift
; ;
2024-09-13 19:50:16 -03:00
*)
2024-10-21 20:31:05 -03:00
set_logging_flags " ${ ARG } " " ${ 2 } "
shift
2024-09-13 19:50:16 -03:00
; ;
esac
2024-10-21 20:31:05 -03:00
2024-08-12 11:33:28 -03:00
shift
2024-09-13 19:50:16 -03:00
ARG = $1
done
2024-10-21 20:31:05 -03:00
2024-10-14 16:54:36 -03:00
if [ $headless -eq 1 ] ; then
WPT_ARGS += ( "--webdriver-arg=--headless" )
fi
2024-08-12 11:33:28 -03:00
exit_if_running_as_root "Do not run WPT.sh as root"
2024-12-18 17:37:43 -03:00
construct_test_list( ) {
2025-05-02 16:08:02 -03:00
TEST_LIST = ( " $@ " )
for i in " ${ !TEST_LIST[@] } " ; do
item = " ${ TEST_LIST [i] } "
item = " ${ item # " $WPT_SOURCE_DIR " / } "
item = " ${ item #*Tests/LibWeb/WPT/wpt/ } "
item = " ${ item #http : //wpt.live/ } "
item = " ${ item #https : //wpt.live/ } "
TEST_LIST[ i] = " $item "
done
2024-12-18 17:37:43 -03:00
}
2024-08-12 11:33:28 -03:00
ensure_wpt_repository( ) {
mkdir -p " ${ WPT_SOURCE_DIR } "
pushd " ${ WPT_SOURCE_DIR } " > /dev/null
if [ ! -d .git ] ; then
git clone --depth 1 " ${ WPT_REPOSITORY_URL } " " ${ WPT_SOURCE_DIR } "
fi
popd > /dev/null
}
build_ladybird_and_webdriver( ) {
2025-07-15 16:14:07 -03:00
" ${ LADYBIRD_SOURCE_DIR } " /Meta/ladybird.py build WebDriver
2024-08-12 11:33:28 -03:00
}
update_wpt( ) {
ensure_wpt_repository
pushd " ${ WPT_SOURCE_DIR } " > /dev/null
git pull
popd > /dev/null
}
2025-04-24 12:36:10 -03:00
cleanup_run_infra( ) {
readarray -t pids < <( jobs -p)
for pid in " ${ pids [@] } " ; do
if ps -p " $pid " > /dev/null; then
echo " Killing background process $pid "
kill -HUP " $pid " 2>/dev/null || true
fi
done
readarray -t NSS < <( ip netns list 2>/dev/null | grep -E '^wptns[0-9]+' | awk '{print $1}' )
if [ " ${# NSS } " = 0 ] ; then
return
fi
echo " Cleaning up namespaces: ${ NSS [*] } "
for i in " ${ !NSS[@] } " ; do
ns = " ${ NSS [ $i ] } "
echo " Cleaning up namespace: $ns "
# Delete namespace
if sudo_and_ask "" ip netns list | grep -qw " $ns " ; then
sudo_and_ask " Removing netns $ns " ip netns delete " $ns " || echo " failed to delete netns $ns "
fi
# Remove hosts override
sudo_and_ask " Removing support files for netns $ns " rm -rf " /etc/netns/ $ns " || echo " failed to delete /etc/netns/ $ns "
done
}
cleanup_run_dirs( ) {
readarray -t dirs < <( ls " ${ BUILD_DIR } /wpt " 2>/dev/null)
if [ " ${# dirs } " = 0 ] ; then
return
fi
echo " Cleaning run dirs: ${ dirs [*] } "
for dir in " ${ dirs [@] } " ; do
mount_path = " ${ BUILD_DIR } /wpt/ $dir /merged "
for _ in $( seq 1 5) ; do
readarray -t pids_in_use < <( sudo_and_ask "" lsof " $mount_path " 2>/dev/null | cut -f2 -d' ' )
[ " ${# pids_in_use [@] } " = 0 ] && break
echo Trying to kill procs: " ${ pids_in_use [@] } "
kill -INT " ${ pids_in_use [@] } " 2>/dev/null || true
done
2026-01-02 07:12:27 -03:00
sudo_and_ask "" umount " $mount_path " || true
done
rm -fr " ${ BUILD_DIR } /wpt "
}
2025-04-24 12:36:10 -03:00
cleanup_merge_dirs_and_infra( ) {
2025-06-18 05:14:34 -03:00
# Cleanup is only needed on Linux
if [ [ $OSTYPE = = 'linux' * ] ] ; then
cleanup_run_dirs
cleanup_run_infra
fi
2025-04-24 12:36:10 -03:00
}
trap cleanup_merge_dirs_and_infra EXIT INT TERM
make_instances( ) {
if [ " ${ PARALLEL_INSTANCES } " = 1 ] ; then
echo 1
return
fi
if ! command -v ip & >/dev/null; then
echo "the 'ip' command is required to run WPT in chunked mode" >& 2
echo 1
return
fi
if ! sudo_and_ask "Making test netns 'testns'" ip netns add testns; then
echo "ip netns failed, chunked mode not available" >& 2
echo 1
return
fi
sudo_and_ask "Cleaning up test netns 'testns'" ip netns delete testns
explicit_count = " ${ PARALLEL_INSTANCES } "
local total_cores count ns
total_cores = $( nproc)
count = $(( total_cores / 2 ))
( ( count < 1 ) ) && count = 1
if ( ( explicit_count > 0 ) ) ; then
count = " $explicit_count "
fi
for i in $( seq 0 $(( count - 1 )) ) ; do
ns = " wptns $i "
# Create namespace
sudo_and_ask "" ip netns add " $ns "
sudo_and_ask "" ip netns exec " $ns " ip link set lo up
# Setup DNS and hosts (we've messed with it before getting here)
sudo_and_ask "" mkdir -p " /etc/netns/ $ns "
sudo_and_ask "" cp /etc/hosts " /etc/netns/ $ns /hosts "
done
echo " $count "
}
instance_run( ) {
local idx = " $1 " ; shift
local rundir = " $1 " ; shift
local ns = " wptns $idx "
if sudo_and_ask "" ip netns list | grep -qw " $ns " ; then
(
cd " $rundir "
sudo_and_ask "" ip netns exec " $ns " sudo -u " $USER " -- env " PATH= $PATH " " $@ "
)
else
echo " netns $ns not found, running in the host namespace "
(
cd " ${ WPT_SOURCE_DIR } "
" $@ "
)
fi
}
show_files( ) {
if ! " $SHOW_LOGFILES " ; then
return
fi
local files = ( " $@ " )
if ! command -v tmux & >/dev/null || ! " $TRY_SHOW_LOGFILES_IN_TMUX " ; then
if " $TRY_SHOW_LOGFILES_IN_TMUX " ; then
echo "tmux is not available, falling back to tail"
fi
if " $SHOW_PROGRESS " ; then
bash " ${ DIR } /watch_wpt_progress.sh " " ${ files [@] } " &
else
tail -f " ${ files [@] } " &
fi
PID = $!
for pid in $( jobs -p | grep -v $PID ) ; do
# shellcheck disable=SC2009
ps | grep -q " $pid " && wait " $pid "
done
kill -HUP $PID
else
tmux new-session -d
tmux send-keys " less +F ${ files [0] } " C-m
for ( ( i = 1; i < ${# files [@] } ; i++) ) ; do
if ( ( i % 2 = = 1 ) ) ; then
tmux split-window -h " less +F ${ files [i] } "
else
tmux split-window -v " less +F ${ files [i] } "
fi
tmux select -layout tiled > /dev/null
done
tmux attach
fi
}
copy_results_to( ) {
local target = " $1 " ; shift
local runcount = " $1 " ; shift
mkdir -p " $target "
for i in $( seq 0 $(( runcount - 1 )) ) ; do
for f in " $( run_dir_path " $i " ) /upper " /*; do
cp -r " $f " " $target / $( basename " $f " ) .run_ $i "
done
done
}
show_summary( ) {
local logs = ( " $@ " )
local total_tests = 0
local expected = 0
local skipped = 0
local errored = 0
local subtest_issues = 0
local max_time = 0
for out_file in " ${ logs [@] } " ; do
# wpt puts random garbage in the output, strip those (as they're all nonprint)
mapfile -t lines < <( grep -A4 -aE 'Ran [0-9]+ tests finished in' " $out_file " \
| iconv -f utf-8 -t ascii//TRANSLIT 2>/dev/null \
| sed 's/[^[:print:]]//g' )
for line in " ${ lines [@] } " ; do
if [ [ $line = ~ Ran[ [ :space:] ] ( [ 0-9] +) [ [ :space:] ] tests[ [ :space:] ] finished[ [ :space:] ] in[ [ :space:] ] ( [ 0-9.] +) ] ] ; then
( ( total_tests += BASH_REMATCH[ 1] ) )
time = ${ BASH_REMATCH [2] }
[ [ $( echo " $time > $max_time " | bc -l) = = 1 ] ] && max_time = $time
elif [ [ $line = ~ ( [ 0-9] +) [ [ :space:] ] ran[ [ :space:] ] as[ [ :space:] ] expected ] ] ; then
( ( expected += BASH_REMATCH[ 1] ) )
elif [ [ $line = ~ ( [ 0-9] +) [ [ :space:] ] tests[ [ :space:] ] skipped ] ] ; then
( ( skipped += BASH_REMATCH[ 1] ) )
elif [ [ $line = ~ ( [ 0-9] +) [ [ :space:] ] tests[ [ :space:] ] ( crashed| timed[ [ :space:] ] out| had[ [ :space:] ] errors) [ [ :space:] ] unexpectedly ] ] ; then
( ( errored += BASH_REMATCH[ 1] ) )
elif [ [ $line = ~ ( [ 0-9] +) [ [ :space:] ] tests[ [ :space:] ] had[ [ :space:] ] unexpected[ [ :space:] ] subtest[ [ :space:] ] results ] ] ; then
( ( subtest_issues += BASH_REMATCH[ 1] ) )
fi
done
done
echo " Total tests run: $total_tests "
echo " Ran as expected: $expected "
echo " Skipped: $skipped "
echo " Errored unexpectedly: $errored "
echo " Unexpected subtest results: $subtest_issues "
echo " Longest run time: ${ max_time } s "
}
2025-05-08 08:40:07 -03:00
# run_wpt_chunked <#processes> <wpt args...>
2025-04-24 12:36:10 -03:00
run_wpt_chunked( ) {
local procs concurrency
2025-05-08 08:40:07 -03:00
procs = " $1 " ; shift
2025-04-24 12:36:10 -03:00
2025-03-25 16:38:29 -03:00
# Ensure open files limit is at least 1024, so the WPT runner does not run out of descriptors
2025-04-24 12:36:10 -03:00
if [ " $( ulimit -n) " -lt $(( 1024 * procs)) ] ; then
ulimit -S -n $(( 1024 * procs))
fi
if [ " $procs " -le 1 ] ; then
2025-05-14 03:21:25 -03:00
command = ( ./wpt run -f --browser-version= " 1.0- $( ladybird_git_hash) " --processes= " ${ WPT_PROCESSES } " " $@ " )
2025-04-24 12:36:10 -03:00
echo " ${ command [@] } "
" ${ command [@] } "
return
2025-03-25 16:38:29 -03:00
fi
2025-04-24 12:36:10 -03:00
concurrency = $(( $( nproc) * 2 / procs ))
echo "Preparing the venv setup..."
base_venv = " ${ BUILD_DIR } /wpt-prep/_venv "
./wpt --venv " $base_venv " run " ${ WPT_ARGS [@] } " ladybird THIS_TEST_CANNOT_POSSIBLY_EXIST || true
echo " Launching $procs chunked instances (concurrency= $concurrency each) "
local logs = ( )
2025-05-15 06:49:31 -03:00
local run_start_time
run_start_time = $( date +"%Y%m%d%H%M%S" )
2025-04-24 12:36:10 -03:00
for i in $( seq 0 $(( procs - 1 )) ) ; do
local rundir runpath logpath
rundir = " $( ensure_run_dir " $i " ) "
runpath = " $( run_dir_path " $i " ) "
logpath = " $runpath /upper/run.logs "
echo " rundir at $rundir , logs in $logpath "
touch " $logpath "
logs += ( " $logpath " )
cp -r " $base_venv " " ${ runpath } /_venv "
command = ( ./wpt --venv " ${ runpath } /_venv " \
run \
--this-chunk= " $(( i + 1 )) " \
--total-chunks= " $procs " \
--chunk-type= hash \
-f \
2025-05-14 03:21:25 -03:00
--browser-version= " 1.0- $( ladybird_git_hash) "
2025-04-24 12:36:10 -03:00
--processes= " $concurrency " \
" $@ " )
2025-05-14 03:21:25 -03:00
echo " [INSTANCE $i / ns wptns $i ] ${ command [*] } "
2025-04-24 12:36:10 -03:00
instance_run " $i " " $rundir " script -q " $logpath " -c " $( printf "%q " " ${ command [@] } " ) " & >/dev/null &
done
show_files " ${ logs [@] } "
wait
2025-05-15 06:49:31 -03:00
copy_results_to " ${ BUILD_DIR } /wpt-run- ${ run_start_time } " " $procs "
2025-04-24 12:36:10 -03:00
show_summary " ${ logs [@] } "
}
2025-05-08 08:40:07 -03:00
absolutize_log_args( ) {
for ( ( i = 0; i<${# WPT_LOG_ARGS [@] } ; i += 2) ) ; do
WPT_LOG_ARGS[ i + 1] = " $( absolutize_path " ${ WPT_LOG_ARGS [i + 1] } " ) "
done
}
2025-09-07 05:19:04 -03:00
update_hosts_file_if_needed( ) {
pushd " ${ WPT_SOURCE_DIR } " > /dev/null
if [ " $( comm -13 <( sort -u /etc/hosts) <(./wpt make-hosts-file | sort -u) | wc -l) " -gt 0 ] ; then
./wpt make-hosts-file | sudo_and_ask "Appending wpt hosts to /etc/hosts" tee -a /etc/hosts
fi
popd > /dev/null
}
2025-04-24 12:36:10 -03:00
execute_wpt( ) {
2025-05-08 08:40:07 -03:00
local procs
procs = $( make_instances)
if [ [ " $procs " -le 1 ] ] ; then
absolutize_log_args
fi
2024-08-12 11:33:28 -03:00
pushd " ${ WPT_SOURCE_DIR } " > /dev/null
for certificate_path in " ${ WPT_CERTIFICATES [@] } " ; do
if [ ! -f " ${ certificate_path } " ] ; then
echo " Certificate not found: \" ${ certificate_path } \" "
exit 1
fi
WPT_ARGS += ( " --webdriver-arg=--certificate= ${ certificate_path } " )
done
2024-12-18 17:37:43 -03:00
construct_test_list " ${ @ } "
2025-05-08 08:40:07 -03:00
run_wpt_chunked " $procs " " ${ WPT_ARGS [@] } " " ${ WPT_LOG_ARGS [@] } " ladybird " ${ TEST_LIST [@] } "
2024-08-12 11:33:28 -03:00
popd > /dev/null
}
run_wpt( ) {
ensure_wpt_repository
build_ladybird_and_webdriver
2025-09-07 05:19:04 -03:00
update_hosts_file_if_needed
2024-12-18 17:37:43 -03:00
execute_wpt " ${ @ } "
2024-08-12 11:33:28 -03:00
}
2024-10-11 15:30:24 -03:00
serve_wpt( )
{
ensure_wpt_repository
2025-09-07 05:19:04 -03:00
update_hosts_file_if_needed
2024-10-11 15:30:24 -03:00
pushd " ${ WPT_SOURCE_DIR } " > /dev/null
./wpt serve
popd > /dev/null
}
2025-07-15 16:14:07 -03:00
cleanup_bisect( )
{
local temp_file_directory = " $1 " ; shift
if [ -d " ${ temp_file_directory } " ] ; then
echo " Removing temp file directory: ${ temp_file_directory } "
rm -rf " ${ temp_file_directory } "
fi
git bisect reset
}
bisect_wpt( )
{
if ! git diff-index --quiet HEAD --; then
echo "You have uncommitted changes, please commit or stash them before bisecting."
exit 1
fi
local bad = " $1 " ; shift
local good = " $1 " ; shift
# Commits from before ladybird.py was added don't currently work with this script
OLDEST_COMMIT_ALLOWED = "061a7f766ce"
if ! git rev-parse --verify " ${ bad } " >/dev/null 2>& 1; then
echo " Bad commit ' ${ bad } ' not found. "
exit 1
fi
if ! git rev-parse --verify " ${ good } " >/dev/null 2>& 1; then
echo " Good commit ' ${ good } ' not found. "
exit 1
fi
if ! git merge-base --is-ancestor ${ OLDEST_COMMIT_ALLOWED } " ${ good } " ; then
echo " Commits older than ${ OLDEST_COMMIT_ALLOWED } aren't allowed (because ladybird.py is required). "
exit 1
fi
if [ " ${ good } " = " ${ bad } " ] ; then
echo "The good commit and the bad commit must be different."
exit 1
fi
if ! git merge-base --is-ancestor " ${ good } " " ${ bad } " ; then
echo "The good commit must be older than the bad commit."
exit 1
fi
ensure_wpt_repository
construct_test_list " ${ @ } "
pushd " ${ LADYBIRD_SOURCE_DIR } " > /dev/null
local temp_file_directory_base
temp_file_directory_base = " $( mktemp -p " ${ TMPDIR } " -d "wpt-bisect-helper-XXXXXX" ) "
mkdir " ${ temp_file_directory_base } /Meta "
local baseline_log_file
baseline_log_file = " $( mktemp -p " ${ temp_file_directory_base } " -u "XXXXXX.log" ) "
local current_branch_or_commit
current_branch_or_commit = " $( git branch --show-current 2> /dev/null) "
if [ -z " ${ current_branch_or_commit } " ] ; then
current_branch_or_commit = " $( git rev-parse HEAD) "
fi
# We create the baseline log file against the bad commit bcause building it may be significantly faster if the
# good commit is significantly older than the bad commit.
git checkout " ${ bad } " 2> /dev/null
trap 'git checkout "${current_branch_or_commit}" 2> /dev/null' EXIT INT TERM
echo " Generating baseline log file at \" ${ baseline_log_file } \" "
$0 run --log " ${ baseline_log_file } " " ${ @ } " || true
trap - EXIT INT TERM
git checkout " ${ current_branch_or_commit } " 2> /dev/null
# We need to copy scripts that will run during bisection to ensure that we will always have the latest version.
required_build_files = (
"shell_include.sh"
"wpt-bisect-helper.sh"
)
for file in " ${ required_build_files [@] } " ; do
cp " ${ LADYBIRD_SOURCE_DIR } /Meta/ ${ file } " " ${ temp_file_directory_base } /Meta/ ${ file } "
done
cp " $0 " " ${ temp_file_directory_base } /Meta/WPT.sh "
git bisect start " ${ bad } " " ${ good } "
trap cleanup_bisect INT TERM
git bisect run " ${ temp_file_directory_base } /Meta/wpt-bisect-helper.sh " " ${ baseline_log_file } " " ${ @ } " || true
trap - INT TERM
cleanup_bisect " ${ temp_file_directory_base } "
popd > /dev/null
}
2024-12-09 08:05:57 -03:00
list_tests_wpt( )
{
ensure_wpt_repository
2024-12-18 17:37:43 -03:00
construct_test_list " ${ @ } "
2024-12-09 08:05:57 -03:00
pushd " ${ WPT_SOURCE_DIR } " > /dev/null
./wpt run --list-tests ladybird " ${ TEST_LIST [@] } "
popd > /dev/null
}
2024-11-02 03:03:22 -03:00
import_wpt( )
{
2025-07-30 16:03:42 -03:00
ensure_wpt_repository
2025-07-02 06:43:37 -03:00
pushd " ${ WPT_SOURCE_DIR } " > /dev/null
if ! git fetch origin > /dev/null; then
echo "Failed to fetch the WPT repository, please check your network connection."
exit 1
fi
local local_hash
local_hash = $( git rev-parse HEAD)
local remote_hash
remote_hash = $( git rev-parse origin/master)
if [ " $local_hash " != " $remote_hash " ] ; then
echo " WPT repository is not up to date, please run ' $0 update' first. "
exit 1
fi
popd > /dev/null
2024-11-06 15:08:42 -03:00
for i in " ${ !INPUT_PATHS[@] } " ; do
item = " ${ INPUT_PATHS [i] } "
item = " ${ item #http : //wpt.live/ } "
item = " ${ item #https : //wpt.live/ } "
INPUT_PATHS[ i] = " $item "
done
2024-12-09 08:37:43 -03:00
2024-12-19 10:04:05 -03:00
RAW_TESTS = ( )
2024-12-09 08:37:43 -03:00
while IFS = read -r test_file; do
2024-12-19 10:04:05 -03:00
RAW_TESTS += ( " ${ test_file %% \? * } " )
2024-12-09 08:37:43 -03:00
done < <(
" ${ ARG0 } " list-tests " ${ INPUT_PATHS [@] } "
)
2024-12-19 10:04:05 -03:00
if [ " ${# RAW_TESTS [@] } " -eq 0 ] ; then
2024-12-09 08:37:43 -03:00
echo "No tests found for the given paths"
exit 1
fi
2024-12-19 10:04:05 -03:00
TESTS = ( )
while IFS = read -r test_file; do
TESTS += ( " $test_file " )
done < <( printf "%s\n" " ${ RAW_TESTS [@] } " | sort -u)
2024-11-02 03:03:22 -03:00
pushd " ${ LADYBIRD_SOURCE_DIR } " > /dev/null
2025-06-06 21:11:13 -03:00
./Meta/ladybird.py build test-web
2025-07-07 11:03:03 -03:00
trap 'exit 1' EXIT INT TERM
2024-12-09 08:37:43 -03:00
for path in " ${ TESTS [@] } " ; do
2024-11-02 03:03:22 -03:00
echo " Importing test from ${ path } "
2025-06-21 01:04:20 -03:00
if ! ./Meta/import-wpt-test.py " ${ IMPORT_ARGS [@] } " https://wpt.live/" ${ path } " ; then
2024-12-09 08:39:05 -03:00
continue
fi
2025-07-07 11:03:03 -03:00
" ${ TEST_WEB_BINARY } " --rebaseline -f " $path " || true
2024-11-02 03:03:22 -03:00
done
2025-07-07 11:03:03 -03:00
trap - EXIT INT TERM
2024-11-02 03:03:22 -03:00
popd > /dev/null
}
2024-08-12 11:33:28 -03:00
compare_wpt( ) {
ensure_wpt_repository
METADATA_DIR = $( mktemp -d)
pushd " ${ WPT_SOURCE_DIR } " > /dev/null
2025-05-02 16:08:02 -03:00
./wpt update-expectations --product ladybird --full --metadata= " ${ METADATA_DIR } " " ${ INPUT_LOG_NAME } "
2024-08-12 11:33:28 -03:00
popd > /dev/null
WPT_ARGS += ( " --metadata= ${ METADATA_DIR } " )
build_ladybird_and_webdriver
2025-09-07 05:19:04 -03:00
update_hosts_file_if_needed
2024-12-18 17:37:43 -03:00
execute_wpt " ${ @ } "
2024-08-12 11:33:28 -03:00
rm -rf " ${ METADATA_DIR } "
}
2025-07-15 16:14:07 -03:00
if [ [ " $CMD " = ~ ^( update| clean| run| serve| bisect| compare| import| list-tests) $ ] ] ; then
2024-08-12 11:33:28 -03:00
case " $CMD " in
update)
update_wpt
; ;
run)
2024-12-18 17:37:43 -03:00
run_wpt " ${ @ } "
2024-08-12 11:33:28 -03:00
; ;
2025-04-24 12:36:10 -03:00
clean)
2026-01-02 07:29:39 -03:00
if [ [ $OSTYPE = = 'linux' * ] ] ; then
cleanup_run_infra
cleanup_run_dirs true
else
echo "Cleanup is only needed on Linux"
fi
2025-04-24 12:36:10 -03:00
; ;
2024-10-11 15:30:24 -03:00
serve)
serve_wpt
; ;
2025-07-15 16:14:07 -03:00
bisect)
if [ $# -lt 3 ] ; then
echo " Usage: $0 bisect <bad> <good> [test paths...] "
usage
fi
bisect_wpt " ${ @ } "
; ;
2024-11-02 03:03:22 -03:00
import)
2025-07-07 10:43:28 -03:00
while [ [ " $1 " = ~ ^--( force| wpt-base-url) $ ] ] ; do
if [ " $1 " = "--wpt-base-url" ] ; then
if [ -z " $2 " ] ; then
echo "Missing argument for --wpt-base-url"
usage
fi
IMPORT_ARGS += ( " --wpt-base-url= $2 " )
shift
else
IMPORT_ARGS += ( " $1 " )
fi
2025-06-21 01:04:20 -03:00
shift
2025-07-07 10:43:28 -03:00
done
2024-11-02 03:03:22 -03:00
if [ $# -eq 0 ] ; then
usage
fi
INPUT_PATHS = ( " $@ " )
import_wpt
; ;
2024-08-12 11:33:28 -03:00
compare)
2025-07-15 17:10:59 -03:00
INPUT_LOG_NAME = " $( realpath " $1 " ) "
2024-08-12 11:33:28 -03:00
if [ ! -f " $INPUT_LOG_NAME " ] ; then
echo " Log file not found: \" ${ INPUT_LOG_NAME } \" "
usage;
fi
shift
2024-12-18 17:37:43 -03:00
compare_wpt " ${ @ } "
2024-08-12 11:33:28 -03:00
; ;
2024-12-09 08:05:57 -03:00
list-tests)
2024-12-18 17:37:43 -03:00
list_tests_wpt " ${ @ } "
2024-12-09 08:05:57 -03:00
; ;
2024-08-12 11:33:28 -03:00
esac
else
>& 2 echo " Unknown command: $CMD "
usage
fi