diff --git a/pkg/api/graphql/resolvers/models.go b/pkg/api/graphql/resolvers/models.go index 5e22be8..997f78b 100644 --- a/pkg/api/graphql/resolvers/models.go +++ b/pkg/api/graphql/resolvers/models.go @@ -5,37 +5,8 @@ package resolvers import ( "github.com/graph-gophers/graphql-go" - "github.com/sassoftware/event-provenance-registry/pkg/api/graphql/schema/types" ) -type EventInput struct { - Name string - Version string - Release string - PlatformID string - Package string - Description string - Payload types.JSON - Success bool - EventReceiverID graphql.ID -} - -type EventReceiverInput struct { - Name string - Type string - Version string - Description string - Schema types.JSON -} - -type EventReceiverGroupInput struct { - Name string - Type string - Version string - Description string - EventReceiverIDs []graphql.ID -} - type FindEventInput struct { ID *graphql.ID Name graphql.NullString diff --git a/pkg/api/graphql/resolvers/models_test.go b/pkg/api/graphql/resolvers/models_test.go index cbf6538..919a4d3 100644 --- a/pkg/api/graphql/resolvers/models_test.go +++ b/pkg/api/graphql/resolvers/models_test.go @@ -8,6 +8,7 @@ import ( "github.com/graph-gophers/graphql-go" "github.com/sassoftware/event-provenance-registry/pkg/api/graphql/schema/types" + "github.com/sassoftware/event-provenance-registry/pkg/epr" "gotest.tools/v3/assert" ) @@ -24,7 +25,7 @@ var ( ) func TestEvent(t *testing.T) { - event := EventInput{ + event := epr.EventInput{ Name: "test", Version: "1.0.0", Release: "1.0.0", @@ -36,7 +37,7 @@ func TestEvent(t *testing.T) { EventReceiverID: "test", } - assert.DeepEqual(t, event, EventInput{ + assert.DeepEqual(t, event, epr.EventInput{ Name: "test", Version: "1.0.0", Release: "1.0.0", @@ -98,14 +99,14 @@ func TestFindEventToMap(t *testing.T) { } func TestEventReceiver(t *testing.T) { - eventReceiver := EventReceiverInput{ + eventReceiver := epr.EventReceiverInput{ Name: "test", Type: "test", Version: "1.0.0", Description: "test", Schema: types.JSON{}, } - assert.DeepEqual(t, eventReceiver, EventReceiverInput{ + assert.DeepEqual(t, eventReceiver, epr.EventReceiverInput{ Name: "test", Type: "test", Version: "1.0.0", @@ -145,14 +146,14 @@ func TestFindEventReceiverToMap(t *testing.T) { } func TestEventReceiverGroup(t *testing.T) { - eventReceiverGroup := EventReceiverGroupInput{ + eventReceiverGroup := epr.EventReceiverGroupInput{ Name: "test", Type: "test", Version: "1.0.0", Description: "test", EventReceiverIDs: []graphql.ID{"test"}, } - assert.DeepEqual(t, eventReceiverGroup, EventReceiverGroupInput{ + assert.DeepEqual(t, eventReceiverGroup, epr.EventReceiverGroupInput{ Name: "test", Type: "test", Version: "1.0.0", diff --git a/pkg/api/graphql/resolvers/mutations.go b/pkg/api/graphql/resolvers/mutations.go index 35c912c..6f735a9 100644 --- a/pkg/api/graphql/resolvers/mutations.go +++ b/pkg/api/graphql/resolvers/mutations.go @@ -4,6 +4,7 @@ import ( "log/slog" "github.com/graph-gophers/graphql-go" + "github.com/sassoftware/event-provenance-registry/pkg/epr" "github.com/sassoftware/event-provenance-registry/pkg/message" "github.com/sassoftware/event-provenance-registry/pkg/storage" ) @@ -18,84 +19,27 @@ type MutationResolver struct { msgProducer message.TopicProducer } -func (r *MutationResolver) CreateEvent(args struct{ Event EventInput }) (graphql.ID, error) { - // TODO: centralize this and make it look better - eventInput := storage.Event{ - Name: args.Event.Name, - Version: args.Event.Version, - Release: args.Event.Release, - PlatformID: args.Event.PlatformID, - Package: args.Event.Package, - Description: args.Event.Description, - Payload: args.Event.Payload, - Success: args.Event.Success, - EventReceiverID: args.Event.EventReceiverID, - } - - event, err := storage.CreateEvent(r.Connection.Client, eventInput) +func (r *MutationResolver) CreateEvent(args struct{ Event epr.EventInput }) (graphql.ID, error) { + event, err := epr.CreateEvent(r.msgProducer, r.Connection, args.Event) if err != nil { - slog.Error("error creating event", "error", err, "input", eventInput) return "", err } - - r.msgProducer.Async(message.NewEvent(*event)) - - slog.Info("created", "event", event) - eventReceiverGroups, err := storage.FindTriggeredEventReceiverGroups(r.Connection.Client, *event) - if err != nil { - slog.Error("error finding triggered event receiver groups", "err", err, "input", eventInput) - return "", err - } - - for _, eventReceiverGroup := range eventReceiverGroups { - r.msgProducer.Async(message.NewEventReceiverGroupComplete(*event, eventReceiverGroup)) - } - return event.ID, nil } -func (r *MutationResolver) CreateEventReceiver(args struct{ EventReceiver EventReceiverInput }) (graphql.ID, error) { - // TODO: centralize this and make it look better - eventReceiverInput := storage.EventReceiver{ - Name: args.EventReceiver.Name, - Type: args.EventReceiver.Type, - Version: args.EventReceiver.Version, - Description: args.EventReceiver.Description, - Schema: args.EventReceiver.Schema, - } - - eventReceiver, err := storage.CreateEventReceiver(r.Connection.Client, eventReceiverInput) +func (r *MutationResolver) CreateEventReceiver(args struct{ EventReceiver epr.EventReceiverInput }) (graphql.ID, error) { + eventReceiver, err := epr.CreateEventReceiver(r.msgProducer, r.Connection, args.EventReceiver) if err != nil { - slog.Error("error creating event receiver", "error", err, "input", eventReceiverInput) return "", err } - - r.msgProducer.Async(message.NewEventReceiver(*eventReceiver)) - - slog.Info("created", "eventReceiver", eventReceiver) return eventReceiver.ID, nil } -func (r *MutationResolver) CreateEventReceiverGroup(args struct{ EventReceiverGroup EventReceiverGroupInput }) (graphql.ID, error) { - // TODO: centralize this and make it look better - eventReceiverGroupInput := storage.EventReceiverGroup{ - Name: args.EventReceiverGroup.Name, - Type: args.EventReceiverGroup.Type, - Version: args.EventReceiverGroup.Version, - Description: args.EventReceiverGroup.Description, - Enabled: true, - EventReceiverIDs: args.EventReceiverGroup.EventReceiverIDs, - } - - eventReceiverGroup, err := storage.CreateEventReceiverGroup(r.Connection.Client, eventReceiverGroupInput) +func (r *MutationResolver) CreateEventReceiverGroup(args struct{ EventReceiverGroup epr.EventReceiverGroupInput }) (graphql.ID, error) { + eventReceiverGroup, err := epr.CreateEventReceiverGroup(r.msgProducer, r.Connection, args.EventReceiverGroup) if err != nil { - slog.Error("error creating event receiver group", "error", err, "input", eventReceiverGroupInput) return "", err } - - r.msgProducer.Async(message.NewEventReceiverGroupCreated(*eventReceiverGroup)) - - slog.Info("created", "eventReceiverGroup", eventReceiverGroup) return eventReceiverGroup.ID, nil } diff --git a/pkg/api/graphql/schema/types/event_receiver_group.graphql b/pkg/api/graphql/schema/types/event_receiver_group.graphql index d307adf..4ec06a5 100644 --- a/pkg/api/graphql/schema/types/event_receiver_group.graphql +++ b/pkg/api/graphql/schema/types/event_receiver_group.graphql @@ -15,6 +15,7 @@ input CreateEventReceiverGroupInput { type: String! version: String! description: String! + enabled: Boolean! event_receiver_ids: [ID!]! } diff --git a/pkg/api/rest/event.go b/pkg/api/rest/event.go index d6f8fcf..ae909f7 100644 --- a/pkg/api/rest/event.go +++ b/pkg/api/rest/event.go @@ -5,13 +5,12 @@ package rest import ( "encoding/json" - "log/slog" "net/http" "github.com/go-chi/chi/v5" "github.com/graph-gophers/graphql-go" + "github.com/sassoftware/event-provenance-registry/pkg/epr" eprErrors "github.com/sassoftware/event-provenance-registry/pkg/errors" - "github.com/sassoftware/event-provenance-registry/pkg/message" "github.com/sassoftware/event-provenance-registry/pkg/storage" ) @@ -31,30 +30,15 @@ func (s *Server) GetEventByID() http.HandlerFunc { } func (s *Server) createEvent(r *http.Request) (graphql.ID, error) { - e := &storage.Event{} - err := json.NewDecoder(r.Body).Decode(e) + var input epr.EventInput + err := json.NewDecoder(r.Body).Decode(&input) if err != nil { return "", eprErrors.InvalidInputError{Msg: err.Error()} } - event, err := storage.CreateEvent(s.DBConnector.Client, *e) + event, err := epr.CreateEvent(s.msgProducer, s.DBConnector, input) if err != nil { return "", err } - - slog.Info("created", "event", event) - s.msgProducer.Async(message.NewEvent(*event)) - - eventReceiverGroups, err := storage.FindTriggeredEventReceiverGroups(s.DBConnector.Client, *event) - if err != nil { - slog.Error("error finding triggered event receiver groups", "error", err, "input", e) - return "", err - } - - for _, eventReceiverGroup := range eventReceiverGroups { - s.msgProducer.Async(message.NewEventReceiverGroupComplete(*event, eventReceiverGroup)) - } - - slog.Info("created", "event", event) return event.ID, nil } diff --git a/pkg/api/rest/group.go b/pkg/api/rest/group.go index 77783e8..5e6578e 100644 --- a/pkg/api/rest/group.go +++ b/pkg/api/rest/group.go @@ -10,8 +10,8 @@ import ( "github.com/go-chi/chi/v5" "github.com/graph-gophers/graphql-go" + "github.com/sassoftware/event-provenance-registry/pkg/epr" eprErrors "github.com/sassoftware/event-provenance-registry/pkg/errors" - "github.com/sassoftware/event-provenance-registry/pkg/message" "github.com/sassoftware/event-provenance-registry/pkg/storage" ) @@ -61,28 +61,15 @@ func (s *Server) UpdateGroup() http.HandlerFunc { } func (s *Server) createGroup(r *http.Request) (graphql.ID, error) { - input := &GroupInput{} - err := json.NewDecoder(r.Body).Decode(input) + var input epr.EventReceiverGroupInput + err := json.NewDecoder(r.Body).Decode(&input) if err != nil { return "", eprErrors.InvalidInputError{Msg: err.Error()} } - eventReceiverGroupInput := storage.EventReceiverGroup{ - Name: input.Name, - Type: input.Type, - Version: input.Version, - Description: input.Description, - Enabled: true, - EventReceiverIDs: input.EventReceiverIDs, - } - - eventReceiverGroup, err := storage.CreateEventReceiverGroup(s.DBConnector.Client, eventReceiverGroupInput) + eventReceiverGroup, err := epr.CreateEventReceiverGroup(s.msgProducer, s.DBConnector, input) if err != nil { return "", err } - - slog.Info("created", "eventReceiverGroup", eventReceiverGroup) - s.msgProducer.Async(message.NewEventReceiverGroupCreated(*eventReceiverGroup)) - return eventReceiverGroup.ID, nil } diff --git a/pkg/api/rest/receiver.go b/pkg/api/rest/receiver.go index ff02af8..f34a35c 100644 --- a/pkg/api/rest/receiver.go +++ b/pkg/api/rest/receiver.go @@ -10,10 +10,9 @@ import ( "github.com/go-chi/chi/v5" "github.com/graph-gophers/graphql-go" + "github.com/sassoftware/event-provenance-registry/pkg/epr" eprErrors "github.com/sassoftware/event-provenance-registry/pkg/errors" - "github.com/sassoftware/event-provenance-registry/pkg/message" "github.com/sassoftware/event-provenance-registry/pkg/storage" - "github.com/xeipuuv/gojsonschema" ) func (s *Server) CreateReceiver() http.HandlerFunc { @@ -33,29 +32,15 @@ func (s *Server) GetReceiverByID() http.HandlerFunc { } func (s *Server) createReceiver(r *http.Request) (graphql.ID, error) { - rec := &storage.EventReceiver{} - err := json.NewDecoder(r.Body).Decode(rec) + var input epr.EventReceiverInput + err := json.NewDecoder(r.Body).Decode(&input) if err != nil { return "", eprErrors.InvalidInputError{Msg: err.Error()} } - // Check that the schema is valid. - if rec.Schema.String() == "" { - return "", eprErrors.InvalidInputError{Msg: "schema is required"} - } - - loader := gojsonschema.NewStringLoader(rec.Schema.String()) - _, err = gojsonschema.NewSchema(loader) - if err != nil { - return "", eprErrors.InvalidInputError{Msg: err.Error()} - } - - eventReceiver, err := storage.CreateEventReceiver(s.DBConnector.Client, *rec) + eventReceiver, err := epr.CreateEventReceiver(s.msgProducer, s.DBConnector, input) if err != nil { return "", err } - - slog.Info("created", "eventReceiver", eventReceiver) - s.msgProducer.Async(message.NewEventReceiver(*eventReceiver)) return eventReceiver.ID, nil } diff --git a/pkg/epr/create.go b/pkg/epr/create.go new file mode 100644 index 0000000..0ca7c31 --- /dev/null +++ b/pkg/epr/create.go @@ -0,0 +1,227 @@ +package epr + +import ( + "errors" + "fmt" + "log/slog" + "strings" + + "github.com/graph-gophers/graphql-go" + "github.com/sassoftware/event-provenance-registry/pkg/api/graphql/schema/types" + eprErrors "github.com/sassoftware/event-provenance-registry/pkg/errors" + "github.com/sassoftware/event-provenance-registry/pkg/message" + "github.com/sassoftware/event-provenance-registry/pkg/storage" + "github.com/xeipuuv/gojsonschema" +) + +type EventInput struct { + Name string `json:"name"` + Version string `json:"version"` + Release string `json:"release"` + PlatformID string `json:"platform_id"` + Package string `json:"package"` + Description string `json:"description"` + Payload types.JSON `json:"payload"` + Success bool `json:"success"` + EventReceiverID graphql.ID `json:"event_receiver_id"` +} + +func (e EventInput) Validate() error { + var err error + + if strings.TrimSpace(e.Name) == "" { + err = errors.Join(err, errors.New("name cannot be blank")) + } + if strings.TrimSpace(e.Version) == "" { + err = errors.Join(err, errors.New("version cannot be blank")) + } + if strings.TrimSpace(e.Release) == "" { + err = errors.Join(err, errors.New("release cannot be blank")) + } + if strings.TrimSpace(e.PlatformID) == "" { + err = errors.Join(err, errors.New("platform id cannot be blank")) + } + if strings.TrimSpace(e.Package) == "" { + err = errors.Join(err, errors.New("package cannot be blank")) + } + if strings.TrimSpace(e.Description) == "" { + err = errors.Join(err, errors.New("description cannot be blank")) + } + if strings.TrimSpace(string(e.EventReceiverID)) == "" { + err = errors.Join(err, errors.New("event receiver id cannot be blank")) + } + + return err +} + +type EventReceiverInput struct { + Name string `json:"name"` + Type string `json:"type"` + Version string `json:"version"` + Description string `json:"description"` + Schema types.JSON `json:"schema"` +} + +func (r EventReceiverInput) Validate() error { + var err error + + if strings.TrimSpace(r.Name) == "" { + err = errors.Join(err, errors.New("name cannot be blank")) + } + if strings.TrimSpace(r.Type) == "" { + err = errors.Join(err, errors.New("type cannot be blank")) + } + if strings.TrimSpace(r.Version) == "" { + err = errors.Join(err, errors.New("version cannot be blank")) + } + if strings.TrimSpace(r.Description) == "" { + err = errors.Join(err, errors.New("description cannot be blank")) + } + schemaErr := func() error { + schema := r.Schema.String() + if schema == "" { + return errors.New("schema is required") + } + loader := gojsonschema.NewStringLoader(schema) + _, err := gojsonschema.NewSchema(loader) + if err != nil { + return fmt.Errorf("failed to parse schema: %w", err) + } + return nil + }() + err = errors.Join(err, schemaErr) + + return err +} + +type EventReceiverGroupInput struct { + Name string `json:"name"` + Type string `json:"type"` + Version string `json:"version"` + Description string `json:"description"` + Enabled bool `json:"enabled"` + EventReceiverIDs []graphql.ID `json:"event_receiver_ids"` +} + +func (g EventReceiverGroupInput) Validate() error { + var err error + + if strings.TrimSpace(g.Name) == "" { + err = errors.Join(err, errors.New("name cannot be blank")) + } + if strings.TrimSpace(g.Type) == "" { + err = errors.Join(err, errors.New("type cannot be blank")) + } + if strings.TrimSpace(g.Version) == "" { + err = errors.Join(err, errors.New("version cannot be blank")) + } + if strings.TrimSpace(g.Description) == "" { + err = errors.Join(err, errors.New("description cannot be blank")) + } + receiverIDErr := func() error { + if len(g.EventReceiverIDs) == 0 { + return errors.New("need at least one event receiver id") + } + for _, receiverID := range g.EventReceiverIDs { + if strings.TrimSpace(string(receiverID)) == "" { + return errors.New("event receiver ids cannot be blank") + } + } + return nil + }() + err = errors.Join(err, receiverIDErr) + + return err +} + +func CreateEvent(msgProducer message.TopicProducer, db *storage.Database, input EventInput) (*storage.Event, error) { + err := input.Validate() + if err != nil { + return nil, eprErrors.InvalidInputError{Msg: err.Error()} + } + + partial := storage.Event{ + Name: input.Name, + Version: input.Version, + Release: input.Release, + PlatformID: input.PlatformID, + Package: input.Package, + Description: input.Description, + Payload: input.Payload, + Success: input.Success, + EventReceiverID: input.EventReceiverID, + } + event, err := storage.CreateEvent(db.Client, partial) + if err != nil { + slog.Error("error creating event", "error", err, "input", input) + return nil, err + } + + msgProducer.Async(message.NewEvent(*event)) + slog.Info("created", "event", event) + + eventReceiverGroups, err := storage.FindTriggeredEventReceiverGroups(db.Client, *event) + if err != nil { + slog.Error("error finding triggered event receiver groups", "error", err, "input", input) + return nil, err + } + + for _, eventReceiverGroup := range eventReceiverGroups { + msgProducer.Async(message.NewEventReceiverGroupComplete(*event, eventReceiverGroup)) + } + + return event, nil +} + +func CreateEventReceiver(msgProducer message.TopicProducer, db *storage.Database, input EventReceiverInput) (*storage.EventReceiver, error) { + err := input.Validate() + if err != nil { + return nil, eprErrors.InvalidInputError{Msg: err.Error()} + } + + partial := storage.EventReceiver{ + Name: input.Name, + Type: input.Type, + Version: input.Version, + Description: input.Description, + Schema: input.Schema, + } + + receiver, err := storage.CreateEventReceiver(db.Client, partial) + if err != nil { + slog.Error("error creating event receiver", "error", err, "input", input) + return nil, err + } + + msgProducer.Async(message.NewEventReceiver(*receiver)) + slog.Info("created", "eventReceiver", receiver) + + return receiver, nil +} + +func CreateEventReceiverGroup(msgProducer message.TopicProducer, db *storage.Database, input EventReceiverGroupInput) (*storage.EventReceiverGroup, error) { + err := input.Validate() + if err != nil { + return nil, eprErrors.InvalidInputError{Msg: err.Error()} + } + + partial := storage.EventReceiverGroup{ + Name: input.Name, + Type: input.Type, + Version: input.Version, + Description: input.Description, + Enabled: input.Enabled, + EventReceiverIDs: input.EventReceiverIDs, + } + + group, err := storage.CreateEventReceiverGroup(db.Client, partial) + if err != nil { + slog.Error("error creating event receiver group", "error", err, "input", input) + return nil, err + } + + msgProducer.Async(message.NewEventReceiverGroupCreated(*group)) + slog.Info("created", "eventReceiverGroup", group) + + return group, nil +} diff --git a/tests/e2e/api_event_receiver_group.go b/tests/e2e/api_event_receiver_group.go index df5ad5f..2c4d925 100644 --- a/tests/e2e/api_event_receiver_group.go +++ b/tests/e2e/api_event_receiver_group.go @@ -33,6 +33,7 @@ type eventReceiverGroupInput struct { Type string Version string Description string + Enabled bool Receivers []string } @@ -43,8 +44,9 @@ func (g eventReceiverGroupInput) toPayload() string { "type": "%s", "version": "%s", "description": "%s", + "enabled": %t, "event_receiver_ids": %s -}`, g.Name, g.Type, g.Version, g.Description, string(receivers)) +}`, g.Name, g.Type, g.Version, g.Description, g.Enabled, string(receivers)) } // createGroup creates a group with the given input, returning diff --git a/tests/e2e/api_event_receiver_group_test.go b/tests/e2e/api_event_receiver_group_test.go index 08c0b6a..1b41554 100644 --- a/tests/e2e/api_event_receiver_group_test.go +++ b/tests/e2e/api_event_receiver_group_test.go @@ -25,6 +25,7 @@ func TestCreateAndGetGroup(t *testing.T) { Type: "one.receiver", Version: "4.5.6", Description: "has a single receiver", + Enabled: true, }, receiverInputs: []eventReceiverInput{ { @@ -42,6 +43,7 @@ func TestCreateAndGetGroup(t *testing.T) { Type: "multiple.receivers", Version: "7.8.9", Description: "has multiple receivers", + Enabled: true, }, receiverInputs: []eventReceiverInput{ { @@ -67,6 +69,24 @@ func TestCreateAndGetGroup(t *testing.T) { }, }, }, + "disabled group": { + input: eventReceiverGroupInput{ + Name: "is-disabled", + Type: "do.something", + Version: "6.20.7", + Description: "basic group that should be disabled", + Enabled: false, + }, + receiverInputs: []eventReceiverInput{ + { + Name: "my receiver", + Type: "does.something", + Version: "3.14.75", + Description: "my receiver", + Schema: `{}`, + }, + }, + }, } for testName, tt := range tests { @@ -105,7 +125,7 @@ func TestCreateAndGetGroup(t *testing.T) { assert.Equal(t, group.Type, tt.input.Type) assert.Equal(t, group.Version, tt.input.Version) assert.Equal(t, group.Description, tt.input.Description) - assert.Equal(t, group.Enabled, true) + assert.Equal(t, group.Enabled, tt.input.Enabled) assert.DeepEqual(t, graphIDsToStrings(group.EventReceiverIDs), tt.input.Receivers) createdAt := time.Time(group.CreatedAt.Date) updatedAt := time.Time(group.UpdatedAt.Date) @@ -159,6 +179,46 @@ func TestCreateInvalidGroup(t *testing.T) { Receivers: []string{}, }, }, + "empty name": { + input: eventReceiverGroupInput{ + Name: "", + Type: "group.complete", + Version: "0.0.2", + Description: "group completes some actions", + Enabled: true, + Receivers: []string{receiverID}, + }, + }, + "empty type": { + input: eventReceiverGroupInput{ + Name: "sample group", + Type: "", + Version: "0.0.2", + Description: "group completes some actions", + Enabled: true, + Receivers: []string{receiverID}, + }, + }, + "empty version": { + input: eventReceiverGroupInput{ + Name: "sample group", + Type: "group.complete", + Version: "", + Description: "group completes some actions", + Enabled: true, + Receivers: []string{receiverID}, + }, + }, + "empty description": { + input: eventReceiverGroupInput{ + Name: "sample group", + Type: "group.complete", + Version: "0.0.2", + Description: "", + Enabled: true, + Receivers: []string{receiverID}, + }, + }, } for testName, tt := range tests { @@ -179,19 +239,29 @@ func TestCreateInvalidGroup(t *testing.T) { func TestToggleGroup(t *testing.T) { client := common.NewHTTPClient() + receiverID, err := createReceiver(client, eventReceiverInput{ + Name: "common-group-receiver", + Type: "my.receiver.type", + Version: "0.0.4", + Description: "common receiver for group testing", + Schema: `{}`, + }) + assert.NilError(t, err) + groupID, err := createGroup(client, eventReceiverGroupInput{ Name: "group to be toggled", Type: "toggled.group", Version: "2.0.11", Description: "group that will be toggled", - Receivers: []string{}, + Enabled: true, + Receivers: []string{receiverID}, }) assert.NilError(t, err) originalGroup, err := getGroup(client, groupID) assert.NilError(t, err) originalUpdatedAt := time.Time(originalGroup.UpdatedAt.Date) - assert.Equal(t, originalGroup.Enabled, true, "group should be enabled by default") + assert.Equal(t, originalGroup.Enabled, true, "group should be initially enabled") err = toggleGroup(client, groupID, false) assert.NilError(t, err) @@ -210,6 +280,20 @@ func TestToggleGroup(t *testing.T) { assert.Check(t, !afterEnableUpdatedAt.Equal(afterDisableUpdatedAt), "updated time should be updated after enable") } +func TestGetNonExistentGroup(t *testing.T) { + client := common.NewHTTPClient() + + resp, err := client.Get(groupURI + "non-existent-group-id") + assert.NilError(t, err) + assert.Equal(t, resp.StatusCode, http.StatusNotFound) + + var body getGroupResponse + err = json.NewDecoder(resp.Body).Decode(&body) + assert.NilError(t, err) + assert.Check(t, len(body.Errors) > 0) + assert.Equal(t, len(body.Data), 0) +} + func graphIDsToStrings(ids []graphql.ID) []string { var s []string for _, id := range ids { diff --git a/tests/e2e/api_event_receiver_test.go b/tests/e2e/api_event_receiver_test.go index 5acdd7c..49f9cd1 100644 --- a/tests/e2e/api_event_receiver_test.go +++ b/tests/e2e/api_event_receiver_test.go @@ -75,23 +75,78 @@ func TestCreateAndGetReceiver(t *testing.T) { func TestCreateInvalidReceiver(t *testing.T) { client := common.NewHTTPClient() - receiver := eventReceiverInput{ - Name: "upload artifact", - Type: "artifact.publish", - Version: "1.0.9", - Description: "upload an artifact somewhere", - Schema: `{abcd}`, + tests := map[string]struct { + input eventReceiverInput + }{ + "empty name": { + input: eventReceiverInput{ + Name: "", + Type: "artifact.publish", + Version: "1.0.9", + Description: "upload an artifact somewhere", + Schema: `{}`, + }, + }, + "empty type": { + input: eventReceiverInput{ + Name: "upload artifact", + Type: "", + Version: "1.0.9", + Description: "upload an artifact somewhere", + Schema: `{}`, + }, + }, + "empty version": { + input: eventReceiverInput{ + Name: "upload artifact", + Type: "artifact.publish", + Version: "", + Description: "upload an artifact somewhere", + Schema: `{}`, + }, + }, + "empty description": { + input: eventReceiverInput{ + Name: "upload artifact", + Type: "artifact.publish", + Version: "1.0.9", + Description: "", + Schema: `{}`, + }, + }, + "invalid schema": { + input: eventReceiverInput{ + Name: "upload artifact", + Type: "artifact.publish", + Version: "1.0.9", + Description: "upload an artifact somewhere", + Schema: `{abcd}`, + }, + }, + "empty schema": { + input: eventReceiverInput{ + Name: "upload artifact", + Type: "artifact.publish", + Version: "1.0.9", + Description: "upload an artifact somewhere", + Schema: "", + }, + }, } - resp, err := client.Post(receiverURI, "application/json", strings.NewReader(receiver.toPayload())) - assert.NilError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusBadRequest) + for testName, tt := range tests { + t.Run(testName, func(t *testing.T) { + resp, err := client.Post(receiverURI, "application/json", strings.NewReader(tt.input.toPayload())) + assert.NilError(t, err) + assert.Equal(t, resp.StatusCode, http.StatusBadRequest) - var body postReceiverResponse - err = json.NewDecoder(resp.Body).Decode(&body) - assert.NilError(t, err) - assert.Check(t, len(body.Errors) > 0) - assert.Equal(t, len(body.Data), 0, "shouldn't get id if creating receiver fails") + var body postReceiverResponse + err = json.NewDecoder(resp.Body).Decode(&body) + assert.NilError(t, err) + assert.Check(t, len(body.Errors) > 0) + assert.Equal(t, len(body.Data), 0, "shouldn't get id if creating receiver fails") + }) + } } func TestGetNonExistentReceiver(t *testing.T) { diff --git a/tests/e2e/api_event_test.go b/tests/e2e/api_event_test.go index 195792c..270b25c 100644 --- a/tests/e2e/api_event_test.go +++ b/tests/e2e/api_event_test.go @@ -138,7 +138,7 @@ func TestCreateAndGetEvent(t *testing.T) { } } -func TestCreateEventWithIncorrectPayload(t *testing.T) { +func TestCreateEventWithInvalidInput(t *testing.T) { client := common.NewHTTPClient() receiverInput := eventReceiverInput{ @@ -154,7 +154,7 @@ func TestCreateEventWithIncorrectPayload(t *testing.T) { tests := map[string]struct { input eventInput }{ - "incorrect field type": { + "incorrect payload field type": { input: eventInput{ Name: "merge PR for service foobar", Version: "1.0.1", @@ -167,7 +167,7 @@ func TestCreateEventWithIncorrectPayload(t *testing.T) { EventReceiverID: receiverID, }, }, - "incorrect array value type": { + "incorrect payload array value type": { input: eventInput{ Name: "merge PR for service foo", Version: "2.11.1", @@ -180,6 +180,110 @@ func TestCreateEventWithIncorrectPayload(t *testing.T) { EventReceiverID: receiverID, }, }, + "empty name": { + input: eventInput{ + Name: "", + Version: "9.9.9", + Release: "2006.01.01", + PlatformID: "oci-linux", + Package: "docker", + Description: "merged a PR for baz", + Payload: `{"filesChanged":16,"reviewers":["someone"]}`, + Success: true, + EventReceiverID: receiverID, + }, + }, + "empty version": { + input: eventInput{ + Name: "merge PR to baz repo", + Version: "", + Release: "2006.01.01", + PlatformID: "oci-linux", + Package: "docker", + Description: "merged a PR for baz", + Payload: `{"filesChanged":16,"reviewers":["someone"]}`, + Success: true, + EventReceiverID: receiverID, + }, + }, + "empty release": { + input: eventInput{ + Name: "merge PR to baz repo", + Version: "9.9.9", + Release: "", + PlatformID: "oci-linux", + Package: "docker", + Description: "merged a PR for baz", + Payload: `{"filesChanged":16,"reviewers":["someone"]}`, + Success: true, + EventReceiverID: receiverID, + }, + }, + "empty platform id": { + input: eventInput{ + Name: "merge PR to baz repo", + Version: "9.9.9", + Release: "2006.01.01", + PlatformID: "", + Package: "docker", + Description: "merged a PR for baz", + Payload: `{"filesChanged":16,"reviewers":["someone"]}`, + Success: true, + EventReceiverID: receiverID, + }, + }, + "empty package": { + input: eventInput{ + Name: "merge PR to baz repo", + Version: "9.9.9", + Release: "2006.01.01", + PlatformID: "oci-linux", + Package: "", + Description: "merged a PR for baz", + Payload: `{"filesChanged":16,"reviewers":["someone"]}`, + Success: true, + EventReceiverID: receiverID, + }, + }, + "empty description": { + input: eventInput{ + Name: "merge PR to baz repo", + Version: "9.9.9", + Release: "2006.01.01", + PlatformID: "oci-linux", + Package: "docker", + Description: "", + Payload: `{"filesChanged":16,"reviewers":["someone"]}`, + Success: true, + EventReceiverID: receiverID, + }, + }, + "empty payload": { + input: eventInput{ + Name: "merge PR to baz repo", + Version: "9.9.9", + Release: "2006.01.01", + PlatformID: "oci-linux", + Package: "docker", + Description: "merged a PR for baz", + Payload: "", + Success: true, + EventReceiverID: receiverID, + }, + }, + "empty event receiver": { + input: eventInput{ + Name: "merge PR to baz repo", + Version: "9.9.9", + Release: "2006.01.01", + PlatformID: "oci-linux", + Package: "docker", + Description: "merged a PR for baz", + Payload: `{"filesChanged":16,"reviewers":["someone"]}`, + Success: true, + EventReceiverID: "", + }, + }, } for testName, tt := range tests { @@ -196,3 +300,17 @@ func TestCreateEventWithIncorrectPayload(t *testing.T) { }) } } + +func TestGetNonExistentEvent(t *testing.T) { + client := common.NewHTTPClient() + + resp, err := client.Get(eventURI + "non-existent-event-id") + assert.NilError(t, err) + assert.Equal(t, resp.StatusCode, http.StatusNotFound) + + var body getEventResponse + err = json.NewDecoder(resp.Body).Decode(&body) + assert.NilError(t, err) + assert.Check(t, len(body.Errors) > 0) + assert.Equal(t, len(body.Data), 0) +} diff --git a/tests/go.mod b/tests/go.mod index 39ccd22..0ceeed4 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -5,6 +5,7 @@ go 1.21 replace github.com/sassoftware/event-provenance-registry => ../ require ( + github.com/graph-gophers/graphql-go v1.5.1-0.20230420075959-f0f4e10d6a70 github.com/sassoftware/event-provenance-registry v0.0.0-20240119220400-0ea37203f496 gotest.tools/v3 v3.5.1 ) @@ -13,7 +14,6 @@ require ( github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/graph-gophers/graphql-go v1.5.1-0.20230420075959-f0f4e10d6a70 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.14.0 // indirect github.com/jackc/pgio v1.0.0 // indirect