From f6fda066cbab870c60d9511e7a95212bb7fbd229 Mon Sep 17 00:00:00 2001 From: Egipti Pavel Date: Mon, 20 Mar 2023 11:43:24 +0300 Subject: [PATCH 1/6] Add supports for user-defined types on Go side --- .../analysis_results.go | 24 +++++--- .../go_source_code_analyzer/analyzer_core.go | 60 ++++++++++--------- 2 files changed, 48 insertions(+), 36 deletions(-) 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..3d8f08bf43 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 @@ -6,11 +6,20 @@ type AnalyzedType interface { GetName() string } +type AnalyzedNamedType struct { + Name string `json:"name"` + PackageName string `json:"packageName"` + PackagePath string `json:"packagePath"` + 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 +41,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..e15ceb6f0d 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,39 @@ 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, + 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 +68,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 +101,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 From 0be17120be5aaacf0a13b11baa86804b075fc84e Mon Sep 17 00:00:00 2001 From: Egipti Pavel Date: Tue, 21 Mar 2023 16:38:21 +0300 Subject: [PATCH 2/6] Change type names to canonical --- .../main/resources/go_source_code_analyzer/analyzer_core.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 e15ceb6f0d..f8131fa51d 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 @@ -55,7 +55,7 @@ func toAnalyzedType(typ types.Type) (AnalyzedType, error) { name := t.Name() result = AnalyzedPrimitiveType{Name: name} case *types.Struct: - name := "struct" + name := "struct{}" fields := []AnalyzedField{} for i := 0; i < t.NumFields(); i++ { @@ -101,7 +101,7 @@ func toAnalyzedType(typ types.Type) (AnalyzedType, error) { ElementType: sliceElemType, } case *types.Interface: - name := "interface" + name := "interface{}" isError := implementsError(t) if !isError { return nil, errors.New("currently only error interface is supported") From f3d549f29832eaeaa830d84b901398a12d684f07 Mon Sep 17 00:00:00 2001 From: Egipti Pavel Date: Wed, 22 Mar 2023 17:12:29 +0300 Subject: [PATCH 3/6] Add support for named types --- .../go-samples/simple/samples_go_ut_test.go | 96 +----------- utbot-go/go-samples/simple/supported_types.go | 43 +++++ .../simple/supported_types_go_ut_test.go | 97 ++++++++---- .../main/kotlin/org/utbot/go/GoLanguage.kt | 3 +- .../kotlin/org/utbot/go/api/GoTypesApi.kt | 60 +++---- .../kotlin/org/utbot/go/api/GoUtModelsApi.kt | 59 +++++-- .../org/utbot/go/api/util/GoTypesApiUtil.kt | 14 +- .../utbot/go/api/util/GoUtModelsApiUtil.kt | 5 + .../org/utbot/go/framework/api/go/GoApi.kt | 4 +- .../fuzzer/providers/GoNamedValueProvider.kt | 34 ++++ .../go/gocodeanalyzer/AnalysisResults.kt | 34 ++-- .../org/utbot/go/imports/GoImportsResolver.kt | 6 +- .../GoTestCasesCodeGenerator.kt | 16 +- .../GoUtModelToCodeConverter.kt | 145 ++++++----------- .../org/utbot/go/worker/GoCodeTemplates.kt | 148 ++++++++++++++---- .../go/worker/GoWorkerCodeGenerationHelper.kt | 6 +- .../utbot/go/worker/RawExecutionResults.kt | 52 ++++-- .../analysis_results.go | 8 +- .../go_source_code_analyzer/analyzer_core.go | 8 +- 19 files changed, 481 insertions(+), 357 deletions(-) create mode 100644 utbot-go/src/main/kotlin/org/utbot/go/fuzzer/providers/GoNamedValueProvider.kt 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 a6c69385c0..6bceb01d85 100644 --- a/utbot-go/go-samples/simple/samples_go_ut_test.go +++ b/utbot-go/go-samples/simple/samples_go_ut_test.go @@ -46,61 +46,21 @@ func TestGenerateArrayOfIntegersByUtGoFuzzer(t *testing.T) { } func TestDistanceBetweenTwoPointsByUtGoFuzzer(t *testing.T) { - actualVal := DistanceBetweenTwoPoints(Point{x: 0.990722785714783, y: 0.990722785714783}, Point{x: 2.0, y: 2.0}) + actualVal := DistanceBetweenTwoPoints(Point{}, Point{}) - assert.Equal(t, 1.4273335246362906, actualVal) + assert.Equal(t, 0.0, actualVal) } func TestGetCoordinatesOfMiddleBetweenTwoPointsByUtGoFuzzer(t *testing.T) { - actualVal0, actualVal1 := GetCoordinatesOfMiddleBetweenTwoPoints(Point{x: 0.4872328470301428, y: 0.4872328470301428}, Point{x: 2.0, y: 2.0}) - - assertMultiple := assert.New(t) - assertMultiple.Equal(1.2436164235150713, actualVal0) - assertMultiple.Equal(1.2436164235150713, actualVal1) -} - -func TestGetCoordinateSumOfPointsByUtGoFuzzer1(t *testing.T) { - actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{x: 0.7462414053223305, y: 0.7462414053223305}}) - - assertMultiple := assert.New(t) - assertMultiple.Equal(0.7462414053223305, actualVal0) - assertMultiple.Equal(0.7462414053223305, actualVal1) -} - -func TestGetCoordinateSumOfPointsByUtGoFuzzer2(t *testing.T) { - actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{x: 0.7462414053223305, y: 0.0}, {x: 0.7462414053223305, y: 0.0}, {x: 0.7462414053223305, y: 2.8480945388892178e-306}, {x: 0.7462414053223305, y: 0.0}}) - - assertMultiple := assert.New(t) - assertMultiple.Equal(2.984965621289322, actualVal0) - assertMultiple.Equal(2.8480945388892178e-306, actualVal1) -} - -func TestGetCoordinateSumOfPointsByUtGoFuzzer3(t *testing.T) { - actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{x: 0.7462414053223305, y: 0.7462414053223305}, {x: 0.0, y: 0.7462414053223305}}) - - assertMultiple := assert.New(t) - assertMultiple.Equal(0.7462414053223305, actualVal0) - assertMultiple.Equal(1.492482810644661, actualVal1) -} - -func TestGetCoordinateSumOfPointsByUtGoFuzzer4(t *testing.T) { - actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{x: 0.0, y: 0.0}, {x: 0.0, y: 0.0}, {x: 0.0, y: 0.0}}) + actualVal0, actualVal1 := GetCoordinatesOfMiddleBetweenTwoPoints(Point{}, Point{}) assertMultiple := assert.New(t) assertMultiple.Equal(0.0, actualVal0) assertMultiple.Equal(0.0, actualVal1) } -func TestGetCoordinateSumOfPointsByUtGoFuzzer5(t *testing.T) { - actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{x: 0.0, y: 0.7462414053223305}, {x: 0.0, y: 0.7462414053223305}, {x: 4.7783097267364807e-299, y: 0.7462414053223305}, {x: 0.0, y: 0.7462414053223305}, {x: 0.0, y: 0.7462414053223305}}) - - assertMultiple := assert.New(t) - assertMultiple.Equal(4.7783097267364807e-299, actualVal0) - assertMultiple.Equal(3.731207026611653, actualVal1) -} - -func TestGetCoordinateSumOfPointsByUtGoFuzzer6(t *testing.T) { - actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{}) +func TestGetCoordinateSumOfPointsByUtGoFuzzer(t *testing.T) { + actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{}}) assertMultiple := assert.New(t) assertMultiple.Equal(0.0, actualVal0) @@ -108,9 +68,9 @@ func TestGetCoordinateSumOfPointsByUtGoFuzzer6(t *testing.T) { } func TestGetAreaOfCircleByUtGoFuzzer(t *testing.T) { - actualVal := GetAreaOfCircle(Circle{Center: Point{x: 0.7331520701949938, y: 0.7331520701949938}, Radius: 2.0}) + actualVal := GetAreaOfCircle(Circle{Center: Point{}, Radius: 0.5504370051176339}) - assert.Equal(t, 12.566370614359172, actualVal) + assert.Equal(t, 0.9518425589456255, actualVal) } func TestIsIdentityByUtGoFuzzer1(t *testing.T) { @@ -126,48 +86,6 @@ func TestIsIdentityByUtGoFuzzer2(t *testing.T) { } func TestIsIdentityByUtGoFuzzer3(t *testing.T) { - actualVal := IsIdentity([3][3]int{{1, 0, 0}, {0, 0, 0}, {0, 0, 0}}) - - assert.Equal(t, false, actualVal) -} - -func TestIsIdentityByUtGoFuzzer4(t *testing.T) { - actualVal := IsIdentity([3][3]int{{1, 0, 1}, {1, 0, 1}, {0, 1, 1}}) - - assert.Equal(t, false, actualVal) -} - -func TestIsIdentityByUtGoFuzzer5(t *testing.T) { - actualVal := IsIdentity([3][3]int{{1, 0, 0}, {0, 1, 2048}, {0, 0, 0}}) - - assert.Equal(t, false, actualVal) -} - -func TestIsIdentityByUtGoFuzzer6(t *testing.T) { - actualVal := IsIdentity([3][3]int{{1, 0, 0}, {2199023255552, 1, 2048}, {0, 0, 3}}) - - assert.Equal(t, false, actualVal) -} - -func TestIsIdentityByUtGoFuzzer7(t *testing.T) { - actualVal := IsIdentity([3][3]int{{1, 0, 0}, {0, 1, 0}, {0, 0, 0}}) - - assert.Equal(t, false, actualVal) -} - -func TestIsIdentityByUtGoFuzzer8(t *testing.T) { - actualVal := IsIdentity([3][3]int{{1, 0, 0}, {0, 1, 0}, {0, 1, 0}}) - - assert.Equal(t, false, actualVal) -} - -func TestIsIdentityByUtGoFuzzer9(t *testing.T) { - actualVal := IsIdentity([3][3]int{{1, 0, 0}, {0, 1, 0}, {18014398509481984, 1, 0}}) - - assert.Equal(t, false, actualVal) -} - -func TestIsIdentityByUtGoFuzzer10(t *testing.T) { actualVal := IsIdentity([3][3]int{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}) assert.Equal(t, true, actualVal) diff --git a/utbot-go/go-samples/simple/supported_types.go b/utbot-go/go-samples/simple/supported_types.go index 3b308da3f1..5ce63feed5 100644 --- a/utbot-go/go-samples/simple/supported_types.go +++ b/utbot-go/go-samples/simple/supported_types.go @@ -214,3 +214,46 @@ func SliceOfSliceOfStructs(slice [][]Structure) [][]Structure { func SliceOfArrayOfInt(slice [][5]int) [][5]int { return slice } + +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 c3b3f3eaf3..83affa9285 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 @@ -3,7 +3,6 @@ package simple import ( "github.com/pmezard/go-difflib/difflib" "github.com/stretchr/testify/assert" - "math" "testing" ) @@ -108,27 +107,27 @@ func TestUintPtrByUtGoFuzzer(t *testing.T) { } func TestFloat32ByUtGoFuzzer(t *testing.T) { - actualVal := Float32(0.6063452) + actualVal := Float32(0.73096776) - assert.Equal(t, float32(0.6063452), actualVal) + assert.Equal(t, float32(0.73096776), actualVal) } func TestFloat64ByUtGoFuzzer(t *testing.T) { - actualVal := Float64(0.6374174253501083) + actualVal := Float64(0.8314409887870612) - assert.Equal(t, 0.6374174253501083, actualVal) + assert.Equal(t, 0.8314409887870612, actualVal) } func TestComplex64ByUtGoFuzzer(t *testing.T) { - actualVal := Complex64(complex(0.550437, 0.550437)) + actualVal := Complex64(complex(0.6063452, 0.6063452)) - assert.Equal(t, complex(float32(0.550437), float32(0.550437)), actualVal) + assert.Equal(t, complex(float32(0.6063452), float32(0.6063452)), actualVal) } func TestComplex128ByUtGoFuzzer(t *testing.T) { - actualVal := Complex128(complex(0.11700660880722513, 0.11700660880722513)) + actualVal := Complex128(complex(0.6374174253501083, 0.6374174253501083)) - assert.Equal(t, complex(0.11700660880722513, 0.11700660880722513), actualVal) + assert.Equal(t, complex(0.6374174253501083, 0.6374174253501083), actualVal) } func TestByteByUtGoFuzzer(t *testing.T) { @@ -156,15 +155,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.7815346, float64: 0.3332183994766498, complex64: complex(0.7815346, 0.7815346), complex128: complex(0.3332183994766498, 0.3332183994766498), 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.7815346, float64: 0.3332183994766498, complex64: complex(float32(0.7815346), float32(0.7815346)), complex128: complex(0.3332183994766498, 0.3332183994766498), 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.38518918, float64: 0.6130357680446138, complex64: complex(0.38518918, 0.38518918), complex128: complex(0.6130357680446138, 0.6130357680446138), 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.38518918, float64: math.NaN(), complex64: complex(float32(0.38518918), float32(0.38518918)), complex128: complex(0.6130357680446138, 0.6130357680446138), byte: 0, rune: -1, string: "", bool: false}, actualVal) + assert.NotEqual(t, Structure{}, actualVal) } func TestArrayOfIntByUtGoFuzzer(t *testing.T) { @@ -186,15 +185,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.9828195, float64: 0.8791825178724801, complex64: complex(0.9828195, 0.9828195), complex128: complex(0.8791825178724801, 0.8791825178724801), 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.9828195, float64: 0.8791825178724801, 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.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.94124913, float64: 0.17597680203548016, complex64: complex(0.94124913, 0.94124913), complex128: complex(0.17597680203548016, 0.17597680203548016), 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.94124913, float64: math.NaN(), complex64: complex(float32(0.94124913), float32(0.94124913)), complex128: complex(0.17597680203548016, 0.17597680203548016), 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) { @@ -206,7 +205,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) { @@ -228,15 +227,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.14660162, float64: 0.7051747444754559, complex64: complex(0.14660162, 0.14660162), complex128: complex(0.7051747444754559, 0.7051747444754559), byte: 1, rune: 0, string: "", bool: false}) + actualVal := ExternalStruct(difflib.Match{A: 1, B: 9223372036854775807, 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.14660162, float64: 0.7051747444754559, complex64: complex(float32(0.14660162), float32(0.14660162)), complex128: complex(0.7051747444754559, 0.7051747444754559), 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: 9223372036854775807, Size: 1}) - assert.Equal(t, difflib.Match{A: 9223372036854775807, B: -1, Size: -9223372036854775808}, actualVal) + assert.Equal(t, difflib.Match{A: 1, B: 9223372036854775807, Size: 1}, actualVal) } func TestSliceOfIntByUtGoFuzzer(t *testing.T) { @@ -258,19 +257,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.0013866425, float64: 0.5467397571984656, complex64: complex(0.0013866425, 0.0013866425), complex128: complex(0.5467397571984656, 0.5467397571984656), 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.0013866425, float64: 0.5467397571984656, complex64: complex(float32(0.0013866425), float32(0.0013866425)), complex128: complex(0.5467397571984656, 0.5467397571984656), 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.96448684, float64: 0.5629496738983792, complex64: complex(0.96448684, 0.96448684), complex128: complex(0.5629496738983792, 0.5629496738983792), 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.96448684, float64: math.NaN(), complex64: complex(float32(0.96448684), float32(0.96448684)), complex128: complex(0.5629496738983792, 0.5629496738983792), byte: 255, rune: 2147483647, string: "", bool: false}}, actualVal) -} - -func TestSliceOfStructsWithNanPanicsByUtGoFuzzer(t *testing.T) { - assert.PanicsWithError(t, "runtime error: index out of range [0] with length 0", func() { SliceOfStructsWithNan([]Structure{}) }) + assert.NotEqual(t, []Structure{{}}, actualVal) } func TestSliceOfSliceOfByteByUtGoFuzzer(t *testing.T) { @@ -290,3 +285,45 @@ func TestSliceOfArrayOfIntByUtGoFuzzer(t *testing.T) { assert.Equal(t, [][5]int{{0, 0, 0, 0, 0}}, 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{-1, 0, 0, -1}}) + + 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{-1, 0, 0, -1}}, 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..7e34162e8e 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,8 @@ fun goDefaultValueProviders() = listOf( GoArrayValueProvider, GoSliceValueProvider, GoStructValueProvider, - GoConstantValueProvider + GoConstantValueProvider, + GoNamedValueProvider, ) 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 f5fa7649e4..60b7f43be4 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 @@ -28,37 +28,21 @@ class GoPrimitiveTypeId(name: String) : GoTypeId(name) { class GoStructTypeId( name: String, - implementsError: Boolean, - override val sourcePackage: GoPackage, val fields: List, -) : GoTypeId(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() } } @@ -90,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 } @@ -98,22 +82,38 @@ 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, + 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.packageName != "") { + "${sourcePackage.packageName}.$name" } else { - simpleName + name } 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}" @@ -124,9 +124,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 d043d6144a..f72c18c86e 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 @@ -153,18 +153,20 @@ fun GoTypeId.goDefaultValueModel(): GoUtModel = when (this) { is GoStructTypeId -> GoUtStructModel(listOf(), this) is GoArrayTypeId -> GoUtArrayModel(hashMapOf(), this) is GoSliceTypeId -> GoUtSliceModel(hashMapOf(), this, 0) + is GoNamedTypeId -> GoUtNamedModel(this.underlyingTypeId.goDefaultValueModel(), this) else -> GoUtNilModel(this) } -fun GoTypeId.getAllStructTypes(): Set = when (this) { - is GoStructTypeId -> fields.fold(setOf(this)) { acc: Set, field -> - acc + (field.declaringType).getAllStructTypes() +fun GoTypeId.getAllNamedTypes(): Set = when (this) { + is GoStructTypeId -> fields.fold(emptySet()) { acc: Set, field -> + acc + (field.declaringType).getAllNamedTypes() } - is GoArrayTypeId, is GoSliceTypeId -> elementTypeId!!.getAllStructTypes() + is GoArrayTypeId, is GoSliceTypeId -> elementTypeId!!.getAllNamedTypes() + is GoNamedTypeId -> setOf(this) + underlyingTypeId.getAllNamedTypes() else -> emptySet() } -fun List.getAllStructTypes(): Set = this.fold(emptySet()) { acc, type -> - acc + type.getAllStructTypes() +fun List.getAllNamedTypes(): Set = this.fold(emptySet()) { acc, type -> + acc + type.getAllNamedTypes() } 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..f985d07096 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), 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 c2f0ed3ce2..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 @@ -58,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/gocodeanalyzer/AnalysisResults.kt b/utbot-go/src/main/kotlin/org/utbot/go/gocodeanalyzer/AnalysisResults.kt index d3e60a9b48..41e6df18c4 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 9fff1c5edc..f2c1e465b4 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.getAllStructTypes +import org.utbot.go.api.util.getAllNamedTypes 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.getAllStructTypes() + val namedTypes = types.getAllNamedTypes() 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..22e711652d 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) @@ -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..001ed75c61 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 @@ -18,16 +18,32 @@ 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 -> 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 +62,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) { + "$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 01cf8760f7..70e7d73ecb 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 { @@ -586,13 +651,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) @@ -604,7 +669,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'") @@ -616,12 +681,34 @@ 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 { @@ -647,7 +734,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) @@ -684,7 +771,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) @@ -708,23 +795,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 } } @@ -754,7 +831,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__{ @@ -766,7 +843,7 @@ object GoCodeTemplates { """.trimIndent() fun getTopLevelHelperStructsAndFunctionsForWorker( - structTypes: Set, + namedTypes: Set, destinationPackage: GoPackage, aliases: Map, maxTraceLength: Int, @@ -782,7 +859,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 1d4e7b6806..682fd51f2d 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.getAllStructTypes +import org.utbot.go.api.util.getAllNamedTypes 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.getAllStructTypes() val aliases = imports.associate { it.goPackage to it.alias } + val namedTypes = types.getAllNamedTypes() 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 cb9e714e4e..8c3fb46130 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 @@ -14,17 +14,27 @@ data class PrimitiveValue( override val value: String, ) : RawValue(type, value) { 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, + override val value: RawValue, +) : RawValue(type, value) { + override fun checkIsEqualTypes(type: GoTypeId): Boolean = error("Not supported") +} + data class StructValue( override val type: String, override val value: List @@ -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) { @@ -67,6 +77,9 @@ data class ArrayValue( override val value: List ) : RawValue(type, value) { override fun checkIsEqualTypes(type: GoTypeId): Boolean { + if (type is GoNamedTypeId) { + return checkIsEqualTypes(type.underlyingTypeId) + } if (type !is GoArrayTypeId) { return false } @@ -84,6 +97,9 @@ data class SliceValue( override val value: List ) : RawValue(type, value) { override fun checkIsEqualTypes(type: GoTypeId): Boolean { + if (type is GoNamedTypeId) { + return checkIsEqualTypes(type.underlyingTypeId) + } if (type !is GoSliceTypeId) { return false } @@ -178,23 +194,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 3d8f08bf43..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,14 +2,18 @@ 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"` - PackageName string `json:"packageName"` - PackagePath string `json:"packagePath"` + SourcePackage GoPackage `json:"sourcePackage"` ImplementsError bool `json:"implementsError"` UnderlyingType AnalyzedType `json:"underlyingType"` } 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 f8131fa51d..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 @@ -45,9 +45,11 @@ func toAnalyzedType(typ types.Type) (AnalyzedType, error) { checkError(err) result = AnalyzedNamedType{ - Name: name, - PackageName: packageName, - PackagePath: packagePath, + Name: name, + SourcePackage: GoPackage{ + PackageName: packageName, + PackagePath: packagePath, + }, ImplementsError: isError, UnderlyingType: underlyingType, } From 04998c3e1a18e69a9601656be5cd355df8cde391 Mon Sep 17 00:00:00 2001 From: Egipti Pavel Date: Mon, 27 Mar 2023 11:46:52 +0300 Subject: [PATCH 4/6] Fix canonicalName in GoNamedTypeId --- utbot-go/src/main/kotlin/org/utbot/go/api/GoTypesApi.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 60b7f43be4..2ebf202a4b 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 @@ -105,10 +105,10 @@ class GoNamedTypeId( ) : GoTypeId(name, implementsError = implementsError) { val packageName: String = sourcePackage.packageName val packagePath: String = sourcePackage.packagePath - override val canonicalName: String = if (sourcePackage.packageName != "") { - "${sourcePackage.packageName}.$name" - } else { + override val canonicalName: String = if (sourcePackage.isBuiltin) { name + } else { + "${sourcePackage.packageName}.$name" } override fun getRelativeName(destinationPackage: GoPackage, aliases: Map): String { From 934963c7ca21b52d8176e0a7a2b2035498334d1d Mon Sep 17 00:00:00 2001 From: Egipti Pavel Date: Mon, 27 Mar 2023 18:25:20 +0300 Subject: [PATCH 5/6] Fix redundant type conversion --- .../go/simplecodegeneration/GoTestCasesCodeGenerator.kt | 2 +- .../go/simplecodegeneration/GoUtModelToCodeConverter.kt | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) 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 22e711652d..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 @@ -235,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" } 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 001ed75c61..793801c68a 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) { @@ -22,7 +22,11 @@ class GoUtModelToCodeConverter( is GoUtSliceModel -> sliceModelToGoCode(model) - is GoUtNamedModel -> namedModelToGoCode(model) + 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") } From 7e728d7fd8d80dbc5084463c7d8e33ef623edac8 Mon Sep 17 00:00:00 2001 From: Egipti Pavel Date: Mon, 27 Mar 2023 19:22:35 +0300 Subject: [PATCH 6/6] Add nil value provider --- .../main/kotlin/org/utbot/go/GoLanguage.kt | 1 + .../org/utbot/go/api/util/GoTypesApiUtil.kt | 13 +++++---- .../utbot/go/api/util/GoUtModelsApiUtil.kt | 3 +- .../go/fuzzer/providers/GoNilValueProvider.kt | 16 +++++++++++ .../GoUtModelToCodeConverter.kt | 2 +- .../org/utbot/go/worker/GoCodeTemplates.kt | 2 +- .../utbot/go/worker/RawExecutionResults.kt | 28 +++++++++++-------- 7 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 utbot-go/src/main/kotlin/org/utbot/go/fuzzer/providers/GoNilValueProvider.kt 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 7e34162e8e..becfd20495 100644 --- a/utbot-go/src/main/kotlin/org/utbot/go/GoLanguage.kt +++ b/utbot-go/src/main/kotlin/org/utbot/go/GoLanguage.kt @@ -15,6 +15,7 @@ fun goDefaultValueProviders() = listOf( GoStructValueProvider, GoConstantValueProvider, GoNamedValueProvider, + GoNilValueProvider ) class GoInstruction( 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 1932f7f814..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,14 +148,14 @@ 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) + is GoSliceTypeId -> GoUtNilModel(this) is GoNamedTypeId -> GoUtNamedModel(this.underlyingTypeId.goDefaultValueModel(), this) - else -> GoUtNilModel(this) + else -> error("Generating Go default value model for ${this.javaClass} is not supported") } fun GoTypeId.getAllVisibleNamedTypes(goPackage: GoPackage): Set = when (this) { @@ -173,6 +173,7 @@ fun GoTypeId.getAllVisibleNamedTypes(goPackage: GoPackage): Set = else -> emptySet() } -fun List.getAllVisibleNamedTypes(goPackage: GoPackage): Set = this.fold(emptySet()) { acc, type -> - acc + type.getAllVisibleNamedTypes(goPackage) -} +fun List.getAllVisibleNamedTypes(goPackage: GoPackage): Set = + this.fold(emptySet()) { acc, type -> + 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 f985d07096..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 @@ -34,7 +34,6 @@ fun GoUtModel.convertToRawValue(destinationPackage: GoPackage, aliases: Map SliceValue( model.typeId.getRelativeName(destinationPackage, aliases), model.typeId.elementTypeId!!.getRelativeName(destinationPackage, aliases), @@ -54,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/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/simplecodegeneration/GoUtModelToCodeConverter.kt b/utbot-go/src/main/kotlin/org/utbot/go/simplecodegeneration/GoUtModelToCodeConverter.kt index 793801c68a..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 @@ -94,7 +94,7 @@ class GoUtModelToCodeConverter( private fun namedModelToGoCode(model: GoUtNamedModel): String { val typeName = model.typeId.getRelativeName(destinationPackage, aliases) - return if (model.value is GoUtPrimitiveModel) { + 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 ee45331ef5..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 @@ -716,7 +716,7 @@ object GoCodeTemplates { 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 { 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 3ade01a38b..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,8 +11,8 @@ 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 is GoNamedTypeId) { return checkIsEqualTypes(type.underlyingTypeId) @@ -30,15 +30,15 @@ data class PrimitiveValue( data class NamedValue( override val type: String, - override val value: RawValue, -) : RawValue(type, value) { + 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, @@ -74,8 +74,8 @@ 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) @@ -94,8 +94,8 @@ 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) @@ -110,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 }