Skip to content

Commit ffbd849

Browse files
mxprshndvvrd
authored andcommitted
[fix] Fix TestRunner returning on failed test | Reset searcher after exploration
1 parent 6fb50a1 commit ffbd849

13 files changed

+211
-130
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Collections.Generic;
2+
using Microsoft.Extensions.DependencyModel;
3+
using Microsoft.Extensions.DependencyModel.Resolution;
4+
5+
namespace VSharp.CSharpUtils
6+
{
7+
public class CompositeCompilationAssemblyResolver : ICompilationAssemblyResolver
8+
{
9+
private readonly ICompilationAssemblyResolver[] _resolvers;
10+
11+
public CompositeCompilationAssemblyResolver(ICompilationAssemblyResolver[] resolvers)
12+
{
13+
_resolvers = resolvers;
14+
}
15+
16+
public bool TryResolveAssemblyPaths(CompilationLibrary library, List<string> assemblies)
17+
{
18+
foreach (ICompilationAssemblyResolver resolver in _resolvers)
19+
{
20+
try
21+
{
22+
if (resolver.TryResolveAssemblyPaths(library, assemblies))
23+
{
24+
return true;
25+
}
26+
}
27+
catch { }
28+
}
29+
30+
return false;
31+
}
32+
}
33+
}

VSharp.CSharpUtils/VSharp.CSharpUtils.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
<ItemGroup>
1515
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
16+
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="6.0.0-rc.2.21480.5" />
1617
</ItemGroup>
1718

1819
</Project>

VSharp.IL/CFG.fs

+6-6
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ and Method internal (m : MethodBase) as this =
258258
Method.ReportCFGLoaded this
259259
cfg |> CfgInfo |> Some
260260
else None)
261-
261+
262262
let blocksCoveredByTests = HashSet<offset>()
263263

264264
member x.CFG with get() =
@@ -291,13 +291,13 @@ and Method internal (m : MethodBase) as this =
291291
static member val internal CoverageZone : Method -> bool = fun _ -> true with get, set
292292

293293
member x.InCoverageZone with get() = Method.CoverageZone x
294-
294+
295295
member x.BasicBlocksCount with get() =
296296
if x.HasBody then x.CFG.SortedOffsets |> Seq.length |> uint else 0u
297-
297+
298298
member x.BlocksCoveredByTests with get() = blocksCoveredByTests :> IReadOnlySet<offset>
299299
member x.SetBlockIsCoveredByTest(offset : offset) = blocksCoveredByTests.Add(offset)
300-
300+
301301
member x.ResetStatistics() = blocksCoveredByTests.Clear()
302302

