mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-05 04:56:11 +00:00
125 lines
4.2 KiB
Go
125 lines
4.2 KiB
Go
// Copyright 2025 the Pinniped contributors. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package testutil
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.pinniped.dev/internal/federationdomain/stateparam"
|
|
)
|
|
|
|
func RequireLogLines(t *testing.T, wantLogs []string, log *bytes.Buffer) {
|
|
t.Helper()
|
|
|
|
expectedLogs := ""
|
|
if len(wantLogs) > 0 {
|
|
expectedLogs = strings.Join(wantLogs, "\n") + "\n"
|
|
}
|
|
require.Equal(t, expectedLogs, log.String())
|
|
}
|
|
|
|
type WantedAuditLog struct {
|
|
Message string
|
|
Params map[string]any
|
|
}
|
|
|
|
func WantAuditLog(message string, params map[string]any) WantedAuditLog {
|
|
result := WantedAuditLog{
|
|
Message: message,
|
|
Params: params,
|
|
}
|
|
return result
|
|
}
|
|
|
|
func WantAuditIDOnEveryAuditLog(wantedAuditLogs []WantedAuditLog, wantAuditID string) {
|
|
for _, wantedAuditLog := range wantedAuditLogs {
|
|
wantedAuditLog.Params["auditID"] = wantAuditID
|
|
}
|
|
}
|
|
|
|
func GetStateParamFromRequestURL(t *testing.T, fullURL string) stateparam.Encoded {
|
|
if fullURL == "" {
|
|
var empty stateparam.Encoded
|
|
return empty
|
|
}
|
|
|
|
path, err := url.Parse(fullURL)
|
|
require.NoError(t, err)
|
|
return stateparam.Encoded(path.Query().Get("state"))
|
|
}
|
|
|
|
func GetStateParamFromRequestBody(t *testing.T, body string) stateparam.Encoded {
|
|
values, err := url.ParseQuery(body)
|
|
require.NoError(t, err)
|
|
return stateparam.Encoded(values.Get("state"))
|
|
}
|
|
|
|
func CompareAuditLogs(t *testing.T, wantAuditLogs []WantedAuditLog, actualAuditLogsOneLiner string) {
|
|
t.Helper()
|
|
|
|
// There are tests that verify that no audit events were emitted
|
|
if len(wantAuditLogs) == 0 {
|
|
require.Empty(t, actualAuditLogsOneLiner, "no audit events were expected, but some were found")
|
|
return
|
|
}
|
|
|
|
wantJsonAuditLogs := make([]map[string]any, 0)
|
|
wantMessages := make([]string, 0)
|
|
for _, wantAuditLog := range wantAuditLogs {
|
|
wantJsonAuditLog := make(map[string]any)
|
|
require.Empty(t, wantAuditLog.Params["level"], "do not specify level in audit log expectations")
|
|
wantJsonAuditLog["level"] = "info"
|
|
require.Empty(t, wantAuditLog.Params["message"], "do not specify message in audit log expectations")
|
|
wantJsonAuditLog["message"] = wantAuditLog.Message
|
|
wantMessages = append(wantMessages, wantAuditLog.Message)
|
|
wantJsonAuditLog["auditEvent"] = true
|
|
require.Empty(t, wantAuditLog.Params["timestamp"], "do not specify timestamp in audit log expectations")
|
|
wantJsonAuditLog["timestamp"] = "2099-08-08T13:57:36.123456Z"
|
|
for k, v := range wantAuditLog.Params {
|
|
wantJsonAuditLog[k] = v
|
|
}
|
|
wantJsonAuditLogs = append(wantJsonAuditLogs, wantJsonAuditLog)
|
|
}
|
|
|
|
actualJsonAuditLogs := make([]map[string]any, 0)
|
|
actualMessages := make([]string, 0)
|
|
actualAuditLogs := strings.Split(actualAuditLogsOneLiner, "\n")
|
|
require.GreaterOrEqual(t, len(actualAuditLogs), 2,
|
|
"expected %d log lines, found %d", len(wantAuditLogs), len(actualAuditLogs)-1)
|
|
actualAuditLogs = actualAuditLogs[:len(actualAuditLogs)-1] // trim off the last ""
|
|
for _, actualAuditLog := range actualAuditLogs {
|
|
actualJsonAuditLog := make(map[string]any)
|
|
err := json.Unmarshal([]byte(actualAuditLog), &actualJsonAuditLog)
|
|
require.NoError(t, err)
|
|
|
|
// we don't care to test exact equality on the caller - just make sure it is a non-empty string
|
|
caller, ok := actualJsonAuditLog["caller"]
|
|
require.True(t, ok)
|
|
require.NotEmpty(t, caller, "caller for message %q must not be empty", actualJsonAuditLog["message"])
|
|
delete(actualJsonAuditLog, "caller")
|
|
actualJsonAuditLogs = append(actualJsonAuditLogs, actualJsonAuditLog)
|
|
|
|
actualMessage, ok := actualJsonAuditLog["message"].(string)
|
|
require.True(t, ok, "actual message is not a string, instead %+v", actualJsonAuditLog["message"])
|
|
actualMessages = append(actualMessages, actualMessage)
|
|
}
|
|
|
|
// We should check array indices first so that we don't exceed any boundaries.
|
|
// But we also want to be sure to indicate to the caller what went wrong, so compare the messages.
|
|
require.Equal(t, wantMessages, actualMessages)
|
|
|
|
// We can expect the audit logs to be ordered deterministically.
|
|
for i := range wantJsonAuditLogs {
|
|
// compare each item individually so we know which message it is
|
|
require.Equal(t, wantJsonAuditLogs[i], actualJsonAuditLogs[i],
|
|
"audit event for message %q does not match", wantJsonAuditLogs[i]["message"])
|
|
}
|
|
}
|