feat: harden runtime import and frontend verification workflows
This commit is contained in:
133
internal/app/admin_auth_extra_test.go
Normal file
133
internal/app/admin_auth_extra_test.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAdminSessionDebugValue(t *testing.T) {
|
||||
secret := "test-secret"
|
||||
username := "admin"
|
||||
expiresAt := time.Now().Add(time.Hour)
|
||||
|
||||
result := adminSessionDebugValue(secret, username, expiresAt)
|
||||
|
||||
// Result should be a hex string
|
||||
if result == "" {
|
||||
t.Error("adminSessionDebugValue should return non-empty string")
|
||||
}
|
||||
|
||||
// Should be valid hex (only contains hex characters)
|
||||
for _, c := range result {
|
||||
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) {
|
||||
t.Errorf("adminSessionDebugValue returned non-hex character: %c", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdminSessionPayload(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
raw string
|
||||
wantUser string
|
||||
wantExp bool
|
||||
}{
|
||||
{
|
||||
name: "valid payload",
|
||||
raw: createValidPayload("admin", "1234567890"),
|
||||
wantUser: "admin",
|
||||
wantExp: true,
|
||||
},
|
||||
{
|
||||
name: "invalid format - no dot",
|
||||
raw: "invalid-no-dot",
|
||||
wantUser: "",
|
||||
wantExp: false,
|
||||
},
|
||||
{
|
||||
name: "invalid format - too many dots",
|
||||
raw: "part1.part2.part3",
|
||||
wantUser: "",
|
||||
wantExp: false,
|
||||
},
|
||||
{
|
||||
name: "invalid base64",
|
||||
raw: "invalid!!!.signature",
|
||||
wantUser: "",
|
||||
wantExp: false,
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
raw: "",
|
||||
wantUser: "",
|
||||
wantExp: false,
|
||||
},
|
||||
{
|
||||
name: "single part",
|
||||
raw: "onlyonepart",
|
||||
wantUser: "",
|
||||
wantExp: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
payload := adminSessionPayload(tt.raw)
|
||||
|
||||
// All results should have "raw" field
|
||||
if _, ok := payload["raw"]; !ok {
|
||||
t.Error("payload should contain 'raw' field")
|
||||
}
|
||||
|
||||
if tt.wantUser != "" {
|
||||
if user, ok := payload["username"].(string); !ok || user != tt.wantUser {
|
||||
t.Errorf("username = %v, want %v", user, tt.wantUser)
|
||||
}
|
||||
}
|
||||
|
||||
if tt.wantExp {
|
||||
if _, ok := payload["expires_unix"]; !ok {
|
||||
t.Error("expected expires_unix field")
|
||||
}
|
||||
if _, ok := payload["payload"]; !ok {
|
||||
t.Error("expected payload field")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalAdminSessionPayload(t *testing.T) {
|
||||
validPayload := createValidPayload("admin", "1234567890")
|
||||
|
||||
result := marshalAdminSessionPayload(validPayload)
|
||||
|
||||
// Result should be valid JSON
|
||||
if result == "" {
|
||||
t.Error("marshalAdminSessionPayload should return non-empty string")
|
||||
}
|
||||
|
||||
// Should contain expected fields
|
||||
if !strings.Contains(result, "raw") {
|
||||
t.Error("result should contain 'raw' field")
|
||||
}
|
||||
|
||||
if !strings.Contains(result, "username") {
|
||||
t.Error("result should contain 'username' field")
|
||||
}
|
||||
|
||||
// Test with invalid payload
|
||||
invalidResult := marshalAdminSessionPayload("invalid")
|
||||
if invalidResult == "" {
|
||||
t.Error("marshalAdminSessionPayload with invalid input should still return something")
|
||||
}
|
||||
}
|
||||
|
||||
// createValidPayload creates a valid payload string for testing
|
||||
func createValidPayload(username, expires string) string {
|
||||
body := username + "|" + expires
|
||||
encoded := base64.RawURLEncoding.EncodeToString([]byte(body))
|
||||
return encoded + ".signature"
|
||||
}
|
||||
@@ -21,13 +21,13 @@ func NewServer(listenAddr string, handler http.Handler, listenerFactory Listener
|
||||
}
|
||||
server := &Server{
|
||||
server: &http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: handler,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
Addr: listenAddr,
|
||||
Handler: handler,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
ReadHeaderTimeout: 10 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20, // 1MB
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20, // 1MB
|
||||
},
|
||||
listen: net.Listen,
|
||||
}
|
||||
|
||||
@@ -743,25 +743,25 @@ func TestServerAddrReturnsConfiguredAddress(t *testing.T) {
|
||||
|
||||
func TestServerHasTimeoutConfiguration(t *testing.T) {
|
||||
server := NewServer("127.0.0.1:0", nil, nil)
|
||||
|
||||
|
||||
s := server.server
|
||||
|
||||
|
||||
if s.ReadTimeout != 30*time.Second {
|
||||
t.Errorf("ReadTimeout = %v, want 30s", s.ReadTimeout)
|
||||
}
|
||||
|
||||
|
||||
if s.ReadHeaderTimeout != 10*time.Second {
|
||||
t.Errorf("ReadHeaderTimeout = %v, want 10s", s.ReadHeaderTimeout)
|
||||
}
|
||||
|
||||
|
||||
if s.WriteTimeout != 30*time.Second {
|
||||
t.Errorf("WriteTimeout = %v, want 30s", s.WriteTimeout)
|
||||
}
|
||||
|
||||
|
||||
if s.IdleTimeout != 120*time.Second {
|
||||
t.Errorf("IdleTimeout = %v, want 120s", s.IdleTimeout)
|
||||
}
|
||||
|
||||
|
||||
if s.MaxHeaderBytes != 1<<20 {
|
||||
t.Errorf("MaxHeaderBytes = %d, want %d", s.MaxHeaderBytes, 1<<20)
|
||||
}
|
||||
|
||||
57
internal/app/batch_utils_test.go
Normal file
57
internal/app/batch_utils_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Test utility functions from batch_runtime.go
|
||||
|
||||
func TestSleepWithContext_Normal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
start := time.Now()
|
||||
err := sleepWithContext(ctx, 1*time.Millisecond)
|
||||
elapsed := time.Since(start)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("sleep should not error: %v", err)
|
||||
}
|
||||
if elapsed < 1*time.Millisecond {
|
||||
t.Error("should have slept")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSleepWithContext_Canceled(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
|
||||
start := time.Now()
|
||||
err := sleepWithContext(ctx, 100*time.Millisecond)
|
||||
elapsed := time.Since(start)
|
||||
|
||||
if err == nil {
|
||||
t.Error("canceled context should return error")
|
||||
}
|
||||
if elapsed > 10*time.Millisecond {
|
||||
t.Error("should have returned early due to cancellation")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirstNonEmptyString(t *testing.T) {
|
||||
if firstNonEmptyString("", "", "value") != "value" {
|
||||
t.Error("should return first non-empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirstNonEmptyString_First(t *testing.T) {
|
||||
if firstNonEmptyString("first", "second", "third") != "first" {
|
||||
t.Error("should return first value when all non-empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirstNonEmptyString_AllEmpty(t *testing.T) {
|
||||
if firstNonEmptyString("", "", "") != "" {
|
||||
t.Error("all empty should return empty")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user