diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a8cf254..76ae353 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,23 +17,17 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Set up Go + - name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.24' - - - name: Cache Go modules - uses: actions/cache@v4 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + cache-dependency-path: '**/go.sum' - name: Install dependencies - run: go mod tidy + run: go mod download + + - name: Build + run: go build -v ./... - name: Run tests with coverage run: go test ./... -v -race -coverprofile=coverage.out -covermode=atomic diff --git a/internal/client/client.go b/internal/client/client.go index 17bc1fa..1cf7777 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -42,14 +42,15 @@ func (c *Client) Connect() error { c.log.Sugar().Errorf("Error connecting: %v\n", err) return errors.New("failed to connect") } - if code == http.StatusOK { + switch code { + case http.StatusOK: c.log.Info("Connected successfully") c.initHeartbeat() return nil - } else if code == http.StatusConflict { + case http.StatusConflict: c.log.Warn("Connection exists at another device") return errors.New("failed to connect") - } else { + default: c.log.Error("Failed to connect") return errors.New("failed to connect") } @@ -61,14 +62,15 @@ func (c *Client) Disconnect() error { c.log.Sugar().Errorf("Error disconnecting: %v\n", err) return errors.New("failed to disconnect") } + if code == http.StatusOK { c.log.Info("Disconnected successfully") c.stopHeartbeat() return nil - } else { - c.log.Error("Failed to disconnect") - return errors.New("failed to disconnect") } + + c.log.Error("Failed to disconnect") + return errors.New("failed to disconnect") } func (c *Client) heartbeat() { @@ -77,12 +79,13 @@ func (c *Client) heartbeat() { c.log.Sugar().Errorf("Error sending heartbeat: %v\n", err) return } + if code == http.StatusOK { c.log.Info("Heartbeat sent successfully") - } else { - c.log.Error("Failed to send heartbeat") return } + + c.log.Error("Failed to send heartbeat") } func (c *Client) initHeartbeat() { diff --git a/internal/client/client_test.go b/internal/client/client_test.go index 73a693f..644ca4b 100644 --- a/internal/client/client_test.go +++ b/internal/client/client_test.go @@ -11,121 +11,106 @@ import ( ) func TestConnect(t *testing.T) { - tests := []struct { - Name string - ReceivedResponse int - IsError bool - Heartbeat bool - }{ - { - Name: "Server returns 500", - ReceivedResponse: http.StatusInternalServerError, - IsError: true, - Heartbeat: false, - }, - { - Name: "Connection already exists", - ReceivedResponse: http.StatusConflict, - IsError: true, - Heartbeat: false, - }, - { - Name: "Connected successfully", - ReceivedResponse: http.StatusOK, - IsError: false, - Heartbeat: true, - }, - } - - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - t.Parallel() - log := zap.NewNop() - - server := newMockServer(test.ReceivedResponse, http.StatusOK) - defer server.Server.Close() - - client := New(Config{ - Host: server.Server.URL, - UserID: "u1", - DeviceID: "d1", - Log: log, - }) - - err := client.Connect() - if test.IsError { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } - - time.Sleep(2 * time.Second) - - server.mu.Lock() - if test.Heartbeat { - assert.GreaterOrEqual(t, server.HeartbeatCount, 1) - } else { - assert.Zero(t, server.HeartbeatCount) - } - server.mu.Unlock() - }) - } + t.Run("Successful connect", func(t *testing.T) { + t.Parallel() + + server := newMockServer(http.StatusOK, http.StatusOK) + defer server.Server.Close() + + client := newClient(server.Server.URL) + + err := client.Connect() + assert.NoError(t, err) + + time.Sleep(2 * time.Second) + + server.mu.Lock() + assert.GreaterOrEqual(t, server.HeartbeatCount, 1) + server.mu.Unlock() + }) + + t.Run("Connection exists", func(t *testing.T) { + t.Parallel() + + server := newMockServer(http.StatusConflict, http.StatusOK) + defer server.Server.Close() + + client := newClient(server.Server.URL) + + err := client.Connect() + assert.Error(t, err) + + time.Sleep(2 * time.Second) + + server.mu.Lock() + assert.Zero(t, server.HeartbeatCount) + server.mu.Unlock() + }) + + t.Run("Internal server error", func(t *testing.T) { + t.Parallel() + + server := newMockServer(http.StatusInternalServerError, http.StatusOK) + defer server.Server.Close() + + client := newClient(server.Server.URL) + + err := client.Connect() + assert.Error(t, err) + + time.Sleep(2 * time.Second) + + server.mu.Lock() + assert.Zero(t, server.HeartbeatCount) + server.mu.Unlock() + }) } func TestDisconnect(t *testing.T) { - tests := []struct { - Name string - ReceivedResponse int - IsError bool - Heartbeat bool - }{ - { - Name: "Success", - ReceivedResponse: http.StatusOK, - IsError: false, - Heartbeat: false, - }, - { - Name: "Fail", - ReceivedResponse: http.StatusInternalServerError, - IsError: true, - Heartbeat: true, - }, - } - - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - t.Parallel() - - log := zap.NewNop() - - server := newMockServer(http.StatusOK, test.ReceivedResponse) - defer server.Server.Close() - - client := New(Config{ - Host: server.Server.URL, - UserID: "u1", - DeviceID: "d1", - Log: log, - }) - - client.Connect() - err := client.Disconnect() - if test.IsError { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } - - time.Sleep(2 * time.Second) - - server.mu.Lock() - if test.Heartbeat { - assert.GreaterOrEqual(t, server.HeartbeatCount, 1) - } else { - assert.Zero(t, server.HeartbeatCount) - } - server.mu.Unlock() - }) - } + t.Run("Successful disconnect", func(t *testing.T) { + t.Parallel() + + server := newMockServer(http.StatusOK, http.StatusOK) + defer server.Server.Close() + + client := newClient(server.Server.URL) + + client.Connect() + err := client.Disconnect() + assert.NoError(t, err) + + time.Sleep(2 * time.Second) + + server.mu.Lock() + assert.Zero(t, server.HeartbeatCount) + server.mu.Unlock() + }) + + t.Run("Failed disconnect", func(t *testing.T) { + t.Parallel() + + server := newMockServer(http.StatusOK, http.StatusInternalServerError) + defer server.Server.Close() + + client := newClient(server.Server.URL) + + client.Connect() + err := client.Disconnect() + assert.Error(t, err) + + time.Sleep(2 * time.Second) + + server.mu.Lock() + assert.GreaterOrEqual(t, server.HeartbeatCount, 1) + server.mu.Unlock() + }) +} + +func newClient(url string) *Client { + return New(Config{ + Host: url, + UserID: "u1", + DeviceID: "d1", + Log: zap.NewNop(), + }) }