chore: move the go code into a subfolder

This commit is contained in:
Florian Forster
2025-08-05 15:20:32 -07:00
parent 4ad22ba456
commit cd2921de26
2978 changed files with 373 additions and 300 deletions

View File

@@ -0,0 +1,103 @@
package test
import (
"reflect"
"github.com/stretchr/testify/assert"
)
func AssertMapContains[M ~map[K]V, K comparable, V any](t assert.TestingT, m M, key K, expectedValue V) {
val, exists := m[key]
assert.True(t, exists, "Key '%s' should exist in the map", key)
if !exists {
return
}
assert.Equal(t, expectedValue, val, "Key '%s' should have value '%d'", key, expectedValue)
}
// PartiallyDeepEqual is similar to reflect.DeepEqual,
// but only compares exported non-zero fields of the expectedValue
func PartiallyDeepEqual(expected, actual interface{}) bool {
if expected == nil {
return actual == nil
}
if actual == nil {
return false
}
return partiallyDeepEqual(reflect.ValueOf(expected), reflect.ValueOf(actual))
}
func partiallyDeepEqual(expected, actual reflect.Value) bool {
// Dereference pointers if needed
if expected.Kind() == reflect.Ptr {
if expected.IsNil() {
return true
}
expected = expected.Elem()
}
if actual.Kind() == reflect.Ptr {
if actual.IsNil() {
return false
}
actual = actual.Elem()
}
if expected.Type() != actual.Type() {
return false
}
switch expected.Kind() { //nolint:exhaustive
case reflect.Struct:
for i := 0; i < expected.NumField(); i++ {
field := expected.Type().Field(i)
if field.PkgPath != "" { // Skip unexported fields
continue
}
expectedField := expected.Field(i)
actualField := actual.Field(i)
// Skip zero-value fields in expected
if reflect.DeepEqual(expectedField.Interface(), reflect.Zero(expectedField.Type()).Interface()) {
continue
}
// Compare fields recursively
if !partiallyDeepEqual(expectedField, actualField) {
return false
}
}
return true
case reflect.Slice, reflect.Array:
if expected.Len() > actual.Len() {
return false
}
for i := 0; i < expected.Len(); i++ {
if !partiallyDeepEqual(expected.Index(i), actual.Index(i)) {
return false
}
}
return true
default:
// Compare primitive types
return reflect.DeepEqual(expected.Interface(), actual.Interface())
}
}
func Must[T any](result T, error error) T {
if error != nil {
panic(error)
}
return result
}

View File

