Skip to content

Commit c57cc4b

Browse files
authored
Go. Support for all user-defined types (#2056)
* Add supports for user-defined types on Go side * Change type names to canonical * Add support for named types * Fix canonicalName in GoNamedTypeId * Fix redundant type conversion * Add nil value provider
1 parent b56ba76 commit c57cc4b

File tree

20 files changed

+576
-334
lines changed

20 files changed

+576
-334
lines changed

utbot-go/go-samples/simple/samples_go_ut_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,29 +46,29 @@ func TestGenerateArrayOfIntegersByUtGoFuzzer(t *testing.T) {
4646
}
4747

4848
func TestDistanceBetweenTwoPointsByUtGoFuzzer(t *testing.T) {
49-
actualVal := DistanceBetweenTwoPoints(Point{x: 0.730967787376657, y: 0.730967787376657}, Point{x: 2.0, y: 2.0})
49+
actualVal := DistanceBetweenTwoPoints(Point{}, Point{})
5050

51-
assert.Equal(t, 1.794682566180269, actualVal)
51+
assert.Equal(t, 0.0, actualVal)
5252
}
5353

5454
func TestGetCoordinatesOfMiddleBetweenTwoPointsByUtGoFuzzer(t *testing.T) {
55-
actualVal0, actualVal1 := GetCoordinatesOfMiddleBetweenTwoPoints(Point{x: 0.24053641567148587, y: 0.24053641567148587}, Point{x: 2.0, y: 2.0})
55+
actualVal0, actualVal1 := GetCoordinatesOfMiddleBetweenTwoPoints(Point{}, Point{})
5656

5757
assertMultiple := assert.New(t)
58-
assertMultiple.Equal(1.1202682078357429, actualVal0)
59-
assertMultiple.Equal(1.1202682078357429, actualVal1)
58+
assertMultiple.Equal(0.0, actualVal0)
59+
assertMultiple.Equal(0.0, actualVal1)
6060
}
6161

6262
func TestGetCoordinateSumOfPointsByUtGoFuzzer(t *testing.T) {
63-
actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{x: 0.6374174253501083, y: 0.6374174253501083}})
63+
actualVal0, actualVal1 := GetCoordinateSumOfPoints([]Point{{}})
6464

6565
assertMultiple := assert.New(t)
66-
assertMultiple.Equal(0.6374174253501083, actualVal0)
67-
assertMultiple.Equal(0.6374174253501083, actualVal1)
66+
assertMultiple.Equal(0.0, actualVal0)
67+
assertMultiple.Equal(0.0, actualVal1)
6868
}
6969

7070
func TestGetAreaOfCircleByUtGoFuzzer(t *testing.T) {
71-
actualVal := GetAreaOfCircle(Circle{Center: Point{x: 0.5504370051176339, y: 0.5504370051176339}, Radius: 2.0})
71+
actualVal := GetAreaOfCircle(Circle{Center: Point{}, Radius: 2.0})
7272

7373
assert.Equal(t, 12.566370614359172, actualVal)
7474
}
@@ -155,4 +155,4 @@ func TestStringSearchByUtGoFuzzer5(t *testing.T) {
155155
actualVal := StringSearch("ABC")
156156

157157
assert.Equal(t, true, actualVal)
158-
}
158+
}

