feature (events): add TestWithoutEventing(t) (#2137)

pull/2149/head
Jim 4 years ago committed by GitHub
parent 6ceda0e595
commit 0425384b49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"strconv"
"strings"
@ -373,6 +374,11 @@ type TestControllerOpts struct {
// If true, the controller will not be started
DisableAutoStart bool
// DisableEventing, if true the test controller will not create events
// You must not run the test in parallel (no calls to t.Parallel) since the
// this option relies on modifying the system wide default eventer.
DisableEventing bool
// DisableAuthorizationFailures will still cause authz checks to be
// performed but they won't cause 403 Forbidden. Useful for API-level
// testing to avoid a lot of faff.
@ -543,8 +549,32 @@ func TestControllerConfig(t testing.TB, ctx context.Context, tc *TestController,
}
opts.Config.Controller.SchedulerRunJobInterval = opts.SchedulerRunJobInterval
if err := tc.b.SetupEventing(tc.b.Logger, tc.b.StderrLock, opts.Config.Controller.Name, base.WithEventerConfig(opts.Config.Eventing)); err != nil {
t.Fatal(err)
switch {
case opts.DisableEventing:
opts.Config.Eventing = &event.EventerConfig{
AuditEnabled: false,
ObservationsEnabled: false,
SysEventsEnabled: false,
}
testLogger := hclog.New(&hclog.LoggerOptions{
Mutex: tc.b.StderrLock,
Output: io.Discard,
})
e, err := event.NewEventer(
testLogger,
tc.b.StderrLock,
opts.Config.Controller.Name,
*opts.Config.Eventing,
)
if err != nil {
t.Fatal(err)
}
tc.b.Eventer = e
event.TestWithoutEventing(t) // this ensures the sys eventer will also stop eventing
default:
if err := tc.b.SetupEventing(tc.b.Logger, tc.b.StderrLock, opts.Config.Controller.Name, base.WithEventerConfig(opts.Config.Eventing)); err != nil {
t.Fatal(err)
}
}
// Initialize status grace period

@ -1,7 +1,12 @@
package controller
import (
"bytes"
"io"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_TestController(t *testing.T) {
@ -17,4 +22,44 @@ func Test_TestController(t *testing.T) {
defer tc1.Shutdown()
defer tc2.Shutdown()
})
t.Run("controller-without-eventing", func(t *testing.T) {
const op = "Test_TestWithoutEventing"
assert := assert.New(t)
// this isn't the best solution for capturing stdout but it works for now...
captureFn := func(fn func()) string {
old := os.Stdout
defer func() {
os.Stderr = old
}()
r, w, _ := os.Pipe()
os.Stderr = w
{
fn()
}
outC := make(chan string)
// copy the output in a separate goroutine so writing to stderr can't block indefinitely
go func() {
var buf bytes.Buffer
io.Copy(&buf, r)
outC <- buf.String()
}()
// back to normal state
w.Close()
return <-outC
}
assert.Empty(captureFn(func() {
tc := NewTestController(t, &TestControllerOpts{DisableEventing: true})
defer tc.Shutdown()
}))
assert.NotEmpty(captureFn(func() {
tc := NewTestController(t, nil)
defer tc.Shutdown()
}))
})
}

@ -170,7 +170,8 @@ func NewAuditEncryptFilter(opt ...Option) (*encrypt.Filter, error) {
}
// NewEventer creates a new Eventer using the config. Supports options:
// WithNow, WithSerializationLock, WithBroker, WithAuditWrapper
// WithNow, WithSerializationLock, WithBroker, WithAuditWrapper,
// WithNoDefaultSink
func NewEventer(log hclog.Logger, serializationLock *sync.Mutex, serverName string, c EventerConfig, opt ...Option) (*Eventer, error) {
const op = "event.NewEventer"
if log == nil {
@ -183,9 +184,11 @@ func NewEventer(log hclog.Logger, serializationLock *sync.Mutex, serverName stri
return nil, fmt.Errorf("%s: missing server name: %w", op, ErrInvalidParameter)
}
opts := getOpts(opt...)
// if there are no sinks in config, then we'll default to just one stderr
// sink.
if len(c.Sinks) == 0 {
if len(c.Sinks) == 0 && !opts.withNoDefaultSink {
c.Sinks = append(c.Sinks, DefaultSink())
}
@ -195,7 +198,6 @@ func NewEventer(log hclog.Logger, serializationLock *sync.Mutex, serverName stri
var auditPipelines, observationPipelines, errPipelines, sysPipelines []pipeline
opts := getOpts(opt...)
var b broker
switch {
case opts.withBroker != nil:

@ -54,6 +54,7 @@ type options struct {
withObservationSink bool // test only option
withSysSink bool // test only option
withSinkFormat SinkFormat // test only option
withNoDefaultSink bool // test only option
}
func getDefaultOptions() options {

@ -4,16 +4,41 @@ import (
"context"
"io/ioutil"
"os"
"sync"
"testing"
"time"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/groups"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/wrapperspb"
)
// TestWithoutEventing allows the caller to "disable" all eventing for a test.
// You must not run the test in parallel (no calls to t.Parallel) since the
// function relies on modifying the system wide default eventer.
func TestWithoutEventing(t testing.TB) *Eventer {
t.Helper()
require := require.New(t)
testConfig := EventerConfig{
AuditEnabled: false,
ObservationsEnabled: false,
SysEventsEnabled: false,
}
testLock := &sync.Mutex{}
testLogger := hclog.New(&hclog.LoggerOptions{
Mutex: testLock,
Output: ioutil.Discard,
})
testEventer, err := NewEventer(testLogger, testLock, "TestWithoutEventing", testConfig, withNoDefaultSink(t))
require.NoError(err)
require.NoError(InitSysEventer(testLogger, testLock, "TestWithoutEventing", WithEventer(testEventer)))
return testEventer
}
// TestGetEventerConfig is a test accessor for the eventer's config
func TestGetEventerConfig(t testing.TB, e *Eventer) EventerConfig {
t.Helper()
@ -231,6 +256,14 @@ func TestWithSysSink(t testing.TB) Option {
}
}
// withNoDefaultSink is an unexported test option
func withNoDefaultSink(t testing.TB) Option {
t.Helper()
return func(o *options) {
o.withNoDefaultSink = true
}
}
// testWithSinkFormat is an unexported and a test option
func testWithSinkFormat(t testing.TB, fmt SinkFormat) Option {
t.Helper()

@ -0,0 +1,55 @@
package event_test
import (
"bytes"
"context"
"fmt"
"io"
"os"
"testing"
"github.com/hashicorp/boundary/internal/observability/event"
"github.com/stretchr/testify/assert"
)
func Test_TestWithoutEventing(t *testing.T) {
const op = "Test_TestWithoutEventing"
assert := assert.New(t)
// this isn't the best solution for capturing stdout but it works for now...
captureFn := func(fn func()) string {
old := os.Stdout
defer func() {
os.Stderr = old
}()
r, w, _ := os.Pipe()
os.Stderr = w
{
fn()
}
outC := make(chan string)
// copy the output in a separate goroutine so writing to stderr can't block indefinitely
go func() {
var buf bytes.Buffer
io.Copy(&buf, r)
outC <- buf.String()
}()
// back to normal state
w.Close()
return <-outC
}
assert.NotEmpty(captureFn(func() {
fmt.Fprintln(os.Stderr, "not-empty")
}))
assert.Empty(captureFn(func() {
testCtx := context.Background()
event.TestWithoutEventing(t)
event.WriteSysEvent(testCtx, op, "test-event")
}))
}
Loading…
Cancel
Save