func equal()

in processor/lsmintervalprocessor/internal/data/datatest/equal.go [75:149]


func equal(tb testing.TB, want, got any, name string) bool {
	tb.Helper()
	require.IsType(tb, want, got)

	vw := reflect.ValueOf(want)
	vg := reflect.ValueOf(got)

	if vw.Kind() != reflect.Struct {
		ok := compare.Equal(want, got)
		if !ok {
			tb.Errorf("%s: %+v != %+v", name, want, got)
		}
		return ok
	}

	ok := true
	// compare all "getters" of the struct
	for i := 0; i < vw.NumMethod(); i++ {
		mname := vw.Type().Method(i).Name
		fname := strings.TrimPrefix(name+"."+mname+"()", ".")

		mw := vw.Method(i)
		mg := vg.Method(i)

		// only compare "getters"
		if mw.Type().NumIn() != 0 || mw.Type().NumOut() != 1 {
			continue
		}

		// skip equality check for methods returning functions
		ret := mw.Type().Out(0)
		if ret.Kind() == reflect.Func {
			continue
		}

		// Append(Empty) fails above heuristic, exclude it
		if strings.HasPrefix(mname, "Append") || strings.HasPrefix(mname, "Clone") {
			continue
		}

		rw := mw.Call(nil)[0].Interface()
		rg := mg.Call(nil)[0].Interface()

		ok = equal(tb, rw, rg, fname) && ok
	}

	// compare all exported fields of the struct
	for i := 0; i < vw.NumField(); i++ {
		if !vw.Type().Field(i).IsExported() {
			continue
		}
		fname := name + "." + vw.Type().Field(i).Name
		fw := vw.Field(i).Interface()
		fg := vg.Field(i).Interface()
		ok = equal(tb, fw, fg, fname) && ok
	}
	if !ok {
		return false
	}

	if _, ok := want.(expo.DataPoint); ok {
		err := pmetrictest.CompareExponentialHistogramDataPoint(want.(expo.DataPoint), got.(expo.DataPoint))
		if err != nil {
			tb.Error(err)
		}
	}

	// fallback to a full deep-equal for rare cases (unexported fields, etc)
	if diff := compare.Diff(want, got); diff != "" {
		tb.Error(diff)
		return false
	}

	return true
}