Make describe output for envvars deterministic

As `describe` uses a map to store the env var kv pairs its output varies
in its order.  This is undesirable.

This change introduces a means by which env var output ordering is
predictable.

Signed-off-by: Richard Gee <richard@technologee.co.uk>
This commit is contained in:
Richard Gee
2022-09-24 21:40:48 +01:00
committed by Alex Ellis
parent e390a02607
commit 35fcca5759
2 changed files with 76 additions and 0 deletions

View File

@@ -9,6 +9,7 @@ import (
"io"
"os"
"reflect"
"sort"
"strconv"
"strings"
"text/tabwriter"
@@ -225,6 +226,15 @@ func printMap(w io.Writer, name string, m map[string]string, verbose bool) {
}
fmt.Fprintf(w, "%s:\n", name)
if name == "Environment" {
orderedKeys := generateMapOrder(m)
for _, keyName := range orderedKeys {
fmt.Fprintln(w, "\t "+keyName+": "+m[keyName])
}
return
}
for key, value := range m {
fmt.Fprintln(w, "\t "+key+": "+value)
}
@@ -286,3 +296,16 @@ func isEmpty(a interface{}) bool {
}
return false
}
func generateMapOrder(m map[string]string) []string {
var keyNames []string
for keyName := range m {
keyNames = append(keyNames, keyName)
}
sort.Strings(keyNames)
return keyNames
}

View File

@@ -148,3 +148,56 @@ func TestDescribeOuput(t *testing.T) {
})
}
}
func TestGenerateMapOrder(t *testing.T) {
var generateMapOrderTestcases = []struct {
Name string
Input map[string]string
Output []string
expectFail bool
}{
{
Name: "One item",
Input: map[string]string{
"AAA": "aaa",
},
Output: []string{"AAA"},
expectFail: false,
},
{
Name: "Multiple items",
Input: map[string]string{
"AAA": "aaa",
"BBB": "bbb",
"CCC": "ccc",
"DDD": "ddd",
},
Output: []string{"AAA", "BBB", "CCC", "DDD"},
expectFail: false,
},
{
Name: "Multiple items but use a value",
Input: map[string]string{
"AAA": "aaa",
"BBB": "bbb",
"CCC": "ccc",
"DDD": "ddd",
},
Output: []string{"AAA", "BBB", "CCC", "ddd"},
expectFail: true,
},
}
for _, testcase := range generateMapOrderTestcases {
orderedSlice := generateMapOrder(testcase.Input)
if len(orderedSlice) != len(testcase.Output) {
t.Errorf("Slice sizes do not match: %s", testcase.Name)
t.Fail()
}
for i, v := range testcase.Output {
if v != orderedSlice[i] && !testcase.expectFail {
t.Errorf("Exected %s got %s: %s", v, orderedSlice[i], testcase.Name)
t.Fail()
}
}
}
}