diff --git a/utbot-go/go-samples/simple/samples_go_ut_test.go b/utbot-go/go-samples/simple/samples_go_ut_test.go index df8435cf74..46b38d9b2d 100644 --- a/utbot-go/go-samples/simple/samples_go_ut_test.go +++ b/utbot-go/go-samples/simple/samples_go_ut_test.go @@ -46,29 +46,29 @@ func TestGenerateArrayOfIntegersByUtGoFuzzer(t *testing.T) { } func TestDistanceBetweenTwoPointsByUtGoFuzzer(t *testing.T) { - actualVal := DistanceBetweenTwoPoints(Point{x: 0.730967787376657, y: 0.730967787376657}, Point{x: 2.0, y: 2.0}) + actualVal := DistanceBetweenTwoPoints(Point{}, Point{}) - assert.Equal(t, 1.794682566180269, actualVal) + assert.Equal(t, 0.0, actualVal) } func TestGetCoordinatesOfMiddleBetweenTwoPointsByUtGoFuzzer(t *testing.T) { - actualVal0, actualVal1 := GetCoordinatesOfMiddleBetweenTwoPoints(Point{x: 0.24053641567148587, y: 0.24053641567148587}, Point{x: 2.0, y: 2.0}) + actualVal0, actualVal1 := GetCoordinatesOfMiddleBetweenTwoPoints(Point{}, Point{}) assertMultiple := assert.New(t) - assertMultiple.Equal(1.1202682078357429, actualVal0) - assertMultiple.Equal(1.1202682078357429, actualVal1) + assertMultiple.Equal(0.0, actualVal0) + assertMultiple.Equal(0.0, actualVal1) } func TestGetCoordinateSumOfPointsByUtGoFuzzer(t *testing.T) { - actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{x: 0.6374174253501083, y: 0.6374174253501083}}) + actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{}}) assertMultiple := assert.New(t) - assertMultiple.Equal(0.6374174253501083, actualVal0) - assertMultiple.Equal(0.6374174253501083, actualVal1) + assertMultiple.Equal(0.0, actualVal0) + assertMultiple.Equal(0.0, actualVal1) } func TestGetAreaOfCircleByUtGoFuzzer(t *testing.T) { - actualVal := GetAreaOfCircle(Circle{Center: Point{x: 0.5504370051176339, y: 0.5504370051176339}, Radius: 2.0}) + actualVal := GetAreaOfCircle(Circle{Center: Point{}, Radius: 2.0}) assert.Equal(t, 12.566370614359172, actualVal) } @@ -155,4 +155,4 @@ func TestStringSearchByUtGoFuzzer5(t *testing.T) { actualVal := StringSearch("ABC") assert.Equal(t, true, actualVal) -} +} \ No newline at end of file diff --git a/utbot-go/go-samples/simple/supported_types.go b/utbot-go/go-samples/simple/supported_types.go index fac4dde4d7..5c9dc8909d 100644 --- a/utbot-go/go-samples/simple/supported_types.go +++ b/utbot-go/go-samples/simple/supported_types.go @@ -219,3 +219,46 @@ func SliceOfArrayOfInt(slice [][5]int) [][5]int { func ExportedStructWithEmbeddedUnexportedStruct(exportedStruct nested.ExportedStruct) nested.ExportedStruct { return exportedStruct } + +type Type byte + +func NamedType(n Type) Type { + return n +} + +func ArrayOfNamedType(array [5]Type) [5]Type { + return array +} + +type T [5][5]Type + +func ArrayOfArrayOfNamedType(array [5][5]Type) T { + return array +} + +func SliceOfNamedType(slice []Type) []Type { + return slice +} + +type NA [5]uintptr + +func NamedArray(array NA) NA { + return array +} + +type NS []int + +func NamedSlice(slice NS) NS { + return slice +} + +type S struct { + t Type + T + n NA + NS +} + +func StructWithFieldsOfNamedTypes(s S) S { + return s +} diff --git a/utbot-go/go-samples/simple/supported_types_go_ut_test.go b/utbot-go/go-samples/simple/supported_types_go_ut_test.go index 94ebfa7ad7..239c75f358 100644 --- a/utbot-go/go-samples/simple/supported_types_go_ut_test.go +++ b/utbot-go/go-samples/simple/supported_types_go_ut_test.go @@ -4,7 +4,6 @@ import ( "github.com/pmezard/go-difflib/difflib" "github.com/stretchr/testify/assert" "go-samples/simple/nested" - "math" "testing" ) @@ -109,27 +108,27 @@ func TestUintPtrByUtGoFuzzer(t *testing.T) { } func TestFloat32ByUtGoFuzzer(t *testing.T) { - actualVal := Float32(0.73096776) + actualVal := Float32(0.24053639) - assert.Equal(t, float32(0.73096776), actualVal) + assert.Equal(t, float32(0.24053639), actualVal) } func TestFloat64ByUtGoFuzzer(t *testing.T) { - actualVal := Float64(0.8314409887870612) + actualVal := Float64(0.6063452159973596) - assert.Equal(t, 0.8314409887870612, actualVal) + assert.Equal(t, 0.6063452159973596, actualVal) } func TestComplex64ByUtGoFuzzer(t *testing.T) { - actualVal := Complex64(complex(0.6063452, 0.6063452)) + actualVal := Complex64(complex(0.30905056, 0.30905056)) - assert.Equal(t, complex(float32(0.6063452), float32(0.6063452)), actualVal) + assert.Equal(t, complex(float32(0.30905056), float32(0.30905056)), actualVal) } func TestComplex128ByUtGoFuzzer(t *testing.T) { - actualVal := Complex128(complex(0.6374174253501083, 0.6374174253501083)) + actualVal := Complex128(complex(0.5504370051176339, 0.5504370051176339)) - assert.Equal(t, complex(0.6374174253501083, 0.6374174253501083), actualVal) + assert.Equal(t, complex(0.5504370051176339, 0.5504370051176339), actualVal) } func TestByteByUtGoFuzzer(t *testing.T) { @@ -157,15 +156,15 @@ func TestBoolByUtGoFuzzer(t *testing.T) { } func TestStructByUtGoFuzzer(t *testing.T) { - actualVal := Struct(Structure{int: -1, int8: 1, int16: 32767, int32: -1, int64: -1, uint: 18446744073709551615, uint8: 0, uint16: 1, uint32: 0, uint64: 18446744073709551615, uintptr: 18446744073709551615, float32: 0.550437, float64: 0.11700660880722513, complex64: complex(0.550437, 0.550437), complex128: complex(0.11700660880722513, 0.11700660880722513), byte: 0, rune: -1, string: "", bool: false}) + actualVal := Struct(Structure{}) - assert.Equal(t, Structure{int: -1, int8: 1, int16: 32767, int32: -1, int64: -1, uint: 18446744073709551615, uint8: 0, uint16: 1, uint32: 0, uint64: 18446744073709551615, uintptr: 18446744073709551615, float32: 0.550437, float64: 0.11700660880722513, complex64: complex(float32(0.550437), float32(0.550437)), complex128: complex(0.11700660880722513, 0.11700660880722513), byte: 0, rune: -1, string: "", bool: false}, actualVal) + assert.Equal(t, Structure{}, actualVal) } func TestStructWithNanByUtGoFuzzer(t *testing.T) { - actualVal := StructWithNan(Structure{int: -1, int8: 1, int16: 32767, int32: -1, int64: -1, uint: 18446744073709551615, uint8: 0, uint16: 1, uint32: 0, uint64: 18446744073709551615, uintptr: 18446744073709551615, float32: 0.7815346, float64: 0.3332183994766498, complex64: complex(0.7815346, 0.7815346), complex128: complex(0.3332183994766498, 0.3332183994766498), byte: 0, rune: -1, string: "", bool: false}) + actualVal := StructWithNan(Structure{}) - assert.NotEqual(t, Structure{int: -1, int8: 1, int16: 32767, int32: -1, int64: -1, uint: 18446744073709551615, uint8: 0, uint16: 1, uint32: 0, uint64: 18446744073709551615, uintptr: 18446744073709551615, float32: 0.7815346, float64: math.NaN(), complex64: complex(float32(0.7815346), float32(0.7815346)), complex128: complex(0.3332183994766498, 0.3332183994766498), byte: 0, rune: -1, string: "", bool: false}, actualVal) + assert.NotEqual(t, Structure{}, actualVal) } func TestArrayOfIntByUtGoFuzzer(t *testing.T) { @@ -187,15 +186,15 @@ func TestArrayOfStringByUtGoFuzzer(t *testing.T) { } func TestArrayOfStructsByUtGoFuzzer(t *testing.T) { - actualVal := ArrayOfStructs([10]Structure{{int: -1, int8: 0, int16: -1, int32: -1, int64: -9223372036854775808, uint: 1, uint8: 0, uint16: 65535, uint32: 1, uint64: 18446744073709551615, uintptr: 1, float32: 0.38518918, float64: 0.6130357680446138, complex64: complex(0.38518918, 0.38518918), complex128: complex(0.6130357680446138, 0.6130357680446138), byte: 255, rune: 2147483647, string: "", bool: false}, {}, {}, {}, {}, {}, {}, {}, {}, {}}) + actualVal := ArrayOfStructs([10]Structure{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}) - assert.Equal(t, [10]Structure{{int: -1, int8: 0, int16: -1, int32: -1, int64: -9223372036854775808, uint: 1, uint8: 0, uint16: 65535, uint32: 1, uint64: 18446744073709551615, uintptr: 1, float32: 0.38518918, float64: 0.6130357680446138, complex64: complex(float32(0.38518918), float32(0.38518918)), complex128: complex(0.6130357680446138, 0.6130357680446138), byte: 255, rune: 2147483647, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}}, actualVal) + assert.Equal(t, [10]Structure{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}, actualVal) } func TestArrayOfStructsWithNanByUtGoFuzzer(t *testing.T) { - actualVal := ArrayOfStructsWithNan([10]Structure{{int: 1, int8: 0, int16: -1, int32: -1, int64: -9223372036854775808, uint: 1, uint8: 0, uint16: 65535, uint32: 1, uint64: 18446744073709551615, uintptr: 1, float32: 0.9828195, float64: 0.8791825178724801, complex64: complex(0.9828195, 0.9828195), complex128: complex(0.8791825178724801, 0.8791825178724801), byte: 255, rune: 2147483647, string: "", bool: false}, {}, {}, {}, {}, {}, {}, {}, {}, {}}) + actualVal := ArrayOfStructsWithNan([10]Structure{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}) - assert.NotEqual(t, [10]Structure{{int: 1, int8: 0, int16: -1, int32: -1, int64: -9223372036854775808, uint: 1, uint8: 0, uint16: 65535, uint32: 1, uint64: 18446744073709551615, uintptr: 1, float32: 0.9828195, float64: math.NaN(), complex64: complex(float32(0.9828195), float32(0.9828195)), complex128: complex(0.8791825178724801, 0.8791825178724801), byte: 255, rune: 2147483647, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}}, actualVal) + assert.NotEqual(t, [10]Structure{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}, actualVal) } func TestArrayOfArrayOfUintByUtGoFuzzer(t *testing.T) { @@ -207,7 +206,7 @@ func TestArrayOfArrayOfUintByUtGoFuzzer(t *testing.T) { func TestArrayOfArrayOfStructsByUtGoFuzzer(t *testing.T) { actualVal := ArrayOfArrayOfStructs([5][5]Structure{{{}, {}, {}, {}, {}}, {{}, {}, {}, {}, {}}, {{}, {}, {}, {}, {}}, {{}, {}, {}, {}, {}}, {{}, {}, {}, {}, {}}}) - assert.Equal(t, [5][5]Structure{{{int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}}, {{int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}}, {{int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}}, {{int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}}, {{int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}, {int: 0, int8: 0, int16: 0, int32: 0, int64: 0, uint: 0, uint8: 0, uint16: 0, uint32: 0, uint64: 0, uintptr: 0, float32: 0.0, float64: 0.0, complex64: complex(float32(0.0), float32(0.0)), complex128: complex(0.0, 0.0), byte: 0, rune: 0, string: "", bool: false}}}, actualVal) + assert.Equal(t, [5][5]Structure{{{}, {}, {}, {}, {}}, {{}, {}, {}, {}, {}}, {{}, {}, {}, {}, {}}, {{}, {}, {}, {}, {}}, {{}, {}, {}, {}, {}}}, actualVal) } func TestArrayOfSliceOfUintByUtGoFuzzer(t *testing.T) { @@ -229,15 +228,15 @@ func TestReturnErrorOrNilWithNonNilErrorByUtGoFuzzer2(t *testing.T) { } func TestExternalStructByUtGoFuzzer(t *testing.T) { - actualVal := ExternalStruct(difflib.Match{A: 9223372036854775807, B: -1, Size: -9223372036854775808}, Structure{int: -1, int8: 1, int16: -32768, int32: 2147483647, int64: 1, uint: 1, uint8: 1, uint16: 1, uint32: 1, uint64: 18446744073709551615, uintptr: 18446744073709551615, float32: 0.94124913, float64: 0.17597680203548016, complex64: complex(0.94124913, 0.94124913), complex128: complex(0.17597680203548016, 0.17597680203548016), byte: 1, rune: 0, string: "", bool: false}) + actualVal := ExternalStruct(difflib.Match{A: 1, B: 1, Size: 1}, Structure{}) - assert.Equal(t, Structure{int: -1, int8: 1, int16: -32768, int32: 2147483647, int64: 1, uint: 1, uint8: 1, uint16: 1, uint32: 1, uint64: 18446744073709551615, uintptr: 18446744073709551615, float32: 0.94124913, float64: 0.17597680203548016, complex64: complex(float32(0.94124913), float32(0.94124913)), complex128: complex(0.17597680203548016, 0.17597680203548016), byte: 1, rune: 0, string: "", bool: false}, actualVal) + assert.Equal(t, Structure{}, actualVal) } func TestExternalStructWithAliasByUtGoFuzzer(t *testing.T) { - actualVal := ExternalStructWithAlias(difflib.Match{A: 9223372036854775807, B: -1, Size: -9223372036854775808}) + actualVal := ExternalStructWithAlias(difflib.Match{A: 1, B: 1, Size: 1}) - assert.Equal(t, difflib.Match{A: 9223372036854775807, B: -1, Size: -9223372036854775808}, actualVal) + assert.Equal(t, difflib.Match{A: 1, B: 1, Size: 1}, actualVal) } func TestSliceOfIntByUtGoFuzzer(t *testing.T) { @@ -259,15 +258,15 @@ func TestSliceOfStringByUtGoFuzzer(t *testing.T) { } func TestSliceOfStructsByUtGoFuzzer(t *testing.T) { - actualVal := SliceOfStructs([]Structure{{int: -1, int8: 0, int16: -1, int32: -1, int64: -9223372036854775808, uint: 1, uint8: 0, uint16: 65535, uint32: 1, uint64: 18446744073709551615, uintptr: 1, float32: 0.31293595, float64: 0.12889715087377673, complex64: complex(0.31293595, 0.31293595), complex128: complex(0.12889715087377673, 0.12889715087377673), byte: 255, rune: 2147483647, string: "", bool: false}}) + actualVal := SliceOfStructs([]Structure{{}}) - assert.Equal(t, []Structure{{int: -1, int8: 0, int16: -1, int32: -1, int64: -9223372036854775808, uint: 1, uint8: 0, uint16: 65535, uint32: 1, uint64: 18446744073709551615, uintptr: 1, float32: 0.31293595, float64: 0.12889715087377673, complex64: complex(float32(0.31293595), float32(0.31293595)), complex128: complex(0.12889715087377673, 0.12889715087377673), byte: 255, rune: 2147483647, string: "", bool: false}}, actualVal) + assert.Equal(t, []Structure{{}}, actualVal) } func TestSliceOfStructsWithNanByUtGoFuzzer(t *testing.T) { - actualVal := SliceOfStructsWithNan([]Structure{{int: 1, int8: 0, int16: -1, int32: -1, int64: -9223372036854775808, uint: 1, uint8: 0, uint16: 65535, uint32: 1, uint64: 18446744073709551615, uintptr: 1, float32: 0.14660162, float64: 0.7051747444754559, complex64: complex(0.14660162, 0.14660162), complex128: complex(0.7051747444754559, 0.7051747444754559), byte: 255, rune: 2147483647, string: "", bool: false}}) + actualVal := SliceOfStructsWithNan([]Structure{{}}) - assert.NotEqual(t, []Structure{{int: 1, int8: 0, int16: -1, int32: -1, int64: -9223372036854775808, uint: 1, uint8: 0, uint16: 65535, uint32: 1, uint64: 18446744073709551615, uintptr: 1, float32: 0.14660162, float64: math.NaN(), complex64: complex(float32(0.14660162), float32(0.14660162)), complex128: complex(0.7051747444754559, 0.7051747444754559), byte: 255, rune: 2147483647, string: "", bool: false}}, actualVal) + assert.NotEqual(t, []Structure{{}}, actualVal) } func TestSliceOfSliceOfByteByUtGoFuzzer(t *testing.T) { @@ -293,3 +292,45 @@ func TestExportedStructWithEmbeddedUnexportedStructByUtGoFuzzer(t *testing.T) { assert.Equal(t, nested.ExportedStruct{}, actualVal) } + +func TestNamedTypeByUtGoFuzzer(t *testing.T) { + actualVal := NamedType(Type(0)) + + assert.Equal(t, Type(0), actualVal) +} + +func TestArrayOfNamedTypeByUtGoFuzzer(t *testing.T) { + actualVal := ArrayOfNamedType([5]Type{0, 0, 0, 0, 0}) + + assert.Equal(t, [5]Type{0, 0, 0, 0, 0}, actualVal) +} + +func TestArrayOfArrayOfNamedTypeByUtGoFuzzer(t *testing.T) { + actualVal := ArrayOfArrayOfNamedType([5][5]Type{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}) + + assert.Equal(t, T{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, actualVal) +} + +func TestSliceOfNamedTypeByUtGoFuzzer(t *testing.T) { + actualVal := SliceOfNamedType([]Type{0}) + + assert.Equal(t, []Type{0}, actualVal) +} + +func TestNamedArrayByUtGoFuzzer(t *testing.T) { + actualVal := NamedArray(NA{1, 0, 18446744073709551615, 18446744073709551615, 18446744073709551615}) + + assert.Equal(t, NA{1, 0, 18446744073709551615, 18446744073709551615, 18446744073709551615}, actualVal) +} + +func TestNamedSliceByUtGoFuzzer(t *testing.T) { + actualVal := NamedSlice(NS{-1, 9223372036854775807, 9223372036854775807, 1, 9223372036854775807}) + + assert.Equal(t, NS{-1, 9223372036854775807, 9223372036854775807, 1, 9223372036854775807}, actualVal) +} + +func TestStructWithFieldsOfNamedTypesByUtGoFuzzer(t *testing.T) { + actualVal := StructWithFieldsOfNamedTypes(S{T: T{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, NS: NS{9223372036854775807, 1, 0, -9223372036854775808, 9223372036854775807}}) + + assert.Equal(t, S{T: T{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, NS: NS{9223372036854775807, 1, 0, -9223372036854775808, 9223372036854775807}}, actualVal) +} diff --git a/utbot-go/src/main/kotlin/org/utbot/go/GoLanguage.kt b/utbot-go/src/main/kotlin/org/utbot/go/GoLanguage.kt index 5d00f199c2..becfd20495 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/GoLanguage.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/GoLanguage.kt @@ -13,7 +13,9 @@ fun goDefaultValueProviders() = listOf( GoArrayValueProvider, GoSliceValueProvider, GoStructValueProvider, - GoConstantValueProvider + GoConstantValueProvider, + GoNamedValueProvider, + GoNilValueProvider ) class GoInstruction( diff --git a/utbot-go/src/main/kotlin/org/utbot/go/api/GoTypesApi.kt b/utbot-go/src/main/kotlin/org/utbot/go/api/GoTypesApi.kt index c3c8c54423..7d12ae9e0f 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/api/GoTypesApi.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/api/GoTypesApi.kt @@ -1,7 +1,6 @@ package org.utbot.go.api import org.utbot.go.framework.api.go.GoFieldId -import org.utbot.go.framework.api.go.GoNamedTypeId import org.utbot.go.framework.api.go.GoPackage import org.utbot.go.framework.api.go.GoTypeId @@ -29,37 +28,21 @@ class GoPrimitiveTypeId(name: String) : GoTypeId(name) { class GoStructTypeId( name: String, - implementsError: Boolean, - override val sourcePackage: GoPackage, val fields: List, -) : GoNamedTypeId(name, implementsError = implementsError) { - val packageName: String = sourcePackage.packageName - val packagePath: String = sourcePackage.packagePath - override val canonicalName: String = "${sourcePackage.packageName}.$name" +) : GoTypeId(name) { + override val canonicalName: String = name - override fun getRelativeName(destinationPackage: GoPackage, aliases: Map): String { - val alias = aliases[sourcePackage] - return if (sourcePackage == destinationPackage || alias == ".") { - simpleName - } else if (alias == null) { - "${packageName}.${simpleName}" - } else { - "${alias}.${simpleName}" - } - } + override fun getRelativeName(destinationPackage: GoPackage, aliases: Map): String = simpleName override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is GoStructTypeId) return false - return packagePath == other.packagePath && packageName == other.packageName && name == other.name + return fields == other.fields } override fun hashCode(): Int { - var result = packagePath.hashCode() - result = 31 * result + packageName.hashCode() - result = 31 * result + name.hashCode() - return result + return fields.hashCode() } } @@ -91,7 +74,7 @@ class GoSliceTypeId( override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is GoArrayTypeId) return false + if (other !is GoSliceTypeId) return false return elementTypeId == other.elementTypeId } @@ -99,22 +82,40 @@ class GoSliceTypeId( override fun hashCode(): Int = elementTypeId.hashCode() } -class GoInterfaceTypeId( +class GoInterfaceTypeId(name: String) : GoTypeId(name) { + override val canonicalName: String = name + + override fun getRelativeName(destinationPackage: GoPackage, aliases: Map): String = simpleName + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is GoInterfaceTypeId) return false + + return name == other.name + } + + override fun hashCode(): Int = name.hashCode() +} + +class GoNamedTypeId( name: String, - implementsError: Boolean, override val sourcePackage: GoPackage, -) : GoNamedTypeId(name, implementsError = implementsError) { + implementsError: Boolean, + val underlyingTypeId: GoTypeId +) : GoTypeId(name, implementsError = implementsError) { val packageName: String = sourcePackage.packageName val packagePath: String = sourcePackage.packagePath - override val canonicalName: String = if (packageName != "") { - "$packageName.$name" + override val canonicalName: String = if (sourcePackage.isBuiltin) { + name } else { - simpleName + "${sourcePackage.packageName}.$name" } + fun exported(): Boolean = name.first().isUpperCase() + override fun getRelativeName(destinationPackage: GoPackage, aliases: Map): String { val alias = aliases[sourcePackage] - return if (sourcePackage == destinationPackage || alias == ".") { + return if (sourcePackage.isBuiltin || sourcePackage == destinationPackage || alias == ".") { simpleName } else if (alias == null) { "${packageName}.${simpleName}" @@ -125,9 +126,9 @@ class GoInterfaceTypeId( override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is GoInterfaceTypeId) return false + if (other !is GoNamedTypeId) return false - return packagePath == other.packagePath && packageName == other.packageName && name == other.name + return sourcePackage == other.sourcePackage && name == other.name } override fun hashCode(): Int { diff --git a/utbot-go/src/main/kotlin/org/utbot/go/api/GoUtModelsApi.kt b/utbot-go/src/main/kotlin/org/utbot/go/api/GoUtModelsApi.kt index ae3a17a42b..7199cf327b 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/api/GoUtModelsApi.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/api/GoUtModelsApi.kt @@ -47,7 +47,7 @@ class GoUtStructModel( value.filter { typeId.sourcePackage == destinationPackage || it.fieldId.isExported } override fun getRequiredPackages(destinationPackage: GoPackage): Set = - getVisibleFields(destinationPackage).fold(setOf(typeId.sourcePackage)) { acc, fieldModel -> + getVisibleFields(destinationPackage).fold(emptySet()) { acc, fieldModel -> acc + fieldModel.getRequiredPackages(destinationPackage) } @@ -68,14 +68,19 @@ class GoUtArrayModel( get() = super.typeId as GoArrayTypeId override fun getRequiredPackages(destinationPackage: GoPackage): Set { - val elementStructTypeId = typeId.elementTypeId as? GoStructTypeId - val imports = if (elementStructTypeId != null && elementStructTypeId.sourcePackage != destinationPackage) { - mutableSetOf(elementStructTypeId.sourcePackage) - } else { - mutableSetOf() + val elementNamedTypeId = typeId.elementTypeId as? GoNamedTypeId + val imports = + if (elementNamedTypeId != null && + !elementNamedTypeId.sourcePackage.isBuiltin && + elementNamedTypeId.sourcePackage != destinationPackage + ) { + setOf(elementNamedTypeId.sourcePackage) + } else { + emptySet() + } + return value.values.fold(imports) { acc, model -> + acc + model.getRequiredPackages(destinationPackage) } - value.values.map { it.getRequiredPackages(destinationPackage) }.forEach { imports += it } - return imports } override fun isComparable(): Boolean = value.values.all { it.isComparable() } @@ -98,14 +103,19 @@ class GoUtSliceModel( get() = super.typeId as GoSliceTypeId override fun getRequiredPackages(destinationPackage: GoPackage): Set { - val elementStructTypeId = typeId.elementTypeId as? GoStructTypeId - val imports = if (elementStructTypeId != null && elementStructTypeId.sourcePackage != destinationPackage) { - mutableSetOf(elementStructTypeId.sourcePackage) - } else { - mutableSetOf() + val elementNamedTypeId = typeId.elementTypeId as? GoNamedTypeId + val imports = + if (elementNamedTypeId != null && + !elementNamedTypeId.sourcePackage.isBuiltin && + elementNamedTypeId.sourcePackage != destinationPackage + ) { + setOf(elementNamedTypeId.sourcePackage) + } else { + emptySet() + } + return value.values.fold(imports) { acc, model -> + acc + model.getRequiredPackages(destinationPackage) } - value.values.map { it.getRequiredPackages(destinationPackage) }.forEach { imports += it } - return imports } override fun isComparable(): Boolean = value.values.all { it.isComparable() } @@ -167,4 +177,23 @@ class GoUtNilModel( ) : GoUtModel(typeId) { override fun isComparable(): Boolean = true override fun toString() = "nil" +} + +class GoUtNamedModel( + var value: GoUtModel, + typeId: GoNamedTypeId, +) : GoUtModel(typeId) { + override val typeId: GoNamedTypeId + get() = super.typeId as GoNamedTypeId + + override fun getRequiredPackages(destinationPackage: GoPackage): Set { + val import = if (!typeId.sourcePackage.isBuiltin && typeId.sourcePackage != destinationPackage) { + setOf(typeId.sourcePackage) + } else { + emptySet() + } + return import + value.getRequiredPackages(destinationPackage) + } + + override fun isComparable(): Boolean = value.isComparable() } \ No newline at end of file diff --git a/utbot-go/src/main/kotlin/org/utbot/go/api/util/GoTypesApiUtil.kt b/utbot-go/src/main/kotlin/org/utbot/go/api/util/GoTypesApiUtil.kt index 97532c58fa..7578456c94 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/api/util/GoTypesApiUtil.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/api/util/GoTypesApiUtil.kt @@ -148,29 +148,32 @@ fun GoTypeId.goDefaultValueModel(): GoUtModel = when (this) { goStringTypeId -> GoUtPrimitiveModel("", this) goUintPtrTypeId -> GoUtPrimitiveModel(0, this) - else -> error("Go primitive ${this.javaClass} is not supported") + else -> error("Generating Go default value model for ${this.javaClass} is not supported") } is GoStructTypeId -> GoUtStructModel(listOf(), this) is GoArrayTypeId -> GoUtArrayModel(hashMapOf(), this) - is GoSliceTypeId -> GoUtSliceModel(hashMapOf(), this, 0) - else -> GoUtNilModel(this) + is GoSliceTypeId -> GoUtNilModel(this) + is GoNamedTypeId -> GoUtNamedModel(this.underlyingTypeId.goDefaultValueModel(), this) + else -> error("Generating Go default value model for ${this.javaClass} is not supported") } -fun GoTypeId.getAllVisibleStructTypes(goPackage: GoPackage): Set = when (this) { - is GoStructTypeId -> if (this.sourcePackage == goPackage || this.exported()) { - fields.fold(setOf(this)) { acc: Set, field -> - acc + (field.declaringType).getAllVisibleStructTypes(goPackage) - } +fun GoTypeId.getAllVisibleNamedTypes(goPackage: GoPackage): Set = when (this) { + is GoStructTypeId -> fields.fold(emptySet()) { acc: Set, field -> + acc + (field.declaringType).getAllVisibleNamedTypes(goPackage) + } + + is GoArrayTypeId, is GoSliceTypeId -> elementTypeId!!.getAllVisibleNamedTypes(goPackage) + is GoNamedTypeId -> if (this.sourcePackage == goPackage || this.exported()) { + setOf(this) + underlyingTypeId.getAllVisibleNamedTypes(goPackage) } else { emptySet() } - is GoArrayTypeId, is GoSliceTypeId -> elementTypeId!!.getAllVisibleStructTypes(goPackage) else -> emptySet() } -fun List.getAllVisibleStructTypes(goPackage: GoPackage): Set = +fun List.getAllVisibleNamedTypes(goPackage: GoPackage): Set = this.fold(emptySet()) { acc, type -> - acc + type.getAllVisibleStructTypes(goPackage) + acc + type.getAllVisibleNamedTypes(goPackage) } diff --git a/utbot-go/src/main/kotlin/org/utbot/go/api/util/GoUtModelsApiUtil.kt b/utbot-go/src/main/kotlin/org/utbot/go/api/util/GoUtModelsApiUtil.kt index 57f0fb7b06..633b482b6b 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/api/util/GoUtModelsApiUtil.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/api/util/GoUtModelsApiUtil.kt @@ -22,6 +22,11 @@ fun GoUtModel.convertToRawValue(destinationPackage: GoPackage, aliases: Map NamedValue( + model.typeId.getRelativeName(destinationPackage, aliases), + model.value.convertToRawValue(destinationPackage, aliases) + ) + is GoUtArrayModel -> ArrayValue( model.typeId.getRelativeName(destinationPackage, aliases), model.typeId.elementTypeId!!.getRelativeName(destinationPackage, aliases), @@ -29,7 +34,6 @@ fun GoUtModel.convertToRawValue(destinationPackage: GoPackage, aliases: Map SliceValue( model.typeId.getRelativeName(destinationPackage, aliases), model.typeId.elementTypeId!!.getRelativeName(destinationPackage, aliases), @@ -49,6 +53,6 @@ fun GoUtModel.convertToRawValue(destinationPackage: GoPackage, aliases: Map PrimitiveValue(model.typeId.name, model.value.toString()) - + is GoUtNilModel -> NilValue(model.typeId.getRelativeName(destinationPackage, aliases)) else -> error("Converting ${model.javaClass} to RawValue is not supported") } \ No newline at end of file diff --git a/utbot-go/src/main/kotlin/org/utbot/go/framework/api/go/GoApi.kt b/utbot-go/src/main/kotlin/org/utbot/go/framework/api/go/GoApi.kt index 36f52f9124..d874cacd66 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/framework/api/go/GoApi.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/framework/api/go/GoApi.kt @@ -18,14 +18,6 @@ abstract class GoTypeId( override fun toString(): String = canonicalName } -abstract class GoNamedTypeId( - name: String, - elementTypeId: GoTypeId? = null, - implementsError: Boolean = false -) : GoTypeId(name, elementTypeId, implementsError) { - fun exported(): Boolean = name.first().isUpperCase() -} - /** * Parent class for all Go models. * @@ -66,7 +58,9 @@ class GoFieldId( data class GoPackage( val packageName: String, val packagePath: String -) +) { + val isBuiltin = packageName == "" && packagePath == "" +} /** * Class for Go import. diff --git a/utbot-go/src/main/kotlin/org/utbot/go/fuzzer/providers/GoNamedValueProvider.kt b/utbot-go/src/main/kotlin/org/utbot/go/fuzzer/providers/GoNamedValueProvider.kt new file mode 100644 index 0000000000..57492b8fc0 --- /dev/null +++ b/utbot-go/src/main/kotlin/org/utbot/go/fuzzer/providers/GoNamedValueProvider.kt @@ -0,0 +1,34 @@ +package org.utbot.go.fuzzer.providers + +import org.utbot.fuzzing.Routine +import org.utbot.fuzzing.Seed +import org.utbot.fuzzing.ValueProvider +import org.utbot.go.GoDescription +import org.utbot.go.api.GoNamedTypeId +import org.utbot.go.api.GoUtNamedModel +import org.utbot.go.api.util.goDefaultValueModel +import org.utbot.go.framework.api.go.GoTypeId +import org.utbot.go.framework.api.go.GoUtModel + +object GoNamedValueProvider : ValueProvider { + override fun accept(type: GoTypeId): Boolean = type is GoNamedTypeId + + override fun generate(description: GoDescription, type: GoTypeId): Sequence> = sequence { + type.let { it as GoNamedTypeId }.also { namedType -> + yield(Seed.Recursive(construct = Routine.Create(listOf(namedType.underlyingTypeId)) { values -> + GoUtNamedModel( + value = values.first(), + typeId = namedType, + ) + }, modify = sequence { + yield(Routine.Call(listOf(namedType.underlyingTypeId)) { self, values -> + val model = self as GoUtNamedModel + val value = values.first() + model.value = value + }) + }, empty = Routine.Empty { + GoUtNamedModel(namedType.underlyingTypeId.goDefaultValueModel(), namedType) + })) + } + } +} \ No newline at end of file diff --git a/utbot-go/src/main/kotlin/org/utbot/go/fuzzer/providers/GoNilValueProvider.kt b/utbot-go/src/main/kotlin/org/utbot/go/fuzzer/providers/GoNilValueProvider.kt new file mode 100644 index 0000000000..cb1d65ee19 --- /dev/null +++ b/utbot-go/src/main/kotlin/org/utbot/go/fuzzer/providers/GoNilValueProvider.kt @@ -0,0 +1,16 @@ +package org.utbot.go.fuzzer.providers + +import org.utbot.fuzzing.Seed +import org.utbot.fuzzing.ValueProvider +import org.utbot.go.GoDescription +import org.utbot.go.api.GoSliceTypeId +import org.utbot.go.api.GoUtNilModel +import org.utbot.go.framework.api.go.GoTypeId +import org.utbot.go.framework.api.go.GoUtModel + +object GoNilValueProvider : ValueProvider { + override fun accept(type: GoTypeId): Boolean = type is GoSliceTypeId + + override fun generate(description: GoDescription, type: GoTypeId): Sequence> = + sequenceOf(Seed.Simple(GoUtNilModel(type))) +} \ No newline at end of file diff --git a/utbot-go/src/main/kotlin/org/utbot/go/gocodeanalyzer/AnalysisResults.kt b/utbot-go/src/main/kotlin/org/utbot/go/gocodeanalyzer/AnalysisResults.kt index 60a9e9f59e..078969214b 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/gocodeanalyzer/AnalysisResults.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/gocodeanalyzer/AnalysisResults.kt @@ -18,9 +18,6 @@ data class AnalyzedPrimitiveType( data class AnalyzedStructType( override val name: String, - val packageName: String, - val packagePath: String, - val implementsError: Boolean, val fields: List ) : AnalyzedType(name) { data class AnalyzedField( @@ -31,8 +28,6 @@ data class AnalyzedStructType( override fun toGoTypeId(): GoTypeId = GoStructTypeId( name = name, - sourcePackage = GoPackage(packageName, packagePath), - implementsError = implementsError, fields = fields.map { field -> GoFieldId(field.type.toGoTypeId(), field.name, field.isExported) } ) } @@ -61,18 +56,22 @@ data class AnalyzedSliceType( data class AnalyzedInterfaceType( override val name: String, - val implementsError: Boolean, - val packageName: String, - val packagePath: String ) : AnalyzedType(name) { - override fun toGoTypeId(): GoTypeId = - GoInterfaceTypeId( - name = simpleName, - implementsError = implementsError, - sourcePackage = GoPackage(packageName, packagePath) - ) + override fun toGoTypeId(): GoTypeId = GoInterfaceTypeId(name = name) +} - private val simpleName: String = name.replaceFirst("interface ", "") +data class AnalyzedNamedType( + override val name: String, + val sourcePackage: GoPackage, + val implementsError: Boolean, + val underlyingType: AnalyzedType +) : AnalyzedType(name) { + override fun toGoTypeId(): GoTypeId = GoNamedTypeId( + name = name, + sourcePackage = sourcePackage, + implementsError = implementsError, + underlyingTypeId = underlyingType.toGoTypeId(), + ) } @TypeFor(field = "name", adapter = AnalyzedTypeAdapter::class) @@ -84,12 +83,13 @@ class AnalyzedTypeAdapter : TypeAdapter { override fun classFor(type: Any): KClass { val typeName = type as String return when { - typeName.startsWith("interface ") -> AnalyzedInterfaceType::class + typeName == "interface{}" -> AnalyzedInterfaceType::class + typeName == "struct{}" -> AnalyzedStructType::class typeName.startsWith("map[") -> error("Map type not yet supported") typeName.startsWith("[]") -> AnalyzedSliceType::class typeName.startsWith("[") -> AnalyzedArrayType::class goPrimitives.map { it.name }.contains(typeName) -> AnalyzedPrimitiveType::class - else -> AnalyzedStructType::class + else -> AnalyzedNamedType::class } } } diff --git a/utbot-go/src/main/kotlin/org/utbot/go/imports/GoImportsResolver.kt b/utbot-go/src/main/kotlin/org/utbot/go/imports/GoImportsResolver.kt index 0fbb0353c6..4779688709 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/imports/GoImportsResolver.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/imports/GoImportsResolver.kt @@ -1,6 +1,6 @@ package org.utbot.go.imports -import org.utbot.go.api.util.getAllVisibleStructTypes +import org.utbot.go.api.util.getAllVisibleNamedTypes import org.utbot.go.framework.api.go.GoImport import org.utbot.go.framework.api.go.GoPackage import org.utbot.go.framework.api.go.GoTypeId @@ -12,10 +12,10 @@ object GoImportsResolver { sourcePackage: GoPackage, busyImports: Set = emptySet() ): Set { - val structTypes = types.getAllVisibleStructTypes(sourcePackage) + val namedTypes = types.getAllVisibleNamedTypes(sourcePackage) val result = busyImports.toMutableSet() val busyAliases = busyImports.map { it.alias ?: it.goPackage.packageName }.toMutableSet() - structTypes.map { it.sourcePackage }.distinct().filter { it != sourcePackage }.forEach { goPackage -> + namedTypes.map { it.sourcePackage }.distinct().filter { it != sourcePackage }.forEach { goPackage -> val alias = if (goPackage.packageName in busyAliases) { var n = 1 while (goPackage.packageName + n in busyAliases) { diff --git a/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoTestCasesCodeGenerator.kt b/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoTestCasesCodeGenerator.kt index 31d0aef4c6..58a7daad93 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoTestCasesCodeGenerator.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoTestCasesCodeGenerator.kt @@ -159,11 +159,13 @@ object GoTestCasesCodeGenerator { assertionTParameter: String, goUtModelToCodeConverter: GoUtModelToCodeConverter ): String { - if (expectedModel is GoUtNilModel) { + if (expectedModel is GoUtNilModel || (expectedModel is GoUtNamedModel && expectedModel.value is GoUtNilModel)) { return "Nil($assertionTParameter$actualResultCode)" } - if (doesReturnTypeImplementError && expectedModel.typeId == goStringTypeId) { - return "ErrorContains($assertionTParameter$actualResultCode, $expectedModel)" + if (doesReturnTypeImplementError && (expectedModel is GoUtNamedModel && expectedModel.value.typeId == goStringTypeId)) { + return "ErrorContains($assertionTParameter$actualResultCode, ${ + goUtModelToCodeConverter.toGoCode(expectedModel.value) + })" } if (expectedModel is GoUtFloatNaNModel) { val castedActualResultCode = generateCastIfNeed(goFloat64TypeId, expectedModel.typeId, actualResultCode) @@ -233,7 +235,7 @@ object GoTestCasesCodeGenerator { functionName: String, parameters: List, goUtModelToCodeConverter: GoUtModelToCodeConverter ): String { val fuzzedParametersToString = parameters.joinToString(prefix = "(", postfix = ")") { - goUtModelToCodeConverter.toGoCode(it) + goUtModelToCodeConverter.toGoCode(it, false) } return "$functionName$fuzzedParametersToString" } @@ -248,8 +250,7 @@ object GoTestCasesCodeGenerator { fuzzedFunction: GoUtFuzzedFunction, goUtModelToCodeConverter: GoUtModelToCodeConverter ): String = generateVariablesDeclarationTo( - variablesNames, - generateFuzzedFunctionCall( + variablesNames, generateFuzzedFunctionCall( fuzzedFunction.function.name, fuzzedFunction.parametersValues, goUtModelToCodeConverter ) ) @@ -264,9 +265,8 @@ object GoTestCasesCodeGenerator { } } - fun generateCastedValueIfPossible( - model: GoUtPrimitiveModel, - goUtModelToCodeConverter: GoUtModelToCodeConverter + private fun generateCastedValueIfPossible( + model: GoUtPrimitiveModel, goUtModelToCodeConverter: GoUtModelToCodeConverter ): String { return if (model.explicitCastMode == ExplicitCastMode.NEVER) { goUtModelToCodeConverter.primitiveModelToValueGoCode(model) diff --git a/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoUtModelToCodeConverter.kt b/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoUtModelToCodeConverter.kt index 9dc69f8b52..dc9be0521f 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoUtModelToCodeConverter.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoUtModelToCodeConverter.kt @@ -10,7 +10,7 @@ class GoUtModelToCodeConverter( private val aliases: Map ) { - fun toGoCode(model: GoUtModel): String = when (model) { + fun toGoCode(model: GoUtModel, withTypeConversion: Boolean = true): String = when (model) { is GoUtNilModel -> "nil" is GoUtPrimitiveModel -> when (model.explicitCastMode) { @@ -18,16 +18,36 @@ class GoUtModelToCodeConverter( ExplicitCastMode.DEPENDS, ExplicitCastMode.NEVER -> primitiveModelToValueGoCode(model) } - is GoUtStructModel -> { - val typeName = model.typeId.getRelativeName(destinationPackage, aliases) - "$typeName${structModelToGoCodeWithoutStructName(model)}" - } - is GoUtArrayModel -> arrayModelToGoCode(model) is GoUtSliceModel -> sliceModelToGoCode(model) - else -> error("Converting a $javaClass to Go code isn't supported") + is GoUtNamedModel -> if (!withTypeConversion && model.value is GoUtPrimitiveModel) { + toGoCodeWithoutTypeName(model.value) + } else { + namedModelToGoCode(model) + } + + else -> error("Converting a ${model.javaClass} to Go code isn't supported") + } + + private fun toGoCodeWithoutTypeName(model: GoUtModel): String = when (model) { + is GoUtNilModel -> "nil" + + is GoUtPrimitiveModel -> when (model.explicitCastMode) { + ExplicitCastMode.REQUIRED -> primitiveModelToCastedValueGoCode(model) + ExplicitCastMode.DEPENDS, ExplicitCastMode.NEVER -> primitiveModelToValueGoCode(model) + } + + is GoUtStructModel -> structModelToGoCodeWithoutStructName(model) + + is GoUtArrayModel -> arrayModelToGoCodeWithoutTypeName(model) + + is GoUtSliceModel -> sliceModelToGoCodeWithoutTypeName(model) + + is GoUtNamedModel -> toGoCodeWithoutTypeName(model.value) + + else -> error("Converting a ${model.javaClass} to Go code isn't supported") } fun primitiveModelToValueGoCode(model: GoUtPrimitiveModel): String = when (model) { @@ -46,107 +66,38 @@ class GoUtModelToCodeConverter( "${it.fieldId.name}: ${toGoCode(it.model)}" } - private fun arrayModelToGoCode(model: GoUtArrayModel): String = - when (val elementType = model.typeId.elementTypeId!!) { - is GoStructTypeId -> model.getElements().joinToString( - prefix = "[${model.length}]${ - elementType.getRelativeName(destinationPackage, aliases) - }{", - postfix = "}" - ) { - structModelToGoCodeWithoutStructName(it as GoUtStructModel) - } - - is GoArrayTypeId -> model.getElements().joinToString( - prefix = "[${model.length}]${ - elementType.getRelativeName(destinationPackage, aliases) - }{", - postfix = "}" - ) { - arrayModelToGoCodeWithoutTypeName(it as GoUtArrayModel) - } - - is GoSliceTypeId -> model.getElements().joinToString( - prefix = "[${model.length}]${ - elementType.getRelativeName(destinationPackage, aliases) - }{", - postfix = "}" - ) { - sliceModelToGoCodeWithoutTypeName(it as GoUtSliceModel) - } - - else -> model.getElements().joinToString( - prefix = "[${model.length}]${elementType.getRelativeName(destinationPackage, aliases)}{", - postfix = "}" - ) + private fun arrayModelToGoCode(model: GoUtArrayModel): String { + val elementType = model.typeId.elementTypeId!! + val elementTypeName = elementType.getRelativeName(destinationPackage, aliases) + return model.getElements().joinToString(prefix = "[${model.length}]$elementTypeName{", postfix = "}") { + toGoCodeWithoutTypeName(it) } + } private fun arrayModelToGoCodeWithoutTypeName(model: GoUtArrayModel): String = - when (model.typeId.elementTypeId!!) { - is GoStructTypeId -> model.getElements().joinToString(prefix = "{", postfix = "}") { - structModelToGoCodeWithoutStructName(it as GoUtStructModel) - } - - is GoArrayTypeId -> model.getElements().joinToString(prefix = "{", postfix = "}") { - arrayModelToGoCodeWithoutTypeName(it as GoUtArrayModel) - } - - is GoSliceTypeId -> model.getElements().joinToString(prefix = "{", postfix = "}") { - sliceModelToGoCodeWithoutTypeName(it as GoUtSliceModel) - } - - else -> model.getElements().joinToString(prefix = "{", postfix = "}") + model.getElements().joinToString(prefix = "{", postfix = "}") { + toGoCodeWithoutTypeName(it) } - private fun sliceModelToGoCode(model: GoUtSliceModel): String = - when (val elementType = model.typeId.elementTypeId!!) { - is GoStructTypeId -> model.getElements().joinToString( - prefix = "[]${ - elementType.getRelativeName(destinationPackage, aliases) - }{", - postfix = "}" - ) { - structModelToGoCodeWithoutStructName(it as GoUtStructModel) - } - - is GoArrayTypeId -> model.getElements().joinToString( - prefix = "[]${ - elementType.getRelativeName(destinationPackage, aliases) - }{", - postfix = "}" - ) { - arrayModelToGoCodeWithoutTypeName(it as GoUtArrayModel) - } - - is GoSliceTypeId -> model.getElements().joinToString( - prefix = "[]${ - elementType.getRelativeName(destinationPackage, aliases) - }{", - postfix = "}" - ) { - sliceModelToGoCodeWithoutTypeName(it as GoUtSliceModel) - } - - else -> model.getElements().joinToString( - prefix = "[]${elementType.getRelativeName(destinationPackage, aliases)}{", - postfix = "}" - ) + private fun sliceModelToGoCode(model: GoUtSliceModel): String { + val elementType = model.typeId.elementTypeId!! + val elementTypeName = elementType.getRelativeName(destinationPackage, aliases) + return model.getElements().joinToString(prefix = "[]$elementTypeName{", postfix = "}") { + toGoCodeWithoutTypeName(it) } + } private fun sliceModelToGoCodeWithoutTypeName(model: GoUtSliceModel): String = - when (model.typeId.elementTypeId!!) { - is GoStructTypeId -> model.getElements().joinToString(prefix = "{", postfix = "}") { - structModelToGoCodeWithoutStructName(it as GoUtStructModel) - } - - is GoArrayTypeId -> model.getElements().joinToString(prefix = "{", postfix = "}") { - arrayModelToGoCodeWithoutTypeName(it as GoUtArrayModel) - } - - is GoSliceTypeId -> model.getElements().joinToString(prefix = "{", postfix = "}") { - sliceModelToGoCodeWithoutTypeName(it as GoUtSliceModel) - } + model.getElements().joinToString(prefix = "{", postfix = "}") { + toGoCodeWithoutTypeName(it) + } - else -> model.getElements().joinToString(prefix = "{", postfix = "}") + private fun namedModelToGoCode(model: GoUtNamedModel): String { + val typeName = model.typeId.getRelativeName(destinationPackage, aliases) + return if (model.value is GoUtPrimitiveModel || model.value is GoUtNilModel) { + "$typeName(${toGoCodeWithoutTypeName(model.value)})" + } else { + "$typeName${toGoCodeWithoutTypeName(model.value)}" } + } } diff --git a/utbot-go/src/main/kotlin/org/utbot/go/worker/GoCodeTemplates.kt b/utbot-go/src/main/kotlin/org/utbot/go/worker/GoCodeTemplates.kt index 984b94602a..ea8bc46219 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/worker/GoCodeTemplates.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/worker/GoCodeTemplates.kt @@ -1,7 +1,10 @@ package org.utbot.go.worker +import org.utbot.go.api.GoNamedTypeId import org.utbot.go.api.GoStructTypeId +import org.utbot.go.api.util.goDefaultValueModel import org.utbot.go.framework.api.go.GoPackage +import org.utbot.go.simplecodegeneration.GoUtModelToCodeConverter object GoCodeTemplates { @@ -138,7 +141,7 @@ object GoCodeTemplates { return reflect.ValueOf(uintptr(value)), nil } - return reflect.Value{}, fmt.Errorf("not supported type %s", v.Type) + return reflect.Value{}, fmt.Errorf("primitive type '%s' is not supported", v.Type) } """.trimIndent() @@ -243,11 +246,72 @@ object GoCodeTemplates { } """.trimIndent() - private fun convertStringToReflectType( - structTypes: Set, + private val nilValueStruct = """ + type __NilValue__ struct { + Type string `json:"type"` + } + """.trimIndent() + + private val nilValueToReflectValueMethod = """ + func (v __NilValue__) __toReflectValue__() (reflect.Value, error) { + typ, err := __convertStringToReflectType__(v.Type) + __checkErrorAndExit__(err) + + return reflect.Zero(typ), nil + } + """.trimIndent() + + private val namedValueStruct = """ + type __NamedValue__ struct { + Type string `json:"type"` + Value __RawValue__ `json:"value"` + } + """.trimIndent() + + private val namedValueToReflectValueMethod = """ + func (v __NamedValue__) __toReflectValue__() (reflect.Value, error) { + value, err := v.Value.__toReflectValue__() + __checkErrorAndExit__(err) + + val, err := __typeConversionToNamedType__(v.Type, value.Interface()) + __checkErrorAndExit__(err) + + return reflect.ValueOf(val), nil + } + """.trimIndent() + + private fun typeConversionToNamedType( + namedTypes: Set, destinationPackage: GoPackage, aliases: Map ) = """ + func __typeConversionToNamedType__(typ string, value any) (any, error) { + switch typ { + ${ + namedTypes.joinToString(separator = "\n") { + val relativeName = it.getRelativeName(destinationPackage, aliases) + "case \"${relativeName}\": return ${relativeName}(value.(${ + if (it.underlyingTypeId is GoStructTypeId) { + relativeName + } else { + it.underlyingTypeId.getRelativeName(destinationPackage, aliases) + } + })), nil" + } + } + default: + return nil, fmt.Errorf("unknown named type: %s", typ) + } + } + """.trimIndent() + + private fun convertStringToReflectType( + namedTypes: Set, + destinationPackage: GoPackage, + aliases: Map + ): String { + val converter = GoUtModelToCodeConverter(destinationPackage, aliases) + return """ func __convertStringToReflectType__(typeName string) (reflect.Type, error) { var result reflect.Type @@ -325,18 +389,19 @@ object GoCodeTemplates { case "uintptr": result = reflect.TypeOf(uintptr(0)) ${ - structTypes.joinToString(separator = "\n") { - val relativeName = it.getRelativeName(destinationPackage, aliases) - "case \"${relativeName}\": result = reflect.TypeOf(${relativeName}{})" + namedTypes.joinToString(separator = "\n") { + val relativeName = it.getRelativeName(destinationPackage, aliases) + "case \"${relativeName}\": result = reflect.TypeOf(${converter.toGoCode(it.goDefaultValueModel())})" + } } - } default: - return nil, fmt.Errorf("type '%s' not supported", typeName) + return nil, fmt.Errorf("type '%s' is not supported", typeName) } } return result, nil } """.trimIndent() + } private val panicMessageStruct = """ type __RawPanicMessage__ struct { @@ -590,13 +655,13 @@ object GoCodeTemplates { var testInput __TestInput__ err := decoder.Decode(&testInput) if err == io.EOF { - return "", nil, err + return "", nil, err } __checkErrorAndExit__(err) result := make([]__RawValue__, 0) for _, arg := range testInput.Arguments { - rawValue, err := __convertParsedJsonToRawValue__(arg) + rawValue, err := __convertParsedJsonToRawValue__(arg, "") __checkErrorAndExit__(err) result = append(result, rawValue) @@ -608,7 +673,7 @@ object GoCodeTemplates { private val convertParsedJsonToRawValueFunction = """ //goland:noinspection GoPreferNilSlice - func __convertParsedJsonToRawValue__(rawValue map[string]interface{}) (__RawValue__, error) { + func __convertParsedJsonToRawValue__(rawValue map[string]interface{}, name string) (__RawValue__, error) { typeName, ok := rawValue["type"] if !ok { return nil, fmt.Errorf("every rawValue must contain field 'type'") @@ -620,16 +685,38 @@ object GoCodeTemplates { v, ok := rawValue["value"] if !ok { - return nil, fmt.Errorf("every rawValue must contain field 'value'") + return __NilValue__{Type: typeNameStr}, nil } switch { + case typeNameStr == "struct{}": + if name == "" { + return nil, fmt.Errorf("anonymous structs is not supported") + } + + value, ok := v.([]interface{}) + if !ok { + return nil, fmt.Errorf("structValue field 'value' must be array") + } + + values := []__FieldValue__{} + for _, v := range value { + nextValue, err := __convertParsedJsonToFieldValue__(v.(map[string]interface{})) + __checkErrorAndExit__(err) + + values = append(values, nextValue) + } + + return __StructValue__{ + Type: name, + Value: values, + }, nil case strings.HasPrefix(typeNameStr, "map["): - return nil, fmt.Errorf("map type not supported") + return nil, fmt.Errorf("map type is not supported") case strings.HasPrefix(typeNameStr, "[]"): elementType, ok := rawValue["elementType"] if !ok { - return nil, fmt.Errorf("sliceValue must contain field 'elementType") + return nil, fmt.Errorf("sliceValue must contain field 'elementType'") } elementTypeStr, ok := elementType.(string) if !ok { @@ -651,7 +738,7 @@ object GoCodeTemplates { values := []__RawValue__{} for _, v := range value { - nextValue, err := __convertParsedJsonToRawValue__(v.(map[string]interface{})) + nextValue, err := __convertParsedJsonToRawValue__(v.(map[string]interface{}), "") __checkErrorAndExit__(err) values = append(values, nextValue) @@ -688,7 +775,7 @@ object GoCodeTemplates { values := []__RawValue__{} for _, v := range value { - nextValue, err := __convertParsedJsonToRawValue__(v.(map[string]interface{})) + nextValue, err := __convertParsedJsonToRawValue__(v.(map[string]interface{}), "") __checkErrorAndExit__(err) values = append(values, nextValue) @@ -712,23 +799,13 @@ object GoCodeTemplates { Type: typeNameStr, Value: value, }, nil - default: - value, ok := v.([]interface{}) - if !ok { - return nil, fmt.Errorf("structValue field 'value' must be array") - } - - values := []__FieldValue__{} - for _, v := range value { - nextValue, err := __convertParsedJsonToFieldValue__(v.(map[string]interface{})) - __checkErrorAndExit__(err) - - values = append(values, nextValue) - } + default: // named type + value, err := __convertParsedJsonToRawValue__(v.(map[string]interface{}), typeNameStr) + __checkErrorAndExit__(err) - return __StructValue__{ + return __NamedValue__{ Type: typeNameStr, - Value: values, + Value: value, }, nil } } @@ -758,7 +835,7 @@ object GoCodeTemplates { if _, ok := p["value"]; !ok { return __FieldValue__{}, fmt.Errorf("fieldValue must contain field 'value'") } - value, err := __convertParsedJsonToRawValue__(p["value"].(map[string]interface{})) + value, err := __convertParsedJsonToRawValue__(p["value"].(map[string]interface{}), "") __checkErrorAndExit__(err) return __FieldValue__{ @@ -770,7 +847,7 @@ object GoCodeTemplates { """.trimIndent() fun getTopLevelHelperStructsAndFunctionsForWorker( - structTypes: Set, + namedTypes: Set, destinationPackage: GoPackage, aliases: Map, maxTraceLength: Int, @@ -786,7 +863,12 @@ object GoCodeTemplates { arrayValueToReflectValueMethod, sliceValueStruct, sliceValueToReflectValueMethod, - convertStringToReflectType(structTypes, destinationPackage, aliases), + nilValueStruct, + nilValueToReflectValueMethod, + namedValueStruct, + namedValueToReflectValueMethod, + typeConversionToNamedType(namedTypes, destinationPackage, aliases), + convertStringToReflectType(namedTypes, destinationPackage, aliases), panicMessageStruct, rawExecutionResultStruct, checkErrorFunction, diff --git a/utbot-go/src/main/kotlin/org/utbot/go/worker/GoWorkerCodeGenerationHelper.kt b/utbot-go/src/main/kotlin/org/utbot/go/worker/GoWorkerCodeGenerationHelper.kt index aca57a5a45..6000899735 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/worker/GoWorkerCodeGenerationHelper.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/worker/GoWorkerCodeGenerationHelper.kt @@ -2,7 +2,7 @@ package org.utbot.go.worker import org.utbot.go.api.GoUtFile import org.utbot.go.api.GoUtFunction -import org.utbot.go.api.util.getAllVisibleStructTypes +import org.utbot.go.api.util.getAllVisibleNamedTypes import org.utbot.go.framework.api.go.GoImport import org.utbot.go.framework.api.go.GoPackage import org.utbot.go.simplecodegeneration.GoFileCodeBuilder @@ -89,12 +89,12 @@ internal object GoWorkerCodeGenerationHelper { val workerTestFunctionCode = generateWorkerTestFunctionCode(functions, eachExecutionTimeoutMillis, port) val types = functions.flatMap { it.parameters }.map { it.type } - val structTypes = types.getAllVisibleStructTypes(destinationPackage) val aliases = imports.associate { it.goPackage to it.alias } + val namedTypes = types.getAllVisibleNamedTypes(destinationPackage) fileCodeBuilder.addTopLevelElements( GoCodeTemplates.getTopLevelHelperStructsAndFunctionsForWorker( - structTypes, + namedTypes, destinationPackage, aliases, maxTraceLength, diff --git a/utbot-go/src/main/kotlin/org/utbot/go/worker/RawExecutionResults.kt b/utbot-go/src/main/kotlin/org/utbot/go/worker/RawExecutionResults.kt index 78b72c3920..438f469545 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/worker/RawExecutionResults.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/worker/RawExecutionResults.kt @@ -11,24 +11,34 @@ import kotlin.reflect.KClass data class PrimitiveValue( override val type: String, - override val value: String, -) : RawValue(type, value) { + val value: String, +) : RawValue(type) { override fun checkIsEqualTypes(type: GoTypeId): Boolean { - if (!type.isPrimitiveGoType && type !is GoInterfaceTypeId && !type.implementsError) { + if (type is GoNamedTypeId) { + return checkIsEqualTypes(type.underlyingTypeId) + } + if (!type.isPrimitiveGoType && type !is GoInterfaceTypeId) { return false } // for error support - if (this.type == "string" && type is GoInterfaceTypeId && type.implementsError) { + if (this.type == "string" && type is GoInterfaceTypeId) { return true } return GoPrimitiveTypeId(this.type) == type } } +data class NamedValue( + override val type: String, + val value: RawValue, +) : RawValue(type) { + override fun checkIsEqualTypes(type: GoTypeId): Boolean = error("Not supported") +} + data class StructValue( override val type: String, - override val value: List -) : RawValue(type, value) { + val value: List +) : RawValue(type) { data class FieldValue( val name: String, val value: RawValue, @@ -36,10 +46,10 @@ data class StructValue( ) override fun checkIsEqualTypes(type: GoTypeId): Boolean { - if (type !is GoStructTypeId) { - return false + if (type is GoNamedTypeId) { + return this.type == type.canonicalName && checkIsEqualTypes(type.underlyingTypeId) } - if (this.type != type.canonicalName) { + if (type !is GoStructTypeId) { return false } if (value.size != type.fields.size) { @@ -64,9 +74,12 @@ data class ArrayValue( override val type: String, val elementType: String, val length: Int, - override val value: List -) : RawValue(type, value) { + val value: List +) : RawValue(type) { override fun checkIsEqualTypes(type: GoTypeId): Boolean { + if (type is GoNamedTypeId) { + return checkIsEqualTypes(type.underlyingTypeId) + } if (type !is GoArrayTypeId) { return false } @@ -81,9 +94,12 @@ data class SliceValue( override val type: String, val elementType: String, val length: Int, - override val value: List -) : RawValue(type, value) { + val value: List +) : RawValue(type) { override fun checkIsEqualTypes(type: GoTypeId): Boolean { + if (type is GoNamedTypeId) { + return checkIsEqualTypes(type.underlyingTypeId) + } if (type !is GoSliceTypeId) { return false } @@ -94,8 +110,14 @@ data class SliceValue( } } +data class NilValue( + override val type: String +) : RawValue(type) { + override fun checkIsEqualTypes(type: GoTypeId): Boolean = error("Not supported") +} + @TypeFor(field = "type", adapter = RawResultValueAdapter::class) -abstract class RawValue(open val type: String, open val value: Any) { +abstract class RawValue(open val type: String) { abstract fun checkIsEqualTypes(type: GoTypeId): Boolean } @@ -180,23 +202,25 @@ fun convertRawExecutionResultToExecutionResult( private fun createGoUtModelFromRawValue( rawValue: RawValue?, typeId: GoTypeId, intSize: Int -): GoUtModel = if (rawValue == null) { - GoUtNilModel(typeId) -} else { - when (typeId) { - // Only for error interface - is GoInterfaceTypeId -> GoUtPrimitiveModel((rawValue as PrimitiveValue).value, goStringTypeId) +): GoUtModel = when (typeId) { + is GoNamedTypeId -> GoUtNamedModel(createGoUtModelFromRawValue(rawValue, typeId.underlyingTypeId, intSize), typeId) - is GoStructTypeId -> createGoUtStructModelFromRawValue(rawValue as StructValue, typeId, intSize) + // Only for error interface + is GoInterfaceTypeId -> if (rawValue == null) { + GoUtNilModel(typeId) + } else { + GoUtPrimitiveModel((rawValue as PrimitiveValue).value, goStringTypeId) + } - is GoArrayTypeId -> createGoUtArrayModelFromRawValue(rawValue as ArrayValue, typeId, intSize) + is GoStructTypeId -> createGoUtStructModelFromRawValue(rawValue as StructValue, typeId, intSize) - is GoSliceTypeId -> createGoUtSliceModelFromRawValue(rawValue as SliceValue, typeId, intSize) + is GoArrayTypeId -> createGoUtArrayModelFromRawValue(rawValue as ArrayValue, typeId, intSize) - is GoPrimitiveTypeId -> createGoUtPrimitiveModelFromRawValue(rawValue as PrimitiveValue, typeId, intSize) + is GoSliceTypeId -> createGoUtSliceModelFromRawValue(rawValue as SliceValue, typeId, intSize) - else -> error("Creating a model from raw value of [${typeId.javaClass}] type is not supported") - } + is GoPrimitiveTypeId -> createGoUtPrimitiveModelFromRawValue(rawValue as PrimitiveValue, typeId, intSize) + + else -> error("Creating a model from raw value of [${typeId.javaClass}] type is not supported") } private fun createGoUtPrimitiveModelFromRawValue( diff --git a/utbot-go/src/main/resources/go_source_code_analyzer/analysis_results.go b/utbot-go/src/main/resources/go_source_code_analyzer/analysis_results.go index f0410d0add..91bec689a5 100644 --- a/utbot-go/src/main/resources/go_source_code_analyzer/analysis_results.go +++ b/utbot-go/src/main/resources/go_source_code_analyzer/analysis_results.go @@ -2,15 +2,28 @@ package main import "go/token" +type GoPackage struct { + PackageName string `json:"packageName"` + PackagePath string `json:"packagePath"` +} + type AnalyzedType interface { GetName() string } +type AnalyzedNamedType struct { + Name string `json:"name"` + SourcePackage GoPackage `json:"sourcePackage"` + ImplementsError bool `json:"implementsError"` + UnderlyingType AnalyzedType `json:"underlyingType"` +} + +func (t AnalyzedNamedType) GetName() string { + return t.Name +} + type AnalyzedInterfaceType struct { - Name string `json:"name"` - ImplementsError bool `json:"implementsError"` - PackageName string `json:"packageName"` - PackagePath string `json:"packagePath"` + Name string `json:"name"` } func (t AnalyzedInterfaceType) GetName() string { @@ -32,11 +45,8 @@ type AnalyzedField struct { } type AnalyzedStructType struct { - Name string `json:"name"` - PackageName string `json:"packageName"` - PackagePath string `json:"packagePath"` - ImplementsError bool `json:"implementsError"` - Fields []AnalyzedField `json:"fields"` + Name string `json:"name"` + Fields []AnalyzedField `json:"fields"` } func (t AnalyzedStructType) GetName() string { diff --git a/utbot-go/src/main/resources/go_source_code_analyzer/analyzer_core.go b/utbot-go/src/main/resources/go_source_code_analyzer/analyzer_core.go index d1c99101e1..9a2e424298 100644 --- a/utbot-go/src/main/resources/go_source_code_analyzer/analyzer_core.go +++ b/utbot-go/src/main/resources/go_source_code_analyzer/analyzer_core.go @@ -27,19 +27,41 @@ func implementsError(typ types.Type) bool { //goland:noinspection GoPreferNilSlice func toAnalyzedType(typ types.Type) (AnalyzedType, error) { var result AnalyzedType - switch underlyingType := typ.Underlying().(type) { + + switch t := typ.(type) { + case *types.Named: + name := t.Obj().Name() + + pkg := t.Obj().Pkg() + packageName, packagePath := "", "" + if pkg != nil { + packageName = pkg.Name() + packagePath = pkg.Path() + } + + isError := implementsError(t) + + underlyingType, err := toAnalyzedType(t.Underlying()) + checkError(err) + + result = AnalyzedNamedType{ + Name: name, + SourcePackage: GoPackage{ + PackageName: packageName, + PackagePath: packagePath, + }, + ImplementsError: isError, + UnderlyingType: underlyingType, + } case *types.Basic: - name := underlyingType.Name() + name := t.Name() result = AnalyzedPrimitiveType{Name: name} case *types.Struct: - namedType := typ.(*types.Named) - name := namedType.Obj().Name() - pkg := namedType.Obj().Pkg() - isError := implementsError(namedType) + name := "struct{}" fields := []AnalyzedField{} - for i := 0; i < underlyingType.NumFields(); i++ { - field := underlyingType.Field(i) + for i := 0; i < t.NumFields(); i++ { + field := t.Field(i) fieldType, err := toAnalyzedType(field.Type()) checkError(err) @@ -48,11 +70,8 @@ func toAnalyzedType(typ types.Type) (AnalyzedType, error) { } result = AnalyzedStructType{ - Name: name, - PackageName: pkg.Name(), - PackagePath: pkg.Path(), - ImplementsError: isError, - Fields: fields, + Name: name, + Fields: fields, } case *types.Array: arrayType := typ.(*types.Array) @@ -84,24 +103,13 @@ func toAnalyzedType(typ types.Type) (AnalyzedType, error) { ElementType: sliceElemType, } case *types.Interface: - namedType := typ.(*types.Named) - name := namedType.Obj().Name() - pkg := namedType.Obj().Pkg() - packageName, packagePath := "", "" - if pkg != nil { - packageName = pkg.Name() - packagePath = pkg.Path() - } - - isError := implementsError(namedType) + name := "interface{}" + isError := implementsError(t) if !isError { return nil, errors.New("currently only error interface is supported") } result = AnalyzedInterfaceType{ - Name: fmt.Sprintf("interface %s", name), - ImplementsError: isError, - PackageName: packageName, - PackagePath: packagePath, + Name: name, } } return result, nil