Merged in feature/testing (pull request #102)
Minimum Testing Threshold * mintests
This commit is contained in:
+1
-1
@@ -10,4 +10,4 @@ includes:
|
||||
vars:
|
||||
IMAGE_NAME: queryorchestration
|
||||
COVERAGE_THRESHOLD: 80
|
||||
FUNCTION_COVERAGE_THRESHOLD: 10
|
||||
FUNCTION_COVERAGE_THRESHOLD: 60
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -17,7 +16,6 @@ import (
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
_ "github.com/lib/pq"
|
||||
echoSwagger "github.com/swaggo/echo-swagger"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config interface {
|
||||
@@ -90,7 +88,6 @@ func getSlogCustomEchoMiddleware(logger *slog.Logger) echo.MiddlewareFunc {
|
||||
}
|
||||
|
||||
func New(ctx context.Context, cfg Config) (*Server, error) {
|
||||
|
||||
cleanup, err := server.New(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -114,25 +111,17 @@ func New(ctx context.Context, cfg Config) (*Server, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.GET("/swagger/doc.json", func(c echo.Context) error {
|
||||
spec, err := opnapi.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Blob(http.StatusOK, "application/json", spec)
|
||||
})
|
||||
e.GET("/swagger/doc.yaml", func(c echo.Context) error {
|
||||
spec, err := opnapi.MarshalYAML()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
yaml, err := yaml.Marshal(spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jsonFunc, err := getSwaggerJSONFunc(opnapi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.GET("/swagger/doc.json", jsonFunc)
|
||||
|
||||
return c.Blob(http.StatusOK, "application/yaml", yaml)
|
||||
})
|
||||
yamlFunc, err := getSwaggerYAMLFunc(opnapi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.GET("/swagger/doc.yaml", yamlFunc)
|
||||
|
||||
e.GET("/swagger/*", echoSwagger.EchoWrapHandler(
|
||||
echoSwagger.DocExpansion("full"),
|
||||
|
||||
@@ -2,16 +2,22 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"testing"
|
||||
|
||||
"queryorchestration/internal/serviceconfig/logger"
|
||||
"queryorchestration/internal/test"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
@@ -78,3 +84,31 @@ func TestGetRouter(t *testing.T) {
|
||||
assert.Equal(t, &echo.Echo{}, r)
|
||||
assert.Equal(t, r, c.Router)
|
||||
}
|
||||
|
||||
func TestGetSlogCustomEchoMiddleware(t *testing.T) {
|
||||
l := &logger.TestLogger{
|
||||
T: t,
|
||||
}
|
||||
sl := slog.New(l)
|
||||
handlerFunc := getSlogCustomEchoMiddleware(sl)
|
||||
require.NotNil(t, handlerFunc)
|
||||
|
||||
mid := func(c echo.Context) error {
|
||||
sl.Info("in middleware", "location", "middleware")
|
||||
return nil
|
||||
}
|
||||
myFunc := handlerFunc(mid)
|
||||
require.NotNil(t, myFunc)
|
||||
|
||||
uri := "/example"
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, uri, strings.NewReader("hello"))
|
||||
rec := httptest.NewRecorder()
|
||||
ctx := echo.New().NewContext(req, rec)
|
||||
err := myFunc(ctx)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Len(t, l.Logs, 2)
|
||||
assert.Equal(t, "middleware", l.Logs[0]["location"])
|
||||
assert.Equal(t, uri, l.Logs[1]["uri"])
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/labstack/echo/v4"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func getSwaggerJSONFunc(opnapi *openapi3.T) (func(echo.Context) error, error) {
|
||||
spec, err := opnapi.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(c echo.Context) error {
|
||||
return c.Blob(http.StatusOK, "application/json", spec)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getSwaggerYAMLFunc(opnapi *openapi3.T) (func(echo.Context) error, error) {
|
||||
spec, err := opnapi.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
yaml, err := yaml.Marshal(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(c echo.Context) error {
|
||||
return c.Blob(http.StatusOK, "application/yaml", yaml)
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
queryservice "queryorchestration/api/queryService"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetSwaggerJSONFunc(t *testing.T) {
|
||||
openapi, err := queryservice.GetSwagger()
|
||||
require.NoError(t, err)
|
||||
|
||||
f, err := getSwaggerJSONFunc(openapi)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, f)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("hello"))
|
||||
rec := httptest.NewRecorder()
|
||||
ctx := echo.New().NewContext(req, rec)
|
||||
|
||||
err = f(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, rec.Result().StatusCode)
|
||||
}
|
||||
|
||||
func TestGetSwaggerYAMLFunc(t *testing.T) {
|
||||
openapi, err := queryservice.GetSwagger()
|
||||
require.NoError(t, err)
|
||||
|
||||
f, err := getSwaggerYAMLFunc(openapi)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, f)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("hello"))
|
||||
rec := httptest.NewRecorder()
|
||||
ctx := echo.New().NewContext(req, rec)
|
||||
|
||||
err = f(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, rec.Result().StatusCode)
|
||||
}
|
||||
@@ -25,10 +25,16 @@ var startupTime time.Time
|
||||
var startupTimeOnce sync.Once
|
||||
|
||||
func GetVersionTimestamp() time.Time {
|
||||
startupTimeOnce.Do(func() {
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
startupTimeOnce.Do(getStartTime(&startupTime, debug.ReadBuildInfo))
|
||||
|
||||
return startupTime
|
||||
}
|
||||
|
||||
func getStartTime(startupTime *time.Time, readBuildInfo func() (info *debug.BuildInfo, ok bool)) func() {
|
||||
return func() {
|
||||
info, ok := readBuildInfo()
|
||||
if !ok {
|
||||
startupTime = time.Now()
|
||||
*startupTime = time.Now()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -38,7 +44,7 @@ func GetVersionTimestamp() time.Time {
|
||||
// Parse the build timestamp
|
||||
buildTime, err := time.Parse(time.RFC3339, setting.Value)
|
||||
if err == nil {
|
||||
startupTime = buildTime
|
||||
*startupTime = buildTime
|
||||
return
|
||||
}
|
||||
break
|
||||
@@ -46,10 +52,8 @@ func GetVersionTimestamp() time.Time {
|
||||
}
|
||||
|
||||
// Return current time if no build time found
|
||||
startupTime = time.Now()
|
||||
})
|
||||
|
||||
return startupTime
|
||||
*startupTime = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
func GetVersionUnixTimestamp() int64 {
|
||||
|
||||
@@ -1,46 +1,45 @@
|
||||
package build_test
|
||||
package build
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetVersionUnixTimestamp(t *testing.T) {
|
||||
t1 := build.GetVersionUnixTimestamp()
|
||||
t1 := GetVersionUnixTimestamp()
|
||||
assert.NotZero(t, t1)
|
||||
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
t2 := build.GetVersionUnixTimestamp()
|
||||
t2 := GetVersionUnixTimestamp()
|
||||
assert.Equal(t, t1, t2)
|
||||
}
|
||||
|
||||
func TestIsValidUnixVersion(t *testing.T) {
|
||||
assert.NotNil(t, build.IsValidUnixVersion(0))
|
||||
assert.NotNil(t, build.IsValidUnixVersion(time.Now().Add(time.Second).UnixMilli()))
|
||||
assert.Nil(t, build.IsValidUnixVersion(1))
|
||||
assert.NotNil(t, IsValidUnixVersion(0))
|
||||
assert.NotNil(t, IsValidUnixVersion(time.Now().Add(time.Second).UnixMilli()))
|
||||
assert.Nil(t, IsValidUnixVersion(1))
|
||||
}
|
||||
|
||||
func TestGetVersionTimestamp(t *testing.T) {
|
||||
// Test 1: First call should set the timestamp
|
||||
t1 := build.GetVersionTimestamp()
|
||||
t1 := GetVersionTimestamp()
|
||||
if t1.IsZero() {
|
||||
t.Error("GetVersionTimestamp returned zero time")
|
||||
}
|
||||
|
||||
// Test 2: Second call should return exactly the same time
|
||||
time.Sleep(time.Millisecond * 100) // Small delay to ensure time would be different if not cached
|
||||
t2 := build.GetVersionTimestamp()
|
||||
t2 := GetVersionTimestamp()
|
||||
if !t1.Equal(t2) {
|
||||
t.Errorf("Timestamps should be identical but got t1=%v, t2=%v", t1, t2)
|
||||
}
|
||||
|
||||
// Test 3: Even after a longer delay, should still return the same time
|
||||
time.Sleep(time.Second) // Longer delay
|
||||
t3 := build.GetVersionTimestamp()
|
||||
t3 := GetVersionTimestamp()
|
||||
if !t1.Equal(t3) {
|
||||
t.Errorf("Timestamp changed after delay: original=%v, new=%v", t1, t3)
|
||||
}
|
||||
@@ -51,9 +50,46 @@ func TestGetVersionTimestamp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStartTime(t *testing.T) {
|
||||
t.Run("vcs time", func(t *testing.T) {
|
||||
var tt time.Time
|
||||
expectedTime := time.Now()
|
||||
f := getStartTime(&tt, func() (info *debug.BuildInfo, ok bool) {
|
||||
return &debug.BuildInfo{
|
||||
Settings: []debug.BuildSetting{
|
||||
{
|
||||
Key: "vcs.time",
|
||||
Value: expectedTime.Format(time.RFC3339),
|
||||
},
|
||||
},
|
||||
}, true
|
||||
})
|
||||
assert.NotNil(t, f)
|
||||
f()
|
||||
assert.Equal(t, expectedTime.UTC().Truncate(time.Second), tt)
|
||||
})
|
||||
t.Run("vcs time - invalid format", func(t *testing.T) {
|
||||
var tt time.Time
|
||||
expectedTime := time.Now()
|
||||
f := getStartTime(&tt, func() (info *debug.BuildInfo, ok bool) {
|
||||
return &debug.BuildInfo{
|
||||
Settings: []debug.BuildSetting{
|
||||
{
|
||||
Key: "vcs.time",
|
||||
Value: "invalid",
|
||||
},
|
||||
},
|
||||
}, true
|
||||
})
|
||||
assert.NotNil(t, f)
|
||||
f()
|
||||
assert.True(t, expectedTime.Before(tt))
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetVersion(t *testing.T) {
|
||||
// Test 1: Basic call
|
||||
version := build.GetVersion()
|
||||
version := GetVersion()
|
||||
if version == "" {
|
||||
t.Error("Version should not be empty")
|
||||
}
|
||||
@@ -67,7 +103,7 @@ func TestGetVersion(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test 3: Multiple calls should be consistent
|
||||
version2 := build.GetVersion()
|
||||
version2 := GetVersion()
|
||||
if version != version2 {
|
||||
t.Errorf("Version not consistent between calls: '%s' != '%s'", version, version2)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"queryorchestration/internal/serviceconfig"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -31,6 +32,12 @@ func TestCreateContainer(t *testing.T) {
|
||||
Name: QueryService,
|
||||
Cfg: cfg,
|
||||
Network: ncfg,
|
||||
Env: map[string]string{
|
||||
"EXAMPLE": "value",
|
||||
},
|
||||
ExposedPorts: []nat.Port{
|
||||
nat.Port("8080/tcp"),
|
||||
},
|
||||
}
|
||||
|
||||
container, cleanup := createContainer(t, ctx, ccfg)
|
||||
|
||||
@@ -60,6 +60,8 @@ paths:
|
||||
- ClientService
|
||||
summary: Get a client by ID
|
||||
description: Retrieves a specific client by its ID.
|
||||
security:
|
||||
- placeholderAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: Client details.
|
||||
|
||||
Reference in New Issue
Block a user