Skip to content

Commit

Permalink
Merge pull request #6075 from mysteriumnetwork/diag/6022
Browse files Browse the repository at this point in the history
Fix the bug #6022
  • Loading branch information
Zensey authored Sep 10, 2024
2 parents 7337b84 + c4a6a29 commit 9967fae
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/tests-and-linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ jobs:
- name: E2E basic test
run: go run mage.go -v TestE2EBasic

- name: E2E shaper test
run: go run mage.go -v TestE2EShaper

e2e-nat:
runs-on: ubuntu-latest

Expand Down
36 changes: 36 additions & 0 deletions ci/test/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/magefile/mage/mg"
"github.com/magefile/mage/sh"
"github.com/mysteriumnetwork/node/e2e"
e2e_shaper "github.com/mysteriumnetwork/node/e2e/shaper"
"github.com/mysteriumnetwork/node/logconfig"
"github.com/rs/zerolog/log"
)
Expand All @@ -50,6 +51,23 @@ func BuildE2eTestBinary() error {
return os.Rename("./e2e.test", "./build/e2e/test")
}

// BuildE2eShaperTestBinary builds the e2e test binary.
func BuildE2eShaperTestBinary() error {
err := sh.RunWith(crossCompileFlags, "go", "test", "-c", "./e2e/shaper")
if err != nil {
return err
}
err = sh.RunWith(crossCompileFlags, "go", "build", "-o", "shaper.websvc", "./e2e/shaper/websvc")
if err != nil {
return err
}

_ = os.Mkdir("./build/e2e/", os.ModeDir)
os.Rename("./shaper.test", "./build/e2e/shaper.test")
os.Rename("./shaper.websvc", "./build/e2e/shaper.websvc")
return nil
}

// BuildE2eDeployerBinary builds the deployer binary for e2e tests.
func BuildE2eDeployerBinary() error {
return sh.RunWith(crossCompileFlags, "go", "build", "-o", "./build/e2e/deployer", "./e2e/blockchain/deployer.go")
Expand All @@ -75,6 +93,24 @@ func TestE2EBasic() error {
return runner.Test("myst-provider")
}

// TestE2EShaper runs end-to-end tests
func TestE2EShaper() error {
logconfig.Bootstrap()

mg.Deps(BuildE2eShaperTestBinary)

composeFiles := []string{
"./docker-compose.e2e-shaper.yml",
}

runner, cleanup := e2e_shaper.NewRunner(composeFiles, "node_e2e_shaper_test", "")
defer cleanup()
if err := runner.Init(); err != nil {
return err
}
return runner.Test()
}

// TestE2ENAT runs end-to-end tests in NAT environment
func TestE2ENAT() error {
logconfig.Bootstrap()
Expand Down
25 changes: 25 additions & 0 deletions docker-compose.e2e-shaper.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
version: '3.0'
services:

shaper-websvc:
build:
context: .
dockerfile: ./e2e/shaper/websvc/Dockerfile
cap_add:
- NET_ADMIN
working_dir: /node
expose:
- 8083

#go runner to run go programs inside localnet (usefull for contract deployment or e2e test running)
go-runner:
depends_on:
- shaper-websvc
build:
context: .
dockerfile: ./e2e/gorunner-shaper/Dockerfile.precompiled
cap_add:
- NET_ADMIN
volumes:
- ./e2e/blockchain/keystore:/node/keystore
working_dir: /node
3 changes: 3 additions & 0 deletions e2e/gorunner-shaper/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM golang:1.20-alpine

RUN apk add --no-cache bash gcc musl-dev make linux-headers iptables ipset ca-certificates openvpn bash sudo openresolv
6 changes: 6 additions & 0 deletions e2e/gorunner-shaper/Dockerfile.precompiled
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM alpine:3.12

RUN apk add --no-cache bash gcc musl-dev make linux-headers iptables ipset ca-certificates openvpn bash sudo openresolv
RUN ln -s /sbin/iptables /usr/sbin/iptables

COPY ./build/e2e/shaper.test /usr/local/bin/shaper.test
92 changes: 92 additions & 0 deletions e2e/shaper/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package shaper

import (
"github.com/magefile/mage/sh"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)

// NewRunner returns e2e test runners instance
func NewRunner(composeFiles []string, testEnv, services string) (runner *Runner, cleanup func()) {
fileArgs := make([]string, 0)
for _, f := range composeFiles {
fileArgs = append(fileArgs, "-f", f)
}
var args []string
args = append(args, fileArgs...)
args = append(args, "-p", testEnv)

runner = &Runner{
compose: sh.RunCmd("docker", append([]string{"compose"}, args...)...),
composeOut: sh.OutCmd("docker", append([]string{"compose"}, args...)...),
testEnv: testEnv,
services: services,
}
return runner, runner.cleanup
}

// Runner is e2e tests runner responsible for starting test environment and running e2e tests.
type Runner struct {
compose func(args ...string) error
composeOut func(args ...string) (string, error)
etherPassphrase string
testEnv string
services string
}

// Test starts given provider and consumer nodes and runs e2e tests.
func (r *Runner) Test() (retErr error) {
log.Info().Msg("Running tests for env: " + r.testEnv)

err := r.compose("run", "go-runner",
"/usr/local/bin/shaper.test",
)

retErr = errors.Wrap(err, "tests failed!")
return
}

func (r *Runner) cleanup() {
log.Info().Msg("Cleaning up")

_ = r.compose("logs")
if err := r.compose("down", "--volumes", "--remove-orphans", "--timeout", "30"); err != nil {
log.Warn().Err(err).Msg("Cleanup error")
}
}

// Init starts bug6022.test dependency
func (r *Runner) Init() error {
log.Info().Msg("Starting other services")
if err := r.compose("pull"); err != nil {
return errors.Wrap(err, "could not pull images")
}

if err := r.compose("up", "-d", "shaper-websvc"); err != nil {
return errors.Wrap(err, "starting other services failed!")
}

log.Info().Msg("Building app images")
if err := r.compose("build"); err != nil {
return errors.Wrap(err, "building app images failed!")
}

return nil
}
157 changes: 157 additions & 0 deletions e2e/shaper/shaper_service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* Copyright (C) 2024 The "MysteriumNetwork/node" Authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package shaper

import (
"bytes"
"encoding/hex"
"io"
"log"
"net"
"net/http"
"net/netip"
"net/url"
"strings"
"testing"

"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"

"github.com/mysteriumnetwork/node/config"
netstack "github.com/mysteriumnetwork/node/services/wireguard/endpoint/netstack"
netstack_provider "github.com/mysteriumnetwork/node/services/wireguard/endpoint/netstack-provider"
)

func startClient(t *testing.T, priv, pubServ wgtypes.Key) {
tun, tnet, err := netstack.CreateNetTUN(
[]netip.Addr{netip.MustParseAddr("192.168.4.100")},
[]netip.Addr{netip.MustParseAddr("8.8.8.8")},
device.DefaultMTU)
if err != nil {
t.Error(err)
return
}

dev := device.NewDevice(tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelError, "C> "))

wgConf := &bytes.Buffer{}
wgConf.WriteString("private_key=" + hex.EncodeToString(priv[:]) + "\n")
wgConf.WriteString("public_key=" + hex.EncodeToString(pubServ[:]) + "\n")
wgConf.WriteString("allowed_ip=0.0.0.0/0\n")
wgConf.WriteString("endpoint=127.0.0.1:58120\n")

if err = dev.IpcSetOperation(wgConf); err != nil {
t.Error(err)
return
}
if err = dev.Up(); err != nil {
t.Error(err)
return
}

client := http.Client{
Transport: &http.Transport{
DialContext: tnet.DialContext,
},
}

// resolve docker container hostname
u, _ := url.Parse("http://shaper-websvc:8083/test")
address, err := net.LookupHost(u.Hostname())
if err != nil {
t.Error(err)
return
}
u.Host = address[0] + ":" + u.Port()

resp, err := client.Get(u.String())
if err != nil {
t.Error(err)
log.Println(err)
return
}

body, err := io.ReadAll(resp.Body)
if err != nil {
t.Error(err)
log.Println(err)
return
}
log.Println("Reply:", string(body))

res := strings.HasPrefix(string(body), "Hello,")
ok := "success"
if !res {
ok = "failed"
}
log.Println("Test result:", ok)
}

func startServer(t *testing.T, privKey, pubClinet wgtypes.Key) {
tun, _, _, err := netstack_provider.CreateNetTUNWithStack(
[]netip.Addr{netip.MustParseAddr("192.168.4.1")},
53,
device.DefaultMTU,
)
if err != nil {
t.Error(err)
return
}
dev := device.NewDevice(tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelError, "S> "))

wgConf := &bytes.Buffer{}
wgConf.WriteString("private_key=" + hex.EncodeToString(privKey[:]) + "\n")
wgConf.WriteString("listen_port=58120\n")
wgConf.WriteString("public_key=" + hex.EncodeToString(pubClinet[:]) + "\n")
wgConf.WriteString("allowed_ip=0.0.0.0/0\n")

if err = dev.IpcSetOperation(wgConf); err != nil {
t.Error(err)
return
}
if err = dev.Up(); err != nil {
t.Error(err)
return
}
}

func TestShaperEnabled(t *testing.T) {
log.Default().SetFlags(0)

config.Current.SetDefault(config.FlagShaperBandwidth.Name, "6250")
config.Current.SetDefault(config.FlagShaperEnabled.Name, "true")
config.FlagFirewallProtectedNetworks.Value = "10.0.0.0/8,127.0.0.0/8" // 192.168.0.0/16,

netstack_provider.InitUserspaceShaper(nil)

privKey1, err := wgtypes.GeneratePrivateKey()
if err != nil {
t.Error(err)
return
}
privKey2, err := wgtypes.GeneratePrivateKey()
if err != nil {
t.Error(err)
return
}
_, _ = privKey1, privKey2

startServer(t, privKey1, privKey2.PublicKey())
startClient(t, privKey2, privKey1.PublicKey())
}
5 changes: 5 additions & 0 deletions e2e/shaper/websvc/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM alpine:3.12

COPY ./build/e2e/shaper.websvc /usr/local/bin/shaper.websvc

ENTRYPOINT ["/usr/local/bin/shaper.websvc"]
33 changes: 33 additions & 0 deletions e2e/shaper/websvc/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2024 The "MysteriumNetwork/node" Authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package main

import (
"fmt"
"net/http"
)

func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8083", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.URL.Path, r.RemoteAddr)
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
Loading

0 comments on commit 9967fae

Please sign in to comment.