Skip to content

Commit 7d402bf

Browse files
authored
Add wpt runner (#173)
* Add wpt runner * Enable more tests * Add rules to order headers * Fix whitespace parsing in host * Fix whitespace parsing in opaque path * Fix file URL with Windows driver letter * Fix handling of '@' in password * Apply fix for percent encoding validation * Fix out-of-date documentation and examples
1 parent 329c541 commit 7d402bf

101 files changed

Lines changed: 3126 additions & 1444 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.clang-format

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ DerivePointerAlignment: false
7575
PointerAlignment: Left
7676
ReferenceAlignment: Left
7777
ReflowComments: true
78-
SortIncludes: false
78+
SortIncludes: CaseSensitive
7979
SortUsingDeclarations: false
8080
MaxEmptyLinesToKeep: 1
8181

@@ -93,7 +93,24 @@ IndentRequiresClause: true
9393
SpaceAroundPointerQualifiers: Default
9494

9595
# Include formatting
96-
IncludeBlocks: Preserve
96+
IncludeBlocks: Regroup
97+
IncludeCategories:
98+
# 1. Main header (e.g., foo.cpp includes foo.hpp first)
99+
- Regex: '^".*\.hpp"$'
100+
Priority: 1
101+
SortPriority: 1
102+
# 2. C++ standard library
103+
- Regex: '^<[^/]+>$'
104+
Priority: 2
105+
SortPriority: 2
106+
# 3. Third-party libraries (uni-algo, catch2, nlohmann)
107+
- Regex: '^<(uni|catch2|nlohmann)/'
108+
Priority: 3
109+
SortPriority: 3
110+
# 4. Project headers (skyr/...)
111+
- Regex: '^<skyr/'
112+
Priority: 4
113+
SortPriority: 4
97114

98115
# Namespace formatting
99116
CompactNamespaces: false

.github/workflows/wpt.yml

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
name: Web Platform Tests
2+
3+
# Run on push to main, weekly schedule, and manual trigger
4+
on:
5+
push:
6+
branches:
7+
- main
8+
schedule:
9+
# Run every Monday at 00:00 UTC
10+
- cron: '0 0 * * 1'
11+
workflow_dispatch:
12+
# Allow manual triggering
13+
14+
env:
15+
CMAKE_VERSION: 3.21.7
16+
NINJA_VERSION: 1.11.0
17+
18+
jobs:
19+
wpt-report:
20+
name: Web Platform Tests Report
21+
runs-on: ubuntu-24.04
22+
23+
steps:
24+
- uses: actions/checkout@master
25+
26+
- name: Download Ninja and CMake
27+
id: cmake_and_ninja
28+
shell: cmake -P {0}
29+
run: |
30+
set(cmake_version $ENV{CMAKE_VERSION})
31+
set(ninja_version $ENV{NINJA_VERSION})
32+
33+
message(STATUS "Using host CMake version: ${CMAKE_VERSION}")
34+
35+
set(ninja_suffix "linux.zip")
36+
set(cmake_suffix "linux-x86_64.tar.gz")
37+
set(cmake_dir "cmake-${cmake_version}-linux-x86_64/bin")
38+
39+
set(ninja_url "https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-${ninja_suffix}")
40+
file(DOWNLOAD "${ninja_url}" ./ninja.zip SHOW_PROGRESS)
41+
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ninja.zip)
42+
43+
set(cmake_url "https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-${cmake_suffix}")
44+
file(DOWNLOAD "${cmake_url}" ./cmake.zip SHOW_PROGRESS)
45+
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./cmake.zip)
46+
47+
# Save the path for other steps
48+
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/${cmake_dir}" cmake_dir)
49+
message("::set-output name=cmake_dir::${cmake_dir}")
50+
51+
execute_process(
52+
COMMAND chmod +x ninja
53+
COMMAND chmod +x ${cmake_dir}/cmake
54+
)
55+
56+
- name: Install vcpkg
57+
id: vcpkg
58+
shell: bash
59+
run: |
60+
mkdir -p ${GITHUB_WORKSPACE}/vcpkg
61+
cd ${GITHUB_WORKSPACE}/vcpkg
62+
git init
63+
git remote add origin https://github.com/microsoft/vcpkg.git
64+
git fetch origin master
65+
git checkout -b master origin/master
66+
./bootstrap-vcpkg.sh
67+
./vcpkg install uni-algo nlohmann-json
68+
69+
- name: Configure
70+
shell: cmake -P {0}
71+
working-directory: ${{ env.HOME }}
72+
run: |
73+
set(ENV{CC} gcc-14)
74+
set(ENV{CXX} g++-14)
75+
76+
set(path_separator ":")
77+
set(ENV{PATH} "$ENV{GITHUB_WORKSPACE}${path_separator}$ENV{PATH}")
78+
79+
execute_process(
80+
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
81+
-S .
82+
-B build
83+
-G Ninja
84+
-D CMAKE_CXX_STANDARD:STRING=23
85+
-D skyr_WARNINGS_AS_ERRORS=OFF
86+
-D skyr_BUILD_TESTS=OFF
87+
-D skyr_BUILD_WPT=ON
88+
-D skyr_BUILD_DOCS=OFF
89+
-D skyr_BUILD_EXAMPLES=OFF
90+
-D CMAKE_BUILD_TYPE=RelWithDebInfo
91+
-D CMAKE_TOOLCHAIN_FILE=$ENV{GITHUB_WORKSPACE}/vcpkg/scripts/buildsystems/vcpkg.cmake
92+
RESULT_VARIABLE result
93+
)
94+
if (NOT result EQUAL 0)
95+
message(FATAL_ERROR "Configuration failed")
96+
endif()
97+
98+
- name: Build
99+
shell: cmake -P {0}
100+
working-directory: ${{ env.HOME }}
101+
run: |
102+
set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ")
103+
104+
set(path_separator ":")
105+
set(ENV{PATH} "$ENV{GITHUB_WORKSPACE}${path_separator}$ENV{PATH}")
106+
107+
execute_process(
108+
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake --build build
109+
RESULT_VARIABLE result
110+
)
111+
if (NOT result EQUAL 0)
112+
message(FATAL_ERROR "Build failed")
113+
endif()
114+
115+
- name: Run Web Platform Tests
116+
shell: bash
117+
working-directory: ${{ env.HOME }}
118+
run: |
119+
echo "Running Web Platform Tests..."
120+
./build/tests/wpt/wpt_runner --force-download 2>&1 | tee wpt-report.txt
121+
echo "WPT_EXIT_CODE=${PIPESTATUS[0]}" >> $GITHUB_ENV
122+
123+
- name: Display Report Summary
124+
if: always()
125+
shell: bash
126+
run: |
127+
echo "==================================================="
128+
echo "Web Platform Tests Report Summary"
129+
echo "==================================================="
130+
if [ -f wpt-report.txt ]; then
131+
# Extract summary section from report
132+
sed -n '/SUMMARY:/,/^$/p' wpt-report.txt
133+
else
134+
echo "Report file not found!"
135+
fi
136+
137+
- name: Upload Full Report
138+
if: always()
139+
uses: actions/upload-artifact@v4
140+
with:
141+
name: wpt-report
142+
path: wpt-report.txt
143+
retention-days: 90
144+
145+
- name: Job Status
146+
if: always()
147+
shell: bash
148+
run: |
149+
if [ "${{ env.WPT_EXIT_CODE }}" -eq "0" ]; then
150+
echo "✅ Web Platform Tests completed successfully"
151+
echo "📊 Full report available as workflow artifact"
152+
else
153+
echo "⚠️ Web Platform Tests exited with code ${{ env.WPT_EXIT_CODE }}"
154+
echo "📊 Check the report for details"
155+
exit 0 # Don't fail the workflow - this is just a report
156+
fi

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ _build
66
.build
77
*.log
88
.DS_Store
9+
urltestdata.json

