Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ DerivePointerAlignment: false
PointerAlignment: Left
ReferenceAlignment: Left
ReflowComments: true
SortIncludes: false
SortIncludes: CaseSensitive
SortUsingDeclarations: false
MaxEmptyLinesToKeep: 1

Expand All @@ -93,7 +93,24 @@ IndentRequiresClause: true
SpaceAroundPointerQualifiers: Default

# Include formatting
IncludeBlocks: Preserve
IncludeBlocks: Regroup
IncludeCategories:
# 1. Main header (e.g., foo.cpp includes foo.hpp first)
- Regex: '^".*\.hpp"$'
Priority: 1
SortPriority: 1
# 2. C++ standard library
- Regex: '^<[^/]+>$'
Priority: 2
SortPriority: 2
# 3. Third-party libraries (uni-algo, catch2, nlohmann)
- Regex: '^<(uni|catch2|nlohmann)/'
Priority: 3
SortPriority: 3
# 4. Project headers (skyr/...)
- Regex: '^<skyr/'
Priority: 4
SortPriority: 4

# Namespace formatting
CompactNamespaces: false
Expand Down
156 changes: 156 additions & 0 deletions .github/workflows/wpt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
name: Web Platform Tests

# Run on push to main, weekly schedule, and manual trigger
on:
push:
branches:
- main
schedule:
# Run every Monday at 00:00 UTC
- cron: '0 0 * * 1'
workflow_dispatch:
# Allow manual triggering

env:
CMAKE_VERSION: 3.21.7
NINJA_VERSION: 1.11.0

jobs:
wpt-report:
name: Web Platform Tests Report
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@master

- name: Download Ninja and CMake
id: cmake_and_ninja
shell: cmake -P {0}
run: |
set(cmake_version $ENV{CMAKE_VERSION})
set(ninja_version $ENV{NINJA_VERSION})

message(STATUS "Using host CMake version: ${CMAKE_VERSION}")

set(ninja_suffix "linux.zip")
set(cmake_suffix "linux-x86_64.tar.gz")
set(cmake_dir "cmake-${cmake_version}-linux-x86_64/bin")

set(ninja_url "https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-${ninja_suffix}")
file(DOWNLOAD "${ninja_url}" ./ninja.zip SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ninja.zip)

set(cmake_url "https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-${cmake_suffix}")
file(DOWNLOAD "${cmake_url}" ./cmake.zip SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./cmake.zip)

# Save the path for other steps
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/${cmake_dir}" cmake_dir)
message("::set-output name=cmake_dir::${cmake_dir}")

execute_process(
COMMAND chmod +x ninja
COMMAND chmod +x ${cmake_dir}/cmake
)

- name: Install vcpkg
id: vcpkg
shell: bash
run: |
mkdir -p ${GITHUB_WORKSPACE}/vcpkg
cd ${GITHUB_WORKSPACE}/vcpkg
git init
git remote add origin https://github.com/microsoft/vcpkg.git
git fetch origin master
git checkout -b master origin/master
./bootstrap-vcpkg.sh
./vcpkg install uni-algo nlohmann-json

- name: Configure
shell: cmake -P {0}
working-directory: ${{ env.HOME }}
run: |
set(ENV{CC} gcc-14)
set(ENV{CXX} g++-14)

set(path_separator ":")
set(ENV{PATH} "$ENV{GITHUB_WORKSPACE}${path_separator}$ENV{PATH}")

