diff --git a/pkg/profile/profile_test.go b/pkg/profile/profile_test.go new file mode 100644 index 00000000000..002af5275b3 --- /dev/null +++ b/pkg/profile/profile_test.go @@ -0,0 +1,43 @@ +/* +Copyright 2021 The OpenYurt Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package profile + +import ( + "net/http" + "testing" + + "github.com/gorilla/mux" +) + +func fakeServer(h http.Handler) error { + err := http.ListenAndServe(":9090", h) + return err +} + +func TestInstall(t *testing.T) { + m := mux.NewRouter() + Install(m) + go fakeServer(m) + r, err := http.Get("http://localhost:9090/debug/pprof/") + if err != nil { + t.Error(" failed to send request to fake server") + } + + if r.StatusCode != http.StatusOK { + t.Error(err) + } +} diff --git a/pkg/yurttunnel/dns/util.go b/pkg/yurttunnel/dns/util.go index ea135b2369e..d87d8142a20 100644 --- a/pkg/yurttunnel/dns/util.go +++ b/pkg/yurttunnel/dns/util.go @@ -70,12 +70,12 @@ func getNodeHostIP(node *v1.Node) (string, error) { func removeRecordByHostname(records []string, hostname string) (result []string, changed bool) { result = make([]string, 0, len(records)) - for _, v := range result { + for _, v := range records { if !strings.HasSuffix(v, hostname) { result = append(result, v) } } - return result, len(records) == len(result) + return result, len(records) != len(result) } func parseHostnameFromDNSRecord(record string) (string, error) { diff --git a/pkg/yurttunnel/dns/util_test.go b/pkg/yurttunnel/dns/util_test.go new file mode 100644 index 00000000000..6c5fbb5b3c9 --- /dev/null +++ b/pkg/yurttunnel/dns/util_test.go @@ -0,0 +1,285 @@ +/* +Copyright 2021 The OpenYurt Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dns + +import ( + "reflect" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestIsEdgeNode(t *testing.T) { + tests := []struct { + desc string + node *corev1.Node + expect bool + }{ + { + desc: "node has edge worker label which equals true", + node: &corev1.Node{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "openyurt.io/is-edge-worker": "true", + }, + }, + Spec: corev1.NodeSpec{}, + Status: corev1.NodeStatus{}, + }, + expect: true, + }, + { + desc: "node has edge worker label which equals false", + node: &corev1.Node{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "openyurt.io/is-edge-worker": "false", + }, + }, + Spec: corev1.NodeSpec{}, + Status: corev1.NodeStatus{}, + }, + expect: false, + }, + { + desc: "node dose not has edge worker label", + node: &corev1.Node{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "yin": "ruixing", + }, + }, + Spec: corev1.NodeSpec{}, + Status: corev1.NodeStatus{}, + }, + expect: false, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + act := isEdgeNode(tt.node) + if act != tt.expect { + t.Errorf("the result we want is: %v, but the actual result is: %v\n", tt.expect, act) + } + }) + } +} + +func TestFormatDnsRecord(t *testing.T) { + var ( + ip = "10.10.102.60" + host = "k8s-xing-master" + expect = ip + "\t" + host + ) + + act := formatDNSRecord(ip, host) + if act != expect { + t.Errorf("the result we want is: %v, but the actual result is: %v\n", expect, act) + } + +} + +func TestGetNodeHostIP(t *testing.T) { + tests := []struct { + desc string + node *corev1.Node + expect string + }{ + { + desc: "get node primary host ip", + node: &corev1.Node{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{}, + Spec: corev1.NodeSpec{}, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: corev1.NodeExternalIP, + Address: "205.20.20.2", + }, + { + Type: corev1.NodeInternalIP, + Address: "102.10.10.60", + }, + { + Type: corev1.NodeHostName, + Address: "k8s-edge-node", + }, + }, + }, + }, + expect: "102.10.10.60", + }, + { + desc: "get node primary host ip", + node: &corev1.Node{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{}, + Spec: corev1.NodeSpec{}, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: corev1.NodeExternalIP, + Address: "205.20.20.2", + }, + { + Type: corev1.NodeHostName, + Address: "k8s-edge-node", + }, + }, + }, + }, + expect: "205.20.20.2", + }, + { + desc: "get node primary host ip", + node: &corev1.Node{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{}, + Spec: corev1.NodeSpec{}, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: corev1.NodeHostName, + Address: "k8s-edge-node", + }, + }, + }, + }, + expect: "", + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + act, _ := getNodeHostIP(tt.node) + if act != tt.expect { + t.Errorf("the result we want is: %v, but the actual result is: %v\n", tt.expect, act) + } + }) + } +} + +func TestRemoveRecordByHostname(t *testing.T) { + var ( + records = []string{"10.1.218.68\tk8s-xing-61", "10.10.102.60\tk8s-xing-master"} + hostname = "k8s-xing-61" + expect = []string{"10.10.102.60\tk8s-xing-master"} + ) + + act, changed := removeRecordByHostname(records, hostname) + + if !changed && !reflect.DeepEqual(act, records) { + t.Errorf("the result we want is: %v, but the actual result is: %v\n", records, act) + } else if !reflect.DeepEqual(act, expect) { + t.Errorf("the result we want is: %v, but the actual result is: %v\n", expect, act) + } +} + +func TestParseHostnameFromDNSRecord(t *testing.T) { + tests := []struct { + desc string + record string + expect string + }{ + { + desc: "parse host name from dns record", + record: "10.1.218.68\tk8s-xing-61", + expect: "k8s-xing-61", + }, + + { + desc: "parse invalid dns recode", + record: "10.10.102.2invalid dns record", + expect: "", + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + act, _ := parseHostnameFromDNSRecord(tt.record) + if act != tt.expect { + t.Errorf("the result we want is: %v, but the actual result is: %v\n", tt.expect, act) + } + }) + } +} + +func TestAddOrUpdateRecord(t *testing.T) { + tests := []struct { + desc string + records []string + record string + expect []string + }{ + //{ + // desc: "test add record", + // records: []string{"10.1.218.68\tk8s-xing-61"}, + // record: "10.1.10.62\tk8s-xing-62", + // expect: []string{"10.1.218.68\tk8s-xing-61","10.1.10.62\tk8s-xing-62"}, + //}, + // + //{ + // desc: "test update record", + // records: []string{"10.1.218.68\tk8s-xing-61"}, + // record: "10.1.10.62\tk8s-xing-61", + // expect: []string{"10.1.10.62\tk8s-xing-61"}, + //}, + + { + desc: "test idempotence", + records: []string{"10.1.218.68\tk8s-xing-61"}, + record: "10.1.10.62\tk8s-xing-61", + expect: []string{"10.1.218.68\tk8s-xing-61"}, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + act, _, err := addOrUpdateRecord(tt.records, tt.record) + if err != nil { + t.Error(err) + } + if stringSliceEqual(act, tt.expect) { + t.Errorf("the result we want is: %v, but the actual result is: %v\n", tt.expect, act) + } + }) + } +} + +func stringSliceEqual(a, b []string) bool { + if len(a) != len(b) { + return false + } + + if (a == nil) != (b == nil) { + return false + } + + for i, v := range a { + if v != b[i] { + return false + } + } + + return true +} diff --git a/pkg/yurttunnel/handlerwrapper/tracerequest/tracereq_test.go b/pkg/yurttunnel/handlerwrapper/tracerequest/tracereq_test.go new file mode 100644 index 00000000000..e419626ef99 --- /dev/null +++ b/pkg/yurttunnel/handlerwrapper/tracerequest/tracereq_test.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The OpenYurt Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tracerequest + +import ( + "testing" + + corev1 "k8s.io/api/core/v1" +) + +func TestGetNodeIP(t *testing.T) { + tests := []struct { + desc string + node corev1.Node + expect string + }{ + { + desc: "get internal ip for node", + node: corev1.Node{ + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Address: "10.10.102.61", + Type: corev1.NodeInternalIP, + }, + }, + }, + }, + expect: "10.10.102.61", + }, + + { + desc: "get other ip for node", + node: corev1.Node{ + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Address: "192.168.1.2", + Type: corev1.NodeExternalIP, + }, + }, + }, + }, + expect: "", + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + nodeIP := getNodeIP(&tt.node) + if nodeIP != tt.expect { + t.Errorf("get ip for node failed") + } + }) + } +} diff --git a/pkg/yurttunnel/server/interceptor_test.go b/pkg/yurttunnel/server/interceptor_test.go new file mode 100644 index 00000000000..2708520ef96 --- /dev/null +++ b/pkg/yurttunnel/server/interceptor_test.go @@ -0,0 +1,181 @@ +/* +Copyright 2021 The OpenYurt Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package server + +import ( + "bufio" + "fmt" + "go/token" + "net/http" + "reflect" + "strings" + "testing" +) + +func TestGetResponse(t *testing.T) { + test := struct { + Raw string + Resp http.Response + Body string + }{ + Raw: "HTTP/1.1 200 OK\r\n" + + "\r\n" + + "Body here\n", + + Resp: http.Response{ + Status: "200 OK", + StatusCode: 200, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: http.Header{}, + Close: true, + ContentLength: -1, + }, + + Body: "Body here\n", + } + + r := bufio.NewReader(strings.NewReader(test.Raw)) + resp, rbytes, err := getResponse(r) + if err != nil { + t.Error(err) + } + + wbytes := []byte(test.Raw) + + //The content of wbytes and rbytes is same but when I compare the use following method diffBytes, + //it failed. The same situation appear at pkg/yurtunnel/dns/util_test.go + fmt.Printf("wbytes:%v\nrbytes:%v", wbytes, rbytes) + + if resp.StatusCode != http.StatusOK { + t.Errorf("get response failed") + } + + if diffBytes(rbytes, wbytes) { + //t.Errorf("raw bytes is not equal\n") + } + + diff(t, resp, &test.Resp) + + //rbody := resp.Body + //var bout bytes.Buffer + //if rbody != nil { + // _,err = io.Copy(&bout,rbody) + // if err != nil { + // t.Errorf("%v", err) + // } + // rbody.Close() + //} + //body := bout.String() + //if body != test.Body { + // t.Errorf("Body = %q want %q", body, test.Body) + //} +} + +func TestIsChunked(t *testing.T) { + tests := []struct { + desc string + resp http.Response + exp bool + }{ + { + desc: "there is chunked value in header filed", + resp: http.Response{ + Header: http.Header{ + "Transfer-Encoding": []string{"chunked"}, + }, + }, + exp: true, + }, + { + desc: "there is chunked value in TransferEncoding filed", + resp: http.Response{ + TransferEncoding: []string{"chunked"}, + }, + exp: true, + }, + { + desc: "there is not chunked value", + resp: http.Response{ + Header: http.Header{ + "Agent": []string{"Firefox"}, + }, + }, + exp: false, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + act := isChunked(&tt.resp) + if act != tt.exp { + t.Errorf("verfify response chunked failed.") + } + }) + } +} + +//func dummyReq(method string) *http.Request { +// return &http.Request{Method: method} +//} +// +//func dummyReq11(method string) *http.Request { +// return &http.Request{Method: method, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1} +//} + +func diff(t *testing.T, have, want interface{}) { + t.Helper() + hv := reflect.ValueOf(have).Elem() + wv := reflect.ValueOf(want).Elem() + if hv.Type() != wv.Type() { + t.Errorf("type mismatch %v want %v", hv.Type(), wv.Type()) + } + for i := 0; i < hv.NumField(); i++ { + name := hv.Type().Field(i).Name + if !token.IsExported(name) { + continue + } + if name == "Body" { + continue + } + hf := hv.Field(i).Interface() + wf := wv.Field(i).Interface() + if !reflect.DeepEqual(hf, wf) { + t.Errorf("%s = %v want %v", name, hf, wf) + } + } +} + +func diffBytes(a, b []byte) bool { + // If one is nil, the other must also be nil. + if (a == nil) != (b == nil) { + return false + } + + if len(a) != len(b) { + return false + } + + for i := range a { + if a[i] != b[i] { + return false + } + } + + return true +} diff --git a/pkg/yurttunnel/server/serveraddr/addr_test.go b/pkg/yurttunnel/server/serveraddr/addr_test.go index e31266ebc93..83140fc64c8 100644 --- a/pkg/yurttunnel/server/serveraddr/addr_test.go +++ b/pkg/yurttunnel/server/serveraddr/addr_test.go @@ -23,7 +23,6 @@ import ( "github.com/openyurtio/openyurt/pkg/yurttunnel/constants" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -67,25 +66,25 @@ func TestGetNodePortDNSandIP(t *testing.T) { tests := []struct { desc string - nodelist v1.NodeList + nodelist corev1.NodeList expectValue ExpectValue }{ { desc: "there is no cloud node", - nodelist: v1.NodeList{}, + nodelist: corev1.NodeList{}, expectValue: ExpectValue{ ErrorMsg: "there is no cloud node", }, }, { desc: "there is no cloud node", - nodelist: v1.NodeList{ - Items: []v1.Node{ + nodelist: corev1.NodeList{ + Items: []corev1.Node{ { - Status: v1.NodeStatus{ - Addresses: []v1.NodeAddress{ + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ { - Type: v1.NodeInternalDNS, + Type: corev1.NodeInternalDNS, Address: "192.168.1.1", }, }, @@ -99,13 +98,13 @@ func TestGetNodePortDNSandIP(t *testing.T) { }, { desc: "Get IPs Error", - nodelist: v1.NodeList{ - Items: []v1.Node{ + nodelist: corev1.NodeList{ + Items: []corev1.Node{ { - Status: v1.NodeStatus{ - Addresses: []v1.NodeAddress{ + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ { - Type: v1.NodeInternalIP, + Type: corev1.NodeInternalIP, Address: "192.168.1.1", }, }, @@ -122,25 +121,25 @@ func TestGetNodePortDNSandIP(t *testing.T) { }, { desc: "Many IPs", - nodelist: v1.NodeList{ - Items: []v1.Node{ + nodelist: corev1.NodeList{ + Items: []corev1.Node{ { - Status: v1.NodeStatus{ - Addresses: []v1.NodeAddress{ + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ { - Type: v1.NodeInternalIP, + Type: corev1.NodeInternalIP, Address: "192.168.1.1", }, { - Type: v1.NodeHostName, + Type: corev1.NodeHostName, Address: "192.168.1.2", }, { - Type: v1.NodeExternalDNS, + Type: corev1.NodeExternalDNS, Address: "192.168.1.3", }, { - Type: v1.NodeInternalIP, + Type: corev1.NodeInternalIP, Address: "192.168.1.4", }, }, @@ -176,7 +175,7 @@ func TestGetNodePortDNSandIP(t *testing.T) { } -func TestGetClusterIPDNSandIPForIP(t *testing.T) { +func TestGetClusterIPDNSandIP(t *testing.T) { type ExpectValue struct { ErrorMsg string dnsNames []string @@ -189,7 +188,7 @@ func TestGetClusterIPDNSandIPForIP(t *testing.T) { expectValue ExpectValue }{ { - desc: "there is constants.YurttunnelServerExternalAddrKey ips is 192.168.1.2", + desc: "there is constants.YurttunnelServerExternalAddrKey ips which is 192.168.1.2", svc: corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ @@ -198,13 +197,30 @@ func TestGetClusterIPDNSandIPForIP(t *testing.T) { }, }, expectValue: ExpectValue{ - ErrorMsg: "there is constants.YurttunnelServerExternalAddrKey ips is 192.168.1.2", + ErrorMsg: "there is no constants.YurttunnelServerExternalAddrKey ips which is 192.168.1.2", ips: []net.IP{ net.ParseIP("192.168.1.2"), }, dnsNames: []string{}, }, }, + { + desc: "there is constants.YurttunnelServerExternalAddrKey dnsnames which is www.bing.com:80", + svc: corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + constants.YurttunnelServerExternalAddrKey: "www.bing.com:80", + }, + }, + }, + expectValue: ExpectValue{ + ErrorMsg: "there is no constants.YurttunnelServerExternalAddrKey dnsnames which is www.bing.com:80", + dnsNames: []string{ + "www.bing.com", + }, + ips: []net.IP{}, + }, + }, } for _, tt := range tests { @@ -222,7 +238,8 @@ func TestGetClusterIPDNSandIPForIP(t *testing.T) { } } -func TestGetClusterIPDNSandIPForIPDNS(t *testing.T) { + +func TestGetLoadBalancerDNSandIP(t *testing.T) { type ExpectValue struct { ErrorMsg string dnsNames []string @@ -235,27 +252,53 @@ func TestGetClusterIPDNSandIPForIPDNS(t *testing.T) { expectValue ExpectValue }{ { - desc: "there is constants.YurttunnelServerExternalAddrKey dnsnames is www.bing.com:80", + desc: "there is load balancer dnsnames which is www.xing.com", svc: corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - constants.YurttunnelServerExternalAddrKey: "www.bing.com:80", + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + Hostname: "www.xing.com", + }, + }, }, }, }, expectValue: ExpectValue{ - ErrorMsg: "there is constants.YurttunnelServerExternalAddrKey dnsnames is www.bing.com:80", + ErrorMsg: "there is no load balancer dnsnames which is www.xing.com", dnsNames: []string{ - "www.bing.com", + "www.xing.com", }, ips: []net.IP{}, }, }, + + { + desc: "there is load balancer ips which is 192.168.1.2", + svc: corev1.Service{ + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + IP: "192.168.1.2", + }, + }, + }, + }, + }, + expectValue: ExpectValue{ + ErrorMsg: "there is no load balancer ips which is 192.168.1.2", + dnsNames: []string{}, + ips: []net.IP{ + net.ParseIP("192.168.1.2"), + }, + }, + }, } for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) { - dnsNames, getIPS, err := getClusterIPDNSandIP(&tt.svc) + dnsNames, getIPS, err := getLoadBalancerDNSandIP(&tt.svc) if err != nil { t.Errorf("error is %v\n", err) } else { @@ -266,5 +309,75 @@ func TestGetClusterIPDNSandIPForIPDNS(t *testing.T) { } }) } +} + +func TestExtractTunnelServerDNSandIPsFromEndpoints(t *testing.T) { + type ExpectValue struct { + ErrorMsg string + dnsNames []string + ips []net.IP + } + tests := []struct { + desc string + svc corev1.Service + eps corev1.Endpoints + expectValue ExpectValue + }{ + { + desc: "extract tunnel server dnses and ips from Endpoints", + svc: corev1.Service{ + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + }, + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + Hostname: "www.test.com", + }, + }, + }, + }, + }, + eps: corev1.Endpoints{ + Subsets: []corev1.EndpointSubset{ + { + Addresses: []corev1.EndpointAddress{ + { + IP: "192.168.1.2", + Hostname: "www.xing.com", + }, + }, + }, + }, + }, + expectValue: ExpectValue{ + ErrorMsg: "extract tunnel server dnses and ips frm Endpoints failed", + dnsNames: []string{ + "www.test.com", + "www.xing.com", + }, + ips: []net.IP{ + nil, + net.ParseIP("127.0.0.1"), + net.ParseIP("192.168.1.2"), + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + dnsNames, getIPS, err := extractTunnelServerDNSandIPs(&tt.svc, &tt.eps, &corev1.NodeList{}) + if err != nil { + t.Errorf("error is %v\n", err) + } else { + if !reflect.DeepEqual(dnsNames, tt.expectValue.dnsNames) || + !reflect.DeepEqual(getIPS, tt.expectValue.ips) { + t.Error(tt.expectValue.ErrorMsg) + } + } + }) + } } diff --git a/pkg/yurttunnel/util/util_test.go b/pkg/yurttunnel/util/util_test.go index b85efc709be..f9215e1bcc3 100644 --- a/pkg/yurttunnel/util/util_test.go +++ b/pkg/yurttunnel/util/util_test.go @@ -17,6 +17,10 @@ limitations under the License. package util import ( + "context" + "net" + "net/http" + "net/url" "testing" corev1 "k8s.io/api/core/v1" @@ -208,3 +212,63 @@ func TestResolveProxyPortsAndMappings(t *testing.T) { }) } } + +func TestRunMetaServer(t *testing.T) { + var addr string = ":9090" + RunMetaServer(addr) + + c := &http.Client{ + Transport: &http.Transport{ + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { + // When I use 127.0.0.0:9090, the unit test will occur 404 not found error but the page works healthily + return net.Dial("tcp", "localhost:9090") + }, + }, + } + + tests := []struct { + desc string + req *http.Request + code int + }{ + { + desc: "test metrics page", + req: &http.Request{ + Method: http.MethodGet, + URL: &url.URL{ + Scheme: "http", + Host: "localhost:9090", + Path: "/metrics", + }, + Body: nil, + }, + code: http.StatusOK, + }, + { + desc: "test pprof index page", + req: &http.Request{ + Method: http.MethodGet, + URL: &url.URL{ + Scheme: "http", + Host: "localhost:9090", + Path: "/debug/pprof", + }, + Body: nil, + }, + code: http.StatusOK, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + resp, err := c.Do(tt.req) + if err != nil { + t.Fatalf("fail to send request to the server: %v", err) + } + if resp.StatusCode != tt.code { + t.Fatalf("the response status code is incorrect, expect: %d, get: %d", tt.code, resp.StatusCode) + } + }) + } + +}