SEBA-688 add additional unit tests
Change-Id: I361bc872af08b97bccb29f17838940205fed48e9
diff --git a/commands/backup.go b/commands/backup.go
index 287236f..fc5d509 100644
--- a/commands/backup.go
+++ b/commands/backup.go
@@ -37,7 +37,7 @@
type BackupCreate struct {
OutputOptions
- ChunkSize int `short:"h" long:"chunksize" default:"65536" description:"Host and port"`
+ ChunkSize int `short:"h" long:"chunksize" default:"65536" description:"Chunk size for streaming transfer"`
Args struct {
LocalFileName string
} `positional-args:"yes" required:"yes"`
@@ -45,9 +45,11 @@
type BackupRestore struct {
OutputOptions
- Args struct {
+ ChunkSize int `short:"h" long:"chunksize" default:"65536" description:"Chunk size for streaming transfer"`
+ Args struct {
LocalFileName string
} `positional-args:"yes" required:"yes"`
+ CreateURIFunc func() (string, string) // allow override of CreateURIFunc for easy unit testing
}
type BackupOpts struct {
@@ -152,6 +154,13 @@
return nil
}
+// Create a file:/// URI to use for storing the file in the core
+func CreateDynamicURI() (string, string) {
+ remote_name := "cordctl-restore-" + time.Now().Format("20060102T150405Z")
+ uri := "file:///var/run/xos/backup/local/" + remote_name
+ return remote_name, uri
+}
+
func (options *BackupRestore) Execute(args []string) error {
conn, descriptor, err := InitReflectionClient()
if err != nil {
@@ -162,12 +171,17 @@
ctx := context.Background() // TODO: Implement a sync timeout
local_name := options.Args.LocalFileName
- remote_name := "cordctl-restore-" + time.Now().Format("20060102T150405Z")
- uri := "file:///var/run/xos/backup/local/" + remote_name
+
+ var remote_name, uri string
+ if options.CreateURIFunc != nil {
+ remote_name, uri = options.CreateURIFunc()
+ } else {
+ remote_name, uri = CreateDynamicURI()
+ }
// STEP 1: Upload the file
- h, upload_result, err := UploadFile(conn, descriptor, local_name, uri, 65536)
+ h, upload_result, err := UploadFile(conn, descriptor, local_name, uri, options.ChunkSize)
if err != nil {
return err
}
diff --git a/commands/backup_test.go b/commands/backup_test.go
new file mode 100644
index 0000000..357f891
--- /dev/null
+++ b/commands/backup_test.go
@@ -0,0 +1,90 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * 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 commands
+
+import (
+ "bytes"
+ "github.com/opencord/cordctl/testutils"
+ "io/ioutil"
+ "testing"
+)
+
+func TestBackupCreate(t *testing.T) {
+ // use `python -m json.tool` to pretty-print json
+ expected := `[
+ {
+ "bytes": 6,
+ "checksum": "sha256:e9c0f8b575cbfcb42ab3b78ecc87efa3b011d9a5d10b09fa4e96f240bf6a82f5",
+ "chunks": 2,
+ "status": "SUCCESS"
+ }
+ ]`
+
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options BackupOpts
+ options.Create.OutputAs = "json"
+ options.Create.Args.LocalFileName = "/tmp/transfer.down"
+ options.Create.ChunkSize = 3
+ err := options.Create.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertJSONEqual(t, got.String(), expected)
+}
+
+// Mock the CreateURI function in the Restore code to use file:///tmp/transfer.up
+func CreateURI() (string, string) {
+ remote_name := "transfer.up"
+ uri := "file:///tmp/" + remote_name
+ return remote_name, uri
+}
+
+func TestBackupRestore(t *testing.T) {
+ // use `python -m json.tool` to pretty-print json
+ expected := `[
+ {
+ "bytes": 6,
+ "checksum": "sha256:e9c0f8b575cbfcb42ab3b78ecc87efa3b011d9a5d10b09fa4e96f240bf6a82f5",
+ "chunks": 2,
+ "status": "SUCCESS"
+ }
+ ]`
+
+ err := ioutil.WriteFile("/tmp/transfer.up", []byte("ABCDEF"), 0644)
+
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options BackupRestore
+ options.OutputAs = "json"
+ options.Args.LocalFileName = "/tmp/transfer.up"
+ options.ChunkSize = 3
+ options.CreateURIFunc = CreateURI
+ err = options.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertJSONEqual(t, got.String(), expected)
+}
diff --git a/commands/completion.go b/commands/completion.go
index 67c7ad3..65c4883 100644
--- a/commands/completion.go
+++ b/commands/completion.go
@@ -32,6 +32,6 @@
}
func (options *BashOptions) Execute(args []string) error {
- fmt.Println(completion.Bash)
+ fmt.Fprintln(OutputStream, completion.Bash)
return nil
}
diff --git a/commands/completion_test.go b/commands/completion_test.go
new file mode 100644
index 0000000..6b9c119
--- /dev/null
+++ b/commands/completion_test.go
@@ -0,0 +1,39 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * 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 commands
+
+import (
+ "bytes"
+ "github.com/opencord/cordctl/completion"
+ "github.com/opencord/cordctl/testutils"
+ "testing"
+)
+
+func TestCompletion(t *testing.T) {
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options CompletionOptions
+ err := options.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertStringEqual(t, got.String(), completion.Bash+"\n")
+}
diff --git a/commands/modeltypes_test.go b/commands/modeltypes_test.go
new file mode 100644
index 0000000..678afba
--- /dev/null
+++ b/commands/modeltypes_test.go
@@ -0,0 +1,110 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * 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 commands
+
+import (
+ "bytes"
+ "github.com/opencord/cordctl/testutils"
+ "testing"
+)
+
+func TestModelTypeList(t *testing.T) {
+ // use `python -m json.tool` to pretty-print json
+ expected := `AddressPool
+AttWorkflowDriverService
+AttWorkflowDriverServiceInstance
+AttWorkflowDriverWhiteListEntry
+BNGPortMapping
+BackupFile
+BackupOperation
+BandwidthProfile
+ComputeServiceInstance
+FabricCrossconnectService
+FabricCrossconnectServiceInstance
+FabricIpAddress
+FabricService
+Flavor
+Image
+InterfaceType
+KubernetesConfigMap
+KubernetesConfigVolumeMount
+KubernetesData
+KubernetesResourceInstance
+KubernetesSecret
+KubernetesSecretVolumeMount
+KubernetesService
+KubernetesServiceInstance
+NNIPort
+Network
+NetworkParameter
+NetworkParameterType
+NetworkSlice
+NetworkTemplate
+Node
+NodeLabel
+NodeToSwitchPort
+OLTDevice
+ONOSApp
+ONOSService
+ONUDevice
+PONONUPort
+PONPort
+Port
+PortBase
+PortInterface
+Principal
+Privilege
+RCORDIpAddress
+RCORDService
+RCORDSubscriber
+Role
+Service
+ServiceAttribute
+ServiceDependency
+ServiceGraphConstraint
+ServiceInstance
+ServiceInstanceAttribute
+ServiceInstanceLink
+ServiceInterface
+ServicePort
+Site
+Slice
+Switch
+SwitchPort
+Tag
+TrustDomain
+UNIPort
+User
+VOLTService
+VOLTServiceInstance
+XOSCore
+XOSGuiExtension
+`
+
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options ModelTypeOpts
+ err := options.List.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertStringEqual(t, got.String(), expected)
+}
diff --git a/commands/orm_test.go b/commands/orm_test.go
new file mode 100644
index 0000000..aa1b7c4
--- /dev/null
+++ b/commands/orm_test.go
@@ -0,0 +1,179 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * 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 commands
+
+import (
+ "context"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestDecodeOperator(t *testing.T) {
+ value, operator, invert, err := DecodeOperator("=something")
+ assert.Equal(t, value, "something")
+ assert.Equal(t, operator, "EQUAL")
+ assert.Equal(t, invert, false)
+ assert.Equal(t, err, nil)
+
+ value, operator, invert, err = DecodeOperator("!=something")
+ assert.Equal(t, value, "something")
+ assert.Equal(t, operator, "EQUAL")
+ assert.Equal(t, invert, true)
+ assert.Equal(t, err, nil)
+
+ value, operator, invert, err = DecodeOperator(">3")
+ assert.Equal(t, value, "3")
+ assert.Equal(t, operator, "GREATER_THAN")
+ assert.Equal(t, invert, false)
+ assert.Equal(t, err, nil)
+
+ value, operator, invert, err = DecodeOperator(">=3")
+ assert.Equal(t, value, "3")
+ assert.Equal(t, operator, "GREATER_THAN_OR_EQUAL")
+ assert.Equal(t, invert, false)
+ assert.Equal(t, err, nil)
+
+ value, operator, invert, err = DecodeOperator("<3")
+ assert.Equal(t, value, "3")
+ assert.Equal(t, operator, "LESS_THAN")
+ assert.Equal(t, invert, false)
+ assert.Equal(t, err, nil)
+
+ value, operator, invert, err = DecodeOperator("<=3")
+ assert.Equal(t, value, "3")
+ assert.Equal(t, operator, "LESS_THAN_OR_EQUAL")
+ assert.Equal(t, invert, false)
+ assert.Equal(t, err, nil)
+}
+
+func TestCommaSeparatedQueryStringsToMap(t *testing.T) {
+ m, err := CommaSeparatedQueryToMap("foo=7,bar!=stuff, x = 5, y= 27", true)
+ assert.Equal(t, err, nil)
+ assert.Equal(t, m["foo"], "=7")
+ assert.Equal(t, m["bar"], "!=stuff")
+ assert.Equal(t, m["x"], "= 5")
+ assert.Equal(t, m["y"], "= 27")
+}
+
+func TestTypeConvert(t *testing.T) {
+ conn, descriptor, err := InitReflectionClient()
+ assert.Equal(t, err, nil)
+ defer conn.Close()
+
+ v, err := TypeConvert(descriptor, "Site", "id", "7")
+ assert.Equal(t, err, nil)
+ assert.Equal(t, v, int32(7))
+
+ v, err = TypeConvert(descriptor, "Site", "name", "foo")
+ assert.Equal(t, err, nil)
+ assert.Equal(t, v, "foo")
+
+ v, err = TypeConvert(descriptor, "Site", "enacted", "123.4")
+ assert.Equal(t, err, nil)
+ assert.Equal(t, v, 123.4)
+}
+
+func TestCheckModelName(t *testing.T) {
+ conn, descriptor, err := InitReflectionClient()
+ assert.Equal(t, err, nil)
+ defer conn.Close()
+
+ err = CheckModelName(descriptor, "Slice")
+ assert.Equal(t, err, nil)
+
+ err = CheckModelName(descriptor, "DoesNotExist")
+ assert.Equal(t, err.Error(), "Model DoesNotExist does not exist. Use `cordctl models available` to get a list of available models")
+}
+
+func TestCreateModel(t *testing.T) {
+ conn, descriptor, err := InitReflectionClient()
+ assert.Equal(t, err, nil)
+ defer conn.Close()
+
+ m := make(map[string]interface{})
+ m["name"] = "mockslice3"
+ m["site_id"] = int32(1)
+
+ err = CreateModel(conn, descriptor, "Slice", m)
+ assert.Equal(t, err, nil)
+
+ assert.Equal(t, m["id"], int32(3))
+}
+
+func TestUpdateModel(t *testing.T) {
+ conn, descriptor, err := InitReflectionClient()
+ assert.Equal(t, err, nil)
+ defer conn.Close()
+
+ m := make(map[string]interface{})
+ m["id"] = int32(1)
+ m["name"] = "mockslice1_newname"
+
+ err = UpdateModel(conn, descriptor, "Slice", m)
+ assert.Equal(t, err, nil)
+}
+
+func TestGetModel(t *testing.T) {
+ conn, descriptor, err := InitReflectionClient()
+ assert.Equal(t, err, nil)
+ defer conn.Close()
+
+ m, err := GetModel(context.Background(), conn, descriptor, "Slice", int32(1))
+ assert.Equal(t, err, nil)
+
+ assert.Equal(t, m.GetFieldByName("id").(int32), int32(1))
+ assert.Equal(t, m.GetFieldByName("name").(string), "mockslice1")
+}
+
+func TestListModels(t *testing.T) {
+ conn, descriptor, err := InitReflectionClient()
+ assert.Equal(t, err, nil)
+ defer conn.Close()
+
+ m, err := ListModels(context.Background(), conn, descriptor, "Slice")
+ assert.Equal(t, err, nil)
+
+ assert.Equal(t, len(m), 2)
+ assert.Equal(t, m[0].GetFieldByName("id").(int32), int32(1))
+ assert.Equal(t, m[0].GetFieldByName("name").(string), "mockslice1")
+ assert.Equal(t, m[1].GetFieldByName("id").(int32), int32(2))
+ assert.Equal(t, m[1].GetFieldByName("name").(string), "mockslice2")
+}
+
+func TestFilterModels(t *testing.T) {
+ conn, descriptor, err := InitReflectionClient()
+ assert.Equal(t, err, nil)
+ defer conn.Close()
+
+ qm := map[string]string{"id": "=1"}
+
+ m, err := FilterModels(context.Background(), conn, descriptor, "Slice", qm)
+ assert.Equal(t, err, nil)
+
+ assert.Equal(t, len(m), 1)
+ assert.Equal(t, m[0].GetFieldByName("id").(int32), int32(1))
+ assert.Equal(t, m[0].GetFieldByName("name").(string), "mockslice1")
+}
+
+func TestDeleteModel(t *testing.T) {
+ conn, descriptor, err := InitReflectionClient()
+ assert.Equal(t, err, nil)
+ defer conn.Close()
+
+ err = DeleteModel(conn, descriptor, "Slice", int32(1))
+ assert.Equal(t, err, nil)
+}
diff --git a/commands/services.go b/commands/services.go
index 99d39c0..e46dac6 100644
--- a/commands/services.go
+++ b/commands/services.go
@@ -21,7 +21,6 @@
"github.com/fullstorydev/grpcurl"
flags "github.com/jessevdk/go-flags"
"github.com/jhump/protoreflect/dynamic"
- //"github.com/opencord/cordctl/format"
)
const (
@@ -49,25 +48,19 @@
}
func (options *ServiceList) Execute(args []string) error {
-
- conn, err := NewConnection()
+ conn, descriptor, err := InitReflectionClient()
if err != nil {
return err
}
defer conn.Close()
- descriptor, method, err := GetReflectionMethod(conn, "xos.dynamicload.GetLoadStatus")
- if err != nil {
- return err
- }
-
ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
defer cancel()
headers := GenerateHeaders()
h := &RpcEventHandler{}
- err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, headers, h, h.GetParams)
+ err = grpcurl.InvokeRPC(ctx, descriptor, conn, "xos.dynamicload.GetLoadStatus", headers, h, h.GetParams)
if err != nil {
return err
}
diff --git a/commands/services_test.go b/commands/services_test.go
new file mode 100644
index 0000000..3b213bf
--- /dev/null
+++ b/commands/services_test.go
@@ -0,0 +1,101 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * 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 commands
+
+import (
+ "bytes"
+ "github.com/opencord/cordctl/testutils"
+ "testing"
+)
+
+func TestServicesList(t *testing.T) {
+ // use `python -m json.tool` to pretty-print json
+ expected := `[
+ {
+ "name": "onos",
+ "state": "present",
+ "version": "2.1.1-dev"
+ },
+ {
+ "name": "kubernetes",
+ "state": "present",
+ "version": "1.2.1"
+ }
+ ]`
+
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options ServiceOpts
+ options.List.OutputAs = "json"
+ err := options.List.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertJSONEqual(t, got.String(), expected)
+}
+
+func TestServicesListTable(t *testing.T) {
+ // We'll use the ServicesList command to be our end-to-end test for
+ // table formatted commands, as the output is relatively simple.
+ expected := `NAME VERSION STATE
+onos 2.1.1-dev present
+kubernetes 1.2.1 present
+`
+
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options ServiceOpts
+ err := options.List.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertStringEqual(t, got.String(), expected)
+}
+
+func TestServicesListYaml(t *testing.T) {
+ // We'll use the ServicesList command to be our end-to-end test for
+ // yaml formatted commands, as the output is relatively simple.
+ expected := `- name: onos
+ version: 2.1.1-dev
+ state: present
+- name: kubernetes
+ version: 1.2.1
+ state: present
+`
+
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options ServiceOpts
+ options.List.OutputAs = "yaml"
+ err := options.List.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertStringEqual(t, got.String(), expected)
+}
diff --git a/commands/transfer_test.go b/commands/transfer_test.go
new file mode 100644
index 0000000..71b7d8e
--- /dev/null
+++ b/commands/transfer_test.go
@@ -0,0 +1,83 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * 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 commands
+
+import (
+ "bytes"
+ "github.com/opencord/cordctl/testutils"
+ "io/ioutil"
+ "testing"
+)
+
+func TestDownload(t *testing.T) {
+ // use `python -m json.tool` to pretty-print json
+ expected := `[
+ {
+ "bytes": 6,
+ "checksum": "sha256:e9c0f8b575cbfcb42ab3b78ecc87efa3b011d9a5d10b09fa4e96f240bf6a82f5",
+ "chunks": 2,
+ "status": "SUCCESS"
+ }
+ ]`
+
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options TransferOpts
+ options.Download.OutputAs = "json"
+ options.Download.Args.LocalFileName = "/tmp/transfer.down"
+ options.Download.Args.URI = "file:///tmp/transfer.down"
+ err := options.Download.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertJSONEqual(t, got.String(), expected)
+}
+
+func TestUpload(t *testing.T) {
+ // use `python -m json.tool` to pretty-print json
+ expected := `[
+ {
+ "bytes": 6,
+ "checksum": "sha256:e9c0f8b575cbfcb42ab3b78ecc87efa3b011d9a5d10b09fa4e96f240bf6a82f5",
+ "chunks": 2,
+ "status": "SUCCESS"
+ }
+ ]`
+
+ err := ioutil.WriteFile("/tmp/transfer.up", []byte("ABCDEF"), 0644)
+
+ got := new(bytes.Buffer)
+ OutputStream = got
+
+ var options TransferOpts
+ options.Upload.OutputAs = "json"
+ options.Upload.Args.LocalFileName = "/tmp/transfer.up"
+ options.Upload.Args.URI = "file:///tmp/transfer.up"
+ options.Upload.ChunkSize = 3
+ err = options.Upload.Execute([]string{})
+
+ if err != nil {
+ t.Errorf("%s: Received error %v", t.Name(), err)
+ return
+ }
+
+ testutils.AssertJSONEqual(t, got.String(), expected)
+}