package main import ( "context" "strings" "testing" "github.com/kami/maven/internal/config" ) func TestWireNetScanOffUnlessEnabled(t *testing.T) { for name, cfg := range map[string]*config.Config{ "no block": {}, "written but dark": {NetScan: &config.NetScanConfig{ Subnets: []string{"192.168.1.0/24"}, }}, "enabled but nothing to scan": {NetScan: &config.NetScanConfig{Enabled: true}}, "enabled but public": {NetScan: &config.NetScanConfig{ Subnets: []string{"8.8.8.0/24"}, Enabled: true, }}, "enabled but far too wide": {NetScan: &config.NetScanConfig{ Subnets: []string{"10.0.0.0/8"}, Enabled: true, }}, } { t.Run(name, func(t *testing.T) { if w := wireNetScan(cfg); w != nil { t.Fatal("the scanner must not wire for this config") } }) } var w *netWiring if _, ok := w.scanSummary(context.Background()); ok { t.Fatal("a nil wiring must not claim a query") } ok := wireNetScan(&config.Config{NetScan: &config.NetScanConfig{ Subnets: []string{"192.168.1.0/24"}, Enabled: true, }}) if ok == nil { t.Fatal("a valid enabled block should wire") } } // A loopback /32 with nothing listening on the scanned port: the summary must // come back honest rather than inventing a host. This also exercises the real // dialer end to end without touching anything outside this box. func TestScanSummaryOnAnEmptyRange(t *testing.T) { w := wireNetScan(&config.Config{NetScan: &config.NetScanConfig{ // Port 1 on loopback: nothing listens and the connection is refused // immediately, so the scan is fast and touches only this machine. Subnets: []string{"127.0.0.1/32"}, Ports: []int{1}, Rate: 1000, Enabled: true, }}) if w == nil { t.Fatal("wireNetScan returned nil") } out, claimed := w.scanSummary(context.Background()) if !claimed { t.Fatal("the summary did not claim the turn") } if out == "" { t.Fatal("empty summary") } // Persona: feminine self-reference, informal address, no pet names. low := strings.ToLower(out) for _, bad := range []string{"нашёл", "не смог ", "вы ", "ваш", "милый", "дорогой"} { if strings.Contains(low, bad) { t.Errorf("persona violation %q in %q", bad, out) } } } func TestHostWordAgreesWithTheCount(t *testing.T) { for n, want := range map[int]string{ 1: "устройство", 2: "устройства", 4: "устройства", 5: "устройств", 11: "устройств", 12: "устройств", 21: "устройство", 22: "устройства", 25: "устройств", 111: "устройств", 101: "устройство", 0: "устройств", } { if got := hostWord(n); got != want { t.Errorf("hostWord(%d) = %q, want %q", n, got, want) } } } func TestIsNetworkQuery(t *testing.T) { yes := []string{ "какие устройства в сети?", "кто в сети?", "просканируй сеть", "покажи устройства в локальной сети", "сколько машин в сети", } no := []string{ "", "интернет не работает", "сеть какая-то медленная", "я в сети инстаграма", "что включено дома?", "напомни оплатить интернет", } for _, u := range yes { if !isNetworkQuery(u) { t.Errorf("isNetworkQuery(%q) = false, want true", u) } } for _, u := range no { if isNetworkQuery(u) { t.Errorf("isNetworkQuery(%q) = true, want false", u) } } }