arblant
firefox-vpn-client / core / internal / service / netwait_test.go
netwait_test.go64 lines · 1.8 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
package service

import (
	"net/http"
	"sync/atomic"
	"testing"
	"time"
)

func waitMessage(t *testing.T, d *Daemon, phase, message string) {
	t.Helper()
	deadline := time.Now().Add(5 * time.Second)
	for time.Now().Before(deadline) {
		d.mu.Lock()
		state := d.state
		d.mu.Unlock()
		if state.Phase == phase && state.Message == message {
			return
		}
		time.Sleep(20 * time.Millisecond)
	}
	d.mu.Lock()
	defer d.mu.Unlock()
	t.Fatalf("state %q %q, want %q %q", d.state.Phase, d.state.Message, phase, message)
}

func setNetwork(t *testing.T) *atomic.Bool {
	t.Helper()
	var online atomic.Bool
	oldConnected, oldPoll := networkConnected, networkPoll
	networkConnected, networkPoll = online.Load, 10*time.Millisecond
	t.Cleanup(func() { networkConnected, networkPoll = oldConnected, oldPoll })
	return &online
}

// Without a network the start waits and sends nothing; it starts as soon
// as a network connects. With no account, a start ends in "Add an
// account", which shows that it ran.
func TestEngineWaitsForNetwork(t *testing.T) {
	online := setNetwork(t)
	d := newTestDaemon(t)
	d.mu.Lock()
	d.cfg.Dashboard.Listen = "127.0.0.1:0"
	d.mu.Unlock()
	done := make(chan error, 1)
	go func() { done <- d.Run() }()
	defer func() {
		d.Shutdown()
		<-done
	}()
	waitMessage(t, d, PhaseWaiting, MessageWaitingForNetwork)
	time.Sleep(50 * time.Millisecond)
	waitMessage(t, d, PhaseWaiting, MessageWaitingForNetwork)

	// A restart request ends the wait, and the next start waits again.
	client := newDashboardClient(t, d)
	if rec := client.do(http.MethodPost, "/api/proxy/restart", nil); rec.Code != http.StatusOK {
		t.Fatalf("restart: %d", rec.Code)
	}
	waitMessage(t, d, PhaseWaiting, MessageWaitingForNetwork)

	online.Store(true)
	waitMessage(t, d, PhaseWaiting, "Add an account in the dashboard to start the proxy")
}