Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
fbe7530
Add manifest-first streaming tar writer for tile extracts
Archdoog Jul 9, 2026
eeb6844
Reject index.bin entries that point past the end of the archive
Archdoog Oct 14, 2026
6055dc4
Report tile IDs in extract errors and make the byte source generic
Archdoog Oct 14, 2026
bc2038f
Split valinor-cli into one module for each subcommand
Archdoog Oct 14, 2026
58cb49b
Add valinor-cli extract for offline sub-extracts
Archdoog Oct 14, 2026
95d76d1
Add GraphId::relative_path and string parsers for graph IDs
Archdoog Oct 21, 2026
dc5a59c
Add one helper module for the test fixture paths
Archdoog Oct 21, 2026
0bffa56
Share the tar block size and index entry name between reader and writer
Archdoog Oct 21, 2026
82b06e4
Make the extract writer generic over tarball and directory sources
Archdoog Oct 21, 2026
708b60b
Write valinor-cli extracts atomically, and from tarballs or directories
Archdoog Oct 21, 2026
241ba87
Share the tile file extension and index entry size constants
Archdoog Oct 21, 2026
280c9e3
Cut the code comments and docstrings to the contract
Archdoog Oct 21, 2026
0208d92
Merge upstream main into feat/write-extract
Archdoog Nov 2, 2026
1fd952d
Add one helper module for the test fixture paths
Archdoog Oct 21, 2026
1ae638d
Reject index.bin entries that point past the end of the archive
Archdoog Oct 14, 2026
76c26eb
Get tile bytes and tile sizes through GraphTileProvider
Archdoog Nov 2, 2026
7bdbdf8
Add GraphId::relative_path and string parsers for graph IDs
Archdoog Oct 21, 2026
cbab35f
Merge the GraphId path and parser helpers
Archdoog Nov 2, 2026
453c996
Merge tile bytes and sizes through GraphTileProvider
Archdoog Nov 2, 2026
462597b
Move the valinor-cli changes to their own pull request
Archdoog Nov 2, 2026
decc8fb
Split valinor-cli into one module for each subcommand
Archdoog Oct 14, 2026
b2898cf
Write extracts from GraphTileProvider handles
Archdoog Nov 2, 2026
9588157
Add valinor-cli extract for offline sub-extracts
Archdoog Nov 2, 2026
2d468ac
Add integration tests of offline extracts with C++ Valhalla
Archdoog Oct 21, 2026
0572140
Merge upstream main into feat/provider-tile-bytes
Archdoog Nov 3, 2026
9387c23
Merge upstream main through the tile bytes and sizes branch
Archdoog Nov 3, 2026
c625852
Merge upstream main through the extract writer branch
Archdoog Nov 3, 2026
9d00f03
Merge upstream main through the extract CLI branch
Archdoog Nov 3, 2026
8db81fd
Read and write the test tile so the writer tests run in Miri
Archdoog Nov 3, 2026
c116b77
Merge the Miri fix for the writer tests
Archdoog Nov 3, 2026
56819aa
Merge the Miri fix for the writer tests
Archdoog Nov 3, 2026
be1f78d
Merge the Miri test gates for the tarball tests
Archdoog Nov 4, 2026
62d309b
Gate the test items that only tarball tests use under Miri
Archdoog Nov 4, 2026
86c50a7
Move the writer tests that Miri cannot run to one module
Archdoog Nov 4, 2026
1cb79f4
Merge the Miri test cleanup
Archdoog Nov 4, 2026
b073b2f
Merge the Miri test cleanup
Archdoog Nov 4, 2026
48adbfe
Reword the doc comments of the provider methods
Archdoog Nov 4, 2026
3747b45
Reword the doc comment of GraphId::parse_tile
Archdoog Nov 4, 2026
cf0eb36
Merge the provider doc comment changes
Archdoog Nov 4, 2026
1419de3
Merge the GraphId doc comment changes
Archdoog Nov 4, 2026
ec4ccc9
Reword the comments of the extract writer
Archdoog Nov 4, 2026
29fa767
Merge the comment changes
Archdoog Nov 4, 2026
01a4ae8
Merge the comment changes
Archdoog Nov 4, 2026
9487e6d
Reword the comments of the integration harness
Archdoog Nov 4, 2026
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
50 changes: 50 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Integration tests of offline extracts with C++ Valhalla. See scripts/integration/README.md.
name: Integration

