@@ -22,11 +22,13 @@ type internal GenerationData = {
22
22
}
23
23
24
24
type internal Generator ( options : Startup.FuzzerOptions , typeSolver : TypeSolver ) =
25
- let instancesCache = Dictionary< Type, Type option>()
25
+ let instancesCache = Dictionary< Type, Type[] option>()
26
26
let mutable allocatedObjects = HashSet< obj>()
27
27
let mutable instantiatedMocks = Dictionary< obj, ITypeMock>()
28
28
let mutable referencedObjects = HashSet< obj>()
29
29
30
+ let mutable mockedGenerics = Dictionary< Type, ITypeMock>()
31
+
30
32
let traceGeneration ( t : Type ) msg = Logger.traceGeneration $" [{t.Name}] {msg}"
31
33
32
34
let setAllFields ( t : Type ) ( setter : Type -> obj ) =
@@ -57,14 +59,13 @@ type internal Generator(options: Startup.FuzzerOptions, typeSolver: TypeSolver)
57
59
| :? TargetInvocationException as e ->
58
60
traceGeneration t $" Constructor thrown an exception: {e}"
59
61
None
60
-
61
- let getInstance ( t : Type ) ( rnd : Random ) _ =
62
- traceGeneration t " Try get installable type"
62
+
63
+ let findInstances ( t : Type ) =
64
+ traceGeneration t " Try find installable type"
63
65
match instancesCache.TryGetValue t with
64
- | true , instance ->
65
- let none = " None"
66
- traceGeneration t $" Installable type got from cache: {match instance with | Some x -> x.Name | None -> none}"
67
- instance
66
+ | true , instances ->
67
+ traceGeneration t " Installable types got from cache"
68
+ instances
68
69
| false , _ ->
69
70
let instances =
70
71
t.Assembly.GetTypes()
@@ -79,9 +80,8 @@ type internal Generator(options: Startup.FuzzerOptions, typeSolver: TypeSolver)
79
80
traceGeneration t " Installable type not found"
80
81
instancesCache.Add( t, None)
81
82
else
82
- let installableType = instances[ rnd.Next( 0 , instances.Length)]
83
- traceGeneration t $" Installable type found: {installableType}"
84
- instancesCache.Add( t, Some installableType)
83
+ traceGeneration t " Installable types found"
84
+ instancesCache.Add( t, Some instances)
85
85
instancesCache[ t]
86
86
87
87
let generateUnboxedChar ( rnd : Random ) =
@@ -160,15 +160,21 @@ type internal Generator(options: Startup.FuzzerOptions, typeSolver: TypeSolver)
160
160
// TODO: LowerBound
161
161
__ notImplemented__ ()
162
162
163
- let generateAbstractClass commonGenerator ( rnd : Random ) ( t : Type ) =
164
- traceGeneration t " Generate abstract class"
165
- match getInstance t rnd commonGenerator with
166
- | Some instance -> commonGenerator rnd instance
167
- | None ->
168
- let mock , typ = typeSolver.MockType t ( commonGenerator rnd)
169
- let result = commonGenerator rnd typ
170
- instantiatedMocks.Add( result, mock)
171
- result
163
+ let generateAbstractClassWithInstances commonGenerator ( rnd : Random ) ( t : Type ) =
164
+ traceGeneration t " Generate abstract class with instances"
165
+ let instances = findInstances t |> Option.defaultWith ( fun () ->
166
+ internalfailf " Incorrect usage of generateAbstractClassWithInstances"
167
+ )
168
+ let instance = instances[ rnd.Next( 0 , instances.Length)]
169
+ commonGenerator rnd instance
170
+
171
+ let generateAbstractClassWithoutInstances commonGenerator ( rnd : Random ) ( t : Type ) =
172
+ traceGeneration t " Generate abstract class without instances"
173
+ assert ( findInstances t |> Option.isNone)
174
+ let mock , typ = typeSolver.MockType t ( commonGenerator rnd)
175
+ let result = commonGenerator rnd typ
176
+ instantiatedMocks.Add( result, mock)
177
+ result
172
178
173
179
let generateByRef commonGenerator ( rnd : Random ) ( t : Type ) =
174
180
traceGeneration t " Generate ByRef"
@@ -214,11 +220,15 @@ type internal Generator(options: Startup.FuzzerOptions, typeSolver: TypeSolver)
214
220
else OtherStruct
215
221
216
222
// Reference types
217
- let (| Array | Delegate | String | AbstractClass | OtherClass |) ( t : Type ) =
223
+ let (| Array | Delegate | String | AbstractClassWithInstances | AbstractClassWithoutInstances | OtherClass |) ( t : Type ) =
218
224
if t.IsArray then Array
219
225
elif t = typeof< string> then String
220
226
elif t.IsSubclassOf typeof< System.Delegate> then Delegate
221
- elif t.IsAbstract || t.IsInterface then AbstractClass
227
+ elif t.IsAbstract || t.IsInterface then
228
+ if findInstances t |> Option.isSome then
229
+ AbstractClassWithInstances
230
+ else
231
+ AbstractClassWithoutInstances
222
232
else OtherClass
223
233
224
234
let rec commonGenerate ( rnd : Random ) ( t : Type ) =
@@ -240,7 +250,8 @@ type internal Generator(options: Startup.FuzzerOptions, typeSolver: TypeSolver)
240
250
| Array -> generateArray
241
251
| Delegate -> generateDelegate
242
252
| String -> generateString
243
- | AbstractClass -> __ notImplemented__ ()
253
+ | AbstractClassWithoutInstances -> __ notImplemented__ ()
254
+ | AbstractClassWithInstances -> generateAbstractClassWithInstances
244
255
| OtherClass -> generateClass
245
256
| ByRefType -> __ notImplemented__ ()
246
257
| PointerType -> __ notImplemented__ ()
@@ -249,11 +260,19 @@ type internal Generator(options: Startup.FuzzerOptions, typeSolver: TypeSolver)
249
260
250
261
member private this.GenerateObject rnd ( t : Type ) =
251
262
Logger.traceGeneration $" Target type: {t.Name}"
252
- match t with
253
- | ByRefType -> generateByRef commonGenerate rnd t
254
- | PointerType -> generatePointer commonGenerate rnd t
255
- | AbstractClass -> generateAbstractClass commonGenerate rnd t
256
- | _ -> commonGenerate rnd t
263
+
264
+ let result =
265
+ match t with
266
+ | ByRefType -> generateByRef commonGenerate rnd t
267
+ | PointerType -> generatePointer commonGenerate rnd t
268
+ | AbstractClassWithoutInstances -> generateAbstractClassWithoutInstances commonGenerate rnd t
269
+ | _ -> commonGenerate rnd t
270
+
271
+ if mockedGenerics.ContainsKey t then
272
+ traceGeneration t " Added generated object to instantiated mocks"
273
+ instantiatedMocks.Add( result, mockedGenerics[ t])
274
+
275
+ result
257
276
258
277
member private this.RefreshInstantiatedMocks () =
259
278
let result = instantiatedMocks
@@ -290,7 +309,8 @@ type internal Generator(options: Startup.FuzzerOptions, typeSolver: TypeSolver)
290
309
291
310
{| this = methodThis; thisType = methodThisType; args = args; argsTypes = argsTypes |}
292
311
293
- member this.Generate ( method : MethodBase ) typeStorage rndSeed =
312
+ member this.Generate methodMockedGenerics ( method : MethodBase ) typeStorage rndSeed =
313
+ mockedGenerics <- methodMockedGenerics
294
314
let case = this.GenerateCase method rndSeed
295
315
{
296
316
seed = rndSeed
0 commit comments