Skip to content

pathfinding: dask barrier/NaN handling, degenerate shapes, and parameter branches lack test coverage #3657

Description

@brendancol

Is your feature request related to a problem? Please describe.

Test-coverage audit of xrspatial/pathfinding.py. Measured branch coverage is 86% (NUMBA_DISABLE_JIT=1, 57 tests passing). The uncovered lines sit exactly where a regression would ship without any test going red:

1. Dask backend edge handling is untested (high)

The dask path is a separate pure-Python A* implementation (_a_star_dask + _is_not_crossable_py), so the numpy tests give it no protection. Every existing dask test routes over an all-ones grid with no barriers. Uncovered as of today:

  • barrier cells (_is_not_crossable_py equality branch, neighbor rejection at line 682)
  • NaN cells (line 83) and the no-path return (line 708)
  • non-crossable start/goal warnings on dask (lines 985, 988) and the early empty return (line 629)
  • friction-blocked start (line 634)
  • numpy-backed friction with a dask surface (da.from_array promotion, line 1039)

A regression in any of these would pass the current suite. Verified against numpy behavior on this host: dask output currently matches numpy for a barrier grid and returns all-NaN for a NaN wall, so these are coverage gaps, not bugs.

2. Degenerate raster shapes untested (high)

No test exercises a 1x1, 1xN, or Nx1 raster on any backend. These shapes stress _get_pixel_id (single-element coords fall back to attrs['res']) and the kernel's neighborhood bounds checks. Spot-checked on numpy: they work today, but nothing keeps it that way.

3. Parameter and error paths untested (medium)

  • connectivity other than 4/8 (ValueError, line 938)
  • friction shape mismatch in a_star_search (line 1025)
  • friction has no positive finite values raise on numpy (1128), dask (1046), and cupy (1070)
  • search_radius combined with friction (_bounded_a_star_sub's friction slice, line 341)
  • multi_stop_search(snap=True), including the snapped-goal remap (lines 1495-1500)
  • optimize_order warning with fewer than 3 waypoints (1462), snap+dask raise (1456), waypoint length check (1440)

4. CuPy snap and search_radius untested (medium)

snap_start/snap_goal on cupy (lines 993-1003) and the cupy bounded/auto-radius branch (1083-1102) never run in the suite. CUDA is available on the dev box, so these can execute for real.

5. HPA with friction untested (medium)*

_coarsen_friction (lines 419-441) is a full numba kernel with zero coverage, reachable in production via auto-radius + manhattan distance > 1000 + a friction surface.

Low-severity gaps, documented but not fixed here: _ChunkCache eviction (579), _held_karp two-city shortcut (1209), the 2-opt improvement branch (1303-1304), non-square cellsizes, _get_pixel_id default dim arguments (40, 42).

Note: #3649 (error-handling sweep) plans to reword the dims-mismatch message and add validation for barriers/search_radius. Tests here stay off those paths to avoid churn.

Describe the solution you'd like

Add tests only, no source changes:

  • dask parity with numpy on a barrier grid; dask NaN-wall no-path; dask non-crossable start/goal warnings; dask friction-blocked start; numpy friction with dask surface
  • 1x1 / 1xN / Nx1 rasters across backends
  • the error paths and parameter combinations above
  • cupy snap and cupy search_radius parity tests (executed on the dev GPU)
  • direct _hpa_star_search test with a friction surface

Found by the test-coverage sweep on 2026-07-08.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:pathfindingArea: pathfindingbackend-coverageAdding missing dask/cupy/dask+cupy backend supportseverity:highSweep finding: HIGHtestsTest coverage and parity

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions