You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/internal/event/eventer_gate_test.go

207 lines
4.5 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package event
import (
"bytes"
"context"
"fmt"
"strings"
"sync"
"testing"
"github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestEventer_Gating(t *testing.T) {
t.Parallel()
require := require.New(t)
buffer := new(bytes.Buffer)
eventerConfig := EventerConfig{
AuditEnabled: true,
ObservationsEnabled: true,
SysEventsEnabled: true,
Sinks: []*SinkConfig{
{
Name: "test-sink",
EventTypes: []Type{EveryType},
Format: TextHclogSinkFormat,
Type: WriterSink,
WriterConfig: &WriterSinkTypeConfig{
Writer: buffer,
},
},
},
}
testLock := &sync.Mutex{}
testLogger := testLogger(t, testLock)
eventer, err := NewEventer(
testLogger,
testLock,
"TestEventer_Gating",
eventerConfig,
WithGating(true),
)
require.NoError(err)
ctx, err := NewEventerContext(context.Background(), eventer)
require.NoError(err)
// This test sends a series of events of different types. The tests are
// meant to be in order as we want to send some that should be gated and
// some that shouldn't and ensure correct behavior at each step.
var totalEvents int
tests := []struct {
name string
eventFn func()
expectedGatedEvents int
}{
{
name: "system-event-1",
eventFn: func() {
WriteSysEvent(ctx, "system-event-1", "system-event-1")
totalEvents++
},
expectedGatedEvents: 1,
},
{
name: "system-event-2",
eventFn: func() {
WriteSysEvent(ctx, "system-event-2", "system-event-2")
totalEvents++
},
expectedGatedEvents: 2,
},
{
name: "audit-1",
eventFn: func() {
require.NoError(WriteAudit(ctx, "audit-1"))
totalEvents++
},
expectedGatedEvents: 2,
},
{
name: "observation-1",
eventFn: func() {
require.NoError(WriteObservation(ctx, "observation-1", WithId("observation-1"), WithHeader("foo", "bar")))
totalEvents++
},
expectedGatedEvents: 2,
},
{
name: "error-1",
eventFn: func() {
WriteError(ctx, "error-1", fmt.Errorf("error-1"))
totalEvents++
},
expectedGatedEvents: 3,
},
{
name: "error-2",
eventFn: func() {
WriteError(ctx, "error-2", fmt.Errorf("error-2"))
totalEvents++
},
expectedGatedEvents: 4,
},
// This should result in all events being flushed so none gated
{
name: "release-gate",
eventFn: func() {
require.NoError(eventer.ReleaseGate())
},
expectedGatedEvents: 0,
},
// From here on out we're verifying that all events of all types go through
{
name: "system-event-3",
eventFn: func() {
WriteSysEvent(ctx, "system-event-3", "system-event-3")
totalEvents++
},
expectedGatedEvents: 0,
},
{
name: "audit-2",
eventFn: func() {
require.NoError(WriteAudit(ctx, "audit-2"))
totalEvents++
},
expectedGatedEvents: 0,
},
{
name: "observation-2",
eventFn: func() {
require.NoError(WriteObservation(ctx, "observation-2", WithId("observation-2"), WithHeader("foo", "bar")))
totalEvents++
},
expectedGatedEvents: 0,
},
{
name: "error-2",
eventFn: func() {
WriteError(ctx, "error-2", fmt.Errorf("error-2"))
totalEvents++
},
expectedGatedEvents: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
tt.eventFn()
assert.Len(strutil.RemoveEmpty(strings.Split(buffer.String(), "\n")), totalEvents-tt.expectedGatedEvents, buffer.String())
})
}
}
func TestReleaseGate_NoError_CanceledContext(t *testing.T) {
require := require.New(t)
buffer := new(bytes.Buffer)
eventerConfig := EventerConfig{
AuditEnabled: true,
ObservationsEnabled: true,
SysEventsEnabled: true,
Sinks: []*SinkConfig{
{
Name: "test-sink",
EventTypes: []Type{EveryType},
Format: TextHclogSinkFormat,
Type: WriterSink,
WriterConfig: &WriterSinkTypeConfig{
Writer: buffer,
},
},
},
}
testLock := &sync.Mutex{}
testLogger := testLogger(t, testLock)
eventer, err := NewEventer(
testLogger,
testLock,
"TestEventer_Gating",
eventerConfig,
WithGating(true),
)
require.NoError(err)
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
ctx, err = NewEventerContext(ctx, eventer)
require.NoError(err)
WriteError(ctx, "error-1", fmt.Errorf("error-1"))
_ = WriteObservation(ctx, "observation-1", WithId("observation-1"), WithHeader("foo", "bar"))
cancel()
require.NoError(eventer.ReleaseGate())
}