303303
[<CustomEquality; CustomComparison>]
@@ -319,7 +319,7 @@ type public codeLocation = {offset : offset; method : Method}
319319
module public CodeLocation =
320320
let isBasicBlockCoveredByTest (blockStart : codeLocation) =
321321
blockStart.method.BlocksCoveredByTests.Contains blockStart.offset
322-
322+
323323
let hasSiblings (blockStart : codeLocation) =
324324
let method = blockStart.method
325325
method.HasBody && method.CFG.HasSiblings blockStart.offset
@@ -515,7 +515,7 @@ module Application =
515515
let addGoal = graph.AddGoal
516516
let addGoals = graph.AddGoals
517517
let removeGoal = graph.RemoveGoal
518-
518+
519519
let resetMethodStatistics() =
520520
lock methods (fun () ->
521521
for method in methods.Values do

VSharp.SILI/BidirectionalSearcher.fs

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace VSharp.Interpreter.IL
22

3-
open System.Reflection
43
open System.Collections.Generic
54
open FSharpx.Collections
65
open VSharp
@@ -78,6 +77,11 @@ type BidirectionalSearcher(forward : IForwardSearcher, backward : IBackwardSearc
7877
// GoFront s
7978
// | None -> Stop
8079

80+
override x.Reset () =
81+
forward.Reset()
82+
backward.Reset()
83+
targeted.Reset()
84+
8185
type OnlyForwardSearcher(searcher : IForwardSearcher) =
8286
interface IBidirectionalSearcher with
8387
override x.Init _ cilStates _ = searcher.Init cilStates
@@ -90,6 +94,7 @@ type OnlyForwardSearcher(searcher : IForwardSearcher) =
9094
| Some s -> GoFront s
9195
| None -> Stop
9296
override x.States() = searcher.States()
97+
override x.Reset() = searcher.Reset()
9398

9499
// TODO: check pob duplicates
95100
type BackwardSearcher() =
@@ -191,6 +196,8 @@ type BackwardSearcher() =
191196
// TODO: need this?
192197
internalfail "olololo!"
193198

199+
override x.Reset() = clear()
200+
194201
module DummyTargetedSearcher =
195202
open CilStateOperations
196203

@@ -232,3 +239,9 @@ module DummyTargetedSearcher =
232239

233240
override x.Pick () =
234241
targets.Keys |> Seq.tryPick (fun ip -> forPropagation.[ip] |> Seq.tryHead)
242+
243+
override x.Reset () =
244+
forPropagation.Clear()
245+
finished.Clear()
246+
reached.Clear()
247+
targets.Clear()

VSharp.SILI/InterleavedSearcher.fs

+12-9
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,30 @@
33
open System.Linq
44

55
type InterleavedSearcher(searchersWithStepCount: (IForwardSearcher * int) list) =
6-
7-
let searchers = seq { while true do yield! searchersWithStepCount |> Seq.collect Enumerable.Repeat }
6+
7+
let searchers = seq { while true do yield! searchersWithStepCount |> Seq.collect Enumerable.Repeat }
88
let searchersEnumerator = searchers.GetEnumerator()
9-
9+
1010
let getCurrentSearcher() =
1111
searchersEnumerator.MoveNext() |> ignore
1212
searchersEnumerator.Current
1313

14-
let init states = for searcher, _ in searchersWithStepCount do searcher.Init states
15-
14+
let init states = for searcher, _ in searchersWithStepCount do searcher.Init states
15+
1616
// TODO: handle None
1717
let pick() = getCurrentSearcher().Pick()
18-
18+
1919
let update (parent, newStates) =
2020
for searcher, _ in searchersWithStepCount do
2121
searcher.Update(parent, newStates)
22-
23-
let states() = searchersWithStepCount |> Seq.collect (fun (s, _) -> s.States()) |> Seq.distinct
24-
22+
23+
let states() = searchersWithStepCount |> Seq.collect (fun (s, _) -> s.States()) |> Seq.distinct
24+
25+
let reset() = for searcher, _ in searchersWithStepCount do searcher.Reset()
26+
2527
interface IForwardSearcher with
2628
override x.Init states = init states
2729
override x.Pick() = pick()
2830
override x.Update (parent, newStates) = update (parent, newStates)
2931
override x.States() = states()
32+
override x.Reset() = reset()

VSharp.SILI/SILI.fs

+53-45
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ open VSharp.Solver
1616
type public SILI(options : SiliOptions) =
1717

1818
let stopwatch = Stopwatch()
19-
let () = stopwatch.Start()
2019
let timeout = if options.timeout <= 0 then Int64.MaxValue else int64 options.timeout * 1000L
2120
let branchReleaseTimeout = if options.timeout <= 0 || not options.releaseBranches then Int64.MaxValue else timeout * 80L / 100L
2221
let mutable branchesReleased = false
@@ -214,6 +213,7 @@ type public SILI(options : SiliOptions) =
214213
isStopped <- false
215214
branchesReleased <- false
216215
AcquireBranches()
216+
searcher.Reset()
217217
let mainPobs = coveragePobsForMethod entryPoint |> Seq.filter (fun pob -> pob.loc.offset <> 0<offsets>)
218218
Application.spawnStates (Seq.cast<_> initialStates)
219219
mainPobs |> Seq.map (fun pob -> pob.loc) |> Seq.toArray |> Application.addGoals
@@ -245,58 +245,66 @@ type public SILI(options : SiliOptions) =
245245
member x.InterpretEntryPoint (method : MethodBase) (mainArguments : string[]) (onFinished : Action<UnitTest>)
246246
(onException : Action<UnitTest>) (onIIE : Action<InsufficientInformationException>)
247247
(onInternalFail : Action<Exception>) : unit =
248+
stopwatch.Restart()
248249
reportInternalFail <- wrapOnInternalFail onInternalFail
249250
try
250-
assert method.IsStatic
251-
let optionArgs = if mainArguments = null then None else Some mainArguments
252-
let method = Application.getMethod method
253-
reportFinished <- wrapOnTest onFinished method optionArgs
254-
reportError <- wrapOnError onException method optionArgs
255-
reportIncomplete <- wrapOnIIE onIIE
256-
interpreter.ConfigureErrorReporter reportError
257-
let state = Memory.EmptyState()
258-
state.model <- Memory.EmptyModel method
259-
let argsToState args =
260-
let argTerms = Seq.map (fun str -> Memory.AllocateString str state) args
261-
let stringType = typeof<string>
262-
let argsNumber = MakeNumber mainArguments.Length
263-
Memory.AllocateConcreteVectorArray state argsNumber stringType argTerms
264-
let arguments = Option.map (argsToState >> List.singleton) optionArgs
265-
ILInterpreter.InitFunctionFrame state method None arguments
266-
if Option.isNone optionArgs then
267-
// NOTE: if args are symbolic, constraint 'args != null' is added
268-
let parameters = method.Parameters
269-
assert(Array.length parameters = 1)
270-
let argsParameter = Array.head parameters
271-
let argsParameterTerm = Memory.ReadArgument state argsParameter
272-
AddConstraint state (!!(IsNullReference argsParameterTerm))
273-
Memory.InitializeStaticMembers state method.DeclaringType
274-
let initialState = makeInitialState method state
275-
x.AnswerPobs method [initialState]
276-
with
277-
| e -> reportInternalFail e
251+
try
252+
assert method.IsStatic
253+
let optionArgs = if mainArguments = null then None else Some mainArguments
254+
let method = Application.getMethod method
255+
reportFinished <- wrapOnTest onFinished method optionArgs
256+
reportError <- wrapOnError onException method optionArgs
257+
reportIncomplete <- wrapOnIIE onIIE
258+
interpreter.ConfigureErrorReporter reportError
259+
let state = Memory.EmptyState()
260+
state.model <- Memory.EmptyModel method
261+
let argsToState args =
262+
let argTerms = Seq.map (fun str -> Memory.AllocateString str state) args
263+
let stringType = typeof<string>
264+
let argsNumber = MakeNumber mainArguments.Length
265+
Memory.AllocateConcreteVectorArray state argsNumber stringType argTerms
266+
let arguments = Option.map (argsToState >> List.singleton) optionArgs
267+
ILInterpreter.InitFunctionFrame state method None arguments
268+
if Option.isNone optionArgs then
269+
// NOTE: if args are symbolic, constraint 'args != null' is added
270+
let parameters = method.Parameters
271+
assert(Array.length parameters = 1)
272+
let argsParameter = Array.head parameters
273+
let argsParameterTerm = Memory.ReadArgument state argsParameter
274+
AddConstraint state (!!(IsNullReference argsParameterTerm))
275+
Memory.InitializeStaticMembers state method.DeclaringType
276+
let initialState = makeInitialState method state
277+
x.AnswerPobs method [initialState]
278+
with
279+
| e -> reportInternalFail e
280+
finally
281+
searcher.Reset()
278282

279283
member x.InterpretIsolated (method : MethodBase) (onFinished : Action<UnitTest>)
280284
(onException : Action<UnitTest>) (onIIE : Action<InsufficientInformationException>)
281285
(onInternalFail : Action<Exception>) : unit =
286+
stopwatch.Restart()
282287
reportInternalFail <- wrapOnInternalFail onInternalFail
283288
try
284-
Reset()
285-
SolverPool.reset()
286-
let method = Application.getMethod method
287-
reportFinished <- wrapOnTest onFinished method None
288-
reportError <- wrapOnError onException method None
289-
reportIncomplete <- wrapOnIIE onIIE
290-
interpreter.ConfigureErrorReporter reportError
291-
let initialStates = x.FormInitialStates method
292-
let iieStates, initialStates = initialStates |> List.partition (fun state -> state.iie.IsSome)
293-
iieStates |> List.iter reportIncomplete
294-
if not initialStates.IsEmpty then
295-
x.AnswerPobs method initialStates
296-
Restore()
297-
with
298-
| e -> reportInternalFail e
299-
289+
try
290+
Reset()
291+
SolverPool.reset()
292+
let method = Application.getMethod method
293+
reportFinished <- wrapOnTest onFinished method None
294+
reportError <- wrapOnError onException method None
295+
reportIncomplete <- wrapOnIIE onIIE
296+
interpreter.ConfigureErrorReporter reportError
297+
let initialStates = x.FormInitialStates method
298+
let iieStates, initialStates = initialStates |> List.partition (fun state -> state.iie.IsSome)
299+
iieStates |> List.iter reportIncomplete
300+
if not initialStates.IsEmpty then
301+
x.AnswerPobs method initialStates
302+
Restore()
303+
with
304+
| e -> reportInternalFail e
305+
finally
306+
searcher.Reset()
307+
300308
member x.Stop() = isStopped <- true
301309

302310
member x.Statistics with get() = statistics

VSharp.SILI/Searcher.fs

+8-2
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,20 @@ type IBidirectionalSearcher =
2020
abstract member Answer : pob -> pobStatus -> unit
2121
abstract member Statuses : unit -> seq<pob * pobStatus>
2222
abstract member States : unit -> cilState seq
23+
abstract member Reset : unit -> unit
2324

2425
type IForwardSearcher =
2526
abstract member Init : cilState seq -> unit
2627
abstract member Update : cilState * cilState seq -> unit
2728
abstract member Pick : unit -> cilState option
2829
abstract member States : unit -> cilState seq
30+
abstract member Reset : unit -> unit
2931

3032
type ITargetedSearcher =
3133
abstract member SetTargets : ip -> ip seq -> unit
3234
abstract member Update : cilState -> cilState seq -> cilState seq // returns states that reached its target
3335
abstract member Pick : unit -> cilState option
36+
abstract member Reset : unit -> unit
3437

3538
type backwardAction = Propagate of cilState * pob | InitTarget of ip * pob seq | NoAction
3639

@@ -41,6 +44,7 @@ type IBackwardSearcher =
4144
abstract member Statuses : unit -> seq<pob * pobStatus>
4245
abstract member Pick : unit -> backwardAction
4346
abstract member AddBranch : cilState -> pob list
47+
abstract member Reset : unit -> unit
4448

4549
// TODO: get rid of this!
4650
abstract member RemoveBranch : cilState -> unit
@@ -70,16 +74,17 @@ type SimpleForwardSearcher(maxBound) =
7074
override x.Update (parent, newStates) =
7175
x.Insert forPropagation (parent, newStates)
7276
override x.States() = forPropagation
77+
override x.Reset() = forPropagation.Clear()
7378

7479
abstract member Choose : seq<cilState> -> cilState option
7580
default x.Choose states = Seq.tryLast states
76-
81+
7782
abstract member Insert : List<cilState> -> cilState * seq<cilState> -> unit
7883
default x.Insert states (parent, newStates) =
7984
if isStopped parent then
8085
states.Remove(parent) |> ignore
8186
Seq.iter (add states) newStates
82-
87+
8388
abstract member Init : List<cilState> -> seq<cilState> -> unit
8489
default x.Init states initStates = states.AddRange(initStates)
8590

@@ -151,6 +156,7 @@ type WeightedSearcher(maxBound, weighter : IWeighter, storage : IPriorityCollect
151156
override x.Pick() = x.Pick()
152157
override x.Update (parent, newStates) = x.Update (parent, newStates)
153158
override x.States() = storage.ToSeq
159+
override x.Reset() = storage.Clear()
154160

155161
member x.Weighter = weighter
156162
member x.TryGetWeight state = storage.TryGetPriority state

VSharp.SILI/TargetedSearcher.fs

+5
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,18 @@ type GuidedSearcher(maxBound, threshold : uint, baseSearcher : IForwardSearcher,
213213

214214
let pick () = pick' id
215215

216+
let reset () =
217+
baseSearcher.Reset()
218+
for searcher in targetedSearchers.Values do (searcher :> IForwardSearcher).Reset()
219+
216220
interface IForwardSearcher with
217221
override x.Init states =
218222
baseSearcher.Init states
219223
insertInTargetedSearchers states
220224
override x.Pick() = pick ()
221225
override x.Update (parent, newStates) = update parent newStates
222226
override x.States() = baseSearcher.States()
227+
override x.Reset() = reset ()
223228

224229
type ShortestDistanceBasedSearcher(maxBound, statistics : SILIStatistics) =
225230
inherit WeightedSearcher(maxBound, IntraproceduralShortestDistanceToUncoveredWeighter(statistics), BidictionaryPriorityQueue())

0 commit comments

Comments
 (0)