on:
pull_request:
branches: [ "main" ]
paths:
- "valhalla-graphtile/src/extract/**"
# The tar layout and the index.bin code are in the tile providers.
- "valhalla-graphtile/src/tile_provider/**"
- "valinor-cli/**"
- "scripts/integration/**"
- ".github/workflows/integration.yml"
workflow_dispatch:

env:
CARGO_TERM_COLOR: always
# The Valhalla release under test. Without this pin, the harness uses `latest`.
# When you change it, examine the differences in the responses and logs before you merge.
VALHALLA_VERSION: "3.8.2"

jobs:
integration:
# Linux only: the job tests the Docker image, not the platform.
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- uses: astral-sh/setup-uv@v10.3.0

- name: Check the harness
working-directory: scripts/integration
run: |
uv run --locked ruff check
uv run --locked ruff format --check
uv run --locked pytest

- name: Run the integration tests with C++ Valhalla
run: uv run --locked --project scripts/integration valinor-integration

- name: Upload harness artifacts on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: integration-workdir
path: |
target/integration/responses
target/integration/valhalla-*.log
target/integration/valhalla.json
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ serde = { version = "1.0.229", features = ["derive"] }
serde_with = "3.24.0"
serde_json = "1.0.154"
tar = "0.4.46"
tempfile = "3.27.0"
thiserror = "2.0.21"
tokio = { version = "1.54.1", features = ["macros", "rt-multi-thread", "fs", "io-util", "sync"] }
tracing = "0.1.44"
Expand Down
3 changes: 3 additions & 0 deletions scripts/integration/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.venv/
__pycache__/
.pytest_cache/
94 changes: 94 additions & 0 deletions scripts/integration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Integration tests with C++ Valhalla

This harness makes sure that a sub-extract from `valinor-cli extract`
works in stock C++ Valhalla the same way as the full extract.

The harness does these steps:

1. It writes a sub-extract of the full extract with `valinor-cli extract`.
The tiles are in [`sub-extract-tiles.txt`](sub-extract-tiles.txt).
The sub-extract must be a proper subset of the full extract,
or the comparison would prove nothing.
2. It starts two `valhalla_service` containers with docker-py:
one for the full extract and one for the sub-extract.
The image's own `valhalla_build_config` makes the config.
The harness sets `mjolnir.shortcut_caching` to `false`,
because Valhalla stops at startup with a partial extract when it is `true`.
3. It sends each request of the [Bruno collection](bruno/) to both servers.
It saves each response, and it compares the two responses of each request
(see [`checks.py`](src/valinor_integration/checks.py) for the fields that it compares).
4. It makes sure that the logs of both servers contain no `[ERROR]` lines.

The default full extract is the Andorra fixture
(`valhalla-graphtile/fixtures/andorra-tiles.tar`).

## Requirements

