testsuite/ui/uitest: add Edge testing

Change-Id: I1e592ac755b582d4fa73e95fd999a35a27f8a116
This commit is contained in:
Egon Elbre 2021-10-14 14:27:03 +03:00
parent 96dc43fd49
commit 52c950e429
9 changed files with 793 additions and 8 deletions

View File

@ -359,6 +359,7 @@ pipeline {
STORJ_TEST_POSTGRES = 'postgres://postgres@localhost/testui?sslmode=disable'
STORJ_TEST_BROWSER = '/usr/bin/chromium'
STORJ_TEST_SATELLITE_WEB = "${pwd()}/web/satellite"
STORJ_TEST_EDGE_HOST = '127.0.0.10'
}
steps {
sh 'psql -U postgres -c \'create database testui;\''

View File

@ -79,7 +79,7 @@ type Config struct {
PartneredSatellites SatList `help:"names and addresses of partnered satellites in JSON list format" default:"[[\"US1\",\"https://us1.storj.io\"],[\"EU1\",\"https://eu1.storj.io\"],[\"AP1\",\"https://ap1.storj.io\"]]"`
GeneralRequestURL string `help:"url link to general request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000379291"`
ProjectLimitsIncreaseRequestURL string `help:"url link to project limit increase request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000683212"`
GatewayCredentialsRequestURL string `help:"url link for gateway credentials requests" default:"https://auth.us1.storjshare.io"`
GatewayCredentialsRequestURL string `help:"url link for gateway credentials requests" default:"https://auth.us1.storjshare.io" devDefault:""`
IsBetaSatellite bool `help:"indicates if satellite is in beta" default:"false"`
BetaSatelliteFeedbackURL string `help:"url link for for beta satellite feedback" default:""`
BetaSatelliteSupportURL string `help:"url link for for beta satellite support" default:""`

View File

@ -6,8 +6,12 @@ replace storj.io/storj => ../
require (
github.com/go-rod/rod v0.101.8
github.com/spacemonkeygo/monkit/v3 v3.0.15
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
go.uber.org/zap v1.17.0
storj.io/common v0.0.0-20211011135704-cbe49e9e173e
storj.io/gateway-mt v1.14.4-0.20211015103214-01eddbc864fb
storj.io/private v0.0.0-20210810102517-434aeab3f17d
storj.io/storj v0.12.1-0.20210916114455-b2d724962c24
)

File diff suppressed because it is too large Load Diff

View File

@ -45,7 +45,8 @@ func Browser(t *testing.T, ctx *testcontext.Context, fn func(*rod.Browser)) {
UserDataDir(ctx.Dir("browser")).
Logger(zapWriter{Logger: logLauncher}).
Set("enable-logging").
Set("disable-gpu")
Set("disable-gpu").
Set("disable-web-security") // TODO: ensure we have proper CORS for testing
if browserHost := os.Getenv("STORJ_TEST_BROWER_HOSTPORT"); browserHost != "" {
host, port, err := net.SplitHostPort(browserHost)

187
testsuite/ui/uitest/edge.go Normal file
View File

@ -0,0 +1,187 @@
// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
package uitest
import (
"context"
"crypto/rand"
"encoding/binary"
"fmt"
"net"
"net/url"
"os"
"strconv"
"testing"
"time"
"github.com/go-rod/rod"
"github.com/spf13/pflag"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
"storj.io/common/sync2"
"storj.io/common/testcontext"
"storj.io/gateway-mt/auth"
"storj.io/gateway-mt/pkg/authclient"
"storj.io/gateway-mt/pkg/server"
"storj.io/gateway-mt/pkg/trustedip"
"storj.io/private/cfgstruct"
"storj.io/storj/cmd/uplink/cmd"
"storj.io/storj/private/testplanet"
"storj.io/storj/satellite"
)
// EdgePlanet contains defaults for testplanet with Edge.
type EdgePlanet struct {
*testplanet.Planet
Gateway struct {
AccessKey string
SecretKey string
Addr string
}
Auth struct {
Addr string
}
}
// EdgeTest defines common args for edge testing.
type EdgeTest func(t *testing.T, ctx *testcontext.Context, planet *EdgePlanet, browser *rod.Browser)
// Edge starts a testplanet together with auth service and gateway.
func Edge(t *testing.T, test EdgeTest) {
edgehost := os.Getenv("STORJ_TEST_EDGE_HOST")
if edgehost == "" {
edgehost = "127.0.0.1"
}
// TODO: make address not hardcoded the address selection here may
// conflict with some automatically bound address.
authSvcAddr := net.JoinHostPort(edgehost, strconv.Itoa(randomRange(20000, 40000)))
authSvcAddrTLS := net.JoinHostPort(edgehost, strconv.Itoa(randomRange(20000, 40000)))
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1, StorageNodeCount: 4, UplinkCount: 1,
Reconfigure: testplanet.Reconfigure{
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
if dir := os.Getenv("STORJ_TEST_SATELLITE_WEB"); dir != "" {
config.Console.StaticDir = dir
}
config.Console.NewOnboarding = true
// TODO: this should be dynamically set from the auth service
config.Console.GatewayCredentialsRequestURL = "http://" + authSvcAddr
},
},
NonParallel: true, // Note, do not remove this, because the code above uses same auth service addr.
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
access := planet.Uplinks[0].Access[planet.Satellites[0].ID()]
gwConfig := server.Config{}
cfgstruct.Bind(&pflag.FlagSet{}, &gwConfig, cfgstruct.UseTestDefaults())
gwConfig.Server.Address = "127.0.0.1:0"
gwConfig.AuthURL = "http://" + authSvcAddr
gwConfig.InsecureLogAll = true
authURL, err := url.Parse("http://" + authSvcAddr)
require.NoError(t, err)
authClient, err := authclient.New(authURL, "super-secret", 5*time.Minute)
require.NoError(t, err)
gateway, err := server.New(gwConfig, zaptest.NewLogger(t).Named("gateway"), nil, trustedip.NewListTrustAll(), []string{}, authClient)
require.NoError(t, err)
defer ctx.Check(gateway.Close)
authConfig := auth.Config{
Endpoint: "http://" + gateway.Address(),
AuthToken: "super-secret",
KVBackend: "memory://",
ListenAddr: authSvcAddr,
ListenAddrTLS: authSvcAddrTLS,
}
for _, sat := range planet.Satellites {
authConfig.AllowedSatellites = append(authConfig.AllowedSatellites, sat.NodeURL().String())
}
auth, err := auth.New(ctx, zaptest.NewLogger(t).Named("auth"), authConfig, ctx.Dir("authservice"))
require.NoError(t, err)
defer ctx.Check(auth.Close)
ctx.Go(func() error { return auth.Run(ctx) })
require.NoError(t, waitForAddress(ctx, authSvcAddr, 3*time.Second))
ctx.Go(gateway.Run)
require.NoError(t, waitForAddress(ctx, gateway.Address(), 3*time.Second))
// todo: use the unused endpoint below
accessKey, secretKey, _, err := cmd.RegisterAccess(ctx, access, "http://"+authSvcAddr, false, 15*time.Second)
require.NoError(t, err)
edge := &EdgePlanet{}
edge.Planet = planet
edge.Gateway.AccessKey = accessKey
edge.Gateway.SecretKey = secretKey
edge.Gateway.Addr = gateway.Address()
edge.Auth.Addr = authSvcAddr
Browser(t, ctx, func(browser *rod.Browser) {
test(t, ctx, edge, browser)
})
})
}
func randomRange(low, high int) int {
// this generates biased crypt random numbers
// but it uses crypt/rand to avoid potentially
// someone seeding math/rand.
span := high - low
return low + int(randomUint64()&0x7FFF_FFFF)%span
}
func randomUint64() uint64 {
var value [8]byte
if _, err := rand.Read(value[:]); err != nil {
panic(err)
}
return binary.LittleEndian.Uint64(value[:])
}
// waitForAddress will monitor starting when we are able to start the process.
func waitForAddress(ctx context.Context, address string, maxStartupWait time.Duration) error {
defer mon.Task()(&ctx)(nil)
start := time.Now()
for time.Since(start) < maxStartupWait {
if tryConnect(ctx, address) {
return ctx.Err()
}
// wait a bit before retrying to reduce load
if !sync2.Sleep(ctx, 50*time.Millisecond) {
return ctx.Err()
}
}
return fmt.Errorf("did not start in required time %v", maxStartupWait)
}
// tryConnect will try to connect to the process public address.
func tryConnect(ctx context.Context, address string) bool {
defer mon.Task()(&ctx)(nil)
dialer := net.Dialer{}
conn, err := dialer.DialContext(ctx, "tcp", address)
if err != nil {
return false
}
// write empty byte slice to trigger refresh on connection
_, _ = conn.Write([]byte{})
// ignoring errors, because we only care about being able to connect
_ = conn.Close()
return true
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
package uitest_test
import (
"testing"
"github.com/go-rod/rod"
"storj.io/common/testcontext"
"storj.io/storj/testsuite/ui/uitest"
)
func TestEdge(t *testing.T) {
uitest.Edge(t, func(t *testing.T, ctx *testcontext.Context, planet *uitest.EdgePlanet, browser *rod.Browser) {
t.Log("working")
})
}

View File

@ -8,6 +8,7 @@ import (
"testing"
"github.com/go-rod/rod"
"github.com/spacemonkeygo/monkit/v3"
"go.uber.org/zap"
"storj.io/common/testcontext"
@ -15,6 +16,8 @@ import (
"storj.io/storj/satellite"
)
var mon = monkit.Package()
// Test defines common services for uitests.
type Test func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet, browser *rod.Browser)

View File

@ -49,7 +49,11 @@ export class ObjectsState {
public apiKey = '';
public accessGrant = '';
public gatewayCredentials: GatewayCredentials = new GatewayCredentials();
public s3Client: S3 = new S3({});
public s3Client: S3 = new S3({
s3ForcePathStyle: true,
signatureVersion: "v4",
httpOptions: { timeout: 0 },
});
public bucketsList: Bucket[] = [];
public passphrase = '';
public fileComponentBucketName = '';
@ -88,6 +92,9 @@ export function makeObjectsModule(): StoreModule<ObjectsState, ObjectsContext> {
accessKeyId: state.gatewayCredentials.accessKeyId,
secretAccessKey: state.gatewayCredentials.secretKey,
endpoint: state.gatewayCredentials.endpoint,
s3ForcePathStyle: true,
signatureVersion: "v4",
httpOptions: { timeout: 0 },
};
state.s3Client = new S3(s3Config);
@ -109,7 +116,11 @@ export function makeObjectsModule(): StoreModule<ObjectsState, ObjectsContext> {
state.passphrase = '';
state.accessGrant = '';
state.gatewayCredentials = new GatewayCredentials();
state.s3Client = new S3({});
state.s3Client = new S3({
s3ForcePathStyle: true,
signatureVersion: "v4",
httpOptions: { timeout: 0 },
});
state.bucketsList = [];
state.fileComponentBucketName = '';
},