Skip to content
This repository was archived by the owner on Feb 2, 2022. It is now read-only.

Commit 40c1c97

Browse files
stishkinstas
andauthored
Add support for bug hashes reported by RESTler (#57)
- If Fuzz or Test modality of RESTler, then do not post bugs if they are in the ignoreBugHashes list - If Replay modality of RESTler then do not replay the bugs that are in the ignoreBugHashes list - Add Replay all fuzz bugs after running petstore sample - Use bug hash as the replay summary key Co-authored-by: stas <[email protected]>
1 parent d756330 commit 40c1c97

File tree

9 files changed

+223
-84
lines changed

9 files changed

+223
-84
lines changed

cli/samples/restler/self-contained/swagger-petstore/restler.fuzz.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"tasks": [
3636
{
3737
"toolName": "RESTler",
38-
"outputFolder": "fuzz",
38+
"outputFolder": "{outputFolder}",
3939
"duration": "00:10:00",
4040
"toolConfiguration": {
4141
"task": "Fuzz",
@@ -44,7 +44,11 @@
4444
"Port" : 8080
4545
},
4646
"useSsl" : false,
47-
"inputFolderPath": "/job-compile/compile"
47+
"inputFolderPath": "/job-compile/compile",
48+
"IgnoreBugHashes" : [
49+
"PayloadBodyChecker_500_3d6e2d1e897967f3bc14cd8f08252a98b25c4d48",
50+
"PayloadBodyChecker_500_6a4f4fb484d57121a271a4c65948ba8149e92dee"
51+
]
4852
}
4953
}
5054
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"readOnlyFileShareMounts": [
3+
{
4+
"FileShareName": "{jobId}",
5+
"MountPath": "/job-run"
6+
}
7+
],
8+
"testTargets" : {
9+
"targets" : [
10+
{
11+
"Container" : "swaggerapi/petstore",
12+
"Port" : 8080,
13+
"ExpectedDurationUntilReady" : "00:02:00",
14+
"Shell" : "/bin/sh",
15+
"OutputFolder" : "petstore",
16+
"PostRun" : {
17+
"Command" : "/bin/sh",
18+
"Arguments" : ["-c", "cp /var/log/*-requests.log $RAFT_WORK_DIRECTORY"],
19+
"ExpectedRunDuration" : "00:00:10"
20+
}
21+
}
22+
]
23+
},
24+
"tasks": [
25+
{
26+
"toolName": "RESTler",
27+
"outputFolder": "RESTler-replay-{experiment}-all-bug-buckets",
28+
"toolConfiguration": {
29+
"task": "Replay",
30+
"runConfiguration": {
31+
"targetEndpointConfiguration" : {
32+
"Port" : 8080
33+
},
34+
"useSsl" : false,
35+
"inputFolderPath": "/job-run/{outputFolder}/RestlerResults/{experiment}/bug_buckets",
36+
"ignoreBugHashes" : [
37+
"PayloadBodyChecker_500_acb1c0dcc79e949c24bec51f0ea3f841c61c38a3",
38+
"PayloadBodyChecker_500_b8ebb5eaf46cdad18ac1d8e9ed67e2cdc729db3d"
39+
]
40+
}
41+
}
42+
}
43+
]
44+
}

