mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-02 11:39:06 +02:00
Merge branch 'main' into profile-ownership
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package profilemanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Regression test: a concurrent Get and Set of the ActiveProfileState will
|
||||
// fail on Windows since the write is a temp file renamed over an open file.
|
||||
// Windows will refuse to replace a file another handle holds open by default.
|
||||
func TestActiveProfileState_ReadsDoNotBreakAConcurrentWrite(t *testing.T) {
|
||||
withTempConfigDir(t, func(configDir string) {
|
||||
withPatchedGlobals(t, configDir, func() {
|
||||
sm := &ServiceManager{}
|
||||
require.NoError(t, sm.CreateDefaultProfile())
|
||||
require.NoError(t, sm.SetActiveProfileStateToDefault())
|
||||
|
||||
const switched = ID("0123456789abcdef0123456789abcdef")
|
||||
const rounds = 50
|
||||
|
||||
var wg sync.WaitGroup
|
||||
errs := make(chan error, 128)
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for r := 0; r < rounds; r++ {
|
||||
state, err := sm.GetActiveProfileState()
|
||||
if err != nil {
|
||||
errs <- fmt.Errorf("read: %w", err)
|
||||
return
|
||||
}
|
||||
if state.ID != defaultProfileName && state.ID != switched {
|
||||
errs <- fmt.Errorf("read: active profile is %q, which no writer wrote", state.ID)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for r := 0; r < rounds; r++ {
|
||||
id := switched
|
||||
if r%2 == 0 {
|
||||
id = defaultProfileName
|
||||
}
|
||||
if err := sm.SetActiveProfileState(&ActiveProfileState{ID: id, Username: "testuser"}); err != nil {
|
||||
errs <- fmt.Errorf("switch: %w", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(errs)
|
||||
|
||||
for err := range errs {
|
||||
assert.NoError(t, err, "a switch and a read of the active profile state must not collide")
|
||||
}
|
||||
|
||||
state, err := sm.GetActiveProfileState()
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, []ID{defaultProfileName, switched}, state.ID,
|
||||
"the file holds whichever switch landed last, not a mix of the two")
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user