mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 12:04:03 +03:00
Refactor network to a top-level module
This commit is contained in:
+5
-5
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/9seconds/mtg/v2/config"
|
||||
"github.com/9seconds/mtg/v2/mtglib"
|
||||
"github.com/9seconds/mtg/v2/testlib"
|
||||
"github.com/jarcoal/httpmock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
@@ -126,7 +127,7 @@ func (suite *AccessTestSuite) TestGenerateNoCalls() {
|
||||
suite.cli.Access.PublicIPv4 = net.ParseIP("10.0.0.10")
|
||||
suite.cli.Access.PublicIPv6 = net.ParseIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
|
||||
|
||||
output := suite.CaptureStdout(func() {
|
||||
output := testlib.CaptureStdout(func() {
|
||||
suite.NoError(suite.cli.Access.Execute(suite.cli))
|
||||
})
|
||||
|
||||
@@ -150,7 +151,7 @@ func (suite *AccessTestSuite) TestGenerateIPv4Call() {
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://ifconfig.co",
|
||||
httpmock.NewStringResponder(http.StatusOK, "10.11.12.13"))
|
||||
|
||||
output := suite.CaptureStdout(func() {
|
||||
output := testlib.CaptureStdout(func() {
|
||||
suite.NoError(suite.cli.Access.Execute(suite.cli))
|
||||
})
|
||||
|
||||
@@ -174,7 +175,7 @@ func (suite *AccessTestSuite) TestIPv4CallFail() {
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://ifconfig.co",
|
||||
httpmock.NewStringResponder(http.StatusForbidden, ""))
|
||||
|
||||
output := suite.CaptureStdout(func() {
|
||||
output := testlib.CaptureStdout(func() {
|
||||
suite.NoError(suite.cli.Access.Execute(suite.cli))
|
||||
})
|
||||
|
||||
@@ -191,7 +192,6 @@ func (suite *AccessTestSuite) TestIPv4CallFail() {
|
||||
suite.Contains(output, suite.cli.Access.Config.Secret.Hex())
|
||||
}
|
||||
|
||||
func TestAccess(t *testing.T) {
|
||||
t.Parallel()
|
||||
func TestAccess(t *testing.T) { // nolint: paralleltest
|
||||
suite.Run(t, &AccessTestSuite{})
|
||||
}
|
||||
|
||||
+4
-3
@@ -7,11 +7,12 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/9seconds/mtg/v2/config"
|
||||
"github.com/9seconds/mtg/v2/mtglib/network"
|
||||
"github.com/9seconds/mtg/v2/mtglib"
|
||||
"github.com/9seconds/mtg/v2/network"
|
||||
)
|
||||
|
||||
type base struct {
|
||||
Network network.Network
|
||||
Network mtglib.Network
|
||||
Config *config.Config
|
||||
}
|
||||
|
||||
@@ -37,7 +38,7 @@ func (b *base) ReadConfig(path, version string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *base) makeNetwork(conf *config.Config, version string) (network.Network, error) {
|
||||
func (b *base) makeNetwork(conf *config.Config, version string) (mtglib.Network, error) {
|
||||
tcpTimeout := conf.Network.Timeout.TCP.Value(network.DefaultTimeout)
|
||||
idleTimeout := conf.Network.Timeout.Idle.Value(network.DefaultIdleTimeout)
|
||||
httpTimeout := conf.Network.Timeout.HTTP.Value(network.DefaultHTTPTimeout)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/9seconds/mtg/v2/mtglib"
|
||||
"github.com/9seconds/mtg/v2/testlib"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
@@ -19,7 +20,7 @@ func (suite *GenerateSecretTestSuite) SetupTest() {
|
||||
}
|
||||
|
||||
func (suite *GenerateSecretTestSuite) TestDefault() {
|
||||
output := suite.CaptureStdout(func() {
|
||||
output := testlib.CaptureStdout(func() {
|
||||
suite.NoError(suite.cli.GenerateSecret.Run(suite.cli, "dev"))
|
||||
})
|
||||
suite.True(strings.HasPrefix(output, "7"))
|
||||
@@ -33,7 +34,7 @@ func (suite *GenerateSecretTestSuite) TestDefault() {
|
||||
func (suite *GenerateSecretTestSuite) TestHex() {
|
||||
suite.cli.GenerateSecret.Hex = true
|
||||
|
||||
output := suite.CaptureStdout(func() {
|
||||
output := testlib.CaptureStdout(func() {
|
||||
suite.NoError(suite.cli.GenerateSecret.Run(suite.cli, "dev"))
|
||||
})
|
||||
suite.True(strings.HasPrefix(output, "ee"))
|
||||
|
||||
+3
-78
@@ -1,66 +1,25 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/9seconds/mtg/v2/cli"
|
||||
"github.com/9seconds/mtg/v2/mtglib/network"
|
||||
"github.com/9seconds/mtg/v2/testlib"
|
||||
"github.com/jarcoal/httpmock"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type NetworkMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (n *NetworkMock) Dial(network, address string) (net.Conn, error) {
|
||||
args := n.Called(network, address)
|
||||
|
||||
return args.Get(0).(net.Conn), args.Error(1)
|
||||
}
|
||||
|
||||
func (n *NetworkMock) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
args := n.Called(ctx, network, address)
|
||||
|
||||
return args.Get(0).(net.Conn), args.Error(1)
|
||||
}
|
||||
|
||||
func (n *NetworkMock) DNSResolve(network, hostname string) ([]string, error) {
|
||||
args := n.Called(network, hostname)
|
||||
|
||||
return args.Get(0).([]string), args.Error(1)
|
||||
}
|
||||
|
||||
func (n *NetworkMock) MakeHTTPClient(dialFunc network.DialFunc) *http.Client {
|
||||
return n.Called(dialFunc).Get(0).(*http.Client)
|
||||
}
|
||||
|
||||
func (n *NetworkMock) IdleTimeout() time.Duration {
|
||||
return n.Called().Get(0).(time.Duration)
|
||||
}
|
||||
|
||||
func (n *NetworkMock) HTTPTimeout() time.Duration {
|
||||
return n.Called().Get(0).(time.Duration)
|
||||
}
|
||||
|
||||
type CommonTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cli *cli.CLI
|
||||
networkMock *NetworkMock
|
||||
networkMock *testlib.NetworkMock
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func (suite *CommonTestSuite) SetupTest() {
|
||||
suite.networkMock = &NetworkMock{}
|
||||
suite.networkMock = &testlib.NetworkMock{}
|
||||
suite.httpClient = &http.Client{}
|
||||
suite.cli = &cli.CLI{}
|
||||
|
||||
@@ -76,37 +35,3 @@ func (suite *CommonTestSuite) TearDownTest() {
|
||||
suite.networkMock.AssertExpectations(suite.T())
|
||||
httpmock.DeactivateAndReset()
|
||||
}
|
||||
|
||||
func (suite *CommonTestSuite) CaptureStdout(callback func()) string {
|
||||
return suite.captureOutput(&os.Stdout, callback)
|
||||
}
|
||||
|
||||
func (suite *CommonTestSuite) CaptureStderr(callback func()) string {
|
||||
return suite.captureOutput(&os.Stderr, callback)
|
||||
}
|
||||
|
||||
func (suite *CommonTestSuite) captureOutput(filefp **os.File, callback func()) string {
|
||||
oldFp := *filefp
|
||||
|
||||
defer func() {
|
||||
*filefp = oldFp
|
||||
}()
|
||||
|
||||
reader, writer, _ := os.Pipe()
|
||||
buf := &bytes.Buffer{}
|
||||
closeChan := make(chan bool)
|
||||
|
||||
go func() {
|
||||
io.Copy(buf, reader) // nolint: errcheck
|
||||
close(closeChan)
|
||||
}()
|
||||
|
||||
*filefp = writer
|
||||
|
||||
callback()
|
||||
|
||||
writer.Close()
|
||||
<-closeChan
|
||||
|
||||
return strings.TrimSpace(buf.String())
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ require (
|
||||
github.com/libp2p/go-reuseport v0.0.2
|
||||
github.com/mccutchen/go-httpbin v1.1.1
|
||||
github.com/pelletier/go-toml v1.8.1
|
||||
github.com/rs/zerolog v1.20.0 // indirect
|
||||
github.com/stretchr/objx v0.3.0 // indirect
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
|
||||
@@ -6,6 +6,7 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -27,6 +28,9 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
|
||||
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
|
||||
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
@@ -42,15 +46,22 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY=
|
||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
+28
-1
@@ -1,5 +1,32 @@
|
||||
package mtglib
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ErrSecretEmpty = errors.New("secret is empty")
|
||||
|
||||
type Network interface {
|
||||
Dial(network, address string) (net.Conn, error)
|
||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
||||
MakeHTTPClient(func(ctx context.Context, network, address string) (net.Conn, error)) *http.Client
|
||||
IdleTimeout() time.Duration
|
||||
}
|
||||
|
||||
type Logger interface {
|
||||
Named(name string) Logger
|
||||
|
||||
BindInt(name string, value int) Logger
|
||||
BindStr(name, value string) Logger
|
||||
|
||||
Info(msg string)
|
||||
InfoError(msg string, err error)
|
||||
Warning(msg string)
|
||||
WarningError(msg string, err error)
|
||||
Debug(msg string)
|
||||
DebugError(msg string, err error)
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
type ConnMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (c *ConnMock) Read(b []byte) (int, error) {
|
||||
args := c.Called(b)
|
||||
|
||||
return args.Int(0), args.Error(1)
|
||||
}
|
||||
|
||||
func (c *ConnMock) Write(b []byte) (int, error) {
|
||||
args := c.Called(b)
|
||||
|
||||
return args.Int(0), args.Error(1)
|
||||
}
|
||||
|
||||
func (c *ConnMock) Close() error {
|
||||
return c.Called().Error(0)
|
||||
}
|
||||
|
||||
func (c *ConnMock) LocalAddr() net.Addr {
|
||||
return c.Called().Get(0).(net.Addr)
|
||||
}
|
||||
|
||||
func (c *ConnMock) RemoteAddr() net.Addr {
|
||||
return c.Called().Get(0).(net.Addr)
|
||||
}
|
||||
|
||||
func (c *ConnMock) SetDeadline(t time.Time) error {
|
||||
return c.Called(t).Error(0)
|
||||
}
|
||||
|
||||
func (c *ConnMock) SetReadDeadline(t time.Time) error {
|
||||
return c.Called(t).Error(0)
|
||||
}
|
||||
|
||||
func (c *ConnMock) SetWriteDeadline(t time.Time) error {
|
||||
return c.Called(t).Error(0)
|
||||
}
|
||||
|
||||
type DialerMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (d *DialerMock) Dial(network, address string) (net.Conn, error) {
|
||||
args := d.Called(network, address)
|
||||
|
||||
return args.Get(0).(net.Conn), args.Error(1)
|
||||
}
|
||||
|
||||
func (d *DialerMock) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
args := d.Called(ctx, network, address)
|
||||
|
||||
return args.Get(0).(net.Conn), args.Error(1)
|
||||
}
|
||||
+3
-2
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/9seconds/mtg/v2/testlib"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
@@ -20,7 +21,7 @@ type CircuitBreakerTestSuite struct {
|
||||
mutex sync.Mutex
|
||||
ctx context.Context
|
||||
ctxCancel context.CancelFunc
|
||||
connMock *ConnMock
|
||||
connMock *testlib.NetConnMock
|
||||
baseDialerMock *DialerMock
|
||||
}
|
||||
|
||||
@@ -28,7 +29,7 @@ func (suite *CircuitBreakerTestSuite) SetupTest() {
|
||||
suite.mutex = sync.Mutex{}
|
||||
suite.ctx, suite.ctxCancel = context.WithCancel(context.Background())
|
||||
suite.baseDialerMock = &DialerMock{}
|
||||
suite.connMock = &ConnMock{}
|
||||
suite.connMock = &testlib.NetConnMock{}
|
||||
suite.d = newCircuitBreakerDialer(suite.baseDialerMock,
|
||||
3, 100*time.Millisecond, 50*time.Millisecond)
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/9seconds/mtg/v2/mtglib/network"
|
||||
"github.com/9seconds/mtg/v2/network"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -27,18 +26,7 @@ var (
|
||||
ErrCannotDialWithAllProxies = errors.New("cannot dial with all proxies")
|
||||
)
|
||||
|
||||
type DialFunc func(ctx context.Context, protocol, address string) (net.Conn, error)
|
||||
|
||||
type Dialer interface {
|
||||
Dial(network, address string) (net.Conn, error)
|
||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
||||
}
|
||||
|
||||
type Network interface {
|
||||
Dialer
|
||||
|
||||
DNSResolve(network, hostname string) (ips []string, err error)
|
||||
MakeHTTPClient(DialFunc) *http.Client
|
||||
IdleTimeout() time.Duration
|
||||
HTTPTimeout() time.Duration
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
type DialerMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (d *DialerMock) Dial(network, address string) (net.Conn, error) {
|
||||
args := d.Called(network, address)
|
||||
|
||||
return args.Get(0).(net.Conn), args.Error(1)
|
||||
}
|
||||
|
||||
func (d *DialerMock) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
args := d.Called(ctx, network, address)
|
||||
|
||||
return args.Get(0).(net.Conn), args.Error(1)
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/9seconds/mtg/v2/mtglib/network"
|
||||
"github.com/9seconds/mtg/v2/network"
|
||||
socks5 "github.com/armon/go-socks5"
|
||||
"github.com/mccutchen/go-httpbin/httpbin"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/9seconds/mtg/v2/mtglib/network"
|
||||
"github.com/9seconds/mtg/v2/network"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/9seconds/mtg/v2/mtglib"
|
||||
doh "github.com/babolivier/go-doh-client"
|
||||
)
|
||||
|
||||
@@ -38,7 +39,7 @@ func (n *network) Dial(protocol, address string) (net.Conn, error) {
|
||||
func (n *network) DialContext(ctx context.Context, protocol, address string) (net.Conn, error) {
|
||||
host, port, _ := net.SplitHostPort(address)
|
||||
|
||||
ips, err := n.DNSResolve(protocol, host)
|
||||
ips, err := n.dnsResolve(protocol, host)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot resolve dns names: %w", err)
|
||||
}
|
||||
@@ -61,7 +62,20 @@ func (n *network) DialContext(ctx context.Context, protocol, address string) (ne
|
||||
return nil, fmt.Errorf("cannot dial to %s:%s: %w", protocol, address, err)
|
||||
}
|
||||
|
||||
func (n *network) DNSResolve(protocol, address string) ([]string, error) {
|
||||
func (n *network) MakeHTTPClient(dialFunc func(ctx context.Context,
|
||||
network, address string) (net.Conn, error)) *http.Client {
|
||||
if dialFunc == nil {
|
||||
dialFunc = n.DialContext
|
||||
}
|
||||
|
||||
return makeHTTPClient(n.userAgent, n.httpTimeout, dialFunc)
|
||||
}
|
||||
|
||||
func (n *network) IdleTimeout() time.Duration {
|
||||
return n.idleTimeout
|
||||
}
|
||||
|
||||
func (n *network) dnsResolve(protocol, address string) ([]string, error) {
|
||||
if net.ParseIP(address) != nil {
|
||||
return []string{address}, nil
|
||||
}
|
||||
@@ -115,25 +129,9 @@ func (n *network) DNSResolve(protocol, address string) ([]string, error) {
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func (n *network) MakeHTTPClient(dialFunc DialFunc) *http.Client {
|
||||
if dialFunc == nil {
|
||||
dialFunc = n.DialContext
|
||||
}
|
||||
|
||||
return makeHTTPClient(n.userAgent, n.httpTimeout, dialFunc)
|
||||
}
|
||||
|
||||
func (n *network) IdleTimeout() time.Duration {
|
||||
return n.idleTimeout
|
||||
}
|
||||
|
||||
func (n *network) HTTPTimeout() time.Duration {
|
||||
return n.httpTimeout
|
||||
}
|
||||
|
||||
func NewNetwork(dialer Dialer,
|
||||
userAgent, dohHostname string,
|
||||
httpTimeout, idleTimeout time.Duration) (Network, error) {
|
||||
httpTimeout, idleTimeout time.Duration) (mtglib.Network, error) {
|
||||
switch {
|
||||
case idleTimeout < 0:
|
||||
return nil, fmt.Errorf("timeout should be positive number %s", idleTimeout)
|
||||
@@ -158,7 +156,9 @@ func NewNetwork(dialer Dialer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func makeHTTPClient(userAgent string, timeout time.Duration, dialFunc DialFunc) *http.Client {
|
||||
func makeHTTPClient(userAgent string,
|
||||
timeout time.Duration,
|
||||
dialFunc func(ctx context.Context, network, address string) (net.Conn, error)) *http.Client {
|
||||
return &http.Client{
|
||||
Timeout: timeout,
|
||||
Transport: networkHTTPTransport{
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/9seconds/mtg/v2/mtglib/network"
|
||||
"github.com/9seconds/mtg/v2/network"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package testlib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CaptureStdout(callback func()) string {
|
||||
return captureOutput(&os.Stdout, callback)
|
||||
}
|
||||
|
||||
func CaptureStderr(callback func()) string {
|
||||
return captureOutput(&os.Stderr, callback)
|
||||
}
|
||||
|
||||
func captureOutput(filefp **os.File, callback func()) string {
|
||||
oldFp := *filefp
|
||||
|
||||
defer func() {
|
||||
*filefp = oldFp
|
||||
}()
|
||||
|
||||
reader, writer, _ := os.Pipe()
|
||||
buf := &bytes.Buffer{}
|
||||
closeChan := make(chan bool)
|
||||
|
||||
go func() {
|
||||
io.Copy(buf, reader) // nolint: errcheck
|
||||
close(closeChan)
|
||||
}()
|
||||
|
||||
*filefp = writer
|
||||
|
||||
callback()
|
||||
|
||||
writer.Close()
|
||||
<-closeChan
|
||||
|
||||
return strings.TrimSpace(buf.String())
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package testlib
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
type NetConnMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (n *NetConnMock) Read(b []byte) (int, error) {
|
||||
args := n.Called(b)
|
||||
|
||||
return args.Int(0), args.Error(1)
|
||||
}
|
||||
|
||||
func (n *NetConnMock) Write(b []byte) (int, error) {
|
||||
args := n.Called(b)
|
||||
|
||||
return args.Int(0), args.Error(1)
|
||||
}
|
||||
|
||||
func (n *NetConnMock) Close() error {
|
||||
return n.Called().Error(0)
|
||||
}
|
||||
|
||||
func (n *NetConnMock) LocalAddr() net.Addr {
|
||||
return n.Called().Get(0).(net.Addr)
|
||||
}
|
||||
|
||||
func (n *NetConnMock) RemoteAddr() net.Addr {
|
||||
return n.Called().Get(0).(net.Addr)
|
||||
}
|
||||
|
||||
func (n *NetConnMock) SetDeadline(t time.Time) error {
|
||||
return n.Called(t).Error(0)
|
||||
}
|
||||
|
||||
func (n *NetConnMock) SetReadDeadline(t time.Time) error {
|
||||
return n.Called(t).Error(0)
|
||||
}
|
||||
|
||||
func (n *NetConnMock) SetWriteDeadline(t time.Time) error {
|
||||
return n.Called(t).Error(0)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package testlib
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
type NetworkMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (n *NetworkMock) Dial(network, address string) (net.Conn, error) {
|
||||
args := n.Called(network, address)
|
||||
|
||||
return args.Get(0).(net.Conn), args.Error(1)
|
||||
}
|
||||
|
||||
func (n *NetworkMock) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
args := n.Called(ctx, network, address)
|
||||
|
||||
return args.Get(0).(net.Conn), args.Error(1)
|
||||
}
|
||||
|
||||
func (n *NetworkMock) MakeHTTPClient(dialFunc func(ctx context.Context,
|
||||
network, address string) (net.Conn, error)) *http.Client {
|
||||
return n.Called(dialFunc).Get(0).(*http.Client)
|
||||
}
|
||||
|
||||
func (n *NetworkMock) IdleTimeout() time.Duration {
|
||||
return n.Called().Get(0).(time.Duration)
|
||||
}
|
||||
Reference in New Issue
Block a user