From d065153629e92e2c312269547fdb5a0eeb787027 Mon Sep 17 00:00:00 2001 From: Juliano Martinez Date: Mon, 12 Feb 2024 20:42:49 +0100 Subject: [PATCH] update ci info --- .github/workflows/ci.yml | 22 +++++ internal/ballot/ballot.go | 4 + internal/ballot/ballot_test.go | 144 ++++++++++++++++++++++++--------- 3 files changed, 133 insertions(+), 37 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e19f6a7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +name: Test and coverage + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + - uses: actions/setup-go@v3 + with: + go-version: '1.21' + - name: Run coverage + run: go test -coverpkg=./... ./... -race -coverprofile=coverage.out -covermode=atomic + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + verbose: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/internal/ballot/ballot.go b/internal/ballot/ballot.go index f7003ba..629f4db 100644 --- a/internal/ballot/ballot.go +++ b/internal/ballot/ballot.go @@ -101,6 +101,7 @@ func (b *Ballot) copyServiceToRegistration(service *api.AgentService) *api.Agent } } +// Copy *api.CatalogService to *api.CatalogRegistration func (b *Ballot) copyCatalogServiceToRegistration(service *api.CatalogService) *api.CatalogRegistration { return &api.CatalogRegistration{ ID: service.ID, @@ -243,6 +244,7 @@ func (b *Ballot) cleanup(payload *ElectionPayload) error { return nil } +// election is the main logic for the leader election. func (b *Ballot) election() (err error) { err = b.handleServiceCriticalState() if err != nil { @@ -284,6 +286,7 @@ func (b *Ballot) election() (err error) { return b.verifyAndUpdateLeadershipStatus() } +// attemptLeadershipAcquisition attempts to acquire leadership. func (b *Ballot) attemptLeadershipAcquisition(electionPayload *ElectionPayload) (bool, *api.WriteMeta, error) { payload, err := json.Marshal(electionPayload) if err != nil { @@ -299,6 +302,7 @@ func (b *Ballot) attemptLeadershipAcquisition(electionPayload *ElectionPayload) return b.client.KV().Acquire(content, nil) } +// verifyAndUpdateLeadershipStatus checks the current session data and updates the leadership status. func (b *Ballot) verifyAndUpdateLeadershipStatus() error { currentSessionData, err := b.getSessionData() if err != nil { diff --git a/internal/ballot/ballot_test.go b/internal/ballot/ballot_test.go index db9fe2b..dea62f6 100644 --- a/internal/ballot/ballot_test.go +++ b/internal/ballot/ballot_test.go @@ -17,46 +17,66 @@ func TestNew(t *testing.T) { } func TestCopyServiceToRegistration(t *testing.T) { - b, _ := New(context.Background(), "test") - service := &api.AgentService{ - ID: "id", - Service: "service", - Port: 8080, - Address: "127.0.0.1", - } - reg := b.copyServiceToRegistration(service) - assert.Equal(t, service.ID, reg.ID) - assert.Equal(t, service.Service, reg.Name) - assert.Equal(t, service.Port, reg.Port) - assert.Equal(t, service.Address, reg.Address) + b := &Ballot{} + + t.Run("successful copy", func(t *testing.T) { + service := &api.AgentService{ + ID: "testID", + Service: "testService", + Tags: []string{"tag1", "tag2"}, + Port: 8080, + Address: "127.0.0.1", + } + + registration := b.copyServiceToRegistration(service) + + assert.Equal(t, service.ID, registration.ID) + assert.Equal(t, service.Service, registration.Name) + assert.Equal(t, service.Tags, registration.Tags) + assert.Equal(t, service.Port, registration.Port) + assert.Equal(t, service.Address, registration.Address) + }) + + t.Run("failure due to nil service", func(t *testing.T) { + assert.Panics(t, func() { b.copyServiceToRegistration(nil) }) + }) } func TestCopyCatalogServiceToRegistration(t *testing.T) { - b, _ := New(context.Background(), "test") - service := &api.CatalogService{ - ID: "id", - Node: "node", - ServiceAddress: "127.0.0.1", - ServiceID: "serviceId", - ServiceName: "serviceName", - ServicePort: 8080, - ServiceTags: []string{"tag1", "tag2"}, - ServiceMeta: map[string]string{"key": "value"}, - ServiceWeights: api.Weights{Passing: 1, Warning: 1}, - ServiceEnableTagOverride: true, - } - reg := b.copyCatalogServiceToRegistration(service) - assert.Equal(t, service.ID, reg.ID) - assert.Equal(t, service.Node, reg.Node) - assert.Equal(t, service.ServiceAddress, reg.Address) - assert.Equal(t, service.ServiceID, reg.Service.ID) - assert.Equal(t, service.ServiceName, reg.Service.Service) - assert.Equal(t, service.ServicePort, reg.Service.Port) - assert.Equal(t, service.ServiceTags, reg.Service.Tags) - assert.Equal(t, service.ServiceMeta, reg.Service.Meta) - assert.Equal(t, service.ServiceWeights.Passing, reg.Service.Weights.Passing) - assert.Equal(t, service.ServiceWeights.Warning, reg.Service.Weights.Warning) - assert.Equal(t, service.ServiceEnableTagOverride, reg.Service.EnableTagOverride) + b := &Ballot{} + + t.Run("successful copy", func(t *testing.T) { + service := &api.CatalogService{ + ID: "id", + Node: "node", + ServiceAddress: "127.0.0.1", + ServiceID: "serviceId", + ServiceName: "serviceName", + ServicePort: 8080, + ServiceTags: []string{"tag1", "tag2"}, + ServiceMeta: map[string]string{"key": "value"}, + ServiceWeights: api.Weights{Passing: 1, Warning: 1}, + ServiceEnableTagOverride: true, + } + + registration := b.copyCatalogServiceToRegistration(service) + assert.Equal(t, service.ID, registration.ID) + assert.Equal(t, service.Node, registration.Node) + assert.Equal(t, service.ServiceAddress, registration.Address) + assert.Equal(t, service.ServiceID, registration.Service.ID) + assert.Equal(t, service.ServiceName, registration.Service.Service) + assert.Equal(t, service.ServicePort, registration.Service.Port) + assert.Equal(t, service.ServiceTags, registration.Service.Tags) + assert.Equal(t, service.ServiceMeta, registration.Service.Meta) + assert.Equal(t, service.ServiceWeights.Passing, registration.Service.Weights.Passing) + assert.Equal(t, service.ServiceWeights.Warning, registration.Service.Weights.Warning) + assert.Equal(t, service.ServiceEnableTagOverride, registration.Service.EnableTagOverride) + + }) + + t.Run("failure due to nil service", func(t *testing.T) { + assert.Panics(t, func() { b.copyCatalogServiceToRegistration(nil) }) + }) } // MockCommandExecutor is a mock implementation of the CommandExecutor interface @@ -100,3 +120,53 @@ func TestRunCommand(t *testing.T) { // Assert that the method did not return an error assert.NoError(t, err) } + +func TestMakeServiceCheck(t *testing.T) { + b := &Ballot{} + + t.Run("successful creation of service checks", func(t *testing.T) { + sc := []string{"check1", "check2", "check3"} + + serviceChecks := b.makeServiceCheck(sc) + + assert.Equal(t, len(sc), len(serviceChecks)) + for i, check := range serviceChecks { + assert.Equal(t, sc[i], check.ID) + } + }) + + t.Run("handling of empty slice", func(t *testing.T) { + sc := []string{} + + serviceChecks := b.makeServiceCheck(sc) + + assert.Equal(t, 0, len(serviceChecks)) + }) +} + +func TestIsLeader(t *testing.T) { + t.Run("returns true when the ballot is the leader", func(t *testing.T) { + b := &Ballot{} + b.leader.Store(true) + b.sessionID.Store("session") + assert.True(t, b.IsLeader()) + }) + + t.Run("returns false when the ballot is not the leader", func(t *testing.T) { + b := &Ballot{} + + assert.False(t, b.IsLeader()) + }) + + t.Run("returns false when the ballot hasn't stored a state yet", func(t *testing.T) { + b := &Ballot{} + + assert.False(t, b.IsLeader()) + }) + + t.Run("returns false when the ballot hasn't stored a session yet", func(t *testing.T) { + b := &Ballot{} + + assert.False(t, b.IsLeader()) + }) +}