mirror of
https://github.com/fatedier/frp.git
synced 2026-01-11 22:23:12 +00:00
more e2e test cases (#2450)
This commit is contained in:
@@ -22,6 +22,7 @@ func NewAllocator(from int, to int, mod int, index int) *Allocator {
|
||||
reserved: sets.NewInt(),
|
||||
used: sets.NewInt(),
|
||||
}
|
||||
|
||||
for i := from; i <= to; i++ {
|
||||
if i%mod == index {
|
||||
pa.reserved.Insert(i)
|
||||
@@ -50,7 +51,7 @@ func (pa *Allocator) GetByName(portName string) int {
|
||||
pa.mu.Lock()
|
||||
defer pa.mu.Unlock()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
for i := 0; i < 20; i++ {
|
||||
port := pa.getByRange(builder.rangePortFrom, builder.rangePortTo)
|
||||
if port == 0 {
|
||||
return 0
|
||||
|
||||
@@ -13,11 +13,17 @@ type Process struct {
|
||||
stdOutput *bytes.Buffer
|
||||
|
||||
beforeStopHandler func()
|
||||
stopped bool
|
||||
}
|
||||
|
||||
func New(path string, params []string) *Process {
|
||||
return NewWithEnvs(path, params, nil)
|
||||
}
|
||||
|
||||
func NewWithEnvs(path string, params []string, envs []string) *Process {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cmd := exec.CommandContext(ctx, path, params...)
|
||||
cmd.Env = envs
|
||||
p := &Process{
|
||||
cmd: cmd,
|
||||
cancel: cancel,
|
||||
@@ -34,6 +40,12 @@ func (p *Process) Start() error {
|
||||
}
|
||||
|
||||
func (p *Process) Stop() error {
|
||||
if p.stopped {
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
p.stopped = true
|
||||
}()
|
||||
if p.beforeStopHandler != nil {
|
||||
p.beforeStopHandler()
|
||||
}
|
||||
|
||||
@@ -1,26 +1,44 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
libnet "github.com/fatedier/golib/net"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
protocol string
|
||||
addr string
|
||||
port int
|
||||
body []byte
|
||||
timeout time.Duration
|
||||
proxyURL string
|
||||
proxyHost string
|
||||
protocol string
|
||||
|
||||
// for all protocol
|
||||
addr string
|
||||
port int
|
||||
body []byte
|
||||
timeout time.Duration
|
||||
|
||||
// for http
|
||||
method string
|
||||
host string
|
||||
path string
|
||||
headers map[string]string
|
||||
|
||||
proxyURL string
|
||||
}
|
||||
|
||||
func New() *Request {
|
||||
return &Request{
|
||||
protocol: "tcp",
|
||||
addr: "127.0.0.1",
|
||||
|
||||
method: "GET",
|
||||
path: "/",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,9 +57,13 @@ func (r *Request) UDP() *Request {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Request) Proxy(url, host string) *Request {
|
||||
func (r *Request) HTTP() *Request {
|
||||
r.protocol = "http"
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Request) Proxy(url string) *Request {
|
||||
r.proxyURL = url
|
||||
r.proxyHost = host
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -55,6 +77,29 @@ func (r *Request) Port(port int) *Request {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Request) HTTPParams(method, host, path string, headers map[string]string) *Request {
|
||||
r.method = method
|
||||
r.host = host
|
||||
r.path = path
|
||||
r.headers = headers
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Request) HTTPHost(host string) *Request {
|
||||
r.host = host
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Request) HTTPPath(path string) *Request {
|
||||
r.path = path
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Request) HTTPHeaders(headers map[string]string) *Request {
|
||||
r.headers = headers
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Request) Timeout(timeout time.Duration) *Request {
|
||||
r.timeout = timeout
|
||||
return r
|
||||
@@ -65,28 +110,34 @@ func (r *Request) Body(content []byte) *Request {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Request) Do() ([]byte, error) {
|
||||
func (r *Request) Do() (*Response, error) {
|
||||
var (
|
||||
conn net.Conn
|
||||
err error
|
||||
)
|
||||
|
||||
addr := net.JoinHostPort(r.addr, strconv.Itoa(r.port))
|
||||
// for protocol http
|
||||
if r.protocol == "http" {
|
||||
return sendHTTPRequest(r.method, fmt.Sprintf("http://%s%s", addr, r.path),
|
||||
r.host, r.headers, r.proxyURL, r.body)
|
||||
}
|
||||
|
||||
// for protocol tcp and udp
|
||||
if len(r.proxyURL) > 0 {
|
||||
if r.protocol != "tcp" {
|
||||
return nil, fmt.Errorf("only tcp protocol is allowed for proxy")
|
||||
}
|
||||
conn, err = libnet.DialTcpByProxy(r.proxyURL, r.proxyHost)
|
||||
conn, err = libnet.DialTcpByProxy(r.proxyURL, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if r.addr == "" {
|
||||
r.addr = fmt.Sprintf("127.0.0.1:%d", r.port)
|
||||
}
|
||||
switch r.protocol {
|
||||
case "tcp":
|
||||
conn, err = net.Dial("tcp", r.addr)
|
||||
conn, err = net.Dial("tcp", addr)
|
||||
case "udp":
|
||||
conn, err = net.Dial("udp", r.addr)
|
||||
conn, err = net.Dial("udp", addr)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid protocol")
|
||||
}
|
||||
@@ -99,29 +150,63 @@ func (r *Request) Do() ([]byte, error) {
|
||||
if r.timeout > 0 {
|
||||
conn.SetDeadline(time.Now().Add(r.timeout))
|
||||
}
|
||||
return sendRequestByConn(conn, r.body)
|
||||
buf, err := sendRequestByConn(conn, r.body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Response{Content: buf}, nil
|
||||
}
|
||||
|
||||
func SendTCPRequest(port int, content []byte, timeout time.Duration) ([]byte, error) {
|
||||
c, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("connect to tcp server error: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
c.SetDeadline(time.Now().Add(timeout))
|
||||
return sendRequestByConn(c, content)
|
||||
type Response struct {
|
||||
Code int
|
||||
Header http.Header
|
||||
Content []byte
|
||||
}
|
||||
|
||||
func SendUDPRequest(port int, content []byte, timeout time.Duration) ([]byte, error) {
|
||||
c, err := net.Dial("udp", fmt.Sprintf("127.0.0.1:%d", port))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("connect to udp server error: %v", err)
|
||||
func sendHTTPRequest(method, urlstr string, host string, headers map[string]string, proxy string, body []byte) (*Response, error) {
|
||||
var inBody io.Reader
|
||||
if len(body) != 0 {
|
||||
inBody = bytes.NewReader(body)
|
||||
}
|
||||
req, err := http.NewRequest(method, urlstr, inBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if host != "" {
|
||||
req.Host = host
|
||||
}
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
tr := &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
if len(proxy) != 0 {
|
||||
tr.Proxy = func(req *http.Request) (*url.URL, error) {
|
||||
return url.Parse(proxy)
|
||||
}
|
||||
}
|
||||
client := http.Client{Transport: tr}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
c.SetDeadline(time.Now().Add(timeout))
|
||||
return sendRequestByConn(c, content)
|
||||
ret := &Response{Code: resp.StatusCode, Header: resp.Header}
|
||||
buf, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret.Content = buf
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func sendRequestByConn(c net.Conn, content []byte) ([]byte, error) {
|
||||
|
||||
133
test/e2e/pkg/sdk/client/client.go
Normal file
133
test/e2e/pkg/sdk/client/client.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/client"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/utils"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
address string
|
||||
authUser string
|
||||
authPwd string
|
||||
}
|
||||
|
||||
func New(host string, port int) *Client {
|
||||
return &Client{
|
||||
address: net.JoinHostPort(host, strconv.Itoa(port)),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) SetAuth(user, pwd string) {
|
||||
c.authUser = user
|
||||
c.authPwd = pwd
|
||||
}
|
||||
|
||||
func (c *Client) GetProxyStatus(name string) (*client.ProxyStatusResp, error) {
|
||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/status", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
content, err := c.do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allStatus := &client.StatusResp{}
|
||||
if err = json.Unmarshal([]byte(content), &allStatus); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(content))
|
||||
}
|
||||
for _, s := range allStatus.TCP {
|
||||
if s.Name == name {
|
||||
return &s, nil
|
||||
}
|
||||
}
|
||||
for _, s := range allStatus.UDP {
|
||||
if s.Name == name {
|
||||
return &s, nil
|
||||
}
|
||||
}
|
||||
for _, s := range allStatus.HTTP {
|
||||
if s.Name == name {
|
||||
return &s, nil
|
||||
}
|
||||
}
|
||||
for _, s := range allStatus.HTTPS {
|
||||
if s.Name == name {
|
||||
return &s, nil
|
||||
}
|
||||
}
|
||||
for _, s := range allStatus.STCP {
|
||||
if s.Name == name {
|
||||
return &s, nil
|
||||
}
|
||||
}
|
||||
for _, s := range allStatus.XTCP {
|
||||
if s.Name == name {
|
||||
return &s, nil
|
||||
}
|
||||
}
|
||||
for _, s := range allStatus.SUDP {
|
||||
if s.Name == name {
|
||||
return &s, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no proxy status found")
|
||||
}
|
||||
|
||||
func (c *Client) Reload() error {
|
||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/reload", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = c.do(req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) GetConfig() (string, error) {
|
||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/config", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return c.do(req)
|
||||
}
|
||||
|
||||
func (c *Client) UpdateConfig(content string) error {
|
||||
req, err := http.NewRequest("PUT", "http://"+c.address+"/api/config", strings.NewReader(content))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = c.do(req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) setAuthHeader(req *http.Request) {
|
||||
if c.authUser != "" || c.authPwd != "" {
|
||||
req.Header.Set("Authorization", utils.BasicAuth(c.authUser, c.authPwd))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) do(req *http.Request) (string, error) {
|
||||
c.setAuthHeader(req)
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return "", fmt.Errorf("api status code [%d]", resp.StatusCode)
|
||||
}
|
||||
buf, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
10
test/e2e/pkg/utils/utils.go
Normal file
10
test/e2e/pkg/utils/utils.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
func BasicAuth(username, passwd string) string {
|
||||
auth := username + ":" + passwd
|
||||
return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
|
||||
}
|
||||
Reference in New Issue
Block a user