145 lines
4.6 KiB
Go
145 lines
4.6 KiB
Go
package oci
|
||
|
||
import (
|
||
"reflect"
|
||
"testing"
|
||
"time"
|
||
|
||
"github.com/oracle/oci-go-sdk/v65/audit"
|
||
"github.com/oracle/oci-go-sdk/v65/common"
|
||
)
|
||
|
||
func TestToAuditEvent(t *testing.T) {
|
||
eventTime := time.Date(2026, 7, 6, 10, 30, 0, 0, time.UTC)
|
||
tests := []struct {
|
||
name string
|
||
ev audit.AuditEvent
|
||
want AuditEvent
|
||
}{
|
||
{
|
||
name: "全字段齐全",
|
||
ev: audit.AuditEvent{
|
||
EventId: common.String("evt-abc"),
|
||
Source: common.String("ComputeApi"),
|
||
EventTime: &common.SDKTime{Time: eventTime},
|
||
Data: &audit.Data{
|
||
EventName: common.String("TerminateInstance"),
|
||
ResourceName: common.String("web-1"),
|
||
CompartmentName: common.String("prod"),
|
||
Identity: &audit.Identity{
|
||
PrincipalName: common.String("api-admin"),
|
||
IpAddress: common.String("1.2.3.4"),
|
||
},
|
||
Request: &audit.Request{
|
||
Action: common.String("DELETE"),
|
||
Path: common.String("/20160918/instances/ocid1..."),
|
||
},
|
||
Response: &audit.Response{Status: common.String("204")},
|
||
},
|
||
},
|
||
want: AuditEvent{
|
||
EventId: "evt-abc",
|
||
EventTime: &eventTime,
|
||
EventName: "TerminateInstance",
|
||
Source: "ComputeApi",
|
||
ResourceName: "web-1",
|
||
CompartmentName: "prod",
|
||
PrincipalName: "api-admin",
|
||
IPAddress: "1.2.3.4",
|
||
Status: "204",
|
||
RequestAction: "DELETE",
|
||
RequestPath: "/20160918/instances/ocid1...",
|
||
},
|
||
},
|
||
{
|
||
name: "Data 为 nil 时只保留信封字段",
|
||
ev: audit.AuditEvent{
|
||
Source: common.String("VcnApi"),
|
||
EventTime: &common.SDKTime{Time: eventTime},
|
||
},
|
||
want: AuditEvent{EventTime: &eventTime, Source: "VcnApi"},
|
||
},
|
||
{
|
||
name: "嵌套局部 nil 各自安全跳过",
|
||
ev: audit.AuditEvent{
|
||
Data: &audit.Data{
|
||
EventName: common.String("GetInstance"),
|
||
Identity: nil,
|
||
Request: &audit.Request{Path: common.String("/instances")},
|
||
Response: nil,
|
||
},
|
||
},
|
||
want: AuditEvent{EventName: "GetInstance", RequestPath: "/instances"},
|
||
},
|
||
{
|
||
name: "空事件全部零值",
|
||
ev: audit.AuditEvent{},
|
||
want: AuditEvent{},
|
||
},
|
||
}
|
||
for _, tt := range tests {
|
||
t.Run(tt.name, func(t *testing.T) {
|
||
if got := toAuditEvent(tt.ev); !auditEventEqual(got, tt.want) {
|
||
t.Errorf("toAuditEvent() = %+v, want %+v", got, tt.want)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// auditEventEqual 比较两个 DTO:EventTime 按值比较,Raw 不参与,其余反射比较。
|
||
func auditEventEqual(a, b AuditEvent) bool {
|
||
if (a.EventTime == nil) != (b.EventTime == nil) {
|
||
return false
|
||
}
|
||
if a.EventTime != nil && !a.EventTime.Equal(*b.EventTime) {
|
||
return false
|
||
}
|
||
a.EventTime, b.EventTime = nil, nil
|
||
a.Raw, b.Raw = nil, nil
|
||
return reflect.DeepEqual(a, b)
|
||
}
|
||
|
||
func TestSortAuditEvents(t *testing.T) {
|
||
t1 := time.Date(2026, 7, 6, 8, 0, 0, 0, time.UTC)
|
||
t2 := time.Date(2026, 7, 6, 9, 0, 0, 0, time.UTC)
|
||
items := []AuditEvent{
|
||
{EventName: "old", EventTime: &t1},
|
||
{EventName: "no-time", EventTime: nil},
|
||
{EventName: "new", EventTime: &t2},
|
||
}
|
||
sortAuditEvents(items)
|
||
got := []string{items[0].EventName, items[1].EventName, items[2].EventName}
|
||
want := []string{"new", "old", "no-time"}
|
||
for i := range want {
|
||
if got[i] != want[i] {
|
||
t.Fatalf("sortAuditEvents() order = %v, want %v", got, want)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestKeepAuditEvent(t *testing.T) {
|
||
cases := []struct {
|
||
name string
|
||
event AuditEvent
|
||
keep bool
|
||
}{
|
||
{"公网IP的普通事件保留", AuditEvent{EventName: "CreateUser", IPAddress: "203.0.113.7"}, true},
|
||
{"SummarizeMetricsData 噪声排除", AuditEvent{EventName: "SummarizeMetricsData", IPAddress: "203.0.113.7"}, false},
|
||
{"内网10段发起排除", AuditEvent{EventName: "ListInstances", IPAddress: "10.1.2.3"}, false},
|
||
{"内网172.16段发起排除", AuditEvent{EventName: "ListInstances", IPAddress: "172.20.0.1"}, false},
|
||
{"172.15不属内网保留", AuditEvent{EventName: "ListInstances", IPAddress: "172.15.0.1"}, true},
|
||
{"内网192.168段发起排除", AuditEvent{EventName: "ListInstances", IPAddress: "192.168.1.1"}, false},
|
||
{"CGNAT 100.64段排除", AuditEvent{EventName: "ListInstances", IPAddress: "100.100.0.1"}, false},
|
||
{"100.128不属CGNAT保留", AuditEvent{EventName: "ListInstances", IPAddress: "100.128.0.1"}, true},
|
||
{"IP为空保留(控制面事件)", AuditEvent{EventName: "TerminateInstance", IPAddress: ""}, true},
|
||
{"IP不可解析保留", AuditEvent{EventName: "ListInstances", IPAddress: "not-an-ip"}, true},
|
||
}
|
||
for _, tc := range cases {
|
||
t.Run(tc.name, func(t *testing.T) {
|
||
if got := keepAuditEvent(tc.event); got != tc.keep {
|
||
t.Fatalf("keepAuditEvent(%+v) = %v, want %v", tc.event, got, tc.keep)
|
||
}
|
||
})
|
||
}
|
||
}
|