func TestReaderUpdate(t *testing.T) { var reader Reader reader.options.FilterRoutes = "test-" if err := reader.init(); err != nil { panic(err) } // setup var syncGroup sync.WaitGroup for name, testSource := range testReaderSources { testSource.syncGroup = &syncGroup if err := reader.open(testSource); err != nil { t.Fatalf("reader.open %v: %v\n", name, err) } } // ensure the test terminates go func() { syncGroup.Wait() reader.stop() }() // read var readerConfig Config for config := range reader.Listen() { t.Logf("reader.Listen: tick\n") // touch it _ = pretty.Sprint(config) readerConfig = config } prettyConfig := pretty.Config{ // omit Meta node IncludeUnexported: false, } if diff := prettyConfig.Compare(testReaderConfig, readerConfig); diff != "" { t.Errorf("reader config:\n%s", diff) } }
func TestHandlers(t *testing.T) { res := fakeDNS(t) res.extResolver = exchanger.Func(func(m *dns.Msg, a string) (*dns.Msg, time.Duration, error) { rr1, err := res.formatA("google.com.", "1.1.1.1") if err != nil { return nil, 0, err } rr2, err := res.formatA("google.com.", "2.2.2.2") if err != nil { return nil, 0, err } msg := &dns.Msg{Answer: []dns.RR{rr1, rr2}} msg.SetReply(m) return msg, 0, nil }) for i, tt := range []struct { dns.HandlerFunc *dns.Msg }{ { res.HandleMesos, Message( Question("chronos.marathon.mesos.", dns.TypeA), Header(true, dns.RcodeSuccess), Answers( A(RRHeader("chronos.marathon.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.11")))), }, { // case insensitive res.HandleMesos, Message( Question("cHrOnOs.MARATHON.mesoS.", dns.TypeA), Header(true, dns.RcodeSuccess), Answers( A(RRHeader("chronos.marathon.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.11")))), }, { res.HandleMesos, Message( Question("_liquor-store._tcp.marathon.mesos.", dns.TypeSRV), Header(true, dns.RcodeSuccess), Answers( SRV(RRHeader("_liquor-store._tcp.marathon.mesos.", dns.TypeSRV, 60), "liquor-store-17700-0.marathon.mesos.", 443, 0, 0), SRV(RRHeader("_liquor-store._tcp.marathon.mesos.", dns.TypeSRV, 60), "liquor-store-7581-1.marathon.mesos.", 80, 0, 0), SRV(RRHeader("_liquor-store._tcp.marathon.mesos.", dns.TypeSRV, 60), "liquor-store-7581-1.marathon.mesos.", 443, 0, 0), SRV(RRHeader("_liquor-store._tcp.marathon.mesos.", dns.TypeSRV, 60), "liquor-store-17700-0.marathon.mesos.", 80, 0, 0)), Extras( A(RRHeader("liquor-store-17700-0.marathon.mesos.", dns.TypeA, 60), net.ParseIP("10.3.0.1")), A(RRHeader("liquor-store-17700-0.marathon.mesos.", dns.TypeA, 60), net.ParseIP("10.3.0.1")), A(RRHeader("liquor-store-7581-1.marathon.mesos.", dns.TypeA, 60), net.ParseIP("10.3.0.2")), A(RRHeader("liquor-store-7581-1.marathon.mesos.", dns.TypeA, 60), net.ParseIP("10.3.0.2")))), }, { res.HandleMesos, Message( Question("_car-store._udp.marathon.mesos.", dns.TypeSRV), Header(true, dns.RcodeSuccess), Answers( SRV(RRHeader("_car-store._udp.marathon.mesos.", dns.TypeSRV, 60), "car-store-50548-0.marathon.slave.mesos.", 31365, 0, 0), SRV(RRHeader("_car-store._udp.marathon.mesos.", dns.TypeSRV, 60), "car-store-50548-0.marathon.slave.mesos.", 31364, 0, 0)), Extras( A(RRHeader("car-store-50548-0.marathon.slave.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.11")), A(RRHeader("car-store-50548-0.marathon.slave.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.11")))), }, { res.HandleMesos, Message( Question("non-existing.mesos.", dns.TypeSOA), Header(true, dns.RcodeSuccess), NSs( SOA(RRHeader("non-existing.mesos.", dns.TypeSOA, 60), "root.ns1.mesos", "ns1.mesos", 60))), }, { res.HandleMesos, Message( Question("non-existing.mesos.", dns.TypeNS), Header(true, dns.RcodeSuccess), NSs( NS(RRHeader("non-existing.mesos.", dns.TypeNS, 60), "ns1.mesos"))), }, { res.HandleMesos, Message( Question("missing.mesos.", dns.TypeA), Header(true, dns.RcodeNameError), NSs( SOA(RRHeader("missing.mesos.", dns.TypeSOA, 60), "root.ns1.mesos", "ns1.mesos", 60))), }, { res.HandleMesos, Message( Question("chronos.marathon.mesos.", dns.TypeAAAA), Header(true, dns.RcodeSuccess), NSs( SOA(RRHeader("chronos.marathon.mesos.", dns.TypeSOA, 60), "root.ns1.mesos", "ns1.mesos", 60))), }, { res.HandleMesos, Message( Question("missing.mesos.", dns.TypeAAAA), Header(true, dns.RcodeNameError), NSs( SOA(RRHeader("missing.mesos.", dns.TypeSOA, 60), "root.ns1.mesos", "ns1.mesos", 60))), }, { res.HandleNonMesos, Message( Question("google.com.", dns.TypeA), Header(false, dns.RcodeSuccess), Answers( A(RRHeader("google.com.", dns.TypeA, 60), net.ParseIP("1.1.1.1")), A(RRHeader("google.com.", dns.TypeA, 60), net.ParseIP("2.2.2.2")))), }, } { var rw ResponseRecorder tt.HandlerFunc(&rw, tt.Msg) if got, want := rw.Msg, tt.Msg; !reflect.DeepEqual(got, want) { t.Logf("Test #%d\n%v\n", i, pretty.Sprint(tt.Msg.Question)) t.Error(pretty.Compare(got, want)) } } }
func TestMapSchemaClientToClient(t *testing.T) { tests := []struct { sc Client want client.Client wantErr bool }{ { sc: Client{ Id: "123", Secret: "sec_123", RedirectURIs: []string{ "https://client.example.com", "https://client2.example.com", }, ClientName: "Bill", LogoURI: "https://logo.example.com", ClientURI: "https://clientURI.example.com", }, want: client.Client{ Credentials: oidc.ClientCredentials{ ID: "123", Secret: "sec_123", }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ *mustParseURL(t, "https://client.example.com"), *mustParseURL(t, "https://client2.example.com"), }, ClientName: "Bill", LogoURI: mustParseURL(t, "https://logo.example.com"), ClientURI: mustParseURL(t, "https://clientURI.example.com"), }, }, }, { sc: Client{ Id: "123", Secret: "sec_123", RedirectURIs: []string{ "ht.d://p * * *", }, }, wantErr: true, }, } for i, tt := range tests { got, err := MapSchemaClientToClient(tt.sc) if tt.wantErr { if err == nil { t.Errorf("case %d: want non-nil error", i) t.Logf(pretty.Sprint(got)) } continue } if err != nil { t.Errorf("case %d: unexpected error mapping: %v", i, err) } if diff := pretty.Compare(tt.want, got); diff != "" { t.Errorf("case %d: Compare(want, got): %v", i, diff) } } }
func TestClientsFromReader(t *testing.T) { tests := []struct { json string want []Client wantErr bool }{ { json: "[]", want: []Client{}, }, { json: "[" + goodClient1 + "]", want: []Client{ { Credentials: oidc.ClientCredentials{ ID: "my_id", Secret: goodSecret1, }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ mustParseURL(t, "https://client.example.com"), }, }, }, }, }, { json: "[" + strings.Join([]string{goodClient1, goodClient2}, ",") + "]", want: []Client{ { Credentials: oidc.ClientCredentials{ ID: "my_id", Secret: goodSecret1, }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ mustParseURL(t, "https://client.example.com"), }, }, }, { Credentials: oidc.ClientCredentials{ ID: "my_other_id", Secret: goodSecret2, }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ mustParseURL(t, "https://client2.example.com"), mustParseURL(t, "https://client2_a.example.com"), }, }, }, }, }, { json: "[" + badURLClient + "]", wantErr: true, }, { json: "[" + badSecretClient + "]", wantErr: true, }, { json: "[" + noSecretClient + "]", wantErr: true, }, { json: "[" + noIDClient + "]", wantErr: true, }, } for i, tt := range tests { r := strings.NewReader(tt.json) cs, err := ClientsFromReader(r) if tt.wantErr { if err == nil { t.Errorf("case %d: want non-nil err", i) t.Logf(pretty.Sprint(cs)) } continue } if err != nil { t.Errorf("case %d: got unexpected error parsing clients: %v", i, err) t.Logf(tt.json) } if diff := pretty.Compare(tt.want, cs); diff != "" { t.Errorf("case %d: Compare(want, got): %v", i, diff) } } }
func TestClientsFromReader(t *testing.T) { tests := []struct { json string want []LoadableClient wantErr bool }{ { json: "[]", want: []LoadableClient{}, }, { json: "[" + goodClient1 + "]", want: []LoadableClient{ { Client: Client{ Credentials: oidc.ClientCredentials{ ID: "my_id", Secret: goodSecret1, }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ mustParseURL(t, "https://client.example.com"), }, }, Admin: true, }, }, }, }, { json: "[" + strings.Join([]string{goodClient1, goodClient2}, ",") + "]", want: []LoadableClient{ { Client: Client{ Credentials: oidc.ClientCredentials{ ID: "my_id", Secret: goodSecret1, }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ mustParseURL(t, "https://client.example.com"), }, }, Admin: true, }, }, { Client: Client{ Credentials: oidc.ClientCredentials{ ID: "my_other_id", Secret: goodSecret2, }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ mustParseURL(t, "https://client2.example.com"), mustParseURL(t, "https://client2_a.example.com"), }, }, }, }, }, }, { json: "[" + goodClient3 + "]", want: []LoadableClient{ { Client: Client{ Credentials: oidc.ClientCredentials{ ID: "yet_another_id", Secret: goodSecret3, }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ mustParseURL(t, "https://client3.example.com"), mustParseURL(t, "https://client3_a.example.com"), }, }, }, TrustedPeers: []string{"goodClient1", "goodClient2"}, }, }, }, { json: "[" + publicClient + "]", want: []LoadableClient{ { Client: Client{ Credentials: oidc.ClientCredentials{ ID: "public_client", Secret: goodSecret3, }, Metadata: oidc.ClientMetadata{ RedirectURIs: []url.URL{ mustParseURL(t, "http://localhost:8080"), mustParseURL(t, "urn:ietf:wg:oauth:2.0:oob"), }, }, Public: true, }, }, }, }, { json: "[" + badURLClient + "]", wantErr: true, }, { json: "[" + badSecretClient + "]", wantErr: true, }, { json: "[" + noSecretClient + "]", wantErr: true, }, { json: "[" + noIDClient + "]", wantErr: true, }, } for i, tt := range tests { r := strings.NewReader(tt.json) cs, err := ClientsFromReader(r) if tt.wantErr { if err == nil { t.Errorf("case %d: want non-nil err", i) t.Logf(pretty.Sprint(cs)) } continue } if err != nil { t.Errorf("case %d: got unexpected error parsing clients: %v", i, err) t.Logf(tt.json) } if diff := pretty.Compare(tt.want, cs); diff != "" { t.Errorf("case %d: Compare(want, got): %v", i, diff) } } }
func TestHandlers(t *testing.T) { res := fakeDNS(t) res.extResolver = func(r *dns.Msg, nameserver string, proto string, cnt int) (*dns.Msg, error) { rr1, err := res.formatA("google.com.", "1.1.1.1") if err != nil { return nil, err } rr2, err := res.formatA("google.com.", "2.2.2.2") if err != nil { return nil, err } msg := &dns.Msg{Answer: []dns.RR{rr1, rr2}} msg.SetReply(r) return msg, nil } for i, tt := range []struct { dns.HandlerFunc *dns.Msg }{ { res.HandleMesos, message( question("chronos.marathon.mesos.", dns.TypeA), header(true, dns.RcodeSuccess), answers( a(rrheader("chronos.marathon.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.11")))), }, { // case insensitive res.HandleMesos, message( question("cHrOnOs.MARATHON.mesoS.", dns.TypeA), header(true, dns.RcodeSuccess), answers( a(rrheader("chronos.marathon.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.11")))), }, { res.HandleMesos, message( question("_liquor-store._udp.marathon.mesos.", dns.TypeSRV), header(true, dns.RcodeSuccess), answers( srv(rrheader("_liquor-store._udp.marathon.mesos.", dns.TypeSRV, 60), "liquor-store-17700-0.marathon.mesos.", 31355, 0, 0), srv(rrheader("_liquor-store._udp.marathon.mesos.", dns.TypeSRV, 60), "liquor-store-17700-0.marathon.mesos.", 31354, 0, 0), srv(rrheader("_liquor-store._udp.marathon.mesos.", dns.TypeSRV, 60), "liquor-store-7581-1.marathon.mesos.", 31737, 0, 0)), extras( a(rrheader("liquor-store-17700-0.marathon.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.11")), a(rrheader("liquor-store-17700-0.marathon.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.11")), a(rrheader("liquor-store-7581-1.marathon.mesos.", dns.TypeA, 60), net.ParseIP("1.2.3.12")))), }, { res.HandleMesos, message( question("non-existing.mesos.", dns.TypeSOA), header(true, dns.RcodeSuccess), nss( soa(rrheader("non-existing.mesos.", dns.TypeSOA, 60), "root.ns1.mesos.", "ns1.mesos.", 60))), }, { res.HandleMesos, message( question("non-existing.mesos.", dns.TypeNS), header(true, dns.RcodeSuccess), nss( ns(rrheader("non-existing.mesos.", dns.TypeNS, 60), "ns1.mesos."))), }, { res.HandleMesos, message( question("missing.mesos.", dns.TypeA), header(true, dns.RcodeNameError), nss( soa(rrheader("missing.mesos.", dns.TypeSOA, 60), "root.ns1.mesos.", "ns1.mesos.", 60))), }, { res.HandleMesos, message( question("chronos.marathon.mesos.", dns.TypeAAAA), header(true, dns.RcodeSuccess), nss( soa(rrheader("chronos.marathon.mesos.", dns.TypeSOA, 60), "root.ns1.mesos.", "ns1.mesos.", 60))), }, { res.HandleMesos, message( question("missing.mesos.", dns.TypeAAAA), header(true, dns.RcodeNameError), nss( soa(rrheader("missing.mesos.", dns.TypeSOA, 60), "root.ns1.mesos.", "ns1.mesos.", 60))), }, { res.HandleNonMesos, message( question("google.com.", dns.TypeA), header(false, dns.RcodeSuccess), answers( a(rrheader("google.com.", dns.TypeA, 60), net.ParseIP("1.1.1.1")), a(rrheader("google.com.", dns.TypeA, 60), net.ParseIP("2.2.2.2")))), }, } { var rw responseRecorder tt.HandlerFunc(&rw, tt.Msg) if got, want := rw.msg, tt.Msg; !reflect.DeepEqual(got, want) { t.Logf("Test #%d\n%v\n", i, pretty.Sprint(tt.Msg.Question)) t.Error(pretty.Compare(got, want)) } } }