Sfoglia il codice sorgente

use empty structs, pre-size array during dedupe (#3041)

* use empty structs, pre-size array during dedupe

Signed-off-by: Alex Meijer <alexander.meijer@ibm.com>

* add testing

Signed-off-by: Alex Meijer <alexander.meijer@ibm.com>

---------

Signed-off-by: Alex Meijer <alexander.meijer@ibm.com>
Alex Meijer 1 anno fa
parent
commit
47c4b68175
2 ha cambiato i file con 67 aggiunte e 7 eliminazioni
  1. 7 7
      pkg/costmodel/costmodel.go
  2. 60 0
      pkg/costmodel/costmodel_test.go

+ 7 - 7
pkg/costmodel/costmodel.go

@@ -1628,8 +1628,8 @@ func pruneDuplicates(s []string) []string {
 	for _, v := range s {
 		if strings.Contains(v, "_") {
 			name := strings.Replace(v, "_", "-", -1)
-			if !m[name] {
-				m[name] = true
+			if _, found := m[name]; !found {
+				m[name] = struct{}{}
 			}
 			delete(m, v)
 		}
@@ -1638,16 +1638,16 @@ func pruneDuplicates(s []string) []string {
 	return setToSlice(m)
 }
 
-// Creates a map[string]bool containing the slice values as keys
-func sliceToSet(s []string) map[string]bool {
-	m := make(map[string]bool)
+// Creates a map[string]struct{} containing the slice values as keys
+func sliceToSet(s []string) map[string]struct{} {
+	m := make(map[string]struct{}, len(s))
 	for _, v := range s {
-		m[v] = true
+		m[v] = struct{}{}
 	}
 	return m
 }
 
-func setToSlice(m map[string]bool) []string {
+func setToSlice(m map[string]struct{}) []string {
 	var result []string
 	for k := range m {
 		result = append(result, k)

+ 60 - 0
pkg/costmodel/costmodel_test.go

@@ -1,6 +1,7 @@
 package costmodel
 
 import (
+	"slices"
 	"testing"
 
 	"github.com/opencost/opencost/core/pkg/util"
@@ -10,6 +11,65 @@ import (
 	"k8s.io/apimachinery/pkg/api/resource"
 )
 
+func TestPruneDuplicates(t *testing.T) {
+
+	tests := []struct {
+		name     string
+		input    []string
+		expected []string
+	}{
+		{
+			name:     "empty slice",
+			input:    []string{},
+			expected: []string{},
+		},
+		{
+			name:     "single element slice",
+			input:    []string{"test1"},
+			expected: []string{"test1"},
+		},
+		{
+			name:     "basic duplicate",
+			input:    []string{"test1", "test1"},
+			expected: []string{"test1"},
+		},
+		{
+			name:     "compound duplicate",
+			input:    []string{"test1", "test2", "test1", "test2"},
+			expected: []string{"test1", "test2"},
+		},
+		{
+			name:     "mixture of duplicate/ no duplicate",
+			input:    []string{"test1", "test2", "test1", "test2", "test3"},
+			expected: []string{"test1", "test2", "test3"},
+		},
+		{
+			name:     "underscore sanitization",
+			input:    []string{"test_1", "test_2", "test_1", "test_2", "test_3"},
+			expected: []string{"test-1", "test-2", "test-3"},
+		},
+		{
+			name:     "underscore sanitization II",
+			input:    []string{"test-1", "test_2", "test_1", "test_2", "test_3"},
+			expected: []string{"test-1", "test-2", "test-3"},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			actual := pruneDuplicates(tt.expected)
+			slices.Sort(actual)
+			expected := tt.expected
+			slices.Sort(expected)
+
+			if !slices.Equal(actual, expected) {
+				t.Fatalf("test failuire for case %s. Expected %v, got %v", tt.name, expected, actual)
+			}
+		})
+	}
+
+}
+
 func TestGetGPUCount(t *testing.T) {
 	tests := []struct {
 		name          string