testsuite/ui/uitest: separate func for browser

The code will be clearer if the browser starting is entirely separate
from the testplanet and edge setup.

Change-Id: I6d26aa25f4c2a929ba4eda1388234e8aeec518c7
This commit is contained in:
Egon Elbre 2021-10-12 16:20:23 +03:00
parent 1fdb0eaa5b
commit aa858a3a23
2 changed files with 146 additions and 126 deletions

View File

@ -0,0 +1,143 @@
// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
package uitest
import (
"context"
"fmt"
"net"
"os"
"testing"
"time"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/defaults"
"github.com/go-rod/rod/lib/launcher"
"github.com/go-rod/rod/lib/launcher/flags"
"github.com/go-rod/rod/lib/utils"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
"storj.io/common/testcontext"
)
// Our testing suite heavily uses randomly selected ports, which may collide
// with the launcher lock port. We'll disable the lock port entirely for
// the time being.
func init() { defaults.LockPort = 0 }
// Browser starts a browser for testing using environment variables for configuration.
func Browser(t *testing.T, ctx *testcontext.Context, fn func(*rod.Browser)) {
showBrowser := os.Getenv("STORJ_TEST_SHOW_BROWSER") != ""
slowBrowser := os.Getenv("STORJ_TEST_SHOW_BROWSER") == "slow"
logLauncher := zaptest.NewLogger(t).Named("launcher")
browserLoaded := browserTimeoutDetector(10 * time.Second)
defer browserLoaded()
launch := launcher.New().
Headless(!showBrowser).
Leakless(false).
Devtools(false).
NoSandbox(true).
UserDataDir(ctx.Dir("browser")).
Logger(zapWriter{Logger: logLauncher}).
Set("enable-logging").
Set("disable-gpu")
if browserHost := os.Getenv("STORJ_TEST_BROWER_HOSTPORT"); browserHost != "" {
host, port, err := net.SplitHostPort(browserHost)
require.NoError(t, err)
launch = launch.Set("remote-debugging-address", host).Set(flags.RemoteDebuggingPort, port)
}
if browserBin := os.Getenv("STORJ_TEST_BROWSER"); browserBin != "" {
launch = launch.Bin(browserBin)
}
defer func() {
launch.Kill()
avoidStall(3*time.Second, launch.Cleanup)
}()
url, err := launch.Launch()
require.NoError(t, err)
logBrowser := zaptest.NewLogger(t).Named("rod")
browser := rod.New().
Timeout(time.Minute).
Sleeper(func() utils.Sleeper { return timeoutSleeper(5*time.Second, 5) }).
ControlURL(url).
Logger(utils.Log(func(msg ...interface{}) {
logBrowser.Info(fmt.Sprintln(msg...))
})).
Context(ctx).
WithPanic(func(v interface{}) { require.Fail(t, "check failed", v) })
if slowBrowser {
browser = browser.SlowMotion(300 * time.Millisecond).Trace(true)
}
defer ctx.Check(browser.Close)
require.NoError(t, browser.Connect())
browserLoaded()
fn(browser)
}
func browserTimeoutDetector(duration time.Duration) context.CancelFunc {
ctx, cancel := context.WithCancel(context.Background())
go func() {
t := time.NewTimer(duration)
defer t.Stop()
select {
case <-t.C:
panic("timeout for starting browser exceeded")
case <-ctx.Done():
return
}
}()
return cancel
}
func timeoutSleeper(totalSleep time.Duration, maxTries int) utils.Sleeper {
singleSleep := totalSleep / time.Duration(maxTries)
var slept int
return func(ctx context.Context) error {
slept++
if slept > maxTries {
return &utils.ErrMaxSleepCount{Max: maxTries}
}
t := time.NewTimer(singleSleep)
defer t.Stop()
select {
case <-t.C:
case <-ctx.Done():
}
return nil
}
}
func avoidStall(maxDuration time.Duration, fn func()) {
done := make(chan struct{})
go func() {
fn()
close(done)
}()
timeout := time.NewTicker(maxDuration)
defer timeout.Stop()
select {
case <-done:
case <-timeout.C:
fmt.Printf("go-rod did not shutdown within %v\n", maxDuration)
}
}

