github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/xtest/ydb_grpc_mocks.go (about) 1 package xtest 2 3 import ( 4 "context" 5 "fmt" 6 "net" 7 "reflect" 8 "strconv" 9 "time" 10 11 "github.com/rekby/fixenv" 12 "github.com/rekby/fixenv/sf" 13 "github.com/ydb-platform/ydb-go-genproto/Ydb_Discovery_V1" 14 "github.com/ydb-platform/ydb-go-genproto/Ydb_Topic_V1" 15 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" 16 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Discovery" 17 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Operations" 18 "google.golang.org/grpc" 19 "google.golang.org/protobuf/types/known/anypb" 20 ) 21 22 func GrpcMockTopicConnString(e fixenv.Env, topicServiceImpl Ydb_Topic_V1.TopicServiceServer) string { 23 v := reflect.ValueOf(topicServiceImpl) 24 addr := v.Pointer() 25 26 var f fixenv.GenericFixtureFunction[string] = func() (*fixenv.GenericResult[string], error) { 27 listener := sf.LocalTCPListenerNamed(e, fmt.Sprintf("ydb-grpc-mock-topic-%v", addr)) 28 connString := fmt.Sprintf("grpc://%s/local", listener.Addr()) 29 30 mock, err := newGrpcMock(listener, topicServiceImpl) 31 if err != nil { 32 return nil, fmt.Errorf("failed to create grpc mock: %w", err) 33 } 34 35 clean := func() { 36 _ = mock.Close() 37 } 38 39 return fixenv.NewGenericResultWithCleanup(connString, clean), nil 40 } 41 42 return fixenv.CacheResult(e, f, fixenv.CacheOptions{CacheKey: addr}) 43 } 44 45 type grpcMock struct { 46 listener net.Listener 47 grpcServer *grpc.Server 48 stopChan chan error 49 } 50 51 func (m *grpcMock) Close() error { 52 m.grpcServer.Stop() 53 54 return m.listener.Close() 55 } 56 57 func newGrpcMock(listener net.Listener, topicServiceImpl Ydb_Topic_V1.TopicServiceServer) (*grpcMock, error) { 58 res := &grpcMock{ 59 listener: listener, 60 grpcServer: grpc.NewServer(), 61 stopChan: make(chan error, 1), 62 } 63 64 host, portS, err := net.SplitHostPort(listener.Addr().String()) 65 if err != nil { 66 return nil, fmt.Errorf("failed to split host port addresses: %w", err) 67 } 68 69 port, err := strconv.ParseUint(portS, 10, 32) 70 if err != nil { 71 return nil, fmt.Errorf("failed convert port to int: %w", err) 72 } 73 discoveryService := newMockDiscoveryService(host, uint32(port)) 74 75 Ydb_Discovery_V1.RegisterDiscoveryServiceServer(res.grpcServer, discoveryService) 76 Ydb_Topic_V1.RegisterTopicServiceServer(res.grpcServer, topicServiceImpl) 77 78 go func() { 79 res.stopChan <- res.grpcServer.Serve(res.listener) 80 }() 81 82 select { 83 case <-res.stopChan: 84 return nil, err 85 case <-time.After(time.Millisecond): 86 return res, nil 87 } 88 } 89 90 type mockDiscoveryService struct { 91 Ydb_Discovery_V1.UnimplementedDiscoveryServiceServer 92 host string 93 port uint32 94 } 95 96 func newMockDiscoveryService(host string, port uint32) *mockDiscoveryService { 97 return &mockDiscoveryService{ 98 host: host, 99 port: port, 100 } 101 } 102 103 func (m mockDiscoveryService) ListEndpoints( 104 ctx context.Context, 105 request *Ydb_Discovery.ListEndpointsRequest, 106 ) (*Ydb_Discovery.ListEndpointsResponse, error) { 107 res := &Ydb_Discovery.ListEndpointsResult{ 108 Endpoints: []*Ydb_Discovery.EndpointInfo{ 109 { 110 Address: m.host, 111 Port: m.port, 112 LoadFactor: 0, 113 Ssl: false, 114 Service: nil, 115 Location: "", 116 NodeId: 1, 117 IpV4: []string{"127.0.0.1"}, 118 }, 119 }, 120 SelfLocation: "", 121 } 122 resp := &Ydb_Discovery.ListEndpointsResponse{ 123 Operation: &Ydb_Operations.Operation{ 124 Id: "test-list-operation", 125 Ready: true, 126 Status: Ydb.StatusIds_SUCCESS, 127 Result: &anypb.Any{}, 128 }, 129 } 130 err := resp.GetOperation().GetResult().MarshalFrom(res) 131 132 return resp, err 133 } 134 135 func (m mockDiscoveryService) WhoAmI( 136 ctx context.Context, 137 request *Ydb_Discovery.WhoAmIRequest, 138 ) (*Ydb_Discovery.WhoAmIResponse, error) { 139 panic("unimplemented") 140 }