package adif_test import ( "context" "os" "path/filepath" "strings" "testing" "hamlog/internal/adif" "hamlog/internal/db" "hamlog/internal/qso" ) // End to end: an operator's own record, through a real SQLite logbook and back. // // Written because CONTEST_ID was reported as "not imported". It is imported, and // this pins the whole path — parse, remap, insert, read back — rather than the // conversion step alone, which was already green while the report stood. A field // can be lost at five places between the file and the grid; only the round trip // says which. func TestContestIDSurvivesImport(t *testing.T) { dir := t.TempDir() conn, err := db.Open(filepath.Join(dir, "logbook.db")) if err != nil { t.Fatalf("open: %v", err) } defer conn.Close() const file = "2E0CVN 20260725 120039 EU005 20M 14.014 CW RSGB-IOTA 599 599 001EU005 \n" path := filepath.Join(dir, "in.adi") if err := os.WriteFile(path, []byte(file), 0o644); err != nil { t.Fatal(err) } repo := qso.NewRepo(conn) im := &adif.Importer{Repo: repo, FieldMap: map[string]string{"state": "iota"}} res, err := im.ImportFile(context.Background(), path) if err != nil { t.Fatalf("import: %v", err) } t.Logf("result: %+v", res) rows, err := conn.Query("SELECT callsign, contest_id, iota, state FROM qso") if err != nil { t.Fatal(err) } defer rows.Close() n := 0 for rows.Next() { var call, contest, iota, state any if err := rows.Scan(&call, &contest, &iota, &state); err != nil { t.Fatal(err) } n++ t.Logf("stored: call=%v contest_id=%v iota=%v state=%v", call, contest, iota, state) if s := strings.TrimSpace(toS(contest)); s != "RSGB-IOTA" { t.Errorf("contest_id in the DATABASE = %q, want RSGB-IOTA", s) } } if n == 0 { t.Fatal("nothing was stored") } } func toS(v any) string { switch x := v.(type) { case string: return x case []byte: return string(x) } return "" }