CLAUDE.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ cmake --build _build
6363

6464
Key build options:
6565
- `skyr_BUILD_TESTS` (ON): Build tests
66+
- `skyr_BUILD_WPT` (OFF): Build Web Platform Tests runner
6667
- `skyr_ENABLE_FILESYSTEM_FUNCTIONS` (ON): Enable filesystem::path conversion
6768
- `skyr_ENABLE_JSON_FUNCTIONS` (ON): Enable JSON serialization
6869
- `skyr_BUILD_WITHOUT_EXCEPTIONS` (OFF): Build without exceptions
@@ -118,6 +119,109 @@ ctest --test-dir _build
118119
endforeach ()
119120
```
120121

122+
## Web Platform Tests (WPT)
123+
124+
**Web Platform Tests** provide conformance testing against the official WhatWG URL specification test suite. Unlike unit tests, WPT generates a **report** showing which edge cases are handled and which are not.
125+
126+
### Philosophy
127+
128+
- **Not pass/fail tests** - WPT is a reporting tool, not a quality gate
129+
- **Edge case discovery** - Shows which obscure URL patterns are supported
130+
- **100% is not the goal** - Some edge cases may be intentionally unsupported if they add complexity or hurt performance
131+
- **Separate from unit tests** - Does not affect CI/PR status
132+
133+
### Building WPT Tests
134+
135+
```bash
136+
cmake \
137+
-B _build \
138+
-G "Ninja" \
139+
-DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake \
140+
-Dskyr_BUILD_WPT=ON \
141+
.
142+
cmake --build _build
143+
```
144+
145+
**Dependencies**: Requires `nlohmann-json` for parsing test data.
146+
147+
### Running WPT Tests
148+
149+
```bash
150+
# Run with latest test data (downloads from WPT repository)
151+
./_build/tests/wpt/wpt_runner --force-download
152+
153+
# Run with cached data (if less than 24 hours old)
154+
./_build/tests/wpt/wpt_runner
155+
156+
# Specify custom cache location
157+
./_build/tests/wpt/wpt_runner --cache /path/to/urltestdata.json
158+
```
159+
160+
### Report Format
161+
162+
The runner outputs a comprehensive report:
163+
164+
```
165+
=================================================
166+
WPT URL Test Suite Report
167+
=================================================
168+
Test Data: https://github.com/web-platform-tests/...
169+
Generated: 2025-12-30 10:30:00 UTC
170+
171+
SUMMARY:
172+
Total Tests: 1,234
173+
Successful: 1,150 (93.2%)
174+
Failed: 84 (6.8%)
175+
176+
FAILURE BREAKDOWN:
177+
Parse Errors: 45 (53.6% of failures)
178+
Component Mismatch: 39 (46.4% of failures)
179+
180+
SAMPLE FAILURES (first 20):
181+
[1] Input: "http://example.org/foo%2€bar"
182+
Expected: parse failure
183+
Actual: parsed successfully
184+
185+
[2] Input: "http://[::1]:65536/"
186+
Expected: parsed successfully
187+
Actual: parse failure (invalid port)
188+
...
189+
=================================================
190+
```
191+
192+
### Implementation Details
193+
194+
- **Parallel execution**: Uses `std::execution::par_unseq` to process tests in parallel
195+
- **Thread-safe aggregation**: Atomic counters and mutex-protected failure collection
196+
- **Automatic downloads**: Fetches latest `urltestdata.json` from WPT repository
197+
- **Smart caching**: Reuses cached data if less than 24 hours old
198+
199+
### GitHub Actions
200+
201+
WPT runs automatically via `.github/workflows/wpt-integration.yml`:
202+
203+
**Triggers:**
204+
- Push to `main` branch
205+
- Weekly schedule (Mondays at 00:00 UTC)
206+
- Manual workflow dispatch
207+
208+
**Output:**
209+
- Report displayed in workflow log
210+
- Full report uploaded as artifact (90-day retention)
211+
- Does not fail CI - informational only
212+
213+
**Configuration:**
214+
- Single build: Linux GCC 14 Release
215+
- Fast execution: Parallel test processing
216+
- Always downloads latest test data
217+
218+
### Test Data Source
219+
220+
Test data comes from the official WPT repository:
221+
`https://github.com/web-platform-tests/wpt/blob/master/url/resources/urltestdata.json`
222+
223+
This ensures compliance testing against the latest WhatWG URL specification test cases.
224+
121225
## Code Structure
122226

