package checker import ( "reflect" "testing" ) func TestDeriveView_Nil(t *testing.T) { deriveView(nil) // must not panic } func TestDeriveView_PicksMajoritySignature(t *testing.T) { key := "example.com./A" data := &ResolverPropagationData{ Resolvers: map[string]*ResolverView{ "a": mkResolver("a", "eu", false, true, map[string]*RRProbe{key: mkProbe("NOERROR", "1.1.1.1")}), "b": mkResolver("b", "global", false, true, map[string]*RRProbe{key: mkProbe("NOERROR", "1.1.1.1")}), "c": mkResolver("c", "na", false, true, map[string]*RRProbe{key: mkProbe("NOERROR", "9.9.9.9")}), }, RRsets: map[string]*RRsetView{ key: {Name: "example.com.", Type: "A"}, }, } deriveView(data) v := data.RRsets[key] if v.ConsensusSig != "1.1.1.1" { t.Errorf("consensus = %q", v.ConsensusSig) } if !reflect.DeepEqual(v.Agreeing, []string{"a", "b"}) { t.Errorf("agreeing = %v", v.Agreeing) } if !reflect.DeepEqual(v.Dissenting, []string{"c"}) { t.Errorf("dissenting = %v", v.Dissenting) } if data.Stats.UnfilteredAgreeing != 2 { t.Errorf("unfilteredAgreeing = %d", data.Stats.UnfilteredAgreeing) } } func TestDeriveView_FilteredResolverDoesNotVote(t *testing.T) { key := "example.com./A" data := &ResolverPropagationData{ Resolvers: map[string]*ResolverView{ "good": mkResolver("good", "eu", false, true, map[string]*RRProbe{key: mkProbe("NOERROR", "1.1.1.1")}), "filt": mkResolver("filt", "eu", true, true, map[string]*RRProbe{key: mkProbe("NOERROR", "0.0.0.0")}), "filt2": mkResolver("filt2", "eu", true, true, map[string]*RRProbe{key: mkProbe("NOERROR", "0.0.0.0")}), "filt3": mkResolver("filt3", "eu", true, true, map[string]*RRProbe{key: mkProbe("NOERROR", "0.0.0.0")}), }, RRsets: map[string]*RRsetView{ key: {Name: "example.com.", Type: "A"}, }, } deriveView(data) if data.RRsets[key].ConsensusSig != "1.1.1.1" { t.Errorf("filtered resolvers should not win: %q", data.RRsets[key].ConsensusSig) } } func TestDeriveView_ExpectedMatch(t *testing.T) { key := "example.com./A" data := &ResolverPropagationData{ Resolvers: map[string]*ResolverView{ "a": mkResolver("a", "eu", false, true, map[string]*RRProbe{key: mkProbe("NOERROR", "1.1.1.1")}), }, RRsets: map[string]*RRsetView{ key: {Name: "example.com.", Type: "A", Expected: "1.1.1.1"}, }, } deriveView(data) if !data.RRsets[key].MatchesExpected { t.Errorf("expected match should be true") } // Drift case. data.RRsets[key].Expected = "9.9.9.9" data.RRsets[key].MatchesExpected = false deriveView(data) if data.RRsets[key].MatchesExpected { t.Errorf("expected match should be false on drift") } } func TestDeriveView_Idempotent(t *testing.T) { key := "example.com./A" data := &ResolverPropagationData{ Resolvers: map[string]*ResolverView{ "a": mkResolver("a", "eu", false, true, map[string]*RRProbe{key: mkProbe("NOERROR", "1.1.1.1")}), "b": mkResolver("b", "eu", false, true, map[string]*RRProbe{key: mkProbe("NOERROR", "1.1.1.1")}), }, RRsets: map[string]*RRsetView{key: {Name: "example.com.", Type: "A"}}, } deriveView(data) first := *data.RRsets[key] deriveView(data) second := *data.RRsets[key] if !reflect.DeepEqual(first.Groups, second.Groups) || first.ConsensusSig != second.ConsensusSig || !reflect.DeepEqual(first.Agreeing, second.Agreeing) { t.Errorf("deriveView is not idempotent: %+v vs %+v", first, second) } } func TestDeriveView_SkipsErrorProbes(t *testing.T) { key := "example.com./A" data := &ResolverPropagationData{ Resolvers: map[string]*ResolverView{ "a": mkResolver("a", "eu", false, true, map[string]*RRProbe{key: {Error: "timeout", Transport: TransportUDP}}), "b": mkResolver("b", "eu", false, true, map[string]*RRProbe{key: mkProbe("NOERROR", "1.1.1.1")}), }, RRsets: map[string]*RRsetView{key: {Name: "example.com.", Type: "A"}}, } deriveView(data) if data.RRsets[key].ConsensusSig != "1.1.1.1" { t.Errorf("err probe shouldn't be counted: %q", data.RRsets[key].ConsensusSig) } } func TestDeriveView_DissenterDoesNotAgree(t *testing.T) { // Resolver "c" probes two RRsets and disagrees on one ⇒ should not be // counted in UnfilteredAgreeing. k1, k2 := "ex./A", "ex./MX" data := &ResolverPropagationData{ Resolvers: map[string]*ResolverView{ "a": mkResolver("a", "eu", false, true, map[string]*RRProbe{ k1: mkProbe("NOERROR", "1.1.1.1"), k2: mkProbe("NOERROR", "10 mx."), }), "b": mkResolver("b", "eu", false, true, map[string]*RRProbe{ k1: mkProbe("NOERROR", "1.1.1.1"), k2: mkProbe("NOERROR", "10 mx."), }), "c": mkResolver("c", "eu", false, true, map[string]*RRProbe{ k1: mkProbe("NOERROR", "1.1.1.1"), k2: mkProbe("NOERROR", "20 nope."), // dissents }), }, RRsets: map[string]*RRsetView{ k1: {Name: "ex.", Type: "A"}, k2: {Name: "ex.", Type: "MX"}, }, } deriveView(data) if data.Stats.UnfilteredAgreeing != 2 { t.Errorf("UnfilteredAgreeing = %d, want 2", data.Stats.UnfilteredAgreeing) } }