test(utils): 添加事件驱动模型测试
- 在 sqrt_test.go 中添加了 fastSqr1 测试函数,用于测试事件驱动模型 - 新增了 Event 和 Uint32AsyncEvent 类型用于测试 - 更新了 go.work、go.mod 和
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package cart
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/badu/bus"
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/events"
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/inventory"
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/prices"
|
||||
)
|
||||
|
||||
type ServiceImpl struct {
|
||||
sb *strings.Builder
|
||||
}
|
||||
|
||||
func NewService(sb *strings.Builder) ServiceImpl {
|
||||
result := ServiceImpl{sb: sb}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) AddProductToCart(ctx context.Context, productID string) error {
|
||||
inventoryClientRequest := events.NewInventoryGRPCClientRequestEvent()
|
||||
bus.Pub(inventoryClientRequest)
|
||||
inventoryClientRequest.WaitReply()
|
||||
|
||||
pricesClientRequest := events.NewPricesGRPCClientRequestEvent()
|
||||
bus.Pub(pricesClientRequest)
|
||||
pricesClientRequest.WaitReply()
|
||||
|
||||
defer inventoryClientRequest.Conn.Close() // close GRPC connection when done
|
||||
stockResponse, err := inventoryClientRequest.Client.GetStockForProduct(ctx, &inventory.ProductIDRequest{ID: productID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer pricesClientRequest.Conn.Close() // close GRPC connection when done
|
||||
priceResponse, err := pricesClientRequest.Client.GetPricesForProduct(ctx, &prices.ProductIDRequest{ID: productID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.sb.WriteString(fmt.Sprintf("stock %0.2fpcs @ price %0.2f$\n", stockResponse.Stock, priceResponse.Price))
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/inventory"
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/prices"
|
||||
)
|
||||
|
||||
type InventoryGRPCClientRequestEvent struct {
|
||||
wg sync.WaitGroup
|
||||
Conn Closer // should be *grpc.ClientConn, but we're avoiding the import
|
||||
Client inventory.ServiceClient
|
||||
}
|
||||
|
||||
func NewInventoryGRPCClientRequestEvent() *InventoryGRPCClientRequestEvent {
|
||||
result := InventoryGRPCClientRequestEvent{}
|
||||
result.wg.Add(1)
|
||||
return &result
|
||||
}
|
||||
|
||||
func (i *InventoryGRPCClientRequestEvent) Async() bool {
|
||||
return true // this one is async
|
||||
}
|
||||
|
||||
func (i *InventoryGRPCClientRequestEvent) WaitReply() {
|
||||
i.wg.Wait()
|
||||
}
|
||||
|
||||
func (i *InventoryGRPCClientRequestEvent) Reply() {
|
||||
i.wg.Done()
|
||||
}
|
||||
|
||||
type PricesGRPCClientRequestEvent struct {
|
||||
wg sync.WaitGroup
|
||||
Conn Closer // should be *grpc.ClientConn, but we're avoiding the import
|
||||
Client prices.ServiceClient
|
||||
}
|
||||
|
||||
func NewPricesGRPCClientRequestEvent() *PricesGRPCClientRequestEvent {
|
||||
result := PricesGRPCClientRequestEvent{}
|
||||
result.wg.Add(1)
|
||||
return &result
|
||||
}
|
||||
|
||||
func (p *PricesGRPCClientRequestEvent) WaitReply() {
|
||||
p.wg.Wait()
|
||||
}
|
||||
|
||||
func (p *PricesGRPCClientRequestEvent) Reply() {
|
||||
p.wg.Done()
|
||||
}
|
||||
|
||||
type Closer interface {
|
||||
Close() error
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type ServiceClient interface {
|
||||
GetStockForProduct(ctx context.Context, in *ProductIDRequest) (*ProductStockResponse, error) // , opts ...grpc.CallOption) (*ProductStockResponse, error)
|
||||
}
|
||||
|
||||
type ProductIDRequest struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
type ProductStockResponse struct {
|
||||
Stock float64
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type ServiceImpl struct {
|
||||
}
|
||||
|
||||
func NewService() ServiceImpl {
|
||||
result := ServiceImpl{}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) GetStockForProduct(ctx context.Context, productID string) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package factory_request_reply
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/badu/bus"
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/cart"
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/events"
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/inventory"
|
||||
"github.com/badu/bus/test_scenarios/factory-request-reply/prices"
|
||||
)
|
||||
|
||||
var sb strings.Builder
|
||||
|
||||
type pricesClientStub struct{}
|
||||
|
||||
func (s *pricesClientStub) GetPricesForProduct(ctx context.Context, in *prices.ProductIDRequest) (*prices.ProductPriceResponse, error) {
|
||||
return &prices.ProductPriceResponse{Price: 10.30}, nil
|
||||
}
|
||||
|
||||
type fakeCloser struct {
|
||||
}
|
||||
|
||||
func (f *fakeCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func OnPricesGRPCClientStubRequest(e *events.PricesGRPCClientRequestEvent) {
|
||||
sb.WriteString("OnPricesGRPCClientStubRequest\n")
|
||||
e.Client = &pricesClientStub{}
|
||||
e.Conn = &fakeCloser{}
|
||||
<-time.After(300 * time.Millisecond)
|
||||
e.Reply()
|
||||
}
|
||||
|
||||
type inventoryClientStub struct{}
|
||||
|
||||
func (s *inventoryClientStub) GetStockForProduct(ctx context.Context, in *inventory.ProductIDRequest) (*inventory.ProductStockResponse, error) {
|
||||
return &inventory.ProductStockResponse{Stock: 200}, nil
|
||||
}
|
||||
|
||||
func OnInventoryGRPCClientStubRequest(e *events.InventoryGRPCClientRequestEvent) {
|
||||
sb.WriteString("OnInventoryGRPCClientStubRequest\n")
|
||||
e.Client = &inventoryClientStub{}
|
||||
e.Conn = &fakeCloser{}
|
||||
<-time.After(300 * time.Millisecond)
|
||||
e.Reply()
|
||||
}
|
||||
|
||||
func TestGRPCClientStub(t *testing.T) {
|
||||
|
||||
cartSvc := cart.NewService(&sb)
|
||||
|
||||
bus.Sub(OnInventoryGRPCClientStubRequest)
|
||||
bus.Sub(OnPricesGRPCClientStubRequest)
|
||||
|
||||
err := cartSvc.AddProductToCart(context.Background(), "1")
|
||||
if err != nil {
|
||||
t.Fatalf("error adding product to cart : %#v", err)
|
||||
}
|
||||
|
||||
err = cartSvc.AddProductToCart(context.Background(), "2")
|
||||
if err != nil {
|
||||
t.Fatalf("error adding product to cart : %#v", err)
|
||||
}
|
||||
|
||||
const expecting = "OnInventoryGRPCClientStubRequest\n" +
|
||||
"OnPricesGRPCClientStubRequest\n" +
|
||||
"stock 200.00pcs @ price 10.30$\n" +
|
||||
"OnInventoryGRPCClientStubRequest\n" +
|
||||
"OnPricesGRPCClientStubRequest\n" +
|
||||
"stock 200.00pcs @ price 10.30$\n"
|
||||
|
||||
got := sb.String()
|
||||
if got != expecting {
|
||||
t.Fatalf("expecting :\n%s but got : \n%s", expecting, got)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package prices
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type ServiceClient interface {
|
||||
GetPricesForProduct(ctx context.Context, in *ProductIDRequest) (*ProductPriceResponse, error) // , opts ...grpc.CallOption) (*ProductPriceResponse, error)
|
||||
}
|
||||
|
||||
type ProductIDRequest struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
type ProductPriceResponse struct {
|
||||
Price float64
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package prices
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type ServiceImpl struct {
|
||||
}
|
||||
|
||||
func NewService() ServiceImpl {
|
||||
result := ServiceImpl{}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) GetPricesForProduct(ctx context.Context, productID string) {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user