130 lines
5.1 KiB
Go
130 lines
5.1 KiB
Go
|
|
// 被测契约:标准气象下与原升落一致;高压低温让日出提前、日落推迟;非法气象报错。
|
||
|
|
package basic
|
||
|
|
|
||
|
|
import (
|
||
|
|
"math"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestRiseSetWithAtmosphere(t *testing.T) {
|
||
|
|
jd, lon, lat, tz := 2460676.5, 116.4, 39.9, 8.0
|
||
|
|
cases := []struct {
|
||
|
|
name string
|
||
|
|
standard func() (float64, error)
|
||
|
|
weather func(p, c float64) (float64, error)
|
||
|
|
rise bool
|
||
|
|
}{
|
||
|
|
{"sunrise", func() (float64, error) { return GetSunRiseTimeWithInstance(jd, lon, lat, tz, 1, 0, nil) },
|
||
|
|
func(p, c float64) (float64, error) {
|
||
|
|
return GetSunRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, p, c, nil)
|
||
|
|
}, true},
|
||
|
|
{"sunset", func() (float64, error) { return GetSunSetTimeWithInstance(jd, lon, lat, tz, 1, 0, nil) },
|
||
|
|
func(p, c float64) (float64, error) {
|
||
|
|
return GetSunSetTimeWithAtmosphere(jd, lon, lat, tz, 0, p, c, nil)
|
||
|
|
}, false},
|
||
|
|
{"moonrise", func() (float64, error) { return GetMoonRiseTimeWithInstance(jd, lon, lat, tz, 1, 0, nil) },
|
||
|
|
func(p, c float64) (float64, error) {
|
||
|
|
return GetMoonRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, p, c, nil)
|
||
|
|
}, true},
|
||
|
|
{"moonset", func() (float64, error) { return GetMoonSetTimeWithInstance(jd, lon, lat, tz, 1, 0, nil) },
|
||
|
|
func(p, c float64) (float64, error) {
|
||
|
|
return GetMoonSetTimeWithAtmosphere(jd, lon, lat, tz, 0, p, c, nil)
|
||
|
|
}, false},
|
||
|
|
}
|
||
|
|
for _, c := range cases {
|
||
|
|
base, err := c.standard()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("%s: %v", c.name, err)
|
||
|
|
}
|
||
|
|
same, err := c.weather(refractionStandardPressureHPa, refractionStandardTemperatureC)
|
||
|
|
if err != nil || math.Abs(same-base)*86400 > 0.01 {
|
||
|
|
t.Errorf("%s: standard weather %.6f vs %.6f (%v)", c.name, same, base, err)
|
||
|
|
}
|
||
|
|
dense, err := c.weather(1040, -30)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("%s dense: %v", c.name, err)
|
||
|
|
}
|
||
|
|
shift := (dense - base) * 86400
|
||
|
|
t.Logf("%s: 1040 hPa / -30 °C shifts %+.1f s", c.name, shift)
|
||
|
|
if c.rise && shift >= 0 || !c.rise && shift <= 0 || math.Abs(shift) > 120 {
|
||
|
|
t.Errorf("%s: implausible shift %.1f s", c.name, shift)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if _, err := GetSunRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, -1, 10, nil); err != ErrInvalidObservationInput {
|
||
|
|
t.Errorf("negative pressure: %v", err)
|
||
|
|
}
|
||
|
|
if _, err := GetSunRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, 1010, -300, nil); err != ErrInvalidObservationInput {
|
||
|
|
t.Errorf("below absolute zero: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPointRiseSetWithAtmosphere(t *testing.T) {
|
||
|
|
jd, lon, lat, tz := 2460676.5, 116.4, 39.9, 8.0
|
||
|
|
type pair struct {
|
||
|
|
name string
|
||
|
|
plain, atmos func(p, temp float64) (float64, error)
|
||
|
|
}
|
||
|
|
cases := []pair{
|
||
|
|
{"MarsRise", func(float64, float64) (float64, error) { return MarsRiseTimeWithInstance(jd, lon, lat, tz, 1, 0, nil) },
|
||
|
|
func(p, temp float64) (float64, error) {
|
||
|
|
return MarsRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, p, temp, nil)
|
||
|
|
}},
|
||
|
|
{"JupiterSet", func(float64, float64) (float64, error) {
|
||
|
|
return JupiterSetTimeWithInstance(jd, lon, lat, tz, 1, 0, nil)
|
||
|
|
},
|
||
|
|
func(p, temp float64) (float64, error) {
|
||
|
|
return JupiterSetTimeWithAtmosphere(jd, lon, lat, tz, 0, p, temp, nil)
|
||
|
|
}},
|
||
|
|
{"SiriusRise", func(float64, float64) (float64, error) {
|
||
|
|
return StarRiseTime(jd, 101.29, -16.72, lon, lat, 0, tz, true)
|
||
|
|
},
|
||
|
|
func(p, temp float64) (float64, error) {
|
||
|
|
return StarRiseTimeWithAtmosphere(jd, 101.29, -16.72, lon, lat, tz, 0, p, temp)
|
||
|
|
}},
|
||
|
|
}
|
||
|
|
for _, c := range cases {
|
||
|
|
plain, err := c.plain(0, 0)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("%s plain: %v", c.name, err)
|
||
|
|
}
|
||
|
|
std, err := c.atmos(refractionStandardPressureHPa, refractionStandardTemperatureC)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("%s standard: %v", c.name, err)
|
||
|
|
}
|
||
|
|
// 原接口用固定 34′ 地平折射,这里按公式在实际高度求折射,标准气象下差约 2–3 s。
|
||
|
|
if d := math.Abs(std-plain) * 86400; d > 5 {
|
||
|
|
t.Errorf("%s: standard weather differs from plain by %.2f s", c.name, d)
|
||
|
|
}
|
||
|
|
dense, err := c.atmos(1040, -30)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("%s dense: %v", c.name, err)
|
||
|
|
}
|
||
|
|
shift := (dense - std) * 86400
|
||
|
|
t.Logf("%s: 1040 hPa / -30 °C shifts %+.1f s", c.name, shift)
|
||
|
|
rising := c.name != "JupiterSet"
|
||
|
|
if (rising && shift >= 0) || (!rising && shift <= 0) || math.Abs(shift) > 300 {
|
||
|
|
t.Errorf("%s: implausible shift %.1f s", c.name, shift)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if _, err := MarsRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, -1, 10, nil); err == nil {
|
||
|
|
t.Error("invalid pressure must fail")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRiseSetWeatherRejectsOutOfRange(t *testing.T) {
|
||
|
|
jd, lon, lat, tz := 2460831.0, 116.4, 39.9, 8.0
|
||
|
|
for _, c := range [][2]float64{{1.01e9, 10}, {1e6, 10}, {1201, 10}, {1010, -273.14}, {1010, -101}, {1010, 81}, {math.NaN(), 10}, {1010, math.Inf(1)}} {
|
||
|
|
if _, err := GetSunRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, c[0], c[1], nil); err != ErrInvalidObservationInput {
|
||
|
|
t.Errorf("sun p=%g T=%g: err=%v", c[0], c[1], err)
|
||
|
|
}
|
||
|
|
if _, err := MercuryRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, c[0], c[1], nil); err != ErrInvalidObservationInput {
|
||
|
|
t.Errorf("mercury p=%g T=%g: err=%v", c[0], c[1], err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for _, c := range [][2]float64{{1200, 10}, {1010, -100}, {1010, 80}, {300, 10}} {
|
||
|
|
if _, err := GetSunRiseTimeWithAtmosphere(jd, lon, lat, tz, 0, c[0], c[1], nil); err != nil {
|
||
|
|
t.Errorf("sun p=%g T=%g must be accepted: %v", c[0], c[1], err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|