Skip to content

Commit

Permalink
chore: improve tests (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
thevilledev authored Oct 28, 2024
1 parent 13fa08a commit edb451a
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 4 deletions.
191 changes: 191 additions & 0 deletions lease_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package gonsensus

import (
"testing"
"time"
)

func TestNewLease(t *testing.T) {
t.Parallel()

lease := NewLease()
if lease == nil {
t.Fatal("NewLease() returned nil")
}

// Check initial version is empty string
if v := lease.GetCurrentVersion(); v != "" {
t.Errorf("initial version = %q, want empty string", v)
}

// Check initial info is nil
if info := lease.GetLeaseInfo(); info != nil {
t.Errorf("initial info = %+v, want nil", info)
}
}

func TestLease_UpdateLease(t *testing.T) {
t.Parallel()

tests := []struct {
name string
info *LockInfo
wantInfo *LockInfo
}{
{
name: "update with valid info",
info: &LockInfo{
Node: "node1",
Version: "v1",
Timestamp: time.Now(),
Term: 1,
},
wantInfo: &LockInfo{
Node: "node1",
Version: "v1",
Timestamp: time.Now(),
Term: 1,
},
},
{
name: "update with nil observers",
info: &LockInfo{
Node: "node2",
Version: "v2",
Timestamp: time.Now(),
Term: 2,
Observers: nil,
},
wantInfo: &LockInfo{
Node: "node2",
Version: "v2",
Timestamp: time.Now(),
Term: 2,
Observers: nil,
},
},
{
name: "update with observers",
info: &LockInfo{
Node: "node3",
Version: "v3",
Timestamp: time.Now(),
Term: 3,
Observers: map[string]ObserverInfo{
"observer1": {
LastHeartbeat: time.Now(),
IsActive: true,
},
},
},
wantInfo: &LockInfo{
Node: "node3",
Version: "v3",
Timestamp: time.Now(),
Term: 3,
Observers: map[string]ObserverInfo{
"observer1": {
LastHeartbeat: time.Now(),
IsActive: true,
},
},
},
},
}

for _, testCase := range tests {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()

lease := NewLease()
lease.UpdateLease(testCase.info)

// Check version was updated
if got := lease.GetCurrentVersion(); got != testCase.info.Version {
t.Errorf("GetCurrentVersion() = %v, want %v", got, testCase.info.Version)
}

// Check info was updated
got := lease.GetLeaseInfo()
if got == nil {
t.Fatal("GetLeaseInfo() returned nil")
}

// Compare relevant fields
if got.Node != testCase.wantInfo.Node {
t.Errorf("Node = %v, want %v", got.Node, testCase.wantInfo.Node)
}

if got.Version != testCase.wantInfo.Version {
t.Errorf("Version = %v, want %v", got.Version, testCase.wantInfo.Version)
}

if got.Term != testCase.wantInfo.Term {
t.Errorf("Term = %v, want %v", got.Term, testCase.wantInfo.Term)
}

// Compare observers if present
if testCase.wantInfo.Observers != nil {
if len(got.Observers) != len(testCase.wantInfo.Observers) {
t.Errorf("Observers count = %v, want %v", len(got.Observers), len(testCase.wantInfo.Observers))
}

for k, v := range testCase.wantInfo.Observers {
if gotObs, exists := got.Observers[k]; !exists {
t.Errorf("Observer %v not found", k)
} else if gotObs.IsActive != v.IsActive {
t.Errorf("Observer %v IsActive = %v, want %v", k, gotObs.IsActive, v.IsActive)
}
}
}
})
}
}

func TestLease_Concurrent(t *testing.T) {
t.Parallel()

lease := NewLease()
done := make(chan bool)
iterations := 1000

// Concurrent writers
go func() {
for range iterations {
lease.UpdateLease(&LockInfo{
Version: "v1",
Node: "node1",
})
}
done <- true
}()

// Concurrent readers
go func() {
for range iterations {
_ = lease.GetLeaseInfo()
_ = lease.GetCurrentVersion()
}
done <- true
}()

// Wait for both goroutines to finish
<-done
<-done
}

func TestLease_GetCurrentVersion_PanicOnInvalidStore(t *testing.T) {
t.Parallel()

defer func() {
if r := recover(); r == nil {
t.Error("GetCurrentVersion() should panic on invalid type assertion")
}
}()

lease := NewLease()
// Force an invalid value into the atomic.Value
lease.version.Store(123) // Store non-string value

lease.GetCurrentVersion()
}
4 changes: 0 additions & 4 deletions manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,6 @@ func NewManager(client S3Client, bucket string, cfg Config) (*Manager, error) {
cfg.QuorumSize = defaultQuorumSize
}

if cfg.RequireQuorum && cfg.QuorumSize < 1 {
return nil, fmt.Errorf("%w: quorum size must be at least 1", ErrInvalidConfig)
}

return &Manager{
s3Client: client,
bucket: bucket,
Expand Down
14 changes: 14 additions & 0 deletions manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ func TestNewManager(t *testing.T) {
cfg: Config{},
expectError: true,
},
{
name: "Quorum size is 0 and quorum is required",
client: NewMockS3Client(),
bucket: "test-bucket",
cfg: Config{QuorumSize: 0, RequireQuorum: true},
expectError: false,
},
{
name: "Quorum size is 0 and quorum is not required",
client: NewMockS3Client(),
bucket: "test-bucket",
cfg: Config{QuorumSize: 0, RequireQuorum: false},
expectError: false,
},
}

for _, tCase := range tests {
Expand Down

0 comments on commit edb451a

Please sign in to comment.