102 lines
2.8 KiB
Go
102 lines
2.8 KiB
Go
package landscape
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"gis/internal/raster"
|
|
)
|
|
|
|
func grid(w, h int) raster.Grid {
|
|
return raster.Grid{Width: w, Height: h, GeoTransform: [6]float64{0, 30, 0, 0, 0, -30}, ProjectionWKT: "EPSG:32642"}
|
|
}
|
|
|
|
func constRaster(w, h int, v float64) []float64 {
|
|
d := make([]float64, w*h)
|
|
for i := range d {
|
|
d[i] = v
|
|
}
|
|
return d
|
|
}
|
|
|
|
func TestCompute_E_TilesWindowsAndWritesEveryPixel(t *testing.T) {
|
|
fio := newFakeIO()
|
|
g := grid(10, 7)
|
|
z := constRaster(10, 7, 2)
|
|
u := constRaster(10, 7, 4)
|
|
z[0] = -9999 // pixel 0 invalid
|
|
fio.put("z.tif", g, z)
|
|
fio.put("u.tif", g, u)
|
|
node, _ := NodeByCode("10")
|
|
p := DefaultParams()
|
|
p.WindowSize = 4 // forces partial windows (10x7 with 4x4 tiles)
|
|
out, err := Compute(context.Background(), fio, node, map[string]string{OutZIntegrated: "z.tif", OutUIntegrated: "u.tif"}, "/out", p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
path := out[OutE]
|
|
if path != filepath.Join("/out", OutE+".tif") {
|
|
t.Fatalf("unexpected output path %q", path)
|
|
}
|
|
res := fio.files[path]
|
|
if res.grid != g {
|
|
t.Fatal("output grid must copy the first input's grid")
|
|
}
|
|
for i, v := range res.data {
|
|
want := 4.0
|
|
if i == 0 {
|
|
want = -9999
|
|
}
|
|
if v != want {
|
|
t.Fatalf("pixel %d = %v want %v", i, v, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCompute_FailsOnGridMismatch(t *testing.T) {
|
|
fio := newFakeIO()
|
|
fio.put("z.tif", grid(10, 7), constRaster(10, 7, 2))
|
|
fio.put("u.tif", grid(9, 7), constRaster(9, 7, 4))
|
|
node, _ := NodeByCode("10")
|
|
_, err := Compute(context.Background(), fio, node, map[string]string{OutZIntegrated: "z.tif", OutUIntegrated: "u.tif"}, "/out", DefaultParams())
|
|
if err == nil {
|
|
t.Fatal("expected grid mismatch error")
|
|
}
|
|
if _, created := fio.files[filepath.Join("/out", OutE+".tif")]; created {
|
|
t.Fatal("no output must be created on mismatch")
|
|
}
|
|
}
|
|
|
|
func TestCompute_FailsOnMissingInput(t *testing.T) {
|
|
fio := newFakeIO()
|
|
fio.put("z.tif", grid(2, 2), constRaster(2, 2, 2))
|
|
node, _ := NodeByCode("10")
|
|
if _, err := Compute(context.Background(), fio, node, map[string]string{OutZIntegrated: "z.tif"}, "/out", DefaultParams()); err == nil {
|
|
t.Fatal("expected error for missing input group")
|
|
}
|
|
}
|
|
|
|
func TestCompute_MultiOutputNode(t *testing.T) {
|
|
fio := newFakeIO()
|
|
g := grid(3, 1)
|
|
paths := map[string]string{}
|
|
for i, s := range []string{SlotPIrrigation, SlotPSnow, SlotPCrop, SlotPPasture, SlotPTourism} {
|
|
paths[s] = s + ".tif"
|
|
fio.put(paths[s], g, constRaster(3, 1, float64(i+1)))
|
|
}
|
|
paths[OutE] = "e.tif"
|
|
fio.put("e.tif", g, constRaster(3, 1, 3))
|
|
node, _ := NodeByCode("20")
|
|
out, err := Compute(context.Background(), fio, node, paths, "/o", DefaultParams())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(out) != 5 {
|
|
t.Fatalf("want 5 outputs, got %d", len(out))
|
|
}
|
|
if fio.files[out[OutCTourism]].data[0] != 3 || fio.files[out[OutCIrrigation]].data[0] != 1 {
|
|
t.Fatal("min(P, E) not applied per output")
|
|
}
|
|
}
|