Another thing we can test automatically, we sorta settled on using an uppercase letter in in t.Log and t.Fatal calls. Let's just check for this.
220 lines
6.4 KiB
Go
220 lines
6.4 KiB
Go
package proxy
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/coredns/coredns/plugin/pkg/healthcheck"
|
|
"github.com/coredns/coredns/plugin/pkg/tls"
|
|
"github.com/coredns/coredns/plugin/test"
|
|
"github.com/coredns/coredns/request"
|
|
|
|
"github.com/miekg/dns"
|
|
"google.golang.org/grpc/grpclog"
|
|
)
|
|
|
|
func init() {
|
|
grpclog.SetLoggerV2(discardV2{})
|
|
}
|
|
|
|
func buildPool(size int) ([]*healthcheck.UpstreamHost, func(), error) {
|
|
ups := make([]*healthcheck.UpstreamHost, size)
|
|
srvs := []*dns.Server{}
|
|
errs := []error{}
|
|
for i := 0; i < size; i++ {
|
|
srv, addr, err := test.TCPServer("localhost:0")
|
|
if err != nil {
|
|
errs = append(errs, err)
|
|
continue
|
|
}
|
|
ups[i] = &healthcheck.UpstreamHost{Name: addr}
|
|
srvs = append(srvs, srv)
|
|
}
|
|
stopIt := func() {
|
|
for _, s := range srvs {
|
|
s.Shutdown()
|
|
}
|
|
}
|
|
if len(errs) > 0 {
|
|
go stopIt()
|
|
valErr := ""
|
|
for _, e := range errs {
|
|
valErr += fmt.Sprintf("%v\n", e)
|
|
}
|
|
return nil, nil, fmt.Errorf("Error at allocation of the pool : %v", valErr)
|
|
}
|
|
return ups, stopIt, nil
|
|
}
|
|
|
|
func TestGRPCStartupShutdown(t *testing.T) {
|
|
|
|
pool, closePool, err := buildPool(2)
|
|
if err != nil {
|
|
t.Fatalf("Error creating the pool of upstream for the test : %s", err)
|
|
}
|
|
defer closePool()
|
|
|
|
upstream := &staticUpstream{
|
|
from: ".",
|
|
HealthCheck: healthcheck.HealthCheck{
|
|
Hosts: pool,
|
|
},
|
|
}
|
|
g := newGrpcClient(nil, upstream)
|
|
upstream.ex = g
|
|
|
|
p := &Proxy{}
|
|
p.Upstreams = &[]Upstream{upstream}
|
|
|
|
err = g.OnStartup(p)
|
|
if err != nil {
|
|
t.Fatalf("Error starting grpc client exchanger: %s", err)
|
|
}
|
|
if len(g.clients) != len(pool) {
|
|
t.Fatalf("Expected %d grpc clients but found %d", len(pool), len(g.clients))
|
|
}
|
|
|
|
err = g.OnShutdown(p)
|
|
if err != nil {
|
|
t.Fatalf("Error stopping grpc client exchanger: %s", err)
|
|
}
|
|
if len(g.clients) != 0 {
|
|
t.Errorf("Shutdown didn't remove clients, found %d", len(g.clients))
|
|
}
|
|
if len(g.conns) != 0 {
|
|
t.Errorf("Shutdown didn't remove conns, found %d", len(g.conns))
|
|
}
|
|
}
|
|
|
|
func TestGRPCRunAQuery(t *testing.T) {
|
|
|
|
pool, closePool, err := buildPool(2)
|
|
if err != nil {
|
|
t.Fatalf("Error creating the pool of upstream for the test : %s", err)
|
|
}
|
|
defer closePool()
|
|
|
|
upstream := &staticUpstream{
|
|
from: ".",
|
|
HealthCheck: healthcheck.HealthCheck{
|
|
Hosts: pool,
|
|
},
|
|
}
|
|
g := newGrpcClient(nil, upstream)
|
|
upstream.ex = g
|
|
|
|
p := &Proxy{}
|
|
p.Upstreams = &[]Upstream{upstream}
|
|
|
|
err = g.OnStartup(p)
|
|
if err != nil {
|
|
t.Fatalf("Error starting grpc client exchanger: %s", err)
|
|
}
|
|
// verify the client is usable, or an error is properly raised
|
|
state := request.Request{W: &test.ResponseWriter{}, Req: new(dns.Msg)}
|
|
g.Exchange(context.TODO(), "localhost:10053", state)
|
|
|
|
// verify that you have proper error if the hostname is unknwn or not registered
|
|
_, err = g.Exchange(context.TODO(), "invalid:10055", state)
|
|
if err == nil {
|
|
t.Errorf("Expecting a proper error when querying gRPC client with invalid hostname : %s", err)
|
|
}
|
|
|
|
err = g.OnShutdown(p)
|
|
if err != nil {
|
|
t.Fatalf("Error stopping grpc client exchanger: %s", err)
|
|
}
|
|
}
|
|
|
|
func TestGRPCRunAQueryOnSecureLinkWithInvalidCert(t *testing.T) {
|
|
|
|
pool, closePool, err := buildPool(1)
|
|
if err != nil {
|
|
t.Fatalf("Error creating the pool of upstream for the test : %s", err)
|
|
}
|
|
defer closePool()
|
|
|
|
upstream := &staticUpstream{
|
|
from: ".",
|
|
HealthCheck: healthcheck.HealthCheck{
|
|
Hosts: pool,
|
|
},
|
|
}
|
|
|
|
filename, rmFunc, err := test.TempFile("", aCert)
|
|
if err != nil {
|
|
t.Errorf("Error saving file : %s", err)
|
|
return
|
|
}
|
|
defer rmFunc()
|
|
|
|
tls, _ := tls.NewTLSClientConfig(filename)
|
|
// ignore error as the certificate is known valid
|
|
|
|
g := newGrpcClient(tls, upstream)
|
|
upstream.ex = g
|
|
|
|
p := &Proxy{}
|
|
p.Upstreams = &[]Upstream{upstream}
|
|
|
|
// Although dial will not work, it is not expected to have an error
|
|
err = g.OnStartup(p)
|
|
if err != nil {
|
|
t.Fatalf("Error starting grpc client exchanger: %s", err)
|
|
}
|
|
|
|
// verify that you have proper error if the hostname is unknwn or not registered
|
|
state := request.Request{W: &test.ResponseWriter{}, Req: new(dns.Msg)}
|
|
_, err = g.Exchange(context.TODO(), pool[0].Name+"-whatever", state)
|
|
if err == nil {
|
|
t.Errorf("Error in Exchange process : %s ", err)
|
|
}
|
|
|
|
err = g.OnShutdown(p)
|
|
if err != nil {
|
|
t.Fatalf("Error stopping grpc client exchanger: %s", err)
|
|
}
|
|
}
|
|
|
|
// discard is a Logger that outputs nothing.
|
|
type discardV2 struct{}
|
|
|
|
func (d discardV2) Info(args ...interface{}) {}
|
|
func (d discardV2) Infoln(args ...interface{}) {}
|
|
func (d discardV2) Infof(format string, args ...interface{}) {}
|
|
func (d discardV2) Warning(args ...interface{}) {}
|
|
func (d discardV2) Warningln(args ...interface{}) {}
|
|
func (d discardV2) Warningf(format string, args ...interface{}) {}
|
|
func (d discardV2) Error(args ...interface{}) {}
|
|
func (d discardV2) Errorln(args ...interface{}) {}
|
|
func (d discardV2) Errorf(format string, args ...interface{}) {}
|
|
func (d discardV2) Fatal(args ...interface{}) {}
|
|
func (d discardV2) Fatalln(args ...interface{}) {}
|
|
func (d discardV2) Fatalf(format string, args ...interface{}) {}
|
|
func (d discardV2) V(l int) bool { return true }
|
|
|
|
const (
|
|
aCert = `-----BEGIN CERTIFICATE-----
|
|
MIIDlDCCAnygAwIBAgIJAPaRnBJUE/FVMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
|
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
|
aWRnaXRzIFB0eSBMdGQwHhcNMTcxMTI0MTM0OTQ3WhcNMTgxMTI0MTM0OTQ3WjBF
|
|
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
|
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
|
CgKCAQEAuTDeAoWS6tdZVcp/Vh3FlagbC+9Ohi5VjRXgkpcn9JopbcF5s2jpl1v+
|
|
cRpqkrmNNKLh8qOhmgdZQdh185VNe/iZ94H42qwKZ48vvnC5hLkk3MdgUT2ewgup
|
|
vZhy/Bb1bX+buCWkQa1u8SIilECMIPZHhBP4TuBUKJWK8bBEFAeUnxB5SCkX+un4
|
|
pctRlcfg8sX/ghADnp4e//YYDqex+1wQdFqM5zWhWDZAzc5Kdkyy9r+xXNfo4s1h
|
|
fI08f6F4skz1koxG2RXOzQ7OK4YxFwT2J6V72iyzUIlRGZTbYDvair/zm1kjTF1R
|
|
B1B+XLJF9oIB4BMZbekf033ZVaQ8YwIDAQABo4GGMIGDMDMGA1UdEQQsMCqHBH8A
|
|
AAGHBDR3AQGHBDR3AQCHBDR3KmSHBDR3KGSHBDR3KmWHBDR3KtIwHQYDVR0OBBYE
|
|
FFAEccLm7D/rN3fEe1fwzH7p0spAMB8GA1UdIwQYMBaAFFAEccLm7D/rN3fEe1fw
|
|
zH7p0spAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAF4zqaucNcK2
|
|
GwYfijwbbtgMqPEvbReUEXsC65riAPjksJQ9L2YxQ7K0RIugRizuD1DNQam+FSb0
|
|
cZEMEKzvMUIexbhZNFINWXY2X9yUS/oZd5pWP0WYIhn6qhmLvzl9XpxNPVzBXYWe
|
|
duMECCigU2x5tAGmFa6g/pXXOoZCBRzFXwXiuNhSyhJEEwODjLZ6vgbySuU2jso3
|
|
va4FKFDdVM16s1/RYOK5oM48XytCMB/JoYoSJHPfpt8LpVNAQEHMvPvHwuZBON/z
|
|
q8HFtDjT4pBpB8AfuzwtUZ/zJ5atwxa5+ahcqRnK2kX2RSINfyEy43FZjLlvjcGa
|
|
UIRTUJK1JKg=
|
|
-----END CERTIFICATE-----`
|
|
)
|