utbot-go/go-samples/simple/supported_types.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,46 @@ func SliceOfArrayOfInt(slice [][5]int) [][5]int {
219219
func ExportedStructWithEmbeddedUnexportedStruct(exportedStruct nested.ExportedStruct) nested.ExportedStruct {
220220
return exportedStruct
221221
}
222+
223+
type Type byte
224+
225+
func NamedType(n Type) Type {
226+
return n
227+
}
228+
229+
func ArrayOfNamedType(array [5]Type) [5]Type {
230+
return array
231+
}
232+
233+
type T [5][5]Type
234+
235+
func ArrayOfArrayOfNamedType(array [5][5]Type) T {
236+
return array
237+
}
238+
239+
func SliceOfNamedType(slice []Type) []Type {
240+
return slice
241+
}
242+
243+
type NA [5]uintptr
244+
245+
func NamedArray(array NA) NA {
246+
return array
247+
}
248+
249+
type NS []int
250+
251+
func NamedSlice(slice NS) NS {
252+
return slice
253+
}
254+
255+
type S struct {
256+
t Type
257+
T
258+
n NA
259+
NS
260+
}
261+
262+
func StructWithFieldsOfNamedTypes(s S) S {
263+
return s
264+
}

utbot-go/go-samples/simple/supported_types_go_ut_test.go

Lines changed: 67 additions & 26 deletions
Large diffs are not rendered by default.

utbot-go/src/main/kotlin/org/utbot/go/GoLanguage.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ fun goDefaultValueProviders() = listOf(
1313
GoArrayValueProvider,
1414
GoSliceValueProvider,
1515
GoStructValueProvider,
16-
GoConstantValueProvider
16+
GoConstantValueProvider,
17+
GoNamedValueProvider,
18+
GoNilValueProvider
1719
)
1820

1921
class GoInstruction(

utbot-go/src/main/kotlin/org/utbot/go/api/GoTypesApi.kt

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.utbot.go.api
22

33
import org.utbot.go.framework.api.go.GoFieldId
4-
import org.utbot.go.framework.api.go.GoNamedTypeId
54
import org.utbot.go.framework.api.go.GoPackage
65
import org.utbot.go.framework.api.go.GoTypeId
76

@@ -29,37 +28,21 @@ class GoPrimitiveTypeId(name: String) : GoTypeId(name) {
2928

3029
class GoStructTypeId(
3130
name: String,
32-
implementsError: Boolean,
33-
override val sourcePackage: GoPackage,
3431
val fields: List<GoFieldId>,
35-
) : GoNamedTypeId(name, implementsError = implementsError) {
36-
val packageName: String = sourcePackage.packageName
37-
val packagePath: String = sourcePackage.packagePath
38-
override val canonicalName: String = "${sourcePackage.packageName}.$name"
32+
) : GoTypeId(name) {
33+
override val canonicalName: String = name
3934

40-
override fun getRelativeName(destinationPackage: GoPackage, aliases: Map<GoPackage, String?>): String {
41-
val alias = aliases[sourcePackage]
42-
return if (sourcePackage == destinationPackage || alias == ".") {
43-
simpleName
44-
} else if (alias == null) {
45-
"${packageName}.${simpleName}"
46-
} else {
47-
"${alias}.${simpleName}"
48-
}
49-
}
35+
override fun getRelativeName(destinationPackage: GoPackage, aliases: Map<GoPackage, String?>): String = simpleName
5036

5137
override fun equals(other: Any?): Boolean {
5238
if (this === other) return true
5339
if (other !is GoStructTypeId) return false
5440

55-
return packagePath == other.packagePath && packageName == other.packageName && name == other.name
41+
return fields == other.fields
5642
}
5743

5844
override fun hashCode(): Int {
59-
var result = packagePath.hashCode()
60-
result = 31 * result + packageName.hashCode()
61-
result = 31 * result + name.hashCode()
62-
return result
45+
return fields.hashCode()
6346
}
6447
}
6548

@@ -91,30 +74,48 @@ class GoSliceTypeId(
9174

9275
override fun equals(other: Any?): Boolean {
9376
if (this === other) return true
94-
if (other !is GoArrayTypeId) return false
77+
if (other !is GoSliceTypeId) return false
9578

9679
return elementTypeId == other.elementTypeId
9780
}
9881

9982
override fun hashCode(): Int = elementTypeId.hashCode()
10083
}
10184

102-
class GoInterfaceTypeId(
85+
class GoInterfaceTypeId(name: String) : GoTypeId(name) {
86+
override val canonicalName: String = name
87+
88+
override fun getRelativeName(destinationPackage: GoPackage, aliases: Map<GoPackage, String?>): String = simpleName
89+
90+
override fun equals(other: Any?): Boolean {
91+
if (this === other) return true
92+
if (other !is GoInterfaceTypeId) return false
93+
94+
return name == other.name
95+
}
96+
97+
override fun hashCode(): Int = name.hashCode()
98+
}
99+
100+
class GoNamedTypeId(
103101
name: String,
104-
implementsError: Boolean,
105102
override val sourcePackage: GoPackage,
106-
) : GoNamedTypeId(name, implementsError = implementsError) {
103+
implementsError: Boolean,
104+
val underlyingTypeId: GoTypeId
105+
) : GoTypeId(name, implementsError = implementsError) {
107106
val packageName: String = sourcePackage.packageName
108107
val packagePath: String = sourcePackage.packagePath
109-
override val canonicalName: String = if (packageName != "") {
110-
"$packageName.$name"
108+
override val canonicalName: String = if (sourcePackage.isBuiltin) {
109+
name
111110
} else {
112-
simpleName
111+
"${sourcePackage.packageName}.$name"
113112
}
114113

114+
fun exported(): Boolean = name.first().isUpperCase()
115+
115116
override fun getRelativeName(destinationPackage: GoPackage, aliases: Map<GoPackage, String?>): String {
116117
val alias = aliases[sourcePackage]
117-
return if (sourcePackage == destinationPackage || alias == ".") {
118+
return if (sourcePackage.isBuiltin || sourcePackage == destinationPackage || alias == ".") {
118119
simpleName
119120
} else if (alias == null) {
120121
"${packageName}.${simpleName}"
@@ -125,9 +126,9 @@ class GoInterfaceTypeId(
125126

126127
override fun equals(other: Any?): Boolean {
127128
if (this === other) return true
128-
if (other !is GoInterfaceTypeId) return false
129+
if (other !is GoNamedTypeId) return false
129130

130-
return packagePath == other.packagePath && packageName == other.packageName && name == other.name
131+
return sourcePackage == other.sourcePackage && name == other.name
131132
}
132133

133134
override fun hashCode(): Int {

utbot-go/src/main/kotlin/org/utbot/go/api/GoUtModelsApi.kt

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class GoUtStructModel(
4747
value.filter { typeId.sourcePackage == destinationPackage || it.fieldId.isExported }
4848

4949
override fun getRequiredPackages(destinationPackage: GoPackage): Set<GoPackage> =
50-
getVisibleFields(destinationPackage).fold(setOf(typeId.sourcePackage)) { acc, fieldModel ->
50+
getVisibleFields(destinationPackage).fold(emptySet()) { acc, fieldModel ->
5151
acc + fieldModel.getRequiredPackages(destinationPackage)
5252
}
5353

@@ -68,14 +68,19 @@ class GoUtArrayModel(
6868
get() = super.typeId as GoArrayTypeId
6969

7070
override fun getRequiredPackages(destinationPackage: GoPackage): Set<GoPackage> {
71-
val elementStructTypeId = typeId.elementTypeId as? GoStructTypeId
72-
val imports = if (elementStructTypeId != null && elementStructTypeId.sourcePackage != destinationPackage) {
73-
mutableSetOf(elementStructTypeId.sourcePackage)
74-
} else {
75-
mutableSetOf()
71+
val elementNamedTypeId = typeId.elementTypeId as? GoNamedTypeId
72+
val imports =
73+
if (elementNamedTypeId != null &&
74+
!elementNamedTypeId.sourcePackage.isBuiltin &&
75+
elementNamedTypeId.sourcePackage != destinationPackage
76+
) {
77+
setOf(elementNamedTypeId.sourcePackage)
78+
} else {
79+
emptySet()
80+
}
81+
return value.values.fold(imports) { acc, model ->
82+
acc + model.getRequiredPackages(destinationPackage)
7683
}
77-
value.values.map { it.getRequiredPackages(destinationPackage) }.forEach { imports += it }
78-
return imports
7984
}
8085

8186
override fun isComparable(): Boolean = value.values.all { it.isComparable() }
@@ -98,14 +103,19 @@ class GoUtSliceModel(
98103
get() = super.typeId as GoSliceTypeId
99104

100105
override fun getRequiredPackages(destinationPackage: GoPackage): Set<GoPackage> {
101-
val elementStructTypeId = typeId.elementTypeId as? GoStructTypeId
102-
val imports = if (elementStructTypeId != null && elementStructTypeId.sourcePackage != destinationPackage) {
103-
mutableSetOf(elementStructTypeId.sourcePackage)
104-
} else {
105-
mutableSetOf()
106+
val elementNamedTypeId = typeId.elementTypeId as? GoNamedTypeId
107+
val imports =
108+
if (elementNamedTypeId != null &&
109+
!elementNamedTypeId.sourcePackage.isBuiltin &&
110+
elementNamedTypeId.sourcePackage != destinationPackage
111+
) {
112+
setOf(elementNamedTypeId.sourcePackage)
113+
} else {
114+
emptySet()
115+
}
116+
return value.values.fold(imports) { acc, model ->
117+
acc + model.getRequiredPackages(destinationPackage)
106118
}
107-
value.values.map { it.getRequiredPackages(destinationPackage) }.forEach { imports += it }
108-
return imports
109119
}
110120

111121
override fun isComparable(): Boolean = value.values.all { it.isComparable() }
@@ -167,4 +177,23 @@ class GoUtNilModel(
167177
) : GoUtModel(typeId) {
168178
override fun isComparable(): Boolean = true
169179
override fun toString() = "nil"
180+
}
181+
182+
class GoUtNamedModel(
183+
var value: GoUtModel,
184+
typeId: GoNamedTypeId,
185+
) : GoUtModel(typeId) {
186+
override val typeId: GoNamedTypeId
187+
get() = super.typeId as GoNamedTypeId
188+
189+
override fun getRequiredPackages(destinationPackage: GoPackage): Set<GoPackage> {
190+
val import = if (!typeId.sourcePackage.isBuiltin && typeId.sourcePackage != destinationPackage) {
191+
setOf(typeId.sourcePackage)
192+
} else {
193+
emptySet()
194+
}
195+
return import + value.getRequiredPackages(destinationPackage)
196+
}
197+
198+
override fun isComparable(): Boolean = value.isComparable()
170199
}

utbot-go/src/main/kotlin/org/utbot/go/api/util/GoTypesApiUtil.kt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,29 +148,32 @@ fun GoTypeId.goDefaultValueModel(): GoUtModel = when (this) {
148148
goStringTypeId -> GoUtPrimitiveModel("", this)
149149
goUintPtrTypeId -> GoUtPrimitiveModel(0, this)
150150

151-
else -> error("Go primitive ${this.javaClass} is not supported")
151+
else -> error("Generating Go default value model for ${this.javaClass} is not supported")
152152
}
153153

154154
is GoStructTypeId -> GoUtStructModel(listOf(), this)
155155
is GoArrayTypeId -> GoUtArrayModel(hashMapOf(), this)
156-
is GoSliceTypeId -> GoUtSliceModel(hashMapOf(), this, 0)
157-
else -> GoUtNilModel(this)
156+
is GoSliceTypeId -> GoUtNilModel(this)
157+
is GoNamedTypeId -> GoUtNamedModel(this.underlyingTypeId.goDefaultValueModel(), this)
158+
else -> error("Generating Go default value model for ${this.javaClass} is not supported")
158159
}
159160

160-
fun GoTypeId.getAllVisibleStructTypes(goPackage: GoPackage): Set<GoStructTypeId> = when (this) {
161-
is GoStructTypeId -> if (this.sourcePackage == goPackage || this.exported()) {
162-
fields.fold(setOf(this)) { acc: Set<GoStructTypeId>, field ->
163-
acc + (field.declaringType).getAllVisibleStructTypes(goPackage)
164-
}
161+
fun GoTypeId.getAllVisibleNamedTypes(goPackage: GoPackage): Set<GoNamedTypeId> = when (this) {
162+
is GoStructTypeId -> fields.fold(emptySet()) { acc: Set<GoNamedTypeId>, field ->
163+
acc + (field.declaringType).getAllVisibleNamedTypes(goPackage)
164+
}
165+
166+
is GoArrayTypeId, is GoSliceTypeId -> elementTypeId!!.getAllVisibleNamedTypes(goPackage)
167+
is GoNamedTypeId -> if (this.sourcePackage == goPackage || this.exported()) {
168+
setOf(this) + underlyingTypeId.getAllVisibleNamedTypes(goPackage)
165169
} else {
166170
emptySet()
167171
}
168172

169-
is GoArrayTypeId, is GoSliceTypeId -> elementTypeId!!.getAllVisibleStructTypes(goPackage)
170173
else -> emptySet()
171174
}
172175

173-
fun List<GoTypeId>.getAllVisibleStructTypes(goPackage: GoPackage): Set<GoStructTypeId> =
176+
fun List<GoTypeId>.getAllVisibleNamedTypes(goPackage: GoPackage): Set<GoNamedTypeId> =
174177
this.fold(emptySet()) { acc, type ->
175-
acc + type.getAllVisibleStructTypes(goPackage)
178+
acc + type.getAllVisibleNamedTypes(goPackage)
176179
}

utbot-go/src/main/kotlin/org/utbot/go/api/util/GoUtModelsApiUtil.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,18 @@ fun GoUtModel.convertToRawValue(destinationPackage: GoPackage, aliases: Map<GoPa
2222
"${model.realValue}@${model.imagValue}"
2323
)
2424

25+
is GoUtNamedModel -> NamedValue(
26+
model.typeId.getRelativeName(destinationPackage, aliases),
27+
model.value.convertToRawValue(destinationPackage, aliases)
28+
)
29+
2530
is GoUtArrayModel -> ArrayValue(
2631
model.typeId.getRelativeName(destinationPackage, aliases),
2732
model.typeId.elementTypeId!!.getRelativeName(destinationPackage, aliases),
2833
model.length,
2934
model.getElements().map { it.convertToRawValue(destinationPackage, aliases) }
3035
)
3136

32-
3337
is GoUtSliceModel -> SliceValue(
3438
model.typeId.getRelativeName(destinationPackage, aliases),
3539
model.typeId.elementTypeId!!.getRelativeName(destinationPackage, aliases),
@@ -49,6 +53,6 @@ fun GoUtModel.convertToRawValue(destinationPackage: GoPackage, aliases: Map<GoPa
4953
)
5054

5155
is GoUtPrimitiveModel -> PrimitiveValue(model.typeId.name, model.value.toString())
52-
56+
is GoUtNilModel -> NilValue(model.typeId.getRelativeName(destinationPackage, aliases))
5357
else -> error("Converting ${model.javaClass} to RawValue is not supported")
5458
}

0 commit comments

Comments
 (0)