-
Notifications
You must be signed in to change notification settings - Fork 19
fix: add function for proper bytearray to base64 encoding #3548
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
54110ff
2753631
4502061
7f3f460
524e633
af6488f
da7124e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,6 +1,7 @@ | ||||||||||||||
package utils | ||||||||||||||
|
||||||||||||||
import ( | ||||||||||||||
"encoding/base64" | ||||||||||||||
"testing" | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
|
@@ -37,3 +38,166 @@ func TestContainsInt(t *testing.T) { | |||||||||||||
t.Fatalf("Should not be contained") | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// Test struct for YAML conversion testing | ||||||||||||||
type TestServer struct { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
doesn't need to be exposed I guess There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...or just move the struct definition into the |
||||||||||||||
Name string `json:"name"` | ||||||||||||||
UserData *[]byte `json:"userData,omitempty"` | ||||||||||||||
Data []byte `json:"data,omitempty"` | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
func TestConvertByteArraysToBase64(t *testing.T) { | ||||||||||||||
tests := []struct { | ||||||||||||||
name string | ||||||||||||||
input interface{} | ||||||||||||||
expectedFields map[string]interface{} | ||||||||||||||
expectError bool | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You have no test case in your table test where I would say either add some test cases which are expected to exit with an error or get rid of this input. |
||||||||||||||
}{ | ||||||||||||||
{ | ||||||||||||||
name: "nil input", | ||||||||||||||
input: nil, | ||||||||||||||
expectError: false, | ||||||||||||||
}, | ||||||||||||||
{ | ||||||||||||||
name: "normal case with byte arrays", | ||||||||||||||
input: TestServer{ | ||||||||||||||
Name: "test-server", | ||||||||||||||
UserData: func() *[]byte { b := []byte("hello world"); return &b }(), | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
stackit-sdk-go/core/utils/utils.go Lines 3 to 6 in 0b4638e
|
||||||||||||||
Data: []byte("test data"), | ||||||||||||||
}, | ||||||||||||||
expectedFields: map[string]interface{}{ | ||||||||||||||
"name": "test-server", | ||||||||||||||
"userData": base64.StdEncoding.EncodeToString([]byte("hello world")), | ||||||||||||||
"data": base64.StdEncoding.EncodeToString([]byte("test data")), | ||||||||||||||
}, | ||||||||||||||
expectError: false, | ||||||||||||||
}, | ||||||||||||||
{ | ||||||||||||||
name: "nil pointer case", | ||||||||||||||
input: TestServer{ | ||||||||||||||
Name: "test-server", | ||||||||||||||
UserData: nil, | ||||||||||||||
Data: []byte("test"), | ||||||||||||||
}, | ||||||||||||||
expectedFields: map[string]interface{}{ | ||||||||||||||
"name": "test-server", | ||||||||||||||
"data": base64.StdEncoding.EncodeToString([]byte("test")), | ||||||||||||||
}, | ||||||||||||||
expectError: false, | ||||||||||||||
}, | ||||||||||||||
{ | ||||||||||||||
name: "empty byte array case", | ||||||||||||||
input: TestServer{ | ||||||||||||||
Name: "test-server", | ||||||||||||||
Data: []byte{}, | ||||||||||||||
}, | ||||||||||||||
expectedFields: map[string]interface{}{ | ||||||||||||||
"name": "test-server", | ||||||||||||||
// Note: empty byte arrays are omitted from JSON output | ||||||||||||||
}, | ||||||||||||||
expectError: false, | ||||||||||||||
}, | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
for _, tt := range tests { | ||||||||||||||
t.Run(tt.name, func(t *testing.T) { | ||||||||||||||
result, err := ConvertByteArraysToBase64(tt.input) | ||||||||||||||
|
||||||||||||||
if tt.expectError { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should handle all cases without needing 3 if conditions 😄 |
||||||||||||||
if err == nil { | ||||||||||||||
t.Fatalf("Expected error but got none") | ||||||||||||||
} | ||||||||||||||
return | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
if err != nil { | ||||||||||||||
t.Fatalf("Expected no error, got: %v", err) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// Special case for nil input | ||||||||||||||
if tt.input == nil { | ||||||||||||||
if result != nil { | ||||||||||||||
t.Fatalf("Expected nil result for nil input, got: %v", result) | ||||||||||||||
} | ||||||||||||||
return | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why stop the test case only because the input is nil? |
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// Check expected fields | ||||||||||||||
for fieldName, expectedValue := range tt.expectedFields { | ||||||||||||||
if actualValue, exists := result[fieldName]; !exists { | ||||||||||||||
// For empty byte arrays, the field might be omitted from JSON | ||||||||||||||
if fieldName == "data" && expectedValue == nil { | ||||||||||||||
t.Logf("Empty byte array was omitted from JSON output, which is expected") | ||||||||||||||
continue | ||||||||||||||
} | ||||||||||||||
t.Fatalf("Expected field %s to exist, but it doesn't", fieldName) | ||||||||||||||
} else if actualValue != expectedValue { | ||||||||||||||
t.Fatalf("Expected field %s to be %v, got %v", fieldName, expectedValue, actualValue) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// Check that no unexpected fields exist (except for omitted empty byte arrays) | ||||||||||||||
for fieldName, actualValue := range result { | ||||||||||||||
if _, expected := tt.expectedFields[fieldName]; !expected { | ||||||||||||||
// Allow data field to exist even if not in expectedFields (for empty byte array case) | ||||||||||||||
if fieldName == "data" && tt.name == "empty byte array case" { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems weird to me checking for test case names here. Any reason? |
||||||||||||||
continue | ||||||||||||||
} | ||||||||||||||
t.Fatalf("Unexpected field %s with value %v", fieldName, actualValue) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
}) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
func TestConvertByteArraysToBase64Recursive(t *testing.T) { | ||||||||||||||
tests := []struct { | ||||||||||||||
name string | ||||||||||||||
input interface{} | ||||||||||||||
expected string // check if []byte was converted to base64 string | ||||||||||||||
}{ | ||||||||||||||
{"nil", nil, ""}, | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||
{"map with []byte", map[string]interface{}{"data": []byte("hello")}, "aGVsbG8="}, | ||||||||||||||
{"slice with []byte", []interface{}{[]byte("test")}, "dGVzdA=="}, | ||||||||||||||
{"nested map", map[string]interface{}{"level": map[string]interface{}{"data": []byte("nested")}}, "bmVzdGVk"}, | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please format the input for the table test properly. {
name: "nested map",
input: map[string]interface{}{
"level": map[string]interface{}{
"data": []byte("nested")
},
},
expected: "bmVzdGVk"
}, Maybe it's just me, but I'm having a really hard time to get the goal of this PR in it's current state. |
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
for _, tt := range tests { | ||||||||||||||
t.Run(tt.name, func(t *testing.T) { | ||||||||||||||
convertByteArraysToBase64Recursive(tt.input) | ||||||||||||||
|
||||||||||||||
if tt.expected == "" { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this skip of the further checks needed? |
||||||||||||||
return | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// check if base64 string in the result | ||||||||||||||
found := findBase64String(tt.input) | ||||||||||||||
if found != tt.expected { | ||||||||||||||
t.Fatalf("Expected %s, got %s", tt.expected, found) | ||||||||||||||
} | ||||||||||||||
}) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// helper to find base64 string in interface{} | ||||||||||||||
func findBase64String(data interface{}) string { | ||||||||||||||
switch v := data.(type) { | ||||||||||||||
case map[string]interface{}: | ||||||||||||||
for _, val := range v { | ||||||||||||||
if str := findBase64String(val); str != "" { | ||||||||||||||
return str | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
case []interface{}: | ||||||||||||||
for _, val := range v { | ||||||||||||||
if str := findBase64String(val); str != "" { | ||||||||||||||
return str | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
case string: | ||||||||||||||
if v != "" && v != "hello" && v != "test" && v != "nested" { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hardcoded values? 🤔 |
||||||||||||||
return v | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
return "" | ||||||||||||||
} |
Uh oh!
There was an error while loading. Please reload this page.