@@ -0,0 +1,153 @@
package test
import "testing"
func TestPartiallyDeepEqual(t *testing.T) {
type SecondaryNestedType struct {
Value int
}
type NestedType struct {
Value int
ValueSlice []int
Nested SecondaryNestedType
NestedPointer *SecondaryNestedType
}
type args struct {
expected interface{}
actual interface{}
}
tests := []struct {
name string
args args
want bool
}{
{
name: "nil",
args: args{
expected: nil,
actual: nil,
},
want: true,
},
{
name: "scalar value",
args: args{
expected: 10,
actual: 10,
},
want: true,
},
{
name: "different scalar value",
args: args{
expected: 11,
actual: 10,
},
want: false,
},
{
name: "string value",
args: args{
expected: "foo",
actual: "foo",
},
want: true,
},
{
name: "different string value",
args: args{
expected: "foo2",
actual: "foo",
},
want: false,
},
{
name: "scalar only set in actual",
args: args{
expected: &SecondaryNestedType{},
actual: &SecondaryNestedType{Value: 10},
},
want: true,
},
{
name: "scalar equal",
args: args{
expected: &SecondaryNestedType{Value: 10},
actual: &SecondaryNestedType{Value: 10},
},
want: true,
},
{
name: "scalar only set in expected",
args: args{
expected: &SecondaryNestedType{Value: 10},
actual: &SecondaryNestedType{},
},
want: false,
},
{
name: "ptr only set in expected",
args: args{
expected: &NestedType{NestedPointer: &SecondaryNestedType{Value: 10}},
actual: &NestedType{},
},
want: false,
},
{
name: "ptr only set in actual",
args: args{
expected: &NestedType{},
actual: &NestedType{NestedPointer: &SecondaryNestedType{Value: 10}},
},
want: true,
},
{
name: "ptr equal",
args: args{
expected: &NestedType{NestedPointer: &SecondaryNestedType{Value: 10}},
actual: &NestedType{NestedPointer: &SecondaryNestedType{Value: 10}},
},
want: true,
},
{
name: "nested equal",
args: args{
expected: &NestedType{Nested: SecondaryNestedType{Value: 10}},
actual: &NestedType{Nested: SecondaryNestedType{Value: 10}},
},
want: true,
},
{
name: "slice equal",
args: args{
expected: &NestedType{ValueSlice: []int{10, 20}},
actual: &NestedType{ValueSlice: []int{10, 20}},
},
want: true,
},
{
name: "slice additional in expected",
args: args{
expected: &NestedType{ValueSlice: []int{10, 20, 30}},
actual: &NestedType{ValueSlice: []int{10, 20}},
},
want: false,
},
{
name: "slice additional in actual",
args: args{
expected: &NestedType{ValueSlice: []int{10, 20}},
actual: &NestedType{ValueSlice: []int{10, 20, 30}},
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := PartiallyDeepEqual(tt.args.expected, tt.args.actual); got != tt.want {
t.Errorf("PartiallyDeepEqual() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -0,0 +1,168 @@
package test
import (
"reflect"
"sort"
"strings"
)
// testingT is a wrapper for testing.T
//
// this wrapper is needed for internal testing
type testingT interface {
Errorf(format string, args ...interface{})
Helper()
}
func AssertFieldsMapped(t testingT, object interface{}, ignoreFields ...string) (failed bool) {
t.Helper()
val := reflect.ValueOf(object)
fields := BuildList(val)
notEmptyFields := validateEmptyFields(fields, ignoreFields)
if len(notEmptyFields) > 0 {
sort.Strings(notEmptyFields)
t.Errorf("expected fields are not empty:\n\t%s\n", strings.Join(notEmptyFields, ",\n\t"))
}
notFilledFields := validateFilledFields(fields)
if len(notFilledFields) > 0 {
sort.Strings(notFilledFields)
t.Errorf("unexpected empty fields:\n\t%s\n", strings.Join(notFilledFields, ",\n\t"))
}
return len(notEmptyFields) > 0 || len(notFilledFields) > 0
}
func BuildList(val reflect.Value) map[string]bool {
if val.Kind() == reflect.Ptr {
if val.IsNil() {
return nil
}
val = reflect.Indirect(val)
}
fields := map[string]bool{}
for i := 0; i < val.NumField(); i++ {
if !isPublicField(val.Type().Field(i).Name) {
continue
}
if val.Field(i).Kind() == reflect.Struct || val.Field(i).Kind() == reflect.Ptr {
fieldName := val.Type().Field(i).Name
fields[fieldName] = false
subFields := BuildList(val.Field(i))
for k, v := range subFields {
fields[fieldName+"."+k] = v
fields[fieldName] = fields[val.Type().Field(i).Name] || v
}
if len(subFields) == 0 &&
((val.Field(i).Kind() == reflect.Ptr && !val.Field(i).IsNil()) ||
val.Field(i).Kind() == reflect.Struct && !val.Field(i).IsZero()) {
fields[fieldName] = true
}
} else {
fields[val.Type().Field(i).Name] = isFieldFilled(val.Field(i))
}
}
return fields
}
func isPublicField(fieldName string) bool {
return fieldName[0] >= 'A' && fieldName[0] <= 'Z'
}
func isFieldFilled(val reflect.Value) bool {
if isLengthMeasurable(val) {
switch val.Kind() {
case reflect.Slice:
if val.IsNil() {
return false
}
fallthrough
case reflect.Array:
if val.Len() == 0 {
return false
}
for i := 0; i < val.Len(); i++ {
if val.Index(i).IsZero() {
return false
}
}
return true
case reflect.Map:
if val.Len() == 0 {
return false
}
for _, key := range val.MapKeys() {
if val.MapIndex(key).IsZero() {
return false
}
}
return true
}
}
return !val.IsZero()
}
func isLengthMeasurable(val reflect.Value) bool {
return val.Kind() == reflect.Slice ||
val.Kind() == reflect.Array ||
val.Kind() == reflect.Map
}
func validateEmptyFields(fields map[string]bool, emptyFields []string) (notEmptyFields []string) {
for _, emptyField := range emptyFields {
isFilled := fields[emptyField]
subs := subFields(fields, emptyField)
if isFilled {
filledFields := filledSubFields(fields, subs)
if len(filledFields) == 0 {
filledFields = append(filledFields, emptyField)
}
notEmptyFields = append(notEmptyFields, filledFields...)
}
fields = removeFields(fields, append([]string{emptyField}, subs...))
}
return notEmptyFields
}
func filledSubFields(fields map[string]bool, subFields []string) (filledSubs []string) {
for _, subField := range subFields {
if fields[subField] {
filledSubs = append(filledSubs, subField)
}
}
return filledSubs
}
func subFields(fields map[string]bool, parentName string) (subs []string) {
for fieldName := range fields {
if strings.HasPrefix(fieldName, parentName+".") {
subs = append(subs, fieldName)
}
}
return subs
}
func removeFields(fields map[string]bool, fieldNames []string) map[string]bool {
for _, fieldName := range fieldNames {
delete(fields, fieldName)
}
return fields
}
func validateFilledFields(fields map[string]bool) (emptyFields []string) {
for fieldName, isFilled := range fields {
if !isFilled {
emptyFields = append(emptyFields, fieldName)
}
}
return emptyFields
}

View File

@@ -0,0 +1,306 @@
package test
import (
"sort"
"strings"
"testing"
"time"
)
func TestCheckAllFieldsIgnores(t *testing.T) {
type args struct {
object interface{}
ignoredFields []string
}
type res struct {
mock *mappedExpecter
}
tests := []struct {
name string
args args
res res
}{
{
name: "simple struct",
args: args{
object: &struct {
Company string
}{
Company: "caos AG",
},
ignoredFields: []string{"Company"},
},
res: res{
mock: newMappedExpeter(
[]string{"Company"},
nil,
),
},
},
{
name: "simple struct with private",
args: args{
object: &struct {
Company string
priv bool
}{
Company: "caos AG",
priv: true,
},
ignoredFields: []string{"Company"},
},
res: res{
mock: newMappedExpeter(
[]string{"Company"},
nil,
),
},
},
{
name: "simple struct length",
args: args{
object: &struct {
Company map[string]string
priv bool
}{
Company: map[string]string{"caos AG": "ZITADEL"},
priv: true,
},
ignoredFields: []string{"Company"},
},
res: res{
mock: newMappedExpeter(
[]string{"Company"},
nil,
),
},
},
{
name: "ignore empty nested field",
args: args{
object: &struct {
Company *struct {
Name string
Founded time.Time
}
priv bool
}{
Company: &struct {
Name string
Founded time.Time
}{},
priv: true,
},
ignoredFields: []string{"Company"},
},
res: res{
mock: newMappedExpeter(
nil,
nil,
),
},
},
{
name: "ignore nested field",
args: args{
object: &struct {
Company *struct {
Name string
Founded time.Time
}
priv bool
}{
Company: &struct {
Name string
Founded time.Time
}{
Founded: time.Date(2019, time.April, 1, 1, 1, 1, 1, time.Local),
},
priv: true,
},
ignoredFields: []string{"Company.Founded"},
},
res: res{
mock: newMappedExpeter(
[]string{"Company.Founded"},
[]string{"Company.Name"},
),
},
},
{
name: "ignore nested fields",
args: args{
object: &struct {
Company *struct {
Name string
Founded time.Time
}
priv bool
}{
Company: &struct {
Name string
Founded time.Time
}{
Name: "caos AG",
Founded: time.Date(2019, time.April, 1, 1, 1, 1, 1, time.Local),
},
priv: true,
},
ignoredFields: []string{"Company"},
},
res: res{
mock: newMappedExpeter(
[]string{"Company.Name", "Company.Founded"},
nil,
),
},
},
{
name: "ignore nested struct first field filled",
args: args{
object: &struct {
Nested
Priv bool
}{
Nested: Nested{
ID: "1",
},
Priv: true,
},
ignoredFields: []string{"Nested"},
},
res: res{
mock: newMappedExpeter(
[]string{"Nested.ID"},
nil,
),
},
},
{
name: "ignore nested struct second field filled",
args: args{
object: &struct {
Nested
Priv bool
}{
Nested: Nested{
ID: "",
Seq: 134,
},
Priv: true,
},
ignoredFields: []string{"Nested"},
},
res: res{
mock: newMappedExpeter(
[]string{"Nested.Seq"},
nil,
),
},
},
{
name: "ignore nested struct last field filled",
args: args{
object: &struct {
Nested
Priv bool
}{
Nested: Nested{
Seq2: 134,
},
Priv: true,
},
ignoredFields: []string{"Nested"},
},
res: res{
mock: newMappedExpeter(
[]string{"Nested.Seq2"},
nil,
),
},
},
{
name: "ignore not nested field",
args: args{
object: &struct {
Number int
Company *struct {
Name string
Founded time.Time
}
priv bool
}{
Number: 13,
Company: &struct {
Name string
Founded time.Time
}{
Name: "caos AG",
Founded: time.Date(2019, time.April, 1, 0, 0, 0, 0, time.Local),
},
priv: true,
},
ignoredFields: []string{"Number"},
},
res: res{
mock: newMappedExpeter(
[]string{"Number"},
nil,
),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
AssertFieldsMapped(tt.res.mock, tt.args.object, tt.args.ignoredFields...)
tt.res.mock.expectationsMet(t)
})
}
}
type Nested struct {
ID string
Seq uint64
Seq2 uint64
}
func newMappedExpeter(expectedNotEmptyFields, expectedNotFilledFields []string) *mappedExpecter {
sort.Strings(expectedNotEmptyFields)
sort.Strings(expectedNotFilledFields)
return &mappedExpecter{
expectedNotEmptyFields: strings.Join(expectedNotEmptyFields, ",\n\t"),
expectedNotFilledFields: strings.Join(expectedNotFilledFields, ",\n\t"),
}
}
type mappedExpecter struct {
expectedNotEmptyFields string
expectedNotFilledFields string
notEmptyFields string
notFilledFields string
}
func (e *mappedExpecter) Errorf(format string, args ...interface{}) {
if format == "expected fields are not empty:\n\t%s\n" {
e.notEmptyFields = args[0].(string)
}
if format == "unexpected empty fields:\n\t%s\n" {
e.notFilledFields = args[0].(string)
}
}
func (e *mappedExpecter) Helper() {}
func (e *mappedExpecter) expectationsMet(t *testing.T) {
if e.notEmptyFields != e.expectedNotEmptyFields {
t.Errorf("not empty fields not matched: \n expected:\n\t%s\n got:\n\t%s", e.expectedNotEmptyFields, e.notEmptyFields)
}
if e.notFilledFields != e.expectedNotFilledFields {
t.Errorf("not filled fields not matched: \n expected:\n\t%s\n got:\n\t%s", e.expectedNotFilledFields, e.notFilledFields)
}
}