Files
vm/api/health/service_test.go
zeekay 021a8edace fix: resolve proto import paths and test compilation issues
- Fix dag package imports to use vm/proto/pb/dag instead of node/proto
- Fix api/health test to use atomic.Atomic from github.com/luxfi/atomic
- Fix components/message test to use crypto.RandomBytes
- Fix chains/manager to use correct EngineType constant
2026-01-11 20:58:38 -08:00

226 lines
5.8 KiB
Go

// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package health
import (
"context"
"net/http"
"testing"
"github.com/luxfi/metric"
"github.com/stretchr/testify/require"
"github.com/luxfi/ids"
"github.com/luxfi/log"
)
func TestServiceResponses(t *testing.T) {
require := require.New(t)
check := CheckerFunc(func(context.Context) (interface{}, error) {
return "", nil
})
h, err := New(log.NewNoOpLogger(), metric.NewRegistry())
require.NoError(err)
s := &Service{
log: log.NewNoOpLogger(),
health: h,
}
require.NoError(h.RegisterReadinessCheck("check", check))
require.NoError(h.RegisterHealthCheck("check", check))
require.NoError(h.RegisterLivenessCheck("check", check))
{
reply := APIReply{}
require.NoError(s.Readiness(nil, &APIArgs{}, &reply))
require.Len(reply.Checks, 1)
require.Contains(reply.Checks, "check")
require.Equal(notYetRunResult, reply.Checks["check"])
require.False(reply.Healthy)
}
{
reply := APIReply{}
require.NoError(s.Health(nil, &APIArgs{}, &reply))
require.Len(reply.Checks, 1)
require.Contains(reply.Checks, "check")
require.Equal(notYetRunResult, reply.Checks["check"])
require.False(reply.Healthy)
}
{
reply := APIReply{}
require.NoError(s.Liveness(nil, &APIArgs{}, &reply))
require.Len(reply.Checks, 1)
require.Contains(reply.Checks, "check")
require.Equal(notYetRunResult, reply.Checks["check"])
require.False(reply.Healthy)
}
h.Start(context.Background(), checkFreq)
defer h.Stop()
awaitReadiness(t, h, true)
awaitHealthy(t, h, true)
awaitLiveness(t, h, true)
{
reply := APIReply{}
require.NoError(s.Readiness(nil, &APIArgs{}, &reply))
result := reply.Checks["check"]
require.Empty(result.Details)
require.Nil(result.Error)
require.Zero(result.ContiguousFailures)
require.True(reply.Healthy)
}
{
reply := APIReply{}
require.NoError(s.Health(nil, &APIArgs{}, &reply))
result := reply.Checks["check"]
require.Empty(result.Details)
require.Nil(result.Error)
require.Zero(result.ContiguousFailures)
require.True(reply.Healthy)
}
{
reply := APIReply{}
require.NoError(s.Liveness(nil, &APIArgs{}, &reply))
result := reply.Checks["check"]
require.Empty(result.Details)
require.Nil(result.Error)
require.Zero(result.ContiguousFailures)
require.True(reply.Healthy)
}
}
func TestServiceTagResponse(t *testing.T) {
check := CheckerFunc(func(context.Context) (interface{}, error) {
return "", nil
})
netID1 := ids.GenerateTestID()
netID2 := ids.GenerateTestID()
// test cases
type testMethods struct {
name string
register func(Health, string, Checker, ...string) error
check func(*Service, *http.Request, *APIArgs, *APIReply) error
await func(*testing.T, Reporter, bool)
}
tests := []testMethods{
{
name: "Readiness",
register: func(h Health, s1 string, c Checker, s2 ...string) error {
return h.RegisterReadinessCheck(s1, c, s2...)
},
check: func(s *Service, req *http.Request, a1 *APIArgs, a2 *APIReply) error {
return s.Readiness(req, a1, a2)
},
await: awaitReadiness,
},
{
name: "Health",
register: func(h Health, s1 string, c Checker, s2 ...string) error {
return h.RegisterHealthCheck(s1, c, s2...)
},
check: func(s *Service, r *http.Request, a1 *APIArgs, a2 *APIReply) error {
return s.Health(r, a1, a2)
},
await: awaitHealthy,
},
{
name: "Liveness",
register: func(h Health, s1 string, c Checker, s2 ...string) error {
return h.RegisterLivenessCheck(s1, c, s2...)
},
check: func(s *Service, r *http.Request, a1 *APIArgs, a2 *APIReply) error {
return s.Liveness(r, a1, a2)
},
await: awaitLiveness,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
require := require.New(t)
h, err := New(log.NewNoOpLogger(), metric.NewRegistry())
require.NoError(err)
require.NoError(test.register(h, "check1", check))
require.NoError(test.register(h, "check2", check, netID1.String()))
require.NoError(test.register(h, "check3", check, netID2.String()))
require.NoError(test.register(h, "check4", check, netID1.String(), netID2.String()))
s := &Service{
log: log.NewNoOpLogger(),
health: h,
}
// default checks
{
reply := APIReply{}
require.NoError(test.check(s, nil, &APIArgs{}, &reply))
require.Len(reply.Checks, 4)
require.Contains(reply.Checks, "check1")
require.Contains(reply.Checks, "check2")
require.Contains(reply.Checks, "check3")
require.Contains(reply.Checks, "check4")
require.Equal(notYetRunResult, reply.Checks["check1"])
require.False(reply.Healthy)
require.NoError(test.check(s, nil, &APIArgs{Tags: []string{netID1.String()}}, &reply))
require.Len(reply.Checks, 2)
require.Contains(reply.Checks, "check2")
require.Contains(reply.Checks, "check4")
require.Equal(notYetRunResult, reply.Checks["check2"])
require.False(reply.Healthy)
}
h.Start(context.Background(), checkFreq)
test.await(t, h, true)
{
reply := APIReply{}
require.NoError(test.check(s, nil, &APIArgs{Tags: []string{netID1.String()}}, &reply))
require.Len(reply.Checks, 2)
require.Contains(reply.Checks, "check2")
require.Contains(reply.Checks, "check4")
require.True(reply.Healthy)
}
// stop the health check
h.Stop()
{
// now we'll add a new check which is unhealthy by default (notYetRunResult)
require.NoError(test.register(h, "check5", check, netID1.String()))
reply := APIReply{}
require.NoError(test.check(s, nil, &APIArgs{Tags: []string{netID1.String()}}, &reply))
require.Len(reply.Checks, 3)
require.Contains(reply.Checks, "check2")
require.Contains(reply.Checks, "check4")
require.Contains(reply.Checks, "check5")
require.Equal(notYetRunResult, reply.Checks["check5"])
require.False(reply.Healthy)
}
})
}
}