Skip to content

Commit

Permalink
Functional demo - Woot!
Browse files Browse the repository at this point in the history
Signed-off-by: Laurent Broudoux <laurent.broudoux@gmail.com>
  • Loading branch information
lbroudoux committed Nov 14, 2024
1 parent 8d7ceb1 commit e43a4b4
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 305 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,5 @@ $ go test -timeout 30s -run "^TestPostmanCollectionContract$" ./internal/control

$ go test -timeout 30s -run "^TestOrderEventIsPublishedWhenOrderIsCreated$" ./internal/service -v

#$ go test -timeout 30s -run "^TestEventIsConsumedAndProcessedByService$" ./internal/service -v
$ go test -timeout 30s -run "^TestEventIsConsumedAndProcessedByService$" ./internal/service -v
```
4 changes: 3 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ func main() {
}

appServicesChan := make(chan internal.ApplicationServices)
go run.Run(*applicationProperties, appServicesChan)
app := run.NewApplication()
go app.Start(*applicationProperties, appServicesChan)
_ = <-appServicesChan

// Setup signal hooks.
Expand All @@ -66,5 +67,6 @@ func main() {
}()

<-close
app.Stop()
fmt.Println("Exiting Microcks TestContainers Go Demo application main.")
}
58 changes: 37 additions & 21 deletions cmd/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ import (
"fmt"
"net/http"
"os"
"os/signal"
"strings"
"syscall"

"github.com/confluentinc/confluent-kafka-go/v2/kafka"
app "github.com/microcks/microcks-testcontainers-go-demo/internal"
Expand All @@ -36,20 +34,27 @@ const (
DefaultApplicationPort = 9000
)

var close chan bool
// Application is the application interface for starting/stopping it.
type Application interface {
// Start this demo application using properties.
Start(applicationProperties app.ApplicationProperties, applicationServices chan app.ApplicationServices)
// Stop this demo application.
Stop()
}

func Run(applicationProperties app.ApplicationProperties, applicationServices chan app.ApplicationServices) {
// Setup signal hooks.
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
close = make(chan bool, 1)
type application struct {
stopChannel chan struct{}
appServices app.ApplicationServices
}

go func() {
sig := <-sigs
fmt.Println("Caught signal " + sig.String())
close <- true
}()
func NewApplication() Application {
return &application{}
}

func (me *application) Start(applicationProperties app.ApplicationProperties, applicationServices chan app.ApplicationServices) {
me.stopChannel = make(chan struct{})

// Initialize kafka server.
kafkaServer, err := applicationProperties.KafkaConfigMap.Get("bootstrap.servers", "unknown")
if err != nil {
fmt.Println("No bootstrap.servers specified for KafkaServer", err)
Expand Down Expand Up @@ -104,17 +109,28 @@ func Run(applicationProperties app.ApplicationProperties, applicationServices ch

//go http.ListenAndServe(":9000", nil)
server := &http.Server{Addr: ":9000", Handler: mux}
err = server.ListenAndServe()

<-close
orderListener.Stop()
kafkaProducer.Close()
server.Shutdown(context.Background())
fmt.Println("Exiting Microcks TestContainers Go Demo application.")
go func() {
for {
select {
case <-me.stopChannel:
orderListener.Stop()
fmt.Println("Stopping Kafka producer & consumer...")
kafkaProducer.Close()
kafkaConsumer.Close()
server.Shutdown(context.Background())
fmt.Println("Application is stopped")
return
default:
err = server.ListenAndServe()
}
}
}()
}

func Close() {
close <- true
func (me *application) Stop() {
fmt.Println("Stopping Microcks TestContainers Go Demo application...")
close(me.stopChannel)
}

func handler(w http.ResponseWriter, r *http.Request) {
Expand Down
15 changes: 15 additions & 0 deletions internal/client/pastry_api.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* Copyright The Microcks 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 client

import (
Expand Down
20 changes: 17 additions & 3 deletions internal/client/pastry_api_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* Copyright The Microcks 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 client_test

import (
Expand All @@ -7,13 +22,12 @@ import (
"github.com/stretchr/testify/require"

"github.com/microcks/microcks-testcontainers-go-demo/internal/client"
"github.com/testcontainers/testcontainers-go"
microcks "microcks.io/testcontainers-go"
)

func setup(ctx context.Context, t *testing.T) *microcks.MicrocksContainer {
microcksContainer, err := microcks.RunContainer(ctx,
testcontainers.WithImage("quay.io/microcks/microcks-uber:1.9.0-native"),
microcksContainer, err := microcks.Run(ctx,
"quay.io/microcks/microcks-uber:1.10.0-native",
microcks.WithMainArtifact("../../testdata/apipastries-openapi.yaml"),
microcks.WithSecondaryArtifact("../../testdata/apipastries-postman-collection.json"),
)
Expand Down
193 changes: 47 additions & 146 deletions internal/controller/order_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,175 +21,76 @@ import (
"fmt"
"testing"

"github.com/confluentinc/confluent-kafka-go/v2/kafka"
server "github.com/microcks/microcks-testcontainers-go-demo/cmd/run"
app "github.com/microcks/microcks-testcontainers-go-demo/internal"
helper "github.com/microcks/microcks-testcontainers-go-demo/internal/test"
"github.com/stretchr/testify/require"
testcontainers "github.com/testcontainers/testcontainers-go"
kafkaTC "github.com/testcontainers/testcontainers-go/modules/kafka"
"github.com/testcontainers/testcontainers-go/network"
client "microcks.io/go-client"
ensemble "microcks.io/testcontainers-go/ensemble"
)

func setupEnsemble(ctx context.Context, t *testing.T, net *testcontainers.DockerNetwork) *ensemble.MicrocksContainersEnsemble {
microcksEnsemble, err := ensemble.RunContainers(ctx,
ensemble.WithMainArtifact("../../testdata/order-service-openapi.yaml"),
ensemble.WithMainArtifact("../../testdata/apipastries-openapi.yaml"),
ensemble.WithSecondaryArtifact("../../testdata/order-service-postman-collection.json"),
ensemble.WithSecondaryArtifact("../../testdata/apipastries-postman-collection.json"),
ensemble.WithPostman(),
ensemble.WithNetwork(net),
ensemble.WithHostAccessPorts([]int{server.DefaultApplicationPort}),
)
require.NoError(t, err)
t.Cleanup(func() {
if err := microcksEnsemble.Terminate(ctx); err != nil {
t.Fatalf("failed to terminate container: %s", err)
}
})
return microcksEnsemble
}

func TestOpenAPIContractAdvanced(t *testing.T) {
ctx := context.Background()

// Common network and Kafka container.
net, err := network.New(ctx, network.WithCheckDuplicate())
if err != nil {
require.NoError(t, err)
return
}

kafkaContainer, err := kafkaTC.Run(ctx,
"confluentinc/confluent-local:7.5.0",
network.WithNetwork([]string{"kafka"}, net),
)
t.Cleanup(func() {
if err := kafkaContainer.Terminate(ctx); err != nil {
t.Fatalf("failed to terminate Kafka container: %s", err)
t.Run("Test", testOpenAPIContractAdvanced(func(t *testing.T, tc *helper.TestContext) {
// Test code goes here which can leverage the context
// Prepare a Microcks Test.
testRequest := client.TestRequest{
ServiceId: "Order Service API:0.1.0",
RunnerType: client.TestRunnerTypeOPENAPISCHEMA,
TestEndpoint: fmt.Sprintf("http://host.testcontainers.internal:%d/api", server.DefaultApplicationPort),
Timeout: 2000,
}
})

brokerURL, err := kafkaContainer.Brokers(ctx)
if err != nil || len(brokerURL) == 0 {
testResult, err := tc.MicrocksEnsemble.GetMicrocksContainer().TestEndpoint(ctx, &testRequest)
require.NoError(t, err)
return
}
fmt.Println("BrokerURL is " + brokerURL[0])

microcksEnsemble := setupEnsemble(ctx, t, net)

baseApiUrl, err := microcksEnsemble.GetMicrocksContainer().RestMockEndpoint(ctx, "API Pastries", "0.0.1")
require.NoError(t, err)

applicationProperties := &app.ApplicationProperties{
PastriesBaseUrl: baseApiUrl,
OrderEventsCreatedTopic: "orders-created",
OrderEventsReviewedTopic: "orders-reviewed",
KafkaConfigMap: &kafka.ConfigMap{
"bootstrap.servers": brokerURL[0],
"group.id": "order-service",
"auto.offset.reset": "latest",
},
}
t.Logf("Test Result success is %t", testResult.Success)

appServicesChan := make(chan app.ApplicationServices)
go server.Run(*applicationProperties, appServicesChan)
t.Cleanup(func() {
server.Close()
})
// Log TestResult raw structure.
j, err := json.Marshal(testResult)
t.Logf(string(j))

// Wait til application is ready.
_ = <-appServicesChan
require.True(t, testResult.Success)
require.Equal(t, 1, len(*testResult.TestCaseResults))
}))
}

// Prepare a Microcks Test.
testRequest := client.TestRequest{
ServiceId: "Order Service API:0.1.0",
RunnerType: client.TestRunnerTypeOPENAPISCHEMA,
TestEndpoint: fmt.Sprintf("http://host.testcontainers.internal:%d/api", server.DefaultApplicationPort),
Timeout: 2000,
func testOpenAPIContractAdvanced(test func(t *testing.T, tc *helper.TestContext)) func(*testing.T) {
return func(t *testing.T) {
tc, err := helper.SetupTestContext(t)
require.NoError(t, err)
defer helper.TeardownTestContext(tc)
test(t, tc)
}
testResult, err := microcksEnsemble.GetMicrocksContainer().TestEndpoint(ctx, &testRequest)
require.NoError(t, err)

t.Logf("Test Result success is %t", testResult.Success)

// Log TestResult raw structure.
j, err := json.Marshal(testResult)
t.Logf(string(j))

require.True(t, testResult.Success)
require.Equal(t, 1, len(*testResult.TestCaseResults))
}

func TestPostmanCollectionContract(t *testing.T) {
ctx := context.Background()

// Common network and Kafka container.
net, err := network.New(ctx, network.WithCheckDuplicate())
if err != nil {
require.NoError(t, err)
return
}

kafkaContainer, err := kafkaTC.Run(ctx,
"confluentinc/confluent-local:7.5.0",
network.WithNetwork([]string{"kafka"}, net),
)
t.Cleanup(func() {
if err := kafkaContainer.Terminate(ctx); err != nil {
t.Fatalf("failed to terminate Kafka container: %s", err)
t.Run("Test", testPostmanCollectionContract(func(t *testing.T, tc *helper.TestContext) {
// Test code goes here which can leverage the context
// Prepare a Microcks Test.
testRequest := client.TestRequest{
ServiceId: "Order Service API:0.1.0",
RunnerType: client.TestRunnerTypePOSTMAN,
TestEndpoint: fmt.Sprintf("http://host.testcontainers.internal:%d/api", server.DefaultApplicationPort),
Timeout: 2000,
}
})

microcksEnsemble := setupEnsemble(ctx, t, net)

baseApiUrl, err := microcksEnsemble.GetMicrocksContainer().RestMockEndpoint(ctx, "API Pastries", "0.0.1")
require.NoError(t, err)

brokerURL, err := kafkaContainer.Brokers(ctx)
if err != nil || len(brokerURL) == 0 {
testResult, err := tc.MicrocksEnsemble.GetMicrocksContainer().TestEndpoint(ctx, &testRequest)
require.NoError(t, err)
return
}

applicationProperties := &app.ApplicationProperties{
PastriesBaseUrl: baseApiUrl,
OrderEventsCreatedTopic: "orders-created",
OrderEventsReviewedTopic: "orders-reviewed",
KafkaConfigMap: &kafka.ConfigMap{
"bootstrap.servers": brokerURL[0],
"group.id": "order-service",
"auto.offset.reset": "latest",
},
}
t.Logf("Test Result success is %t", testResult.Success)

appServicesChan := make(chan app.ApplicationServices)
go server.Run(*applicationProperties, appServicesChan)
t.Cleanup(func() {
server.Close()
})
// Log TestResult raw structure.
j, err := json.Marshal(testResult)
t.Logf(string(j))

// Wait til application is ready.
_ = <-appServicesChan
require.True(t, testResult.Success)
require.Equal(t, 1, len(*testResult.TestCaseResults))
}))
}

// Prepare a Microcks Test.
testRequest := client.TestRequest{
ServiceId: "Order Service API:0.1.0",
RunnerType: client.TestRunnerTypePOSTMAN,
TestEndpoint: fmt.Sprintf("http://host.testcontainers.internal:%d/api", server.DefaultApplicationPort),
Timeout: 2000,
func testPostmanCollectionContract(test func(t *testing.T, tc *helper.TestContext)) func(*testing.T) {
return func(t *testing.T) {
tc, err := helper.SetupTestContext(t)
require.NoError(t, err)
defer helper.TeardownTestContext(tc)
test(t, tc)
}
testResult, err := microcksEnsemble.GetMicrocksContainer().TestEndpoint(ctx, &testRequest)
require.NoError(t, err)

t.Logf("Test Result success is %t", testResult.Success)

// Log TestResult raw structure.
j, err := json.Marshal(testResult)
t.Logf(string(j))

require.True(t, testResult.Success)
require.Equal(t, 1, len(*testResult.TestCaseResults))
}
Loading

0 comments on commit e43a4b4

Please sign in to comment.