productcatalogservice: implementation

This commit is contained in:
Jonathan Amsterdam 2018-06-16 09:37:11 -04:00
parent 9af0ca0eda
commit 914f07f307
4 changed files with 2556 additions and 0 deletions

View file

@ -0,0 +1,6 @@
#!/bin/bash -e
PATH=$PATH:$GOPATH/bin
protodir=../../pb
protoc --go_out=plugins=grpc:genproto -I $protodir $protodir/demo.proto

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,66 @@
package main
import (
"context"
"flag"
"fmt"
"log"
"net"
"strings"
pb "./genproto"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var port = flag.Int("port", 3550, "port to listen at")
var catalog = []*pb.Product{
{Id: 1, Name: "shirt", Description: "nice shirt", Picture: "picture1", PriceUsd: &pb.MoneyAmount{Decimal: 53}},
{Id: 2, Name: "pants", Description: "nice pants", Picture: "picture2", PriceUsd: &pb.MoneyAmount{Decimal: 81}},
{Id: 3, Name: "hat", Description: "nice hat", Picture: "picture3", PriceUsd: &pb.MoneyAmount{Decimal: 20}},
}
func main() {
flag.Parse()
run(*port)
select {}
}
func run(port int) string {
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatal(err)
}
srv := grpc.NewServer()
pb.RegisterProductCatalogServiceServer(srv, &productCatalog{})
go srv.Serve(l)
return l.Addr().String()
}
type productCatalog struct{}
func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) {
return &pb.ListProductsResponse{Products: catalog}, nil
}
func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductRequest) (*pb.Product, error) {
for _, p := range catalog {
if req.Id == p.Id {
return p, nil
}
}
return nil, status.Errorf(codes.NotFound, "no product with ID %d", req.Id)
}
func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProductsRequest) (*pb.SearchProductsResponse, error) {
// Intepret query as a substring match in name or description.
var ps []*pb.Product
for _, p := range catalog {
if strings.Contains(p.Name, req.Query) || strings.Contains(p.Description, req.Query) {
ps = append(ps, p)
}
}
return &pb.SearchProductsResponse{Results: ps}, nil
}

View file

@ -0,0 +1,51 @@
package main
import (
"context"
"testing"
pb "./genproto"
"github.com/golang/protobuf/proto"
"github.com/google/go-cmp/cmp"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func TestServer(t *testing.T) {
ctx := context.Background()
addr := run(0)
conn, err := grpc.Dial(addr, grpc.WithInsecure())
if err != nil {
t.Fatal(err)
}
defer conn.Close()
client := pb.NewProductCatalogServiceClient(conn)
res, err := client.ListProducts(ctx, &pb.Empty{})
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(res.Products, catalog, cmp.Comparer(proto.Equal)); diff != "" {
t.Error(diff)
}
got, err := client.GetProduct(ctx, &pb.GetProductRequest{Id: 2})
if err != nil {
t.Fatal(err)
}
if want := catalog[1]; !proto.Equal(got, want) {
t.Errorf("got %v, want %v", got, want)
}
_, err = client.GetProduct(ctx, &pb.GetProductRequest{Id: -1})
if got, want := status.Code(err), codes.NotFound; got != want {
t.Errorf("got %s, want %s", got, want)
}
sres, err := client.SearchProducts(ctx, &pb.SearchProductsRequest{Query: "nice"})
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(sres.Results, catalog, cmp.Comparer(proto.Equal)); diff != "" {
t.Error(diff)
}
}