From 00829d40dba77c6e6c7a3f55656d9a238c7b4734 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Fri, 8 Jul 2022 11:32:34 -0400 Subject: [PATCH 1/5] Add SupportsQOSAck func, improve SupportsTransaction func, update error - make `SupportsTransaction` easier to read - add missing message type for `TestMessageTypeSupportsTransaction` - add `SupportsQOSAck` - add `TestMessageTypeSupportsQOSAck` - improve readability for `SupportsTransaction` and add missing message type case `lastMessageType` - update error message --- messagetype.go | 28 ++++++++++++++-------------- messagetype_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/messagetype.go b/messagetype.go index b2d5532..36163ae 100644 --- a/messagetype.go +++ b/messagetype.go @@ -49,22 +49,22 @@ const ( // where applicable). func (mt MessageType) SupportsTransaction() bool { switch mt { - case Invalid0MessageType: - return false - case Invalid1MessageType: - return false - case AuthorizationMessageType: + case SimpleRequestResponseMessageType, CreateMessageType, RetrieveMessageType, UpdateMessageType, DeleteMessageType: + return true + default: return false + } +} + +// SupportsQOSAck tests if messages of this type are allowed to participate in QOS Ack +// as specified in https://xmidt.io/docs/wrp/basics/#qos-description-qos . +// If this method returns false, QOS Ack is foregone. +func (mt MessageType) SupportsQOSAck() bool { + switch mt { case SimpleEventMessageType: - return false - case ServiceRegistrationMessageType: - return false - case ServiceAliveMessageType: - return false - case UnknownMessageType: - return false - default: return true + default: + return false } } @@ -114,7 +114,7 @@ func init() { func StringToMessageType(value string) (MessageType, error) { mt, ok := stringToMessageType[value] if !ok { - return MessageType(-1), fmt.Errorf("Invalid message type: %s", value) + return MessageType(-1), fmt.Errorf("invalid message type: %s", value) } return mt, nil diff --git a/messagetype_test.go b/messagetype_test.go index 41c96be..5a3e689 100644 --- a/messagetype_test.go +++ b/messagetype_test.go @@ -73,6 +73,7 @@ func TestMessageTypeSupportsTransaction(t *testing.T) { ServiceRegistrationMessageType: false, ServiceAliveMessageType: false, UnknownMessageType: false, + lastMessageType: false, } ) @@ -81,6 +82,31 @@ func TestMessageTypeSupportsTransaction(t *testing.T) { } } +func TestMessageTypeSupportsQOSAck(t *testing.T) { + var ( + assert = assert.New(t) + expectedSupportsQOSAck = map[MessageType]bool{ + Invalid0MessageType: false, + Invalid1MessageType: false, + AuthorizationMessageType: false, + SimpleRequestResponseMessageType: false, + SimpleEventMessageType: true, + CreateMessageType: false, + RetrieveMessageType: false, + UpdateMessageType: false, + DeleteMessageType: false, + ServiceRegistrationMessageType: false, + ServiceAliveMessageType: false, + UnknownMessageType: false, + lastMessageType: false, + } + ) + + for messageType, expected := range expectedSupportsQOSAck { + assert.Equal(expected, messageType.SupportsQOSAck()) + } +} + func testStringToMessageTypeValid(t *testing.T, expected MessageType) { var ( assert = assert.New(t) From 4c9945f4e60616ed23b964874a34daf05c7d1522 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Mon, 11 Jul 2022 16:19:55 -0400 Subject: [PATCH 2/5] update tests for TestMessageTypeSupportsTransaction, TestMessageTypeSupportsQOSAck --- messagetype_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/messagetype_test.go b/messagetype_test.go index 5a3e689..068ed45 100644 --- a/messagetype_test.go +++ b/messagetype_test.go @@ -74,6 +74,7 @@ func TestMessageTypeSupportsTransaction(t *testing.T) { ServiceAliveMessageType: false, UnknownMessageType: false, lastMessageType: false, + lastMessageType + 1: false, } ) @@ -99,6 +100,7 @@ func TestMessageTypeSupportsQOSAck(t *testing.T) { ServiceAliveMessageType: false, UnknownMessageType: false, lastMessageType: false, + lastMessageType + 1: false, } ) From e405bd2781cb13ba767e4b235fbd4f46e8f4dc97 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Tue, 19 Jul 2022 10:30:50 -0400 Subject: [PATCH 3/5] Add IsQOSAckPart func, useful default qos values and unit tests --- messages.go | 16 +++++++ messages_test.go | 111 +++++++++++++++++++++++++++++++++++++++++++++++ qos.go | 7 +++ qos_test.go | 16 +++++++ 4 files changed, 150 insertions(+) diff --git a/messages.go b/messages.go index ecb84a1..78b910a 100644 --- a/messages.go +++ b/messages.go @@ -201,6 +201,22 @@ func (msg *Message) TransactionKey() string { return msg.TransactionUUID } +// IsQOSAckPart determines whether or not a message can QOS ack. +func (msg *Message) IsQOSAckPart() bool { + // TODO add tests + if !msg.Type.SupportsQOSAck() { + return false + } + + // https://xmidt.io/docs/wrp/basics/#qos-description-qos + switch msg.QualityOfService.Level() { + case QOSMedium, QOSHigh, QOSCritical: + return true + default: + return false + } +} + func (msg *Message) Response(newSource string, requestDeliveryResponse int64) Routable { response := *msg response.Destination = msg.Source diff --git a/messages_test.go b/messages_test.go index 030894f..a5f88b1 100644 --- a/messages_test.go +++ b/messages_test.go @@ -397,6 +397,117 @@ func testSimpleEventEncode(t *testing.T, f Format, original SimpleEvent) { assert.Equal(original, decoded) } +func TestIsQOSAckPart(t *testing.T) { + tests := []struct { + description string + msg Message + ack bool + }{ + // Ack case + { + description: "SimpleEventMessageType QOSMediumValue ack", + msg: Message{Type: SimpleEventMessageType, QualityOfService: QOSMediumValue}, + ack: true, + }, + { + description: "SimpleEventMessageType QOSHighValue ack", + msg: Message{Type: SimpleEventMessageType, QualityOfService: QOSHighValue}, + ack: true, + }, + { + description: "SimpleEventMessageType QOSCriticalValue ack", + msg: Message{Type: SimpleEventMessageType, QualityOfService: QOSCriticalValue}, + ack: true, + }, + { + description: "SimpleEventMessageType above QOS range ack", + msg: Message{Type: SimpleEventMessageType, QualityOfService: QOSCriticalValue + 1}, + ack: true, + }, + // No ack case + { + description: "SimpleEventMessageType below QOS range no ack", + msg: Message{Type: SimpleEventMessageType, QualityOfService: QOSLowValue - 1}, + }, + { + description: "SimpleEventMessageType QOSLowValue no ack", + msg: Message{Type: SimpleEventMessageType, QualityOfService: QOSLowValue}, + }, + { + description: "Invalid0MessageType no ack", + msg: Message{Type: Invalid0MessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "SimpleRequestResponseMessageType no ack", + msg: Message{Type: SimpleRequestResponseMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "CreateMessageType no ack", + msg: Message{Type: CreateMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "RetrieveMessageType no ack", + msg: Message{Type: RetrieveMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "UpdateMessageType no ack", + msg: Message{Type: UpdateMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "DeleteMessageType no ack", + msg: Message{Type: DeleteMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "ServiceRegistrationMessageType no ack", + msg: Message{Type: ServiceRegistrationMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "ServiceAliveMessageType no ack", + msg: Message{Type: ServiceAliveMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "UnknownMessageType no ack", + msg: Message{Type: UnknownMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "AuthorizationMessageType no ack", + msg: Message{Type: AuthorizationMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "Invalid0MessageType no ack", + msg: Message{Type: Invalid0MessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "Invalid1MessageType no ack", + msg: Message{Type: Invalid1MessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "lastMessageType no ack", + msg: Message{Type: lastMessageType, QualityOfService: QOSCriticalValue}, + }, + { + description: "Nonexistent negative MessageType no ack", + msg: Message{Type: -10, QualityOfService: QOSCriticalValue}, + }, + { + description: "Nonexistent positive MessageType no ack", + msg: Message{Type: lastMessageType + 1, QualityOfService: QOSCriticalValue}, + }, + } + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + if tc.ack { + assert.True(tc.msg.IsQOSAckPart()) + return + } + + assert.False(tc.msg.IsQOSAckPart()) + }) + } +} + func TestSimpleEvent(t *testing.T) { var messages = []SimpleEvent{ {}, diff --git a/qos.go b/qos.go index d7209f8..0087fc3 100644 --- a/qos.go +++ b/qos.go @@ -16,6 +16,13 @@ const ( // type determine what QOSLevel a message has. type QOSValue int +const ( + QOSLowValue QOSValue = iota * 25 + QOSMediumValue + QOSHighValue + QOSCriticalValue +) + // Level determines the QOSLevel for this value. Negative values are assumed // to be QOSLow. Values higher than the highest value (99) are assumed to // be QOSCritical. diff --git a/qos_test.go b/qos_test.go index d7eb683..7bd97d9 100644 --- a/qos_test.go +++ b/qos_test.go @@ -21,6 +21,22 @@ func TestQOSValue(t *testing.T) { value QOSValue expected QOSLevel }{ + { + value: QOSLowValue, + expected: QOSLow, + }, + { + value: QOSMediumValue, + expected: QOSMedium, + }, + { + value: QOSHighValue, + expected: QOSHigh, + }, + { + value: QOSCriticalValue, + expected: QOSCritical, + }, { value: -1, expected: QOSLow, From 7094bbecc23f9f728465bc5d7e5d4b1abfe4e8d7 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Tue, 19 Jul 2022 16:24:18 -0400 Subject: [PATCH 4/5] remove todo note --- messages.go | 1 - 1 file changed, 1 deletion(-) diff --git a/messages.go b/messages.go index 78b910a..0a9c2f4 100644 --- a/messages.go +++ b/messages.go @@ -203,7 +203,6 @@ func (msg *Message) TransactionKey() string { // IsQOSAckPart determines whether or not a message can QOS ack. func (msg *Message) IsQOSAckPart() bool { - // TODO add tests if !msg.Type.SupportsQOSAck() { return false } From a347b659056cf4007df2d1d62a627f8bec77180b Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Tue, 19 Jul 2022 17:18:20 -0400 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76466f7..d2593c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fix unmarshalling error due to missig metadata fields [#79](https://github.com/xmidt-org/wrp-go/pull/79) - Deprecated the concrete message structs, e.g. SimpleEvent - Added support for the new qos field. +- QOS implementation [#93](https://github.com/xmidt-org/wrp-go/pull/93), [#81](https://github.com/xmidt-org/wrp-go/pull/81) ## [v3.1.3] - Fix `500 Invalid WRP content type` for invalid `Accept` headers [#74](https://github.com/xmidt-org/wrp-go/pull/74)