@@ -5,7 +5,11 @@ package main
55
66import (
77 "testing"
8+ "time"
89
10+ "github.com/google/syzkaller/dashboard/dashapi"
11+ "github.com/google/syzkaller/pkg/aflow/trajectory"
12+ "github.com/google/syzkaller/prog"
913 "github.com/stretchr/testify/require"
1014)
1115
@@ -23,4 +27,173 @@ func TestAIMigrations(t *testing.T) {
2327 require .NoError (t , executeSpannerDDL (c .ctx , down ))
2428 require .NoError (t , executeSpannerDDL (c .ctx , up ))
2529 require .NoError (t , executeSpannerDDL (c .ctx , down ))
30+ require .NoError (t , executeSpannerDDL (c .ctx , up ))
31+ }
32+
33+ func TestAIBugWorkflows (t * testing.T ) {
34+ c := NewSpannerCtx (t )
35+ defer c .Close ()
36+
37+ build := testBuild (1 )
38+ c .aiClient .UploadBuild (build )
39+
40+ // KCSAN bug w/o repro.
41+ crash1 := testCrash (build , 1 )
42+ crash1 .Title = "KCSAN: data-race in foo / bar"
43+ c .aiClient .ReportCrash (crash1 )
44+ bugExtID1 := c .aiClient .pollEmailExtID ()
45+ kcsanBug , _ , _ := c .loadBug (bugExtID1 )
46+
47+ // Bug2: KASAN bug with repro.
48+ crash2 := testCrashWithRepro (build , 2 )
49+ crash2 .Title = "KASAN: head-use-after-free in foo"
50+ c .aiClient .ReportCrash (crash2 )
51+ bugExtID2 := c .aiClient .pollEmailExtID ()
52+ kasanBug , _ , _ := c .loadBug (bugExtID2 )
53+
54+ requireWorkflows := func (bug * Bug , want []string ) {
55+ got , err := aiBugWorkflows (c .ctx , bug )
56+ require .NoError (t , err )
57+ require .Equal (t , got , want )
58+ }
59+ requireWorkflows (kcsanBug , nil )
60+ requireWorkflows (kasanBug , nil )
61+
62+ _ , err := c .aiClient .AIJobPoll (& dashapi.AIJobPollReq {
63+ CodeRevision : prog .GitRevision ,
64+ LLMModel : "smarty" ,
65+ Workflows : []dashapi.AIWorkflow {
66+ {Type : "patching" , Name : "patching" },
67+ {Type : "patching" , Name : "patching-foo" },
68+ {Type : "patching" , Name : "patching-bar" },
69+ },
70+ })
71+ require .NoError (t , err )
72+
73+ // This should make patching-foo inactive.
74+ c .advanceTime (2 * 24 * time .Hour )
75+
76+ _ , err = c .aiClient .AIJobPoll (& dashapi.AIJobPollReq {
77+ CodeRevision : prog .GitRevision ,
78+ LLMModel : "smarty" ,
79+ Workflows : []dashapi.AIWorkflow {
80+ {Type : "patching" , Name : "patching" },
81+ {Type : "patching" , Name : "patching-bar" },
82+ {Type : "patching" , Name : "patching-baz" },
83+ {Type : "assessment-kcsan" , Name : "assessment-kcsan" },
84+ },
85+ })
86+ require .NoError (t , err )
87+
88+ _ , err = c .aiClient .AIJobPoll (& dashapi.AIJobPollReq {
89+ CodeRevision : prog .GitRevision ,
90+ LLMModel : "smarty" ,
91+ Workflows : []dashapi.AIWorkflow {
92+ {Type : "patching" , Name : "patching" },
93+ {Type : "patching" , Name : "patching-bar" },
94+ {Type : "patching" , Name : "patching-qux" },
95+ {Type : "assessment-kcsan" , Name : "assessment-kcsan" },
96+ {Type : "assessment-kcsan" , Name : "assessment-kcsan-foo" },
97+ },
98+ })
99+ require .NoError (t , err )
100+
101+ requireWorkflows (kcsanBug , []string {"assessment-kcsan" , "assessment-kcsan-foo" })
102+ requireWorkflows (kasanBug , []string {"patching" , "patching-bar" , "patching-baz" , "patching-qux" })
103+ }
104+
105+ func TestAIJob (t * testing.T ) {
106+ c := NewSpannerCtx (t )
107+ defer c .Close ()
108+
109+ build := testBuild (1 )
110+ c .aiClient .UploadBuild (build )
111+ crash := testCrash (build , 1 )
112+ crash .Title = "KCSAN: data-race in foo / bar"
113+ c .aiClient .ReportCrash (crash )
114+ c .aiClient .pollEmailBug ()
115+
116+ resp , err := c .aiClient .AIJobPoll (& dashapi.AIJobPollReq {
117+ CodeRevision : prog .GitRevision ,
118+ LLMModel : "smarty" ,
119+ Workflows : []dashapi.AIWorkflow {
120+ {Type : "assessment-kcsan" , Name : "assessment-kcsan" },
121+ },
122+ })
123+ require .NoError (t , err )
124+ require .NotEqual (t , resp .ID , "" )
125+ require .Equal (t , resp .Workflow , "assessment-kcsan" )
126+ require .Equal (t , resp .Args , map [string ]any {
127+ "CrashReport" : "report1" ,
128+ "KernelRepo" : "repo1" ,
129+ "KernelCommit" : "1111111111111111111111111111111111111111" ,
130+ "KernelConfig" : "config1" ,
131+ "SyzkallerCommit" : "syzkaller_commit1" ,
132+ "ReproOpts" : "" ,
133+ })
134+
135+ resp2 , err2 := c .aiClient .AIJobPoll (& dashapi.AIJobPollReq {
136+ CodeRevision : prog .GitRevision ,
137+ LLMModel : "smarty" ,
138+ Workflows : []dashapi.AIWorkflow {
139+ {Type : "assessment-kcsan" , Name : "assessment-kcsan" },
140+ },
141+ })
142+ require .NoError (t , err2 )
143+ require .Equal (t , resp2 .ID , "" )
144+
145+ require .NoError (t , c .aiClient .AITrajectoryLog (& dashapi.AITrajectoryReq {
146+ JobID : resp .ID ,
147+ Span : & trajectory.Span {
148+ Seq : 0 ,
149+ Type : trajectory .SpanFlow ,
150+ Name : "assessment-kcsan" ,
151+ Started : c .mockedTime ,
152+ },
153+ }))
154+
155+ require .NoError (t , c .aiClient .AITrajectoryLog (& dashapi.AITrajectoryReq {
156+ JobID : resp .ID ,
157+ Span : & trajectory.Span {
158+ Seq : 1 ,
159+ Type : trajectory .SpanAgent ,
160+ Name : "agent" ,
161+ Prompt : "do something" ,
162+ Started : c .mockedTime ,
163+ },
164+ }))
165+
166+ require .NoError (t , c .aiClient .AITrajectoryLog (& dashapi.AITrajectoryReq {
167+ JobID : resp .ID ,
168+ Span : & trajectory.Span {
169+ Seq : 1 ,
170+ Type : trajectory .SpanAgent ,
171+ Name : "agent" ,
172+ Prompt : "do something" ,
173+ Started : c .mockedTime ,
174+ Finished : c .mockedTime .Add (time .Second ),
175+ Reply : "something" ,
176+ },
177+ }))
178+
179+ require .NoError (t , c .aiClient .AITrajectoryLog (& dashapi.AITrajectoryReq {
180+ JobID : resp .ID ,
181+ Span : & trajectory.Span {
182+ Seq : 0 ,
183+ Type : trajectory .SpanFlow ,
184+ Name : "assessment-kcsan" ,
185+ Started : c .mockedTime ,
186+ Finished : c .mockedTime .Add (time .Second ),
187+ },
188+ }))
189+
190+ require .NoError (t , c .aiClient .AIJobDone (& dashapi.AIJobDoneReq {
191+ ID : resp .ID ,
192+ Results : map [string ]any {
193+ "Patch" : "patch" ,
194+ "Explanation" : "foo" ,
195+ "Number" : 1 ,
196+ "Bool" : true ,
197+ },
198+ }))
26199}
0 commit comments