mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-16 19:49:56 +00:00
* [management] Copy private field on shallowCloneMapping added test to ensure clone handles new fields * Remove unnecessary debug logs from proxy service * Increase Wasm binary size limit to 60MB in build validation
89 lines
2.7 KiB
Go
89 lines
2.7 KiB
Go
package grpc
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/netbirdio/netbird/shared/management/proto"
|
|
)
|
|
|
|
// authTokenField is the only per-proxy field that shallowCloneMapping must NOT
|
|
// copy from the source, since callers assign it individually after cloning.
|
|
const authTokenField = "AuthToken"
|
|
|
|
// TestShallowCloneMapping_ClonesAllFields populates every exported field of
|
|
// ProxyMapping with a non-zero value and verifies the clone carries each one
|
|
// (except AuthToken). It uses reflection so adding a new field to ProxyMapping
|
|
// without updating shallowCloneMapping fails this test.
|
|
func TestShallowCloneMapping_ClonesAllFields(t *testing.T) {
|
|
src := &proto.ProxyMapping{}
|
|
populated := populateExportedFields(t, reflect.ValueOf(src).Elem())
|
|
require.NotEmpty(t, populated, "ProxyMapping should expose fields to populate")
|
|
|
|
clone := shallowCloneMapping(src)
|
|
require.NotNil(t, clone, "clone must not be nil")
|
|
|
|
srcVal := reflect.ValueOf(src).Elem()
|
|
cloneVal := reflect.ValueOf(clone).Elem()
|
|
|
|
for _, name := range populated {
|
|
srcField := srcVal.FieldByName(name).Interface()
|
|
cloneField := cloneVal.FieldByName(name).Interface()
|
|
|
|
if name == authTokenField {
|
|
assert.Zero(t, cloneField, "AuthToken must not be cloned; it is set per proxy after cloning")
|
|
continue
|
|
}
|
|
|
|
assert.Equal(t, srcField, cloneField, "field %s must be carried over by shallowCloneMapping", name)
|
|
}
|
|
}
|
|
|
|
// populateExportedFields sets a non-zero value on every settable exported field
|
|
// of the struct and returns their names.
|
|
func populateExportedFields(t *testing.T, v reflect.Value) []string {
|
|
t.Helper()
|
|
|
|
var names []string
|
|
typ := v.Type()
|
|
for i := 0; i < v.NumField(); i++ {
|
|
field := v.Field(i)
|
|
structField := typ.Field(i)
|
|
|
|
if structField.PkgPath != "" || !field.CanSet() {
|
|
continue
|
|
}
|
|
|
|
setNonZero(t, field, structField.Name)
|
|
names = append(names, structField.Name)
|
|
}
|
|
return names
|
|
}
|
|
|
|
// setNonZero assigns a deterministic non-zero value based on the field kind.
|
|
func setNonZero(t *testing.T, field reflect.Value, name string) {
|
|
t.Helper()
|
|
|
|
switch field.Kind() {
|
|
case reflect.String:
|
|
field.SetString("non-zero-" + name)
|
|
case reflect.Bool:
|
|
field.SetBool(true)
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
field.SetInt(7)
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
field.SetUint(7)
|
|
case reflect.Ptr:
|
|
field.Set(reflect.New(field.Type().Elem()))
|
|
case reflect.Slice:
|
|
field.Set(reflect.MakeSlice(field.Type(), 1, 1))
|
|
case reflect.Map:
|
|
field.Set(reflect.MakeMapWithSize(field.Type(), 0))
|
|
default:
|
|
t.Fatalf("unhandled field kind %s for field %s; extend setNonZero", field.Kind(), name)
|
|
}
|
|
}
|