View File

@ -4,32 +4,17 @@
package uitest
import (
"context"
"fmt"
"net"
"os"
"testing"
"time"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/defaults"
"github.com/go-rod/rod/lib/launcher"
"github.com/go-rod/rod/lib/launcher/flags"
"github.com/go-rod/rod/lib/utils"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
"storj.io/common/testcontext"
"storj.io/storj/private/testplanet"
"storj.io/storj/satellite"
)
// Our testing suite heavily uses randomly selected ports, which may collide
// with the launcher lock port. We'll disable the lock port entirely for
// the time being.
func init() { defaults.LockPort = 0 }
// Test defines common services for uitests.
type Test func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet, browser *rod.Browser)
@ -56,116 +41,8 @@ func Run(t *testing.T, test Test) {
},
NonParallel: true,
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
showBrowser := os.Getenv("STORJ_TEST_SHOW_BROWSER") != ""
slowBrowser := os.Getenv("STORJ_TEST_SHOW_BROWSER") == "slow"
logLauncher := zaptest.NewLogger(t).Named("launcher")
browserLoaded := browserTimeoutDetector(10 * time.Second)
defer browserLoaded()
launch := launcher.New().
Headless(!showBrowser).
Leakless(false).
Devtools(false).
NoSandbox(true).
UserDataDir(ctx.Dir("browser")).
Logger(zapWriter{Logger: logLauncher}).
Set("enable-logging").
Set("disable-gpu")
if browserHost := os.Getenv("STORJ_TEST_BROWER_HOSTPORT"); browserHost != "" {
host, port, err := net.SplitHostPort(browserHost)
require.NoError(t, err)
launch = launch.Set("remote-debugging-address", host).Set(flags.RemoteDebuggingPort, port)
}
if browserBin := os.Getenv("STORJ_TEST_BROWSER"); browserBin != "" {
launch = launch.Bin(browserBin)
}
defer func() {
launch.Kill()
avoidStall(3*time.Second, launch.Cleanup)
}()
url, err := launch.Launch()
require.NoError(t, err)
logBrowser := zaptest.NewLogger(t).Named("rod")
browser := rod.New().
Timeout(time.Minute).
Sleeper(func() utils.Sleeper { return timeoutSleeper(5*time.Second, 5) }).
ControlURL(url).
Logger(utils.Log(func(msg ...interface{}) {
logBrowser.Info(fmt.Sprintln(msg...))
})).
Context(ctx).
WithPanic(func(v interface{}) { require.Fail(t, "check failed", v) })
if slowBrowser {
browser = browser.SlowMotion(300 * time.Millisecond).Trace(true)
}
defer ctx.Check(browser.Close)
require.NoError(t, browser.Connect())
browserLoaded()
test(t, ctx, planet, browser)
Browser(t, ctx, func(browser *rod.Browser) {
test(t, ctx, planet, browser)
})
})
}
func browserTimeoutDetector(duration time.Duration) context.CancelFunc {
ctx, cancel := context.WithCancel(context.Background())
go func() {
t := time.NewTimer(duration)
defer t.Stop()
select {
case <-t.C:
panic("timeout for starting browser exceeded")
case <-ctx.Done():
return
}
}()
return cancel
}
func timeoutSleeper(totalSleep time.Duration, maxTries int) utils.Sleeper {
singleSleep := totalSleep / time.Duration(maxTries)
var slept int
return func(ctx context.Context) error {
slept++
if slept > maxTries {
return &utils.ErrMaxSleepCount{Max: maxTries}
}
t := time.NewTimer(singleSleep)
defer t.Stop()
select {
case <-t.C:
case <-ctx.Done():
}
return nil
}
}
func avoidStall(maxDuration time.Duration, fn func()) {
done := make(chan struct{})
go func() {
fn()
close(done)
}()
timeout := time.NewTicker(maxDuration)
defer timeout.Stop()
select {
case <-done:
case <-timeout.C:
fmt.Printf("go-rod did not shutdown within %v\n", maxDuration)
}
}