Remove obsolete code and database info.
This commit is contained in:
Родитель
63fcafd3b0
Коммит
131b1b41f3
2
TODO
2
TODO
|
@ -1,2 +0,0 @@
|
||||||
UPDATE.php: make sequential
|
|
||||||
migrate-2.php: create a sequence out of what used to be a stamp
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
$migrate = function() {
|
||||||
|
mysql_query("DROP TABLE awfy_regression_breakdown_noise");
|
||||||
|
mysql_query("DROP TABLE awfy_regression_score_noise");
|
||||||
|
mysql_query("ALTER TABLE `awfy_suite` DROP `confidence_factor`;");
|
||||||
|
mysql_query("ALTER TABLE `awfy_suite_test` DROP `confidence_factor`;");
|
||||||
|
mysql_query("ALTER TABLE `awfy_machine` DROP `confidence_runs`");
|
||||||
|
};
|
||||||
|
|
||||||
|
$rollback = function() {
|
||||||
|
|
||||||
|
mysql_query("CREATE TABLE `awfy_regression_breakdown_noise` (
|
||||||
|
`id` int(10) UNSIGNED NOT NULL,
|
||||||
|
`machine_id` int(10) UNSIGNED NOT NULL,
|
||||||
|
`mode_id` int(10) UNSIGNED NOT NULL,
|
||||||
|
`suite_test_id` int(10) UNSIGNED NOT NULL,
|
||||||
|
`noise` double NOT NULL,
|
||||||
|
`disabled` tinyint(1) NOT NULL DEFAULT '0'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='avg_consequent_diff'");
|
||||||
|
|
||||||
|
mysql_query("ALTER TABLE `awfy_regression_breakdown_noise`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD UNIQUE KEY `machine_id` (`machine_id`,`mode_id`,`suite_test_id`)");
|
||||||
|
|
||||||
|
mysql_query("ALTER TABLE `awfy_regression_breakdown_noise`
|
||||||
|
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT");
|
||||||
|
|
||||||
|
mysql_query("CREATE TABLE `awfy_regression_score_noise` (
|
||||||
|
`id` int(10) UNSIGNED NOT NULL,
|
||||||
|
`machine_id` int(10) UNSIGNED NOT NULL,
|
||||||
|
`mode_id` int(10) UNSIGNED NOT NULL,
|
||||||
|
`suite_version_id` int(10) UNSIGNED NOT NULL,
|
||||||
|
`noise` double NOT NULL,
|
||||||
|
`disabled` tinyint(1) NOT NULL DEFAULT '0'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='avg_consequent_diff'");
|
||||||
|
|
||||||
|
mysql_query("ALTER TABLE `awfy_regression_score_noise`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `machine_id` (`machine_id`),
|
||||||
|
ADD KEY `mode_id` (`mode_id`),
|
||||||
|
ADD KEY `suite_version_id` (`suite_version_id`)");
|
||||||
|
|
||||||
|
mysql_query("ALTER TABLE `awfy_regression_score_noise`
|
||||||
|
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT");
|
||||||
|
|
||||||
|
mysql_query("ALTER TABLE `awfy_suite` ADD `confidence_factor` FLOAT NOT NULL DEFAULT '1' AFTER `visible`");
|
||||||
|
mysql_query("ALTER TABLE `awfy_suite_test` ADD `confidence_factor` FLOAT NOT NULL DEFAULT '1' AFTER `visible`");
|
||||||
|
mysql_query("ALTER TABLE `awfy_machine` ADD `confidence_runs` TINYINT NOT NULL DEFAULT '5' AFTER `message`");
|
||||||
|
};
|
|
@ -1,109 +0,0 @@
|
||||||
# vim: set ts=4 sw=4 tw=99 et:
|
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
sys.path.append("../server")
|
|
||||||
import awfy
|
|
||||||
import tables
|
|
||||||
|
|
||||||
|
|
||||||
parser = OptionParser(usage="usage: %prog [options]")
|
|
||||||
parser.add_option("-n", "--non-existing", dest="nonexistonly", action="store_true", default=False,
|
|
||||||
help="Only compute noise of items that don't have one yet.")
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
|
|
||||||
def median(x):
|
|
||||||
x.sort()
|
|
||||||
length = len(x)
|
|
||||||
if length % 2 == 1:
|
|
||||||
return x[length/2]
|
|
||||||
else:
|
|
||||||
return (x[(length-1)/2] + x[(length+1)/2]) / 2.0
|
|
||||||
|
|
||||||
def avg_diff(machine, suite, mode, first):
|
|
||||||
prev = first
|
|
||||||
current = first.next()
|
|
||||||
diffs = []
|
|
||||||
while current:
|
|
||||||
diff = abs(prev.get('score') - current.get('score'))
|
|
||||||
if diff != 0:
|
|
||||||
diffs.append(diff)
|
|
||||||
|
|
||||||
prev = current
|
|
||||||
current = current.next()
|
|
||||||
if len(diffs) == 0:
|
|
||||||
return None
|
|
||||||
return median(diffs)
|
|
||||||
|
|
||||||
def equal_sign(a, b):
|
|
||||||
if a >= 0 and b >= 0:
|
|
||||||
return True
|
|
||||||
if a <= 0 and b <= 0:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def avg_consequent_diff(machine, suite, mode, first):
|
|
||||||
prev = first
|
|
||||||
current = first.next()
|
|
||||||
diffs = []
|
|
||||||
consequent = 0
|
|
||||||
while current:
|
|
||||||
diff = prev.get('score') - current.get('score')
|
|
||||||
if diff != 0:
|
|
||||||
if equal_sign(diff, consequent):
|
|
||||||
consequent += diff
|
|
||||||
else:
|
|
||||||
diffs.append(abs(consequent))
|
|
||||||
consequent = diff
|
|
||||||
|
|
||||||
prev = current
|
|
||||||
current = current.next()
|
|
||||||
if consequent != 0:
|
|
||||||
diffs.append(abs(consequent))
|
|
||||||
if len(diffs) == 0:
|
|
||||||
return None
|
|
||||||
return median(diffs)
|
|
||||||
|
|
||||||
for machine in tables.Machine.all():
|
|
||||||
if (machine.id != 28 and # mac os x 32 bit shell
|
|
||||||
machine.id != 29 and # mac os x 64 bit shell
|
|
||||||
machine.id != 26 and # ffos flame browser
|
|
||||||
machine.id != 30 and # mac os x browser
|
|
||||||
machine.id != 17): # windows 8 browser
|
|
||||||
continue
|
|
||||||
|
|
||||||
for mode in tables.Mode.allWith(machine):
|
|
||||||
for suite in tables.SuiteVersion.all():
|
|
||||||
# Don't update, only insert new ones, if requested
|
|
||||||
if tables.RegressionScoreNoise(machine, suite, mode).id != 0 and options.nonexistonly:
|
|
||||||
continue
|
|
||||||
|
|
||||||
first = tables.Score.firstOfRecent(machine, suite, mode)
|
|
||||||
if not first:
|
|
||||||
continue
|
|
||||||
diff = avg_consequent_diff(machine, suite, mode, first)
|
|
||||||
if not diff:
|
|
||||||
continue
|
|
||||||
tables.RegressionScoreNoise.insertOrUpdate(machine, suite, mode, diff)
|
|
||||||
print suite.get('name'), mode.get('name'), diff
|
|
||||||
awfy.db.commit()
|
|
||||||
for suite in tables.SuiteTest.all():
|
|
||||||
# Don't update, only insert new ones, if requested
|
|
||||||
if tables.RegressionBreakdownNoise(machine, suite, mode).id != 0 and options.nonexistonly:
|
|
||||||
continue
|
|
||||||
|
|
||||||
first = tables.Breakdown.firstOfRecent(machine, suite, mode)
|
|
||||||
if not first:
|
|
||||||
continue
|
|
||||||
diff = avg_consequent_diff(machine, suite, mode, first)
|
|
||||||
if not diff:
|
|
||||||
continue
|
|
||||||
tables.RegressionBreakdownNoise.insertOrUpdate(machine, suite, mode, diff)
|
|
||||||
print suite.get('name'), mode.get('name'), diff
|
|
||||||
awfy.db.commit()
|
|
||||||
|
|
|
@ -1,178 +0,0 @@
|
||||||
# vim: set ts=4 sw=4 tw=99 et:
|
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
pwd = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
sys.path.append("../server")
|
|
||||||
import awfy
|
|
||||||
import tables
|
|
||||||
|
|
||||||
RUNS = 20
|
|
||||||
|
|
||||||
def isOutliner(item):
|
|
||||||
score = item.score()
|
|
||||||
nexts = [i.get("score") for i in score.nexts_no_outliners(RUNS)]
|
|
||||||
prevs = [i.get("score") for i in score.prevs_no_outliners(RUNS)]
|
|
||||||
if len(nexts) != RUNS:
|
|
||||||
return False
|
|
||||||
if len(prevs) != RUNS:
|
|
||||||
return False
|
|
||||||
if not item.score().hasNoise():
|
|
||||||
return False
|
|
||||||
avg_nexts = sum(nexts)/len(nexts)
|
|
||||||
avg_prevs = sum(prevs)/len(prevs)
|
|
||||||
|
|
||||||
if abs(avg_nexts - avg_prevs) < score.noise() / tables.NOISE_FACTOR:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def isEmptyRegression(item):
|
|
||||||
score = item.score()
|
|
||||||
if score.prev().get("build").get("cset") == score.get("build").get("cset"):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def isBiModal(item):
|
|
||||||
def divide(li):
|
|
||||||
h = max(li)
|
|
||||||
l = min(li)
|
|
||||||
highs = []
|
|
||||||
lows = []
|
|
||||||
for i in li:
|
|
||||||
if h-i < i-l:
|
|
||||||
highs.append(i)
|
|
||||||
else:
|
|
||||||
lows.append(i)
|
|
||||||
return highs, lows
|
|
||||||
|
|
||||||
|
|
||||||
score = item.score()
|
|
||||||
nexts = [i.get("score") for i in score.nexts(RUNS)]
|
|
||||||
prevs = [i.get("score") for i in score.prevs(RUNS)]
|
|
||||||
nexts_h, nexts_l = divide(nexts)
|
|
||||||
prevs_h, prevs_l = divide(prevs)
|
|
||||||
|
|
||||||
if len(nexts_h) < 4:
|
|
||||||
return False
|
|
||||||
if len(nexts_l) < 4:
|
|
||||||
return False
|
|
||||||
if len(prevs_h) < 4:
|
|
||||||
return False
|
|
||||||
if len(prevs_l) < 4:
|
|
||||||
return False
|
|
||||||
if not score.hasNoise():
|
|
||||||
return False
|
|
||||||
avg_nexts_h = sum(nexts_h)/len(nexts_h)
|
|
||||||
avg_nexts_l = sum(nexts_l)/len(nexts_l)
|
|
||||||
avg_prevs_h = sum(prevs_h)/len(prevs_h)
|
|
||||||
avg_prevs_l = sum(prevs_l)/len(prevs_l)
|
|
||||||
|
|
||||||
if abs(avg_nexts_h - avg_prevs_h) >= score.noise() / tables.NOISE_FACTOR:
|
|
||||||
return False
|
|
||||||
if abs(avg_nexts_l - avg_prevs_l) >= score.noise() / tables.NOISE_FACTOR:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def zoomNoRegression(item):
|
|
||||||
PARTITIONS = 5
|
|
||||||
CRUNS = 100 / PARTITIONS * PARTITIONS
|
|
||||||
AMOUNT = CRUNS / PARTITIONS
|
|
||||||
|
|
||||||
def _avg(items):
|
|
||||||
if len(items) == 0:
|
|
||||||
return 0
|
|
||||||
return sum(items)/len(items)
|
|
||||||
|
|
||||||
def partition(li):
|
|
||||||
nli = []
|
|
||||||
for i in range(PARTITIONS):
|
|
||||||
nli.append(_avg(li[i*AMOUNT:i*AMOUNT+AMOUNT]))
|
|
||||||
return nli
|
|
||||||
|
|
||||||
def _noise(li):
|
|
||||||
noise = []
|
|
||||||
for i in range(len(li)-1):
|
|
||||||
noise.append(abs(li[i] - li[i+1]))
|
|
||||||
return noise
|
|
||||||
|
|
||||||
def outliner(li, i, noise):
|
|
||||||
if i == 0:
|
|
||||||
return False
|
|
||||||
elif len(li) - 1 == i:
|
|
||||||
return False
|
|
||||||
if abs(li[i-1] - li[i+1]) < noise:
|
|
||||||
if abs(li[i] - li[i+1]) > noise and abs(li[i] - li[i-1]) > noise:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def remove_outliners(li, noise):
|
|
||||||
return [li[i] for i in range(len(li)) if not outliner(li, i, noise)]
|
|
||||||
|
|
||||||
score = item.score()
|
|
||||||
nexts = [score.get("score")] + [i.get("score") for i in score.nexts(CRUNS - 1)]
|
|
||||||
prevs = [i.get("score") for i in score.prevs(CRUNS)]
|
|
||||||
if len(nexts) != CRUNS:
|
|
||||||
return False
|
|
||||||
if len(prevs) != CRUNS:
|
|
||||||
return False
|
|
||||||
|
|
||||||
nexts = partition(nexts)
|
|
||||||
prevs = partition(prevs)
|
|
||||||
noise = _avg(_noise(nexts) + _noise(prevs))
|
|
||||||
|
|
||||||
nexts = remove_outliners(nexts, noise)
|
|
||||||
prevs = remove_outliners(prevs, noise)
|
|
||||||
noise = _avg(_noise(nexts) + _noise(prevs))
|
|
||||||
if abs(nexts[0] - prevs[0]) > noise:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
modes = [14,16,20,21,22,23,25,26,27,28,29,31,32,33,35]
|
|
||||||
for regression in tables.Regression.where({'status':'unconfirmed'}):
|
|
||||||
if regression.get("build").get("mode_id") not in modes:
|
|
||||||
continue
|
|
||||||
|
|
||||||
allRemoved = True
|
|
||||||
for item in regression.regressions():
|
|
||||||
if item.get("noise"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
print "item"
|
|
||||||
|
|
||||||
if isEmptyRegression(item):
|
|
||||||
print "remove", regression.id
|
|
||||||
item.score().dump()
|
|
||||||
item.update({"noise":"1"})
|
|
||||||
continue
|
|
||||||
|
|
||||||
if isOutliner(item):
|
|
||||||
print "remove", regression.id
|
|
||||||
item.score().dump()
|
|
||||||
item.update({"noise":"1"})
|
|
||||||
continue
|
|
||||||
|
|
||||||
if isBiModal(item):
|
|
||||||
print "remove", regression.id
|
|
||||||
item.score().dump()
|
|
||||||
item.update({"noise":"1"})
|
|
||||||
continue
|
|
||||||
|
|
||||||
if zoomNoRegression(item):
|
|
||||||
print "remove", regression.id
|
|
||||||
item.score().dump()
|
|
||||||
item.update({"noise":"1"})
|
|
||||||
continue
|
|
||||||
|
|
||||||
allRemoved = False
|
|
||||||
|
|
||||||
if allRemoved:
|
|
||||||
print "remove item"
|
|
||||||
regression.update({"status":"noise"})
|
|
||||||
|
|
||||||
awfy.db.commit()
|
|
|
@ -1,141 +0,0 @@
|
||||||
# vim: set ts=4 sw=4 tw=99 et:
|
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
pwd = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
sys.path.append(pwd + "../server")
|
|
||||||
import awfy
|
|
||||||
import tables
|
|
||||||
|
|
||||||
parser = OptionParser(usage="usage: %prog [options]")
|
|
||||||
parser.add_option( "--dry-run", dest="dryrun", action="store_true", default=False,
|
|
||||||
help="Don't commit the new regressions to the database yet.")
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
|
|
||||||
def notProcessedRuns():
|
|
||||||
# Only look at reports in the last week
|
|
||||||
newer = int(time.time() - 60 * 60 * 24 * 7)
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id \
|
|
||||||
FROM awfy_run \
|
|
||||||
WHERE finish_stamp > "+str(newer)+" AND \
|
|
||||||
status = 1 AND \
|
|
||||||
detector != 1 AND \
|
|
||||||
machine in (28,29,26,17,30)")
|
|
||||||
runs = []
|
|
||||||
for row in c.fetchall():
|
|
||||||
runs.append(tables.Run(row[0]))
|
|
||||||
return runs
|
|
||||||
|
|
||||||
def regressed(score):
|
|
||||||
# Disabled. So no testing
|
|
||||||
if score.disabled():
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Lower than threshold, no regression.
|
|
||||||
change = score.change()
|
|
||||||
if change is None:
|
|
||||||
return None
|
|
||||||
if abs(change) <= score.noise():
|
|
||||||
return False
|
|
||||||
|
|
||||||
#Don't report outliners
|
|
||||||
if score.outliner():
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Don't report if same revision
|
|
||||||
if score.prev() is not None:
|
|
||||||
if score.get('build').get('cset') == score.prev().get('build').get('cset'):
|
|
||||||
return False
|
|
||||||
|
|
||||||
# average change over multiple runs.
|
|
||||||
change = score.avg_change()
|
|
||||||
|
|
||||||
# No change, so wait for more data before reporting.
|
|
||||||
if change is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Next is not available. Wait for that before reporting.
|
|
||||||
if not score.next():
|
|
||||||
return None
|
|
||||||
if score.next().avg_change() is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Next has a bigger change. Regression is more likely to be that.
|
|
||||||
if change >= 0 and score.next().avg_change() > change:
|
|
||||||
return False
|
|
||||||
if change <= 0 and score.next().avg_change() < change:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# If there is a prev, test that prev change is smaller
|
|
||||||
if score.prev():
|
|
||||||
if change >= 0 and score.prev().avg_change() >= change:
|
|
||||||
return False
|
|
||||||
if change <= 0 and score.prev().avg_change() <= change:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
os.environ['TZ'] = "Europe/Amsterdam"
|
|
||||||
time.tzset()
|
|
||||||
|
|
||||||
start = time.time()
|
|
||||||
for run in notProcessedRuns():
|
|
||||||
scores = run.getScoresAndBreakdowns()
|
|
||||||
finish = True
|
|
||||||
print "run:", run.get("id")
|
|
||||||
for score in scores:
|
|
||||||
if not score.sane():
|
|
||||||
continue
|
|
||||||
regressed_ = regressed(score)
|
|
||||||
|
|
||||||
# Not enough info yet
|
|
||||||
if regressed_ is None:
|
|
||||||
finish = False
|
|
||||||
|
|
||||||
if regressed_ is True:
|
|
||||||
score.dump()
|
|
||||||
if not options.dryrun:
|
|
||||||
build = score.get("build_id")
|
|
||||||
prev_build = score.prev().get("build_id")
|
|
||||||
regression = [regression for regression in tables.Regression.where({
|
|
||||||
"build_id": build,
|
|
||||||
"prev_build_id": prev_build
|
|
||||||
})]
|
|
||||||
if len(regression) == 0:
|
|
||||||
regression_id = tables.Regression.insert({
|
|
||||||
"build_id": build,
|
|
||||||
"prev_build_id": prev_build
|
|
||||||
})
|
|
||||||
tables.RegressionStatus.insert({"regression_id": regression_id,
|
|
||||||
"name": "awfy",
|
|
||||||
"extra": "Submitted",
|
|
||||||
"stamp":"UNIX_TIMESTAMP()"})
|
|
||||||
else:
|
|
||||||
regression_id = regression[0].id
|
|
||||||
|
|
||||||
try:
|
|
||||||
if score.__class__ == tables.Score:
|
|
||||||
tables.RegressionScore.insert({"regression_id": regression_id,
|
|
||||||
"score_id": score.get("id")})
|
|
||||||
elif score.__class__ == tables.Breakdown:
|
|
||||||
tables.RegressionBreakdown.insert({"regression_id": regression_id,
|
|
||||||
"breakdown_id": score.get("id")})
|
|
||||||
else:
|
|
||||||
assert False
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if finish and not options.dryrun:
|
|
||||||
run.update({"detector": "1"})
|
|
||||||
tables.DBTable.maybeflush()
|
|
||||||
|
|
||||||
awfy.db.commit()
|
|
|
@ -1,35 +0,0 @@
|
||||||
# vim: set ts=4 sw=4 tw=99 et:
|
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.append("../server")
|
|
||||||
import awfy
|
|
||||||
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
#TODO: ONLY DELETE IF REPORTED BY REGRESSION DETECTOR
|
|
||||||
c.execute("SELECT id, build_id \
|
|
||||||
FROM awfy_regression \
|
|
||||||
WHERE status = 'unconfirmed'")
|
|
||||||
for row in c.fetchall():
|
|
||||||
c.execute("DELETE FROM awfy_regression_breakdown \
|
|
||||||
WHERE build_id = %s", row[1])
|
|
||||||
c.execute("DELETE FROM awfy_regression_score \
|
|
||||||
WHERE build_id = %s", row[1])
|
|
||||||
c.execute("DELETE FROM awfy_regression_status \
|
|
||||||
WHERE regression_id = %s", row[0])
|
|
||||||
c.execute("DELETE FROM awfy_regression \
|
|
||||||
WHERE id = %s", row[0])
|
|
||||||
c.execute("UPDATE awfy_run \
|
|
||||||
LEFT JOIN awfy_build ON awfy_run.id = awfy_build.run_id \
|
|
||||||
SET detector = 0 \
|
|
||||||
WHERE awfy_build.id = %s", row[1])
|
|
||||||
|
|
||||||
print row[0]
|
|
||||||
#TODO: remove detector status from all itmes higher than the lowest run id
|
|
||||||
#c.execute("UPDATE awfy_run \
|
|
||||||
# SET detector = 0 \
|
|
||||||
# WHERE id > 249273")
|
|
||||||
awfy.db.commit()
|
|
614
server/tables.py
614
server/tables.py
|
@ -149,19 +149,6 @@ class Run(DBTable):
|
||||||
def table():
|
def table():
|
||||||
return "awfy_run"
|
return "awfy_run"
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def fromSortOrder(machine_id, sort_order):
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id \
|
|
||||||
FROM awfy_run \
|
|
||||||
WHERE machine = %s AND \
|
|
||||||
sort_order = %s", (machine_id, sort_order))
|
|
||||||
rows = c.fetchall()
|
|
||||||
if len(rows) == 0:
|
|
||||||
return None
|
|
||||||
assert len(rows) == 1
|
|
||||||
return Run(rows[0][0])
|
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
if self.initialized:
|
if self.initialized:
|
||||||
return
|
return
|
||||||
|
@ -170,16 +157,6 @@ class Run(DBTable):
|
||||||
self.cached["machine_id"] = self.cached["machine"]
|
self.cached["machine_id"] = self.cached["machine"]
|
||||||
del self.cached["machine"]
|
del self.cached["machine"]
|
||||||
|
|
||||||
def getScoresAndBreakdowns(self):
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id \
|
|
||||||
FROM awfy_build \
|
|
||||||
WHERE run_id = %s", (self.id,))
|
|
||||||
scores = []
|
|
||||||
for row in c.fetchall():
|
|
||||||
scores += Build(row[0]).getScoresAndBreakdowns()
|
|
||||||
return scores
|
|
||||||
|
|
||||||
def getScores(self):
|
def getScores(self):
|
||||||
c = awfy.db.cursor()
|
c = awfy.db.cursor()
|
||||||
c.execute("SELECT id \
|
c.execute("SELECT id \
|
||||||
|
@ -190,9 +167,6 @@ class Run(DBTable):
|
||||||
scores += Build(row[0]).getScores()
|
scores += Build(row[0]).getScores()
|
||||||
return scores
|
return scores
|
||||||
|
|
||||||
def finishStamp(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SuiteTest(DBTable):
|
class SuiteTest(DBTable):
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
DBTable.__init__(self, id)
|
DBTable.__init__(self, id)
|
||||||
|
@ -229,137 +203,10 @@ class Mode(DBTable):
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
DBTable.__init__(self, id)
|
DBTable.__init__(self, id)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def allWith(class_, machine):
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT distinct(awfy_build.mode_id) \
|
|
||||||
FROM awfy_build \
|
|
||||||
LEFT JOIN awfy_run ON awfy_build.run_id = awfy_run.id \
|
|
||||||
WHERE machine = %s", (machine.get("id"),))
|
|
||||||
for row in c.fetchall():
|
|
||||||
if row[0] == 0:
|
|
||||||
continue
|
|
||||||
yield Mode(row[0])
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def table():
|
def table():
|
||||||
return "awfy_mode"
|
return "awfy_mode"
|
||||||
|
|
||||||
class Regression(DBTable):
|
|
||||||
def __init__(self, id):
|
|
||||||
DBTable.__init__(self, id)
|
|
||||||
|
|
||||||
def regressions(self):
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id FROM awfy_regression_breakdown \
|
|
||||||
WHERE regression_id = %s", (self.id,))
|
|
||||||
for row in c.fetchall():
|
|
||||||
if row[0] == 0:
|
|
||||||
continue
|
|
||||||
yield RegressionBreakdown(row[0])
|
|
||||||
c.execute("SELECT id FROM awfy_regression_score \
|
|
||||||
WHERE regression_id = %s", (self.id,))
|
|
||||||
for row in c.fetchall():
|
|
||||||
if row[0] == 0:
|
|
||||||
continue
|
|
||||||
yield RegressionScore(row[0])
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def table():
|
|
||||||
return "awfy_regression"
|
|
||||||
|
|
||||||
class RegressionScore(DBTable):
|
|
||||||
|
|
||||||
def score(self):
|
|
||||||
return self.get("score")
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def table():
|
|
||||||
return "awfy_regression_score"
|
|
||||||
|
|
||||||
class RegressionScoreNoise(DBTable):
|
|
||||||
def __init__(self, machine, suite, mode):
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id FROM "+self.table()+" \
|
|
||||||
WHERE machine_id = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_version_id = %s", (machine.get("id"), mode.get("id"), suite.get("id")))
|
|
||||||
row = c.fetchone()
|
|
||||||
id = row[0] if row else 0
|
|
||||||
DBTable.__init__(self, id)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def insertOrUpdate(class_, machine, suite, mode, noise):
|
|
||||||
try:
|
|
||||||
RegressionScoreNoise.insert({
|
|
||||||
"machine_id": machine.get("id"),
|
|
||||||
"suite_version_id": suite.get("id"),
|
|
||||||
"mode_id": mode.get("id"),
|
|
||||||
"noise": noise
|
|
||||||
})
|
|
||||||
except:
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("UPDATE "+class_.table()+" \
|
|
||||||
SET noise = %s \
|
|
||||||
WHERE machine_id = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_version_id = %s", (noise, machine.get("id"), mode.get("id"),
|
|
||||||
suite.get("id")))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def table():
|
|
||||||
return "awfy_regression_score_noise"
|
|
||||||
|
|
||||||
class RegressionBreakdown(DBTable):
|
|
||||||
|
|
||||||
def score(self):
|
|
||||||
return self.get("breakdown")
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def table():
|
|
||||||
return "awfy_regression_breakdown"
|
|
||||||
|
|
||||||
class RegressionBreakdownNoise(DBTable):
|
|
||||||
def __init__(self, machine, suite, mode):
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id FROM "+self.table()+" \
|
|
||||||
WHERE machine_id = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_test_id = %s", (machine.get("id"), mode.get("id"), suite.get("id")))
|
|
||||||
row = c.fetchone()
|
|
||||||
id = row[0] if row else 0
|
|
||||||
DBTable.__init__(self, id)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def insertOrUpdate(class_, machine, suite, mode, noise):
|
|
||||||
try:
|
|
||||||
RegressionBreakdownNoise.insert({
|
|
||||||
"machine_id": machine.get("id"),
|
|
||||||
"suite_test_id": suite.get("id"),
|
|
||||||
"mode_id": mode.get("id"),
|
|
||||||
"noise": noise
|
|
||||||
})
|
|
||||||
except:
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("UPDATE "+class_.table()+" \
|
|
||||||
SET noise = %s \
|
|
||||||
WHERE machine_id = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_test_id = %s", (noise, machine.get("id"), mode.get("id"),
|
|
||||||
suite.get("id")))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def table():
|
|
||||||
return "awfy_regression_breakdown_noise"
|
|
||||||
|
|
||||||
class RegressionStatus(DBTable):
|
|
||||||
def __init__(self, id):
|
|
||||||
DBTable.__init__(self, id)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def table():
|
|
||||||
return "awfy_regression_status"
|
|
||||||
|
|
||||||
class Build(DBTable):
|
class Build(DBTable):
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
DBTable.__init__(self, id)
|
DBTable.__init__(self, id)
|
||||||
|
@ -391,231 +238,10 @@ class Build(DBTable):
|
||||||
scores.append(Score(row[0]))
|
scores.append(Score(row[0]))
|
||||||
return scores
|
return scores
|
||||||
|
|
||||||
def getScoresAndBreakdowns(self):
|
|
||||||
scores = self.getScores()
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT awfy_breakdown.id \
|
|
||||||
FROM awfy_breakdown \
|
|
||||||
LEFT JOIN awfy_score ON awfy_score.id = score_id \
|
|
||||||
WHERE build_id = %s", (self.id,))
|
|
||||||
for row in c.fetchall():
|
|
||||||
scores.append(Breakdown(row[0]))
|
|
||||||
return scores
|
|
||||||
|
|
||||||
class RegressionTools(DBTable):
|
class RegressionTools(DBTable):
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
DBTable.__init__(self, id)
|
DBTable.__init__(self, id)
|
||||||
|
|
||||||
def outliner(self):
|
|
||||||
if self.next() is None:
|
|
||||||
return False
|
|
||||||
if self.prev() is None:
|
|
||||||
return False
|
|
||||||
if not self.hasNoise():
|
|
||||||
return False
|
|
||||||
if abs(self.next().get("score") - self.prev().get("score")) < self.noise():
|
|
||||||
if (abs(self.next().get("score") - self.get("score")) > self.noise() and
|
|
||||||
abs(self.prev().get("score") - self.get("score")) > self.noise()):
|
|
||||||
return True
|
|
||||||
prevs, _ = self.avg_prevs_nexts()
|
|
||||||
_, nexts = self.next().avg_prevs_nexts()
|
|
||||||
if prevs is None or nexts is None:
|
|
||||||
return False
|
|
||||||
if abs(prevs-nexts) <= self.noise():
|
|
||||||
# ?? should this be prevs - self.get("score") ? maybe ?
|
|
||||||
if (abs(self.get('score') - self.prev().get('score')) > self.noise() and
|
|
||||||
abs(self.get('score') - self.next().get('score')) > self.noise()):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def next(self):
|
|
||||||
self.initialize()
|
|
||||||
if "next" not in self.cached:
|
|
||||||
self.cached["next"] = self.compute_next()
|
|
||||||
return self.cached["next"]
|
|
||||||
|
|
||||||
def compute_next(self):
|
|
||||||
nexts = self.prefetch_next(10)
|
|
||||||
|
|
||||||
prev = self
|
|
||||||
prev.cached["next"] = None
|
|
||||||
for score in nexts:
|
|
||||||
prev.initialize()
|
|
||||||
prev.cached["next"] = score
|
|
||||||
score.initialize()
|
|
||||||
score.cached["prev"] = prev
|
|
||||||
prev = score
|
|
||||||
|
|
||||||
return self.cached["next"]
|
|
||||||
|
|
||||||
def prev(self):
|
|
||||||
self.initialize()
|
|
||||||
if "prev" not in self.cached:
|
|
||||||
self.cached["prev"] = self.compute_prev()
|
|
||||||
if self.cached["prev"]:
|
|
||||||
self.cached["prev"].initialize()
|
|
||||||
self.cached["prev"].cached["next"] = self
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
return self.cached["prev"]
|
|
||||||
|
|
||||||
def compute_prev(self):
|
|
||||||
prevs = self.prefetch_prev(10)
|
|
||||||
|
|
||||||
next_ = self
|
|
||||||
next_.cached["prev"] = None
|
|
||||||
for score in prevs:
|
|
||||||
next_.initialize()
|
|
||||||
next_.cached["prev"] = score
|
|
||||||
score.initialize()
|
|
||||||
score.cached["next"] = next_
|
|
||||||
next_ = score
|
|
||||||
|
|
||||||
return self.cached["prev"]
|
|
||||||
|
|
||||||
def prevs(self, amount):
|
|
||||||
prevs = []
|
|
||||||
point = self
|
|
||||||
while len(prevs) < amount:
|
|
||||||
point = point.prev()
|
|
||||||
if not point:
|
|
||||||
break
|
|
||||||
prevs.append(point)
|
|
||||||
return prevs
|
|
||||||
|
|
||||||
def nexts(self, amount):
|
|
||||||
nexts = []
|
|
||||||
point = self
|
|
||||||
while len(nexts) < amount:
|
|
||||||
point = point.next()
|
|
||||||
if not point:
|
|
||||||
break
|
|
||||||
nexts.append(point)
|
|
||||||
return nexts
|
|
||||||
|
|
||||||
def prevs_no_outliners(self, amount):
|
|
||||||
# note this removes outliners
|
|
||||||
prevs = []
|
|
||||||
point = self
|
|
||||||
while len(prevs) < amount:
|
|
||||||
point = point.prev()
|
|
||||||
if not point:
|
|
||||||
break
|
|
||||||
if point.outliner():
|
|
||||||
continue
|
|
||||||
prevs.append(point)
|
|
||||||
return prevs
|
|
||||||
|
|
||||||
def nexts_no_outliners(self, amount):
|
|
||||||
# note this removes outliners
|
|
||||||
nexts = []
|
|
||||||
point = self
|
|
||||||
while len(nexts) < amount:
|
|
||||||
point = point.next()
|
|
||||||
if not point:
|
|
||||||
break
|
|
||||||
if point.outliner():
|
|
||||||
continue
|
|
||||||
nexts.append(point)
|
|
||||||
return nexts
|
|
||||||
|
|
||||||
def avg_prevs_no_outliners(self):
|
|
||||||
avg_prevs, _ = self.avg_prevs_nexts_no_outliners()
|
|
||||||
return avg_prevs
|
|
||||||
|
|
||||||
def avg_nexts_no_outliners(self):
|
|
||||||
_, avg_nexts = self.avg_prevs_nexts_no_outliners()
|
|
||||||
return avg_nexts
|
|
||||||
|
|
||||||
def avg_prevs_nexts_no_outliners(self):
|
|
||||||
self.initialize()
|
|
||||||
if "avg_prevs_no_outliners" not in self.cached:
|
|
||||||
self.cached["avg_prevs_no_outliners"], self.cached["avg_nexts_no_outliners"] = self.compute_avg_prevs_nexts_no_outliners()
|
|
||||||
return self.cached["avg_prevs_no_outliners"], self.cached["avg_nexts_no_outliners"]
|
|
||||||
|
|
||||||
def avg_prevs_nexts(self):
|
|
||||||
self.initialize()
|
|
||||||
if "avg_prevs" not in self.cached:
|
|
||||||
self.cached["avg_prevs"], self.cached["avg_nexts"] = self.compute_avg_prevs_nexts()
|
|
||||||
return self.cached["avg_prevs"], self.cached["avg_nexts"]
|
|
||||||
|
|
||||||
def compute_avg_prevs_nexts_no_outliners(self):
|
|
||||||
"Compute the change in runs before and after the current run"
|
|
||||||
# How many runs do we need to test?
|
|
||||||
runs = self.runs()
|
|
||||||
|
|
||||||
# Get scores before and after this run.
|
|
||||||
prevs = [i.get('score') for i in self.prevs_no_outliners(runs)]
|
|
||||||
nexts = [self.get('score')] + [i.get('score') for i in self.nexts_no_outliners(runs - 1)]
|
|
||||||
|
|
||||||
p_weight = [len(prevs)-i for i in range(len(prevs))]
|
|
||||||
n_weight = [len(nexts)-i for i in range(len(nexts))]
|
|
||||||
prevs = [prevs[i]*p_weight[i] for i in range(len(prevs))]
|
|
||||||
nexts = [nexts[i]*n_weight[i] for i in range(len(nexts))]
|
|
||||||
|
|
||||||
# Not enough data to compute change.
|
|
||||||
if len(nexts) != runs:
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
avg_prevs = sum(prevs)
|
|
||||||
avg_nexts = sum(nexts)
|
|
||||||
|
|
||||||
# Handle edge cases.
|
|
||||||
if avg_prevs != 0:
|
|
||||||
avg_prevs /= sum(p_weight)
|
|
||||||
if avg_nexts != 0:
|
|
||||||
avg_nexts /= sum(n_weight)
|
|
||||||
|
|
||||||
return avg_prevs, avg_nexts
|
|
||||||
|
|
||||||
def compute_avg_prevs_nexts(self):
|
|
||||||
"Compute the change in runs before and after the current run"
|
|
||||||
# How many runs do we need to test?
|
|
||||||
runs = self.runs()
|
|
||||||
|
|
||||||
# Get scores before and after this run.
|
|
||||||
prevs = [i.get('score') for i in self.prevs(runs)]
|
|
||||||
nexts = [self.get('score')] + [i.get('score') for i in self.nexts(runs - 1)]
|
|
||||||
|
|
||||||
p_weight = [len(prevs)-i for i in range(len(prevs))]
|
|
||||||
n_weight = [len(nexts)-i for i in range(len(nexts))]
|
|
||||||
prevs = [prevs[i]*p_weight[i] for i in range(len(prevs))]
|
|
||||||
nexts = [nexts[i]*n_weight[i] for i in range(len(nexts))]
|
|
||||||
|
|
||||||
# Not enough data to compute change.
|
|
||||||
if len(nexts) != runs:
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
avg_prevs = sum(prevs)
|
|
||||||
avg_nexts = sum(nexts)
|
|
||||||
|
|
||||||
# Handle edge cases.
|
|
||||||
if avg_prevs != 0:
|
|
||||||
avg_prevs /= sum(p_weight)
|
|
||||||
if avg_nexts != 0:
|
|
||||||
avg_nexts /= sum(n_weight)
|
|
||||||
|
|
||||||
return avg_prevs, avg_nexts
|
|
||||||
|
|
||||||
def change(self):
|
|
||||||
prevs, nexts = self.avg_prevs_nexts_no_outliners()
|
|
||||||
if not prevs or not nexts:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return abs(prevs - nexts)
|
|
||||||
|
|
||||||
def avg_change(self):
|
|
||||||
prevs, nexts = self.avg_prevs_nexts_no_outliners()
|
|
||||||
if not prevs or not nexts:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if prevs == 0:
|
|
||||||
return float("inf")
|
|
||||||
|
|
||||||
change = (prevs - nexts) / (prevs)
|
|
||||||
return change
|
|
||||||
|
|
||||||
|
|
||||||
class Score(RegressionTools):
|
class Score(RegressionTools):
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
RegressionTools.__init__(self, id)
|
RegressionTools.__init__(self, id)
|
||||||
|
@ -624,19 +250,6 @@ class Score(RegressionTools):
|
||||||
def table():
|
def table():
|
||||||
return "awfy_score"
|
return "awfy_score"
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def fromBuildAndSuite(build_id, suite_version_id):
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id \
|
|
||||||
FROM awfy_score \
|
|
||||||
WHERE build_id = %s AND \
|
|
||||||
suite_version_id = %s", (build_id, suite_version_id))
|
|
||||||
rows = c.fetchall()
|
|
||||||
if len(rows) == 0:
|
|
||||||
return None
|
|
||||||
assert len(rows) == 1
|
|
||||||
return Score(rows[0][0])
|
|
||||||
|
|
||||||
def getBreakdowns(self):
|
def getBreakdowns(self):
|
||||||
c = awfy.db.cursor()
|
c = awfy.db.cursor()
|
||||||
c.execute("SELECT awfy_breakdown.id \
|
c.execute("SELECT awfy_breakdown.id \
|
||||||
|
@ -647,116 +260,6 @@ class Score(RegressionTools):
|
||||||
breakdowns.append(Breakdown(row[0]))
|
breakdowns.append(Breakdown(row[0]))
|
||||||
return breakdowns
|
return breakdowns
|
||||||
|
|
||||||
def sane(self):
|
|
||||||
if self.get("suite_version_id") == -1:
|
|
||||||
return False
|
|
||||||
if self.get("suite_version_id") == 0:
|
|
||||||
return False
|
|
||||||
if not self.hasNoise():
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def prefetch_next(self, limit = 1):
|
|
||||||
sort_order = self.get("build").get("run").get("sort_order")
|
|
||||||
machine = self.get("build").get("run").get("machine_id")
|
|
||||||
mode = self.get("build").get("mode_id")
|
|
||||||
suite = self.get("suite_version_id")
|
|
||||||
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT awfy_score.id \
|
|
||||||
FROM awfy_score \
|
|
||||||
INNER JOIN awfy_build ON awfy_build.id = awfy_score.build_id \
|
|
||||||
INNER JOIN awfy_run ON awfy_run.id = awfy_build.run_id \
|
|
||||||
WHERE sort_order > %s AND \
|
|
||||||
machine = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_version_id = %s AND \
|
|
||||||
status = 1 \
|
|
||||||
ORDER BY sort_order ASC \
|
|
||||||
LIMIT "+str(limit), (sort_order, machine, mode, suite))
|
|
||||||
rows = c.fetchall()
|
|
||||||
return [Score(row[0]) for row in rows]
|
|
||||||
|
|
||||||
def prefetch_prev(self, limit = 1):
|
|
||||||
sort_order = self.get("build").get("run").get("sort_order")
|
|
||||||
machine = self.get("build").get("run").get("machine_id")
|
|
||||||
mode = self.get("build").get("mode_id")
|
|
||||||
suite = self.get("suite_version_id")
|
|
||||||
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT awfy_score.id \
|
|
||||||
FROM awfy_score \
|
|
||||||
INNER JOIN awfy_build ON awfy_build.id = awfy_score.build_id \
|
|
||||||
INNER JOIN awfy_run ON awfy_run.id = awfy_build.run_id \
|
|
||||||
WHERE sort_order < %s AND \
|
|
||||||
machine = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_version_id = %s AND \
|
|
||||||
status = 1 \
|
|
||||||
ORDER BY sort_order DESC \
|
|
||||||
LIMIT "+str(limit), (sort_order, machine, mode, suite))
|
|
||||||
rows = c.fetchall()
|
|
||||||
return [Score(row[0]) for row in rows]
|
|
||||||
|
|
||||||
def runs(self):
|
|
||||||
runs = max(1, self.get('build').get('run').get('machine').get("confidence_runs"))
|
|
||||||
runs *= self.get('suite_version').get('suite').get("confidence_factor")
|
|
||||||
runs *= RUNS_FACTOR
|
|
||||||
runs = int(round(runs))
|
|
||||||
return runs
|
|
||||||
|
|
||||||
def disabled(self):
|
|
||||||
return RegressionScoreNoise(self.get('build').get('run').get('machine'),
|
|
||||||
self.get('suite_version'),
|
|
||||||
self.get('build').get('mode')).get('disabled')
|
|
||||||
|
|
||||||
def noise(self):
|
|
||||||
noise = RegressionScoreNoise(self.get('build').get('run').get('machine'),
|
|
||||||
self.get('suite_version'),
|
|
||||||
self.get('build').get('mode')).get('noise')
|
|
||||||
return NOISE_FACTOR*noise
|
|
||||||
|
|
||||||
def hasNoise(self):
|
|
||||||
return RegressionScoreNoise(self.get('build').get('run').get('machine'),
|
|
||||||
self.get('suite_version'),
|
|
||||||
self.get('build').get('mode')).id != 0
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def firstOfRecent(class_, machine, suite, mode):
|
|
||||||
assert machine.__class__ == Machine
|
|
||||||
assert suite.__class__ == SuiteVersion
|
|
||||||
assert mode.__class__ == Mode
|
|
||||||
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id \
|
|
||||||
FROM (SELECT awfy_score.id, sort_order \
|
|
||||||
FROM awfy_score \
|
|
||||||
INNER JOIN awfy_build ON awfy_build.id = awfy_score.build_id \
|
|
||||||
INNER JOIN awfy_run ON awfy_run.id = awfy_build.run_id \
|
|
||||||
WHERE machine = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_version_id = %s AND \
|
|
||||||
status = 1 \
|
|
||||||
ORDER BY sort_order DESC \
|
|
||||||
LIMIT 1000) tmp \
|
|
||||||
ORDER BY sort_order ASC \
|
|
||||||
LIMIT 1", (machine.get("id"), mode.get("id"), suite.get("id")))
|
|
||||||
row = c.fetchone()
|
|
||||||
if row:
|
|
||||||
return Score(row[0])
|
|
||||||
return None
|
|
||||||
|
|
||||||
def dump(self):
|
|
||||||
import datetime
|
|
||||||
print datetime.datetime.fromtimestamp(
|
|
||||||
int(self.get("build").get("run").get("finish_stamp"))
|
|
||||||
).strftime('%Y-%m-%d %H:%M:%S'),
|
|
||||||
print "", self.get("build").get("run").get("machine").get("description"),
|
|
||||||
print "", self.get("build").get("mode").get("name"),
|
|
||||||
print "", self.get("suite_version").get("name")+":", self.avg_change(),
|
|
||||||
print "", self.prev().get("score") if self.prev() else "", self.get("score"),
|
|
||||||
print " ("+str(self.runs())+" runs, "+str(self.noise())+")"
|
|
||||||
|
|
||||||
class Breakdown(RegressionTools):
|
class Breakdown(RegressionTools):
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
RegressionTools.__init__(self, id)
|
RegressionTools.__init__(self, id)
|
||||||
|
@ -772,120 +275,3 @@ class Breakdown(RegressionTools):
|
||||||
return Score(self.get("score_id")).get("build")
|
return Score(self.get("score_id")).get("build")
|
||||||
|
|
||||||
return super(Breakdown, self).get(field)
|
return super(Breakdown, self).get(field)
|
||||||
|
|
||||||
def sane(self):
|
|
||||||
if self.get("suite_test_id") == 0:
|
|
||||||
return False
|
|
||||||
if self.get("suite_test_id") == -1:
|
|
||||||
return False
|
|
||||||
if self.get("suite_test").get("suite_version_id") == -1:
|
|
||||||
return False
|
|
||||||
if self.get("suite_test").get("suite_version_id") == 0:
|
|
||||||
return False
|
|
||||||
if not self.hasNoise():
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def prefetch_next(self, limit = 1):
|
|
||||||
sort_order = self.get("build").get("run").get("sort_order")
|
|
||||||
machine = self.get("build").get("run").get("machine_id")
|
|
||||||
mode = self.get("build").get("mode_id")
|
|
||||||
suite = self.get("suite_test_id")
|
|
||||||
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT awfy_breakdown.id \
|
|
||||||
FROM awfy_breakdown \
|
|
||||||
INNER JOIN awfy_score ON awfy_score.id = awfy_breakdown.score_id \
|
|
||||||
INNER JOIN awfy_build ON awfy_build.id = awfy_score.build_id \
|
|
||||||
INNER JOIN awfy_run ON awfy_run.id = awfy_build.run_id \
|
|
||||||
WHERE sort_order > %s AND \
|
|
||||||
machine = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_test_id = %s AND \
|
|
||||||
status = 1 \
|
|
||||||
ORDER BY sort_order ASC \
|
|
||||||
LIMIT "+str(limit), (sort_order, machine, mode, suite))
|
|
||||||
rows = c.fetchall()
|
|
||||||
return [Breakdown(row[0]) for row in rows]
|
|
||||||
|
|
||||||
def prefetch_prev(self, limit = 1):
|
|
||||||
sort_order = self.get("build").get("run").get("sort_order")
|
|
||||||
machine = self.get("build").get("run").get("machine_id")
|
|
||||||
mode = self.get("build").get("mode_id")
|
|
||||||
suite = self.get("suite_test_id")
|
|
||||||
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT awfy_breakdown.id \
|
|
||||||
FROM awfy_breakdown \
|
|
||||||
INNER JOIN awfy_score ON awfy_score.id = awfy_breakdown.score_id \
|
|
||||||
INNER JOIN awfy_build ON awfy_build.id = awfy_score.build_id \
|
|
||||||
INNER JOIN awfy_run ON awfy_run.id = awfy_build.run_id \
|
|
||||||
WHERE sort_order < %s AND \
|
|
||||||
machine = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_test_id = %s AND \
|
|
||||||
status = 1 \
|
|
||||||
ORDER BY sort_order DESC \
|
|
||||||
LIMIT "+str(limit), (sort_order, machine, mode, suite))
|
|
||||||
rows = c.fetchall()
|
|
||||||
return [Breakdown(row[0]) for row in rows]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def firstOfRecent(class_, machine, suite, mode):
|
|
||||||
assert machine.__class__ == Machine
|
|
||||||
assert suite.__class__ == SuiteTest
|
|
||||||
assert mode.__class__ == Mode
|
|
||||||
|
|
||||||
c = awfy.db.cursor()
|
|
||||||
c.execute("SELECT id \
|
|
||||||
FROM (SELECT awfy_breakdown.id, sort_order \
|
|
||||||
FROM awfy_breakdown \
|
|
||||||
INNER JOIN awfy_score ON awfy_score.id = awfy_breakdown.score_id \
|
|
||||||
INNER JOIN awfy_build ON awfy_build.id = awfy_score.build_id \
|
|
||||||
INNER JOIN awfy_run ON awfy_run.id = awfy_build.run_id \
|
|
||||||
WHERE machine = %s AND \
|
|
||||||
mode_id = %s AND \
|
|
||||||
suite_test_id = %s AND \
|
|
||||||
status = 1 \
|
|
||||||
ORDER BY sort_order DESC \
|
|
||||||
LIMIT 1000) tmp \
|
|
||||||
ORDER BY sort_order ASC \
|
|
||||||
LIMIT 1", (machine.get("id"), mode.get("id"), suite.get("id")))
|
|
||||||
row = c.fetchone()
|
|
||||||
if row:
|
|
||||||
return Breakdown(row[0])
|
|
||||||
return None
|
|
||||||
|
|
||||||
def runs(self):
|
|
||||||
runs = max(1, self.get('build').get('run').get('machine').get("confidence_runs"))
|
|
||||||
runs *= self.get('suite_test').get("confidence_factor")
|
|
||||||
runs *= RUNS_FACTOR
|
|
||||||
runs = int(round(runs))
|
|
||||||
return runs
|
|
||||||
|
|
||||||
def disabled(self):
|
|
||||||
return RegressionBreakdownNoise(self.get('build').get('run').get('machine'),
|
|
||||||
self.get('suite_test'),
|
|
||||||
self.get('build').get('mode')).get('disabled')
|
|
||||||
|
|
||||||
def noise(self):
|
|
||||||
noise = RegressionBreakdownNoise(self.get('build').get('run').get('machine'),
|
|
||||||
self.get('suite_test'),
|
|
||||||
self.get('build').get('mode')).get('noise')
|
|
||||||
return NOISE_FACTOR*noise
|
|
||||||
|
|
||||||
def hasNoise(self):
|
|
||||||
return RegressionBreakdownNoise(self.get('build').get('run').get('machine'),
|
|
||||||
self.get('suite_test'),
|
|
||||||
self.get('build').get('mode')).id != 0
|
|
||||||
|
|
||||||
def dump(self):
|
|
||||||
import datetime
|
|
||||||
print datetime.datetime.fromtimestamp(
|
|
||||||
int(self.get("build").get("run").get("finish_stamp"))
|
|
||||||
).strftime('%Y-%m-%d %H:%M:%S'),
|
|
||||||
print "", self.get("build").get("run").get("machine").get("description"),
|
|
||||||
print "", self.get("build").get("mode").get("name"),
|
|
||||||
print "", self.get("suite_test").get("suite_version").get("name")+":", self.get("suite_test").get("name")+":", self.avg_change(),
|
|
||||||
print "", self.prev().get("score") if self.prev() else "", self.get("score"),
|
|
||||||
print " ("+str(self.runs())+" runs, "+str(self.noise())+", "+str(self.change())+")"
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче