Files
addrkit/internal/domain/address/parse_test.go
T
Maksim Totmin 7b152c7fb3 addrkit: deterministic address resolution service (Go)
- domain: address normalization/parsing, matching with explicit statuses
- adapters: SQLite registry store, ArcGIS outages client, optional LLM rewriter, HTTP API
- seed pipeline with duplicate handling and unparsed reporting
- CLI (seed/verify/resolve), systemd unit, OpenAPI contract, tests
2026-10-09 21:40:46 +07:00

149 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package address
import "testing"
func TestParseHouseBlock(t *testing.T) {
tests := []struct {
name string
raw string
wantOrdinal string
wantName string
wantType string
wantHouse string
wantFrac string
wantLetter string
wantBuild string
wantBFrac string
wantBLetter string
wantStruct string
wantHas bool
}{
{
name: "ordinal, fraction and structure",
raw: "2-я Станционная улица 1/1 стр.",
wantOrdinal: "2", wantName: "станционная", wantType: "улица",
wantHouse: "1", wantFrac: "1", wantStruct: "", wantHas: true,
},
{
name: "building with fraction and structure",
raw: "Станционная улица 30а к9/1 стр.",
wantName: "станционная", wantType: "улица",
wantHouse: "30", wantLetter: "а", wantBuild: "9", wantBFrac: "1", wantHas: true,
},
{
name: "letter glued to house",
raw: "10-й Бронный переулок 33а",
wantOrdinal: "10", wantName: "бронный", wantType: "переулок",
wantHouse: "33", wantLetter: "а", wantHas: true,
},
{
name: "microdistrict, two-word name",
raw: "Зеленый бор микрорайон 13",
wantName: "бор зеленый", wantType: "микрорайон",
wantHouse: "13", wantHas: true,
},
{
name: "spelled-out ordinal",
raw: "вторая Станционная улица 1",
wantOrdinal: "2", wantName: "станционная", wantType: "улица",
wantHouse: "1", wantHas: true,
},
{
name: "en dash variant",
raw: "2–я Станционная улица 1",
wantOrdinal: "2", wantName: "станционная", wantType: "улица",
wantHouse: "1", wantHas: true,
},
{
name: "no house",
raw: "Станционная улица",
wantName: "станционная", wantType: "улица", wantHas: false,
},
{
name: "structure with number only",
raw: "Станционная улица 3 стр.",
wantName: "станционная", wantType: "улица",
wantHouse: "3", wantStruct: "", wantHas: true,
},
{
name: "letter before fraction",
raw: "Выборная улица 45а/4",
wantName: "выборная", wantType: "улица",
wantHouse: "45", wantLetter: "а", wantFrac: "4", wantHas: true,
},
{
name: "corpus letter without digit",
raw: "1-я Ельцовка улица 1 кД",
wantOrdinal: "1", wantName: "ельцовка", wantType: "улица",
wantHouse: "1", wantBLetter: "д", wantHas: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Parse(tt.raw)
if got.Ordinal != tt.wantOrdinal {
t.Errorf("Ordinal = %q, want %q", got.Ordinal, tt.wantOrdinal)
}
if got.NameKey != tt.wantName {
t.Errorf("NameKey = %q, want %q", got.NameKey, tt.wantName)
}
if got.StreetType != tt.wantType {
t.Errorf("StreetType = %q, want %q", got.StreetType, tt.wantType)
}
if got.House != tt.wantHouse {
t.Errorf("House = %q, want %q", got.House, tt.wantHouse)
}
if got.HouseFrac != tt.wantFrac {
t.Errorf("HouseFrac = %q, want %q", got.HouseFrac, tt.wantFrac)
}
if got.HouseLetter != tt.wantLetter {
t.Errorf("HouseLetter = %q, want %q", got.HouseLetter, tt.wantLetter)
}
if got.Building != tt.wantBuild {
t.Errorf("Building = %q, want %q", got.Building, tt.wantBuild)
}
if got.BuildingFrac != tt.wantBFrac {
t.Errorf("BuildingFrac = %q, want %q", got.BuildingFrac, tt.wantBFrac)
}
if got.BuildingLetter != tt.wantBLetter {
t.Errorf("BuildingLetter = %q, want %q", got.BuildingLetter, tt.wantBLetter)
}
if got.Structure != tt.wantStruct {
t.Errorf("Structure = %q, want %q", got.Structure, tt.wantStruct)
}
if got.HasHouse != tt.wantHas {
t.Errorf("HasHouse = %v, want %v", got.HasHouse, tt.wantHas)
}
})
}
}
// TestParseDeterministic guards the core invariant: parsing the same input
// always yields the same structured result and the same street key.
func TestParseDeterministic(t *testing.T) {
input := "2-я Станционная улица 1/1 стр."
first := Parse(input)
for i := 0; i < 100; i++ {
if got := Parse(input); got.StreetKey != first.StreetKey || got.House != first.House {
t.Fatalf("non-deterministic parse: %+v vs %+v", got, first)
}
}
}
func TestNormalizeIdempotent(t *testing.T) {
inputs := []string{
" 2-Я Станционная\u00a0улица 1/1 стр. ",
"ЁЛКИ д. 5, кв. 3",
"СТАНИЦИОННАЯ — улица, 30а",
"",
}
for _, in := range inputs {
once := NormalizeText(in)
twice := NormalizeText(once)
if once != twice {
t.Errorf("NormalizeText not idempotent for %q: %q != %q", in, once, twice)
}
}
}