Make the home page's AS name search work (closes #151)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
The AS Name Search card on the home page said the search was coming
soon. It now asks the new GET /api/v1/search/as?q=<text>, which
searches the AS list built into asinfo, and lists the matches as links
to their AS pages. An empty q answers 400. asinfo.Search now ignores
case and returns its matches in AS number order.
A match can be an AS that the database does not hold yet. Its AS page
and /api/v1/as/{asn} now answer with its handle and description from
asinfo and no prefixes, instead of 404. Empty prefix lists in that JSON
answer are [] rather than null.
Model: opus-5-5
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/config"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/pkg/asinfo"
|
||||
"github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
@@ -1699,6 +1700,46 @@ func TestGetASDetailsListsEachPrefixOnce(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetASDetailsOfASNotInDatabase asks an empty database for an AS that the
|
||||
// AS info lookup knows, and gets its handle and description with no prefixes
|
||||
// and no seen times. An AS that the lookup does not know is ErrNoRoute.
|
||||
func TestGetASDetailsOfASNotInDatabase(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, err := New(&config.Config{StateDir: t.TempDir()}, logger.New())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create database: %v", err)
|
||||
}
|
||||
defer func() { _ = db.Close() }()
|
||||
|
||||
const knownASN, unknownASN = 15169, 4200000000
|
||||
|
||||
info, ok := asinfo.Get(knownASN)
|
||||
if !ok {
|
||||
t.Fatalf("AS%d is not in the AS info data", knownASN)
|
||||
}
|
||||
|
||||
got, prefixes, err := db.GetASDetails(knownASN)
|
||||
if err != nil {
|
||||
t.Fatalf("GetASDetails(%d): %v", knownASN, err)
|
||||
}
|
||||
|
||||
want := ASN{ASN: knownASN, Handle: info.Handle, Description: info.Description}
|
||||
if *got != want || len(prefixes) != 0 {
|
||||
t.Errorf("GetASDetails(%d) = %+v with prefixes %+v, want %+v and none",
|
||||
knownASN, *got, prefixes, want)
|
||||
}
|
||||
|
||||
if _, ok := asinfo.Get(unknownASN); ok {
|
||||
t.Fatalf("AS%d is in the AS info data", unknownASN)
|
||||
}
|
||||
|
||||
_, _, err = db.GetASDetails(unknownASN)
|
||||
if !errors.Is(err, ErrNoRoute) {
|
||||
t.Errorf("GetASDetails(%d): error %v, want %v", unknownASN, err, ErrNoRoute)
|
||||
}
|
||||
}
|
||||
|
||||
// TestASPrefixQueriesUseCoveringIndexes checks the plan of each query that
|
||||
// lists the prefixes an AS originates: a search of a covering index and no
|
||||
// temporary B-tree, so the list reads one index entry per prefix, not one
|
||||
|
||||
Reference in New Issue
Block a user