From 64fe09804fbb1489f8bcd3e7ff8e5783912c5427 Mon Sep 17 00:00:00 2001 From: Scott Nichols <32305648+n3wscott@users.noreply.github.com> Date: Wed, 8 May 2019 17:29:03 -0700 Subject: [PATCH] fix no data bug. (#122) Signed-off-by: Scott Nichols --- pkg/cloudevents/event_data.go | 5 +- pkg/cloudevents/event_data_test.go | 26 +++- pkg/cloudevents/transport/http/transport.go | 8 +- test/http/loopback_setters_test.go | 159 ++++++++++++++++++++ 4 files changed, 192 insertions(+), 6 deletions(-) diff --git a/pkg/cloudevents/event_data.go b/pkg/cloudevents/event_data.go index d8929ccde..3f2b10fbf 100644 --- a/pkg/cloudevents/event_data.go +++ b/pkg/cloudevents/event_data.go @@ -39,7 +39,8 @@ func (e *Event) DataBytes() ([]byte, error) { if s, ok := e.Data.(string); ok { b = []byte(s) } else { - return nil, errors.New("data was not a byte slice or string") + // No data. + return []byte(nil), nil } } return b, nil @@ -64,7 +65,7 @@ func (e Event) DataAs(data interface{}) error { // TODO: Clean this function up } } if len(obj) == 0 { - // no data. + // No data. return nil } if e.Context.GetDataContentEncoding() == Base64 { diff --git a/pkg/cloudevents/event_data_test.go b/pkg/cloudevents/event_data_test.go index a3cfd69e3..2a3befe20 100644 --- a/pkg/cloudevents/event_data_test.go +++ b/pkg/cloudevents/event_data_test.go @@ -21,6 +21,12 @@ func TestEventSetData_Json(t *testing.T) { versions := []string{ce.CloudEventsVersionV01, ce.CloudEventsVersionV02, ce.CloudEventsVersionV03} testCases := map[string]DataTest{ + "empty": { + event: func(version string) ce.Event { + return ce.New(version) + }, + want: nil, + }, "defaults": { event: func(version string) ce.Event { return ce.New(version) @@ -71,7 +77,11 @@ func TestEventSetData_Json(t *testing.T) { // Make a versioned event. event := tc.event(version) - event.SetData(tc.set) + if tc.set != nil { + if err := event.SetData(tc.set); err != nil { + t.Errorf("unexpected error, %v", err) + } + } got := event.Data as, _ := types.Allocate(tc.set) @@ -95,6 +105,14 @@ func TestEventSetData_xml(t *testing.T) { versions := []string{ce.CloudEventsVersionV01, ce.CloudEventsVersionV02, ce.CloudEventsVersionV03} testCases := map[string]DataTest{ + "empty": { + event: func(version string) ce.Event { + e := ce.New(version) + e.SetDataContentType("application/xml") + return e + }, + want: nil, + }, "text/xml": { event: func(version string) ce.Event { e := ce.New(version) @@ -142,7 +160,11 @@ func TestEventSetData_xml(t *testing.T) { // Make a versioned event. event := tc.event(version) - event.SetData(tc.set) + if tc.set != nil { + if err := event.SetData(tc.set); err != nil { + t.Errorf("unexpected error, %v", err) + } + } got := event.Data as, _ := types.Allocate(tc.set) diff --git a/pkg/cloudevents/transport/http/transport.go b/pkg/cloudevents/transport/http/transport.go index 258691c48..579149fe7 100644 --- a/pkg/cloudevents/transport/http/transport.go +++ b/pkg/cloudevents/transport/http/transport.go @@ -174,8 +174,12 @@ func (t *Transport) obsSend(ctx context.Context, event cloudevents.Event) (*clou if m, ok := msg.(*Message); ok { copyHeaders(m.Header, req.Header) - req.Body = ioutil.NopCloser(bytes.NewBuffer(m.Body)) - req.ContentLength = int64(len(m.Body)) + if m.Body != nil { + req.Body = ioutil.NopCloser(bytes.NewBuffer(m.Body)) + req.ContentLength = int64(len(m.Body)) + } else { + req.ContentLength = 0 + } return httpDo(ctx, t.Client, &req, func(resp *http.Response, err error) (*cloudevents.Event, error) { logger := cecontext.LoggerFrom(ctx) diff --git a/test/http/loopback_setters_test.go b/test/http/loopback_setters_test.go index 0ddad34e6..83c659ae9 100644 --- a/test/http/loopback_setters_test.go +++ b/test/http/loopback_setters_test.go @@ -179,6 +179,165 @@ func TestClientLoopback_setters_binary_json(t *testing.T) { } } +func TestClientLoopback_setters_binary_json_noBody(t *testing.T) { + now := time.Now() + + versions := []string{cloudevents.VersionV01, cloudevents.VersionV02, cloudevents.VersionV03} + + testCases := map[string]struct { + event func(string) *cloudevents.Event + resp func(string) *cloudevents.Event + want map[string]*cloudevents.Event + asSent map[string]*TapValidation + asRecv map[string]*TapValidation + }{ + "Bodiless Loopback": { + event: func(version string) *cloudevents.Event { + event := cloudevents.NewEvent(version) + event.SetID("ABC-123") + event.SetType("unit.test.client.sent") + event.SetSource("/unit/test/client") + return &event + }, + resp: func(version string) *cloudevents.Event { + event := cloudevents.NewEvent(version) + event.SetID("321-CBA") + event.SetType("unit.test.client.response") + event.SetSource("/unit/test/client") + return &event + }, + want: map[string]*cloudevents.Event{ + cloudevents.VersionV01: { + Context: cloudevents.EventContextV01{ + EventID: "321-CBA", + EventType: "unit.test.client.response", + EventTime: &cloudevents.Timestamp{Time: now}, + Source: *cloudevents.ParseURLRef("/unit/test/client"), + ContentType: cloudevents.StringOfApplicationJSON(), + }.AsV01(), + Data: map[string]string{}, + }, + cloudevents.VersionV02: { + Context: cloudevents.EventContextV02{ + ID: "321-CBA", + Type: "unit.test.client.response", + Time: &cloudevents.Timestamp{Time: now}, + Source: *cloudevents.ParseURLRef("/unit/test/client"), + ContentType: cloudevents.StringOfApplicationJSON(), + }.AsV02(), + Data: map[string]string{}, + }, + cloudevents.VersionV03: { + Context: cloudevents.EventContextV03{ + ID: "321-CBA", + Type: "unit.test.client.response", + Time: &cloudevents.Timestamp{Time: now}, + Source: *cloudevents.ParseURLRef("/unit/test/client"), + DataContentType: cloudevents.StringOfApplicationJSON(), + }.AsV03(), + Data: map[string]string{}, + }, + }, + asSent: map[string]*TapValidation{ + cloudevents.VersionV01: { + Method: "POST", + URI: "/", + Header: map[string][]string{ + "ce-cloudeventsversion": {"0.1"}, + "ce-eventid": {"ABC-123"}, + "ce-eventtime": {now.UTC().Format(time.RFC3339Nano)}, + "ce-eventtype": {"unit.test.client.sent"}, + "ce-source": {"/unit/test/client"}, + "content-type": {"application/json"}, + }, + ContentLength: 0, + }, + cloudevents.VersionV02: { + Method: "POST", + URI: "/", + Header: map[string][]string{ + "ce-specversion": {"0.2"}, + "ce-id": {"ABC-123"}, + "ce-time": {now.UTC().Format(time.RFC3339Nano)}, + "ce-type": {"unit.test.client.sent"}, + "ce-source": {"/unit/test/client"}, + "content-type": {"application/json"}, + }, + ContentLength: 0, + }, + cloudevents.VersionV03: { + Method: "POST", + URI: "/", + Header: map[string][]string{ + "ce-specversion": {"0.3"}, + "ce-id": {"ABC-123"}, + "ce-time": {now.UTC().Format(time.RFC3339Nano)}, + "ce-type": {"unit.test.client.sent"}, + "ce-source": {"/unit/test/client"}, + "content-type": {"application/json"}, + }, + ContentLength: 0, + }, + }, + asRecv: map[string]*TapValidation{ + cloudevents.VersionV01: { + Header: map[string][]string{ + "ce-cloudeventsversion": {"0.1"}, + "ce-eventid": {"321-CBA"}, + "ce-eventtime": {now.UTC().Format(time.RFC3339Nano)}, + "ce-eventtype": {"unit.test.client.response"}, + "ce-source": {"/unit/test/client"}, + "content-type": {"application/json"}, + }, + Status: "200 OK", + ContentLength: 0, + }, + cloudevents.VersionV02: { + Header: map[string][]string{ + "ce-specversion": {"0.2"}, + "ce-id": {"321-CBA"}, + "ce-time": {now.UTC().Format(time.RFC3339Nano)}, + "ce-type": {"unit.test.client.response"}, + "ce-source": {"/unit/test/client"}, + "content-type": {"application/json"}, + }, + Status: "200 OK", + ContentLength: 0, + }, + cloudevents.VersionV03: { + Header: map[string][]string{ + "ce-specversion": {"0.3"}, + "ce-id": {"321-CBA"}, + "ce-time": {now.UTC().Format(time.RFC3339Nano)}, + "ce-type": {"unit.test.client.response"}, + "ce-source": {"/unit/test/client"}, + "content-type": {"application/json"}, + }, + Status: "200 OK", + ContentLength: 0, + }, + }, + }, + } + + for n, tc := range testCases { + for _, version := range versions { + t.Run(n+version+" -> "+version, func(t *testing.T) { + + testcase := TapTest{ + now: now, + event: tc.event(version), + resp: tc.resp(version), + want: tc.want[version], + asSent: tc.asSent[version], + asRecv: tc.asRecv[version], + } + ClientLoopback(t, testcase) + }) + } + } +} + func TestClientLoopback_setters_structured_json(t *testing.T) { now := time.Now()