- [uv](https://docs.astral.sh/uv/)
- Docker (Docker Desktop, colima, or a Docker daemon on Linux)
- cargo, if you do not set `VALINOR_CLI`

## Run the test

From the root of the repository:

```bash
uv run --project scripts/integration valinor-integration
```

The command prints `integration: PASS`, or a list of failures with a diff for each difference.
The work directory (`target/integration` by default) contains:

- `sub-extract.tar`: the sub-extract.
- `valhalla.json`: the Valhalla config.
- `responses/full/` and `responses/sub/`: the raw response of each request.
- `valhalla-full.log` and `valhalla-sub.log`: the logs of the two servers.

Use `--help` for the options (a different full extract, work directory, tile list, or collection).

## Send requests by hand with Bruno

```bash
uv run --project scripts/integration valinor-integration serve
```

This serves the full extract at `http://localhost:8002`
and the sub-extract at `http://localhost:8003` until you push Ctrl-C.
Open `scripts/integration/bruno` in [Bruno](https://www.usebruno.com/),
and select the `full` or the `sub` environment.

## Environment variables

All variables are optional.

| Variable | Default | Description |
| --- | --- | --- |
| `VALHALLA_VERSION` | `latest` | The tag of the Valhalla image, such as `3.8.2`. CI sets it in [`integration.yml`](../../.github/workflows/integration.yml). If it is not set, the harness uses `latest` and logs a warning. |
| `VALHALLA_IMAGE` | `ghcr.io/valhalla/valhalla` | The image repository. |
| `VALINOR_CLI` | (none) | The path of a `valinor-cli` binary. If it is not set, the harness runs `cargo run --release -p valinor-cli`. |
| `VALHALLA_PORT` | `8002` | The port of the full extract in `serve` mode. The sub-extract uses the next port. If you change it, change the Bruno environments too. |

## Add a request

1. Add the request to the Bruno collection.
You can do this in the Bruno app, or you can copy a file in `bruno/route/`.
Keep all coordinates far inside the tiles of the sub-extract,
so that the request never needs a tile which the sub-extract does not contain.
2. If the request uses a new endpoint, add a check for the endpoint to
[`checks.py`](src/valinor_integration/checks.py).
The harness refuses a request for an endpoint that has no check.

The harness reads a subset of the Bruno YAML format:
the method, the URL (with `{{baseUrl}}`), headers, and a JSON body.
It refuses requests with Bruno scripts or assertions,
because it does not run them; put such checks in `checks.py`.

## Unit tests of the harness

```bash
uv run --project scripts/integration pytest
```

```bash
uv run --project scripts/integration ruff check
```
4 changes: 4 additions & 0 deletions scripts/integration/bruno/environments/full.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: full
variables:
- name: baseUrl
value: http://localhost:8002
4 changes: 4 additions & 0 deletions scripts/integration/bruno/environments/sub.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: sub
variables:
- name: baseUrl
value: http://localhost:8003
28 changes: 28 additions & 0 deletions scripts/integration/bruno/locate/andorra-la-vella-center.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
info:
name: andorra-la-vella-center
type: http
seq: 1

http:
method: POST
url: "{{baseUrl}}/locate"
body:
type: json
data: |-
{
"locations": [
{
"lat": 42.5063,
"lon": 1.5218
}
],
"costing": "auto",
"verbose": true
}
auth: inherit

settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
8 changes: 8 additions & 0 deletions scripts/integration/bruno/locate/folder.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
info:
name: locate
type: folder
seq: 2

request:
auth: inherit

10 changes: 10 additions & 0 deletions scripts/integration/bruno/opencollection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
opencollection: 1.0.0

info:
name: Valinor integration
bundled: false
extensions:
bruno:
ignore:
- node_modules
- .git
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
info:
name: andorra-la-vella-center-pedestrian
type: http
seq: 5

http:
method: POST
url: "{{baseUrl}}/route"
body:
type: json
data: |-
{
"locations": [
{
"lat": 42.5063,
"lon": 1.5218
},
{
"lat": 42.5103,
"lon": 1.5336
}
],
"costing": "pedestrian",
"units": "kilometers"
}
auth: inherit

settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
info:
name: andorra-la-vella-to-encamp-auto
type: http
seq: 1

http:
method: POST
url: "{{baseUrl}}/route"
body:
type: json
data: |-
{
"locations": [
{
"lat": 42.5063,
"lon": 1.5218
},
{
"lat": 42.536,
"lon": 1.5836
}
],
"costing": "auto",
"units": "kilometers"
}
auth: inherit

settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
info:
name: andorra-la-vella-to-la-massana-auto
type: http
seq: 2

http:
method: POST
url: "{{baseUrl}}/route"
body:
type: json
data: |-
{
"locations": [
{
"lat": 42.5078,
"lon": 1.5211
},
{
"lat": 42.5449,
"lon": 1.5148
}
],
"costing": "auto",
"units": "kilometers"
}
auth: inherit

settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
32 changes: 32 additions & 0 deletions scripts/integration/bruno/route/encamp-to-canillo-auto.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
info:
name: encamp-to-canillo-auto
type: http
seq: 3

http:
method: POST
url: "{{baseUrl}}/route"
body:
type: json
data: |-
{
"locations": [
{
"lat": 42.536,
"lon": 1.5836
},
{
"lat": 42.5676,
"lon": 1.5976
}
],
"costing": "auto",
"units": "kilometers"
}
auth: inherit

settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
8 changes: 8 additions & 0 deletions scripts/integration/bruno/route/folder.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
info:
name: route
type: folder
seq: 1

request:
auth: inherit

Loading
Loading