Skip to content
Closed
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
6 changes: 5 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ linters:
- unparam
- unused
- whitespace
- wsl
- wsl_v5
settings:
dupl:
threshold: 100
Expand All @@ -51,6 +51,10 @@ linters:
require-explanation: true
require-specific: true
allow-unused: false
wsl_v5:
allow-first-in-block: true
allow-whole-block: false
branch-max-lines: 2
exclusions:
generated: lax
presets:
Expand Down
111 changes: 111 additions & 0 deletions api/health_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SPDX-License-Identifier: Apache-2.0

package api

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/gin-gonic/gin"
)

func TestHealth(t *testing.T) {
// Setup
gin.SetMode(gin.TestMode)

tests := []struct {
name string
expectedStatus int
expectedBody string
}{
{
name: "successful health check",
expectedStatus: http.StatusOK,
expectedBody: "ok",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create router and register the handler
r := gin.New()
r.GET("/health", Health)

// Create request
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/health", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

// Create response recorder
w := httptest.NewRecorder()

// Perform request
r.ServeHTTP(w, req)

// Check status code
if w.Code != tt.expectedStatus {
t.Errorf("Health() status = %v, want %v", w.Code, tt.expectedStatus)
}

// Check response body
var response string
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
t.Errorf("failed to unmarshal response: %v", err)
}

if response != tt.expectedBody {
t.Errorf("Health() body = %v, want %v", response, tt.expectedBody)
}
})
}
}

func TestHealth_ContentType(t *testing.T) {
// Setup
gin.SetMode(gin.TestMode)
r := gin.New()
r.GET("/health", Health)

// Create request
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/health", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

// Create response recorder
w := httptest.NewRecorder()

// Perform request
r.ServeHTTP(w, req)

// Check content type
contentType := w.Header().Get("Content-Type")
if contentType != "application/json; charset=utf-8" {
t.Errorf("Health() content-type = %v, want application/json; charset=utf-8", contentType)
}
}

func TestHealth_MethodNotAllowed(t *testing.T) {
// Setup
gin.SetMode(gin.TestMode)
r := gin.New()
r.GET("/health", Health)

// Test that POST is not allowed
req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, "/health", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

w := httptest.NewRecorder()
r.ServeHTTP(w, req)

// Should return 404 Not Found since route is not defined for POST
if w.Code != http.StatusNotFound {
t.Errorf("Health() with POST status = %v, want %v", w.Code, http.StatusNotFound)
}
}
68 changes: 68 additions & 0 deletions api/metrics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: Apache-2.0

package api

import (
"context"
"net/http"
"net/http/httptest"
"testing"
)

func TestMetrics(t *testing.T) {
// Test that Metrics returns a valid http.Handler
handler := Metrics()

if handler == nil {
t.Error("Metrics() returned nil")
}

// Test that the handler can serve HTTP requests
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/metrics", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

w := httptest.NewRecorder()
handler.ServeHTTP(w, req)

// Prometheus metrics endpoint should return 200 OK
if w.Code != http.StatusOK {
t.Errorf("Metrics() status = %v, want %v", w.Code, http.StatusOK)
}

// Check that response contains some metrics content
body := w.Body.String()
if len(body) == 0 {
t.Error("Metrics() returned empty response body")
}

// Basic check for Prometheus metrics format (should contain # TYPE or # HELP)
if !containsMetricsContent(body) {
t.Error("Metrics() response does not appear to be Prometheus metrics format")
}
}

func TestMetrics_ContentType(t *testing.T) {
handler := Metrics()

req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/metrics", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

w := httptest.NewRecorder()
handler.ServeHTTP(w, req)

// Prometheus handler should set appropriate content type
contentType := w.Header().Get("Content-Type")
if contentType == "" {
t.Error("Metrics() did not set Content-Type header")
}
}

// containsMetricsContent checks if the response body contains Prometheus metrics content.
func containsMetricsContent(body string) bool {
// At minimum, should have some content and look like metrics
return len(body) > 0 && (body[0] == '#' || len(body) > 100)
}
90 changes: 90 additions & 0 deletions api/shutdown_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: Apache-2.0

package api

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/gin-gonic/gin"
)

func TestShutdown(t *testing.T) {
// Setup
gin.SetMode(gin.TestMode)

tests := []struct {
name string
expectedStatus int
expectedBody string
}{
{
name: "shutdown endpoint returns not implemented",
expectedStatus: http.StatusNotImplemented,
expectedBody: "This endpoint is not yet implemented",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create router and register the handler
r := gin.New()
r.POST("/api/v1/shutdown", Shutdown)

// Create request
req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, "/api/v1/shutdown", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

// Create response recorder
w := httptest.NewRecorder()

// Perform request
r.ServeHTTP(w, req)

// Check status code
if w.Code != tt.expectedStatus {
t.Errorf("Shutdown() status = %v, want %v", w.Code, tt.expectedStatus)
}

// Check response body
var response string
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
t.Errorf("failed to unmarshal response: %v", err)
}

if response != tt.expectedBody {
t.Errorf("Shutdown() body = %v, want %v", response, tt.expectedBody)
}
})
}
}

func TestShutdown_ContentType(t *testing.T) {
// Setup
gin.SetMode(gin.TestMode)
r := gin.New()
r.POST("/api/v1/shutdown", Shutdown)

// Create request
req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, "/api/v1/shutdown", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

// Create response recorder
w := httptest.NewRecorder()

// Perform request
r.ServeHTTP(w, req)

// Check content type
contentType := w.Header().Get("Content-Type")
if contentType != "application/json; charset=utf-8" {
t.Errorf("Shutdown() content-type = %v, want application/json; charset=utf-8", contentType)
}
}
95 changes: 95 additions & 0 deletions api/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: Apache-2.0

package api

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/gin-gonic/gin"

"github.com/go-vela/server/version"
)

func TestVersion(t *testing.T) {
// Setup
gin.SetMode(gin.TestMode)

tests := []struct {
name string
expectedStatus int
}{
{
name: "successful version request",
expectedStatus: http.StatusOK,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create router and register the handler
r := gin.New()
r.GET("/version", Version)

// Create request
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/version", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

// Create response recorder
w := httptest.NewRecorder()

// Perform request
r.ServeHTTP(w, req)

// Check status code
if w.Code != tt.expectedStatus {
t.Errorf("Version() status = %v, want %v", w.Code, tt.expectedStatus)
}

// Check response body contains version information
var v version.Version
if err := json.Unmarshal(w.Body.Bytes(), &v); err != nil {
t.Errorf("failed to unmarshal response: %v", err)
}

// Verify basic version structure
if v.Canonical == "" {
t.Error("version.Canonical should not be empty")
}

if v.Metadata.Architecture == "" {
t.Error("version.Metadata.Architecture should not be empty")
}
})
}
}

func TestVersion_ContentType(t *testing.T) {
// Setup
gin.SetMode(gin.TestMode)
r := gin.New()
r.GET("/version", Version)

// Create request
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/version", nil)
if err != nil {
t.Fatalf("failed to create request: %v", err)
}

// Create response recorder
w := httptest.NewRecorder()

// Perform request
r.ServeHTTP(w, req)

// Check content type
contentType := w.Header().Get("Content-Type")
if contentType != "application/json; charset=utf-8" {
t.Errorf("Version() content-type = %v, want application/json; charset=utf-8", contentType)
}
}
Loading
Loading