github.com/google/fleetspeak@v0.1.15-0.20240426164851-4f31f62c1aea/fleetspeak/src/server/grpcservice/client/testing/tester.go (about)

     1  // Copyright 2017 Google Inc.
     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  //     https://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 main tests a fleetspeak server talking through a grpcserver to a python loopback process.
    16  package main
    17  
    18  import (
    19  	"context"
    20  	"flag"
    21  	"net"
    22  	"path"
    23  	"time"
    24  
    25  	log "github.com/golang/glog"
    26  	anypb "google.golang.org/protobuf/types/known/anypb"
    27  
    28  	"google.golang.org/grpc"
    29  
    30  	"github.com/google/fleetspeak/fleetspeak/src/common"
    31  	"github.com/google/fleetspeak/fleetspeak/src/comtesting"
    32  	"github.com/google/fleetspeak/fleetspeak/src/server"
    33  	"github.com/google/fleetspeak/fleetspeak/src/server/admin"
    34  	"github.com/google/fleetspeak/fleetspeak/src/server/comms"
    35  	"github.com/google/fleetspeak/fleetspeak/src/server/db"
    36  	"github.com/google/fleetspeak/fleetspeak/src/server/grpcservice"
    37  	"github.com/google/fleetspeak/fleetspeak/src/server/sertesting"
    38  	"github.com/google/fleetspeak/fleetspeak/src/server/service"
    39  	"github.com/google/fleetspeak/fleetspeak/src/server/sqlite"
    40  	"github.com/google/fleetspeak/fleetspeak/src/server/testserver"
    41  
    42  	fspb "github.com/google/fleetspeak/fleetspeak/src/common/proto/fleetspeak"
    43  	gpb "github.com/google/fleetspeak/fleetspeak/src/server/grpcservice/proto/fleetspeak_grpcservice"
    44  	sgrpc "github.com/google/fleetspeak/fleetspeak/src/server/proto/fleetspeak_server"
    45  	spb "github.com/google/fleetspeak/fleetspeak/src/server/proto/fleetspeak_server"
    46  )
    47  
    48  var (
    49  	adminAddr   = flag.String("admin_addr", "", "Bind address for the admin rpc server.")
    50  	messageAddr = flag.String("message_addr", "", "The address to send messages to over grpc.")
    51  )
    52  
    53  func main() {
    54  	flag.Parse()
    55  	tempDir, tmpDirCleanup := comtesting.GetTempDir("grpcservice")
    56  	defer tmpDirCleanup()
    57  	p := path.Join(tempDir, "client_test.sqlite")
    58  	ds, err := sqlite.MakeDatastore(p)
    59  
    60  	sertesting.SetServerRetryTime(func(_ uint32) time.Time {
    61  		return db.Now().Add(time.Second)
    62  	})
    63  
    64  	if err != nil {
    65  		log.Exitf("Unable to create datastore[%s]: %v", p, err)
    66  	}
    67  	ts := testserver.Server{
    68  		DS: ds,
    69  	}
    70  	gc, err := anypb.New(&gpb.Config{
    71  		Target:   *messageAddr,
    72  		Insecure: true,
    73  	})
    74  	if err != nil {
    75  		log.Exitf("Unable to marshal grpcservice config: %v", err)
    76  	}
    77  	s, err := server.MakeServer(
    78  		&spb.ServerConfig{
    79  			Services: []*spb.ServiceConfig{{
    80  				Name:    "TestService",
    81  				Factory: "GRPC",
    82  				Config:  gc,
    83  			}},
    84  		},
    85  		server.Components{
    86  			Datastore:        ds,
    87  			ServiceFactories: map[string]service.Factory{"GRPC": grpcservice.Factory},
    88  			Communicators:    []comms.Communicator{&testserver.FakeCommunicator{Dest: &ts}},
    89  		},
    90  	)
    91  	ts.S = s
    92  	if err != nil {
    93  		log.Exitf("Unable to create server: %v", err)
    94  	}
    95  	serveAdminInterface(s, ds)
    96  
    97  	k, err := ts.AddClient()
    98  	if err != nil {
    99  		log.Exitf("Unable to add client: %v", err)
   100  	}
   101  	id, err := common.MakeClientID(k)
   102  	if err != nil {
   103  		log.Exitf("Unable to make ClientID: %v", err)
   104  	}
   105  
   106  	m := &fspb.Message{
   107  		SourceMessageId: []byte("2"),
   108  		Source: &fspb.Address{
   109  			ClientId:    id.Bytes(),
   110  			ServiceName: "TestService",
   111  		},
   112  		Destination: &fspb.Address{
   113  			ServiceName: "TestService",
   114  		},
   115  		MessageType: "TestMessage",
   116  	}
   117  	mid := common.MakeMessageID(m.Source, m.SourceMessageId)
   118  	m.MessageId = mid.Bytes()
   119  	ctx, fin := context.WithTimeout(context.Background(), 30*time.Second)
   120  	defer fin()
   121  	// Because of grpc retry logic and the possibility of getting an error when
   122  	// the message was successfully sent, the message might pass through the
   123  	// loopback during the first SimulateContact call.
   124  	msgs, err := ts.SimulateContactFromClient(ctx, k, []*fspb.Message{m})
   125  	if err != nil {
   126  		log.Exitf("Error putting message into system: %v", err)
   127  	}
   128  	var resp *fspb.Message
   129  	for len(msgs) == 0 {
   130  		msgs, err = ts.SimulateContactFromClient(ctx, k, nil)
   131  		if err != nil {
   132  			log.Exitf("Error while waiting for loopback: %v", err)
   133  		}
   134  		if len(msgs) > 0 {
   135  			break
   136  		}
   137  		time.Sleep(100 * time.Millisecond)
   138  	}
   139  	if len(msgs) > 1 {
   140  		log.Exitf("Expected 1 message back, got %d", len(msgs))
   141  	}
   142  	resp = msgs[0]
   143  
   144  	log.Infof("Received through loopback: %+v", resp)
   145  	if resp.MessageType != "TestMessage" {
   146  		log.Exitf("Looped message had unexpected MessageType, got [%v] want [%v]", resp.MessageType, "TestMessage")
   147  	}
   148  }
   149  
   150  func serveAdminInterface(fs *server.Server, ds db.Store) *grpc.Server {
   151  	gs := grpc.NewServer()
   152  	as := admin.NewServer(ds, nil)
   153  	sgrpc.RegisterAdminServer(gs, as)
   154  	addr, err := net.ResolveTCPAddr("tcp", *adminAddr)
   155  	if err != nil {
   156  		log.Exitf("Unable to resolve admin listener address [%v]: %v", *adminAddr, err)
   157  	}
   158  	l, err := net.ListenTCP("tcp", addr)
   159  	if err != nil {
   160  		log.Exitf("Unable to listen on [%v]: %v", addr, err)
   161  	}
   162  	go func() {
   163  		err := gs.Serve(l)
   164  		log.Errorf("Admin server finished with error: %v", err)
   165  	}()
   166  	log.Infof("Admin interface started, listening for clients on: %v", l.Addr())
   167  	return gs
   168  }