Skip to content

Commit cbc4829

Browse files
authored
Go. Maps support (#2114)
* Fix raw values * Remove function __typeConversionToNamedType__ * Refactor serialization and deserialization of raw values * Fix lenght of slice * Add logging of number of function executions * Add maps support
1 parent 9e2eaae commit cbc4829

19 files changed

+940
-544
lines changed

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,39 +92,39 @@ func TestIsIdentityByUtGoFuzzer3(t *testing.T) {
9292
}
9393

9494
func TestBinaryWithNonNilErrorByUtGoFuzzer1(t *testing.T) {
95-
actualVal, actualErr := Binary([]int{1}, 2, 0, -1)
95+
actualVal, actualErr := Binary(nil, 2, 0, -1)
9696

9797
assertMultiple := assert.New(t)
9898
assertMultiple.Equal(-1, actualVal)
9999
assertMultiple.ErrorContains(actualErr, "target not found in array")
100100
}
101101

102-
func TestBinaryByUtGoFuzzer2(t *testing.T) {
103-
actualVal, actualErr := Binary([]int{9223372036854775807, -1, -1, -1, -1}, 9223372036854775807, 0, 1)
102+
func TestBinaryWithNonNilErrorByUtGoFuzzer2(t *testing.T) {
103+
actualVal, actualErr := Binary([]int{1, 1, 0}, 2, 1, 1)
104104

105105
assertMultiple := assert.New(t)
106-
assertMultiple.Equal(0, actualVal)
107-
assertMultiple.Nil(actualErr)
106+
assertMultiple.Equal(-1, actualVal)
107+
assertMultiple.ErrorContains(actualErr, "target not found in array")
108108
}
109109

110110
func TestBinaryWithNonNilErrorByUtGoFuzzer3(t *testing.T) {
111-
actualVal, actualErr := Binary([]int{1, 17592186044417, 257, 1125899906842625}, -9223372036854775808, 1, 2)
111+
actualVal, actualErr := Binary([]int{1, 1, 0}, -9214364837600034814, 1, 1)
112112

113113
assertMultiple := assert.New(t)
114114
assertMultiple.Equal(-1, actualVal)
115115
assertMultiple.ErrorContains(actualErr, "target not found in array")
116116
}
117117

118118
func TestBinaryWithNonNilErrorByUtGoFuzzer4(t *testing.T) {
119-
actualVal, actualErr := Binary([]int{-1, -1, -1, -1, 9223372036854775807}, 9223372036854775807, 0, 1)
119+
actualVal, actualErr := Binary([]int{9223372036854775807, 9223372036854775807, 1, 9223372036854775807, -9223372036854775808}, 9223372036854775807, -1, 1)
120120

121121
assertMultiple := assert.New(t)
122-
assertMultiple.Equal(-1, actualVal)
123-
assertMultiple.ErrorContains(actualErr, "target not found in array")
122+
assertMultiple.Equal(0, actualVal)
123+
assertMultiple.Nil(actualErr)
124124
}
125125

126126
func TestBinaryPanicsByUtGoFuzzer(t *testing.T) {
127-
assert.PanicsWithError(t, "runtime error: index out of range [-4611686018427387905]", func() { Binary([]int{1}, 2, -9223372036854775808, -1) })
127+
assert.PanicsWithError(t, "runtime error: index out of range [-4611686018427387905]", func() { Binary(nil, 2, -9223372036854775808, -1) })
128128
}
129129

130130
func TestStringSearchByUtGoFuzzer1(t *testing.T) {
@@ -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: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,29 @@ type S struct {
262262
func StructWithFieldsOfNamedTypes(s S) S {
263263
return s
264264
}
265+
266+
func Map(table map[string]int) map[string]int {
267+
return table
268+
}
269+
270+
func MapOfStructures(table map[Structure]Structure) map[Structure]Structure {
271+
return table
272+
}
273+
274+
func MapOfSliceOfInt(table map[string][]int) map[string][]int {
275+
return table
276+
}
277+
278+
func MapOfNamedType(table map[int]Type) map[int]Type {
279+
return table
280+
}
281+
282+
func MapOfNamedSlice(table map[uint]NS) map[uint]NS {
283+
return table
284+
}
285+
286+
type NM map[string]NA
287+
288+
func NamedMap(n NM) NM {
289+
return n
290+
}

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

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -108,27 +108,27 @@ func TestUintPtrByUtGoFuzzer(t *testing.T) {
108108
}
109109

110110
func TestFloat32ByUtGoFuzzer(t *testing.T) {
111-
actualVal := Float32(0.24053639)
111+
actualVal := Float32(0.59754527)
112112

113-
assert.Equal(t, float32(0.24053639), actualVal)
113+
assert.Equal(t, float32(0.59754527), actualVal)
114114
}
115115

116116
func TestFloat64ByUtGoFuzzer(t *testing.T) {
117-
actualVal := Float64(0.6063452159973596)
117+
actualVal := Float64(0.7815346320453048)
118118

119-
assert.Equal(t, 0.6063452159973596, actualVal)
119+
assert.Equal(t, 0.7815346320453048, actualVal)
120120
}
121121

122122
func TestComplex64ByUtGoFuzzer(t *testing.T) {
123-
actualVal := Complex64(complex(0.30905056, 0.30905056))
123+
actualVal := Complex64(complex(0.25277615, 0.25277615))
124124

125-
assert.Equal(t, complex(float32(0.30905056), float32(0.30905056)), actualVal)
125+
assert.Equal(t, complex(float32(0.25277615), float32(0.25277615)), actualVal)
126126
}
127127

128128
func TestComplex128ByUtGoFuzzer(t *testing.T) {
129-
actualVal := Complex128(complex(0.5504370051176339, 0.5504370051176339))
129+
actualVal := Complex128(complex(0.3851891847407185, 0.3851891847407185))
130130

131-
assert.Equal(t, complex(0.5504370051176339, 0.5504370051176339), actualVal)
131+
assert.Equal(t, complex(0.3851891847407185, 0.3851891847407185), actualVal)
132132
}
133133

134134
func TestByteByUtGoFuzzer(t *testing.T) {
@@ -210,12 +210,12 @@ func TestArrayOfArrayOfStructsByUtGoFuzzer(t *testing.T) {
210210
}
211211

212212
func TestArrayOfSliceOfUintByUtGoFuzzer(t *testing.T) {
213-
actualVal := ArrayOfSliceOfUint([5][]uint{{}, {}, {}, {}, {}})
213+
actualVal := ArrayOfSliceOfUint([5][]uint{nil, nil, nil, nil, nil})
214214

215-
assert.Equal(t, [5][]uint{{}, {}, {}, {}, {}}, actualVal)
215+
assert.Equal(t, [5][]uint{nil, nil, nil, nil, nil}, actualVal)
216216
}
217217

218-
func TestReturnErrorOrNilByUtGoFuzzer1(t *testing.T) {
218+
func TestReturnErrorOrNilWithNonNilErrorByUtGoFuzzer1(t *testing.T) {
219219
actualErr := returnErrorOrNil(0)
220220

221221
assert.Nil(t, actualErr)
@@ -240,21 +240,21 @@ func TestExternalStructWithAliasByUtGoFuzzer(t *testing.T) {
240240
}
241241

242242
func TestSliceOfIntByUtGoFuzzer(t *testing.T) {
243-
actualVal := SliceOfInt([]int{-1})
243+
actualVal := SliceOfInt(nil)
244244

245-
assert.Equal(t, []int{-1}, actualVal)
245+
assert.Nil(t, actualVal)
246246
}
247247

248248
func TestSliceOfUintPtrByUtGoFuzzer(t *testing.T) {
249-
actualVal := SliceOfUintPtr([]uintptr{0})
249+
actualVal := SliceOfUintPtr(nil)
250250

251-
assert.Equal(t, []uintptr{0}, actualVal)
251+
assert.Nil(t, actualVal)
252252
}
253253

254254
func TestSliceOfStringByUtGoFuzzer(t *testing.T) {
255-
actualVal := SliceOfString([]string{"hello"})
255+
actualVal := SliceOfString(nil)
256256

257-
assert.Equal(t, []string{"hello"}, actualVal)
257+
assert.Nil(t, actualVal)
258258
}
259259

260260
func TestSliceOfStructsByUtGoFuzzer(t *testing.T) {
@@ -270,15 +270,15 @@ func TestSliceOfStructsWithNanByUtGoFuzzer(t *testing.T) {
270270
}
271271

272272
func TestSliceOfSliceOfByteByUtGoFuzzer(t *testing.T) {
273-
actualVal := SliceOfSliceOfByte([][]byte{{}})
273+
actualVal := SliceOfSliceOfByte([][]byte{nil})
274274

275-
assert.Equal(t, [][]byte{{}}, actualVal)
275+
assert.Equal(t, [][]byte{nil}, actualVal)
276276
}
277277

278278
func TestSliceOfSliceOfStructsByUtGoFuzzer(t *testing.T) {
279-
actualVal := SliceOfSliceOfStructs([][]Structure{{}})
279+
actualVal := SliceOfSliceOfStructs([][]Structure{nil})
280280

281-
assert.Equal(t, [][]Structure{{}}, actualVal)
281+
assert.Equal(t, [][]Structure{nil}, actualVal)
282282
}
283283

284284
func TestSliceOfArrayOfIntByUtGoFuzzer(t *testing.T) {
@@ -294,7 +294,7 @@ func TestExportedStructWithEmbeddedUnexportedStructByUtGoFuzzer(t *testing.T) {
294294
}
295295

296296
func TestNamedTypeByUtGoFuzzer(t *testing.T) {
297-
actualVal := NamedType(Type(0))
297+
actualVal := NamedType(0)
298298

299299
assert.Equal(t, Type(0), actualVal)
300300
}
@@ -324,13 +324,49 @@ func TestNamedArrayByUtGoFuzzer(t *testing.T) {
324324
}
325325

326326
func TestNamedSliceByUtGoFuzzer(t *testing.T) {
327-
actualVal := NamedSlice(NS{-1, 9223372036854775807, 9223372036854775807, 1, 9223372036854775807})
327+
actualVal := NamedSlice(NS(nil))
328328

329-
assert.Equal(t, NS{-1, 9223372036854775807, 9223372036854775807, 1, 9223372036854775807}, actualVal)
329+
assert.Nil(t, actualVal)
330330
}
331331

332332
func TestStructWithFieldsOfNamedTypesByUtGoFuzzer(t *testing.T) {
333-
actualVal := StructWithFieldsOfNamedTypes(S{T: T{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, NS: NS{9223372036854775807, 1, 0, -9223372036854775808, 9223372036854775807}})
333+
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(nil)})
334334

335-
assert.Equal(t, S{T: T{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, NS: NS{9223372036854775807, 1, 0, -9223372036854775808, 9223372036854775807}}, actualVal)
335+
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(nil)}, actualVal)
336+
}
337+
338+
func TestMapByUtGoFuzzer(t *testing.T) {
339+
actualVal := Map(nil)
340+
341+
assert.Nil(t, actualVal)
342+
}
343+
344+
func TestMapOfStructuresByUtGoFuzzer(t *testing.T) {
345+
actualVal := MapOfStructures(map[Structure]Structure{Structure{}: {}})
346+
347+
assert.Equal(t, map[Structure]Structure{Structure{}: {}}, actualVal)
348+
}
349+
350+
func TestMapOfSliceOfIntByUtGoFuzzer(t *testing.T) {
351+
actualVal := MapOfSliceOfInt(map[string][]int{"hello": {}})
352+
353+
assert.Equal(t, map[string][]int{"hello": {}}, actualVal)
354+
}
355+
356+
func TestMapOfNamedTypeByUtGoFuzzer(t *testing.T) {
357+
actualVal := MapOfNamedType(map[int]Type{-1: 255})
358+
359+
assert.Equal(t, map[int]Type{-1: 255}, actualVal)
360+
}
361+
362+
func TestMapOfNamedSliceByUtGoFuzzer(t *testing.T) {
363+
actualVal := MapOfNamedSlice(nil)
364+
365+
assert.Nil(t, actualVal)
366+
}
367+
368+
func TestNamedMapByUtGoFuzzer(t *testing.T) {
369+
actualVal := NamedMap(NM(nil))
370+
371+
assert.Nil(t, actualVal)
336372
}

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

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ import mu.KotlinLogging
66
import org.utbot.fuzzing.BaseFeedback
77
import org.utbot.fuzzing.Control
88
import org.utbot.fuzzing.utils.Trie
9-
import org.utbot.go.api.GoUtExecutionResult
109
import org.utbot.go.api.GoUtFunction
1110
import org.utbot.go.api.GoUtFuzzedFunction
12-
import org.utbot.go.api.GoUtPanicFailure
1311
import org.utbot.go.framework.api.go.GoPackage
1412
import org.utbot.go.worker.GoWorker
15-
import org.utbot.go.worker.convertRawExecutionResultToExecutionResult
13+
import org.utbot.go.worker.RawExecutionResult
1614

1715
val logger = KotlinLogging.logger {}
1816

@@ -21,24 +19,18 @@ class GoEngine(
2119
private val functionUnderTest: GoUtFunction,
2220
private val aliases: Map<GoPackage, String?>,
2321
private val intSize: Int,
24-
private val eachExecutionTimeoutMillis: Long,
2522
private val timeoutExceededOrIsCanceled: () -> Boolean,
2623
) {
24+
var numberOfFunctionExecutions: Int = 0
2725

28-
fun fuzzing(): Flow<Pair<GoUtFuzzedFunction, GoUtExecutionResult>> = flow {
26+
fun fuzzing(): Flow<Pair<GoUtFuzzedFunction, RawExecutionResult>> = flow {
2927
var attempts = 0
3028
val attemptsLimit = Int.MAX_VALUE
3129
if (functionUnderTest.parameters.isEmpty()) {
3230
worker.sendFuzzedParametersValues(functionUnderTest, emptyList(), emptyMap())
3331
val rawExecutionResult = worker.receiveRawExecutionResult()
34-
val executionResult = convertRawExecutionResultToExecutionResult(
35-
rawExecutionResult,
36-
functionUnderTest.resultTypes,
37-
intSize,
38-
eachExecutionTimeoutMillis,
39-
)
4032
val fuzzedFunction = GoUtFuzzedFunction(functionUnderTest, emptyList())
41-
emit(fuzzedFunction to executionResult)
33+
emit(fuzzedFunction to rawExecutionResult)
4234
} else {
4335
val notCoveredLines = (1..functionUnderTest.numberOfAllStatements).toMutableSet()
4436
runGoFuzzing(functionUnderTest, intSize) { description, values ->
@@ -48,28 +40,20 @@ class GoEngine(
4840
val fuzzedFunction = GoUtFuzzedFunction(functionUnderTest, values)
4941
worker.sendFuzzedParametersValues(functionUnderTest, values, aliases)
5042
val rawExecutionResult = worker.receiveRawExecutionResult()
51-
val executionResult = convertRawExecutionResultToExecutionResult(
52-
rawExecutionResult,
53-
functionUnderTest.resultTypes,
54-
intSize,
55-
eachExecutionTimeoutMillis,
56-
)
57-
if (executionResult.trace.isEmpty()) {
43+
numberOfFunctionExecutions++
44+
if (rawExecutionResult.trace.isEmpty()) {
5845
logger.error { "Coverage is empty for [${functionUnderTest.name}] with $values}" }
59-
if (executionResult is GoUtPanicFailure) {
60-
logger.error { "Execution completed with panic: ${executionResult.panicValue}" }
61-
}
6246
return@runGoFuzzing BaseFeedback(result = Trie.emptyNode(), control = Control.PASS)
6347
}
64-
val trieNode = description.tracer.add(executionResult.trace.map { GoInstruction(it) })
48+
val trieNode = description.tracer.add(rawExecutionResult.trace.map { GoInstruction(it) })
6549
if (trieNode.count > 1) {
6650
if (++attempts >= attemptsLimit) {
6751
return@runGoFuzzing BaseFeedback(result = Trie.emptyNode(), control = Control.STOP)
6852
}
6953
return@runGoFuzzing BaseFeedback(result = trieNode, control = Control.CONTINUE)
7054
}
71-
if (notCoveredLines.removeAll(executionResult.trace.toSet())) {
72-
emit(fuzzedFunction to executionResult)
55+
if (notCoveredLines.removeAll(rawExecutionResult.trace.toSet())) {
56+
emit(fuzzedFunction to rawExecutionResult)
7357
}
7458
BaseFeedback(result = trieNode, control = Control.CONTINUE)
7559
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ fun goDefaultValueProviders() = listOf(
1212
GoPrimitivesValueProvider,
1313
GoArrayValueProvider,
1414
GoSliceValueProvider,
15+
GoMapValueProvider,
1516
GoStructValueProvider,
1617
GoConstantValueProvider,
1718
GoNamedValueProvider,

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,27 @@ class GoSliceTypeId(
8282
override fun hashCode(): Int = elementTypeId.hashCode()
8383
}
8484

85+
class GoMapTypeId(
86+
name: String, val keyTypeId: GoTypeId, elementTypeId: GoTypeId,
87+
) : GoTypeId(name, elementTypeId = elementTypeId) {
88+
override val canonicalName: String = "map[${keyTypeId.canonicalName}]${elementTypeId.canonicalName}"
89+
90+
override fun getRelativeName(destinationPackage: GoPackage, aliases: Map<GoPackage, String?>): String {
91+
val keyType = keyTypeId.getRelativeName(destinationPackage, aliases)
92+
val elementType = elementTypeId!!.getRelativeName(destinationPackage, aliases)
93+
return "map[$keyType]$elementType"
94+
}
95+
96+
override fun equals(other: Any?): Boolean {
97+
if (this === other) return true
98+
if (other !is GoMapTypeId) return false
99+
100+
return keyTypeId == other.keyTypeId && elementTypeId == other.elementTypeId
101+
}
102+
103+
override fun hashCode(): Int = 31 * keyTypeId.hashCode() + elementTypeId.hashCode()
104+
}
105+
85106
class GoInterfaceTypeId(name: String) : GoTypeId(name) {
86107
override val canonicalName: String = name
87108

0 commit comments

Comments
 (0)