execute_process(
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
-S .
-B build
-G Ninja
-D CMAKE_CXX_STANDARD:STRING=23
-D skyr_WARNINGS_AS_ERRORS=OFF
-D skyr_BUILD_TESTS=OFF
-D skyr_BUILD_WPT=ON
-D skyr_BUILD_DOCS=OFF
-D skyr_BUILD_EXAMPLES=OFF
-D CMAKE_BUILD_TYPE=RelWithDebInfo
-D CMAKE_TOOLCHAIN_FILE=$ENV{GITHUB_WORKSPACE}/vcpkg/scripts/buildsystems/vcpkg.cmake
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Configuration failed")
endif()

- name: Build
shell: cmake -P {0}
working-directory: ${{ env.HOME }}
run: |
set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ")

set(path_separator ":")
set(ENV{PATH} "$ENV{GITHUB_WORKSPACE}${path_separator}$ENV{PATH}")

execute_process(
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake --build build
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Build failed")
endif()

- name: Run Web Platform Tests
shell: bash
working-directory: ${{ env.HOME }}
run: |
echo "Running Web Platform Tests..."
./build/tests/wpt/wpt_runner --force-download 2>&1 | tee wpt-report.txt
echo "WPT_EXIT_CODE=${PIPESTATUS[0]}" >> $GITHUB_ENV

- name: Display Report Summary
if: always()
shell: bash
run: |
echo "==================================================="
echo "Web Platform Tests Report Summary"
echo "==================================================="
if [ -f wpt-report.txt ]; then
# Extract summary section from report
sed -n '/SUMMARY:/,/^$/p' wpt-report.txt
else
echo "Report file not found!"
fi

- name: Upload Full Report
if: always()
uses: actions/upload-artifact@v4
with:
name: wpt-report
path: wpt-report.txt
retention-days: 90

- name: Job Status
if: always()
shell: bash
run: |
if [ "${{ env.WPT_EXIT_CODE }}" -eq "0" ]; then
echo "✅ Web Platform Tests completed successfully"
echo "📊 Full report available as workflow artifact"
else
echo "⚠️ Web Platform Tests exited with code ${{ env.WPT_EXIT_CODE }}"
echo "📊 Check the report for details"
exit 0 # Don't fail the workflow - this is just a report
fi
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ _build
.build
*.log
.DS_Store
urltestdata.json
104 changes: 104 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ cmake --build _build

Key build options:
- `skyr_BUILD_TESTS` (ON): Build tests
- `skyr_BUILD_WPT` (OFF): Build Web Platform Tests runner
- `skyr_ENABLE_FILESYSTEM_FUNCTIONS` (ON): Enable filesystem::path conversion
- `skyr_ENABLE_JSON_FUNCTIONS` (ON): Enable JSON serialization
- `skyr_BUILD_WITHOUT_EXCEPTIONS` (OFF): Build without exceptions
Expand Down Expand Up @@ -118,6 +119,109 @@ ctest --test-dir _build
endforeach ()
```

## Web Platform Tests (WPT)

**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.

### Philosophy

- **Not pass/fail tests** - WPT is a reporting tool, not a quality gate
- **Edge case discovery** - Shows which obscure URL patterns are supported
- **100% is not the goal** - Some edge cases may be intentionally unsupported if they add complexity or hurt performance
- **Separate from unit tests** - Does not affect CI/PR status

### Building WPT Tests

```bash
cmake \
-B _build \
-G "Ninja" \
-DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake \
-Dskyr_BUILD_WPT=ON \
.
cmake --build _build
```

**Dependencies**: Requires `nlohmann-json` for parsing test data.

### Running WPT Tests

```bash
# Run with latest test data (downloads from WPT repository)
./_build/tests/wpt/wpt_runner --force-download

# Run with cached data (if less than 24 hours old)
./_build/tests/wpt/wpt_runner

# Specify custom cache location
./_build/tests/wpt/wpt_runner --cache /path/to/urltestdata.json
```

### Report Format

The runner outputs a comprehensive report:

```
=================================================
WPT URL Test Suite Report
=================================================
Test Data: https://github.com/web-platform-tests/...
Generated: 2025-12-30 10:30:00 UTC

SUMMARY:
Total Tests: 1,234
Successful: 1,150 (93.2%)
Failed: 84 (6.8%)

FAILURE BREAKDOWN:
Parse Errors: 45 (53.6% of failures)
Component Mismatch: 39 (46.4% of failures)

SAMPLE FAILURES (first 20):
[1] Input: "http://example.org/foo%2€bar"
Expected: parse failure
Actual: parsed successfully

[2] Input: "http://[::1]:65536/"
Expected: parsed successfully
Actual: parse failure (invalid port)
...
=================================================
```

### Implementation Details

- **Parallel execution**: Uses `std::execution::par_unseq` to process tests in parallel
- **Thread-safe aggregation**: Atomic counters and mutex-protected failure collection
- **Automatic downloads**: Fetches latest `urltestdata.json` from WPT repository
- **Smart caching**: Reuses cached data if less than 24 hours old

### GitHub Actions

WPT runs automatically via `.github/workflows/wpt-integration.yml`:

**Triggers:**
- Push to `main` branch
- Weekly schedule (Mondays at 00:00 UTC)
- Manual workflow dispatch

**Output:**
- Report displayed in workflow log
- Full report uploaded as artifact (90-day retention)
- Does not fail CI - informational only

**Configuration:**
- Single build: Linux GCC 14 Release
- Fast execution: Parallel test processing
- Always downloads latest test data

### Test Data Source

Test data comes from the official WPT repository:
`https://github.com/web-platform-tests/wpt/blob/master/url/resources/urltestdata.json`

This ensures compliance testing against the latest WhatWG URL specification test cases.

## Code Structure

**Directory Layout**:
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ project(
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

option(skyr_BUILD_TESTS "Build the URL tests." ON)
option(skyr_BUILD_WPT "Build Web Platform Tests runner (report-only, not unit tests)." OFF)
option(skyr_BUILD_DOCS "Build the URL documentation." OFF)
option(skyr_BUILD_EXAMPLES "Build the URL examples." OFF)
option(skyr_FULL_WARNINGS "Build the library with all warnings turned on." ON)
Expand Down
14 changes: 7 additions & 7 deletions docs/Doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -829,13 +829,13 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.

INPUT = @PROJECT_SOURCE_DIR@/include/skyr/v1/ \
@PROJECT_SOURCE_DIR@/include/skyr/v1/core/ \
@PROJECT_SOURCE_DIR@/include/skyr/v1/domain/ \
@PROJECT_SOURCE_DIR@/include/skyr/v1/network/ \
@PROJECT_SOURCE_DIR@/include/skyr/v1/percent_encoding/ \
@PROJECT_SOURCE_DIR@/include/skyr/v1/filesystem/ \
@PROJECT_SOURCE_DIR@/include/skyr/v1/json/
INPUT = @PROJECT_SOURCE_DIR@/include/skyr/ \
@PROJECT_SOURCE_DIR@/include/skyr/core/ \
@PROJECT_SOURCE_DIR@/include/skyr/domain/ \
@PROJECT_SOURCE_DIR@/include/skyr/network/ \
@PROJECT_SOURCE_DIR@/include/skyr/percent_encoding/ \
@PROJECT_SOURCE_DIR@/include/skyr/filesystem/ \
@PROJECT_SOURCE_DIR@/include/skyr/json/

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
Expand Down
4 changes: 2 additions & 2 deletions docs/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ API
``skyr::host`` class
^^^^^^^^^^^^^^^^^^^^

.. doxygenclass:: skyr::v1::host
.. doxygenclass:: skyr::host
:members:

``skyr::url_record`` class
^^^^^^^^^^^^^^^^^^^^^^^^^^

.. doxygenclass:: skyr::v1::url_record
.. doxygenclass:: skyr::url_record
:members:

``skyr::url_record`` functions
Expand Down
2 changes: 1 addition & 1 deletion docs/domain.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ Domain to ASCII
Error codes
^^^^^^^^^^^

.. doxygenenum:: skyr::v1::domain_errc
.. doxygenenum:: skyr::domain_errc
6 changes: 3 additions & 3 deletions docs/filesystem.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ API
Path
^^^^

.. doxygenfunction:: skyr::v1::filesystem::from_path
.. doxygenfunction:: skyr::filesystem::from_path

.. doxygenfunction:: skyr::v1::filesystem::to_path
.. doxygenfunction:: skyr::filesystem::to_path

Error codes
^^^^^^^^^^^

.. doxygenenum:: skyr::v1::filesystem::path_errc
.. doxygenenum:: skyr::filesystem::path_errc
4 changes: 2 additions & 2 deletions docs/json.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ API
JSON
^^^^

.. doxygenfunction:: skyr::v1::json::encode_query
.. doxygenfunction:: skyr::json::encode_query

.. doxygenfunction:: skyr::v1::json::decode_query
.. doxygenfunction:: skyr::json::decode_query
Loading
Loading