Skip to content

Commit

Permalink
testsuite/ui/uitest: separate func for browser
Browse files Browse the repository at this point in the history
The code will be clearer if the browser starting is entirely separate
from the testplanet and edge setup.

Change-Id: I6d26aa25f4c2a929ba4eda1388234e8aeec518c7
  • Loading branch information
egonelbre committed Oct 12, 2021
1 parent 1fdb0ea commit aa858a3
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 126 deletions.
143 changes: 143 additions & 0 deletions testsuite/ui/uitest/browser.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
129 changes: 3 additions & 126 deletions testsuite/ui/uitest/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
}
}

0 comments on commit aa858a3

Please sign in to comment.