static check (#36)
* static check * remove duplication * add tests --------- Signed-off-by: Gabriele Santomaggio <G.santomaggio@gmail.com>
This commit is contained in:
parent
a0dbb5594d
commit
8ffd1e6fc3
20
Makefile
20
Makefile
|
|
@ -1,3 +1,10 @@
|
||||||
|
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
|
||||||
|
ifeq (,$(shell go env GOBIN))
|
||||||
|
GOBIN = $(shell go env GOPATH)/bin
|
||||||
|
else
|
||||||
|
GOBIN = $(shell go env GOBIN)
|
||||||
|
endif
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
format:
|
format:
|
||||||
|
|
@ -6,7 +13,18 @@ format:
|
||||||
vet:
|
vet:
|
||||||
go vet ./pkg/rabbitmqamqp
|
go vet ./pkg/rabbitmqamqp
|
||||||
|
|
||||||
test: format vet
|
STATICCHECK ?= $(GOBIN)/staticcheck
|
||||||
|
STATICCHECK_VERSION ?= latest
|
||||||
|
$(STATICCHECK):
|
||||||
|
go install honnef.co/go/tools/cmd/staticcheck@$(STATICCHECK_VERSION)
|
||||||
|
check: $(STATICCHECK)
|
||||||
|
$(STATICCHECK) ./pkg/rabbitmqamqp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
test: format vet check
|
||||||
cd ./pkg/rabbitmqamqp && go run -mod=mod github.com/onsi/ginkgo/v2/ginkgo \
|
cd ./pkg/rabbitmqamqp && go run -mod=mod github.com/onsi/ginkgo/v2/ginkgo \
|
||||||
--randomize-all --randomize-suites \
|
--randomize-all --randomize-suites \
|
||||||
--cover --coverprofile=coverage.txt --covermode=atomic \
|
--cover --coverprofile=coverage.txt --covermode=atomic \
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,9 @@ func address(exchange, key, queue *string, urlParameters *string) (string, error
|
||||||
|
|
||||||
if !isStringNilOrEmpty(exchange) {
|
if !isStringNilOrEmpty(exchange) {
|
||||||
if !isStringNilOrEmpty(key) {
|
if !isStringNilOrEmpty(key) {
|
||||||
return "/" + exchanges + "/" + encodePathSegments(*exchange) + "/" + encodePathSegments(*key) + urlAppend, nil
|
return fmt.Sprintf("/%s/%s/%s%s", exchanges, encodePathSegments(*exchange), encodePathSegments(*key), urlAppend), nil
|
||||||
}
|
}
|
||||||
return "/" + exchanges + "/" + encodePathSegments(*exchange) + urlAppend, nil
|
return fmt.Sprintf("/%s/%s%s", exchanges, encodePathSegments(*exchange), urlAppend), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if queue == nil {
|
if queue == nil {
|
||||||
|
|
@ -73,8 +73,7 @@ func address(exchange, key, queue *string, urlParameters *string) (string, error
|
||||||
if isStringNilOrEmpty(queue) {
|
if isStringNilOrEmpty(queue) {
|
||||||
return "", errors.New("queue must be set")
|
return "", errors.New("queue must be set")
|
||||||
}
|
}
|
||||||
|
return fmt.Sprintf("/%s/%s%s", queues, encodePathSegments(*queue), urlAppend), nil
|
||||||
return "/" + queues + "/" + encodePathSegments(*queue) + urlAppend, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// exchangeAddress Creates the address for the exchange
|
// exchangeAddress Creates the address for the exchange
|
||||||
|
|
|
||||||
|
|
@ -6,59 +6,62 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("address builder test ", func() {
|
var _ = Describe("address builder test ", func() {
|
||||||
It("With exchange, queue and key should raise and error", func() {
|
// Error cases
|
||||||
queue := "my_queue"
|
Describe("Error cases", func() {
|
||||||
exchange := "my_exchange"
|
DescribeTable("should return appropriate errors",
|
||||||
|
func(exchange, key, queue *string, expectedErr string) {
|
||||||
_, err := address(&exchange, nil, &queue, nil)
|
_, err := address(exchange, key, queue, nil)
|
||||||
Expect(err).NotTo(BeNil())
|
Expect(err).To(HaveOccurred())
|
||||||
Expect(err.Error()).To(Equal("exchange and queue cannot be set together"))
|
Expect(err.Error()).To(Equal(expectedErr))
|
||||||
|
},
|
||||||
|
Entry("when both exchange and queue are set",
|
||||||
|
stringPtr("my_exchange"), nil, stringPtr("my_queue"),
|
||||||
|
"exchange and queue cannot be set together"),
|
||||||
|
Entry("when neither exchange nor queue is set",
|
||||||
|
nil, nil, nil,
|
||||||
|
"exchange or queue must be set"),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Without exchange and queue should raise and error", func() {
|
// Exchange-related cases
|
||||||
_, err := address(nil, nil, nil, nil)
|
Describe("Exchange addresses", func() {
|
||||||
Expect(err).NotTo(BeNil())
|
DescribeTable("should generate correct exchange addresses",
|
||||||
Expect(err.Error()).To(Equal("exchange or queue must be set"))
|
func(exchange, key *string, expected string) {
|
||||||
|
address, err := address(exchange, key, nil, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(address).To(Equal(expected))
|
||||||
|
},
|
||||||
|
Entry("with exchange and key",
|
||||||
|
stringPtr("my_exchange"), stringPtr("my_key"),
|
||||||
|
"/exchanges/my_exchange/my_key"),
|
||||||
|
Entry("with exchange only",
|
||||||
|
stringPtr("my_exchange"), nil,
|
||||||
|
"/exchanges/my_exchange"),
|
||||||
|
Entry("with special characters",
|
||||||
|
stringPtr("my_ exchange/()"), stringPtr("my_key "),
|
||||||
|
"/exchanges/my_%20exchange%2F%28%29/my_key%20"),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("With exchange and key should return address", func() {
|
// Queue-related cases
|
||||||
exchange := "my_exchange"
|
Describe("Queue addresses", func() {
|
||||||
key := "my_key"
|
It("should generate correct queue address with special characters", func() {
|
||||||
|
|
||||||
address, err := address(&exchange, &key, nil, nil)
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
Expect(address).To(Equal("/exchanges/my_exchange/my_key"))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("With exchange should return address", func() {
|
|
||||||
exchange := "my_exchange"
|
|
||||||
address, err := address(&exchange, nil, nil, nil)
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
Expect(address).To(Equal("/exchanges/my_exchange"))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("With exchange and key with names to encode should return the encoded address", func() {
|
|
||||||
|
|
||||||
exchange := "my_ exchange/()"
|
|
||||||
key := "my_key "
|
|
||||||
|
|
||||||
address, err := address(&exchange, &key, nil, nil)
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
Expect(address).To(Equal("/exchanges/my_%20exchange%2F%28%29/my_key%20"))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("With queue should return address", func() {
|
|
||||||
queue := "my_queue>"
|
queue := "my_queue>"
|
||||||
address, err := address(nil, nil, &queue, nil)
|
address, err := address(nil, nil, &queue, nil)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(address).To(Equal("/queues/my_queue%3E"))
|
Expect(address).To(Equal("/queues/my_queue%3E"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("With queue and urlParameters should return address", func() {
|
It("should generate correct purge queue address", func() {
|
||||||
queue := "my_queue"
|
queue := "my_queue"
|
||||||
address, err := purgeQueueAddress(&queue)
|
address, err := purgeQueueAddress(&queue)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(address).To(Equal("/queues/my_queue/messages"))
|
Expect(address).To(Equal("/queues/my_queue/messages"))
|
||||||
})
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Helper function to create string pointers
|
||||||
|
func stringPtr(s string) *string {
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -228,8 +228,7 @@ func (a *AmqpConnection) open(ctx context.Context, addresses []string, connOptio
|
||||||
var err error
|
var err error
|
||||||
a.session, err = a.azureConnection.NewSession(ctx, nil)
|
a.session, err = a.azureConnection.NewSession(ctx, nil)
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
<-azureConnection.Done()
|
||||||
case <-azureConnection.Done():
|
|
||||||
{
|
{
|
||||||
a.lifeCycle.SetState(&StateClosed{error: azureConnection.Err()})
|
a.lifeCycle.SetState(&StateClosed{error: azureConnection.Err()})
|
||||||
if azureConnection.Err() != nil {
|
if azureConnection.Err() != nil {
|
||||||
|
|
@ -240,7 +239,7 @@ func (a *AmqpConnection) open(ctx context.Context, addresses []string, connOptio
|
||||||
}
|
}
|
||||||
Debug("connection closed successfully")
|
Debug("connection closed successfully")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -261,67 +260,74 @@ func (a *AmqpConnection) maybeReconnect() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
a.lifeCycle.SetState(&StateReconnecting{})
|
a.lifeCycle.SetState(&StateReconnecting{})
|
||||||
numberOfAttempts := 1
|
// Add exponential backoff with jitter
|
||||||
waitTime := a.amqpConnOptions.RecoveryConfiguration.BackOffReconnectInterval
|
baseDelay := a.amqpConnOptions.RecoveryConfiguration.BackOffReconnectInterval
|
||||||
reconnected := false
|
maxDelay := 1 * time.Minute
|
||||||
for numberOfAttempts <= a.amqpConnOptions.RecoveryConfiguration.MaxReconnectAttempts {
|
|
||||||
|
for attempt := 1; attempt <= a.amqpConnOptions.RecoveryConfiguration.MaxReconnectAttempts; attempt++ {
|
||||||
|
|
||||||
///wait for before reconnecting
|
///wait for before reconnecting
|
||||||
// add some random milliseconds to the wait time to avoid thundering herd
|
// add some random milliseconds to the wait time to avoid thundering herd
|
||||||
// the random time is between 0 and 500 milliseconds
|
// the random time is between 0 and 500 milliseconds
|
||||||
waitTime = waitTime + time.Duration(rand.Intn(500))*time.Millisecond
|
// Calculate delay with exponential backoff and jitter
|
||||||
|
jitter := time.Duration(rand.Intn(500)) * time.Millisecond
|
||||||
|
delay := baseDelay + jitter
|
||||||
|
if delay > maxDelay {
|
||||||
|
delay = maxDelay
|
||||||
|
}
|
||||||
|
|
||||||
Info("Waiting before reconnecting", "in", waitTime, "attempt", numberOfAttempts)
|
Info("Attempting reconnection", "attempt", attempt, "delay", delay)
|
||||||
time.Sleep(waitTime)
|
time.Sleep(delay)
|
||||||
// context with timeout
|
// context with timeout
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
// try to createSender
|
// try to createSender
|
||||||
err := a.open(ctx, a.amqpConnOptions.addresses, a.amqpConnOptions)
|
err := a.open(ctx, a.amqpConnOptions.addresses, a.amqpConnOptions)
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err == nil {
|
||||||
numberOfAttempts++
|
a.restartEntities()
|
||||||
waitTime = waitTime * 2
|
a.lifeCycle.SetState(&StateOpen{})
|
||||||
Error("Failed to connection. ", "id", a.Id(), "error", err)
|
return
|
||||||
} else {
|
|
||||||
reconnected = true
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
baseDelay *= 2
|
||||||
|
Error("Reconnection attempt failed", "attempt", attempt, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if reconnected {
|
}
|
||||||
var fails int32
|
|
||||||
Info("Reconnected successfully, restarting publishers and consumers")
|
// restartEntities attempts to restart all publishers and consumers after a reconnection
|
||||||
|
func (a *AmqpConnection) restartEntities() {
|
||||||
|
var publisherFails, consumerFails int32
|
||||||
|
|
||||||
|
// Restart publishers
|
||||||
a.entitiesTracker.publishers.Range(func(key, value any) bool {
|
a.entitiesTracker.publishers.Range(func(key, value any) bool {
|
||||||
publisher := value.(*Publisher)
|
publisher := value.(*Publisher)
|
||||||
// try to createSender
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
err := publisher.createSender(ctx)
|
defer cancel()
|
||||||
if err != nil {
|
|
||||||
atomic.AddInt32(&fails, 1)
|
if err := publisher.createSender(ctx); err != nil {
|
||||||
Error("Failed to createSender publisher", "ID", publisher.Id(), "error", err)
|
atomic.AddInt32(&publisherFails, 1)
|
||||||
|
Error("Failed to restart publisher", "ID", publisher.Id(), "error", err)
|
||||||
}
|
}
|
||||||
cancel()
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
Info("Restarted publishers", "number of fails", fails)
|
|
||||||
fails = 0
|
// Restart consumers
|
||||||
a.entitiesTracker.consumers.Range(func(key, value any) bool {
|
a.entitiesTracker.consumers.Range(func(key, value any) bool {
|
||||||
consumer := value.(*Consumer)
|
consumer := value.(*Consumer)
|
||||||
// try to createSender
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
err := consumer.createReceiver(ctx)
|
defer cancel()
|
||||||
if err != nil {
|
|
||||||
atomic.AddInt32(&fails, 1)
|
if err := consumer.createReceiver(ctx); err != nil {
|
||||||
Error("Failed to createReceiver consumer", "ID", consumer.Id(), "error", err)
|
atomic.AddInt32(&consumerFails, 1)
|
||||||
|
Error("Failed to restart consumer", "ID", consumer.Id(), "error", err)
|
||||||
}
|
}
|
||||||
cancel()
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
Info("Restarted consumers", "number of fails", fails)
|
|
||||||
|
|
||||||
a.lifeCycle.SetState(&StateOpen{})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Info("Entity restart complete",
|
||||||
|
"publisherFails", publisherFails,
|
||||||
|
"consumerFails", consumerFails)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AmqpConnection) close() {
|
func (a *AmqpConnection) close() {
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,6 @@ func (e *entitiesTracker) storeOrReplaceProducer(entity entityIdentifier) {
|
||||||
e.publishers.Store(entity.Id(), entity)
|
e.publishers.Store(entity.Id(), entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *entitiesTracker) getProducer(id string) (*Publisher, bool) {
|
|
||||||
producer, ok := e.publishers.Load(id)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
return producer.(*Publisher), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *entitiesTracker) removeProducer(entity entityIdentifier) {
|
func (e *entitiesTracker) removeProducer(entity entityIdentifier) {
|
||||||
e.publishers.Delete(entity.Id())
|
e.publishers.Delete(entity.Id())
|
||||||
}
|
}
|
||||||
|
|
@ -69,14 +61,6 @@ func (e *entitiesTracker) storeOrReplaceConsumer(entity entityIdentifier) {
|
||||||
e.consumers.Store(entity.Id(), entity)
|
e.consumers.Store(entity.Id(), entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *entitiesTracker) getConsumer(id string) (*Consumer, bool) {
|
|
||||||
consumer, ok := e.consumers.Load(id)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
return consumer.(*Consumer), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *entitiesTracker) removeConsumer(entity entityIdentifier) {
|
func (e *entitiesTracker) removeConsumer(entity entityIdentifier) {
|
||||||
e.consumers.Delete(entity.Id())
|
e.consumers.Delete(entity.Id())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@ package rabbitmqamqp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Azure/go-amqp"
|
"github.com/Azure/go-amqp"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
testhelper "github.com/rabbitmq/rabbitmq-amqp-go-client/pkg/test-helper"
|
testhelper "github.com/rabbitmq/rabbitmq-amqp-go-client/pkg/test-helper"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Recovery connection test", func() {
|
var _ = Describe("Recovery connection test", func() {
|
||||||
|
|
@ -45,6 +46,7 @@ var _ = Describe("Recovery connection test", func() {
|
||||||
|
|
||||||
consumer, err := connection.NewConsumer(context.Background(),
|
consumer, err := connection.NewConsumer(context.Background(),
|
||||||
qName, nil)
|
qName, nil)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
publisher, err := connection.NewPublisher(context.Background(), &QueueAddress{
|
publisher, err := connection.NewPublisher(context.Background(), &QueueAddress{
|
||||||
Queue: qName,
|
Queue: qName,
|
||||||
|
|
@ -113,6 +115,23 @@ var _ = Describe("Recovery connection test", func() {
|
||||||
// from reconnecting to open
|
// from reconnecting to open
|
||||||
// from open to closed (without error)
|
// from open to closed (without error)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
Expect(consumer.Close(context.Background())).NotTo(BeNil())
|
||||||
|
Expect(publisher.Close(context.Background())).NotTo(BeNil())
|
||||||
|
|
||||||
|
entLen := 0
|
||||||
|
connection.entitiesTracker.consumers.Range(func(key, value interface{}) bool {
|
||||||
|
entLen++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
Expect(entLen).To(Equal(0))
|
||||||
|
|
||||||
|
entLen = 0
|
||||||
|
connection.entitiesTracker.publishers.Range(func(key, value interface{}) bool {
|
||||||
|
entLen++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
Expect(entLen).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("connection should not reconnect producers and consumers if the auto-recovery is disabled", func() {
|
It("connection should not reconnect producers and consumers if the auto-recovery is disabled", func() {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
||||||
|
|
||||||
var _ = Describe("AMQP connection Test", func() {
|
var _ = Describe("AMQP connection Test", func() {
|
||||||
It("AMQP SASLTypeAnonymous connection should succeed", func() {
|
It("AMQP SASLTypeAnonymous connection should succeed", func() {
|
||||||
|
|
||||||
connection, err := Dial(context.Background(), []string{"amqp://"}, &AmqpConnOptions{
|
connection, err := Dial(context.Background(), []string{"amqp://"}, &AmqpConnOptions{
|
||||||
SASLType: amqp.SASLTypeAnonymous()})
|
SASLType: amqp.SASLTypeAnonymous()})
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
@ -72,6 +71,64 @@ var _ = Describe("AMQP connection Test", func() {
|
||||||
Expect(recv.To).To(Equal(&StateClosed{}))
|
Expect(recv.To).To(Equal(&StateClosed{}))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Entity tracker should be aligned with consumers and publishers ", func() {
|
||||||
|
connection, err := Dial(context.Background(), []string{"amqp://"}, &AmqpConnOptions{
|
||||||
|
SASLType: amqp.SASLTypeAnonymous()})
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
Expect(connection).NotTo(BeNil())
|
||||||
|
|
||||||
|
queueName := generateNameWithDateTime("Entity tracker should be aligned with consumers and publishers")
|
||||||
|
|
||||||
|
_, err = connection.Management().DeclareQueue(context.Background(), &QuorumQueueSpecification{
|
||||||
|
Name: queueName,
|
||||||
|
})
|
||||||
|
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
publisher, err := connection.NewPublisher(context.Background(), &QueueAddress{Queue: queueName}, "test")
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
Expect(publisher).NotTo(BeNil())
|
||||||
|
consumer, err := connection.NewConsumer(context.Background(), queueName, nil)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
Expect(consumer).NotTo(BeNil())
|
||||||
|
// check the entity tracker
|
||||||
|
Expect(connection.entitiesTracker).NotTo(BeNil())
|
||||||
|
entLen := 0
|
||||||
|
connection.entitiesTracker.consumers.Range(func(key, value interface{}) bool {
|
||||||
|
entLen++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
Expect(entLen).To(Equal(1))
|
||||||
|
|
||||||
|
entLen = 0
|
||||||
|
connection.entitiesTracker.publishers.Range(func(key, value interface{}) bool {
|
||||||
|
entLen++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
Expect(entLen).To(Equal(1))
|
||||||
|
Expect(consumer.Close(context.Background())).To(BeNil())
|
||||||
|
Expect(publisher.Close(context.Background())).To(BeNil())
|
||||||
|
|
||||||
|
entLen = 0
|
||||||
|
connection.entitiesTracker.consumers.Range(func(key, value interface{}) bool {
|
||||||
|
entLen++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
Expect(entLen).To(Equal(0))
|
||||||
|
|
||||||
|
entLen = 0
|
||||||
|
connection.entitiesTracker.publishers.Range(func(key, value interface{}) bool {
|
||||||
|
entLen++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
Expect(entLen).To(Equal(0))
|
||||||
|
|
||||||
|
err = connection.Management().DeleteQueue(context.Background(), queueName)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
Expect(connection.Close(context.Background())).To(BeNil())
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
//It("AMQP TLS connection should success with SASLTypeAnonymous ", func() {
|
//It("AMQP TLS connection should success with SASLTypeAnonymous ", func() {
|
||||||
// amqpConnection := NewAmqpConnection()
|
// amqpConnection := NewAmqpConnection()
|
||||||
// Expect(amqpConnection).NotTo(BeNil())
|
// Expect(amqpConnection).NotTo(BeNil())
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,23 @@ func (dc *DeliveryContext) Discard(ctx context.Context, e *amqp.Error) error {
|
||||||
return dc.receiver.RejectMessage(ctx, dc.message, e)
|
return dc.receiver.RejectMessage(ctx, dc.message, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *DeliveryContext) DiscardWithAnnotations(ctx context.Context, annotations amqp.Annotations) error {
|
// copyAnnotations helper function to copy annotations
|
||||||
|
func copyAnnotations(annotations amqp.Annotations) (amqp.Annotations, error) {
|
||||||
if err := validateMessageAnnotations(annotations); err != nil {
|
if err := validateMessageAnnotations(annotations); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
destination := make(amqp.Annotations)
|
||||||
|
for key, value := range annotations {
|
||||||
|
destination[key] = value
|
||||||
|
}
|
||||||
|
return destination, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *DeliveryContext) DiscardWithAnnotations(ctx context.Context, annotations amqp.Annotations) error {
|
||||||
|
destination, err := copyAnnotations(annotations)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// copy the rabbitmq annotations to amqp annotations
|
|
||||||
destination := make(amqp.Annotations)
|
|
||||||
for keyA, value := range annotations {
|
|
||||||
destination[keyA] = value
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return dc.receiver.ModifyMessage(ctx, dc.message, &amqp.ModifyMessageOptions{
|
return dc.receiver.ModifyMessage(ctx, dc.message, &amqp.ModifyMessageOptions{
|
||||||
DeliveryFailed: true,
|
DeliveryFailed: true,
|
||||||
UndeliverableHere: true,
|
UndeliverableHere: true,
|
||||||
|
|
@ -48,15 +54,10 @@ func (dc *DeliveryContext) Requeue(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *DeliveryContext) RequeueWithAnnotations(ctx context.Context, annotations amqp.Annotations) error {
|
func (dc *DeliveryContext) RequeueWithAnnotations(ctx context.Context, annotations amqp.Annotations) error {
|
||||||
if err := validateMessageAnnotations(annotations); err != nil {
|
destination, err := copyAnnotations(annotations)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// copy the rabbitmq annotations to amqp annotations
|
|
||||||
destination := make(amqp.Annotations)
|
|
||||||
for key, value := range annotations {
|
|
||||||
destination[key] = value
|
|
||||||
|
|
||||||
}
|
|
||||||
return dc.receiver.ModifyMessage(ctx, dc.message, &amqp.ModifyMessageOptions{
|
return dc.receiver.ModifyMessage(ctx, dc.message, &amqp.ModifyMessageOptions{
|
||||||
DeliveryFailed: false,
|
DeliveryFailed: false,
|
||||||
UndeliverableHere: false,
|
UndeliverableHere: false,
|
||||||
|
|
@ -144,5 +145,6 @@ func (c *Consumer) Receive(ctx context.Context) (*DeliveryContext, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Consumer) Close(ctx context.Context) error {
|
func (c *Consumer) Close(ctx context.Context) error {
|
||||||
|
c.connection.entitiesTracker.removeConsumer(c)
|
||||||
return c.receiver.Load().Close(ctx)
|
return c.receiver.Load().Close(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
dc, err := consumerOffsetValue.Receive(context.Background())
|
dc, err := consumerOffsetValue.Receive(context.Background())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("Message #%d", i+5)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("Message #%d", i+5)))
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
dc, err := consumerFirst.Receive(context.Background())
|
dc, err := consumerFirst.Receive(context.Background())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("Message #%d", i)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("Message #%d", i)))
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
dc, err := consumerLast.Receive(context.Background())
|
dc, err := consumerLast.Receive(context.Background())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).NotTo(Equal(fmt.Sprintf("Message #%d", 0)))
|
Expect(string(dc.Message().GetData())).NotTo(Equal(fmt.Sprintf("Message #%d", 0)))
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
|
|
||||||
consumerNext, err := connection.NewConsumer(context.Background(), qName, &StreamConsumerOptions{
|
consumerNext, err := connection.NewConsumer(context.Background(), qName, &StreamConsumerOptions{
|
||||||
|
|
@ -125,7 +125,7 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
dc, err = consumerNext.Receive(context.Background())
|
dc, err = consumerNext.Receive(context.Background())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal("the next message"))
|
Expect(string(dc.Message().GetData())).To(Equal("the next message"))
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
signal <- struct{}{}
|
signal <- struct{}{}
|
||||||
}()
|
}()
|
||||||
|
|
@ -179,7 +179,7 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
dc, err := consumer.Receive(context.Background())
|
dc, err := consumer.Receive(context.Background())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("Message #%d", i)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("Message #%d", i)))
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,7 +200,7 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
dc, err := consumer.Receive(context.Background())
|
dc, err := consumer.Receive(context.Background())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("Message #%d", i)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("Message #%d", i)))
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(consumer.Close(context.Background())).To(BeNil())
|
Expect(consumer.Close(context.Background())).To(BeNil())
|
||||||
|
|
@ -235,7 +235,7 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
dc, err := consumerBanana.Receive(context.Background())
|
dc, err := consumerBanana.Receive(context.Background())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("banana #%d", i)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("banana #%d", i)))
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,7 +254,7 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
dc, err := consumerApple.Receive(context.Background())
|
dc, err := consumerApple.Receive(context.Background())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("apple #%d", i)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("apple #%d", i)))
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,9 +273,9 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
if i < 10 {
|
if i < 10 {
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("banana #%d", i)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("banana #%d", i)))
|
||||||
} else {
|
} else {
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("apple #%d", i-10)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("apple #%d", i-10)))
|
||||||
}
|
}
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
}
|
}
|
||||||
|
|
@ -296,10 +296,9 @@ var _ = Describe("Consumer stream test", func() {
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(dc.Message()).NotTo(BeNil())
|
Expect(dc.Message()).NotTo(BeNil())
|
||||||
if i < 10 {
|
if i < 10 {
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf("apple #%d", i)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf("apple #%d", i)))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Expect(fmt.Sprintf("%s", dc.Message().GetData())).To(Equal(fmt.Sprintf(" #%d", i-10)))
|
Expect(string(dc.Message().GetData())).To(Equal(fmt.Sprintf(" #%d", i-10)))
|
||||||
}
|
}
|
||||||
Expect(dc.Accept(context.Background())).To(BeNil())
|
Expect(dc.Accept(context.Background())).To(BeNil())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ var _ = Describe("NewConsumer tests", func() {
|
||||||
Expect(consumer.Close(context.Background())).To(BeNil())
|
Expect(consumer.Close(context.Background())).To(BeNil())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
nMessages, err := connection.Management().PurgeQueue(context.Background(), qName)
|
nMessages, err := connection.Management().PurgeQueue(context.Background(), qName)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
Expect(nMessages).To(Equal(1))
|
Expect(nMessages).To(Equal(1))
|
||||||
Expect(connection.Management().DeleteQueue(context.Background(), qName)).To(BeNil())
|
Expect(connection.Management().DeleteQueue(context.Background(), qName)).To(BeNil())
|
||||||
Expect(connection.Close(context.Background())).To(BeNil())
|
Expect(connection.Close(context.Background())).To(BeNil())
|
||||||
|
|
@ -116,6 +117,7 @@ var _ = Describe("NewConsumer tests", func() {
|
||||||
Expect(consumer.Close(context.Background())).To(BeNil())
|
Expect(consumer.Close(context.Background())).To(BeNil())
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
nMessages, err := connection.Management().PurgeQueue(context.Background(), qName)
|
nMessages, err := connection.Management().PurgeQueue(context.Background(), qName)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
Expect(nMessages).To(Equal(1))
|
Expect(nMessages).To(Equal(1))
|
||||||
Expect(connection.Management().DeleteQueue(context.Background(), qName)).To(BeNil())
|
Expect(connection.Management().DeleteQueue(context.Background(), qName)).To(BeNil())
|
||||||
Expect(connection.Close(context.Background())).To(BeNil())
|
Expect(connection.Close(context.Background())).To(BeNil())
|
||||||
|
|
@ -153,6 +155,7 @@ var _ = Describe("NewConsumer tests", func() {
|
||||||
Info: nil,
|
Info: nil,
|
||||||
})).To(BeNil())
|
})).To(BeNil())
|
||||||
nMessages, err := connection.Management().PurgeQueue(context.Background(), qName)
|
nMessages, err := connection.Management().PurgeQueue(context.Background(), qName)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
Expect(nMessages).To(Equal(0))
|
Expect(nMessages).To(Equal(0))
|
||||||
Expect(consumer.Close(context.Background())).To(BeNil())
|
Expect(consumer.Close(context.Background())).To(BeNil())
|
||||||
Expect(connection.Management().DeleteQueue(context.Background(), qName)).To(BeNil())
|
Expect(connection.Management().DeleteQueue(context.Background(), qName)).To(BeNil())
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Azure/go-amqp"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Azure/go-amqp"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrPreconditionFailed = errors.New("precondition Failed")
|
var ErrPreconditionFailed = errors.New("precondition Failed")
|
||||||
|
|
@ -22,7 +23,6 @@ type AmqpManagement struct {
|
||||||
sender *amqp.Sender
|
sender *amqp.Sender
|
||||||
receiver *amqp.Receiver
|
receiver *amqp.Receiver
|
||||||
lifeCycle *LifeCycle
|
lifeCycle *LifeCycle
|
||||||
cancel context.CancelFunc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAmqpManagement() *AmqpManagement {
|
func NewAmqpManagement() *AmqpManagement {
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ var _ = Describe("AMQP publisher ", func() {
|
||||||
err = connection.management.DeleteQueue(context.Background(), qName)
|
err = connection.management.DeleteQueue(context.Background(), qName)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
publishResult, err = publisher.Publish(context.Background(), NewMessage([]byte("hello")))
|
publishResult, err = publisher.Publish(context.Background(), NewMessage([]byte("hello")))
|
||||||
|
Expect(publishResult).To(BeNil())
|
||||||
Expect(err).NotTo(BeNil())
|
Expect(err).NotTo(BeNil())
|
||||||
Expect(connection.Close(context.Background()))
|
Expect(connection.Close(context.Background()))
|
||||||
})
|
})
|
||||||
|
|
@ -146,6 +147,8 @@ var _ = Describe("AMQP publisher ", func() {
|
||||||
Name: name,
|
Name: name,
|
||||||
IsAutoDelete: false,
|
IsAutoDelete: false,
|
||||||
})
|
})
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
msg = NewMessage([]byte("hello"))
|
msg = NewMessage([]byte("hello"))
|
||||||
Expect(MessagePropertyToAddress(msg, &ExchangeAddress{Exchange: name})).To(BeNil())
|
Expect(MessagePropertyToAddress(msg, &ExchangeAddress{Exchange: name})).To(BeNil())
|
||||||
// the status should be StateReleased since the exchange does not have any binding
|
// the status should be StateReleased since the exchange does not have any binding
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ var _ = Describe("AMQP Queue test ", func() {
|
||||||
|
|
||||||
// validate GET (query queue info)
|
// validate GET (query queue info)
|
||||||
queueInfoReceived, err := management.QueueInfo(context.TODO(), queueName)
|
queueInfoReceived, err := management.QueueInfo(context.TODO(), queueName)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
Expect(queueInfoReceived).To(Equal(queueInfo))
|
Expect(queueInfoReceived).To(Equal(queueInfo))
|
||||||
|
|
||||||
err = management.DeleteQueue(context.TODO(), queueName)
|
err = management.DeleteQueue(context.TODO(), queueName)
|
||||||
|
|
@ -84,6 +85,7 @@ var _ = Describe("AMQP Queue test ", func() {
|
||||||
|
|
||||||
// validate GET (query queue info)
|
// validate GET (query queue info)
|
||||||
queueInfoReceived, err := management.QueueInfo(context.TODO(), queueName)
|
queueInfoReceived, err := management.QueueInfo(context.TODO(), queueName)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
Expect(queueInfoReceived).To(Equal(queueInfo))
|
Expect(queueInfoReceived).To(Equal(queueInfo))
|
||||||
|
|
||||||
err = management.DeleteQueue(context.TODO(), queueName)
|
err = management.DeleteQueue(context.TODO(), queueName)
|
||||||
|
|
@ -108,6 +110,7 @@ var _ = Describe("AMQP Queue test ", func() {
|
||||||
Expect(queueInfo.Type()).To(Equal(Quorum))
|
Expect(queueInfo.Type()).To(Equal(Quorum))
|
||||||
// validate GET (query queue info)
|
// validate GET (query queue info)
|
||||||
queueInfoReceived, err := management.QueueInfo(context.TODO(), queueName)
|
queueInfoReceived, err := management.QueueInfo(context.TODO(), queueName)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
Expect(queueInfoReceived).To(Equal(queueInfo))
|
Expect(queueInfoReceived).To(Equal(queueInfo))
|
||||||
|
|
||||||
err = management.DeleteQueue(context.TODO(), queueName)
|
err = management.DeleteQueue(context.TODO(), queueName)
|
||||||
|
|
@ -134,6 +137,7 @@ var _ = Describe("AMQP Queue test ", func() {
|
||||||
Expect(queueInfo.Type()).To(Equal(Classic))
|
Expect(queueInfo.Type()).To(Equal(Classic))
|
||||||
// validate GET (query queue info)
|
// validate GET (query queue info)
|
||||||
queueInfoReceived, err := management.QueueInfo(context.TODO(), queueName)
|
queueInfoReceived, err := management.QueueInfo(context.TODO(), queueName)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
Expect(queueInfoReceived).To(Equal(queueInfo))
|
Expect(queueInfoReceived).To(Equal(queueInfo))
|
||||||
|
|
||||||
err = management.DeleteQueue(context.TODO(), queueName)
|
err = management.DeleteQueue(context.TODO(), queueName)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ package rabbitmqamqp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Azure/go-amqp"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Azure/go-amqp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const AtMostOnce = 0
|
const AtMostOnce = 0
|
||||||
|
|
@ -74,7 +75,7 @@ func random(max int) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateMessageAnnotations(annotations amqp.Annotations) error {
|
func validateMessageAnnotations(annotations amqp.Annotations) error {
|
||||||
for k, _ := range annotations {
|
for k := range annotations {
|
||||||
switch tp := k.(type) {
|
switch tp := k.(type) {
|
||||||
case string:
|
case string:
|
||||||
if err := validateMessageAnnotationKey(tp); err != nil {
|
if err := validateMessageAnnotationKey(tp); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -34,15 +34,15 @@ var _ = Describe("Converters", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Converts from string logError", func() {
|
It("Converts from string logError", func() {
|
||||||
v, err := CapacityFrom("10LL")
|
_, err := CapacityFrom("10LL")
|
||||||
Expect(fmt.Sprintf("%s", err)).
|
Expect(fmt.Sprintf("%s", err)).
|
||||||
To(ContainSubstring("Invalid unit size format"))
|
To(ContainSubstring("Invalid unit size format"))
|
||||||
|
|
||||||
v, err = CapacityFrom("aGB")
|
_, err = CapacityFrom("aGB")
|
||||||
Expect(fmt.Sprintf("%s", err)).
|
Expect(fmt.Sprintf("%s", err)).
|
||||||
To(ContainSubstring("Invalid number format"))
|
To(ContainSubstring("Invalid number format"))
|
||||||
|
|
||||||
v, err = CapacityFrom("")
|
v, err := CapacityFrom("")
|
||||||
Expect(v).To(Equal(int64(0)))
|
Expect(v).To(Equal(int64(0)))
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue