github.com/google/cloudprober@v0.11.3/surfacers/pubsub/pubsub_test.go (about)

     1  // Copyright 2020 The Cloudprober Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package pubsub
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"net"
    21  	"reflect"
    22  	"strings"
    23  	"sync"
    24  	"testing"
    25  	"time"
    26  
    27  	"cloud.google.com/go/pubsub"
    28  	"github.com/google/cloudprober/logger"
    29  	"github.com/google/cloudprober/metrics"
    30  	"github.com/google/cloudprober/surfacers/common/compress"
    31  	"github.com/google/cloudprober/surfacers/common/options"
    32  	configpb "github.com/google/cloudprober/surfacers/pubsub/proto"
    33  	"google.golang.org/api/option"
    34  	pb "google.golang.org/genproto/googleapis/pubsub/v1"
    35  	pb_grpc "google.golang.org/genproto/googleapis/pubsub/v1"
    36  	"google.golang.org/grpc"
    37  	"google.golang.org/grpc/codes"
    38  	"google.golang.org/grpc/status"
    39  	"google.golang.org/protobuf/proto"
    40  )
    41  
    42  // testServer is the underlying service implementor. It is not intended to be used
    43  // directly.
    44  type testServer struct {
    45  	pb_grpc.PublisherServer
    46  	pb_grpc.SubscriberServer
    47  
    48  	topics map[string]*pb.Topic
    49  	msgs   []*Message // all messages ever published
    50  	wg     sync.WaitGroup
    51  	nextID int
    52  }
    53  
    54  // A Message is a message that was published to the server.
    55  type Message struct {
    56  	Data       []byte
    57  	Attributes map[string]string
    58  }
    59  
    60  func (s *testServer) CreateTopic(_ context.Context, t *pb.Topic) (*pb.Topic, error) {
    61  	if s.topics[t.Name] != nil {
    62  		return nil, status.Errorf(codes.AlreadyExists, "topic %q", t.Name)
    63  	}
    64  	s.topics[t.Name] = t
    65  	return t, nil
    66  }
    67  
    68  func (s *testServer) GetTopic(_ context.Context, req *pb.GetTopicRequest) (*pb.Topic, error) {
    69  	if t := s.topics[req.Topic]; t != nil {
    70  		return t, nil
    71  	}
    72  	return nil, status.Errorf(codes.NotFound, "topic %q", req.Topic)
    73  }
    74  
    75  func (s *testServer) Publish(_ context.Context, req *pb.PublishRequest) (*pb.PublishResponse, error) {
    76  	var ids []string
    77  	for _, pm := range req.Messages {
    78  		m := &Message{
    79  			Data:       pm.Data,
    80  			Attributes: pm.Attributes,
    81  		}
    82  		ids = append(ids, fmt.Sprintf("m%d", s.nextID))
    83  		s.nextID++
    84  		s.msgs = append(s.msgs, m)
    85  	}
    86  	return &pb.PublishResponse{MessageIds: ids}, nil
    87  }
    88  
    89  func TestSurfacer(t *testing.T) {
    90  	for _, compression := range []bool{false, true} {
    91  		t.Run(fmt.Sprintf("with_compression=%v", compression), func(t *testing.T) {
    92  			l, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", 0))
    93  			if err != nil {
    94  				t.Fatalf("Error creating listener: %v", err)
    95  			}
    96  			defer l.Close()
    97  
    98  			gSrv := grpc.NewServer()
    99  			srv := &testServer{
   100  				topics: map[string]*pb.Topic{},
   101  			}
   102  
   103  			pb_grpc.RegisterPublisherServer(gSrv, srv)
   104  			pb_grpc.RegisterSubscriberServer(gSrv, srv)
   105  
   106  			go func() {
   107  				if err := gSrv.Serve(l); err != nil {
   108  					t.Errorf("gRPC server start: %v", err)
   109  				}
   110  			}()
   111  			defer gSrv.Stop()
   112  
   113  			// Connect to the server without using TLS.
   114  			conn, err := grpc.Dial(l.Addr().String(), grpc.WithInsecure())
   115  			if err != nil {
   116  				t.Fatalf("Error establishing connection to the test pubsub server (%s): %v", l.Addr().String(), err)
   117  			}
   118  			defer conn.Close()
   119  
   120  			newPubsubClient = func(ctx context.Context, project string) (*pubsub.Client, error) {
   121  				return pubsub.NewClient(ctx, project, option.WithGRPCConn(conn))
   122  			}
   123  
   124  			createSurfacerAndVerify(t, srv, compression)
   125  		})
   126  	}
   127  }
   128  
   129  func createSurfacerAndVerify(t *testing.T, srv *testServer, compression bool) {
   130  	t.Helper()
   131  
   132  	//ctx, cancel := context.WithCancel(context.Background())
   133  	//defer cancel()
   134  
   135  	s, err := New(context.Background(), &configpb.SurfacerConf{
   136  		TopicName:          proto.String("test-topic"),
   137  		CompressionEnabled: proto.Bool(compression),
   138  	}, &options.Options{MetricsBufferSize: 1000}, &logger.Logger{})
   139  	if err != nil {
   140  		t.Fatalf("Error while creating new surfacer: %v", err)
   141  	}
   142  
   143  	testEM := []*metrics.EventMetrics{
   144  		metrics.NewEventMetrics(time.Now()).AddMetric("float-test", metrics.NewInt(123456)),
   145  		metrics.NewEventMetrics(time.Now()).AddMetric("float-test", metrics.NewInt(123457)),
   146  	}
   147  
   148  	var expectedMsgs []string
   149  	for _, em := range testEM {
   150  		s.Write(context.Background(), em)
   151  		expectedMsgs = append(expectedMsgs, em.String())
   152  	}
   153  
   154  	// Closing the surfacer waits for inputs to be processed.
   155  	s.close()
   156  
   157  	srv.wg.Wait()
   158  
   159  	if compression {
   160  		b, err := compress.Compress([]byte(strings.Join(expectedMsgs, "\n") + "\n"))
   161  		if err != nil {
   162  			t.Fatalf("Error while compressing data (%s): %v", string(b), err)
   163  		}
   164  		expectedMsgs = []string{string(b)}
   165  	}
   166  
   167  	if len(srv.msgs) != len(expectedMsgs) {
   168  		t.Fatalf("Got %d message, expected: %d", len(srv.msgs), len(expectedMsgs))
   169  	}
   170  
   171  	expectedAttributes := map[string]string{
   172  		"starttime":  s.starttime,
   173  		"compressed": map[bool]string{false: "false", true: "true"}[compression],
   174  	}
   175  
   176  	for i, msg := range srv.msgs {
   177  		if !reflect.DeepEqual(msg.Attributes, expectedAttributes) {
   178  			t.Errorf("Message attributes: %v, expected: %v", msg.Attributes, expectedAttributes)
   179  		}
   180  		if string(msg.Data) != expectedMsgs[i] {
   181  			t.Errorf("Message data=%s, expected=%s", string(msg.Data), expectedMsgs[i])
   182  		}
   183  	}
   184  }