Import of https://github.com/ciena/voltctl at commit 40d61fbf3f910ed4017cf67c9c79e8e1f82a33a5

Change-Id: I8464c59e60d76cb8612891db3303878975b5416c
diff --git a/pkg/format/formatter_test.go b/pkg/format/formatter_test.go
new file mode 100644
index 0000000..0819f22
--- /dev/null
+++ b/pkg/format/formatter_test.go
@@ -0,0 +1,155 @@
+/*
+ * 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 format
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+)
+
+type TestSubStructure struct {
+	Value string
+}
+
+type TestStructure struct {
+	Field1 string
+	Field2 *string
+	Field3 bool
+	Field4 int
+	Field5 []string
+	Field6 [][]string
+	Field7 TestSubStructure
+	Field8 []TestSubStructure
+	Field9 *TestSubStructure
+}
+
+func generateTestData(rows int) []TestStructure {
+	data := make([]TestStructure, rows)
+
+	abc := "abc"
+	for i := 0; i < rows; i += 1 {
+		data[i].Field1 = fmt.Sprintf("0x%05x", i)
+		data[i].Field2 = &abc
+		if i%2 == 0 {
+			data[i].Field3 = true
+		}
+		data[i].Field4 = i
+		data[i].Field5 = []string{"a", "b", "c", "d"}
+		data[i].Field6 = [][]string{{"x", "y", "z"}}
+		data[i].Field7.Value = "abc"
+		data[i].Field8 = []TestSubStructure{{Value: "abc"}}
+		data[i].Field9 = &TestSubStructure{Value: "abc"}
+	}
+	return data
+}
+
+func TestTableFormat(t *testing.T) {
+	expected := "" +
+		"FIELD1     FIELD2    FIELD3    FIELD4    FIELD5       FIELD6       VALUE    FIELD8     FIELD9\n" +
+		"0x00000    abc       true      0         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00001    abc       false     1         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00002    abc       true      2         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00003    abc       false     3         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00004    abc       true      4         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00005    abc       false     5         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00006    abc       true      6         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00007    abc       false     7         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00008    abc       true      8         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n" +
+		"0x00009    abc       false     9         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n"
+	got := &strings.Builder{}
+	format := Format("table{{.Field1}}\t{{.Field2}}\t{{.Field3}}\t{{.Field4}}\t{{.Field5}}\t{{.Field6}}\t{{.Field7.Value}}\t{{.Field8}}\t{{.Field9}}")
+	data := generateTestData(10)
+	err := format.Execute(got, true, 1, data)
+	if err != nil {
+		t.Errorf("%s: unexpected error result: %s", t.Name(), err)
+	}
+	if got.String() != expected {
+		t.Logf("RECEIVED:\n%s\n", got.String())
+		t.Logf("EXPECTED:\n%s\n", expected)
+		t.Errorf("%s: expected and received did not match", t.Name())
+	}
+}
+
+func TestNoTableFormat(t *testing.T) {
+	expected := "" +
+		"0x00000,abc,true,0,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00001,abc,false,1,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00002,abc,true,2,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00003,abc,false,3,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00004,abc,true,4,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00005,abc,false,5,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00006,abc,true,6,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00007,abc,false,7,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00008,abc,true,8,[a b c d],[[x y z]],abc,[{abc}],{abc}\n" +
+		"0x00009,abc,false,9,[a b c d],[[x y z]],abc,[{abc}],{abc}\n"
+	got := &strings.Builder{}
+	format := Format("{{.Field1}},{{.Field2}},{{.Field3}},{{.Field4}},{{.Field5}},{{.Field6}},{{.Field7.Value}},{{.Field8}},{{.Field9}}")
+	data := generateTestData(10)
+	err := format.Execute(got, false, 0, data)
+	if err != nil {
+		t.Errorf("%s: unexpected error result: %s", t.Name(), err)
+	}
+	if got.String() != expected {
+		t.Logf("RECEIVED:\n%s\n", got.String())
+		t.Logf("EXPECTED:\n%s\n", expected)
+		t.Errorf("%s: expected and received did not match", t.Name())
+	}
+}
+
+func TestTableSingleFormat(t *testing.T) {
+	expected := "" +
+		"FIELD1     FIELD2    FIELD3    FIELD4    FIELD5       FIELD6       VALUE    FIELD8     FIELD9\n" +
+		"0x00000    abc       true      0         [a b c d]    [[x y z]]    abc      [{abc}]    {abc}\n"
+	got := &strings.Builder{}
+	format := Format("table{{.Field1}}\t{{.Field2}}\t{{.Field3}}\t{{.Field4}}\t{{.Field5}}\t{{.Field6}}\t{{.Field7.Value}}\t{{.Field8}}\t{{.Field9}}")
+	data := generateTestData(1)
+	err := format.Execute(got, true, 1, data[0])
+	if err != nil {
+		t.Errorf("%s: unexpected error result: %s", t.Name(), err)
+	}
+	if got.String() != expected {
+		t.Logf("RECEIVED:\n%s\n", got.String())
+		t.Logf("EXPECTED:\n%s\n", expected)
+		t.Errorf("%s: expected and received did not match", t.Name())
+	}
+}
+
+func TestNoTableSingleFormat(t *testing.T) {
+	expected := "0x00000,abc,true,0,[a b c d],[[x y z]],abc,[{abc}],{abc}\n"
+	got := &strings.Builder{}
+	format := Format("{{.Field1}},{{.Field2}},{{.Field3}},{{.Field4}},{{.Field5}},{{.Field6}},{{.Field7.Value}},{{.Field8}},{{.Field9}}")
+	data := generateTestData(1)
+	err := format.Execute(got, false, 0, data[0])
+	if err != nil {
+		t.Errorf("%s: unexpected error result: %s", t.Name(), err)
+	}
+	if got.String() != expected {
+		t.Logf("RECEIVED:\n%s\n", got.String())
+		t.Logf("EXPECTED:\n%s\n", expected)
+		t.Errorf("%s: expected and received did not match", t.Name())
+	}
+}
+
+func TestBadFormat(t *testing.T) {
+	format := Format("table{{.Field1}\t{{.Field2}}\t{{.Field3}}\t{{.Field4}}\t{{.Field5}}\t{{.Field6}}\t{{.Field7.Value}}\t{{.Field8}}\t{{.Field9}}")
+	got := &strings.Builder{}
+	data := generateTestData(10)
+	err := format.Execute(got, true, 0, data)
+	if err == nil {
+		t.Errorf("%s: expected error (bad format) got none", t.Name())
+	}
+}