From c62b9b76afa1c15f96fb31f3ef6c63e738c52850 Mon Sep 17 00:00:00 2001 From: vrenzolaverace Date: Sun, 6 Nov 2022 23:40:45 +0100 Subject: [PATCH] Update mapsutil #13 (#14) * Update mapsutil #13 * refactoring clear func * adding clear's tests * fixing execs on windows * run sh only on unix system Co-authored-by: Mzack9999 --- exec/executil.go | 4 ++ exec/executil_test.go | 6 ++ maps/mapsutil.go | 37 +++++++++-- maps/mapsutil_test.go | 149 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 180 insertions(+), 16 deletions(-) diff --git a/exec/executil.go b/exec/executil.go index d13bf39..4bd4358 100644 --- a/exec/executil.go +++ b/exec/executil.go @@ -4,6 +4,7 @@ import ( "errors" "io" "os/exec" + "runtime" ) const ( @@ -105,6 +106,9 @@ func splitCmdArgs(cmds string) []string { // Run the specified command and return the output func Run(cmd string) (string, error) { + if runtime.GOOS == "windows" { + return "", errors.New("can't execute sh on windows platform") + } return RunSh(splitCmdArgs(cmd)...) } diff --git a/exec/executil_test.go b/exec/executil_test.go index 266b8db..e01a0a3 100644 --- a/exec/executil_test.go +++ b/exec/executil_test.go @@ -18,6 +18,9 @@ func init() { } func TestRun(t *testing.T) { + if runtime.GOOS == "windows" { + return + } // try to run the echo command s, err := Run("echo test") require.Nil(t, err, "failed execution", err) @@ -25,6 +28,9 @@ func TestRun(t *testing.T) { } func TestRunSh(t *testing.T) { + if runtime.GOOS == "windows" { + return + } // try to run the echo command s, err := RunSh("echo", "test") require.Nil(t, err, "failed execution", err) diff --git a/maps/mapsutil.go b/maps/mapsutil.go index 803bd97..c719b46 100644 --- a/maps/mapsutil.go +++ b/maps/mapsutil.go @@ -10,13 +10,14 @@ import ( "time" "github.com/miekg/dns" + "golang.org/x/exp/maps" extmaps "golang.org/x/exp/maps" ) -// MergeMaps merges the inputted maps into a new one. +// Merge merges the inputted maps into a new one. // Be aware: In case of duplicated keys in multiple maps, // the one ending in the result is unknown a priori. -func MergeMaps[K comparable, V any](maps ...map[K]V) (result map[K]V) { +func Merge[K comparable, V any](maps ...map[K]V) (result map[K]V) { result = make(map[K]V) for _, m := range maps { @@ -102,8 +103,8 @@ func DNSToMap(msg *dns.Msg, format string) (m map[string]interface{}) { return m } -// HTTPRequesToMap Converts HTTP Request to Matcher Map -func HTTPRequesToMap(req *http.Request) (map[string]interface{}, error) { +// HTTPRequestToMap Converts HTTP Request to Matcher Map +func HTTPRequestToMap(req *http.Request) (map[string]interface{}, error) { m := make(map[string]interface{}) var headers string for k, v := range req.Header { @@ -224,3 +225,31 @@ func Walk(m map[string]any, callback func(k string, v any)) { } } } + +// Clear the map passed as parameter +func Clear[K comparable, V any](mm ...map[K]V) { + for _, m := range mm { + maps.Clear(m) + } +} + +// SliceToMap returns a map having as keys the elements in +// even positions and as values the elements in odd positions. +// If the number of elements is odd the default value applies. +func SliceToMap[T comparable](s []T, dflt T) map[T]T { + result := map[T]T{} + + for i := 0; i < len(s); i += 2 { + if i+1 < len(s) { + result[s[i]] = s[i+1] + } else { + result[s[i]] = dflt + } + } + return result +} + +// IsEmpty checks if a map is empty. +func IsEmpty[K comparable, V any](m map[K]V) bool { + return len(m) == 0 +} diff --git a/maps/mapsutil_test.go b/maps/mapsutil_test.go index 55cbdf0..3efab17 100644 --- a/maps/mapsutil_test.go +++ b/maps/mapsutil_test.go @@ -1,7 +1,13 @@ package mapsutil import ( + "crypto/tls" + "io" + "net/http" + "net/url" + "strings" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -10,31 +16,89 @@ func TestMergeMaps(t *testing.T) { m1Str := map[string]interface{}{"a": 1, "b": 2} m2Str := map[string]interface{}{"b": 2, "c": 3} rStr := map[string]interface{}{"a": 1, "b": 2, "c": 3} - rrStr := MergeMaps(m1Str, m2Str) + rrStr := Merge(m1Str, m2Str) require.EqualValues(t, rStr, rrStr) m1Int := map[int]interface{}{1: 1, 2: 2} m2Int := map[int]interface{}{1: 1, 2: 2, 3: 3, 4: 4} m3Int := map[int]interface{}{1: 1, 5: 5} rInt := map[int]interface{}{1: 1, 2: 2, 3: 3, 4: 4, 5: 5} - rrInt := MergeMaps(m1Int, m2Int, m3Int) + rrInt := Merge(m1Int, m2Int, m3Int) require.EqualValues(t, rInt, rrInt) } +var ( + req = &http.Request{ + Method: "POST", + URL: &url.URL{ + Scheme: "http", + Host: "test.ts", + Path: "/", + }, + Host: "test.ts", + Proto: "HTTP/1.1", + ProtoMajor: 2, + ProtoMinor: 1, + Header: http.Header{}, + Body: io.NopCloser(strings.NewReader("test")), + ContentLength: 1000, + TransferEncoding: []string{""}, + Close: true, + Trailer: http.Header{}, + TLS: &tls.ConnectionState{}, + } + + resp = &http.Response{ + Status: "200 OK", + StatusCode: 200, + Proto: "HTTP/1.1", + ProtoMajor: 2, + ProtoMinor: 1, + Header: http.Header{}, + Body: io.NopCloser(strings.NewReader("test")), + ContentLength: 1000, + TransferEncoding: []string{""}, + Close: true, + Uncompressed: false, + Trailer: http.Header{}, + Request: &http.Request{}, + TLS: &tls.ConnectionState{}, + } +) + func TestHTTPToMap(t *testing.T) { - // not implemented + bufBody := new(strings.Builder) + // nolint:errcheck + io.Copy(bufBody, resp.Body) + + bufHeaders := new(strings.Builder) + // nolint:errcheck + io.Copy(bufHeaders, resp.Body) + + m := HTTPToMap(resp, bufBody.String(), bufHeaders.String(), time.Duration(2), "") + + require.NotNil(t, m) + require.NotEmpty(t, m) } func TestDNSToMap(t *testing.T) { // not implemented } -func TestHTTPRequesToMap(t *testing.T) { - // not implemented +func TestHTTPRequestToMap(t *testing.T) { + m, err := HTTPRequestToMap(req) + + require.Nil(t, err) + require.NotNil(t, m) + require.NotEmpty(t, m) } func TestHTTPResponseToMap(t *testing.T) { - // not implemented + m, err := HTTPResponseToMap(resp) + + require.Nil(t, err) + require.NotNil(t, m) + require.NotEmpty(t, m) } func TestGetKeys(t *testing.T) { @@ -45,17 +109,17 @@ func TestGetKeys(t *testing.T) { t.Run("GetKeys(string)", func(t *testing.T) { got := GetKeys(map[string]interface{}{"a": "a", "b": "b"}) - require.EqualValues(t, []string{"a", "b"}, got) + require.ElementsMatch(t, []string{"a", "b"}, got) }) t.Run("GetKeys(int)", func(t *testing.T) { got := GetKeys(map[int]interface{}{1: "a", 2: "b"}) - require.EqualValues(t, []int{1, 2}, got) + require.ElementsMatch(t, []int{1, 2}, got) }) t.Run("GetKeys(bool)", func(t *testing.T) { got := GetKeys(map[bool]interface{}{true: "a", false: "b"}) - require.EqualValues(t, []bool{true, false}, got) + require.ElementsMatch(t, []bool{true, false}, got) }) } @@ -67,17 +131,17 @@ func TestGetValues(t *testing.T) { t.Run("GetValues(string)", func(t *testing.T) { got := GetValues(map[string]interface{}{"a": "a", "b": "b"}) - require.EqualValues(t, []interface{}{"a", "b"}, got) + require.ElementsMatch(t, []interface{}{"a", "b"}, got) }) t.Run("GetValues(int)", func(t *testing.T) { got := GetValues(map[string]interface{}{"a": 1, "b": 2}) - require.EqualValues(t, []interface{}{1, 2}, got) + require.ElementsMatch(t, []interface{}{1, 2}, got) }) t.Run("GetValues(bool)", func(t *testing.T) { got := GetValues(map[string]interface{}{"a": true, "b": false}) - require.EqualValues(t, []interface{}{true, false}, got) + require.ElementsMatch(t, []interface{}{true, false}, got) }) } @@ -102,3 +166,64 @@ func TestDifference(t *testing.T) { require.EqualValues(t, map[bool]interface{}{false: 2}, got) }) } + +func TestSliceToMap(t *testing.T) { + t.Run("SliceToMap(empty)", func(t *testing.T) { + got := SliceToMap([]string{}, "") + require.EqualValues(t, map[string]string{}, got) + }) + + t.Run("SliceToMap(string)", func(t *testing.T) { + got := SliceToMap([]string{"a", "b", "c", "d"}, "") + require.EqualValues(t, map[string]string{"a": "b", "c": "d"}, got) + }) + + t.Run("SliceToMap(string odd)", func(t *testing.T) { + got := SliceToMap([]string{"a", "b", "c"}, "") + require.EqualValues(t, map[string]string{"a": "b", "c": ""}, got) + }) + + t.Run("SliceToMap(int odd)", func(t *testing.T) { + got := SliceToMap([]int{1, 2, 3}, 0) + require.EqualValues(t, map[int]int{1: 2, 3: 0}, got) + }) +} + +func TestIsEmpty(t *testing.T) { + t.Run("IsEmpty(empty)", func(t *testing.T) { + got := IsEmpty(map[string]string{}) + require.EqualValues(t, true, got) + }) + + t.Run("IsEmpty(string)", func(t *testing.T) { + got := IsEmpty(map[string]string{"a": "b"}) + require.EqualValues(t, false, got) + }) + + t.Run("IsEmpty(int)", func(t *testing.T) { + got := IsEmpty(map[int]int{1: 2}) + require.EqualValues(t, false, got) + }) +} + +func TestClear(t *testing.T) { + t.Run("Clear(nil)", func(t *testing.T) { + var m map[string]string + Clear(m) + require.Empty(t, m) + }) + + t.Run("Clear(m)", func(t *testing.T) { + m := map[string]string{"a": "a", "b": "b"} + Clear(m) + require.Empty(t, m) + }) + + t.Run("Clear(m1,m2)", func(t *testing.T) { + m1 := map[string]string{"a": "a", "b": "b"} + m2 := map[string]string{"a": "a", "b": "b"} + Clear(m1, m2) + require.Empty(t, m1) + require.Empty(t, m2) + }) +}