/** Compute the test timing as a weighted average of the previous test. * Also compute the difference in errors and tests between builds. * We do that in one shot for speed reasons. */ function ComputeTestTiming() { if (!$this->Id) { add_log("BuildId is not set", "Build::ComputeTestTiming", LOG_ERR, $this->ProjectId, $this->Id, CDASH_OBJECT_BUILD, $this->Id); return false; } if (!$this->ProjectId) { add_log("ProjectId is not set", "Build::ComputeTestTiming", LOG_ERR, $this->ProjectId, $this->Id, CDASH_OBJECT_BUILD, $this->Id); return false; } $testtimestatusfailed = 0; // TEST TIMING $weight = 0.3; // weight of the current test compared to the previous mean/std (this defines a window) $build = pdo_query("SELECT projectid,starttime,siteid,name,type FROM build WHERE id=" . qnum($this->Id)); add_last_sql_error("Build:ComputeTestTiming", $this->ProjectId, $this->Id); $buildid = $this->Id; $build_array = pdo_fetch_array($build); $buildname = $build_array["name"]; $buildtype = $build_array["type"]; $starttime = $build_array["starttime"]; $siteid = $build_array["siteid"]; $projectid = $build_array["projectid"]; $project = pdo_query("SELECT testtimestd,testtimestdthreshold,testtimemaxstatus FROM project WHERE id=" . qnum($this->ProjectId)); add_last_sql_error("Build:ComputeTestTiming", $this->ProjectId, $this->Id); $project_array = pdo_fetch_array($project); $projecttimestd = $project_array["testtimestd"]; $projecttimestdthreshold = $project_array["testtimestdthreshold"]; $projecttestmaxstatus = $project_array["testtimemaxstatus"]; // Find the previous build $previousbuildid = $this->GetPreviousBuildId(); if ($previousbuildid == 0) { return; } // If we have one if ($previousbuildid > 0) { compute_test_difference($buildid, $previousbuildid, 0, $projecttestmaxstatus); // not run compute_test_difference($buildid, $previousbuildid, 1, $projecttestmaxstatus); // fail compute_test_difference($buildid, $previousbuildid, 2, $projecttestmaxstatus); // pass compute_test_difference($buildid, $previousbuildid, 3, $projecttestmaxstatus); // time // Loop through the tests $tests = pdo_query("SELECT build2test.time,build2test.testid,test.name,build2test.status,\n build2test.timestatus\n FROM build2test,test WHERE build2test.buildid=" . qnum($this->Id) . "\n AND build2test.testid=test.id\n "); add_last_sql_error("Build:ComputeTestTiming", $this->ProjectId, $this->Id); // Find the previous test $previoustest = pdo_query("SELECT build2test.testid,test.name FROM build2test,test\n WHERE build2test.buildid=" . qnum($previousbuildid) . "\n AND test.id=build2test.testid\n "); add_last_sql_error("Build:ComputeTestTiming", $this->ProjectId, $this->Id); $testarray = array(); while ($test_array = pdo_fetch_array($previoustest)) { $test = array(); $test['id'] = $test_array["testid"]; $test['name'] = $test_array["name"]; $testarray[] = $test; } while ($test_array = pdo_fetch_array($tests)) { $testtime = $test_array['time']; $testid = $test_array['testid']; $teststatus = $test_array['status']; $testname = $test_array['name']; $previoustestid = 0; $timestatus = $test_array['timestatus']; foreach ($testarray as $test) { if ($test['name'] == $testname) { $previoustestid = $test['id']; break; } } if ($previoustestid > 0) { $previoustest = pdo_query("SELECT timemean,timestd,timestatus FROM build2test\n WHERE buildid=" . qnum($previousbuildid) . "\n AND build2test.testid=" . qnum($previoustestid)); add_last_sql_error("Build:ComputeTestTiming", $this->ProjectId, $this->Id); $previoustest_array = pdo_fetch_array($previoustest); $previoustimemean = $previoustest_array["timemean"]; $previoustimestd = $previoustest_array["timestd"]; $previoustimestatus = $previoustest_array["timestatus"]; if ($teststatus == "passed") { if ($timestatus > 0 && $timestatus <= $projecttestmaxstatus) { $timemean = $previoustimemean; $timestd = $previoustimestd; } else { // Update the mean and std $timemean = (1 - $weight) * $previoustimemean + $weight * $testtime; $timestd = sqrt((1 - $weight) * $previoustimestd * $previoustimestd + $weight * ($testtime - $timemean) * ($testtime - $timemean)); } // Check the current status if ($previoustimestd < $projecttimestdthreshold) { $previoustimestd = $projecttimestdthreshold; } if ($testtime > $previoustimemean + $projecttimestd * $previoustimestd) { $timestatus = $previoustimestatus + 1; // flag } else { $timestatus = 0; // reset the time status to 0 } } else { $timemean = $previoustimemean; $timestd = $previoustimestd; $timestatus = 0; } } else { $timestd = 0; $timestatus = 0; $timemean = $testtime; } pdo_query("UPDATE build2test SET timemean=" . qnum($timemean) . ",timestd=" . qnum($timestd) . ",timestatus=" . qnum($timestatus) . "\n WHERE buildid=" . qnum($this->Id) . " AND testid=" . qnum($testid)); add_last_sql_error("Build:ComputeTestTiming", $this->ProjectId, $this->Id); if ($timestatus >= $projecttestmaxstatus) { $testtimestatusfailed++; } } // end loop through the test } else { $timestd = 0; $timestatus = 0; // Loop throught the tests $tests = pdo_query("SELECT time,testid FROM build2test WHERE buildid=" . qnum($this->Id)); while ($test_array = pdo_fetch_array($tests)) { $timemean = $test_array['time']; $testid = $test_array['testid']; pdo_query("UPDATE build2test SET timemean=" . qnum($timemean) . ",timestd=" . qnum($timestd) . ",timestatus=" . qnum($timestatus) . "\n WHERE buildid=" . qnum($this->Id) . " AND testid=" . qnum($testid)); add_last_sql_error("Build:ComputeTestTiming", $this->ProjectId, $this->Id); if ($timestatus >= $projecttestmaxstatus) { $testtimestatusfailed++; } } // loop through the tests } // end if first build pdo_query("UPDATE build SET testtimestatusfailed=" . qnum($testtimestatusfailed) . " WHERE id=" . $this->Id); add_last_sql_error("Build:ComputeTestTiming", $this->ProjectId, $this->Id); return true; }
/** Compute the test timing as a weighted average of the previous test. * Also compute the difference in errors and tests between builds. * We do that in one shot for speed reasons. */ public function ComputeTestTiming() { if (!$this->Id) { add_log('BuildId is not set', 'Build::ComputeTestTiming', LOG_ERR, $this->ProjectId, $this->Id, CDASH_OBJECT_BUILD, $this->Id); return false; } if (!$this->ProjectId) { add_log('ProjectId is not set', 'Build::ComputeTestTiming', LOG_ERR, $this->ProjectId, $this->Id, CDASH_OBJECT_BUILD, $this->Id); return false; } $testtimestatusfailed = 0; // TEST TIMING $weight = 0.3; // weight of the current test compared to the previous mean/std (this defines a window) $build = pdo_query('SELECT projectid,starttime,siteid,name,type FROM build WHERE id=' . qnum($this->Id)); add_last_sql_error('Build:ComputeTestTiming', $this->ProjectId, $this->Id); $buildid = $this->Id; $build_array = pdo_fetch_array($build); $buildname = $build_array['name']; $buildtype = $build_array['type']; $starttime = $build_array['starttime']; $siteid = $build_array['siteid']; $projectid = $build_array['projectid']; $project = pdo_query('SELECT testtimestd,testtimestdthreshold,testtimemaxstatus FROM project WHERE id=' . qnum($this->ProjectId)); add_last_sql_error('Build:ComputeTestTiming', $this->ProjectId, $this->Id); $project_array = pdo_fetch_array($project); $projecttimestd = $project_array['testtimestd']; $projecttimestdthreshold = $project_array['testtimestdthreshold']; $projecttestmaxstatus = $project_array['testtimemaxstatus']; // Find the previous build $previousbuildid = $this->GetPreviousBuildId(); if ($previousbuildid == 0) { return; } // If we have one if ($previousbuildid > 0) { compute_test_difference($buildid, $previousbuildid, 0, $projecttestmaxstatus); // not run compute_test_difference($buildid, $previousbuildid, 1, $projecttestmaxstatus); // fail compute_test_difference($buildid, $previousbuildid, 2, $projecttestmaxstatus); // pass compute_test_difference($buildid, $previousbuildid, 3, $projecttestmaxstatus); // time // Loop through the tests $tests = pdo_query('SELECT build2test.time,build2test.testid,test.name,build2test.status, build2test.timestatus FROM build2test,test WHERE build2test.buildid=' . qnum($this->Id) . ' AND build2test.testid=test.id '); add_last_sql_error('Build:ComputeTestTiming', $this->ProjectId, $this->Id); // Find the previous test $previoustest = pdo_query('SELECT build2test.testid,test.name FROM build2test,test WHERE build2test.buildid=' . qnum($previousbuildid) . ' AND test.id=build2test.testid '); add_last_sql_error('Build:ComputeTestTiming', $this->ProjectId, $this->Id); $testarray = array(); while ($test_array = pdo_fetch_array($previoustest)) { $test = array(); $test['id'] = $test_array['testid']; $test['name'] = $test_array['name']; $testarray[] = $test; } while ($test_array = pdo_fetch_array($tests)) { $testtime = $test_array['time']; $testid = $test_array['testid']; $teststatus = $test_array['status']; $testname = $test_array['name']; $previoustestid = 0; $timestatus = $test_array['timestatus']; foreach ($testarray as $test) { if ($test['name'] == $testname) { $previoustestid = $test['id']; break; } } if ($previoustestid > 0) { $previoustest = pdo_query('SELECT timemean,timestd,timestatus FROM build2test WHERE buildid=' . qnum($previousbuildid) . ' AND build2test.testid=' . qnum($previoustestid)); add_last_sql_error('Build:ComputeTestTiming', $this->ProjectId, $this->Id); $previoustest_array = pdo_fetch_array($previoustest); $previoustimemean = $previoustest_array['timemean']; $previoustimestd = $previoustest_array['timestd']; $previoustimestatus = $previoustest_array['timestatus']; if ($teststatus == 'passed') { // if the current test passed // Check the current status if ($previoustimestd < $projecttimestdthreshold) { $previoustimestd = $projecttimestdthreshold; } if ($testtime > $previoustimemean + $projecttimestd * $previoustimestd) { // only do positive std $timestatus = $previoustimestatus + 1; // flag } else { $timestatus = 0; // reset the time status to 0 } if ($timestatus > 0 && $timestatus <= $projecttestmaxstatus) { // if we are currently detecting the time changed we should use previous mean std $timemean = $previoustimemean; $timestd = $previoustimestd; } else { // Update the mean and std $timemean = (1 - $weight) * $previoustimemean + $weight * $testtime; $timestd = sqrt((1 - $weight) * $previoustimestd * $previoustimestd + $weight * ($testtime - $timemean) * ($testtime - $timemean)); } } else { // the test failed so we just replicate the previous test time $timemean = $previoustimemean; $timestd = $previoustimestd; $timestatus = 0; } } else { // the test doesn't exist $timestd = 0; $timestatus = 0; $timemean = $testtime; } pdo_query('UPDATE build2test SET timemean=' . qnum($timemean) . ',timestd=' . qnum($timestd) . ',timestatus=' . qnum($timestatus) . ' WHERE buildid=' . qnum($this->Id) . ' AND testid=' . qnum($testid)); add_last_sql_error('Build:ComputeTestTiming', $this->ProjectId, $this->Id); if ($timestatus >= $projecttestmaxstatus) { $testtimestatusfailed++; } } } else { // this is the first build $timestd = 0; $timestatus = 0; // Loop throught the tests $tests = pdo_query('SELECT time,testid FROM build2test WHERE buildid=' . qnum($this->Id)); while ($test_array = pdo_fetch_array($tests)) { $timemean = $test_array['time']; $testid = $test_array['testid']; pdo_query('UPDATE build2test SET timemean=' . qnum($timemean) . ',timestd=' . qnum($timestd) . ',timestatus=' . qnum($timestatus) . ' WHERE buildid=' . qnum($this->Id) . ' AND testid=' . qnum($testid)); add_last_sql_error('Build:ComputeTestTiming', $this->ProjectId, $this->Id); if ($timestatus >= $projecttestmaxstatus) { $testtimestatusfailed++; } } // loop through the tests } pdo_query('UPDATE build SET testtimestatusfailed=' . qnum($testtimestatusfailed) . ' WHERE id=' . $this->Id); add_last_sql_error('Build:ComputeTestTiming', $this->ProjectId, $this->Id); return true; }