Files
astro/geojson/solar_eclipse_options_test.go
T
b612 16c62a97d5 feat: 完善时标与天象几何计算并扩展输出接口
- 新增时标、ΔT 模型、质心时间与 UT1 支持
- 改进日月食、月掩、行星事件及路径边界计算
- 完善恒星三维自行与动态距离传播
- 扩展 SVG、GeoJSON、KML 输出与底层距离换算工具
- 整理中英文手册、示例资源及回归测试
2026-09-23 18:55:12 +08:00

122 lines
3.9 KiB
Go

package geojson_test
import (
"bytes"
"reflect"
"sort"
"testing"
"time"
"b612.me/astro/eclipse"
"b612.me/astro/geojson"
)
// 契约:SolarEclipseOptions.SkipRoles 只裁掉列出的 role、默认输出不变、全部裁光时报错;TimeMarkers 与旧入口等价。
func solarEclipseOptionsFixture(t *testing.T) (eclipse.SolarEclipsePartialFootprintsInfo, eclipse.SolarEclipsePath) {
t.Helper()
date := time.Date(2024, time.April, 8, 0, 0, 0, 0, time.UTC)
partial, ok := eclipse.SolarEclipsePartialFootprints(date, eclipse.SolarEclipsePartialFootprintOptions{
Step: 10 * time.Minute, BoundaryPoints: 24,
})
if !ok {
t.Fatal("expected the 2024-04-08 partial phase")
}
central, ok := eclipse.SolarEclipseCentralPath(date, eclipse.SolarEclipsePathOptions{
Step: time.Minute, TargetSpacingKM: 500,
})
if !ok {
t.Fatal("expected the 2024-04-08 central path")
}
return partial, central
}
func solarRoleCounts(collection decodedCollection) map[string]int {
counts := map[string]int{}
for _, feature := range collection.Features {
role, _ := feature.Properties["role"].(string)
counts[role]++
}
return counts
}
func TestMarshalSolarEclipseSkipRoles(t *testing.T) {
partial, central := solarEclipseOptionsFixture(t)
baseline, err := geojson.MarshalSolarEclipseWithOptions(partial, &central, geojson.SolarEclipseOptions{})
if err != nil {
t.Fatalf("MarshalSolarEclipseWithOptions: %v", err)
}
legacy, err := geojson.MarshalSolarEclipse(partial, &central)
if err != nil {
t.Fatalf("MarshalSolarEclipse: %v", err)
}
if !bytes.Equal(baseline, legacy) {
t.Fatal("零值 SolarEclipseOptions 应等价于 MarshalSolarEclipse")
}
full := solarRoleCounts(decodeCollection(t, baseline))
if full["partial-footprint"] == 0 {
t.Fatalf("默认输出应含瞬时半影轮廓:%v", full)
}
skip := []string{"partial-footprint", "partial-band"}
data, err := geojson.MarshalSolarEclipseWithOptions(partial, &central, geojson.SolarEclipseOptions{SkipRoles: skip})
if err != nil {
t.Fatalf("MarshalSolarEclipseWithOptions: %v", err)
}
filtered := solarRoleCounts(decodeCollection(t, data))
want := map[string]int{}
for role, count := range full {
want[role] = count
}
for _, role := range skip {
if filtered[role] != 0 {
t.Fatalf("被跳过的 %s 仍输出 %d 个", role, filtered[role])
}
delete(want, role)
}
if !reflect.DeepEqual(filtered, want) {
t.Fatalf("跳过 %v 后其余图层被改动:got %v want %v", skip, filtered, want)
}
all := make([]string, 0, len(full))
for role := range full {
all = append(all, role)
}
sort.Strings(all)
if _, err := geojson.MarshalSolarEclipseWithOptions(partial, nil, geojson.SolarEclipseOptions{SkipRoles: all}); err == nil {
t.Fatal("全部 role 都跳过时应返回错误")
}
}
func TestMarshalSolarEclipseOptionsTimeMarkers(t *testing.T) {
partial, central := solarEclipseOptionsFixture(t)
markers := geojson.TimeMarkerOptions{Step: 30 * time.Minute}
legacy, err := geojson.MarshalSolarEclipseWithTimeMarkers(partial, &central, markers)
if err != nil {
t.Fatalf("MarshalSolarEclipseWithTimeMarkers: %v", err)
}
current, err := geojson.MarshalSolarEclipseWithOptions(partial, &central, geojson.SolarEclipseOptions{TimeMarkers: &markers})
if err != nil {
t.Fatalf("MarshalSolarEclipseWithOptions: %v", err)
}
if !bytes.Equal(legacy, current) {
t.Fatal("TimeMarkers 字段与 MarshalSolarEclipseWithTimeMarkers 不等价")
}
both, err := geojson.MarshalSolarEclipseWithOptions(partial, &central, geojson.SolarEclipseOptions{
TimeMarkers: &markers,
SkipRoles: []string{"partial-footprint"},
})
if err != nil {
t.Fatalf("MarshalSolarEclipseWithOptions: %v", err)
}
counts := solarRoleCounts(decodeCollection(t, both))
if counts["time-marker"] == 0 {
t.Fatalf("时间标记被误删:%v", counts)
}
if counts["partial-footprint"] != 0 {
t.Fatalf("瞬时半影轮廓未丢弃:%v", counts)
}
}