@@ -3,7 +3,11 @@ package auditserver
33import (
44 "bytes"
55 "encoding/json"
6+ "errors"
67 "fmt"
8+ "github.com/ncode/vault-audit-filter/pkg/forwarder"
9+ "github.com/ncode/vault-audit-filter/pkg/messaging"
10+ "github.com/stretchr/testify/require"
711 "io"
812 "io/ioutil"
913 "net"
@@ -799,3 +803,101 @@ func TestAuditServer_React_WithForwarding(t *testing.T) {
799803 })
800804 }
801805}
806+
807+ type dummyMessenger struct {
808+ sendErr error
809+ calls int
810+ }
811+
812+ func (d * dummyMessenger ) Send (_ string ) error {
813+ d .calls ++
814+ return d .sendErr
815+ }
816+
817+ type dummyForwarder struct {
818+ forwardErr error
819+ calls int
820+ }
821+
822+ func (d * dummyForwarder ) Forward (_ []byte ) error {
823+ d .calls ++
824+ return d .forwardErr
825+ }
826+
827+ // minimal JSON frame that parses into an AuditLog
828+ func auditFrame () []byte {
829+ return []byte (`{"type":"request","time":"2000-01-01T00:00:00Z","auth":{},"request":{},"response":{}}` )
830+ }
831+
832+ // rule‑group factory: match=true → no rules (auto‑match); match=false → 1 rule that always fails.
833+ func newRuleGroup (match bool , msgr messaging.Messenger , fwd forwarder.Forwarder ) RuleGroup {
834+ var compiled []CompiledRule
835+ if ! match {
836+ compiled = []CompiledRule {{Program : nil }} // any non‑nil slice forces shouldLog=false
837+ }
838+ return RuleGroup {
839+ Name : "grp" ,
840+ CompiledRules : compiled ,
841+ Messenger : msgr ,
842+ Forwarder : fwd ,
843+ Writer : new (bytes.Buffer ), // satisfies io.Writer, avoids disk I/O
844+ }
845+ }
846+
847+ func TestReact_Branches (t * testing.T ) {
848+ tests := []struct {
849+ name string
850+ group RuleGroup
851+ wantAction gnet.Action
852+ wantMsgCalls int
853+ wantFwdCalls int
854+ }{
855+ {
856+ name : "match_no_side_effects_returns_None" ,
857+ group : newRuleGroup (true , nil , nil ),
858+ wantAction : gnet .None ,
859+ },
860+ {
861+ name : "forwarder_ok_triggers_Close" ,
862+ group : newRuleGroup (true , nil , & dummyForwarder {}),
863+ wantAction : gnet .Close ,
864+ wantFwdCalls : 1 ,
865+ },
866+ {
867+ name : "forwarder_error_triggers_Close" ,
868+ group : newRuleGroup (true , nil , & dummyForwarder {forwardErr : errors .New ("x" )}),
869+ wantAction : gnet .Close ,
870+ wantFwdCalls : 1 ,
871+ },
872+ {
873+ name : "messenger_error_triggers_Close" ,
874+ group : newRuleGroup (true , & dummyMessenger {sendErr : errors .New ("x" )}, nil ),
875+ wantAction : gnet .Close ,
876+ wantMsgCalls : 1 ,
877+ },
878+ {
879+ name : "no_match_triggers_Close" ,
880+ group : newRuleGroup (false , nil , nil ),
881+ wantAction : gnet .Close ,
882+ },
883+ }
884+
885+ frame := auditFrame ()
886+
887+ for _ , tc := range tests {
888+ tc := tc // capture range variable
889+ t .Run (tc .name , func (t * testing.T ) {
890+ srv := & AuditServer {ruleGroups : []RuleGroup {tc .group }}
891+ _ , act := srv .React (frame , nil )
892+
893+ require .Equal (t , tc .wantAction , act )
894+
895+ if dm , ok := tc .group .Messenger .(* dummyMessenger ); ok {
896+ require .Equal (t , tc .wantMsgCalls , dm .calls )
897+ }
898+ if df , ok := tc .group .Forwarder .(* dummyForwarder ); ok {
899+ require .Equal (t , tc .wantFwdCalls , df .calls )
900+ }
901+ })
902+ }
903+ }
0 commit comments