github.com/badrootd/nibiru-cometbft@v0.37.5-0.20240307173500-2a75559eee9b/abci/example/example_test.go (about)

     1  package example
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"net"
     7  	"os"
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"google.golang.org/grpc"
    15  
    16  	"golang.org/x/net/context"
    17  
    18  	"github.com/badrootd/nibiru-cometbft/libs/log"
    19  	cmtnet "github.com/badrootd/nibiru-cometbft/libs/net"
    20  
    21  	abcicli "github.com/badrootd/nibiru-cometbft/abci/client"
    22  	"github.com/badrootd/nibiru-cometbft/abci/example/code"
    23  	"github.com/badrootd/nibiru-cometbft/abci/example/kvstore"
    24  	abciserver "github.com/badrootd/nibiru-cometbft/abci/server"
    25  	"github.com/badrootd/nibiru-cometbft/abci/types"
    26  )
    27  
    28  var grand *rand.Rand
    29  
    30  func init() {
    31  	grand = rand.New(rand.NewSource(time.Now().UnixNano()))
    32  }
    33  
    34  func TestKVStore(t *testing.T) {
    35  	fmt.Println("### Testing KVStore")
    36  	testStream(t, kvstore.NewApplication())
    37  }
    38  
    39  func TestBaseApp(t *testing.T) {
    40  	fmt.Println("### Testing BaseApp")
    41  	testStream(t, types.NewBaseApplication())
    42  }
    43  
    44  func TestGRPC(t *testing.T) {
    45  	fmt.Println("### Testing GRPC")
    46  	testGRPCSync(t, types.NewGRPCApplication(types.NewBaseApplication()))
    47  }
    48  
    49  func testStream(t *testing.T, app types.Application) {
    50  	numDeliverTxs := 20000
    51  	socketFile := fmt.Sprintf("test-%08x.sock", grand.Int31n(1<<30))
    52  	defer os.Remove(socketFile)
    53  	socket := fmt.Sprintf("unix://%v", socketFile)
    54  
    55  	// Start the listener
    56  	server := abciserver.NewSocketServer(socket, app)
    57  	server.SetLogger(log.TestingLogger().With("module", "abci-server"))
    58  	if err := server.Start(); err != nil {
    59  		require.NoError(t, err, "Error starting socket server")
    60  	}
    61  	t.Cleanup(func() {
    62  		if err := server.Stop(); err != nil {
    63  			t.Error(err)
    64  		}
    65  	})
    66  
    67  	// Connect to the socket
    68  	client := abcicli.NewSocketClient(socket, false)
    69  	client.SetLogger(log.TestingLogger().With("module", "abci-client"))
    70  	if err := client.Start(); err != nil {
    71  		t.Fatalf("Error starting socket client: %v", err.Error())
    72  	}
    73  	t.Cleanup(func() {
    74  		if err := client.Stop(); err != nil {
    75  			t.Error(err)
    76  		}
    77  	})
    78  
    79  	done := make(chan struct{})
    80  	counter := 0
    81  	client.SetResponseCallback(func(req *types.Request, res *types.Response) {
    82  		// Process response
    83  		switch r := res.Value.(type) {
    84  		case *types.Response_DeliverTx:
    85  			counter++
    86  			if r.DeliverTx.Code != code.CodeTypeOK {
    87  				t.Error("DeliverTx failed with ret_code", r.DeliverTx.Code)
    88  			}
    89  			if counter > numDeliverTxs {
    90  				t.Fatalf("Too many DeliverTx responses. Got %d, expected %d", counter, numDeliverTxs)
    91  			}
    92  			if counter == numDeliverTxs {
    93  				go func() {
    94  					time.Sleep(time.Second * 1) // Wait for a bit to allow counter overflow
    95  					close(done)
    96  				}()
    97  				return
    98  			}
    99  		case *types.Response_Flush:
   100  			// ignore
   101  		default:
   102  			t.Error("Unexpected response type", reflect.TypeOf(res.Value))
   103  		}
   104  	})
   105  
   106  	// Write requests
   107  	for counter := 0; counter < numDeliverTxs; counter++ {
   108  		// Send request
   109  		reqRes := client.DeliverTxAsync(types.RequestDeliverTx{Tx: []byte("test")})
   110  		_ = reqRes
   111  		// check err ?
   112  
   113  		// Sometimes send flush messages
   114  		if counter%123 == 0 {
   115  			client.FlushAsync()
   116  			// check err ?
   117  		}
   118  	}
   119  
   120  	// Send final flush message
   121  	client.FlushAsync()
   122  
   123  	<-done
   124  }
   125  
   126  //-------------------------
   127  // test grpc
   128  
   129  func dialerFunc(ctx context.Context, addr string) (net.Conn, error) {
   130  	return cmtnet.Connect(addr)
   131  }
   132  
   133  func testGRPCSync(t *testing.T, app types.ABCIApplicationServer) {
   134  	numDeliverTxs := 2000
   135  	socketFile := fmt.Sprintf("/tmp/test-%08x.sock", grand.Int31n(1<<30))
   136  	defer os.Remove(socketFile)
   137  	socket := fmt.Sprintf("unix://%v", socketFile)
   138  
   139  	// Start the listener
   140  	server := abciserver.NewGRPCServer(socket, app)
   141  	server.SetLogger(log.TestingLogger().With("module", "abci-server"))
   142  	if err := server.Start(); err != nil {
   143  		t.Fatalf("Error starting GRPC server: %v", err.Error())
   144  	}
   145  
   146  	t.Cleanup(func() {
   147  		if err := server.Stop(); err != nil {
   148  			t.Error(err)
   149  		}
   150  	})
   151  
   152  	// Connect to the socket
   153  	//nolint:staticcheck,nolintlint // SA1019 Existing use of deprecated but supported dial option.
   154  	conn, err := grpc.Dial(socket, grpc.WithInsecure(), grpc.WithContextDialer(dialerFunc))
   155  	if err != nil {
   156  		t.Fatalf("Error dialing GRPC server: %v", err.Error())
   157  	}
   158  
   159  	t.Cleanup(func() {
   160  		if err := conn.Close(); err != nil {
   161  			t.Error(err)
   162  		}
   163  	})
   164  
   165  	client := types.NewABCIApplicationClient(conn)
   166  
   167  	// Write requests
   168  	for counter := 0; counter < numDeliverTxs; counter++ {
   169  		// Send request
   170  		response, err := client.DeliverTx(context.Background(), &types.RequestDeliverTx{Tx: []byte("test")})
   171  		if err != nil {
   172  			t.Fatalf("Error in GRPC DeliverTx: %v", err.Error())
   173  		}
   174  		counter++
   175  		if response.Code != code.CodeTypeOK {
   176  			t.Error("DeliverTx failed with ret_code", response.Code)
   177  		}
   178  		if counter > numDeliverTxs {
   179  			t.Fatal("Too many DeliverTx responses")
   180  		}
   181  		t.Log("response", counter)
   182  		if counter == numDeliverTxs {
   183  			go func() {
   184  				time.Sleep(time.Second * 1) // Wait for a bit to allow counter overflow
   185  			}()
   186  		}
   187  
   188  	}
   189  }