Skip to content

Commit

Permalink
Adds e2e test for gRPC application
Browse files Browse the repository at this point in the history
  • Loading branch information
bsnchan committed Jun 4, 2018
1 parent 69f74e5 commit c08f3d1
Show file tree
Hide file tree
Showing 9 changed files with 330 additions and 8 deletions.
3 changes: 2 additions & 1 deletion test/crd.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func Route(namespace string, route string, config string) *v1alpha1.Route {

// Configuration returns a Configuration object in namespace with the name config
// that uses the image specifed by imagePath.
func Configuration(namespace string, config string, imagePath string) *v1alpha1.Configuration {
func Configuration(namespace string, config string, imagePath string, protocol v1alpha1.RevisionProtocolType) *v1alpha1.Configuration {
return &v1alpha1.Configuration{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Expand All @@ -54,6 +54,7 @@ func Configuration(namespace string, config string, imagePath string) *v1alpha1.
Spec: v1alpha1.ConfigurationSpec{
RevisionTemplate: v1alpha1.RevisionTemplateSpec{
Spec: v1alpha1.RevisionSpec{
Protocol: protocol,
Container: corev1.Container{
Image: imagePath,
},
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/autoscale_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func TestAutoscaleUpDownUp(t *testing.T) {
"/")

log.Println("Creating a new Route and Configuration")
err := CreateRouteAndConfig(clients, imagePath)
err := CreateRouteAndConfig(clients, imagePath, v1alpha1.RevisionProtocolHTTP)
if err != nil {
t.Fatalf("Failed to create Route and Configuration: %v", err)
}
Expand Down
5 changes: 3 additions & 2 deletions test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package e2e
import (
"testing"

"github.com/elafros/elafros/pkg/apis/ela/v1alpha1"
"github.com/elafros/elafros/test"
// Mysteriously required to support GCP auth (required by k8s libs).
// Apparently just importing it is enough. @_@ side effects @_@.
Expand Down Expand Up @@ -34,9 +35,9 @@ func TearDown(clients *test.Clients) {
}
}

func CreateRouteAndConfig(clients *test.Clients, imagePath string) error {
func CreateRouteAndConfig(clients *test.Clients, imagePath string, protocol v1alpha1.RevisionProtocolType) error {
_, err := clients.Configs.Create(
test.Configuration(NamespaceName, ConfigName, imagePath))
test.Configuration(NamespaceName, ConfigName, imagePath, protocol))
if err != nil {
return err
}
Expand Down
80 changes: 79 additions & 1 deletion test/e2e/helloworld_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ limitations under the License.
package e2e

import (
"context"
"fmt"
"log"
"strings"
"testing"
"time"

"github.com/elafros/elafros/pkg/apis/ela/v1alpha1"
"github.com/elafros/elafros/test"
hello "github.com/elafros/elafros/test/e2e/test_images/helloworld-grpc/proto"
"google.golang.org/grpc"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
)

const (
Expand All @@ -44,7 +50,7 @@ func TestHelloWorld(t *testing.T) {
imagePath = strings.Join([]string{test.Flags.DockerRepo, "helloworld"}, "/")

log.Println("Creating a new Route and Configuration")
err := CreateRouteAndConfig(clients, imagePath)
err := CreateRouteAndConfig(clients, imagePath, v1alpha1.RevisionProtocolHTTP)
if err != nil {
t.Fatalf("Failed to create Route and Configuration: %v", err)
}
Expand All @@ -67,3 +73,75 @@ func TestHelloWorld(t *testing.T) {
t.Fatalf("The endpoint for Route %s at domain %s didn't serve the expected text \"%s\": %v", RouteName, domain, helloWorldExpectedOutput, err)
}
}

func TestHelloWorldGRPC(t *testing.T) {
clients := Setup(t)
defer TearDown(clients)
test.CleanupOnInterrupt(func() { TearDown(clients) })

var imagePath string
imagePath = strings.Join([]string{test.Flags.DockerRepo, "helloworld-grpc"}, "/")

log.Println("Creating a new Route and Configuration")
err := CreateRouteAndConfig(clients, imagePath, v1alpha1.RevisionProtocolGRPC)
if err != nil {
t.Fatalf("Failed to create Route and Configuration: %v", err)
}

log.Println("When the Revision can have traffic routed to it, the Route is marked as Ready.")
err = test.WaitForRouteState(clients.Routes, RouteName, func(r *v1alpha1.Route) (bool, error) {
return r.Status.IsReady(), nil
})
if err != nil {
t.Fatalf("The Route %s was not marked as Ready to serve traffic: %v", RouteName, err)
}

route, err := clients.Routes.Get(RouteName, metav1.GetOptions{})
if err != nil {
t.Fatalf("Error fetching Route %s: %v", RouteName, err)
}
domain := route.Status.Domain

endpoint, spoofDomain, err := test.FetchEndpointDomain(clients.Kube, test.Flags.ResolvableDomain, domain, NamespaceName, RouteName)
if err != nil {
t.Fatalf("Error fetching endpoint domains: %v", err)
}

ingressAddress := fmt.Sprintf("%s:%d", strings.TrimPrefix(endpoint, "http://"), 80)
err = waitForHelloWorldGRPCEndpoint(ingressAddress, spoofDomain)
if err != nil {
t.Fatal(err)
}
}

func waitForHelloWorldGRPCEndpoint(address string, spoofDomain string) error {
opts := []grpc.DialOption{
grpc.WithInsecure(),
}
if spoofDomain != "" {
opts = append(opts, grpc.WithAuthority(spoofDomain))
}

err := wait.PollImmediate(test.RequestInterval, test.RequestTimeout, func() (bool, error) {
conn, _ := grpc.Dial(address, opts...)
defer conn.Close()

client := hello.NewHelloServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel()

resp, err := client.Hello(ctx, &hello.Request{Msg: "world"})
if err != nil {
return true, err
}

expectedResponse := "Hello world"
receivedResponse := resp.GetMsg()

if receivedResponse == expectedResponse {
return true, nil
}
return false, fmt.Errorf("Did not get expected response message %s, got %s", expectedResponse, receivedResponse)
})
return err
}
12 changes: 12 additions & 0 deletions test/e2e/test_images/helloworld-grpc/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM golang:latest

ENV APP ${GOPATH}/src/github.com/elafros/elafros/test/e2e/test_images/helloworld-grpc

RUN mkdir -p "$APP"
ADD . "$APP"
RUN go get google.golang.org/grpc && \
go get golang.org/x/net/context

WORKDIR "$APP"
RUN go build -o /app/helloworld-grpc .
CMD ["/app/helloworld-grpc"]
31 changes: 31 additions & 0 deletions test/e2e/test_images/helloworld-grpc/helloworld.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"fmt"
"log"
"net"

hello "github.com/elafros/elafros/test/e2e/test_images/helloworld-grpc/proto"
"golang.org/x/net/context"
"google.golang.org/grpc"
)

type helloServer struct {
}

func (s *helloServer) Hello(ctx context.Context, req *hello.Request) (*hello.Response, error) {
return &hello.Response{Msg: fmt.Sprintf("Hello %s", req.Msg)}, nil
}

func main() {
lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", 8080))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}

helloServer := &helloServer{}

grpcServer := grpc.NewServer()
hello.RegisterHelloServiceServer(grpcServer, helloServer)
grpcServer.Serve(lis)
}
157 changes: 157 additions & 0 deletions test/e2e/test_images/helloworld-grpc/proto/helloworld.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions test/e2e/test_images/helloworld-grpc/proto/helloworld.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
syntax = "proto3";

package hello;


service HelloService {
rpc Hello(Request) returns (Response) {}
}

message Request {
string msg = 1;
}

message Response {
string msg = 1;
}

Loading

0 comments on commit c08f3d1

Please sign in to comment.