123227
**Directory Layout**:

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ project(
2525
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
2626

2727
option(skyr_BUILD_TESTS "Build the URL tests." ON)
28+
option(skyr_BUILD_WPT "Build Web Platform Tests runner (report-only, not unit tests)." OFF)
2829
option(skyr_BUILD_DOCS "Build the URL documentation." OFF)
2930
option(skyr_BUILD_EXAMPLES "Build the URL examples." OFF)
3031
option(skyr_FULL_WARNINGS "Build the library with all warnings turned on." ON)

docs/Doxyfile.in

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -829,13 +829,13 @@ WARN_LOGFILE =
829829
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
830830
# Note: If this tag is empty the current directory is searched.
831831

832-
INPUT = @PROJECT_SOURCE_DIR@/include/skyr/v1/ \
833-
@PROJECT_SOURCE_DIR@/include/skyr/v1/core/ \
834-
@PROJECT_SOURCE_DIR@/include/skyr/v1/domain/ \
835-
@PROJECT_SOURCE_DIR@/include/skyr/v1/network/ \
836-
@PROJECT_SOURCE_DIR@/include/skyr/v1/percent_encoding/ \
837-
@PROJECT_SOURCE_DIR@/include/skyr/v1/filesystem/ \
838-
@PROJECT_SOURCE_DIR@/include/skyr/v1/json/
832+
INPUT = @PROJECT_SOURCE_DIR@/include/skyr/ \
833+
@PROJECT_SOURCE_DIR@/include/skyr/core/ \
834+
@PROJECT_SOURCE_DIR@/include/skyr/domain/ \
835+
@PROJECT_SOURCE_DIR@/include/skyr/network/ \
836+
@PROJECT_SOURCE_DIR@/include/skyr/percent_encoding/ \
837+
@PROJECT_SOURCE_DIR@/include/skyr/filesystem/ \
838+
@PROJECT_SOURCE_DIR@/include/skyr/json/
839839

840840
# This tag can be used to specify the character encoding of the source files
841841
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

docs/core.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ API
5353
``skyr::host`` class
5454
^^^^^^^^^^^^^^^^^^^^
5555

56-
.. doxygenclass:: skyr::v1::host
56+
.. doxygenclass:: skyr::host
5757
:members:
5858

5959
``skyr::url_record`` class
6060
^^^^^^^^^^^^^^^^^^^^^^^^^^
6161

62-
.. doxygenclass:: skyr::v1::url_record
62+
.. doxygenclass:: skyr::url_record
6363
:members:
6464

6565
``skyr::url_record`` functions

docs/domain.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ Domain to ASCII
5050
Error codes
5151
^^^^^^^^^^^
5252

53-
.. doxygenenum:: skyr::v1::domain_errc
53+
.. doxygenenum:: skyr::domain_errc

docs/filesystem.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ API
3535
Path
3636
^^^^
3737

38-
.. doxygenfunction:: skyr::v1::filesystem::from_path
38+
.. doxygenfunction:: skyr::filesystem::from_path
3939

40-
.. doxygenfunction:: skyr::v1::filesystem::to_path
40+
.. doxygenfunction:: skyr::filesystem::to_path
4141

4242
Error codes
4343
^^^^^^^^^^^
4444

45-
.. doxygenenum:: skyr::v1::filesystem::path_errc
45+
.. doxygenenum:: skyr::filesystem::path_errc

docs/json.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ API
2424
JSON
2525
^^^^
2626

27-
.. doxygenfunction:: skyr::v1::json::encode_query
27+
.. doxygenfunction:: skyr::json::encode_query
2828

29-
.. doxygenfunction:: skyr::v1::json::decode_query
29+
.. doxygenfunction:: skyr::json::decode_query

0 commit comments

Comments
 (0)