1package lineup_test23import (4 "encoding/json"5 "slices"6 "strings"7 "testing"89 "airwaves/internal/lineup"10 "airwaves/internal/lineup/lineuptest"11)1213// found is part of what the tuner's scan found around Denver.14var found = []lineup.Scanned{15 {Number: "20.1", Name: "KTVD-HD", RF: 31},16 {Number: "20.2", Name: "H & I", RF: 31},17 {Number: "9.4", Name: "KUSA-HD", RF: 31},18 {Number: "9.7", Name: "TBD", RF: 31},19 {Number: "31.1", Name: "KDVR-DT", RF: 36},20 {Number: "2.1", Name: "KWGN-DT", RF: 36},21 {Number: "6.1", Name: "KRMADT1", RF: 33},22 {Number: "14.1", Name: "Univision Denver", RF: 32},23 {Number: "88.1", Name: "Mystery", RF: 0},24}2526// TestMatch describes the tuner's channels from the records, and never27// adds one: KMGH 7.1 and KUSA 9.1 are listed and licensed, but the tuner28// didn't find them.29func TestMatch(t *testing.T) {30 chans := lineup.Match(lineuptest.Report(), lineuptest.Guide(), found)31 var numbers []string32 by := map[string]lineup.TunerChannel{}33 for _, c := range chans {34 numbers = append(numbers, c.Number)35 by[c.Number] = c36 }37 if want := []string{"2.1", "6.1", "9.4", "9.7", "14.1", "20.1", "20.2", "31.1", "88.1"}; !slices.Equal(numbers, want) {38 t.Fatalf("channels %v, want %v", numbers, want)39 }40 // The call sign shown is the station's, the same for its subchannels;41 // the listings' own ("KUSADT4") is kept apart.42 check := func(number, call, guideCall, tx, via, guideID string, rf int) {43 t.Helper()44 c := by[number]45 if c.CallSign != call || c.BaseCall != call || c.GuideCallSign != guideCall || c.Transmitter != tx || c.Via != via || c.GuideID != guideID || c.RF != rf {46 t.Errorf("%s = %+v", number, c)47 }48 }49 // From the listings, on its own transmitter (not the nearer50 // low-power one on the same RF channel).51 check("20.1", "KTVD", "KTVDDT", "KTVD", "", "g20", 31)52 // Not listed: the transmitter's own virtual channel.53 check("20.2", "KTVD", "", "KTVD", "", "", 31)54 // KUSA's subchannels ride KTVD's transmitter.55 check("9.4", "KUSA", "KUSADT4", "KTVD", "KTVD", "g94", 31)56 check("9.7", "KUSA", "", "KTVD", "KTVD", "", 31)57 // KWGN's ATSC 1.0 signal is on KDVR's transmitter; it broadcasts in58 // ATSC 3.0 itself.59 check("2.1", "KWGN", "KWGNDT", "KDVR", "KDVR", "g2", 36)60 check("6.1", "KRMA", "KRMADT", "KRMA-TV", "", "g6", 33)61 check("14.1", "KCEC", "KCECDT", "KCEC", "", "g14", 32)62 // Nothing on record, and a name that isn't a call sign: the name.63 if c := by["88.1"]; c.CallSign != "Mystery" || c.BaseCall != "" || c.Transmitter != "" || c.GuideID != "" {64 t.Errorf("88.1 = %+v", c)65 }66 if c := by["20.2"]; c.Name != "H & I" || c.Network != "" {67 t.Errorf("20.2 = %+v", c)68 }69 if c := by["2.1"]; c.NextGen == nil || c.NextGen.HostCall != "KWGN-TV" || c.NextGen.RF != "34" || c.Network != "CW" || c.Name != "KWGN-DT" {70 t.Errorf("2.1 = %+v, %+v", c, c.NextGen)71 }72 if c := by["31.1"]; c.NextGen == nil || c.NextGen.HostCall != "KWGN-TV" || c.FacilityID != 126 {73 t.Errorf("31.1 = %+v", c)74 }75 if c := by["20.1"]; c.NextGen != nil {76 t.Errorf("20.1 in ATSC 3.0: %+v", c.NextGen)77 }7879 // Without listings or records: every channel still, as broadcast.80 bare := lineup.Match(&lineup.Report{}, nil, found)81 if len(bare) != len(found) || bare[0].Number != "2.1" || bare[0].CallSign != "KWGN" || bare[0].Transmitter != "" ||82 bare[6].Number != "20.2" || bare[6].CallSign != "H & I" || bare[6].BaseCall != "" {83 t.Errorf("bare = %+v", bare)84 }85}8687// TestForTuner: the app's report is the records without estimates, its88// stations carrying what the tuner receives from them.89func TestForTuner(t *testing.T) {90 rep := lineuptest.Report()91 rep.Presets = nil92 chans := lineup.Match(rep, lineuptest.Guide(), found)93 out := lineup.ForTuner(rep, chans)94 carries := map[string][]string{}95 for _, s := range out.Stations {96 carries[s.CallSign] = s.Carries97 if s.Signal != nil {98 t.Errorf("%s signal %v", s.CallSign, s.Signal)99 }100 }101 if got := carries["KTVD"]; !slices.Equal(got, []string{"9.4", "9.7", "20.1", "20.2"}) {102 t.Errorf("KTVD carries %v", got)103 }104 if got := carries["KWGN-TV"]; !slices.Equal(got, []string{"2.1 (3.0)", "31.1 (3.0)", "4.1 (3.0)"}) {105 t.Errorf("KWGN-TV carries %v", got)106 }107 if got := carries["KMGH-TV"]; got == nil || len(got) != 0 {108 t.Errorf("KMGH-TV carries %v", got)109 }110 if out.Stations[0].CallSign != "K31AB-D" || len(out.Channels) != 0 || len(rep.Stations[5].Carries) != 0 {111 t.Errorf("stations not nearest first, or the report changed: %+v", out.Stations[0])112 }113 raw, _ := json.Marshal(out)114 for _, bad := range []string{"noiseMarginDb", "tier", `"presets"`, `"signal"`} {115 if strings.Contains(string(raw), bad) {116 t.Errorf("report has %s", bad)117 }118 }119}