grpcdump

package module
v0.0.0-...-af16749 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2025 License: BSD-3-Clause Imports: 28 Imported by: 0

README

grpcdump

Go Reference

Purpose

grpcdump is a specialized testing utility for Go that simplifies gRPC service testing by providing tools to capture, serialize, and verify Protocol Buffer messages. It enables snapshot testing for gRPC communications, making it easier to detect regressions and validate message structures in your microservices architecture.

Example Usage

package main

import (
    "testing"
    "context"
    
    "github.com/alextanhongpin/testdump/grpcdump"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    pb "your/protobuf/package"
)

func TestUserService(t *testing.T) {
    // Setup a test gRPC server with grpcdump interceptors
    server := grpcdump.NewServer(
        grpcdump.StreamInterceptor(),
        grpcdump.UnaryInterceptor(),
    )
    
    // Register your service
    pb.RegisterUserServiceServer(server.Server, &yourServiceImplementation{})
    stop := server.ListenAndServe()
    defer stop()
    
    // Setup a test gRPC client with grpcdump
    ctx := context.Background()
    conn, err := server.DialContext(ctx,
        grpcdump.WithUnaryInterceptor(),
        grpc.WithTransportCredentials(insecure.NewCredentials()),
    )
    if err != nil {
        t.Fatal(err)
    }
    defer conn.Close()
    
    client := pb.NewUserServiceClient(conn)
    
    // Create a recorder with options
    ctx = grpcdump.NewRecorder(t, ctx, 
        grpcdump.IgnoreMetadata("user-agent"),
        grpcdump.MaskMessageFields("[MASKED]", []string{"password"}),
    )
    
    // Create a request
    req := &pb.GetUserRequest{
        UserId: "123",
    }
    
    // Make the gRPC call - everything is recorded automatically
    resp, err := client.GetUser(ctx, req)
    if err != nil {
        t.Fatalf("GetUser failed: %v", err)
    }
    
    // No need to explicitly call Dump() - the recorder captures everything
    // Assertions can be made as normal
    if resp.GetUsername() != "expected_username" {
        t.Errorf("Expected username %q, got %q", "expected_username", resp.GetUsername())
    }
}

Benefits

  • Simplified gRPC Testing: Makes it easy to verify that your gRPC services are sending and receiving the correct Protocol Buffer messages.
  • Integration with Snapshot Testing: Create and compare snapshots of your gRPC messages to catch unintended changes.
  • Compatible with protobuf: Works seamlessly with Protocol Buffer messages, including complex nested structures.
  • Flexible Options:
    • Ignore dynamic fields like timestamps and IDs
    • Mask sensitive information in the snapshots
    • Customize output with transformers
    • Target specific paths within complex protobuf messages
  • Developer-Friendly: Minimal setup required to start testing gRPC services effectively.
  • Works with Existing Tests: Easily integrate into your existing test suites without changing your testing approach.

Advanced Features

  • Apply transformations to Protocol Buffer messages before dumping
  • Register type-specific options for consistent handling across tests
  • Compare different versions of the same message type
  • Use with mock gRPC servers for complete service testing
  • Validate message structure against expected schemas

Documentation

Index

Constants

View Source
const OriginClient = "client"
View Source
const OriginServer = "server"

Variables

View Source
var (
	ErrInvalidMetadata = fmt.Errorf("grpcdump: invalid metadata")
)
View Source
var ErrMetadataNotFound = errors.New("grpcdump: metadata not found")

Functions

func NewRecorder

func NewRecorder(t *testing.T, ctx context.Context, opts ...Option) context.Context

NewRecorder is a function that creates a new recorder for gRPC calls. It takes a testing.T object, a context, and a slice of Option objects, and returns a new context. The function delegates the recording task to the Record method of the Dumper object. The returned context should be used in subsequent gRPC calls that should be recorded.

func StreamInterceptor

func StreamInterceptor() grpc.ServerOption

