From 447035ed318cd6106843b794565527370ce41abe Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Mon, 22 Jun 2020 12:14:09 +0200 Subject: [PATCH 1/4] Added conformance test for specversion/message modes Signed-off-by: Francesco Guardiani --- .../channel_message_modes_specversion_test.go | 30 +++++ ...hannel_message_modes_specversion_helper.go | 112 ++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 test/conformance/channel_message_modes_specversion_test.go create mode 100644 test/conformance/helpers/channel_message_modes_specversion_helper.go diff --git a/test/conformance/channel_message_modes_specversion_test.go b/test/conformance/channel_message_modes_specversion_test.go new file mode 100644 index 00000000000..7cc5309b6ec --- /dev/null +++ b/test/conformance/channel_message_modes_specversion_test.go @@ -0,0 +1,30 @@ +// +build e2e + +/* +Copyright 2020 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package conformance + +import ( + "testing" + + "knative.dev/eventing/test/conformance/helpers" + testlib "knative.dev/eventing/test/lib" +) + +func TestChannelEventModesAndSpecVersions(t *testing.T) { + helpers.ChannelMessageModesAndSpecVersionsTestRunner(t, channelTestRunner, testlib.SetupClientOptionNoop) +} diff --git a/test/conformance/helpers/channel_message_modes_specversion_helper.go b/test/conformance/helpers/channel_message_modes_specversion_helper.go new file mode 100644 index 00000000000..2b4801dda04 --- /dev/null +++ b/test/conformance/helpers/channel_message_modes_specversion_helper.go @@ -0,0 +1,112 @@ +/* +Copyright 2020 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package helpers + +import ( + "strings" + "testing" + + cloudevents "github.com/cloudevents/sdk-go/v2" + "github.com/cloudevents/sdk-go/v2/test" + "github.com/google/uuid" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + testlib "knative.dev/eventing/test/lib" + "knative.dev/eventing/test/lib/recordevents" + "knative.dev/eventing/test/lib/resources" + "knative.dev/eventing/test/lib/resources/sender" +) + +// ChannelMessageModesAndSpecVersionsTestRunner tests the support of the channel ingress for different spec versions and message modes +func ChannelMessageModesAndSpecVersionsTestRunner( + t *testing.T, + channelTestRunner testlib.ComponentsTestRunner, + options ...testlib.SetupClientOption, +) { + testCases := []struct { + encoding cloudevents.Encoding + version string + }{ + { + encoding: cloudevents.EncodingBinary, + version: cloudevents.VersionV03, + }, { + encoding: cloudevents.EncodingStructured, + version: cloudevents.VersionV03, + }, { + encoding: cloudevents.EncodingBinary, + version: cloudevents.VersionV1, + }, { + encoding: cloudevents.EncodingStructured, + version: cloudevents.VersionV1, + }, + } + + channelTestRunner.RunTests(t, testlib.FeatureBasic, func(t *testing.T, channel metav1.TypeMeta) { + for _, tc := range testCases { + t.Run("encoding_"+tc.encoding.String()+"_version_"+tc.version, func(t *testing.T) { + messageModeSpecVersionTest(t, channel, tc.encoding, tc.version, options...) + }) + } + }) +} + +// Sender -> Channel -> Subscriber -> Record Events +func messageModeSpecVersionTest(t *testing.T, channel metav1.TypeMeta, encoding cloudevents.Encoding, version string, options ...testlib.SetupClientOption) { + client := testlib.Setup(t, true, options...) + defer testlib.TearDown(client) + + resourcesNamePrefix := strings.ReplaceAll(strings.ToLower(encoding.String()+"-"+version), ".", "") + + channelName := resourcesNamePrefix + "-ch" + client.CreateChannelOrFail(channelName, &channel) + + subscriberName := resourcesNamePrefix + "-recordevents" + eventTracker, _ := recordevents.StartEventRecordOrFail(client, subscriberName) + + client.CreateSubscriptionOrFail( + resourcesNamePrefix+"-sub", + channelName, + &channel, + resources.WithSubscriberForSubscription(subscriberName), + ) + + client.WaitForAllTestResourcesReadyOrFail() + + event := test.FullEvent() + event.SetID(uuid.New().String()) + + switch version { + case cloudevents.VersionV1: + event.Context = event.Context.AsV1() + case cloudevents.VersionV03: + event.Context = event.Context.AsV03() + } + + client.SendEventToAddressable( + resourcesNamePrefix+"-sender", + channelName, + &channel, + event, + sender.WithEncoding(encoding), + ) + + eventTracker.AssertExact(1, recordevents.MatchEvent( + test.HasSpecVersion(version), + test.HasId(event.ID()), + )) +} From 51275440d01fde5fde56c590a085eb396441a1bd Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Mon, 22 Jun 2020 12:53:02 +0200 Subject: [PATCH 2/4] Assert no validation error Signed-off-by: Francesco Guardiani --- ...hannel_message_modes_specversion_helper.go | 2 +- test/lib/recordevents/event_info_matchers.go | 10 ++++++++++ test/lib/recordevents/event_info_store.go | 19 ++++++++++--------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/test/conformance/helpers/channel_message_modes_specversion_helper.go b/test/conformance/helpers/channel_message_modes_specversion_helper.go index 2b4801dda04..678f5066ad7 100644 --- a/test/conformance/helpers/channel_message_modes_specversion_helper.go +++ b/test/conformance/helpers/channel_message_modes_specversion_helper.go @@ -105,7 +105,7 @@ func messageModeSpecVersionTest(t *testing.T, channel metav1.TypeMeta, encoding sender.WithEncoding(encoding), ) - eventTracker.AssertExact(1, recordevents.MatchEvent( + eventTracker.AssertExact(1, recordevents.NoError(), recordevents.MatchEvent( test.HasSpecVersion(version), test.HasId(event.ID()), )) diff --git a/test/lib/recordevents/event_info_matchers.go b/test/lib/recordevents/event_info_matchers.go index 4444f865656..65d1bef4f07 100644 --- a/test/lib/recordevents/event_info_matchers.go +++ b/test/lib/recordevents/event_info_matchers.go @@ -46,6 +46,16 @@ func AllOf(matchers ...EventInfoMatcher) EventInfoMatcher { } } +// Matcher that fails if there is an error in the EventInfo +func NoError() EventInfoMatcher { + return func(ei EventInfo) error { + if ei.Error != "" { + return fmt.Errorf("not expecting an error in event info: %s", ei.Error) + } + return nil + } +} + // Convert a matcher that checks valid messages to a function // that checks EventInfo structures, returning an error for any that don't // contain valid events. diff --git a/test/lib/recordevents/event_info_store.go b/test/lib/recordevents/event_info_store.go index 3a5de9a481a..09c09cb21a2 100644 --- a/test/lib/recordevents/event_info_store.go +++ b/test/lib/recordevents/event_info_store.go @@ -192,7 +192,8 @@ func (ei *EventInfoStore) refreshData() ([]EventInfo, error) { // guaranteed to be called exactly once on each EventInfo from the pod. // The error array contains the eventual match errors, while the last return error contains // an eventual communication error while trying to get the events from the recordevents pod -func (ei *EventInfoStore) Find(f EventInfoMatcher) ([]EventInfo, SearchedInfo, []error, error) { +func (ei *EventInfoStore) Find(matchers ...EventInfoMatcher) ([]EventInfo, SearchedInfo, []error, error) { + f := AllOf(matchers...) const maxLastEvents = 5 allMatch := []EventInfo{} sInfo := SearchedInfo{} @@ -223,8 +224,8 @@ func (ei *EventInfoStore) Find(f EventInfoMatcher) ([]EventInfo, SearchedInfo, [ // Assert that there are at least min number of matches of f. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertAtLeast(min int, f EventInfoMatcher) []EventInfo { - events, err := ei.waitAtLeastNMatch(f, min) +func (ei *EventInfoStore) AssertAtLeast(min int, f ...EventInfoMatcher) []EventInfo { + events, err := ei.waitAtLeastNMatch(AllOf(f...), min) if err != nil { ei.tb.Fatalf("Timeout waiting for at least %d matches.\nError: %v", min, errors.WithStack(err)) } @@ -233,8 +234,8 @@ func (ei *EventInfoStore) AssertAtLeast(min int, f EventInfoMatcher) []EventInfo // Assert that there are at least min number of matches and at most max number of matches of f. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertInRange(min int, max int, f EventInfoMatcher) []EventInfo { - events := ei.AssertAtLeast(min, f) +func (ei *EventInfoStore) AssertInRange(min int, max int, f ...EventInfoMatcher) []EventInfo { + events := ei.AssertAtLeast(min, f...) if max > 0 && len(events) > max { ei.tb.Fatalf("Assert in range failed: %v", errors.WithStack(fmt.Errorf("expected <= %d events, saw %d", max, len(events)))) } @@ -244,8 +245,8 @@ func (ei *EventInfoStore) AssertInRange(min int, max int, f EventInfoMatcher) [] // Assert that there aren't any matches of f. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertNot(f EventInfoMatcher) []EventInfo { - res, recentEvents, _, err := ei.Find(f) +func (ei *EventInfoStore) AssertNot(f ...EventInfoMatcher) []EventInfo { + res, recentEvents, _, err := ei.Find(f...) if err != nil { ei.tb.Fatalf("Unexpected error during find on recordevents '%s': %v", ei.podName, errors.WithStack(err)) } @@ -261,8 +262,8 @@ func (ei *EventInfoStore) AssertNot(f EventInfoMatcher) []EventInfo { // Assert that there are exactly n matches of f. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertExact(n int, f EventInfoMatcher) []EventInfo { - return ei.AssertInRange(n, n, f) +func (ei *EventInfoStore) AssertExact(n int, f ...EventInfoMatcher) []EventInfo { + return ei.AssertInRange(n, n, f...) } // Wait a long time (currently 4 minutes) until the provided function matches at least From 177ee7f2cccb78600102973f2ad212f05cc97f51 Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Mon, 22 Jun 2020 12:54:00 +0200 Subject: [PATCH 3/4] Added IsValid check Signed-off-by: Francesco Guardiani --- .../helpers/channel_message_modes_specversion_helper.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/conformance/helpers/channel_message_modes_specversion_helper.go b/test/conformance/helpers/channel_message_modes_specversion_helper.go index 678f5066ad7..6c9b7205ef1 100644 --- a/test/conformance/helpers/channel_message_modes_specversion_helper.go +++ b/test/conformance/helpers/channel_message_modes_specversion_helper.go @@ -21,7 +21,7 @@ import ( "testing" cloudevents "github.com/cloudevents/sdk-go/v2" - "github.com/cloudevents/sdk-go/v2/test" + . "github.com/cloudevents/sdk-go/v2/test" "github.com/google/uuid" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -87,7 +87,7 @@ func messageModeSpecVersionTest(t *testing.T, channel metav1.TypeMeta, encoding client.WaitForAllTestResourcesReadyOrFail() - event := test.FullEvent() + event := FullEvent() event.SetID(uuid.New().String()) switch version { @@ -106,7 +106,8 @@ func messageModeSpecVersionTest(t *testing.T, channel metav1.TypeMeta, encoding ) eventTracker.AssertExact(1, recordevents.NoError(), recordevents.MatchEvent( - test.HasSpecVersion(version), - test.HasId(event.ID()), + HasSpecVersion(version), + HasId(event.ID()), + IsValid(), )) } From 0bbba8bee84eed89dcde5561889efaa1405af824 Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Mon, 22 Jun 2020 14:37:52 +0200 Subject: [PATCH 4/4] Comments Signed-off-by: Francesco Guardiani --- test/lib/recordevents/event_info_store.go | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/lib/recordevents/event_info_store.go b/test/lib/recordevents/event_info_store.go index 09c09cb21a2..6576936247a 100644 --- a/test/lib/recordevents/event_info_store.go +++ b/test/lib/recordevents/event_info_store.go @@ -185,7 +185,7 @@ func (ei *EventInfoStore) refreshData() ([]EventInfo, error) { return allEvents, nil } -// Find all events received by the recordevents pod that match the provided function, +// Find all events received by the recordevents pod that match the provided matchers, // returning all matching events as well as a SearchedInfo structure including the // last 5 events seen and the total events matched. This SearchedInfo structure // is primarily to ease debugging in failure printouts. The provided function is @@ -222,20 +222,20 @@ func (ei *EventInfoStore) Find(matchers ...EventInfoMatcher) ([]EventInfo, Searc return allMatch, sInfo, nonMatchingErrors, nil } -// Assert that there are at least min number of matches of f. +// Assert that there are at least min number of match for the provided matchers. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertAtLeast(min int, f ...EventInfoMatcher) []EventInfo { - events, err := ei.waitAtLeastNMatch(AllOf(f...), min) +func (ei *EventInfoStore) AssertAtLeast(min int, matchers ...EventInfoMatcher) []EventInfo { + events, err := ei.waitAtLeastNMatch(AllOf(matchers...), min) if err != nil { ei.tb.Fatalf("Timeout waiting for at least %d matches.\nError: %v", min, errors.WithStack(err)) } return events } -// Assert that there are at least min number of matches and at most max number of matches of f. +// Assert that there are at least min number of matches and at most max number of matches for the provided matchers. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertInRange(min int, max int, f ...EventInfoMatcher) []EventInfo { - events := ei.AssertAtLeast(min, f...) +func (ei *EventInfoStore) AssertInRange(min int, max int, matchers ...EventInfoMatcher) []EventInfo { + events := ei.AssertAtLeast(min, matchers...) if max > 0 && len(events) > max { ei.tb.Fatalf("Assert in range failed: %v", errors.WithStack(fmt.Errorf("expected <= %d events, saw %d", max, len(events)))) } @@ -243,10 +243,10 @@ func (ei *EventInfoStore) AssertInRange(min int, max int, f ...EventInfoMatcher) return events } -// Assert that there aren't any matches of f. +// Assert that there aren't any matches for the provided matchers. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertNot(f ...EventInfoMatcher) []EventInfo { - res, recentEvents, _, err := ei.Find(f...) +func (ei *EventInfoStore) AssertNot(matchers ...EventInfoMatcher) []EventInfo { + res, recentEvents, _, err := ei.Find(matchers...) if err != nil { ei.tb.Fatalf("Unexpected error during find on recordevents '%s': %v", ei.podName, errors.WithStack(err)) } @@ -260,10 +260,10 @@ func (ei *EventInfoStore) AssertNot(f ...EventInfoMatcher) []EventInfo { return res } -// Assert that there are exactly n matches of f. +// Assert that there are exactly n matches for the provided matchers. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertExact(n int, f ...EventInfoMatcher) []EventInfo { - return ei.AssertInRange(n, n, f...) +func (ei *EventInfoStore) AssertExact(n int, matchers ...EventInfoMatcher) []EventInfo { + return ei.AssertInRange(n, n, matchers...) } // Wait a long time (currently 4 minutes) until the provided function matches at least