Skip to content

Commit

Permalink
Added mock unit test framework
Browse files Browse the repository at this point in the history
Signed-off-by: Harish P <harish_p4@dell.com>
  • Loading branch information
harishp8889 committed Dec 15, 2022
1 parent 4cbffef commit 626220c
Show file tree
Hide file tree
Showing 10 changed files with 954 additions and 15 deletions.
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@ module github.com/opiproject/goopicsi
go 1.19

require (
github.com/go-chi/chi v1.5.4
github.com/google/uuid v1.3.0
github.com/lithammer/fuzzysearch v1.1.5
github.com/opiproject/opi-api v0.0.0-20221212223617-4ab228a467f7
github.com/stretchr/testify v1.8.1
golang.org/x/net v0.0.0-20221002022538-bcab6841153b
golang.org/x/text v0.4.0
google.golang.org/grpc v1.51.0
google.golang.org/protobuf v1.28.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/net v0.0.0-20221002022538-bcab6841153b // indirect
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect
golang.org/x/text v0.4.0 // indirect
google.golang.org/genproto v0.0.0-20220930163606-c98284e70a91 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
14 changes: 6 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs=
github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/opiproject/opi-api v0.0.0-20221207164013-fd93b840b575 h1:qUuLJp4bRKxC21El2bg6rhlBLjD/HBta7ALSZLD2pMY=
github.com/opiproject/opi-api v0.0.0-20221207164013-fd93b840b575/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY=
github.com/opiproject/opi-api v0.0.0-20221208205708-b089acb781cd h1:9jPT8oOKr5VvC2oRhuoH3YStkHCLOjZuLiQBNHLK1bY=
github.com/opiproject/opi-api v0.0.0-20221208205708-b089acb781cd/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY=
github.com/opiproject/opi-api v0.0.0-20221208224812-65d927304471 h1:W1F/RDX/PHjRanw6aaOtxCGTsPoysGNIhMojKex+kX8=
github.com/opiproject/opi-api v0.0.0-20221208224812-65d927304471/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY=
github.com/opiproject/opi-api v0.0.0-20221212161256-b1b2672e72be h1:lS16v9/5Vr0+ibwLRp0LJPEq3KWAEFcS81ifVS2BscI=
github.com/opiproject/opi-api v0.0.0-20221212161256-b1b2672e72be/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY=
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
github.com/opiproject/opi-api v0.0.0-20221212223617-4ab228a467f7 h1:iQS6+aIBIsWmNfcUmP40rrDrKsP+xgF2Z5nhOP33U/c=
github.com/opiproject/opi-api v0.0.0-20221212223617-4ab228a467f7/go.mod h1:92pv4ulvvPMuxCJ9ND3aYbmBfEMLx0VCjpkiR7ZTqPY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -31,8 +27,10 @@ golang.org/x/net v0.0.0-20221002022538-bcab6841153b h1:6e93nYa3hNqAvLr0pD4PN1fFS
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
google.golang.org/genproto v0.0.0-20220930163606-c98284e70a91 h1:Ezh2cpcnP5Rq60sLensUsFnxh7P6513NLvNtCm9iyJ4=
Expand Down
84 changes: 80 additions & 4 deletions goopicsi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,76 @@
package goopicsi

import (
"fmt"
"log"
"net"
"os"
"strings"
"testing"

"github.com/opiproject/goopicsi/test/mock-server/server"
"github.com/opiproject/goopicsi/test/mock-server/stub"
pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go"
"github.com/stretchr/testify/suite"
"google.golang.org/grpc"

"github.com/stretchr/testify/assert"
)

type GoopcsiTestSuite struct {
suite.Suite
}

func (suite *GoopcsiTestSuite) SetupSuite() {
RunServer()
}

// RunServer launches mock grpc server
func RunServer() {
fmt.Println("RUNNING MOCK SERVER")
const (
csiAddress = "localhost:50051"
defaultStubsPath = "test/mock-server/stubs"
apiPort = "4771"
)

// run admin stub server
stub.RunStubServer(stub.Options{
StubPath: defaultStubsPath,
Port: apiPort,
BindAddr: "0.0.0.0",
})
var protocol string
if strings.Contains(csiAddress, ":") {
protocol = "tcp"
} else {
protocol = "unix"
}
lis, err := net.Listen(protocol, csiAddress)
if err != nil {
fmt.Println(err, "failed to listen on address", "address", csiAddress)
os.Exit(1)
}

MockServer := grpc.NewServer()

pb.RegisterFrontendNvmeServiceServer(MockServer, &server.GoopCSI{})

fmt.Printf("Serving gRPC on %s\n", csiAddress)
errChan := make(chan error)

// run blocking call in a separate goroutine, report errors via channel
go func() {
if err := MockServer.Serve(lis); err != nil {
errChan <- err
}
}()
}

func (suite *GoopcsiTestSuite) TearDownTestSuite() {
suite.T().Log("Cleaning up resources..")
}

func TestNVMeControllerConnect(t *testing.T) {
err := NVMeControllerConnect("12", "", "", 44565, "")
if err != nil {
Expand Down Expand Up @@ -49,11 +113,14 @@ func TestCreateNVMeNamespace(t *testing.T) {
log.Println(resp)
}

func TestDeleteNVMeNamespace(t *testing.T) {
func (suite *GoopcsiTestSuite) TestDeleteNVMeNamespace() {
// positive scenario
err := DeleteNVMeNamespace("1")
if err != nil {
log.Println(err)
}
assert.NoError(suite.T(), err, "DeleteNVMeNamespace success")

// negative scenario
err = DeleteNVMeNamespace("invalid")
assert.Error(suite.T(), err, "DeleteNVMeNamespace failed")
}

func TestExposeRemoteNVMe(t *testing.T) {
Expand All @@ -69,3 +136,12 @@ func TestGenerateHostNQN(t *testing.T) {
hostNQN := GenerateHostNQN()
log.Println(hostNQN)
}

func TestGoopcsiTestSuite(t *testing.T) {
if testing.Short() {
t.Skip("Skipping as requested by short flag")
}
testSuite := new(GoopcsiTestSuite)
suite.Run(t, testSuite)
testSuite.TearDownTestSuite()
}
199 changes: 199 additions & 0 deletions test/mock-server/server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/*
Copyright © 2021-2022 Dell Inc. or its subsidiaries. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package server implements mock gRPC services
package server

import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"

"golang.org/x/net/context"
"google.golang.org/protobuf/types/known/emptypb"

pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go"
)

// GoopCSI mock gRPC server to implement mock service calls
type GoopCSI struct{}

// CreateNVMeSubsystem creates mock NVMe subsystem
func (s *GoopCSI) CreateNVMeSubsystem(ctx context.Context, request *pb.CreateNVMeSubsystemRequest) (*pb.NVMeSubsystem, error) {
// TODO implement me
panic("implement me")
}

// DeleteNVMeSubsystem deletes mock NVMe subsystem
func (s *GoopCSI) DeleteNVMeSubsystem(ctx context.Context, request *pb.DeleteNVMeSubsystemRequest) (*emptypb.Empty, error) {
// TODO implement me
panic("implement me")
}

// UpdateNVMeSubsystem updates a mock NVMe subsystem
func (s *GoopCSI) UpdateNVMeSubsystem(ctx context.Context, request *pb.UpdateNVMeSubsystemRequest) (*pb.NVMeSubsystem, error) {
// TODO implement me
panic("implement me")
}

// ListNVMeSubsystems lists mock NVMe subsystems
func (s *GoopCSI) ListNVMeSubsystems(ctx context.Context, request *pb.ListNVMeSubsystemsRequest) (*pb.ListNVMeSubsystemsResponse, error) {
// TODO implement me
panic("implement me")
}

// GetNVMeSubsystem gets a mock NVMe subsystem
func (s *GoopCSI) GetNVMeSubsystem(ctx context.Context, request *pb.GetNVMeSubsystemRequest) (*pb.NVMeSubsystem, error) {
// TODO implement me
panic("implement me")
}

// NVMeSubsystemStats gets mock subsystem stats
func (s *GoopCSI) NVMeSubsystemStats(ctx context.Context, request *pb.NVMeSubsystemStatsRequest) (*pb.NVMeSubsystemStatsResponse, error) {
// TODO implement me
panic("implement me")
}

// CreateNVMeController creates a mock NVMe controller
func (s *GoopCSI) CreateNVMeController(ctx context.Context, request *pb.CreateNVMeControllerRequest) (*pb.NVMeController, error) {
// TODO implement me
panic("implement me")
}

// DeleteNVMeController deletes a mock NVMe controller
func (s *GoopCSI) DeleteNVMeController(ctx context.Context, request *pb.DeleteNVMeControllerRequest) (*emptypb.Empty, error) {
// TODO implement me
panic("implement me")
}

// UpdateNVMeController updates a mock NVMe controller
func (s *GoopCSI) UpdateNVMeController(ctx context.Context, request *pb.UpdateNVMeControllerRequest) (*pb.NVMeController, error) {
// TODO implement me
panic("implement me")
}

// ListNVMeControllers lists mock controllers
func (s *GoopCSI) ListNVMeControllers(ctx context.Context, request *pb.ListNVMeControllersRequest) (*pb.ListNVMeControllersResponse, error) {
// TODO implement me
panic("implement me")
}

// GetNVMeController gets a mock NVMe controller
func (s *GoopCSI) GetNVMeController(ctx context.Context, request *pb.GetNVMeControllerRequest) (*pb.NVMeController, error) {
// TODO implement me
panic("implement me")
}

// NVMeControllerStats gets mock stats
func (s *GoopCSI) NVMeControllerStats(ctx context.Context, request *pb.NVMeControllerStatsRequest) (*pb.NVMeControllerStatsResponse, error) {
// TODO implement me
panic("implement me")
}

// CreateNVMeNamespace creates a mock NVMe namespace
func (s *GoopCSI) CreateNVMeNamespace(ctx context.Context, request *pb.CreateNVMeNamespaceRequest) (*pb.NVMeNamespace, error) {
out := &pb.NVMeNamespace{}
err := FindStub("FrontendNvmeServiceServer", "CreateNVMeNamespace", request, out)
return out, err
}

// DeleteNVMeNamespace deletes a mock NVMe namespace
func (s *GoopCSI) DeleteNVMeNamespace(ctx context.Context, request *pb.DeleteNVMeNamespaceRequest) (*emptypb.Empty, error) {
out := &emptypb.Empty{}
err := FindStub("FrontendNvmeServiceServer", "DeleteNVMeNamespace", request, out)
return out, err
}

// UpdateNVMeNamespace updates a mock namespace
func (s *GoopCSI) UpdateNVMeNamespace(ctx context.Context, request *pb.UpdateNVMeNamespaceRequest) (*pb.NVMeNamespace, error) {
// TODO implement me
panic("implement me")
}

// ListNVMeNamespaces lists mock namespaces
func (s *GoopCSI) ListNVMeNamespaces(ctx context.Context, request *pb.ListNVMeNamespacesRequest) (*pb.ListNVMeNamespacesResponse, error) {
// TODO implement me
panic("implement me")
}

// GetNVMeNamespace gets a mock namespace
func (s *GoopCSI) GetNVMeNamespace(ctx context.Context, request *pb.GetNVMeNamespaceRequest) (*pb.NVMeNamespace, error) {
// TODO implement me
panic("implement me")
}

// NVMeNamespaceStats gets mock namespace stats
func (s *GoopCSI) NVMeNamespaceStats(ctx context.Context, request *pb.NVMeNamespaceStatsRequest) (*pb.NVMeNamespaceStatsResponse, error) {
// TODO implement me
panic("implement me")
}

type payload struct {
Service string `json:"service"`
Method string `json:"method"`
Data interface{} `json:"data"`
}

type response struct {
Data interface{} `json:"data"`
Error string `json:"error"`
}

// FindStub makes request to mock grpc server
func FindStub(service, method string, in, out interface{}) error {
url := "http://localhost:4771/find"
pyl := payload{
Service: service,
Method: method,
Data: in,
}
byt, err := json.Marshal(pyl)
if err != nil {
return err
}
reader := bytes.NewReader(byt)
resp, err := http.DefaultClient.Post(url, "application/json", reader)
if err != nil {
return fmt.Errorf("error request to stub server %v", err)
}
defer func() {
err := resp.Body.Close()
if err != nil {
log.Fatal(err)
}
}()

if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf(string(body))
}

respRPC := new(response)
err = json.NewDecoder(resp.Body).Decode(respRPC)
if err != nil {
return fmt.Errorf("decoding json response %v", err)
}

if respRPC.Error != "" {
return fmt.Errorf(respRPC.Error)
}

data, _ := json.Marshal(respRPC.Data)
return json.Unmarshal(data, out)
}
Loading

0 comments on commit 626220c

Please sign in to comment.