package config import ( "os" "path/filepath" "reflect" "strings" "testing" ) const sample = `# probe config probe_id: ca-qc-01 key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" # issued by admin ingest_url: https://www.internetpressure.io/ingest/v1/ data_dir: /tmp/ip-probe-test listen: 127.0.0.1:9381 log_level: debug allow_self_update: false resolvers_override: - system - google=8.8.8.8:53 - 1.1.1.1 max_concurrency: 4 ` func TestLoadFile(t *testing.T) { dir := t.TempDir() p := filepath.Join(dir, "probe.yaml") if err := os.WriteFile(p, []byte(sample), 0o600); err != nil { t.Fatal(err) } cfg, err := Load(p, true) if err != nil { t.Fatal(err) } if cfg.ProbeID != "ca-qc-01" || cfg.LogLevel != "debug" || cfg.AllowSelfUpdate || cfg.MaxConcurrency != 4 { t.Fatalf("unexpected config: %+v", cfg) } if cfg.IngestURL != "https://www.internetpressure.io/ingest/v1" { t.Fatalf("ingest_url not normalised: %q", cfg.IngestURL) } want := []string{"system", "google=8.8.8.8:53", "1.1.1.1"} if !reflect.DeepEqual(cfg.ResolversOverride, want) { t.Fatalf("resolvers = %v", cfg.ResolversOverride) } id, addr, err := ParseResolver("1.1.1.1") if err != nil || id != "1-1-1-1" || addr != "1.1.1.1:53" { t.Fatalf("ParseResolver bare ip: %q %q %v", id, addr, err) } } func TestEnvOverrides(t *testing.T) { t.Setenv("IP_PROBE_PROBE_ID", "eu-fr-02") t.Setenv("IP_PROBE_KEY", strings.Repeat("ab", 32)) t.Setenv("IP_PROBE_RESOLVERS_OVERRIDE", "system, quad9=9.9.9.9:53") t.Setenv("IP_PROBE_ALLOW_SELF_UPDATE", "false") cfg, err := Load("", true) if err != nil { t.Fatal(err) } if cfg.ProbeID != "eu-fr-02" || cfg.AllowSelfUpdate || len(cfg.ResolversOverride) != 2 { t.Fatalf("env overrides not applied: %+v", cfg) } if cfg.DataDir != DefaultDataDir || cfg.Listen != DefaultListen { t.Fatalf("defaults lost: %+v", cfg) } } func TestValidation(t *testing.T) { cases := map[string]string{ "probe_id: BAD_ID\nkey: " + strings.Repeat("ab", 32): "probe_id", "probe_id: ok-1\nkey: nothex": "64 hex", "probe_id: ok-1\nkey: " + strings.Repeat("ab", 32) + "\nlisten: nope": "listen", "probe_id: ok-1\nkey: " + strings.Repeat("ab", 32) + "\nlog_level: loud": "log_level", "probe_id: ok-1\nkey: " + strings.Repeat("ab", 32) + "\nbogus: 1": "unknown key", } for src, want := range cases { var c = Defaults() err := c.applyYAML([]byte(src)) if err == nil { c.normalise() err = c.Validate(true) } if err == nil || !strings.Contains(err.Error(), want) { t.Errorf("%q: error %v does not mention %q", src, err, want) } } // Non-strict: missing id/key is fine (used by `once`). if _, err := Load("", false); err != nil { t.Fatal(err) } } func TestYAMLSubset(t *testing.T) { doc, err := parseYAML([]byte("a: 'x # not a comment'\nb: [1, \"two\", 3] # c\nc: []\nd:\ne: ~\n")) if err != nil { t.Fatal(err) } if doc["a"] != "x # not a comment" { t.Errorf("a = %q", doc["a"]) } if !reflect.DeepEqual(doc["b"], []string{"1", "two", "3"}) { t.Errorf("b = %v", doc["b"]) } if doc["c"] != "" || doc["d"] != "" || doc["e"] != "" { t.Errorf("empty values: %v %v %v", doc["c"], doc["d"], doc["e"]) } if _, err := parseYAML([]byte("a:\n b: 1\n")); err == nil { t.Error("nested mapping accepted") } } func TestRedacted(t *testing.T) { c := Config{Key: strings.Repeat("ab", 32)} r := c.Redacted().Key if !strings.HasPrefix(r, "abab") || !strings.HasSuffix(r, "abab") || !strings.Contains(r, "****") { t.Fatalf("redacted = %q", r) } }