Skip to content

Commit

Permalink
Add integration tests for exchange controller
Browse files Browse the repository at this point in the history
  • Loading branch information
ChunyiLyu committed Apr 14, 2021
1 parent da5cd6e commit 6dfac99
Showing 1 changed file with 218 additions and 0 deletions.
218 changes: 218 additions & 0 deletions controllers/exchange_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
package controllers_test

import (
"bytes"
"errors"
"io/ioutil"
"net/http"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"
topology "github.com/rabbitmq/messaging-topology-operator/api/v1alpha2"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)

var _ = Describe("exchange-controller", func() {
var exchange topology.Exchange
var exchangeName string

JustBeforeEach(func() {
exchange = topology.Exchange{
ObjectMeta: metav1.ObjectMeta{
Name: exchangeName,
Namespace: "default",
},
Spec: topology.ExchangeSpec{
RabbitmqClusterReference: topology.RabbitmqClusterReference{
Name: "example-rabbit",
},
},
}
})

Context("creation", func() {
When("the RabbitMQ Client returns a HTTP error response", func() {
BeforeEach(func() {
exchangeName = "test-http-error"
fakeRabbitMQClient.DeclareExchangeReturns(&http.Response{
Status: "418 I'm a teapot",
StatusCode: 418,
}, errors.New("a failure"))
})

It("sets the status condition", func() {
Expect(client.Create(ctx, &exchange)).To(Succeed())
EventuallyWithOffset(1, func() []topology.Condition {
_ = client.Get(
ctx,
types.NamespacedName{Name: exchange.Name, Namespace: exchange.Namespace},
&exchange,
)

return exchange.Status.Conditions
}, 10*time.Second, 1*time.Second).Should(ContainElement(MatchFields(IgnoreExtras, Fields{
"Type": Equal(topology.ConditionType("Ready")),
"Reason": Equal("FailedCreateOrUpdate"),
"Status": Equal(corev1.ConditionFalse),
"Message": ContainSubstring("a failure"),
})))
})
})

When("the RabbitMQ Client returns a Go error response", func() {
BeforeEach(func() {
exchangeName = "test-go-error"
fakeRabbitMQClient.DeclareExchangeReturns(nil, errors.New("a go failure"))
})

It("sets the status condition to indicate a failure to reconcile", func() {
Expect(client.Create(ctx, &exchange)).To(Succeed())
EventuallyWithOffset(1, func() []topology.Condition {
_ = client.Get(
ctx,
types.NamespacedName{Name: exchange.Name, Namespace: exchange.Namespace},
&exchange,
)

return exchange.Status.Conditions
}, 10*time.Second, 1*time.Second).Should(ContainElement(MatchFields(IgnoreExtras, Fields{
"Type": Equal(topology.ConditionType("Ready")),
"Reason": Equal("FailedCreateOrUpdate"),
"Status": Equal(corev1.ConditionFalse),
"Message": ContainSubstring("a go failure"),
})))
})
})

When("success", func() {
BeforeEach(func() {
exchangeName = "test-create-success"
fakeRabbitMQClient.DeclareExchangeReturns(&http.Response{
Status: "201 Created",
StatusCode: http.StatusCreated,
}, nil)
})

It("sets the status condition 'Ready' to 'true' ", func() {
Expect(client.Create(ctx, &exchange)).To(Succeed())
EventuallyWithOffset(1, func() []topology.Condition {
_ = client.Get(
ctx,
types.NamespacedName{Name: exchange.Name, Namespace: exchange.Namespace},
&exchange,
)

return exchange.Status.Conditions
}, 10*time.Second, 1*time.Second).Should(ContainElement(MatchFields(IgnoreExtras, Fields{
"Type": Equal(topology.ConditionType("Ready")),
"Reason": Equal("SuccessfulCreateOrUpdate"),
"Status": Equal(corev1.ConditionTrue),
})))
})
})
})

Context("deletion", func() {
JustBeforeEach(func() {
fakeRabbitMQClient.DeclareExchangeReturns(&http.Response{
Status: "201 Created",
StatusCode: http.StatusCreated,
}, nil)
Expect(client.Create(ctx, &exchange)).To(Succeed())
EventuallyWithOffset(1, func() []topology.Condition {
_ = client.Get(
ctx,
types.NamespacedName{Name: exchange.Name, Namespace: exchange.Namespace},
&exchange,
)

return exchange.Status.Conditions
}, 10*time.Second, 1*time.Second).Should(ContainElement(MatchFields(IgnoreExtras, Fields{
"Type": Equal(topology.ConditionType("Ready")),
"Reason": Equal("SuccessfulCreateOrUpdate"),
"Status": Equal(corev1.ConditionTrue),
})))
})

When("the RabbitMQ Client returns a HTTP error response", func() {
BeforeEach(func() {
exchangeName = "delete-exchange-http-error"
fakeRabbitMQClient.DeleteExchangeReturns(&http.Response{
Status: "502 Bad Gateway",
StatusCode: http.StatusBadGateway,
Body: ioutil.NopCloser(bytes.NewBufferString("Hello World")),
}, nil)
})

It("publishes a 'warning' event", func() {
Expect(client.Delete(ctx, &exchange)).To(Succeed())
Consistently(func() bool {
err := client.Get(ctx, types.NamespacedName{Name: exchange.Name, Namespace: exchange.Namespace}, &topology.Exchange{})
return apierrors.IsNotFound(err)
}, 5).Should(BeFalse())
Expect(observedEvents()).To(ContainElement("Warning FailedDelete failed to delete exchange"))
})
})

When("the RabbitMQ Client returns a Go error response", func() {
BeforeEach(func() {
exchangeName = "delete-go-error"
fakeRabbitMQClient.DeleteExchangeReturns(nil, errors.New("some error"))
})

It("publishes a 'warning' event", func() {
Expect(client.Delete(ctx, &exchange)).To(Succeed())
Consistently(func() bool {
err := client.Get(ctx, types.NamespacedName{Name: exchange.Name, Namespace: exchange.Namespace}, &topology.Exchange{})
return apierrors.IsNotFound(err)
}, 5).Should(BeFalse())
Expect(observedEvents()).To(ContainElement("Warning FailedDelete failed to delete exchange"))
})
})

When("the RabbitMQ cluster is nil", func() {
BeforeEach(func() {
exchangeName = "delete-client-not-found-error"
})

JustBeforeEach(func() {
prepareNoSuchClusterError()
})

It("successfully deletes the exchange regardless", func() {
Expect(client.Delete(ctx, &exchange)).To(Succeed())
Eventually(func() bool {
err := client.Get(ctx, types.NamespacedName{Name: exchange.Name, Namespace: exchange.Namespace}, &topology.Exchange{})
return apierrors.IsNotFound(err)
}, 5).Should(BeTrue())
Expect(observedEvents()).To(ContainElement("Normal SuccessfulDelete successfully deleted exchange"))
})
})

When("the RabbitMQ Client successfully deletes a exchange", func() {
BeforeEach(func() {
exchangeName = "delete-exchange-success"
fakeRabbitMQClient.DeleteExchangeReturns(&http.Response{
Status: "204 No Content",
StatusCode: http.StatusNoContent,
}, nil)
})

It("publishes a normal event", func() {
Expect(client.Delete(ctx, &exchange)).To(Succeed())
Eventually(func() bool {
err := client.Get(ctx, types.NamespacedName{Name: exchange.Name, Namespace: exchange.Namespace}, &topology.Exchange{})
return apierrors.IsNotFound(err)
}, 5).Should(BeTrue())
observedEvents := observedEvents()
Expect(observedEvents).NotTo(ContainElement("Warning FailedDelete failed to delete exchange"))
Expect(observedEvents).To(ContainElement("Normal SuccessfulDelete successfully deleted exchange"))
})
})
})
})

0 comments on commit 6dfac99

Please sign in to comment.