Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the bug #6022 #6075

Merged
merged 5 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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