26
26
combined=name-of-manifest.json
27
27
[db]
28
28
db=db-name
29
+ stability-name=table-name
29
30
results-name=table-name
30
31
branches-name=table-name
31
32
"""
32
33
34
+ def result_flatten (full ):
35
+ """
36
+ Take in a full result dict (for one run, with subtests).
37
+ Return a list of dicts:
38
+ [
39
+ { "group": str, "test": str, "subtest": str/None, "result": bool },
40
+ ]
41
+ """
42
+ flat = []
43
+
44
+ for test in full ["results" ]:
45
+ l1 = { "group" : test ["group" ],
46
+ "test" : test ["test" ],
47
+ "subtest" : None ,
48
+ "result" : test ["result" ].lower () == "pass"
49
+ }
50
+ flat .append (l1 )
51
+ for case in test .get ("results" , []):
52
+ data = l1 .copy ()
53
+ data ["subtest" ] = case ["test" ]
54
+ data ["result" ] = case ["result" ].lower () == "pass"
55
+ flat .append (data )
56
+
57
+ return flat
58
+
33
59
34
60
class FetcherState :
35
61
def __init__ (self ):
@@ -39,6 +65,7 @@ def __init__(self):
39
65
# "fetched" is more of a "need state rebuild"
40
66
self .fetched = True
41
67
68
+ self .tbl_stb = self .config .get ("db" , "stability-name" , fallback = "stability" )
42
69
self .tbl_res = self .config .get ("db" , "results-name" , fallback = "results" )
43
70
self .tbl_brn = self .config .get ("db" , "branches-name" , fallback = "branches" )
44
71
@@ -104,6 +131,70 @@ def psql_json_split(self, data):
104
131
full = json .dumps (data )
105
132
return json .dumps (normal ), full
106
133
134
+ def psql_stability_selector (self , cur , data , row ):
135
+ base = cur .mogrify ("WHERE remote = %s AND executor = %s AND grp = %s AND test = %s" ,
136
+ (data ["remote" ], data ["executor" ], row ["group" ], row ["test" ],)).decode ('utf-8' )
137
+
138
+ if row ["subtest" ] is None :
139
+ return base + " AND subtest is NULL"
140
+ return base + cur .mogrify (" AND subtest = %s" , (row ["subtest" ],)).decode ('utf-8' )
141
+
142
+ def psql_get_stability (self , data , row ):
143
+ with self .psql_conn .cursor () as cur :
144
+ cur .execute (f"SELECT pass_cnt, fail_cnt, pass_srk, fail_srk, pass_cur, fail_cur, passing FROM { self .tbl_stb } " +
145
+ self .psql_stability_selector (cur , data , row ))
146
+ rows = cur .fetchall ()
147
+ if rows and len (rows ) > 0 :
148
+ res = rows [0 ]
149
+ else :
150
+ res = [0 ] * 10
151
+ res [6 ] = None # passing
152
+ return {
153
+ "pass_cnt" : res [0 ],
154
+ "fail_cnt" : res [1 ],
155
+ "pass_srk" : res [2 ],
156
+ "fail_srk" : res [3 ],
157
+ "pass_cur" : res [4 ],
158
+ "fail_cur" : res [5 ],
159
+ "passing" : res [6 ],
160
+ "exists" : bool (rows ),
161
+ }
162
+
163
+ def psql_insert_stability (self , data ):
164
+ flat = result_flatten (data )
165
+
166
+ for row in flat :
167
+ # Fetch current state
168
+ stability = self .psql_get_stability (data , row )
169
+ if not stability ["exists" ]:
170
+ with self .psql_conn .cursor () as cur :
171
+ cur .execute (f"INSERT INTO { self .tbl_stb } (remote, executor, grp, test, subtest) " +
172
+ cur .mogrify ("VALUES (%s, %s, %s, %s, %s)" ,
173
+ (data ["remote" ], data ["executor" ], row ["group" ], row ["test" ], row ["subtest" ],)).decode ('utf-8' ))
174
+ # Update state
175
+ if row ["result" ]:
176
+ key_pfx = "pass"
177
+ stability ["fail_cur" ] = 0
178
+ else :
179
+ key_pfx = "fail"
180
+ stability ["pass_cur" ] = 0
181
+
182
+ stability [key_pfx + "_cnt" ] += 1
183
+ stability [key_pfx + "_cur" ] += 1
184
+ stability [key_pfx + "_srk" ] = max (stability [key_pfx + "_cur" ], stability [key_pfx + "_srk" ])
185
+
186
+ now = datetime .datetime .now ().isoformat () + "+00:00"
187
+ if stability [key_pfx + "_srk" ] > 15 and not stability ["passing" ]: # 5 clean days for HW
188
+ print ("Test reached stability" , row ["remote" ], row ["test" ], row ["subtest" ])
189
+ stability ["passing" ] = now
190
+
191
+ with self .psql_conn .cursor () as cur :
192
+ cur .execute (f"UPDATE { self .tbl_stb } SET " +
193
+ cur .mogrify ("pass_cnt = %s, fail_cnt = %s, pass_srk = %s, fail_srk = %s, pass_cur = %s, fail_cur = %s, passing = %s, last_update = %s" ,
194
+ (stability ["pass_cnt" ], stability ["fail_cnt" ], stability ["pass_srk" ], stability ["fail_srk" ],
195
+ stability ["pass_cur" ], stability ["fail_cur" ], stability ["passing" ], now )).decode ('utf-8' ) +
196
+ self .psql_stability_selector (cur , data , row ))
197
+
107
198
def insert_real (self , remote , run ):
108
199
data = run .copy ()
109
200
data ["remote" ] = remote ["name" ]
@@ -119,6 +210,8 @@ def insert_real(self, remote, run):
119
210
q = f"UPDATE { self .tbl_res } " + vals + ' ' + selector
120
211
cur .execute (q )
121
212
213
+ self .psql_insert_stability (data )
214
+
122
215
123
216
def write_json_atomic (path , data ):
124
217
tmp = path + '.new'
0 commit comments