Our test helper packages were not possible to use with benchmarks. This refactor switches to testing.TB to allow both tests and benchmarks to use the helpers.
285 lines
6.7 KiB
Go
285 lines
6.7 KiB
Go
package event
|
|
|
|
import (
|
|
"context"
|
|
"io/ioutil"
|
|
"os"
|
|
"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/stretchr/testify/require"
|
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
|
)
|
|
|
|
// TestGetEventerConfig is a test accessor for the eventer's config
|
|
func TestGetEventerConfig(t testing.TB, e *Eventer) EventerConfig {
|
|
t.Helper()
|
|
return e.conf
|
|
}
|
|
|
|
// TestResetSysEventer will reset event.syseventer to an uninitialized state.
|
|
func TestResetSystEventer(t testing.TB) {
|
|
t.Helper()
|
|
sysEventerLock.Lock()
|
|
defer sysEventerLock.Unlock()
|
|
sysEventer = nil
|
|
}
|
|
|
|
type TestConfig struct {
|
|
EventerConfig EventerConfig
|
|
AllEvents *os.File
|
|
ErrorEvents *os.File
|
|
ObservationEvents *os.File
|
|
AuditEvents *os.File
|
|
}
|
|
|
|
// TestEventerConfig creates a test config and registers a cleanup func for its
|
|
// test tmp files.
|
|
func TestEventerConfig(t testing.TB, testName string, opt ...Option) TestConfig {
|
|
t.Helper()
|
|
require := require.New(t)
|
|
tmpAllFile, err := ioutil.TempFile("./", "tmp-all-events-"+testName)
|
|
require.NoError(err)
|
|
|
|
tmpErrFile, err := ioutil.TempFile("./", "tmp-errors-"+testName)
|
|
require.NoError(err)
|
|
|
|
t.Cleanup(func() {
|
|
os.Remove(tmpAllFile.Name())
|
|
os.Remove(tmpErrFile.Name())
|
|
})
|
|
|
|
opts := getOpts(opt...)
|
|
if opts.withSinkFormat == "" {
|
|
opts.withSinkFormat = JSONSinkFormat
|
|
}
|
|
|
|
c := TestConfig{
|
|
EventerConfig: EventerConfig{
|
|
ObservationsEnabled: true,
|
|
AuditEnabled: true,
|
|
Sinks: []*SinkConfig{
|
|
{
|
|
Name: "every-type-file-sink",
|
|
Type: FileSink,
|
|
EventTypes: []Type{EveryType},
|
|
Format: opts.withSinkFormat,
|
|
FileConfig: &FileSinkTypeConfig{
|
|
Path: "./",
|
|
FileName: tmpAllFile.Name(),
|
|
},
|
|
AuditConfig: DefaultAuditConfig(),
|
|
},
|
|
{
|
|
Name: "stderr",
|
|
Type: StderrSink,
|
|
EventTypes: []Type{EveryType},
|
|
Format: opts.withSinkFormat,
|
|
AuditConfig: DefaultAuditConfig(),
|
|
},
|
|
{
|
|
Name: "err-file-sink",
|
|
Type: FileSink,
|
|
EventTypes: []Type{ErrorType},
|
|
Format: opts.withSinkFormat,
|
|
FileConfig: &FileSinkTypeConfig{
|
|
Path: "./",
|
|
FileName: tmpErrFile.Name(),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
AllEvents: tmpAllFile,
|
|
ErrorEvents: tmpErrFile,
|
|
}
|
|
if opts.withAuditSink {
|
|
tmpFile, err := ioutil.TempFile("./", "tmp-audit-"+testName)
|
|
require.NoError(err)
|
|
t.Cleanup(func() {
|
|
os.Remove(tmpFile.Name())
|
|
})
|
|
c.EventerConfig.Sinks = append(c.EventerConfig.Sinks, &SinkConfig{
|
|
Name: "audit-file-sink",
|
|
Type: FileSink,
|
|
EventTypes: []Type{AuditType},
|
|
Format: opts.withSinkFormat,
|
|
FileConfig: &FileSinkTypeConfig{
|
|
Path: "./",
|
|
FileName: tmpFile.Name(),
|
|
},
|
|
AuditConfig: DefaultAuditConfig(),
|
|
})
|
|
c.AuditEvents = tmpFile
|
|
}
|
|
if opts.withObservationSink {
|
|
tmpFile, err := ioutil.TempFile("./", "tmp-observation-"+testName)
|
|
require.NoError(err)
|
|
t.Cleanup(func() {
|
|
os.Remove(tmpFile.Name())
|
|
})
|
|
c.EventerConfig.Sinks = append(c.EventerConfig.Sinks, &SinkConfig{
|
|
Name: "err-observation-sink",
|
|
Type: FileSink,
|
|
EventTypes: []Type{ObservationType},
|
|
Format: opts.withSinkFormat,
|
|
FileConfig: &FileSinkTypeConfig{
|
|
Path: "./",
|
|
FileName: tmpFile.Name(),
|
|
},
|
|
})
|
|
c.ObservationEvents = tmpFile
|
|
}
|
|
if opts.withSysSink {
|
|
tmpFile, err := ioutil.TempFile("./", "tmp-sysevents-"+testName)
|
|
require.NoError(err)
|
|
t.Cleanup(func() {
|
|
os.Remove(tmpFile.Name())
|
|
})
|
|
c.EventerConfig.Sinks = append(c.EventerConfig.Sinks, &SinkConfig{
|
|
Name: "err-sysevents-sink",
|
|
Type: FileSink,
|
|
EventTypes: []Type{SystemType},
|
|
Format: opts.withSinkFormat,
|
|
FileConfig: &FileSinkTypeConfig{
|
|
Path: "./",
|
|
FileName: tmpFile.Name(),
|
|
},
|
|
})
|
|
}
|
|
return c
|
|
}
|
|
|
|
// TestRequestInfo provides a test RequestInfo
|
|
func TestRequestInfo(t testing.TB) *RequestInfo {
|
|
t.Helper()
|
|
return &RequestInfo{
|
|
EventId: "test-event-id",
|
|
Id: "test-request-info",
|
|
Method: "POST",
|
|
Path: "/test/request/info",
|
|
PublicId: "public-id",
|
|
}
|
|
}
|
|
|
|
func testAuth(t testing.TB) *Auth {
|
|
t.Helper()
|
|
return &Auth{
|
|
UserEmail: "test-auth@example.com",
|
|
UserName: "test-auth-user-name",
|
|
}
|
|
}
|
|
|
|
func testRequest(t testing.TB) *Request {
|
|
t.Helper()
|
|
return &Request{
|
|
Operation: "op",
|
|
Endpoint: "/group/<id>",
|
|
Details: &pbs.GetGroupRequest{
|
|
Id: "group-id",
|
|
},
|
|
}
|
|
}
|
|
|
|
func testResponse(t testing.TB) *Response {
|
|
t.Helper()
|
|
return &Response{
|
|
StatusCode: 200,
|
|
Details: &pbs.GetGroupResponse{
|
|
Item: &groups.Group{
|
|
Id: "group-id",
|
|
ScopeId: "org-id",
|
|
Name: &wrapperspb.StringValue{
|
|
Value: "group-name",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// TestWithBroker is an unexported and a test option for passing in an optional broker
|
|
func TestWithBroker(t testing.TB, b broker) Option {
|
|
t.Helper()
|
|
return func(o *options) {
|
|
o.withBroker = b
|
|
}
|
|
}
|
|
|
|
// TestWithObservationSink is a test option
|
|
func TestWithObservationSink(t testing.TB) Option {
|
|
t.Helper()
|
|
return func(o *options) {
|
|
o.withObservationSink = true
|
|
}
|
|
}
|
|
|
|
// TestWithAuditSink is a test option
|
|
func TestWithAuditSink(t testing.TB) Option {
|
|
t.Helper()
|
|
return func(o *options) {
|
|
o.withAuditSink = true
|
|
}
|
|
}
|
|
|
|
// TestWithSysSink is a test option
|
|
func TestWithSysSink(t testing.TB) Option {
|
|
t.Helper()
|
|
return func(o *options) {
|
|
o.withSysSink = true
|
|
}
|
|
}
|
|
|
|
// testWithSinkFormat is an unexported and a test option
|
|
func testWithSinkFormat(t testing.TB, fmt SinkFormat) Option {
|
|
t.Helper()
|
|
return func(o *options) {
|
|
o.withSinkFormat = fmt
|
|
}
|
|
}
|
|
|
|
type testMockBroker struct {
|
|
reopened bool
|
|
stopTimeAt time.Time
|
|
registeredNodeIds []eventlogger.NodeID
|
|
successThresholds map[eventlogger.EventType]int
|
|
pipelines []eventlogger.Pipeline
|
|
|
|
errorOnSend error
|
|
}
|
|
|
|
func (b *testMockBroker) Reopen(ctx context.Context) error {
|
|
b.reopened = true
|
|
return nil
|
|
}
|
|
|
|
func (b *testMockBroker) RegisterPipeline(def eventlogger.Pipeline) error {
|
|
b.pipelines = append(b.pipelines, def)
|
|
return nil
|
|
}
|
|
|
|
func (b *testMockBroker) Send(ctx context.Context, t eventlogger.EventType, payload interface{}) (eventlogger.Status, error) {
|
|
if b.errorOnSend != nil {
|
|
return eventlogger.Status{}, b.errorOnSend
|
|
}
|
|
return eventlogger.Status{}, nil
|
|
}
|
|
|
|
func (b *testMockBroker) StopTimeAt(t time.Time) {
|
|
b.stopTimeAt = t
|
|
}
|
|
|
|
func (b *testMockBroker) RegisterNode(id eventlogger.NodeID, node eventlogger.Node) error {
|
|
b.registeredNodeIds = append(b.registeredNodeIds, id)
|
|
return nil
|
|
}
|
|
|
|
func (b *testMockBroker) SetSuccessThreshold(t eventlogger.EventType, successThreshold int) error {
|
|
if b.successThresholds == nil {
|
|
b.successThresholds = map[eventlogger.EventType]int{}
|
|
}
|
|
b.successThresholds[t] = successThreshold
|
|
return nil
|
|
}
|