@@ -201,6 +201,74 @@ test_that("ngen stage detects a cycle in the fp->nexus->fp graph", {
201201 )
202202})
203203
204+ test_that(" ngen slope_valid requires strictly positive slope, all-NA is info" , {
205+ base <- data.frame (flowpath_id = c(" fp-1" , " fp-2" , " fp-3" ),
206+ flowpath_toid = " 0" , stringsAsFactors = FALSE )
207+
208+ ok_fp <- transform(base , slope = c(0.01 , 0.5 , 0.002 ))
209+ expect_true(suppressMessages(hf_check_invariants(" ngen" , flowpaths = ok_fp ,
210+ strict = FALSE ))$ checks $ slope_valid $ ok )
211+
212+ # a zero, a negative, and an NA each make it fail
213+ bad_fp <- transform(base , slope = c(0.01 , 0 , - 1 ))
214+ expect_false(suppressMessages(hf_check_invariants(" ngen" , flowpaths = bad_fp ,
215+ strict = FALSE ))$ checks $ slope_valid $ ok )
216+
217+ na_fp <- transform(base , slope = NA_real_ )
218+ res <- suppressMessages(hf_check_invariants(" ngen" , flowpaths = na_fp ,
219+ strict = FALSE ))
220+ expect_identical(res $ checks $ slope_valid $ kind , " info" )
221+
222+ # absent column -> no check emitted
223+ expect_null(suppressMessages(hf_check_invariants(" ngen" , flowpaths = base ,
224+ strict = FALSE ))$ checks $ slope_valid )
225+ })
226+
227+ test_that(" ngen So_valid checks flowpaths, flowlines, and the network table" , {
228+ fp <- data.frame (flowpath_id = c(" fp-1" , " fp-2" ), flowpath_toid = " 0" ,
229+ So = c(0.003 , 0.004 ), stringsAsFactors = FALSE )
230+ expect_true(suppressMessages(hf_check_invariants(" ngen" , flowpaths = fp ,
231+ strict = FALSE ))$ checks $ So_valid $ ok )
232+
233+ fp_bad <- transform(fp , So = c(0.003 , 0 ))
234+ expect_false(suppressMessages(hf_check_invariants(" ngen" , flowpaths = fp_bad ,
235+ strict = FALSE ))$ checks $ So_valid $ ok )
236+
237+ # So carried only on the network attribute table is still validated
238+ fp_no_so <- fp [, c(" flowpath_id" , " flowpath_toid" )]
239+ network <- data.frame (flowpath_id = c(" fp-1" , " fp-2" ), So = c(0.01 , - 1 ))
240+ expect_false(suppressMessages(hf_check_invariants(" ngen" , flowpaths = fp_no_so ,
241+ network = network , strict = FALSE ))$ checks $ So_valid $ ok )
242+ })
243+
244+ test_that(" ngen lake_spatial_consistent flags reaches far from their lake" , {
245+ skip_if_not_installed(" sf" )
246+ lakes <- sf :: st_sf(
247+ lake_id = " L1" ,
248+ geometry = sf :: st_sfc(.sq(5000 , 5000 , r = 500 ), crs = 5070 ))
249+
250+ # fp-1 sits inside the lake (distance 0); fp-2 is ~70 km away but stamped L1
251+ flowpaths <- sf :: st_sf(
252+ flowpath_id = c(" fp-1" , " fp-2" ),
253+ flowpath_toid = " 0" ,
254+ lake_id = c(" L1" , " L1" ),
255+ geometry = sf :: st_sfc(.ls(5000 , 5000 , 5200 , 5000 ),
256+ .ls(75000 , 75000 , 75200 , 75000 ), crs = 5070 ))
257+
258+ res <- suppressMessages(hf_check_invariants(" ngen" , flowpaths = flowpaths ,
259+ lakes = lakes , strict = FALSE ))
260+ expect_false(res $ checks $ lake_spatial_consistent $ ok )
261+
262+ # drop the far reach -> the remaining stamp is plausible
263+ ok <- suppressMessages(hf_check_invariants(" ngen" ,
264+ flowpaths = flowpaths [1 , ], lakes = lakes , strict = FALSE ))
265+ expect_true(ok $ checks $ lake_spatial_consistent $ ok )
266+
267+ # no lakes supplied -> check is not emitted
268+ expect_null(suppressMessages(hf_check_invariants(" ngen" ,
269+ flowpaths = flowpaths , strict = FALSE ))$ checks $ lake_spatial_consistent )
270+ })
271+
204272test_that(" hf_check_attr_bounds flags out-of-range and skips absent/zero-valid" , {
205273 df <- data.frame (
206274 smcmax_mean = c(0.4 , 0.95 , 0.2 ), # 0.95 > 0.9 -> 1 bad
0 commit comments