Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions test/conformance/channel_message_modes_specversion_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
113 changes: 113 additions & 0 deletions test/conformance/helpers/channel_message_modes_specversion_helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
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 := 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.NoError(), recordevents.MatchEvent(
HasSpecVersion(version),
HasId(event.ID()),
IsValid(),
))
}
10 changes: 10 additions & 0 deletions test/lib/recordevents/event_info_matchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
29 changes: 15 additions & 14 deletions test/lib/recordevents/event_info_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,15 @@ 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
// 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) {
Comment thread
slinkydeveloper marked this conversation as resolved.
f := AllOf(matchers...)
const maxLastEvents = 5
allMatch := []EventInfo{}
sInfo := SearchedInfo{}
Expand Down Expand Up @@ -221,31 +222,31 @@ func (ei *EventInfoStore) Find(f EventInfoMatcher) ([]EventInfo, SearchedInfo, [
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(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))))
}

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))
}
Expand All @@ -259,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
Expand Down