From 8740e6f258a6b444a99b06fe5bee6e15015f6ffc Mon Sep 17 00:00:00 2001 From: RMT Date: Tue, 12 May 2026 13:52:31 +0300 Subject: [PATCH] Add e2e test cases for shadowsocks --- go.mod | 48 +++++- go.sum | 111 ++++++++++-- tests/e2e/Dockerfile | 4 +- tests/e2e/README.md | 53 ++++++ tests/e2e/main_test.go | 40 +++-- tests/e2e/parallel_selector_test.go | 2 +- tests/e2e/scripts/tcp_echo.py | 16 ++ tests/e2e/scripts/udp_echo.py | 9 + tests/e2e/shadowsocks_test.go | 160 ++++++++++++++++++ .../shadowsocks/tcp_client_2022_aes128.yaml | 23 +++ .../tcp_client_2022_aes128_multipsk.yaml | 23 +++ .../shadowsocks/tcp_client_2022_aes256.yaml | 23 +++ .../tcp_client_2022_aes256_multipsk.yaml | 23 +++ .../shadowsocks/tcp_client_aes256gcm.yaml | 23 +++ .../shadowsocks/tcp_client_chacha20.yaml | 23 +++ .../shadowsocks/tcp_server_2022_aes128.yaml | 10 ++ .../tcp_server_2022_aes128_multipsk.yaml | 13 ++ .../shadowsocks/tcp_server_2022_aes256.yaml | 10 ++ .../tcp_server_2022_aes256_multipsk.yaml | 13 ++ .../shadowsocks/tcp_server_aes256gcm.yaml | 10 ++ .../shadowsocks/tcp_server_chacha20.yaml | 10 ++ .../shadowsocks/udp_client_2022_aes128.yaml | 27 +++ .../shadowsocks/udp_client_2022_aes256.yaml | 27 +++ .../shadowsocks/udp_client_aes256gcm.yaml | 27 +++ .../shadowsocks/udp_server_2022_aes128.yaml | 10 ++ .../shadowsocks/udp_server_2022_aes256.yaml | 10 ++ .../shadowsocks/udp_server_aes256gcm.yaml | 10 ++ tests/e2e/utils.go | 138 +++++++++++++-- 28 files changed, 849 insertions(+), 47 deletions(-) create mode 100644 tests/e2e/README.md create mode 100644 tests/e2e/scripts/tcp_echo.py create mode 100644 tests/e2e/scripts/udp_echo.py create mode 100644 tests/e2e/shadowsocks_test.go create mode 100644 tests/e2e/testdata/shadowsocks/tcp_client_2022_aes128.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_client_2022_aes128_multipsk.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_client_2022_aes256.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_client_2022_aes256_multipsk.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_client_aes256gcm.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_client_chacha20.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_server_2022_aes128.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_server_2022_aes128_multipsk.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_server_2022_aes256.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_server_2022_aes256_multipsk.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_server_aes256gcm.yaml create mode 100644 tests/e2e/testdata/shadowsocks/tcp_server_chacha20.yaml create mode 100644 tests/e2e/testdata/shadowsocks/udp_client_2022_aes128.yaml create mode 100644 tests/e2e/testdata/shadowsocks/udp_client_2022_aes256.yaml create mode 100644 tests/e2e/testdata/shadowsocks/udp_client_aes256gcm.yaml create mode 100644 tests/e2e/testdata/shadowsocks/udp_server_2022_aes128.yaml create mode 100644 tests/e2e/testdata/shadowsocks/udp_server_2022_aes256.yaml create mode 100644 tests/e2e/testdata/shadowsocks/udp_server_aes256gcm.yaml diff --git a/go.mod b/go.mod index 7274d47..5c1c7f2 100644 --- a/go.mod +++ b/go.mod @@ -6,22 +6,39 @@ require ( github.com/go-gost/core v0.4.0 github.com/go-gost/x v0.10.0 github.com/judwhite/go-svc v1.2.1 + github.com/stretchr/testify v1.11.1 + github.com/testcontainers/testcontainers-go v0.42.0 ) require ( + dario.cat/mergo v1.0.2 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alessio/shellescape v1.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/coreos/go-iptables v0.5.0 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/danieljoos/wincred v1.2.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/go-connections v0.7.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/dunglas/httpsfv v1.1.0 // indirect + github.com/ebitengine/purego v0.10.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/cors v1.7.2 // indirect @@ -33,6 +50,9 @@ require ( github.com/go-gost/plugin v0.3.0 // indirect github.com/go-gost/relay v0.6.0 // indirect github.com/go-gost/tls-dissector v0.2.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.20.0 // indirect @@ -50,16 +70,29 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.18.5 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/reedsolomon v1.11.8 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/magiconair/properties v1.8.7 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.10 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/miekg/dns v1.1.61 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/go-archive v0.2.0 // indirect + github.com/moby/moby/api v1.54.1 // indirect + github.com/moby/moby/client v0.4.0 // indirect + github.com/moby/patternmatcher v0.6.1 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.4.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pion/dtls/v2 v2.2.6 // indirect @@ -68,6 +101,8 @@ require ( github.com/pion/udp/v2 v2.0.1 // indirect github.com/pires/go-proxyproto v0.8.1 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.6.0 // indirect github.com/prometheus/common v0.48.0 // indirect @@ -80,7 +115,8 @@ require ( github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect + github.com/shirou/gopsutil/v4 v4.26.3 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect @@ -91,6 +127,8 @@ require ( github.com/templexxx/cpu v0.1.1 // indirect github.com/templexxx/xorsimd v0.4.3 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 // indirect @@ -101,8 +139,14 @@ require ( github.com/xtaci/smux v1.5.31 // indirect github.com/xtaci/tcpraw v1.2.25 // indirect github.com/yl2chen/cidranger v1.0.2 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zalando/go-keyring v0.2.4 // indirect github.com/zeebo/blake3 v0.2.4 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect + go.opentelemetry.io/otel v1.41.0 // indirect + go.opentelemetry.io/otel/metric v1.41.0 // indirect + go.opentelemetry.io/otel/trace v1.41.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.50.0 // indirect diff --git a/go.sum b/go.sum index 48f88d2..a3a8f88 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,13 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= @@ -12,6 +20,8 @@ github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -21,8 +31,20 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/coreos/go-iptables v0.5.0 h1:mw6SAibtHKZcNzAsOxjoHIG0gy5YFHhypWSSNc6EjbQ= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -31,12 +53,22 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= +github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -65,10 +97,13 @@ github.com/go-gost/tls-dissector v0.2.0 h1:9tE6WOzzpurATTBWn60DU4R8gibpGNY8/qVcc github.com/go-gost/tls-dissector v0.2.0/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs= github.com/go-gost/x v0.10.0 h1:bPcmXQ7YvwfgqsHxdQSEcuq6orPIEQmVVEGcDG+HAhY= github.com/go-gost/x v0.10.0/go.mod h1:P7iASIn28XVNlENQTdJ8bUkRHcrObjuxd7UUjxK/PaY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -106,6 +141,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -127,6 +163,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/judwhite/go-svc v1.2.1 h1:a7fsJzYUa33sfDJRF2N/WXhA+LonCEEY8BJb1tuS5tA= github.com/judwhite/go-svc v1.2.1/go.mod h1:mo/P2JNX8C07ywpP9YtO2gnBgnUiFTHqtsZekJrUuTk= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -139,8 +177,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= @@ -149,6 +189,24 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8= +github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU= +github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= +github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= +github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= +github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= +github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U= +github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -160,6 +218,10 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= @@ -179,6 +241,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -196,8 +260,8 @@ github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+ github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -206,9 +270,11 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 h1:XdDrN8rtxdgW3TLn7pAuobI9PhPMbf6Geu9nvFzXn2E= github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740/go.mod h1:Oqfn/ykzqjeX00+7IuPyR7wGYgOzld0Tni6djgElacI= +github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= +github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8= github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -224,8 +290,9 @@ github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -244,8 +311,14 @@ github.com/templexxx/cpu v0.1.1 h1:isxHaxBXpYFWnk2DReuKkigaZyrjs2+9ypIdGP4h+HI= github.com/templexxx/cpu v0.1.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= github.com/templexxx/xorsimd v0.4.3 h1:9AQTFHd7Bhk3dIT7Al2XeBX5DWOvsUPZCuhyAtNbHjU= github.com/templexxx/xorsimd v0.4.3/go.mod h1:oZQcD6RFDisW2Am58dSAGwwL6rHjbzrlu25VDqfWkQg= +github.com/testcontainers/testcontainers-go v0.42.0 h1:He3IhTzTZOygSXLJPMX7n44XtK+qhjat1nI9cneBbUY= +github.com/testcontainers/testcontainers-go v0.42.0/go.mod h1:vZjdY1YmUA1qEForxOIOazfsrdyORJAbhi0bp8plN30= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -270,6 +343,8 @@ github.com/xtaci/tcpraw v1.2.25/go.mod h1:dKyZ2V75s0cZ7cbgJYdxPvms7af0joIeOyx1Gg github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU= github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zalando/go-keyring v0.2.4 h1:wi2xxTqdiwMKbM6TWwi+uJCG/Tum2UV0jqaQhCa9/68= github.com/zalando/go-keyring v0.2.4/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= @@ -280,16 +355,18 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= -go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= -go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= -go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c= +go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE= +go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ= +go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps= go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= -go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0= +go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -341,15 +418,17 @@ golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -424,9 +503,13 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= gvisor.dev/gvisor v0.0.0-20250523182742-eede7a881b20 h1:0DxLu8hxI1OGp1qVRPqNd+2k1a7hMNUNqbZG0IrtKlM= gvisor.dev/gvisor v0.0.0-20250523182742-eede7a881b20/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/tests/e2e/Dockerfile b/tests/e2e/Dockerfile index de2f03e..908c806 100644 --- a/tests/e2e/Dockerfile +++ b/tests/e2e/Dockerfile @@ -1,4 +1,4 @@ FROM alpine:3.22 -# add iptables for tun/tap and curl for testing -RUN apk add --no-cache iptables curl +# add tools needed by e2e containers and health checks +RUN apk add --no-cache iptables curl netcat-openbsd python3 diff --git a/tests/e2e/README.md b/tests/e2e/README.md new file mode 100644 index 0000000..81329d0 --- /dev/null +++ b/tests/e2e/README.md @@ -0,0 +1,53 @@ +# End-to-End Tests + +Integration tests that spin up real gost instances inside Docker containers and verify protocol behavior over the network. + +## Prerequisites + +- [Docker](https://docs.docker.com/get-docker/) (running daemon) +- Go toolchain (for compiling the gost binary under test) + +## Running + +From the repository root: + +```bash +# Run all e2e tests +go test ./tests/e2e/ -v -timeout 10m + +# Run a specific test suite +go test ./tests/e2e/ -v -run TestShadowsocksSuite -timeout 5m +go test ./tests/e2e/ -v -run TestParallelSelectorSuite -timeout 5m + +# Use a pre-built gost binary (skips compilation) +go test ./tests/e2e/ -v -gost-bin /path/to/gost +``` + +## Architecture + +``` +tests/e2e/ +├── Dockerfile # Shared base image (Alpine + curl, python3, etc.) +├── main_test.go # TestMain: compiles gost, creates Docker network +├── utils.go # Helpers: container lifecycle, config rendering +├── scripts/ +│ ├── tcp_echo.py # HTTP echo server (responds with "hello-gost") +│ └── udp_echo.py # UDP echo server (reflects payloads) +├── testdata/ # config files or data files for running cases +├── shadowsocks_test.go # Shadowsocks protocol tests +└── parallel_selector_test.go # Parallel node selector tests +``` + +### How it works + +1. **TestMain** (`main_test.go`) compiles the gost binary from `../../cmd/gost` (unless `-gost-bin` is provided) and creates a shared Docker network for all containers. +2. Each test suite starts echo server containers (TCP/UDP), then launches separate gost containers for server and client roles. +3. Client configs use Go template syntax (`{{.ServerAddr}}`) so the server address is injected at runtime. +4. Tests verify end-to-end connectivity by sending traffic through the gost proxy chain and checking that the echo server responds correctly. + +## Tips + +- Increase `-timeout` for CI or slow networks. Container image builds on first run take extra time. +- Use `-gost-bin` to avoid recompiling when iterating on tests locally. +- Add `-v` to see container log output on failure. +- RunGostContainer will wait for exposedPorts automatically, but it's not reliable for udp ports. So, you should check the readiness of udp ports inside cases. diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index 6c6a897..5d82d3a 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -2,6 +2,7 @@ package e2e import ( "context" + "flag" "fmt" "os" "os/exec" @@ -12,23 +13,31 @@ import ( var SharedNetworkName string +var GostBinPath string + +func init() { + flag.StringVar(&GostBinPath, "gost-bin", "", "Path to a pre-built gost binary (skips compilation)") +} + func TestMain(m *testing.M) { + flag.Parse() ctx := context.Background() - // Compile the gost binary - cmd := exec.Command("go", "build", "-o", "/tmp/gost-test-bin", "../../cmd/gost") - cmd.Env = append(os.Environ(), "CGO_ENABLED=0") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - fmt.Printf("Failed to compile gost: %v\n", err) - os.Exit(1) - } - defer func() { - os.Remove("/tmp/gost-test-bin") - }() + shouldCleanup := false + + if GostBinPath == "" { + GostBinPath = "/tmp/gost-test-bin" + cmd := exec.Command("go", "build", "-o", GostBinPath, "../../cmd/gost") + cmd.Env = append(os.Environ(), "CGO_ENABLED=0") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Printf("Failed to compile gost: %v\n", err) + os.Exit(1) + } + shouldCleanup = true + } - // Create a shared Docker network net, err := network.New(ctx) if err != nil { fmt.Printf("Failed to create network: %v\n", err) @@ -36,11 +45,12 @@ func TestMain(m *testing.M) { } SharedNetworkName = net.Name - // Run tests code := m.Run() - // Cleanup net.Remove(ctx) + if shouldCleanup { + os.Remove(GostBinPath) + } os.Exit(code) } diff --git a/tests/e2e/parallel_selector_test.go b/tests/e2e/parallel_selector_test.go index 52c4ebd..e82e0da 100644 --- a/tests/e2e/parallel_selector_test.go +++ b/tests/e2e/parallel_selector_test.go @@ -36,7 +36,7 @@ func (s *ParallelSelectorSuite) TearDownSuite() { } func (s *ParallelSelectorSuite) TestParallelSelector() { - gostC, err := RunGostContainer(s.ctx, SharedNetworkName, "testdata/parallel_selector/server.yaml") + gostC, err := RunGostContainerWithPorts(s.ctx, SharedNetworkName, "testdata/parallel_selector/server.yaml", "8080/tcp") s.Require().NoError(err) defer gostC.Terminate(s.ctx) diff --git a/tests/e2e/scripts/tcp_echo.py b/tests/e2e/scripts/tcp_echo.py new file mode 100644 index 0000000..6937535 --- /dev/null +++ b/tests/e2e/scripts/tcp_echo.py @@ -0,0 +1,16 @@ +from http.server import BaseHTTPRequestHandler, HTTPServer + + +class Handler(BaseHTTPRequestHandler): + def do_GET(self): + body = b"hello-gost" + self.send_response(200) + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + def log_message(self, format, *args): + return + + +HTTPServer(("0.0.0.0", 5678), Handler).serve_forever() diff --git a/tests/e2e/scripts/udp_echo.py b/tests/e2e/scripts/udp_echo.py new file mode 100644 index 0000000..f7797f5 --- /dev/null +++ b/tests/e2e/scripts/udp_echo.py @@ -0,0 +1,9 @@ +import socket + + +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sock.bind(("0.0.0.0", 5679)) + +while True: + data, addr = sock.recvfrom(2048) + sock.sendto(data, addr) diff --git a/tests/e2e/shadowsocks_test.go b/tests/e2e/shadowsocks_test.go new file mode 100644 index 0000000..a8ae6d2 --- /dev/null +++ b/tests/e2e/shadowsocks_test.go @@ -0,0 +1,160 @@ +package e2e + +import ( + "context" + "fmt" + "io" + "net" + "os" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/suite" + "github.com/testcontainers/testcontainers-go" +) + +type ShadowsocksSuite struct { + suite.Suite + ctx context.Context + echoC testcontainers.Container + echoIP string + udpC testcontainers.Container +} + +func (s *ShadowsocksSuite) SetupSuite() { + s.ctx = context.Background() + + s.T().Logf("start tcp echo container...") + echoC, err := RunEchoContainer(s.ctx, SharedNetworkName) + s.Require().NoError(err) + s.echoC = echoC + + echoIP, err := echoC.ContainerIP(s.ctx) + s.Require().NoError(err) + s.echoIP = echoIP + + s.T().Logf("start udp echo container...") + udpC, err := RunUDPEchoContainer(s.ctx, SharedNetworkName) + s.Require().NoError(err) + s.udpC = udpC +} + +func (s *ShadowsocksSuite) TearDownSuite() { + if s.echoC != nil { + s.echoC.Terminate(s.ctx) + } + if s.udpC != nil { + s.udpC.Terminate(s.ctx) + } +} + +func (s *ShadowsocksSuite) TestShadowsocksTCP() { + s.runTCPCase("aes256gcm", "testdata/shadowsocks/tcp_server_aes256gcm.yaml", "testdata/shadowsocks/tcp_client_aes256gcm.yaml") + s.runTCPCase("chacha20", "testdata/shadowsocks/tcp_server_chacha20.yaml", "testdata/shadowsocks/tcp_client_chacha20.yaml") +} + +func (s *ShadowsocksSuite) TestShadowsocks2022TCP() { + s.runTCPCase("2022-aes128", "testdata/shadowsocks/tcp_server_2022_aes128.yaml", "testdata/shadowsocks/tcp_client_2022_aes128.yaml") + s.runTCPCase("2022-aes256", "testdata/shadowsocks/tcp_server_2022_aes256.yaml", "testdata/shadowsocks/tcp_client_2022_aes256.yaml") +} + +func (s *ShadowsocksSuite) TestShadowsocks2022TCPMultiPSK() { + s.runTCPCase("2022-aes128-multipsk", "testdata/shadowsocks/tcp_server_2022_aes128_multipsk.yaml", "testdata/shadowsocks/tcp_client_2022_aes128_multipsk.yaml") + s.runTCPCase("2022-aes256-multipsk", "testdata/shadowsocks/tcp_server_2022_aes256_multipsk.yaml", "testdata/shadowsocks/tcp_client_2022_aes256_multipsk.yaml") +} + +func (s *ShadowsocksSuite) TestShadowsocksUDP() { + s.runUDPCase("aes256gcm", "testdata/shadowsocks/udp_server_aes256gcm.yaml", "testdata/shadowsocks/udp_client_aes256gcm.yaml") +} + +func (s *ShadowsocksSuite) TestShadowsocks2022UDP() { + s.runUDPCase("2022-aes128", "testdata/shadowsocks/udp_server_2022_aes128.yaml", "testdata/shadowsocks/udp_client_2022_aes128.yaml") + s.runUDPCase("2022-aes256", "testdata/shadowsocks/udp_server_2022_aes256.yaml", "testdata/shadowsocks/udp_client_2022_aes256.yaml") +} + +func (s *ShadowsocksSuite) runUDPCase(name, serverConfig, clientConfig string) { + s.T().Run(name, func(t *testing.T) { + serverAlias := name + "-ssu-server" + serverC, err := RunGostContainerWithOptions(s.ctx, SharedNetworkName, serverConfig, []string{serverAlias}, []string{"8389/udp"}) + s.Require().NoError(err) + defer serverC.Terminate(s.ctx) + + rendered, err := RenderConfig(clientConfig, ConfigData{ServerAddr: serverAlias + ":8389"}) + s.Require().NoError(err) + defer os.Remove(rendered) + + clientC, err := RunGostContainerWithPorts( + s.ctx, + SharedNetworkName, + rendered, + "9000/udp", + ) + s.Require().NoError(err) + defer clientC.Terminate(s.ctx) + + host, err := clientC.Host(s.ctx) + s.Require().NoError(err) + port, err := clientC.MappedPort(s.ctx, "9000/udp") + s.Require().NoError(err) + + conn, err := net.DialTimeout("udp", net.JoinHostPort(host, port.Port()), 5*time.Second) + s.Require().NoError(err) + defer conn.Close() + + payload := []byte("hello-gost-udp") + buf := make([]byte, 2048) + var n int + for i := range 5 { + _, err = conn.Write(payload) + s.Require().NoError(err) + _ = conn.SetReadDeadline(time.Now().Add(2 * time.Second)) + n, err = conn.Read(buf) + if err == nil { + break + } + s.T().Logf("udp read attempt %d failed: %v, retrying...", i+1, err) + time.Sleep(2 * time.Second) + } + if err != nil { + DumpLogs(s.T(), s.ctx, name+" udp client logs", clientC) + DumpLogs(s.T(), s.ctx, name+" udp server logs", serverC) + } + s.Require().NoError(err) + s.Require().Contains(string(buf[:n]), "hello-gost") + }) +} + +func TestShadowsocksSuite(t *testing.T) { + suite.Run(t, new(ShadowsocksSuite)) +} + +func (s *ShadowsocksSuite) runTCPCase(name, serverConfig, clientConfig string) { + s.T().Run(name, func(t *testing.T) { + serverAlias := name + "-ss-server" + serverC, err := RunGostContainerWithOptions(s.ctx, SharedNetworkName, serverConfig, []string{serverAlias}, []string{"8388/tcp"}) + s.Require().NoError(err) + defer serverC.Terminate(s.ctx) + + rendered, err := RenderConfig(clientConfig, ConfigData{ServerAddr: serverAlias + ":8388"}) + s.Require().NoError(err) + defer os.Remove(rendered) + + clientC, err := RunGostContainerWithPorts(s.ctx, SharedNetworkName, rendered, "8080/tcp") + s.Require().NoError(err) + defer clientC.Terminate(s.ctx) + + cmd := []string{"curl", "-v", "-s", "-x", "http://127.0.0.1:8080", fmt.Sprintf("http://%s:5678", s.echoIP)} + code, out, err := clientC.Exec(s.ctx, cmd) + s.Require().NoError(err) + + body, err := io.ReadAll(out) + s.Require().NoError(err) + if code != 0 || !strings.Contains(string(body), "hello-gost") { + DumpLogs(s.T(), s.ctx, name+" client logs", clientC) + DumpLogs(s.T(), s.ctx, name+" server logs", serverC) + } + s.Require().Equal(0, code) + s.Require().Contains(string(body), "hello-gost") + }) +} diff --git a/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes128.yaml b/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes128.yaml new file mode 100644 index 0000000..38fe809 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes128.yaml @@ -0,0 +1,23 @@ +services: +- name: http-proxy + addr: :8080 + handler: + type: http + chain: ss-tcp-chain + listener: + type: tcp + +chains: +- name: ss-tcp-chain + hops: + - name: ss-hop + nodes: + - name: ss-node + addr: {{.ServerAddr}} + connector: + type: ss + auth: + username: 2022-blake3-aes-128-gcm + password: MTIzNDU2Nzg5MDEyMzQ1Ng== + dialer: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes128_multipsk.yaml b/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes128_multipsk.yaml new file mode 100644 index 0000000..22b0df9 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes128_multipsk.yaml @@ -0,0 +1,23 @@ +services: +- name: http-proxy + addr: :8080 + handler: + type: http + chain: ss-tcp-chain + listener: + type: tcp + +chains: +- name: ss-tcp-chain + hops: + - name: ss-hop + nodes: + - name: ss-node + addr: {{.ServerAddr}} + connector: + type: ss + auth: + username: 2022-blake3-aes-128-gcm + password: MTIzNDU2Nzg5MDEyMzQ1Ng==:Vbwi6yqCwvPMPR1bCi32Dg== + dialer: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes256.yaml b/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes256.yaml new file mode 100644 index 0000000..13c156c --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes256.yaml @@ -0,0 +1,23 @@ +services: +- name: http-proxy + addr: :8080 + handler: + type: http + chain: ss-tcp-chain + listener: + type: tcp + +chains: +- name: ss-tcp-chain + hops: + - name: ss-hop + nodes: + - name: ss-node + addr: {{.ServerAddr}} + connector: + type: ss + auth: + username: 2022-blake3-aes-256-gcm + password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY= + dialer: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes256_multipsk.yaml b/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes256_multipsk.yaml new file mode 100644 index 0000000..909169a --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_client_2022_aes256_multipsk.yaml @@ -0,0 +1,23 @@ +services: +- name: http-proxy + addr: :8080 + handler: + type: http + chain: ss-tcp-chain + listener: + type: tcp + +chains: +- name: ss-tcp-chain + hops: + - name: ss-hop + nodes: + - name: ss-node + addr: {{.ServerAddr}} + connector: + type: ss + auth: + username: 2022-blake3-aes-256-gcm + password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY=:YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY= + dialer: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_client_aes256gcm.yaml b/tests/e2e/testdata/shadowsocks/tcp_client_aes256gcm.yaml new file mode 100644 index 0000000..fb257e6 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_client_aes256gcm.yaml @@ -0,0 +1,23 @@ +services: +- name: http-proxy + addr: :8080 + handler: + type: http + chain: ss-tcp-chain + listener: + type: tcp + +chains: +- name: ss-tcp-chain + hops: + - name: ss-hop + nodes: + - name: ss-node + addr: {{.ServerAddr}} + connector: + type: ss + auth: + username: aes-256-gcm + password: secret + dialer: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_client_chacha20.yaml b/tests/e2e/testdata/shadowsocks/tcp_client_chacha20.yaml new file mode 100644 index 0000000..b92e4e7 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_client_chacha20.yaml @@ -0,0 +1,23 @@ +services: +- name: http-proxy + addr: :8080 + handler: + type: http + chain: ss-tcp-chain + listener: + type: tcp + +chains: +- name: ss-tcp-chain + hops: + - name: ss-hop + nodes: + - name: ss-node + addr: {{.ServerAddr}} + connector: + type: ss + auth: + username: chacha20-ietf-poly1305 + password: secret + dialer: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes128.yaml b/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes128.yaml new file mode 100644 index 0000000..b2bfad7 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes128.yaml @@ -0,0 +1,10 @@ +services: +- name: ss-server + addr: :8388 + handler: + type: ss + auth: + username: 2022-blake3-aes-128-gcm + password: MTIzNDU2Nzg5MDEyMzQ1Ng== + listener: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes128_multipsk.yaml b/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes128_multipsk.yaml new file mode 100644 index 0000000..b984036 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes128_multipsk.yaml @@ -0,0 +1,13 @@ +services: +- name: ss-server + addr: :8388 + handler: + type: ss + auth: + username: 2022-blake3-aes-128-gcm + password: MTIzNDU2Nzg5MDEyMzQ1Ng== + metadata: + users: + test: Vbwi6yqCwvPMPR1bCi32Dg== + listener: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes256.yaml b/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes256.yaml new file mode 100644 index 0000000..b9e970e --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes256.yaml @@ -0,0 +1,10 @@ +services: +- name: ss-server + addr: :8388 + handler: + type: ss + auth: + username: 2022-blake3-aes-256-gcm + password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY= + listener: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes256_multipsk.yaml b/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes256_multipsk.yaml new file mode 100644 index 0000000..545f526 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_server_2022_aes256_multipsk.yaml @@ -0,0 +1,13 @@ +services: +- name: ss-server + addr: :8388 + handler: + type: ss + auth: + username: 2022-blake3-aes-256-gcm + password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY= + metadata: + users: + test: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY= + listener: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_server_aes256gcm.yaml b/tests/e2e/testdata/shadowsocks/tcp_server_aes256gcm.yaml new file mode 100644 index 0000000..78fb839 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_server_aes256gcm.yaml @@ -0,0 +1,10 @@ +services: +- name: ss-server + addr: :8388 + handler: + type: ss + auth: + username: aes-256-gcm + password: secret + listener: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/tcp_server_chacha20.yaml b/tests/e2e/testdata/shadowsocks/tcp_server_chacha20.yaml new file mode 100644 index 0000000..4b50fef --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/tcp_server_chacha20.yaml @@ -0,0 +1,10 @@ +services: +- name: ss-server + addr: :8388 + handler: + type: ss + auth: + username: chacha20-ietf-poly1305 + password: secret + listener: + type: tcp diff --git a/tests/e2e/testdata/shadowsocks/udp_client_2022_aes128.yaml b/tests/e2e/testdata/shadowsocks/udp_client_2022_aes128.yaml new file mode 100644 index 0000000..2fcdd44 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/udp_client_2022_aes128.yaml @@ -0,0 +1,27 @@ +services: +- name: udp-proxy + addr: :9000 + handler: + type: udp + chain: ssu-chain + forwarder: + nodes: + - name: udp-echo + addr: udp-echo:5679 + listener: + type: udp + +chains: +- name: ssu-chain + hops: + - name: ssu-hop + nodes: + - name: ssu-node + addr: {{.ServerAddr}} + connector: + type: ssu + auth: + username: 2022-blake3-aes-128-gcm + password: MTIzNDU2Nzg5MDEyMzQ1Ng== + dialer: + type: udp diff --git a/tests/e2e/testdata/shadowsocks/udp_client_2022_aes256.yaml b/tests/e2e/testdata/shadowsocks/udp_client_2022_aes256.yaml new file mode 100644 index 0000000..31f7495 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/udp_client_2022_aes256.yaml @@ -0,0 +1,27 @@ +services: +- name: udp-proxy + addr: :9000 + handler: + type: udp + chain: ssu-chain + forwarder: + nodes: + - name: udp-echo + addr: udp-echo:5679 + listener: + type: udp + +chains: +- name: ssu-chain + hops: + - name: ssu-hop + nodes: + - name: ssu-node + addr: {{.ServerAddr}} + connector: + type: ssu + auth: + username: 2022-blake3-aes-256-gcm + password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY= + dialer: + type: udp diff --git a/tests/e2e/testdata/shadowsocks/udp_client_aes256gcm.yaml b/tests/e2e/testdata/shadowsocks/udp_client_aes256gcm.yaml new file mode 100644 index 0000000..8270848 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/udp_client_aes256gcm.yaml @@ -0,0 +1,27 @@ +services: +- name: udp-proxy + addr: :9000 + handler: + type: udp + chain: ssu-chain + forwarder: + nodes: + - name: udp-echo + addr: udp-echo:5679 + listener: + type: udp + +chains: +- name: ssu-chain + hops: + - name: ssu-hop + nodes: + - name: ssu-node + addr: {{.ServerAddr}} + connector: + type: ssu + auth: + username: aes-256-gcm + password: secret + dialer: + type: udp diff --git a/tests/e2e/testdata/shadowsocks/udp_server_2022_aes128.yaml b/tests/e2e/testdata/shadowsocks/udp_server_2022_aes128.yaml new file mode 100644 index 0000000..1a38396 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/udp_server_2022_aes128.yaml @@ -0,0 +1,10 @@ +services: +- name: ssu-server + addr: :8389 + handler: + type: ssu + auth: + username: 2022-blake3-aes-128-gcm + password: MTIzNDU2Nzg5MDEyMzQ1Ng== + listener: + type: udp diff --git a/tests/e2e/testdata/shadowsocks/udp_server_2022_aes256.yaml b/tests/e2e/testdata/shadowsocks/udp_server_2022_aes256.yaml new file mode 100644 index 0000000..f0779e0 --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/udp_server_2022_aes256.yaml @@ -0,0 +1,10 @@ +services: +- name: ssu-server + addr: :8389 + handler: + type: ssu + auth: + username: 2022-blake3-aes-256-gcm + password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY= + listener: + type: udp diff --git a/tests/e2e/testdata/shadowsocks/udp_server_aes256gcm.yaml b/tests/e2e/testdata/shadowsocks/udp_server_aes256gcm.yaml new file mode 100644 index 0000000..60dc15c --- /dev/null +++ b/tests/e2e/testdata/shadowsocks/udp_server_aes256gcm.yaml @@ -0,0 +1,10 @@ +services: +- name: ssu-server + addr: :8389 + handler: + type: ssu + auth: + username: aes-256-gcm + password: secret + listener: + type: udp diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go index de6756a..6465736 100644 --- a/tests/e2e/utils.go +++ b/tests/e2e/utils.go @@ -2,27 +2,68 @@ package e2e import ( "context" + "io" + "os" + "testing" + "text/template" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" ) -func RunEchoContainer(ctx context.Context, networkName string) (testcontainers.Container, error) { - req := testcontainers.ContainerRequest{ - Image: "hashicorp/http-echo:latest", - Networks: []string{networkName}, - Cmd: []string{"-text=hello-gost", "-listen=:5678"}, - ExposedPorts: []string{"5678/tcp"}, - WaitingFor: wait.ForHTTP("/").WithPort("5678/tcp"), +type ConfigData struct { + ServerAddr string +} + +func DumpLogs(t *testing.T, ctx context.Context, label string, c testcontainers.Container) { + logs, err := c.Logs(ctx) + if err != nil { + return } + defer logs.Close() + + body, err := io.ReadAll(logs) + if err != nil { + return + } + + t.Logf("%s:\n%s", label, string(body)) +} + +func RenderConfig(tmplPath string, data ConfigData) (string, error) { + tmpl, err := template.ParseFiles(tmplPath) + if err != nil { + return "", err + } + + f, err := os.CreateTemp("", "gost-e2e-config-*.yaml") + if err != nil { + return "", err + } + + if err := tmpl.Execute(f, data); err != nil { + f.Close() + os.Remove(f.Name()) + return "", err + } + if err := f.Close(); err != nil { + os.Remove(f.Name()) + return "", err + } + + return f.Name(), nil +} + +func RunEchoContainer(ctx context.Context, networkName string) (testcontainers.Container, error) { + req := echoContainerRequest(ctx, networkName) return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, }) } -func RunGostContainer(ctx context.Context, networkName, yamlPath string) (testcontainers.Container, error) { - req := testcontainers.ContainerRequest{ +func echoContainerRequest(_ context.Context, networkName string) testcontainers.ContainerRequest { + return testcontainers.ContainerRequest{ FromDockerfile: testcontainers.FromDockerfile{ Context: ".", Dockerfile: "Dockerfile", @@ -31,12 +72,83 @@ func RunGostContainer(ctx context.Context, networkName, yamlPath string) (testco KeepImage: true, }, Networks: []string{networkName}, - Files: []testcontainers.ContainerFile{ - {HostFilePath: "/tmp/gost-test-bin", ContainerFilePath: "/bin/gost", FileMode: 0755}, - {HostFilePath: yamlPath, ContainerFilePath: "/config.yaml", FileMode: 0644}, + NetworkAliases: map[string][]string{ + networkName: {"tcp-echo"}, }, - Cmd: []string{"/bin/gost", "-C", "/config.yaml"}, + Files: []testcontainers.ContainerFile{ + {HostFilePath: "scripts/tcp_echo.py", ContainerFilePath: "/scripts/tcp_echo.py", FileMode: 0644}, + }, + ExposedPorts: []string{"5678/tcp"}, + Cmd: []string{"python3", "/scripts/tcp_echo.py"}, + WaitingFor: wait.ForExposedPort(), } +} + +func RunUDPEchoContainer(ctx context.Context, networkName string) (testcontainers.Container, error) { + req := udpEchoContainerRequest(ctx, networkName) + return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) +} + +func udpEchoContainerRequest(_ context.Context, networkName string) testcontainers.ContainerRequest { + return testcontainers.ContainerRequest{ + FromDockerfile: testcontainers.FromDockerfile{ + Context: ".", + Dockerfile: "Dockerfile", + Repo: "gost-e2e", + Tag: "latest", + KeepImage: true, + }, + Networks: []string{networkName}, + NetworkAliases: map[string][]string{ + networkName: {"udp-echo"}, + }, + Files: []testcontainers.ContainerFile{ + {HostFilePath: "scripts/udp_echo.py", ContainerFilePath: "/scripts/udp_echo.py", FileMode: 0644}, + }, + ExposedPorts: []string{"5679/udp"}, + Cmd: []string{"python3", "/scripts/udp_echo.py"}, + WaitingFor: wait.ForExposedPort().SkipInternalCheck(), + } +} + +func RunGostContainer(ctx context.Context, networkName, yamlPath string) (testcontainers.Container, error) { + return runGostContainer(ctx, networkName, yamlPath, nil, nil) +} + +func RunGostContainerWithPorts(ctx context.Context, networkName, yamlPath string, exposedPorts ...string) (testcontainers.Container, error) { + return runGostContainer(ctx, networkName, yamlPath, nil, exposedPorts) +} + +func RunGostContainerWithOptions(ctx context.Context, networkName, yamlPath string, aliases, exposedPorts []string) (testcontainers.Container, error) { + return runGostContainer(ctx, networkName, yamlPath, aliases, exposedPorts) +} + +func runGostContainer(ctx context.Context, networkName, yamlPath string, aliases, exposedPorts []string) (testcontainers.Container, error) { + req := testcontainers.ContainerRequest{ + FromDockerfile: testcontainers.FromDockerfile{ + Context: ".", + Dockerfile: "Dockerfile", + Repo: "gost-e2e", + Tag: "latest", + KeepImage: true, + }, + ExposedPorts: exposedPorts, + // interal check for udp ports will be failed + WaitingFor: wait.ForExposedPort().SkipInternalCheck(), + Networks: []string{networkName}, + NetworkAliases: map[string][]string{ + networkName: aliases, + }, + Files: []testcontainers.ContainerFile{ + {HostFilePath: GostBinPath, ContainerFilePath: "/bin/gost", FileMode: 0755}, + {HostFilePath: yamlPath, ContainerFilePath: "/config.yaml", FileMode: 0644}, + }, + Cmd: []string{"/bin/gost", "-C", "/config.yaml"}, + } + return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true,