StreamInterceptor is a function that returns a grpc.ServerOption. This ServerOption, when applied, configures the server to use the StreamServerInterceptor function as the stream interceptor. The stream interceptor is a function that intercepts incoming streaming RPCs on the server.

func StreamServerInterceptor

func StreamServerInterceptor(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error

StreamServerInterceptor is a function that intercepts incoming streaming RPCs on the server. It takes a server, a grpc.ServerStream, a grpc.StreamServerInfo, and a grpc.StreamHandler, and returns an error. If the interception is successful, it should return nil. If the interception fails, it should return an error.

func UnaryClientInterceptor

func UnaryClientInterceptor(ctx context.Context, method string, req, res any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error

UnaryClientInterceptor is a function that intercepts outgoing unary RPCs on the client. It takes a context, a method string, a request, a response, a grpc.ClientConn, a grpc.UnaryInvoker, and a slice of grpc.CallOption, and returns an error. If the interception is successful, it should return nil. If the interception fails, it should return the error.

func UnaryInterceptor

func UnaryInterceptor() grpc.ServerOption

UnaryInterceptor is a function that returns a grpc.ServerOption. This ServerOption, when applied, configures the server to use the UnaryServerInterceptor function as the unary interceptor. The unary interceptor is a function that intercepts incoming unary RPCs on the server.

func UnaryServerInterceptor

func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error)

UnaryServerInterceptor is a function that intercepts incoming unary RPCs on the server. It takes a context, a request, a grpc.UnaryServerInfo, and a grpc.UnaryHandler, and returns a response and an error. If the interception is successful, it should return the response and nil. If the interception fails, it should return nil and the error.

func WithUnaryInterceptor

func WithUnaryInterceptor() grpc.DialOption

WithUnaryInterceptor is a function that returns a grpc.DialOption. This DialOption, when applied, configures the client to use the UnaryClientInterceptor function as the unary interceptor. The unary interceptor is a function that intercepts outgoing unary RPCs on the client.

func Write

func Write(g *GRPC) ([]byte, error)

Write is a function that takes a pointer to a GRPC object and returns a byte slice and an error.

Types

type CompareOption

type CompareOption struct {
	Message  []cmp.Option // Options for comparing the message part of a gRPC message.
	Metadata []cmp.Option // Options for comparing the metadata part of a gRPC message.
	Trailer  []cmp.Option // Options for comparing the trailer part of a gRPC message.
	Header   []cmp.Option // Options for comparing the header part of a gRPC message.
}

CompareOption is a struct that holds comparison options for different parts of a gRPC message. It includes options for comparing the Message, Metadata, Trailer, and Header.

type Dumper

type Dumper struct {
	// contains filtered or unexported fields
}

func New

func New(opts ...Option) *Dumper

func (*Dumper) Record

func (d *Dumper) Record(t *testing.T, ctx context.Context, opts ...Option) context.Context

Record is a method on the Dumper struct. It takes a testing.T object, a context, and a slice of Option objects, and returns a new context. The method configures the Dumper according to the provided options, then starts recording gRPC calls in the provided context. The returned context should be used in subsequent gRPC calls that should be recorded.

type GRPC

type GRPC struct {
	Addr           string      `json:"addr"`
	FullMethod     string      `json:"full_method"`
	Messages       []Message   `json:"messages"`
	Status         *Status     `json:"status"`
	Metadata       metadata.MD `json:"metadata"` // The server receives metadata.
	Header         metadata.MD `json:"header"`   // The client receives header and trailer.
	Trailer        metadata.MD `json:"trailer"`
	IsServerStream bool        `json:"isServerStream"`
	IsClientStream bool        `json:"isClientStream"`
}

GRPC is a struct that represents a gRPC message. It contains all the necessary fields for a complete gRPC message.

func Read

func Read(b []byte) (*GRPC, error)

Read is a function that takes a byte slice and returns a GRPC object and an error. It attempts to unmarshal the byte slice into a GRPC object. If the unmarshalling is successful, it returns the GRPC object and nil. If the unmarshalling fails, it returns nil and the error.

func (*GRPC) Method

func (g *GRPC) Method() string

Method is a method on the GRPC struct. It extracts and returns the method name from the FullMethod field.

func (*GRPC) Service

func (g *GRPC) Service() string

Service is a method on the GRPC struct. It extracts and returns the service name from the FullMethod field.

type Message

type Message struct {
	Origin  string `json:"origin"` // server or client
	Name    string `json:"name"`   // message type (protobuf name)
	Message any    `json:"message"`
}

Message is a struct that represents a gRPC message. It contains all the necessary fields for a complete gRPC message.

type Option

type Option func(o *options)

Option is a type that defines a function that modifies an options object. The function takes a pointer to an options object and does not return any value.

func IgnoreHeader

func IgnoreHeader(keys ...string) Option

IgnoreHeader is a function that returns an Option. This Option, when applied, configures the options object to ignore certain header keys. The keys to ignore are provided as arguments to the function.

func IgnoreMessageFields

func IgnoreMessageFields(keys ...string) Option

IgnoreMessageFields is a function that returns an Option. This Option, when applied, configures the options object to ignore certain message fields. The fields to ignore are provided as arguments to the function.

func IgnoreMetadata

func IgnoreMetadata(keys ...string) Option

IgnoreMetadata is a function that returns an Option. This Option, when applied, configures the options object to ignore certain metadata keys. The keys to ignore are provided as arguments to the function.

func IgnoreTrailer

func IgnoreTrailer(keys ...string) Option

IgnoreTrailer is a function that returns an Option. This Option, when applied, configures the options object to ignore certain trailer keys. The keys to ignore are provided as arguments to the function.

func MaskHeader

func MaskHeader(mask string, keys []string) Option

MaskHeader is a function that returns an Option. This Option, when applied, configures the options object to mask certain header keys. The mask and the keys to mask are provided as arguments to the function.

func MaskMessageFields

func MaskMessageFields(mask string, fields []string) Option

MaskMessageFields is a function that returns an Option. This Option, when applied, configures the options object to mask certain message fields. The mask and the fields to mask are provided as arguments to the function.

func MaskMetadata

func MaskMetadata(mask string, keys []string) Option

MaskMetadata is a function that returns an Option. This Option, when applied, configures the options object to mask certain metadata keys. The mask and the keys to mask are provided as arguments to the function.

func MaskTrailer

func MaskTrailer(mask string, keys []string) Option

MaskTrailer is a function that returns an Option. This Option, when applied, configures the options object to mask certain trailer keys. The mask and the keys to mask are provided as arguments to the function.

type Server

type Server struct {
	BufSize int
	Server  *grpc.Server
	// contains filtered or unexported fields
}

Server is a struct that represents a gRPC server. It contains all the necessary fields and methods for managing a gRPC server.

func NewServer

func NewServer(opts ...grpc.ServerOption) *Server

NewServer is a function that creates a new Server instance. It takes a variadic parameter of type grpc.ServerOption, which are options to configure the Server. It returns a pointer to the newly created Server.

func (*Server) DialContext

func (s *Server) DialContext(ctx context.Context, opts ...grpc.DialOption) (*grpc.ClientConn, error)

DialContext is a method on the Server struct that creates a new gRPC client connection. It takes a context and a variadic parameter of type grpc.DialOption, which are options to configure the connection. It returns a pointer to the newly created grpc.ClientConn and an error. If the connection is successful, the error is nil. Otherwise, the error contains the details of the failure.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() func()

ListenAndServe is a method on the Server struct. It starts the server and listens for incoming connections. It returns a function that, when called, stops the server.

type Status

type Status struct {
	Code    string     `json:"code"`    // Code is the string representation of the status code.
	Number  codes.Code `json:"number"`  // Number is the numerical representation of the status code.
	Message string     `json:"message"` // Message is the error message associated with the status code.
}

Status is a struct that represents the status of a gRPC call.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
JackTT - Gopher 🇻🇳