Private
Public Access
CI / rust (push) Successful in 3m6s
CI / go (push) Successful in 33s
CI / js (push) Successful in 34s
Standalone clients that resolve a machine unique ID (OS machine ID first, falling back to a generated UUID persisted to disk), detect hostname/IP/ container/orchestrator, and register+re-ping origin.warky.dev's public service-checkin endpoint on a daily interval. Ported from icy2's internal origincheckin package but extended to the full check-in contract and made dependency-light for external reuse. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
149 lines
3.9 KiB
Go
149 lines
3.9 KiB
Go
package originclient
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func testConfig(url string) Config {
|
|
return Config{
|
|
URL: url,
|
|
ServiceKey: "test-key",
|
|
Type: "icy2",
|
|
Version: "v1.0.0",
|
|
Name: "icy2-test",
|
|
Site: "Test Site",
|
|
Environment: "test",
|
|
IntervalHours: 24,
|
|
InstallID: "test-install-id",
|
|
}
|
|
}
|
|
|
|
func TestNew_RequiresFields(t *testing.T) {
|
|
_, err := New(Config{})
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestNew_AppliesDefaults(t *testing.T) {
|
|
c, err := New(Config{ServiceKey: "k", Type: "t", Version: "v", Name: "n", InstallID: "id"})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, DefaultURL, c.cfg.URL)
|
|
assert.Equal(t, "go", c.cfg.AppType)
|
|
assert.Equal(t, DefaultIntervalHours, c.cfg.IntervalHours)
|
|
assert.Equal(t, "id", c.installID)
|
|
}
|
|
|
|
func TestBuildPayload(t *testing.T) {
|
|
c, err := New(testConfig("https://example.invalid/checkin"))
|
|
require.NoError(t, err)
|
|
|
|
payload := c.buildPayload()
|
|
|
|
assert.Equal(t, "icy2", payload.Type)
|
|
assert.Equal(t, "go", payload.AppType)
|
|
assert.Equal(t, "v1.0.0", payload.Version)
|
|
assert.Equal(t, "icy2-test", payload.Name)
|
|
assert.Equal(t, "Test Site", payload.Site)
|
|
assert.Equal(t, "test", payload.Environment)
|
|
assert.Equal(t, "test-install-id", payload.UniqueInstallID)
|
|
}
|
|
|
|
func TestCheckinOnce_Success(t *testing.T) {
|
|
var gotKey string
|
|
var gotBody Payload
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotKey = r.Header.Get("X-Origin-Service-Key")
|
|
require.NoError(t, json.NewDecoder(r.Body).Decode(&gotBody))
|
|
w.WriteHeader(http.StatusOK)
|
|
_ = json.NewEncoder(w).Encode(Response{
|
|
Success: true,
|
|
ServiceInstanceID: 42,
|
|
UniqueInstallID: gotBody.UniqueInstallID,
|
|
Status: "provisioning",
|
|
PingedAt: "2026-08-01T00:00:00Z",
|
|
})
|
|
}))
|
|
defer server.Close()
|
|
|
|
c, err := New(testConfig(server.URL))
|
|
require.NoError(t, err)
|
|
|
|
resp, err := c.CheckinOnce(t.Context())
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, "test-key", gotKey)
|
|
assert.Equal(t, "icy2", gotBody.Type)
|
|
assert.Equal(t, "icy2-test", gotBody.Name)
|
|
assert.Equal(t, "test-install-id", gotBody.UniqueInstallID)
|
|
assert.True(t, resp.Success)
|
|
assert.Equal(t, int64(42), resp.ServiceInstanceID)
|
|
}
|
|
|
|
func TestCheckinOnce_ServerErrorReturnsError(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}))
|
|
defer server.Close()
|
|
|
|
c, err := New(testConfig(server.URL))
|
|
require.NoError(t, err)
|
|
|
|
resp, err := c.CheckinOnce(t.Context())
|
|
assert.Error(t, err)
|
|
assert.Nil(t, resp)
|
|
}
|
|
|
|
func TestCheckinOnce_UnreachableDoesNotPanic(t *testing.T) {
|
|
c, err := New(testConfig("http://127.0.0.1:1"))
|
|
require.NoError(t, err)
|
|
|
|
assert.NotPanics(t, func() {
|
|
_, _ = c.CheckinOnce(t.Context())
|
|
})
|
|
}
|
|
|
|
func TestCheckinOnce_LogsOnFailure(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfg := testConfig(server.URL)
|
|
var warned bool
|
|
cfg.Logger = LoggerFunc(func(msg string, err error) { warned = true })
|
|
|
|
c, err := New(cfg)
|
|
require.NoError(t, err)
|
|
|
|
_, _ = c.CheckinOnce(t.Context())
|
|
assert.True(t, warned)
|
|
}
|
|
|
|
func TestRun_ChecksInImmediatelyThenStopsOnContextDone(t *testing.T) {
|
|
var calls atomic.Int32
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
calls.Add(1)
|
|
w.WriteHeader(http.StatusOK)
|
|
_ = json.NewEncoder(w).Encode(Response{Success: true})
|
|
}))
|
|
defer server.Close()
|
|
|
|
c, err := New(testConfig(server.URL))
|
|
require.NoError(t, err)
|
|
|
|
ctx, cancel := context.WithTimeout(t.Context(), 200*time.Millisecond)
|
|
defer cancel()
|
|
|
|
c.Run(ctx)
|
|
|
|
assert.Equal(t, int32(1), calls.Load())
|
|
}
|