cli/samples/restler/self-contained/swagger-petstore/restler.test.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,19 @@
3636
"tasks": [
3737
{
3838
"toolName": "RESTler",
39-
"outputFolder": "test-fuzz-lean",
39+
"outputFolder": "test",
4040
"toolConfiguration": {
4141
"task": "Test",
4242
"runConfiguration": {
4343
"useSsl" : false,
4444
"targetEndpointConfiguration" : {
4545
"Port" : 8080
4646
},
47-
"inputFolderPath": "/job-compile/compile"
47+
"inputFolderPath": "/job-compile/compile",
48+
"ignoreBugHashes" : [
49+
"PayloadBodyChecker_500_7c2ae3b8c78eabad55a8075b487322dbbe146e46",
50+
"PayloadBodyChecker_500_6349a559db300ca67b3caa316142c02a6bea0fbe"
51+
]
4852
}
4953
}
5054
}

cli/samples/restler/self-contained/swagger-petstore/run.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
sys.path.append(os.path.join(cur_dir, '..', '..', '..', '..'))
1010
from raft_sdk.raft_service import RaftCLI, RaftJobConfig, RaftJobError
1111

12-
def run(compile, test, fuzz):
12+
def run(compile, test, fuzz, replay):
1313
# instantiate RAFT CLI
1414
cli = RaftCLI()
15-
1615
# Create compilation job configuration
1716
compile_job_config = RaftJobConfig(file_path=compile)
1817
# add webhook metadata that will be included in every triggered webhook by Compile job
@@ -23,8 +22,8 @@ def run(compile, test, fuzz):
2322
# wait for a job with ID from compile_job to finish the run
2423
cli.poll(compile_job['jobId'])
2524

26-
# use compile job as input for fuzz job
2725
subs = {}
26+
# use compile job as input for fuzz job
2827
subs['{compile.jobId}'] = compile_job['jobId']
2928

3029
test_job_config = RaftJobConfig(file_path=test, substitutions=subs)
@@ -34,6 +33,7 @@ def run(compile, test, fuzz):
3433
# wait for job ID from fuzz_job to finish the run
3534
cli.poll(test_job['jobId'])
3635

36+
subs['{outputFolder}'] = 'fuzz'
3737
# create a new job config with Fuzz configuration JSON
3838
fuzz_job_config = RaftJobConfig(file_path=fuzz, substitutions=subs)
3939
print('Fuzz')
@@ -45,10 +45,28 @@ def run(compile, test, fuzz):
4545
# wait for job ID from fuzz_job to finish the run
4646
cli.poll(fuzz_job['jobId'])
4747

48+
status = cli.job_status(fuzz_job['jobId'])
49+
experiment = None
50+
for s in status:
51+
if (s['agentName'] != s['jobId']):
52+
if (int(s['details']['numberOfBugsFound']) > 0):
53+
experiment = s['details']['experiment']
54+
else:
55+
print("Did not find any bugs")
56+
57+
subs['{experiment}'] = experiment
58+
subs['{jobId}'] = fuzz_job['jobId']
59+
60+
replay_job_config = RaftJobConfig(file_path=replay, substitutions=subs)
61+
replay_job = cli.new_job(replay_job_config)
62+
cli.poll(replay_job['jobId'])
63+
64+
4865
if __name__ == "__main__":
4966
try:
5067
run(os.path.join(cur_dir, "restler.compile.json"),
5168
os.path.join(cur_dir, "restler.test.json"),
52-
os.path.join(cur_dir, "restler.fuzz.json"))
69+
os.path.join(cur_dir, "restler.fuzz.json"),
70+
os.path.join(cur_dir, "restler.replay-all-fuzz-bugs.json"))
5371
except RaftJobError as ex:
5472
print(f'ERROR: {ex.message}')

src/Agent/RESTlerAgent/AgentMain.fs

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,17 @@ let main argv =
547547
do! Raft.RESTlerDriver.compile restlerPath workDirectory compilerConfig
548548
}
549549

550-
let report state (summary: Raft.JobEvents.RunSummary option) =
550+
let report state (experiment : string option, summary:Raft.JobEvents.RunSummary option) =
551551
async {
552552
printfn "Reporting summary [%A]: %A" state summary
553553
let! bugsList = Raft.RESTlerDriver.getListOfBugs workDirectory globalRunStartTime
554+
let bugsListLen = match bugsList with None -> 0 | Some xs -> Seq.length xs
555+
556+
let details =
557+
match experiment with
558+
| Some e -> Map.empty.Add("Experiment", e)
559+
| None -> Map.empty
560+
554561
do! jobEventSender.SendRaftJobEvent jobId
555562
({
556563
AgentName = agentName
@@ -561,7 +568,7 @@ let main argv =
561568

562569
Metrics = summary
563570
UtcEventTime = System.DateTime.UtcNow
564-
Details = Some <| Map.empty.Add("numberOfBugsFound", sprintf "%d" (Seq.length bugsList))
571+
Details = Some( details.Add("numberOfBugsFound", sprintf "%d" bugsListLen))
565572
} : Raft.JobEvents.JobStatus)
566573
}
567574

@@ -617,7 +624,13 @@ let main argv =
617624
let targetIp, targetPort = getIpAndPort jobConfiguration.TargetEndpointConfiguration
618625
let engineParameters = createRESTlerEngineParameters (targetIp, targetPort) grammarPy dictJson task checkerOptions jobConfiguration
619626
printfn "Starting RESTler test task"
620-
do! Raft.RESTlerDriver.test testType restlerPath workDirectory engineParameters onBugFound (report Raft.JobEvents.JobState.Running) (globalRunStartTime, resultAnalyzerReportInterval)
627+
628+
let ignoreBugHashes =
629+
match jobConfiguration.IgnoreBugHashes with
630+
| None -> Set.empty
631+
| Some hs -> Set.ofArray hs
632+
633+
do! Raft.RESTlerDriver.test testType restlerPath workDirectory engineParameters ignoreBugHashes onBugFound (report Raft.JobEvents.JobState.Running) (globalRunStartTime, resultAnalyzerReportInterval)
621634
}
622635

