diff --git a/app/Console/Commands/CleanDatabase.php b/app/Console/Commands/CleanDatabase.php
new file mode 100644
index 0000000000..8fe0bbf3d2
--- /dev/null
+++ b/app/Console/Commands/CleanDatabase.php
@@ -0,0 +1,51 @@
+ 'stderr']);
+
+ Log::info("Deleting unused rows from `banner`");
+ $num_deleted = DB::delete("DELETE FROM banner WHERE projectid != 0 AND
+ NOT EXISTS (SELECT 1 FROM project WHERE project.id = banner.projectid)");
+ Log::info("{$num_deleted} rows deleted from `banner`");
+
+ DatabaseCleanupUtils::deleteUnusedRows('dailyupdate', 'projectid', 'project');
+
+ DatabaseCleanupUtils::deleteUnusedRows('buildfailuredetails', 'id', 'buildfailure', 'detailsid');
+ DatabaseCleanupUtils::deleteUnusedRows('configure', 'id', 'build2configure', 'configureid');
+ DatabaseCleanupUtils::deleteUnusedRows('coveragefile', 'id', 'coverage', 'fileid');
+ DatabaseCleanupUtils::deleteUnusedRows('dailyupdatefile', 'dailyupdateid', 'dailyupdate');
+ DatabaseCleanupUtils::deleteUnusedRows('note', 'id', 'build2note', 'noteid');
+ DatabaseCleanupUtils::deleteUnusedRows('testoutput', 'id', 'build2test', 'outputid');
+ DatabaseCleanupUtils::deleteUnusedRows('uploadfile', 'id', 'build2uploadfile', 'fileid');
+
+ Log::info("Deleting unused rows from `image`");
+ $num_deleted = DB::delete("DELETE FROM image WHERE
+ NOT EXISTS (SELECT 1 FROM project WHERE project.imageid = image.id) AND
+ NOT EXISTS (SELECT 1 FROM test2image WHERE test2image.imgid = image.id)");
+ Log::info("{$num_deleted} rows deleted from `image`");
+ }
+}
diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php
index 337e816dd1..4dc163e556 100644
--- a/app/Http/Controllers/AdminController.php
+++ b/app/Http/Controllers/AdminController.php
@@ -331,7 +331,6 @@ public function upgrade()
@$ComputeTestTiming = $_POST['ComputeTestTiming'];
@$ComputeUpdateStatistics = $_POST['ComputeUpdateStatistics'];
- @$Cleanup = $_POST['Cleanup'];
@$Dependencies = $_POST['Dependencies'];
@$Audit = $_POST['Audit'];
@$ClearAudit = $_POST['Clear'];
@@ -377,55 +376,6 @@ public function upgrade()
unlink($configFile);
}
-
- /* Cleanup the database */
- if ($Cleanup) {
- self::delete_unused_rows('banner', 'projectid', 'project');
- self::delete_unused_rows('blockbuild', 'projectid', 'project');
- self::delete_unused_rows('build', 'projectid', 'project');
- self::delete_unused_rows('buildgroup', 'projectid', 'project');
- self::delete_unused_rows('labelemail', 'projectid', 'project');
- self::delete_unused_rows('project2repositories', 'projectid', 'project');
- self::delete_unused_rows('dailyupdate', 'projectid', 'project');
- self::delete_unused_rows('subproject', 'projectid', 'project');
- self::delete_unused_rows('coveragefilepriority', 'projectid', 'project');
- self::delete_unused_rows('user2project', 'projectid', 'project');
- self::delete_unused_rows('userstatistics', 'projectid', 'project');
-
- self::delete_unused_rows('build2configure', 'buildid', 'build');
- self::delete_unused_rows('build2note', 'buildid', 'build');
- self::delete_unused_rows('build2test', 'buildid', 'build');
- self::delete_unused_rows('buildemail', 'buildid', 'build');
- self::delete_unused_rows('builderror', 'buildid', 'build');
- self::delete_unused_rows('builderrordiff', 'buildid', 'build');
- self::delete_unused_rows('buildfailure', 'buildid', 'build');
- self::delete_unused_rows('buildfailuredetails', 'id', 'buildfailure', 'detailsid');
- self::delete_unused_rows('buildtesttime', 'buildid', 'build');
- self::delete_unused_rows('configure', 'id', 'build2configure', 'configureid');
- self::delete_unused_rows('configureerror', 'configureid', 'configure');
- self::delete_unused_rows('configureerrordiff', 'buildid', 'build');
- self::delete_unused_rows('coverage', 'buildid', 'build');
- self::delete_unused_rows('coveragefilelog', 'buildid', 'build');
- self::delete_unused_rows('coveragesummary', 'buildid', 'build');
- self::delete_unused_rows('coveragesummarydiff', 'buildid', 'build');
- self::delete_unused_rows('dynamicanalysis', 'buildid', 'build');
- self::delete_unused_rows('label2build', 'buildid', 'build');
- self::delete_unused_rows('subproject2build', 'buildid', 'build');
- self::delete_unused_rows('summaryemail', 'buildid', 'build');
- self::delete_unused_rows('testdiff', 'buildid', 'build');
-
- self::delete_unused_rows('dynamicanalysisdefect', 'dynamicanalysisid', 'dynamicanalysis');
- self::delete_unused_rows('subproject2subproject', 'subprojectid', 'subproject');
-
- self::delete_unused_rows('dailyupdatefile', 'dailyupdateid', 'dailyupdate');
- self::delete_unused_rows('coveragefile', 'id', 'coverage', 'fileid');
-
- self::delete_unused_rows('dailyupdatefile', 'dailyupdateid', 'dailyupdate');
- self::delete_unused_rows('test2image', 'outputid', 'testoutput');
-
- $xml .= add_XML_value('alert', 'Database cleanup complete.');
- }
-
/* Check the builds with wrong date */
if ($CheckBuildsWrongDate) {
$currentdate = time() + 3600 * 24 * 3; // or 3 days away from now
@@ -506,11 +456,4 @@ public function userStatistics(): View
{
return $this->angular_view('userStatistics');
}
-
- /** Delete unused rows */
- private static function delete_unused_rows($table, $field, $targettable, $selectfield = 'id'): void
- {
- DB::delete("DELETE FROM $table WHERE $field NOT IN (SELECT $selectfield AS $field FROM $targettable)");
- echo pdo_error();
- }
}
diff --git a/app/Utils/DatabaseCleanupUtils.php b/app/Utils/DatabaseCleanupUtils.php
index b12dc4d936..615d69ac7e 100644
--- a/app/Utils/DatabaseCleanupUtils.php
+++ b/app/Utils/DatabaseCleanupUtils.php
@@ -266,8 +266,6 @@ public static function removeBuild($buildid) : void
// Use array_diff to get the list of tests that should be deleted.
$testoutputs_to_delete = array_diff($all_outputids, $testoutputs_to_save);
if (!empty($testoutputs_to_delete)) {
- self::deleteRowsChunked('DELETE FROM testoutput WHERE id IN ', $testoutputs_to_delete);
-
$testoutputs_to_delete_prepare_array = $db->createPreparedArray(count($testoutputs_to_delete));
// Check if the images for the test are not shared
$test2image = DB::select("
@@ -291,6 +289,8 @@ public static function removeBuild($buildid) : void
$imgids_prepare_array = $db->createPreparedArray(count($imgids));
DB::delete("DELETE FROM image WHERE id IN $imgids_prepare_array", $imgids);
}
+
+ self::deleteRowsChunked('DELETE FROM testoutput WHERE id IN ', $testoutputs_to_delete);
}
}
@@ -366,4 +366,50 @@ private static function deleteRowsChunked(string $query, array $ids): void
usleep(1);
}
}
+
+ /** Delete unused rows in batches */
+ public static function deleteUnusedRows(string $table, string $field, string $targettable, string $selectfield = 'id'): void
+ {
+ $start = DB::table($table)->min($field);
+ $max = DB::table($table)->max($field);
+ if (!is_numeric($start) || !is_numeric($max)) {
+ Log::info("Could not determine min and max for `{$field}` on `{$table}`");
+ return;
+ }
+
+ $start = intval($start);
+ $max = intval($max);
+ $total = $max - $start + 1;
+ if ($total < 1) {
+ Log::info("Invalid values found for min ({$start}) and/or max ({$max}) for `{$field}` on `{$table}`");
+ return;
+ }
+ $num_done = 0;
+ $num_deleted = 0;
+ $next_report = 10;
+ $done = false;
+ Log::info("Deleting unused rows from `{$table}`");
+ while (!$done) {
+ $end = $start + 49999;
+ $num_deleted += DB::delete("
+ DELETE FROM {$table}
+ WHERE {$field} BETWEEN {$start} AND {$end}
+ AND NOT EXISTS
+ (SELECT 1 FROM {$targettable} WHERE {$targettable}.{$selectfield} = {$table}.{$field})");
+ $num_done += 50000;
+ if ($end >= $max) {
+ $done = true;
+ } else {
+ usleep(1);
+ $start += 50000;
+ // Calculate percentage of work completed so far.
+ $percent = round(($num_done / $total) * 100, -1);
+ if ($percent > $next_report) {
+ Log::info("Cleaning `{$table}`: {$next_report}%");
+ $next_report = $next_report + 10;
+ }
+ }
+ }
+ Log::info("{$num_deleted} rows deleted from `{$table}`");
+ }
}
diff --git a/app/cdash/public/upgrade.xsl b/app/cdash/public/upgrade.xsl
index 6142c3acf9..993ea88e5f 100644
--- a/app/cdash/public/upgrade.xsl
+++ b/app/cdash/public/upgrade.xsl
@@ -30,10 +30,6 @@
Manage CDash dependencies: |
diff --git a/app/cdash/tests/test_removebuilds.php b/app/cdash/tests/test_removebuilds.php
index 314b022932..bb14f3b351 100644
--- a/app/cdash/tests/test_removebuilds.php
+++ b/app/cdash/tests/test_removebuilds.php
@@ -27,6 +27,7 @@
use CDash\Model\Image;
use CDash\Model\Label;
use CDash\Model\UploadFile;
+use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
class RemoveBuildsTestCase extends KWWebTestCase
@@ -36,19 +37,17 @@ public function __construct()
parent::__construct();
}
- public function testRemoveBuilds()
+ public function testRemoveBuilds(): void
{
$this->login();
$this->get($this->url . '/removeBuilds.php?projectid=5');
$this->clickSubmitByName('Submit');
if (strpos($this->getBrowser()->getContentAsText(), 'Removed') === false) {
$this->fail("'Removed' not found when expected");
- return 1;
}
- $this->pass('Passed');
}
- public function testBuildRemovalWorksAsExpected()
+ public function testBuildRemovalWorksAsExpected(): void
{
$time = gmdate(FMT_DATETIME);
@@ -272,7 +271,7 @@ public function testBuildRemovalWorksAsExpected()
$measurement = new TestMeasurement();
$measurement->name = 'Exit Value';
$measurement->type = 'text/string';
- $measurement->value = 5;
+ $measurement->value = '5';
$test_creator->measurements->push($measurement);
$image = new Image();
@@ -301,7 +300,7 @@ public function testBuildRemovalWorksAsExpected()
$measurement2 = new TestMeasurement();
$measurement2->name = 'Exit Value';
$measurement2->type = 'text/string';
- $measurement2->value = 0;
+ $measurement2->value = '0';
$test_creator2->measurements->push($measurement2);
$image2 = new Image();
@@ -340,32 +339,130 @@ public function testBuildRemovalWorksAsExpected()
// Various tables that are too hard to spoof with models so we resort
// to direct insertion.
- pdo_query(
- "INSERT INTO buildemail (userid, buildid, category)
- VALUES (1, $build->Id, 0)");
- pdo_query(
- "INSERT INTO builderrordiff
- (buildid, type, difference_positive, difference_negative)
- VALUES ($build->Id, 0, 1, 1)");
- pdo_query(
- "INSERT INTO configureerrordiff (buildid, type, difference)
- VALUES ($build->Id, 0, 1)");
- pdo_query(
- "INSERT INTO coveragesummarydiff (buildid, loctested, locuntested)
- VALUES ($build->Id, 1, 1)");
- pdo_query(
- "INSERT INTO summaryemail (buildid, date, groupid)
- VALUES ($build->Id, '$time', 1)");
- pdo_query(
- "INSERT INTO subproject2build (subprojectid, buildid)
- VALUES (1, $build->Id)");
- pdo_query(
- "INSERT INTO testdiff
- (buildid, type, difference_positive, difference_negative)
- VALUES ($build->Id, 0, 1, 1)");
-
-
- // Check that everything was created successfully.
+ DB::table('buildemail')->insert([
+ 'userid' => 1,
+ 'buildid' => $build->Id,
+ 'category' => 0,
+ ]);
+ DB::table('builderrordiff')->insert([
+ 'buildid' => $build->Id,
+ 'type' => 0,
+ 'difference_positive' => 1,
+ 'difference_negative' => 1,
+ ]);
+ DB::table('configureerrordiff')->insert([
+ 'buildid' => $build->Id,
+ 'type' => 0,
+ 'difference' => 1,
+ ]);
+ DB::table('coveragesummarydiff')->insert([
+ 'buildid' => $build->Id,
+ 'loctested' => 1,
+ 'locuntested' => 1,
+ ]);
+ DB::table('summaryemail')->insert([
+ 'buildid' => $build->Id,
+ 'date' => $time,
+ 'groupid' => 1,
+ ]);
+ DB::table('subproject2build')->insert([
+ 'subprojectid' => 1,
+ 'buildid' => $build->Id,
+ ]);
+ DB::table('testdiff')->insert([
+ 'buildid' => $build->Id,
+ 'type' => 0,
+ 'difference_positive' => 1,
+ 'difference_negative' => 1,
+ ]);
+
+ // Insert some unused records to make sure they get properly pruned by db:clean
+ // without impacting the data created above.
+ $crc32 = crc32('');
+ DB::table('banner')->insert([
+ 'projectid' => 999,
+ 'text' => 'created by test_removebuilds',
+ ]);
+ $buildfailuredetails_id = DB::table('buildfailuredetails')->insertGetId([
+ 'type' => 0,
+ 'stdoutput' => '',
+ 'stderror' => '',
+ 'exitcondition' => 'normal',
+ 'language' => 'PHP',
+ 'targetname' => 'test_removebuilds',
+ 'outputfile' => 'test_removebuilds',
+ 'outputtype' => 'test',
+ 'crc32' => $crc32,
+ ]);
+ $configure_id = DB::table('configure')->insertGetId([
+ 'command' => 'test_removebuilds',
+ 'log' => 'created by test_removebuilds',
+ 'status' => 0,
+ 'warnings' => 0,
+ 'crc32' => $crc32,
+ ]);
+ $coveragefile_id = DB::table('coveragefile')->insertGetId([
+ 'fullpath' => 'tests/test_removebuild.php',
+ 'file' => 'asdf',
+ 'crc32' => $crc32,
+ ]);
+ $dailyupdate_id = DB::table('dailyupdate')->insertGetId([
+ 'projectid' => 999,
+ 'date' => $time,
+ 'command' => 'created by test_removebuilds',
+ 'type' => 'ok',
+ 'status' => 0,
+ 'revision' => 'DEADBEEF',
+ ]);
+ DB::table('dailyupdatefile')->insert([
+ 'dailyupdateid' => $dailyupdate_id,
+ 'filename' => 'test_removebuilds.php',
+ 'checkindate' => $time,
+ 'author' => 'CDash',
+ 'email' => 'admin@cdash.org',
+ 'log' => 'test_removebuilds.php',
+ 'revision' => 'DEADBEEF',
+ 'priorrevision' => '00000000',
+ ]);
+ $image_id = DB::table('image')->insertGetId([
+ 'img' => 'asdf',
+ 'extension' => 'png',
+ 'checksum' => 0,
+ ]);
+ $note_id = DB::table('note')->insertGetId([
+ 'text' => 'note for test_removebuildds',
+ 'name' => 'test_removebuilds.log',
+ 'crc32' => $crc32,
+ ]);
+ $testoutput_id = DB::table('testoutput')->insertGetId([
+ 'output' => 'testoutput for test_removebuildds',
+ 'command' => 'php test_removebuilds.php',
+ 'path' => '/cdash/tests/test_removebuilds.php',
+ 'crc32' => $crc32,
+ ]);
+ $uploadfile_id = DB::table('uploadfile')->insertGetId([
+ 'filename' => 'test_removebuilds.php',
+ 'filesize' => 0,
+ 'sha1sum' => '00000000',
+ 'isurl' => 0,
+ ]);
+
+ // Verify that db:clean works as expected.
+ Artisan::call('db:clean');
+ $extra_msg = 'after db:clean';
+ $this->verify('banner', 'projectid', '=', 999, 0, $extra_msg);
+ $this->verify('buildfailuredetails', 'id', '=', $buildfailuredetails_id, 0, $extra_msg);
+ $this->verify('configure', 'id', '=', $configure_id, 0, $extra_msg);
+ $this->verify('coveragefile', 'id', '=', $coveragefile_id, 0, $extra_msg);
+ $this->verify('dailyupdate', 'id', '=', $dailyupdate_id, 0, $extra_msg);
+ $this->verify('dailyupdatefile', 'dailyupdateid', '=', $dailyupdate_id, 0, $extra_msg);
+ $this->verify('image', 'id', '=', $image_id, 0, $extra_msg);
+ $this->verify('note', 'id', '=', $note_id, 0, $extra_msg);
+ $this->verify('testoutput', 'id', '=', $testoutput_id, 0, $extra_msg);
+ $this->verify('uploadfile', 'id', '=', $uploadfile_id, 0, $extra_msg);
+
+ // Verify that our build-related data was created successfully
+ // and not accidentally removed by db:clean.
$this->verify('build', 'id', '=', $build->Id, 1);
$this->verify('build2group', 'buildid', '=', $build->Id, 1);
$this->verify('buildemail', 'buildid', '=', $build->Id, 1);
@@ -426,68 +523,110 @@ public function testBuildRemovalWorksAsExpected()
$this->verify('label2dynamicanalysis', 'labelid', '=', $labelid, 1);
$this->verify('label2test', 'labelid', '=', $labelid, 3);
- echo "Check on labelid = $labelid\n";
- return;
-
// Remove the build.
DatabaseCleanupUtils::removeBuild($build->Id);
- // Check that everything was deleted properly.
- $this->verify('build', 'id', '=', $build->Id, 0, true);
- $this->verify('build2configure', 'buildid', '=', $build->Id, 0, true);
- $this->verify('build2configure', 'buildid', '=', $existing_build->Id, 1, true);
- $this->verify('build2group', 'buildid', '=', $build->Id, 0, true);
- $this->verify('build2note', 'buildid', '=', $build->Id, 0, true);
- $this->verify('build2test', 'buildid', '=', $build->Id, 0, true);
- $this->verify('build2update', 'buildid', '=', $build->Id, 0, true);
- $this->verify('build2uploadfile', 'buildid', '=', $build->Id, 0, true);
- $this->verify('buildemail', 'buildid', '=', $build->Id, 0, true);
- $this->verify('builderror', 'buildid', '=', $build->Id, 0, true);
- $this->verify('builderrordiff', 'buildid', '=', $build->Id, 0, true);
- $this->verify('buildfailure', 'buildid', '=', $build->Id, 0, true);
- $this->verify('buildfailure2argument', 'buildfailureid', '=', $buildfailureid, 0, true);
- $this->verify('buildfailuredetails', 'id', '=', $detailsid, 1, true);
- $this->verify('buildtesttime', 'buildid', '=', $build->Id, 0, true);
- $this->verify('buildupdate', 'id', '=', $updateid, 1, true);
- $this->verify('configure', 'id', '=', $configureid, 1, true);
- $this->verify('configureerror', 'configureid', '=', $configureid, 1, true);
- $this->verify('configureerrordiff', 'buildid', '=', $build->Id, 0, true);
- $this->verify('coverage', 'buildid', '=', $build->Id, 0, true);
- $this->verify('coveragefile', 'id', 'IN', $coveragefileids, 1, true);
- $this->verify('coveragefilelog', 'buildid', '=', $build->Id, 0, true);
- $this->verify('coveragesummary', 'buildid', '=', $build->Id, 0, true);
- $this->verify('coveragesummarydiff', 'buildid', '=', $build->Id, 0, true);
- $this->verify('dynamicanalysis', 'buildid', '=', $build->Id, 0, true);
- $this->verify('dynamicanalysissummary', 'buildid', '=', $build->Id, 0, true);
- $this->verify('dynamicanalysisdefect', 'dynamicanalysisid', '=', $dynamicanalysisid, 0, true);
- $this->verify('image', 'id', 'IN', $imgids, 1, true);
- $this->verify('label2build', 'buildid', '=', $build->Id, 0, true);
- $this->verify('label2buildfailure', 'labelid', '=', $labelid, 1, true);
- $this->verify('label2coveragefile', 'labelid', '=', $labelid, 1, true);
- $this->verify('label2dynamicanalysis', 'labelid', '=', $labelid, 0, true);
- $this->verify('label2test', 'labelid', '=', $labelid, 0, true);
- $this->verify('note', 'id', 'IN', $noteids, 1, true);
- $this->verify('summaryemail', 'buildid', '=', $build->Id, 0, true);
- $this->verify('subproject2build', 'buildid', '=', $build->Id, 0, true);
- $this->verify('test2image', 'outputid', 'IN', $outputids, 1, true);
- $this->verify('testdiff', 'buildid', '=', $build->Id, 0, true);
- $this->verify('updatefile', 'updateid', '=', $updateid, 1, true);
- $this->verify('uploadfile', 'id', 'IN', $uploadfileids, 1, true);
+ // Check that everything was deleted properly but shared records remain.
+ $extra_msg = 'after 1st delete';
+ $this->verify('build', 'id', '=', $build->Id, 0, $extra_msg);
+ $this->verify('build2configure', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('build2configure', 'buildid', '=', $existing_build->Id, 1, $extra_msg);
+ $this->verify('build2group', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('build2note', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('build2test', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('build2update', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('build2uploadfile', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('buildemail', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('builderror', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('builderrordiff', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('buildfailure', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('buildfailure2argument', 'buildfailureid', '=', $buildfailureid, 0, $extra_msg);
+ $this->verify('buildfailuredetails', 'id', '=', $detailsid, 1, $extra_msg);
+ $this->verify('buildtesttime', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('buildupdate', 'id', '=', $updateid, 1, $extra_msg);
+ $this->verify('configure', 'id', '=', $configureid, 1, $extra_msg);
+ $this->verify('configureerror', 'configureid', '=', $configureid, 1, $extra_msg);
+ $this->verify('configureerrordiff', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('coverage', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('coveragefile', 'id', 'IN', $coveragefileids, 1, $extra_msg);
+ $this->verify('coveragefilelog', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('coveragesummary', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('coveragesummarydiff', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('dynamicanalysis', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('dynamicanalysissummary', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('dynamicanalysisdefect', 'dynamicanalysisid', '=', $dynamicanalysisid, 0, $extra_msg);
+ $this->verify('image', 'id', 'IN', $imgids, 1, $extra_msg);
+ $this->verify('label2build', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('label2buildfailure', 'labelid', '=', $labelid, 1, $extra_msg);
+ $this->verify('label2coveragefile', 'labelid', '=', $labelid, 1, $extra_msg);
+ $this->verify('label2dynamicanalysis', 'labelid', '=', $labelid, 0, $extra_msg);
+ $this->verify('label2test', 'labelid', '=', $labelid, 1, $extra_msg);
+ $this->verify('note', 'id', 'IN', $noteids, 1, $extra_msg);
+ $this->verify('summaryemail', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('subproject2build', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('test2image', 'outputid', 'IN', $outputids, 1, $extra_msg);
+ $this->verify('testdiff', 'buildid', '=', $build->Id, 0, $extra_msg);
+ $this->verify('updatefile', 'updateid', '=', $updateid, 1, $extra_msg);
+ $this->verify('uploadfile', 'id', 'IN', $uploadfileids, 1, $extra_msg);
+
+ // Remove the other build too to verify that shared resources get cleaned up
+ // and to make this test idempotent.
+ DatabaseCleanupUtils::removeBuild($existing_build->Id);
+
+ $extra_msg = 'after 2nd delete';
+ $this->verify('build', 'id', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('build2configure', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('build2group', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('build2note', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('build2test', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('build2update', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('build2uploadfile', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('buildemail', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('builderror', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('builderrordiff', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('buildfailure', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('buildfailuredetails', 'id', '=', $detailsid, 0, $extra_msg);
+ $this->verify('buildtesttime', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('buildupdate', 'id', '=', $updateid, 0, $extra_msg);
+ $this->verify('configure', 'id', '=', $configureid, 0, $extra_msg);
+ $this->verify('configureerror', 'configureid', '=', $configureid, 0, $extra_msg);
+ $this->verify('configureerrordiff', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('coverage', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('coveragefile', 'id', 'IN', $coveragefileids, 0, $extra_msg);
+ $this->verify('coveragefilelog', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('coveragesummary', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('coveragesummarydiff', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('dynamicanalysis', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('dynamicanalysissummary', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('dynamicanalysisdefect', 'dynamicanalysisid', '=', $dynamicanalysisid, 0, $extra_msg);
+ $this->verify('image', 'id', 'IN', $imgids, 0, $extra_msg);
+ $this->verify('label2build', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('label2buildfailure', 'labelid', '=', $labelid, 0, $extra_msg);
+ $this->verify('label2coveragefile', 'labelid', '=', $labelid, 0, $extra_msg);
+ $this->verify('label2dynamicanalysis', 'labelid', '=', $labelid, 0, $extra_msg);
+ $this->verify('label2test', 'labelid', '=', $labelid, 0, $extra_msg);
+ $this->verify('note', 'id', 'IN', $noteids, 0, $extra_msg);
+ $this->verify('summaryemail', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('subproject2build', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('test2image', 'outputid', 'IN', $outputids, 0, $extra_msg);
+ $this->verify('testdiff', 'buildid', '=', $existing_build->Id, 0, $extra_msg);
+ $this->verify('updatefile', 'updateid', '=', $updateid, 0, $extra_msg);
+ $this->verify('uploadfile', 'id', 'IN', $uploadfileids, 0, $extra_msg);
}
- public function verify($table, $field, $compare, $value, $expected, $deleted=false)
+ public function verify(string $table, string $field, string $compare, string|int $value, int $expected, string $extra_msg=''): void
{
- $delete_msg = '';
- if ($deleted) {
- $delete_msg = 'after deletion';
- }
$num_rows = count(DB::select("SELECT $field FROM $table WHERE $field $compare $value"));
if ($num_rows !== $expected) {
- $this->fail("Expected $expected for $table $delete_msg, found $num_rows");
+ $this->fail("Expected $expected for $table $extra_msg, found $num_rows");
}
}
- public function verify_get_columns($table, $columns, $field, $compare, $value, $expected)
+ /**
+ * @param array $columns
+ * @return array
+ */
+ public function verify_get_columns(string $table, array $columns, string $field, string $compare, string $value, int $expected): array
{
$col_arg = implode(',', $columns);
$result = DB::select("SELECT $col_arg FROM $table WHERE $field $compare $value");
@@ -503,7 +642,7 @@ public function verify_get_columns($table, $columns, $field, $compare, $value, $
return $retval;
}
- public function verify_get_rows($table, $column, $field, $compare, $value, $expected)
+ public function verify_get_rows(string $table, string $column, string $field, string $compare, string $value, int $expected): string
{
$result = DB::select("SELECT $column FROM $table WHERE $field $compare $value");
$num_rows = count($result);
diff --git a/app/cdash/tests/test_upgrade.php b/app/cdash/tests/test_upgrade.php
index a697b37266..9b72a5f7fe 100644
--- a/app/cdash/tests/test_upgrade.php
+++ b/app/cdash/tests/test_upgrade.php
@@ -76,18 +76,6 @@ function testComputeUpdateStatistics()
}
*/
- public function testCleanup()
- {
- if (!$this->getMaintenancePage()) {
- return 1;
- }
- set_time_limit(0);
- if (!$this->clickSubmitByName('Cleanup')) {
- $this->fail('clicking Cleanup returned false');
- }
- $this->assertText('Database cleanup complete.');
- }
-
public function getMaintenancePage()
{
$this->login();
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 01b4e298cf..5670fa2089 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -301,7 +301,7 @@ parameters:
#^Call to deprecated function pdo_error\\(\\)\\:
04/01/2023$#
"""
- count: 7
+ count: 6
path: app/Http/Controllers/AdminController.php
-
@@ -410,26 +410,6 @@ parameters:
count: 1
path: app/Http/Controllers/AdminController.php
- -
- message: "#^Method App\\\\Http\\\\Controllers\\\\AdminController\\:\\:delete_unused_rows\\(\\) has parameter \\$field with no type specified\\.$#"
- count: 1
- path: app/Http/Controllers/AdminController.php
-
- -
- message: "#^Method App\\\\Http\\\\Controllers\\\\AdminController\\:\\:delete_unused_rows\\(\\) has parameter \\$selectfield with no type specified\\.$#"
- count: 1
- path: app/Http/Controllers/AdminController.php
-
- -
- message: "#^Method App\\\\Http\\\\Controllers\\\\AdminController\\:\\:delete_unused_rows\\(\\) has parameter \\$table with no type specified\\.$#"
- count: 1
- path: app/Http/Controllers/AdminController.php
-
- -
- message: "#^Method App\\\\Http\\\\Controllers\\\\AdminController\\:\\:delete_unused_rows\\(\\) has parameter \\$targettable with no type specified\\.$#"
- count: 1
- path: app/Http/Controllers/AdminController.php
-
-
message: "#^Method App\\\\Http\\\\Controllers\\\\AdminController\\:\\:removeBuilds\\(\\) never returns Illuminate\\\\Http\\\\RedirectResponse so it can be removed from the return type\\.$#"
count: 1
@@ -447,7 +427,7 @@ parameters:
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
- count: 9
+ count: 8
path: app/Http/Controllers/AdminController.php
-
@@ -26667,149 +26647,11 @@ parameters:
count: 1
path: app/cdash/tests/test_redundanttests.php
- -
- message: """
- #^Call to deprecated function pdo_query\\(\\)\\:
- 04/01/2023$#
- """
- count: 7
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Call to deprecated method pass\\(\\) of class SimpleTestCase\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:testBuildRemovalWorksAsExpected\\(\\) has no return type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:testRemoveBuilds\\(\\) has no return type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify\\(\\) has no return type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify\\(\\) has parameter \\$compare with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify\\(\\) has parameter \\$deleted with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify\\(\\) has parameter \\$expected with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify\\(\\) has parameter \\$field with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify\\(\\) has parameter \\$table with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify\\(\\) has parameter \\$value with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_columns\\(\\) has no return type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_columns\\(\\) has parameter \\$columns with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_columns\\(\\) has parameter \\$compare with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_columns\\(\\) has parameter \\$expected with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_columns\\(\\) has parameter \\$field with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_columns\\(\\) has parameter \\$table with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_columns\\(\\) has parameter \\$value with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_rows\\(\\) has no return type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_rows\\(\\) has parameter \\$column with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_rows\\(\\) has parameter \\$compare with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_rows\\(\\) has parameter \\$expected with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_rows\\(\\) has parameter \\$field with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_rows\\(\\) has parameter \\$table with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Method RemoveBuildsTestCase\\:\\:verify_get_rows\\(\\) has parameter \\$value with no type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
-
message: "#^Parameter \\#1 \\$string of function base64_encode expects string, string\\|false given\\.$#"
count: 1
path: app/cdash/tests/test_removebuilds.php
- -
- message: "#^Property App\\\\Models\\\\TestMeasurement\\:\\:\\$value \\(string\\) does not accept int\\.$#"
- count: 2
- path: app/cdash/tests/test_removebuilds.php
-
- -
- message: "#^Unreachable statement \\- code above always terminates\\.$#"
- count: 1
- path: app/cdash/tests/test_removebuilds.php
-
-
message: "#^Variable property access on mixed\\.$#"
count: 2
@@ -28491,11 +28333,6 @@ parameters:
count: 1
path: app/cdash/tests/test_upgrade.php
- -
- message: "#^Method UpgradeTestCase\\:\\:testCleanup\\(\\) has no return type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_upgrade.php
-
-
message: "#^Method UpgradeTestCase\\:\\:testComputeTestTiming\\(\\) has no return type specified\\.$#"
count: 1
|