Skip to content

chore(test): add tests to memory store #2226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ envtest:
.PHONY: unit-tests
unit-tests: envtest
KUBEBUILDER_ASSETS="$(shell ./operator/bin/setup-envtest use $(ENVTEST_K8S_VERSION) --bin-dir $(shell pwd)/operator/bin -p path)" \
go test -tags $(GO_BUILD_TAGS) -v ./pkg/... ./cmd/... ./web/... ./pkg-new/...
go test -race -tags $(GO_BUILD_TAGS) -v ./pkg/... ./cmd/... ./web/... ./pkg-new/...
$(MAKE) -C api unit-tests
$(MAKE) -C operator test
$(MAKE) -C utils unit-tests
Expand Down
2 changes: 1 addition & 1 deletion api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ swag:

.PHONY: unit-tests
unit-tests:
go test -tags $(GO_BUILD_TAGS) -v ./...
go test -race -tags $(GO_BUILD_TAGS) -v ./...
6 changes: 5 additions & 1 deletion api/integration/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,11 +794,15 @@ func TestSetInstallStatus(t *testing.T) {
func TestInstallWithAPIClient(t *testing.T) {
password := "test-password"

// Create a runtimeconfig to be used in the install process
rc := runtimeconfig.New(nil)

Comment on lines +797 to +799
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to use the same runtime config for both manager and controller.

// Create a config manager
installationManager := installation.NewInstallationManager()
installationManager := installation.NewInstallationManager(installation.WithRuntimeConfig(rc))

// Create an install controller with the config manager
installController, err := install.NewInstallController(
install.WithRuntimeConfig(rc),
install.WithInstallationManager(installationManager),
)
require.NoError(t, err)
Expand Down
167 changes: 167 additions & 0 deletions api/internal/managers/installation/store_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package installation

import (
"sync"
"testing"

"github.com/replicatedhq/embedded-cluster/api/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNewMemoryStore(t *testing.T) {
inst := types.NewInstallation()
store := NewMemoryStore(inst)

assert.NotNil(t, store)
assert.NotNil(t, store.installation)
assert.Equal(t, inst, store.installation)
}

func TestMemoryStore_GetConfig(t *testing.T) {
inst := &types.Installation{
Config: &types.InstallationConfig{
AdminConsolePort: 8080,
DataDirectory: "/some/dir",
},
}
store := NewMemoryStore(inst)

config, err := store.GetConfig()

require.NoError(t, err)
assert.NotNil(t, config)
assert.Equal(t, &types.InstallationConfig{
AdminConsolePort: 8080,
DataDirectory: "/some/dir",
}, config)
}

func TestMemoryStore_SetConfig(t *testing.T) {
inst := &types.Installation{
Config: &types.InstallationConfig{
AdminConsolePort: 1000,
DataDirectory: "/a/different/dir",
},
}
store := NewMemoryStore(inst)
expectedConfig := types.InstallationConfig{
AdminConsolePort: 8080,
DataDirectory: "/some/dir",
}

err := store.SetConfig(expectedConfig)

require.NoError(t, err)

// Verify the config was stored
actualConfig, err := store.GetConfig()
require.NoError(t, err)
assert.Equal(t, &expectedConfig, actualConfig)
}

func TestMemoryStore_GetStatus(t *testing.T) {
inst := &types.Installation{
Status: &types.Status{
State: "failed",
Description: "Failure",
},
}
store := NewMemoryStore(inst)

status, err := store.GetStatus()

require.NoError(t, err)
assert.NotNil(t, status)
assert.Equal(t, &types.Status{
State: "failed",
Description: "Failure",
}, status)
}
func TestMemoryStore_SetStatus(t *testing.T) {
inst := &types.Installation{
Status: &types.Status{
State: "failed",
Description: "Failure",
},
}
store := NewMemoryStore(inst)
expectedStatus := types.Status{
State: "running",
Description: "Running",
}

err := store.SetStatus(expectedStatus)

require.NoError(t, err)

// Verify the status was stored
actualStatus, err := store.GetStatus()
require.NoError(t, err)
assert.Equal(t, &expectedStatus, actualStatus)
}

// Useful to test concurrent access with -race flag
func TestMemoryStore_ConcurrentAccess(t *testing.T) {
inst := types.NewInstallation()
store := NewMemoryStore(inst)
var wg sync.WaitGroup

// Test concurrent reads and writes
numGoroutines := 10
numOperations := 50

// Concurrent config operations
wg.Add(numGoroutines * 2)
for i := 0; i < numGoroutines; i++ {
// Concurrent writes
go func(id int) {
defer wg.Done()
for j := 0; j < numOperations; j++ {
config := types.InstallationConfig{
LocalArtifactMirrorPort: 8080,
DataDirectory: "/some/other/dir",
}
err := store.SetConfig(config)
assert.NoError(t, err)
}
}(i)

// Concurrent reads
go func(id int) {
defer wg.Done()
for j := 0; j < numOperations; j++ {
_, err := store.GetConfig()
assert.NoError(t, err)
}
}(i)
}

// Concurrent status operations
wg.Add(numGoroutines * 2)
for i := 0; i < numGoroutines; i++ {
// Concurrent writes
go func(id int) {
defer wg.Done()
for j := 0; j < numOperations; j++ {
status := types.Status{
State: "pending",
Description: "Pending",
}
err := store.SetStatus(status)
assert.NoError(t, err)
}
}(i)

// Concurrent reads
go func(id int) {
defer wg.Done()
for j := 0; j < numOperations; j++ {
_, err := store.GetStatus()
assert.NoError(t, err)
}
}(i)
}

wg.Wait()
}
7 changes: 4 additions & 3 deletions cmd/installer/cli/signal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"os"
"sync"
"sync/atomic"
"syscall"
"testing"
"time"
Expand Down Expand Up @@ -37,9 +38,9 @@ func Test_signalHandler_Signal(t *testing.T) {
originalOsExit := osExit
defer func() { osExit = originalOsExit }()

exitCode := 0
exitCode := int32(0)
osExit = func(code int) {
exitCode = code
atomic.StoreInt32(&exitCode, int32(code))
Comment on lines +41 to +43
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed to change this for got test -race.

// Instead of exiting, just cancel the context
cancel()
}
Expand Down Expand Up @@ -76,7 +77,7 @@ func Test_signalHandler_Signal(t *testing.T) {
// Verify cleanup was called with the expected error
assert.True(t, cleanupCalled, "Cleanup function should have been called")
assert.Equal(t, syscall.SIGINT, cleanupSignal, "Cleanup should be called with SIGINT")
assert.Equal(t, 1, exitCode, "Exit code should be 1")
assert.Equal(t, int32(1), atomic.LoadInt32(&exitCode), "Exit code should be 1")
}

func Test_signalHandler_ContextDone(t *testing.T) {
Expand Down
Loading