623636
let fuzz (fuzzType:string) checkerOptions (jobConfiguration: RunConfiguration) =
@@ -626,7 +639,13 @@ let main argv =
626639
let targetIp, targetPort = getIpAndPort jobConfiguration.TargetEndpointConfiguration
627640
let engineParameters = createRESTlerEngineParameters (targetIp, targetPort) grammarPy dictJson task checkerOptions jobConfiguration
628641
printfn "Starting RESTler fuzz task"
629-
do! Raft.RESTlerDriver.fuzz fuzzType restlerPath workDirectory engineParameters onBugFound (report Raft.JobEvents.JobState.Running) (globalRunStartTime, resultAnalyzerReportInterval)
642+
643+
let ignoreBugHashes =
644+
match jobConfiguration.IgnoreBugHashes with
645+
| None -> Set.empty
646+
| Some hs -> Set.ofArray hs
647+
648+
do! Raft.RESTlerDriver.fuzz fuzzType restlerPath workDirectory engineParameters ignoreBugHashes onBugFound (report Raft.JobEvents.JobState.Running) (globalRunStartTime, resultAnalyzerReportInterval)
630649
}
631650

632651
let replay replayLogFile (jobConfiguration: RunConfiguration) =
@@ -658,7 +677,7 @@ let main argv =
658677
// Start RESTler process with following flags
659678
// compile, test, fuzz
660679
// --telemetryRootDirPath
661-
let! state, details, exitCode, summary =
680+
let! state, details, exitCode, (experiment, summary) =
662681
async {
663682
try
664683
match restlerPayload.Task with
@@ -697,7 +716,7 @@ let main argv =
697716
| None -> return failwithf "Job-run configuration is not set for Test task for job payload: %A" restlerPayload
698717
| Some jobConfiguration ->
699718
copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath])
700-
do! report Raft.JobEvents.Running None
719+
do! report Raft.JobEvents.Running (None, None)
701720
do! test "directed-smoke-test" [] jobConfiguration
702721
let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime
703722
return Raft.JobEvents.Completed, None, 0, summary
@@ -708,7 +727,7 @@ let main argv =
708727
| None -> return failwithf "Job-run configuration is not set for Test task for job payload: %A" restlerPayload
709728
| Some jobConfiguration ->
710729
copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath])
711-
do! report Raft.JobEvents.Running None
730+
do! report Raft.JobEvents.Running (None, None)
712731
let fuzzLeanCheckers =
713732
[
714733
("--enable_checkers", "*")
@@ -724,7 +743,7 @@ let main argv =
724743
| None -> return failwithf "Job-run configuration is not set for Compile task for job payload: %A" restlerPayload
725744
| Some jobConfiguration ->
726745
copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath])
727-
do! report Raft.JobEvents.Running None
746+
do! report Raft.JobEvents.Running (None, None)
728747
let allCheckers = ["--enable_checkers", "*"]
729748
do! fuzz "bfs" allCheckers jobConfiguration
730749
let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime
@@ -736,7 +755,7 @@ let main argv =
736755
| None -> return failwithf "Job-run configuration is not set for Test task for job payload: %A" restlerPayload
737756
| Some jobConfiguration ->
738757
copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath])
739-
do! report Raft.JobEvents.Running None
758+
do! report Raft.JobEvents.Running (None, None)
740759
let allCheckers = ["--enable_checkers", "*"]
741760
do! fuzz "bfs-cheap" allCheckers jobConfiguration
742761
let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime
@@ -748,7 +767,7 @@ let main argv =
748767
| None -> return failwithf "Job-run configuration is not set for Fuzz task for job payload: %A" restlerPayload
749768
| Some jobConfiguration ->
750769
copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath])
751-
do! report Raft.JobEvents.Running None
770+
do! report Raft.JobEvents.Running (None, None)
752771
let allCheckers = ["--enable_checkers", "*"]
753772
do! fuzz "random-walk" allCheckers jobConfiguration
754773
let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime
@@ -759,23 +778,59 @@ let main argv =
759778
| None -> return failwithf "Job-run configuration is not set Replay task for job payload: %A" restlerPayload
760779
| Some replayRunConfiguration ->
761780
let replaySourcePath = replayRunConfiguration.InputFolderPath
762-
do! report Raft.JobEvents.Running None
781+
do! report Raft.JobEvents.Running (None, None)
763782

