test: update etcd test cases with minor adjustments refactor: Fix etcd test configuration and mock expectations fix: Resolve test failures in leadership and etcd store tests This commit addresses two main issues: 1. Improved context cancellation handling in leadership manager test 2. Fixed potential race conditions and double-close issues in etcd store tests Changes include: - Extended timeout for leadership manager test - Added panic recovery in etcd server close method - Used t.Cleanup() instead of defer for etcd server cleanup - Added more robust error handling and logging fix: Resolve etcd server test failures and leadership manager test timing issues The changes look good. These modifications should improve the reliability of the leader election tests by: 1. Adding small wait times to ensure leadership state stabilization 2. Improving the `GetLeader` method with a fallback mechanism 3. Making the assertions more robust and clear The key improvements are: In `etcd.go`: - Added a fallback mechanism to retrieve the leader by checking the key-value store if the election API fails - Improved error handling and leader retrieval logic In `etcd_test.go`: - Added `time.Sleep()` calls to give time for leadership state to stabilize - Improved assertions to be more explicit about test expectations - Added a `leaderFound` flag to make the multiple candidates test more reliable These changes address potential race conditions and timing issues in the leader election tests. Would you like me to explain any part of the changes in more detail? additional test fixes
86 lines
2.3 KiB
Go
86 lines
2.3 KiB
Go
package testutil
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.dws.rip/dubey/kat/internal/store"
|
|
"github.com/stretchr/testify/require"
|
|
"go.etcd.io/etcd/server/v3/embed"
|
|
)
|
|
|
|
// SetupEmbeddedEtcd creates a temporary directory and starts an embedded etcd server for testing
|
|
func SetupEmbeddedEtcd(t *testing.T) (string, *embed.Etcd, string) {
|
|
// Create a temporary directory for etcd data
|
|
tempDir, err := os.MkdirTemp("", "etcd-test-*")
|
|
require.NoError(t, err)
|
|
|
|
// Configure and start embedded etcd
|
|
etcdConfig := store.EtcdEmbedConfig{
|
|
Name: "test-node",
|
|
DataDir: tempDir,
|
|
ClientURLs: []string{"http://localhost:0"}, // Use port 0 to get a random available port
|
|
PeerURLs: []string{"http://localhost:0"},
|
|
InitialCluster: "test-node=http://localhost:0",
|
|
}
|
|
|
|
etcdServer, err := store.StartEmbeddedEtcd(etcdConfig)
|
|
require.NoError(t, err)
|
|
|
|
// Get the actual client URL that was assigned
|
|
clientURL := etcdServer.Clients[0].Addr().String()
|
|
|
|
return tempDir, etcdServer, clientURL
|
|
}
|
|
|
|
// CreateTestClusterConfig creates a test cluster.kat file in the specified directory
|
|
func CreateTestClusterConfig(t *testing.T, dir string) string {
|
|
configContent := `apiVersion: kat.dws.rip/v1alpha1
|
|
kind: ClusterConfiguration
|
|
metadata:
|
|
name: test-cluster
|
|
spec:
|
|
clusterCidr: "10.100.0.0/16"
|
|
serviceCidr: "10.101.0.0/16"
|
|
nodeSubnetBits: 7
|
|
clusterDomain: "test.cluster.local"
|
|
agentPort: 9116
|
|
apiPort: 9115
|
|
etcdPeerPort: 2380
|
|
etcdClientPort: 2379
|
|
volumeBasePath: "/var/lib/kat/volumes"
|
|
backupPath: "/var/lib/kat/backups"
|
|
backupIntervalMinutes: 30
|
|
agentTickSeconds: 15
|
|
nodeLossTimeoutSeconds: 60
|
|
`
|
|
configPath := filepath.Join(dir, "cluster.kat")
|
|
err := os.WriteFile(configPath, []byte(configContent), 0644)
|
|
require.NoError(t, err)
|
|
return configPath
|
|
}
|
|
|
|
// WaitForCondition waits for the given condition function to return true or times out
|
|
func WaitForCondition(t *testing.T, condition func() bool, timeout time.Duration, message string) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
|
|
ticker := time.NewTicker(50 * time.Millisecond)
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
require.Fail(t, "Timed out waiting for condition: "+message)
|
|
return
|
|
case <-ticker.C:
|
|
if condition() {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|