Files
astro/basic/star_catalog_format_test.go
T

161 lines
4.4 KiB
Go
Raw Normal View History

package basic
import (
"bytes"
"compress/gzip"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"io"
"math"
"os"
"strings"
"testing"
)
// starCatalogDigestWant 解码后星表的摘要,锁定逐位一致。
const starCatalogDigestWant = "3c3455cdb09e1e46c5d513a6c26743c6fd1753f65754888f97ec585324af39e4"
func starCatalogDigest(stars []StarData) string {
hash := sha256.New()
var buf [8]byte
writeUint := func(v uint64) {
binary.LittleEndian.PutUint64(buf[:], v)
hash.Write(buf[:])
}
writeString := func(s string) {
writeUint(uint64(len(s)))
hash.Write([]byte(s))
}
writeUint(uint64(len(stars)))
for _, star := range stars {
writeUint(uint64(star.HR))
writeUint(uint64(star.HD))
writeUint(uint64(star.HIP))
writeString(star.Name)
for _, v := range []float64{star.Ra, star.Dec, star.Mag, star.PmRA, star.PmDec, star.RadVel, star.RotVel, star.Pc} {
writeUint(math.Float64bits(v))
}
for _, s := range []string{star.ChineseName, star.ChineseAlias, star.ChineseRegion, star.ChineseBayerName,
star.CommonName, star.CommonAliasName, star.Cst, star.CstChinese} {
writeString(s)
}
}
return hex.EncodeToString(hash.Sum(nil))
}
func TestStarCatalogDigestStable(t *testing.T) {
if err := LoadStarData(); err != nil {
t.Fatal(err)
}
if got := starCatalogDigest(cachedStarData); got != starCatalogDigestWant {
t.Fatalf("star catalog digest = %s, want %s", got, starCatalogDigestWant)
}
}
func TestStarCatalogNamesGzipMatchesSource(t *testing.T) {
source, err := os.ReadFile("star_catalog_names.tsv")
if err != nil {
t.Fatal(err)
}
reader, err := gzip.NewReader(bytes.NewReader(starCatalogNamesCompressed))
if err != nil {
t.Fatal(err)
}
decompressed, err := io.ReadAll(reader)
reader.Close()
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(source, decompressed) {
t.Fatal("star_catalog_names.tsv.gz is stale; regenerate it from star_catalog_names.tsv")
}
}
// starNameLegacyCorrections 旧 .dat 详情与单一表的已知差异;新增名称不在其中。
var starNameLegacyCorrections = map[uint16]map[string]bool{
390: {"bayer": true, "chinese": true, "cst": true, "cstzh": true},
565: {"chinese": true},
585: {"chinese": true},
1140: {"bayer": true, "chinese": true, "cst": true, "cstzh": true},
1151: {"bayer": true, "chinese": true},
1180: {"bayer": true, "chinese": true},
1324: {"chinese": true},
1387: {"chinese": true},
1412: {"chinese": true},
1656: {"chinese": true},
2585: {"bayer": true, "cst": true, "cstzh": true},
2590: {"chinese": true},
2714: {"chinese": true},
2878: {"chinese": true},
3314: {"chinese": true},
5226: {"chinese": true},
5396: {"chinese": true},
5533: {"bayer": true, "chinese": true, "cst": true, "cstzh": true},
6008: {"bayer": true, "chinese": true, "cst": true, "cstzh": true},
6554: {"chinese": true},
6636: {"chinese": true},
7735: {"chinese": true},
8313: {"chinese": true},
8556: {"chinese": true},
8610: {"bayer": true, "chinese": true, "cst": true, "cstzh": true},
8982: {"chinese": true},
}
func TestStarCatalogNameTableMatchesLegacyDetails(t *testing.T) {
if err := LoadStarData(); err != nil {
t.Fatal(err)
}
for hr, rec := range hr2name {
for field, value := range map[string]string{
"chinese": rec.chinese,
"aliases": strings.Join(rec.aliases, ";"),
"region": rec.region,
} {
if strings.ContainsAny(value, "[]") {
t.Fatalf("HR %d %s has bracket qualifier %q; use the region column", hr, field, value)
}
}
}
reader, err := gzip.NewReader(bytes.NewReader(starCatalogCompressed))
if err != nil {
t.Fatal(err)
}
payload, err := io.ReadAll(reader)
reader.Close()
if err != nil {
t.Fatal(err)
}
_, detail, _, err := decodeStarCatalogPayload(payload, true)
if err != nil {
t.Fatal(err)
}
for hr, info := range detail {
rec, ok := hr2name[hr]
if !ok {
t.Fatalf("HR %d has legacy details but no row in star_catalog_names.tsv", hr)
}
checks := []struct {
field string
old string
new string
}{
{"chinese", info[0], rec.chinese},
{"aliases", info[1], strings.Join(rec.aliases, ";")},
{"bayer", info[2], rec.bayerZH},
{"common", info[3], rec.common},
{"cstzh", info[4], rec.cstZH},
{"cst", info[5], rec.cst},
}
for _, check := range checks {
if check.old == "" || check.old == check.new {
continue
}
if starNameLegacyCorrections[hr][check.field] {
continue
}
t.Fatalf("HR %d %s: legacy %q, table %q", hr, check.field, check.old, check.new)
}
}
}