From 306d51e093bd6de0f8fec1cf61e607a097dc6c99 Mon Sep 17 00:00:00 2001 From: Harshita Pandey <88329939+harshitap26@users.noreply.github.com> Date: Thu, 17 Feb 2022 11:42:53 +0530 Subject: [PATCH] Mock Unit Tests (#6) * Mock And Unit Tests * Mock and Unit Test * NVMe list Signed-off-by: Harshita Pandey * nvme-connect changes * Unit tests * NVME list Changes * NVME list Changes * Mock Unit Tests * Mock Unit Tests * Mock Unit Tests * Mock and Unit tests * NVMe list changes * Unit and Mock tests * Mock and Unit tests * Mock and Unit test * Mock And Unit Tests * Mock and Unit Test * nvme-connect changes * Unit tests * Mock Unit Tests * Mock Unit Tests * Mock Unit Tests * Mock and Unit tests * Unit and Mock tests * Mock and Unit tests * Mock and Unit test --- Makefile | 24 ++ gonvme.go | 25 ++ gonvme_mock.go | 171 +++++++++++++ gonvme_tcp.go | 28 ++- gonvme_test.go | 435 ++++++++++++++++++++++++++++++++++ testdata/initiatorname.nvme | 1 + testdata/multiple_nqn.nvme | 2 + testdata/no_nqn.nvme | 0 testdata/session_info_invalid | 4 + testdata/session_info_valid | 22 ++ testdata/valid.nvme | 1 + 11 files changed, 706 insertions(+), 7 deletions(-) create mode 100644 Makefile create mode 100644 gonvme_mock.go create mode 100644 gonvme_test.go create mode 100644 testdata/initiatorname.nvme create mode 100644 testdata/multiple_nqn.nvme create mode 100644 testdata/no_nqn.nvme create mode 100644 testdata/session_info_invalid create mode 100644 testdata/session_info_valid create mode 100644 testdata/valid.nvme diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4d79390 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ + +# These values should be set for running the entire test suite +# all must be valid +Portal="1.1.1.1" +Target="nqn.1988-11.com.mock:00:e6e2d5b871f1403E169D" + + +all:check int-test + +mock-test: + go clean -cache + go test -v -coverprofile=c.out --run=TestMock + +int-test: + GONVME_PORTAL=$(Portal) GONVME_TARGET=$(Target) \ + go test -v -timeout 20m -coverprofile=c.out -coverpkg ./... + +gocover: + go tool cover -html=c.out + +check: + gofmt -d . + golint -set_exit_status + go vet diff --git a/gonvme.go b/gonvme.go index 89a5bfd..9bfa28d 100644 --- a/gonvme.go +++ b/gonvme.go @@ -31,6 +31,31 @@ type Logger = logger.Logger // Tracer - Placeholder for tracer type Tracer = tracer.Tracer +// NVMEinterface is the interface that provides the iSCSI client functionality +type NVMEinterface interface { + + // DiscoverNVMeTCPTargets discovers the targets exposed via a given portal + // returns an array of ISCSITarget instances + DiscoverNVMeTCPTargets(address string, login bool) ([]NVMeTarget, error) + + // GetInitiators get a list of iSCSI initiators defined in a specified file + // To use the system default file of "/etc/nvme/hostnqn", provide a filename of "" + GetInitiators(filename string) ([]string, error) + + //NVMeConnect connects into a specified NVMe target + NVMeConnect(target NVMeTarget) error + + // NVMeDisconnect disconnect from the specified NVMe target + NVMeDisconnect(target NVMeTarget) error + + // GetSessions queries information about sessions + GetSessions() ([]NVMESession, error) + + // generic implementations + isMock() bool + getOptions() map[string]string +} + // NVMeType is the base structure for each platform implementation type NVMeType struct { mock bool diff --git a/gonvme_mock.go b/gonvme_mock.go new file mode 100644 index 0000000..d7f7035 --- /dev/null +++ b/gonvme_mock.go @@ -0,0 +1,171 @@ +package gonvme + +import ( + "errors" + "fmt" + "strconv" +) + +const ( + // MockNumberOfInitiators controls the number of initiators found in mock mode + MockNumberOfInitiators = "numberOfInitiators" + // MockNumberOfTargets controls the number of targets found in mock mode + MockNumberOfTargets = "numberOfTargets" + // MockNumberOfSessions controls the number of NVMe sessions found in mock mode + MockNumberOfSessions = "numberOfSession" +) + +var ( + // GONVMEMock is a struct controlling induced errors + GONVMEMock struct { + InduceDiscoveryError bool + InduceInitiatorError bool + InduceLoginError bool + InduceLogoutError bool + InduceGetSessionsError bool + } +) + +// MockNVMeTCP provides a mock implementation of an NVMe client +type MockNVMeTCP struct { + NVMeType +} + +// NewMockNVMeTCP - returns a mock NVMeTCP client +func NewMockNVMeTCP(opts map[string]string) *MockNVMeTCP { + nvme := MockNVMeTCP{ + NVMeType: NVMeType{ + mock: true, + options: opts, + }, + } + + return &nvme +} + +func getOptionAsInt(opts map[string]string, key string) int64 { + v, _ := strconv.ParseInt(opts[key], 10, 64) + return v +} + +func (nvme *MockNVMeTCP) discoverNVMeTCPTargets(address string, login bool) ([]NVMeTarget, error) { + if GONVMEMock.InduceDiscoveryError { + return []NVMeTarget{}, errors.New("discoverTargets induced error") + } + mockedTargets := make([]NVMeTarget, 0) + count := getOptionAsInt(nvme.options, MockNumberOfTargets) + + if count == 0 { + count = 1 + } + + for idx := 0; idx < int(count); idx++ { + tgt := fmt.Sprintf("%05d", idx) + mockedTargets = append(mockedTargets, + NVMeTarget{ + Portal: address, + TargetNqn: "nqn.1988-11.com.dell.mock:e6e2d5b871f1403E169D" + tgt, + TrType: "tcp", + AdrFam: "fibre-channel", + SubType: "nvme subsystem", + Treq: "not specified", + PortID: "0", + TrsvcID: "none", + SecType: "none", + TargetType: "tcp", + }) + } + + // send back a slice of targets + return mockedTargets, nil +} + +func (nvme *MockNVMeTCP) getInitiators(filename string) ([]string, error) { + + if GONVMEMock.InduceInitiatorError { + return []string{}, errors.New("getInitiators induced error") + } + + mockedInitiators := make([]string, 0) + count := getOptionAsInt(nvme.options, MockNumberOfInitiators) + if count == 0 { + count = 1 + } + + for idx := 0; idx < int(count); idx++ { + init := fmt.Sprintf("%05d", idx) + mockedInitiators = append(mockedInitiators, + "nqn.1988-11.com.dell.mock:01:00000000"+init) + } + return mockedInitiators, nil +} + +func (nvme *MockNVMeTCP) nvmeConnect(target NVMeTarget) error { + + if GONVMEMock.InduceLoginError { + return errors.New("NVMe Login induced error") + } + + return nil +} + +func (nvme *MockNVMeTCP) nvmeDisconnect(target NVMeTarget) error { + + if GONVMEMock.InduceLogoutError { + return errors.New("NVMe Logout induced error") + } + + return nil +} + +func (nvme *MockNVMeTCP) getSessions() ([]NVMESession, error) { + + if GONVMEMock.InduceGetSessionsError { + return []NVMESession{}, errors.New("getSessions induced error") + } + + var sessions []NVMESession + count := getOptionAsInt(nvme.options, MockNumberOfSessions) + if count == 0 { + count = 1 + } + for idx := 0; idx < int(count); idx++ { + init := fmt.Sprintf("%0d", idx) + session := NVMESession{} + session.Target = fmt.Sprintf("nqn.1988-11.com.dell.mock:00:e6e2d5b871f1403E169D%d", idx) + session.Portal = fmt.Sprintf("192.168.1.%d", idx) + session.Name = "nvme" + init + session.NVMESessionState = NVMESessionStateLive + session.NVMETransportName = NVMETransportNameTCP + sessions = append(sessions, session) + } + return sessions, nil +} + +// ==================================================================== +// Architecture agnostic code for the mock implementation + +// DiscoverNVMeTCPTargets runs an NVMe discovery and returns a list of targets. +func (nvme *MockNVMeTCP) DiscoverNVMeTCPTargets(address string, login bool) ([]NVMeTarget, error) { + return nvme.discoverNVMeTCPTargets(address, login) +} + +// GetInitiators returns a list of NVMe initiators on the local system. +func (nvme *MockNVMeTCP) GetInitiators(filename string) ([]string, error) { + return nvme.getInitiators(filename) +} + +// NVMeConnect will attempt to log into an NVMe target +func (nvme *MockNVMeTCP) NVMeConnect(target NVMeTarget) error { + return nvme.nvmeConnect(target) +} + +// NVMeDisconnect will attempt to log out of an NVMe target +func (nvme *MockNVMeTCP) NVMeDisconnect(target NVMeTarget) error { + return nvme.nvmeDisconnect(target) +} + +// GetSessions Queries NVMe session info +func (nvme *MockNVMeTCP) GetSessions() ([]NVMESession, error) { + return nvme.getSessions() +} diff --git a/gonvme_tcp.go b/gonvme_tcp.go index 7d25d2a..5efea7a 100644 --- a/gonvme_tcp.go +++ b/gonvme_tcp.go @@ -1,6 +1,7 @@ package gonvme import ( + "bufio" "fmt" "os" "os/exec" @@ -253,7 +254,15 @@ func (nvme *NVMeTCP) nvmeConnect(target NVMeTarget) error { exe := nvme.buildNVMeCommand([]string{NVMeCommand, "connect", "-t", "tcp", "-n", target.TargetNqn, "-a", target.Portal, "-s", NVMePort}) cmd := exec.Command(exe[0], exe[1:]...) - _, err := cmd.Output() + var Output string + stderr, _ := cmd.StderrPipe() + err := cmd.Start() + + scanner := bufio.NewScanner(stderr) + for scanner.Scan() { + Output = scanner.Text() + } + err = cmd.Wait() if err != nil { if exiterr, ok := err.(*exec.ExitError); ok { @@ -265,8 +274,13 @@ func (nvme *NVMeTCP) nvmeConnect(target NVMeTarget) error { if nvmeConnectResult == 114 || nvmeConnectResult == 70 { // session already exists // do not treat this as a failure - fmt.Printf("\nnvme connection already exists to: %s", target.TargetNqn) - err = nil + if Output == "Failed to write to /dev/nvme-fabrics: Operation already in progress" { + fmt.Printf("NVMe connection already exists\n") + err = nil + } else { + fmt.Printf("\nError during nvme connect %s at %s: %v", target.TargetNqn, target.Portal, err) + return err + } } else { fmt.Printf("\nnvme connect failure: %v", err) } @@ -285,12 +299,12 @@ func (nvme *NVMeTCP) nvmeConnect(target NVMeTarget) error { return nil } -// NVMeDisonnect will attempt to disconnect from a given nvme target -func (nvme *NVMeTCP) NVMeDisonnect(target NVMeTarget) error { - return nvme.nvmeDisonnect(target) +// NVMeDisconnect will attempt to disconnect from a given nvme target +func (nvme *NVMeTCP) NVMeDisconnect(target NVMeTarget) error { + return nvme.nvmeDisconnect(target) } -func (nvme *NVMeTCP) nvmeDisonnect(target NVMeTarget) error { +func (nvme *NVMeTCP) nvmeDisconnect(target NVMeTarget) error { // nvme disconnect is done via the nvme cli // nvme disconnect -n exe := nvme.buildNVMeCommand([]string{NVMeCommand, "disconnect", "-n", target.TargetNqn}) diff --git a/gonvme_test.go b/gonvme_test.go new file mode 100644 index 0000000..ad10594 --- /dev/null +++ b/gonvme_test.go @@ -0,0 +1,435 @@ +package gonvme + +import ( + "fmt" + "io/ioutil" + "os" + "strings" + "testing" +) + +var ( + testPortal string + testTarget string +) + +func reset() { + if p := os.Getenv("GONVME_PORTAL"); p != "" { + testPortal = p + } + if t := os.Getenv("GONVME_TARGET"); t != "" { + testTarget = t + } + GONVMEMock.InduceDiscoveryError = false + GONVMEMock.InduceInitiatorError = false + GONVMEMock.InduceLoginError = false + GONVMEMock.InduceLogoutError = false + GONVMEMock.InduceGetSessionsError = false +} + +func TestPolymorphichCapability(t *testing.T) { + reset() + var c NVMEinterface + // start off with a real implementation + c = NewNVMeTCP(map[string]string{}) + if c.isMock() { + // this should not be a mock implementation + t.Error("Expected a real implementation but got a mock one") + return + } + // switch it to mock + c = NewMockNVMeTCP(map[string]string{}) + if !c.isMock() { + // this should not be a real implementation + t.Error("Expected a mock implementation but got a real one") + return + } + // switch back to a real implementation + c = NewNVMeTCP(map[string]string{}) + if c.isMock() { + // this should not be a mock implementation + t.Error("Expected a real implementation but got a mock one") + return + } +} + +func TestDiscoverTargets(t *testing.T) { + reset() + c := NewNVMeTCP(map[string]string{}) + _, err := c.DiscoverNVMeTCPTargets(testPortal, false) + if err != nil { + t.Error(err.Error()) + } +} + +func TestLoginLogoutTargets(t *testing.T) { + reset() + c := NewNVMeTCP(map[string]string{}) + tgt := NVMeTarget{ + Portal: testPortal, + TargetNqn: testTarget, + TrType: "tcp", + AdrFam: "fibre-channel", + SubType: "nvme subsystem", + Treq: "not specified", + PortID: "0", + TrsvcID: "none", + SecType: "none", + TargetType: "tcp", + } + err := c.NVMeConnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } + err = c.NVMeDisconnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } +} + +func TestLoginLoginLogoutTargets(t *testing.T) { + reset() + c := NewNVMeTCP(map[string]string{}) + tgt := NVMeTarget{ + Portal: testPortal, + TargetNqn: testTarget, + TrType: "tcp", + AdrFam: "fibre-channel", + SubType: "nvme subsystem", + Treq: "not specified", + PortID: "0", + TrsvcID: "none", + SecType: "none", + TargetType: "tcp", + } + err := c.NVMeConnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } + err = c.NVMeConnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } + err = c.NVMeDisconnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } +} + +func TestLogoutLogoutTargets(t *testing.T) { + reset() + c := NewNVMeTCP(map[string]string{}) + tgt := NVMeTarget{ + Portal: testPortal, + TargetNqn: testTarget, + TrType: "tcp", + AdrFam: "fibre-channel", + SubType: "nvme subsystem", + Treq: "not specified", + PortID: "0", + TrsvcID: "none", + SecType: "none", + TargetType: "tcp", + } + // log out of the target, just in case we are logged in already + _ = c.NVMeConnect(tgt) + err := c.NVMeDisconnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } +} + +func TestGetInitiators(t *testing.T) { + reset() + var testdata = []struct { + filename string + count int + }{ + {"testdata/initiatorname.nvme", 1}, + {"testdata/multiple_nqn.nvme", 2}, + {"testdata/no_nqn.nvme", 0}, + {"testdata/valid.nvme", 1}, + } + + c := NewNVMeTCP(map[string]string{}) + for _, tt := range testdata { + initiators, err := c.GetInitiators(tt.filename) + if err != nil { + t.Errorf("Error getting %d initiators from %s: %s", tt.count, tt.filename, err.Error()) + } + if len(initiators) != tt.count { + t.Errorf("Expected %d initiators in %s, but got %d", tt.count, tt.filename, len(initiators)) + } + } + +} + +func TestBuildNVMECommand(t *testing.T) { + reset() + opts := map[string]string{} + initial := []string{"/bin/ls"} + opts[ChrootDirectory] = "/test" + c := NewNVMeTCP(opts) + command := c.buildNVMeCommand(initial) + // the length of the resulting command should the length of the initial command +2 + if len(command) != (len(initial) + 2) { + t.Errorf("Expected to %d items in the command slice but received %v", len(initial)+2, command) + } + if command[0] != "chroot" { + t.Error("Expected the command to be run with chroot") + } + if command[1] != opts[ChrootDirectory] { + t.Errorf("Expected the command to chroot to %s but got %s", opts[ChrootDirectory], command[1]) + } +} + +func TestGetSessions(t *testing.T) { + reset() + c := NewNVMeTCP(map[string]string{}) + _, err := c.GetSessions() + if err != nil { + t.Error(err.Error()) + } +} + +func TestMockDiscoverTargets(t *testing.T) { + reset() + var c NVMEinterface + opts := map[string]string{} + expected := 5 + opts[MockNumberOfTargets] = fmt.Sprintf("%d", expected) + c = NewMockNVMeTCP(opts) + //c = mock + targets, err := c.DiscoverNVMeTCPTargets("1.1.1.1", true) + if err != nil { + t.Error(err.Error()) + } + if len(targets) != expected { + t.Errorf("Expected to find %d targets, but got back %v", expected, targets) + } +} + +func TestMockDiscoverTargetsError(t *testing.T) { + reset() + opts := map[string]string{} + expected := 5 + opts[MockNumberOfTargets] = fmt.Sprintf("%d", expected) + c := NewMockNVMeTCP(opts) + GONVMEMock.InduceDiscoveryError = true + targets, err := c.DiscoverNVMeTCPTargets("1.1.1.1", false) + if err == nil { + t.Error("Expected an induced error") + return + } + if !strings.Contains(err.Error(), "induced") { + t.Error("Expected an induced error") + return + } + if len(targets) != 0 { + t.Errorf("Expected to receive 0 targets when inducing an error. Received %v", targets) + return + } +} + +func TestMockGetInitiators(t *testing.T) { + reset() + opts := map[string]string{} + expected := 3 + opts[MockNumberOfInitiators] = fmt.Sprintf("%d", expected) + c := NewMockNVMeTCP(opts) + initiators, err := c.GetInitiators("") + if err != nil { + t.Error(err.Error()) + } + if len(initiators) != expected { + t.Errorf("Expected to find %d initiators, but got back %v", expected, initiators) + } +} + +func TestMockGetInitiatorsError(t *testing.T) { + reset() + opts := map[string]string{} + expected := 3 + opts[MockNumberOfInitiators] = fmt.Sprintf("%d", expected) + c := NewMockNVMeTCP(opts) + GONVMEMock.InduceInitiatorError = true + initiators, err := c.GetInitiators("") + if err == nil { + t.Error("Expected an induced error") + return + } + if !strings.Contains(err.Error(), "induced") { + t.Error("Expected an induced error") + return + } + if len(initiators) != 0 { + t.Errorf("Expected to receive 0 initiators when inducing an error. Received %v", initiators) + return + } +} + +func TestMockLoginLogoutTargets(t *testing.T) { + reset() + c := NewMockNVMeTCP(map[string]string{}) + tgt := NVMeTarget{ + Portal: testPortal, + TargetNqn: testTarget, + TrType: "tcp", + AdrFam: "fibre-channel", + SubType: "nvme subsystem", + Treq: "not specified", + PortID: "0", + TrsvcID: "none", + SecType: "none", + TargetType: "tcp", + } + err := c.NVMeConnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } + err = c.NVMeDisconnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } +} + +func TestMockLogoutTargetsError(t *testing.T) { + reset() + c := NewMockNVMeTCP(map[string]string{}) + tgt := NVMeTarget{ + Portal: testPortal, + TargetNqn: testTarget, + TrType: "tcp", + AdrFam: "fibre-channel", + SubType: "nvme subsystem", + Treq: "not specified", + PortID: "0", + TrsvcID: "none", + SecType: "none", + TargetType: "tcp", + } + GONVMEMock.InduceLogoutError = true + err := c.NVMeConnect(tgt) + if err != nil { + t.Error(err.Error()) + return + } + err = c.NVMeDisconnect(tgt) + if err == nil { + t.Error("Expected an induced error") + return + } + if !strings.Contains(err.Error(), "induced") { + t.Error("Expected an induced error") + return + } +} + +func TestMockLoginTargetsError(t *testing.T) { + reset() + c := NewMockNVMeTCP(map[string]string{}) + tgt := NVMeTarget{ + Portal: testPortal, + TargetNqn: testTarget, + TrType: "tcp", + AdrFam: "fibre-channel", + SubType: "nvme subsystem", + Treq: "not specified", + PortID: "0", + TrsvcID: "none", + SecType: "none", + TargetType: "tcp", + } + GONVMEMock.InduceLoginError = true + err := c.NVMeConnect(tgt) + if err == nil { + t.Error("Expected an induced error") + return + } + if !strings.Contains(err.Error(), "induced") { + t.Error("Expected an induced error") + return + } +} + +func TestMockGetSessions(t *testing.T) { + reset() + c := NewMockNVMeTCP(map[string]string{}) + // check without induced error + data, err := c.GetSessions() + if len(data) == 0 || len(data[0].Target) == 0 { + t.Error("invalid response from mock") + } + if err != nil { + t.Error(err.Error()) + return + } +} + +func TestMockGetSessionsError(t *testing.T) { + reset() + c := NewMockNVMeTCP(map[string]string{}) + // check with induced error + GONVMEMock.InduceGetSessionsError = true + _, err := c.GetSessions() + if err == nil { + t.Error("Expected an induced error") + return + } + if !strings.Contains(err.Error(), "induced") { + t.Error("Expected an induced error") + return + } +} + +func TestSessionParserParse(t *testing.T) { + sp := &sessionParser{} + fileErrMsg := "can't read file with test data" + + // test valid data + data, err := ioutil.ReadFile("testdata/session_info_valid") + if err != nil { + t.Error(fileErrMsg) + } + sessions := sp.Parse(data) + if len(sessions) != 2 { + t.Error("unexpected results count") + } + for i, session := range sessions { + if i == 0 { + compareStr(t, session.Target, "nqn.1988-11.com.dell.mock:00:e6e2d5b871f1403E169D") + compareStr(t, session.Portal, "10.230.1.1:4420") + compareStr(t, string(session.NVMESessionState), string(NVMESessionStateLive)) + compareStr(t, string(session.NVMETransportName), string(NVMETransportNameTCP)) + } else { + compareStr(t, session.Target, "nqn.1988-11.com.dell.mock:00:e6e2d5b871f1403E169D") + compareStr(t, session.Portal, "10.230.1.2:4420") + compareStr(t, string(session.NVMESessionState), string(NVMESessionStateDeleting)) + compareStr(t, string(session.NVMETransportName), string(NVMETransportNameTCP)) + } + } + + // test invalid data parsing + data, err = ioutil.ReadFile("testdata/session_info_invalid") + if err != nil { + t.Error(fileErrMsg) + } + r := sp.Parse(data) + if len(r) != 0 { + t.Error("non empty result while parsing invalid data") + } +} + +func compareStr(t *testing.T, str1 string, str2 string) { + if str1 != str2 { + t.Errorf("strings are not equal: %s != %s", str1, str2) + } +} diff --git a/testdata/initiatorname.nvme b/testdata/initiatorname.nvme new file mode 100644 index 0000000..29bce89 --- /dev/null +++ b/testdata/initiatorname.nvme @@ -0,0 +1 @@ +nqn.2014-08.org.mock:uuid:02a08600-0000-0000-0000-bf1f7326990e diff --git a/testdata/multiple_nqn.nvme b/testdata/multiple_nqn.nvme new file mode 100644 index 0000000..b00e26c --- /dev/null +++ b/testdata/multiple_nqn.nvme @@ -0,0 +1,2 @@ +nqn.2014-08.org.mock:uuid:02a08600-0000-0000-0000-bf1f7326990e + nqn.2014-08.org.mock:uuid:02a08600-0000-0000-0000-bf1f7326990e diff --git a/testdata/no_nqn.nvme b/testdata/no_nqn.nvme new file mode 100644 index 0000000..e69de29 diff --git a/testdata/session_info_invalid b/testdata/session_info_invalid new file mode 100644 index 0000000..ac8e2c2 --- /dev/null +++ b/testdata/session_info_invalid @@ -0,0 +1,4 @@ +Current Portal: 192.168.1.1:4420,1 + +nvme0 tcp traddr=10.230.42.113 trsvcid=4420 live +nvme1 tcp traddr=10.230.42.114 trsvcid=4420 live diff --git a/testdata/session_info_valid b/testdata/session_info_valid new file mode 100644 index 0000000..db90f7c --- /dev/null +++ b/testdata/session_info_valid @@ -0,0 +1,22 @@ +{ + "Subsystems" : [ + { + "Name" : "nvme-subsys0", + "NQN" : "nqn.1988-11.com.dell.mock:00:e6e2d5b871f1403E169D", + "Paths" : [ + { + "Name" : "nvme0", + "Transport" : "tcp", + "Address" : "traddr=10.230.1.1 trsvcid=4420", + "State" : "live" + }, + { + "Name" : "nvme1", + "Transport" : "tcp", + "Address" : "traddr=10.230.1.2 trsvcid=4420", + "State" : "deleting" + } + ] + } + ] +} diff --git a/testdata/valid.nvme b/testdata/valid.nvme new file mode 100644 index 0000000..29bce89 --- /dev/null +++ b/testdata/valid.nvme @@ -0,0 +1 @@ +nqn.2014-08.org.mock:uuid:02a08600-0000-0000-0000-bf1f7326990e