764783
let replayAndReport (bugs: IO.FileInfo seq) =
765784
async {
785+
let! existingBugBuckets = Raft.RESTlerDriver.getListOfBugsFromBugBuckets replayRunConfiguration.InputFolderPath
786+
787+
let remapBugHashes (bugHashes : Raft.RESTlerTypes.Logs.BugHashes) =
788+
bugHashes
789+
|> Seq.map(fun (KeyValue(k, v)) -> v.file_path, k)
790+
|> Map.ofSeq
791+
792+
let bugs, fileNameToBugHashMap =
793+
match replayRunConfiguration.IgnoreBugHashes, existingBugBuckets with
794+
| None, None | Some _, None -> bugs, Map.empty
795+
| None, Some existingBugs ->
796+
bugs, (remapBugHashes existingBugs)
797+
798+
| Some ignoreHashes, Some existingBugs ->
799+
let filesToIgnore =
800+
ignoreHashes
801+
|> Array.map(fun h ->
802+
match Map.tryFind h existingBugs with
803+
| None -> None
804+
| Some b -> Some b.file_path
805+
)
806+
|> Array.filter Option.isSome
807+
|> Array.map Option.get
808+
|> Set.ofArray
809+
810+
let filteredBugs =
811+
bugs
812+
|> Seq.filter (fun b ->
813+
not (filesToIgnore.Contains b.Name)
814+
)
815+
filteredBugs, (remapBugHashes existingBugs)
816+
766817
let replaySummaryDetails = ResizeArray<string * string>()
767818

768819
for bug in bugs do
769820
printfn "Running replay on %s" bug.FullName
770-
let! replaySummary = replay bug.FullName replayRunConfiguration
821+
let! (experiment, replaySummary) = replay bug.FullName replayRunConfiguration
771822
let summary =
772823
match replaySummary with
773824
| None ->
774825
sprintf "%s : No results" bug.Name
775826
| Some s ->
776-
sprintf "%s: %A" bug.Name (s.ResponseCodeCounts |> Map.toList)
827+
sprintf "%s/%s: %A" (Option.defaultValue "ExperimentNotSet" experiment) bug.Name (s.ResponseCodeCounts |> Map.toList)
777828

778-
replaySummaryDetails.Add(bug.Name, summary)
829+
let bugKey =
830+
match Map.tryFind bug.Name fileNameToBugHashMap with
831+
| None -> bug.Name
832+
| Some h -> h
833+
replaySummaryDetails.Add(bugKey, summary)
779834
do! jobEventSender.SendRaftJobEvent jobId
780835
({
781836
AgentName = agentName
@@ -823,7 +878,7 @@ let main argv =
823878
return Some details
824879
| None -> return! replayAll()
825880
}
826-
return Raft.JobEvents.Completed, (details |> Option.map Map.ofSeq), 0, None
881+
return Raft.JobEvents.Completed, (details |> Option.map Map.ofSeq), 0, (None, None)
827882
with
828883
| ex ->
829884
printfn "%A" ex
@@ -832,17 +887,24 @@ let main argv =
832887
}
833888

834889
let! bugsList = Raft.RESTlerDriver.getListOfBugs workDirectory globalRunStartTime
890+
let bugsListLen = match bugsList with None -> 0 | Some xs -> Seq.length xs
835891

836892
let testingSummary = Raft.RESTlerDriver.loadTestRunSummary workDirectory globalRunStartTime
837893

894+
let details =
895+
let d = Option.defaultValue Map.empty details
896+
match experiment with
897+
| Some e -> Some (d.Add("Experiment", e))
898+
| None -> Some d
899+
838900
let details =
839901
match testingSummary with
840902
| None -> details
841903
| Some status ->
842904
let d = Option.defaultValue Map.empty details
843905
Some( d
844906
.Add("finalSpecCoverage", status.final_spec_coverage)
845-
.Add("numberOfBugsFound", sprintf "%d" (Seq.length bugsList))
907+
.Add("numberOfBugsFound", sprintf "%d" bugsListLen)
846908
//.Add("renderedRequests", status.rendered_requests)
847909
//.Add("renderedRequestsValidStatus", status.rendered_requests_valid_status)
848910
//.Add("numFullyValid", sprintf "%d" status.num_fully_valid)

src/Agent/RESTlerAgent/RESTlerAgentConfigTypes.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,11 @@ type RunConfiguration =
102102

103103
/// Path regex for filtering tested endpoints
104104
PathRegex : string option
105-
}
106105

106+
// In context of Replay - do not replay bugs specified in the list
107+
// In context of Test or Fuzz - do not post onBugFound events if they are in the list
108+
IgnoreBugHashes : string array option
109+
}
107110

108111

109112
type AgentConfiguration =

0 commit comments

Comments
 (0)