mosn

Форк
0
186 строк · 4.7 Кб
1
package functiontest
2

3
import (
4
	"crypto/tls"
5
	"fmt"
6
	"io/ioutil"
7
	"net"
8
	"net/http"
9
	"strings"
10
	"testing"
11
	"time"
12

13
	"golang.org/x/net/http2"
14
	"mosn.io/mosn/pkg/protocol"
15
	_ "mosn.io/mosn/pkg/stream/http"
16
	_ "mosn.io/mosn/pkg/stream/http2"
17
	"mosn.io/mosn/pkg/types"
18
	"mosn.io/mosn/test/integrate"
19
	"mosn.io/mosn/test/util"
20
)
21

22
// check request path is match method
23
type MethodHTTPHandler struct {
24
	latency func() time.Duration
25
}
26

27
type errorWrapper struct {
28
	method   string
29
	original error
30
}
31

32
func (e errorWrapper) Error() string {
33
	return fmt.Sprintf("method:%s request error: %v", e.method, e.original)
34
}
35

36
func (e errorWrapper) Timeout() bool {
37
	err, ok := e.original.(net.Error)
38
	return ok && err.Timeout()
39
}
40

41
func (h *MethodHTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
42
	if h.latency != nil {
43
		if l := h.latency(); l > 0 {
44
			time.Sleep(l)
45
		}
46
	}
47
	m := r.Method
48
	mm := strings.Trim(r.URL.Path, "/")
49
	w.Header().Set("Content-Type", "text/plain")
50
	if m != mm {
51
		w.WriteHeader(http.StatusMethodNotAllowed)
52
	}
53
}
54

55
// http.MethodConnect is quite different from other method
56
// http.MethodHead have bugs on http2, needs to fix
57
var allMethods = []string{http.MethodDelete, http.MethodGet, http.MethodOptions, http.MethodPatch, http.MethodPost, http.MethodPut, http.MethodTrace}
58

59
type HTTPCase struct {
60
	*integrate.TestCase
61
}
62

63
func NewHTTPCase(t *testing.T, serverProto, meshProto types.ProtocolName, server util.UpstreamServer) *HTTPCase {
64
	c := integrate.NewTestCase(t, serverProto, meshProto, server)
65
	return &HTTPCase{c}
66
}
67

68
func (c *HTTPCase) RunCase(n int, interval int) {
69
	client := http.DefaultClient
70
	if c.AppProtocol == protocol.HTTP2 {
71
		tr := &http2.Transport{
72
			AllowHTTP: true,
73
			DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
74
				return net.Dial(netw, addr)
75
			},
76
		}
77
		client = &http.Client{Transport: tr}
78
	}
79
	c.runCaseWithClient(client, n, interval)
80
}
81

82
func (c *HTTPCase) runCaseWithClient(client *http.Client, n, interval int) {
83
	callHttp := func(req *http.Request) error {
84
		resp, err := client.Do(req)
85
		if err != nil {
86
			return err
87
		}
88
		defer resp.Body.Close()
89
		if resp.StatusCode != http.StatusOK {
90
			return fmt.Errorf("response status: %d", resp.StatusCode)
91
		}
92
		if _, err := ioutil.ReadAll(resp.Body); err != nil {
93
			return err
94
		}
95
		return nil
96
	}
97
	call := func() error {
98
		for _, m := range allMethods {
99
			req, err := http.NewRequest(m, fmt.Sprintf("http://%s/%s", c.ClientMeshAddr, m), nil)
100
			if err != nil {
101
				return errorWrapper{method: m, original: err}
102
			}
103
			if err := callHttp(req); err != nil {
104
				return errorWrapper{method: m, original: err}
105
			}
106
		}
107
		return nil
108
	}
109
	for i := 0; i < n; i++ {
110
		if err := call(); err != nil {
111
			c.C <- err
112
			return
113
		}
114
		time.Sleep(time.Duration(interval) * time.Millisecond)
115
	}
116
	c.C <- nil
117
}
118

119
func TestHTTPMethod(t *testing.T) {
120
	appaddr := "127.0.0.1:8080"
121
	// support non-tls/tls/proxy mode
122
	for _, f := range []func(c *HTTPCase){
123
		func(c *HTTPCase) {
124
			c.Start(false)
125
		},
126
		func(c *HTTPCase) {
127
			c.Start(true)
128
		},
129
		func(c *HTTPCase) {
130
			c.StartProxy()
131
		},
132
	} {
133
		testCases := []*HTTPCase{
134
			NewHTTPCase(t, protocol.HTTP1, protocol.HTTP1, util.NewHTTPServer(t, &MethodHTTPHandler{})),
135
			// NewHTTPCase(t, protocol.HTTP1, protocol.HTTP2, util.NewHTTPServer(t, &MethodHTTPHandler{})),
136
			NewHTTPCase(t, protocol.HTTP2, protocol.HTTP2, util.NewUpstreamHTTP2(t, appaddr, &MethodHTTPHandler{})),
137
			// NewHTTPCase(t, protocol.HTTP2, protocol.HTTP1, util.NewUpstreamHTTP2(t, appaddr, &MethodHTTPHandler{})),
138
		}
139
		for i, tc := range testCases {
140
			t.Logf("start case #%d\n", i)
141
			f(tc)
142
			go tc.RunCase(1, 0)
143
			select {
144
			case err := <-tc.C:
145
				if err != nil {
146
					t.Errorf("[ERROR MESSAGE] #%d %v to mesh %v test failed, error: %v\n", i, tc.AppProtocol, tc.MeshProtocol, err)
147
				}
148
			case <-time.After(15 * time.Second):
149
				t.Errorf("[ERROR MESSAGE] #%d %v to mesh %v hang\n", i, tc.AppProtocol, tc.MeshProtocol)
150
			}
151
			tc.FinishCase()
152
		}
153
	}
154
}
155

156
func TestHttp1DownstreamReset(t *testing.T) {
157
	handler := &MethodHTTPHandler{}
158
	c := NewHTTPCase(t, protocol.HTTP1, protocol.HTTP1, util.NewHTTPServer(t, handler))
159
	c.StartProxy()
160

161
	for i := 0; i < 2; i++ {
162
		client := http.Client{}
163
		if i == 0 {
164
			handler.latency = func() time.Duration {
165
				return time.Second
166
			}
167
			client.Timeout = time.Millisecond * 500
168
		} else {
169
			handler.latency = nil
170
		}
171
		go c.runCaseWithClient(&client, 1, 0)
172
		select {
173
		case err := <-c.C:
174
			if err != nil {
175
				if err, ok := err.(errorWrapper); ok && err.Timeout() {
176
					t.Logf("request timeout, error:%v", err)
177
				} else {
178
					t.Errorf("[ERROR MESSAGE] test failed, error: %v", err)
179
				}
180
			}
181
		case <-time.After(15 * time.Second):
182
			t.Errorf("[ERROR MESSAGE] hang\n")
183
		}
184
	}
185
	c.FinishCase()
186
}
187

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.