Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relate test measurements to tests instead of test outputs #2336

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/Http/Controllers/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,6 @@ public function upgrade()

self::delete_unused_rows('dailyupdatefile', 'dailyupdateid', 'dailyupdate');
self::delete_unused_rows('test2image', 'outputid', 'testoutput');
self::delete_unused_rows('testmeasurement', 'outputid', 'testoutput');
self::delete_unused_rows('label2test', 'outputid', 'testoutput');

$xml .= add_XML_value('alert', 'Database cleanup complete.');
Expand Down
6 changes: 3 additions & 3 deletions app/Http/Controllers/TestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ public function apiTestSummary(): JsonResponse|StreamedResponse
SELECT testmeasurement.name
FROM build2test
JOIN build ON (build.id = build2test.buildid)
JOIN testmeasurement ON (build2test.outputid = testmeasurement.outputid)
JOIN testmeasurement ON (build2test.id = testmeasurement.testid)
JOIN measurement ON (
build.projectid=measurement.projectid
AND testmeasurement.name=measurement.name
Expand Down Expand Up @@ -259,7 +259,7 @@ public function apiTestSummary(): JsonResponse|StreamedResponse
build2test.time
FROM build2test
JOIN build ON (build.id = build2test.buildid)
JOIN testmeasurement ON (build2test.outputid = testmeasurement.outputid)
JOIN testmeasurement ON (build2test.id = testmeasurement.testid)
JOIN measurement ON (
build.projectid = measurement.projectid
AND testmeasurement.name = measurement.name
Expand Down Expand Up @@ -472,7 +472,7 @@ public function apiTestSummary(): JsonResponse|StreamedResponse
build2test.time
FROM build2test
JOIN build ON (build.id = build2test.buildid)
JOIN testmeasurement ON (build2test.outputid = testmeasurement.outputid)
JOIN testmeasurement ON (build2test.id = testmeasurement.testid)
JOIN measurement ON (
build.projectid = measurement.projectid
AND testmeasurement.name = measurement.name
Expand Down
9 changes: 9 additions & 0 deletions app/Models/BuildTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Config;

/**
Expand Down Expand Up @@ -73,6 +74,14 @@ public function testOutput(): BelongsTo
return $this->belongsTo('App\Models\TestOutput', 'outputid');
}

/**
* @return HasMany<TestMeasurement>
*/
public function testMeasurements(): HasMany
{
return $this->hasMany(TestMeasurement::class, 'testid');
}

/**
* Add a label to this buildtest.
**/
Expand Down
6 changes: 3 additions & 3 deletions app/Models/TestMeasurement.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/**
* @property int $id
* @property int $outputid
* @property int $testid
* @property string $name
* @property string $type
* @property string $value
Expand All @@ -21,14 +21,14 @@ class TestMeasurement extends Model
public $timestamps = false;

protected $fillable = [
'outputid',
'testid',
'name',
'type',
'value',
];

protected $casts = [
'id' => 'integer',
'outputid' => 'integer',
'testid' => 'integer',
];
}
8 changes: 0 additions & 8 deletions app/Models/TestOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ public function buildTests(): HasMany
return $this->hasMany(BuildTest::class, 'outputid');
}

/**
* @return HasMany<TestMeasurement>
*/
public function testMeasurements(): HasMany
{
return $this->hasMany(TestMeasurement::class, 'outputid');
}

/**
* Returns uncompressed test output.
*/
Expand Down
11 changes: 5 additions & 6 deletions app/Utils/TestCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,6 @@ public function create(Build $build): void
':crc32' => $crc32]);
$outputid = DB::getPdo()->lastInsertId();

// testmeasurement
foreach ($this->measurements as $measurement) {
$measurement->outputid = $outputid;
$measurement->save();
}

// test2image
foreach ($this->images as $image) {
$this->saveImage($image, $outputid);
Expand All @@ -225,6 +219,11 @@ public function create(Build $build): void
// Build::ComputeTestTiming.
$buildtest->save();

foreach ($this->measurements as $measurement) {
$measurement->testid = $buildtest->id;
$measurement->save();
}

// Give measurements to the buildtest model so we can properly calculate
// proctime later on.
$buildtest->measurements = $this->measurements;
Expand Down
16 changes: 8 additions & 8 deletions app/cdash/app/Controller/Api/QueryTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -385,17 +385,17 @@ public function getResponse()
$this->limitSQL
", $query_params);

$outputids = [];
$testids = [];
foreach ($rows as $row) {
$outputids[] = (int) $row->outputid;
$testids[] = (int) $row->buildtestid;
}

$outputid_to_testmeasurements = [];
foreach (TestMeasurement::whereIn('outputid', $outputids)->get() as $testmeasurement) {
if (!isset($outputid_to_testmeasurements[$testmeasurement->outputid])) {
$outputid_to_testmeasurements[$testmeasurement->outputid] = [];
$testid_to_testmeasurements = [];
foreach (TestMeasurement::whereIn('testid', $testids)->get() as $testmeasurement) {
if (!isset($testid_to_testmeasurements[$testmeasurement->testid])) {
$testid_to_testmeasurements[$testmeasurement->testid] = [];
}
$outputid_to_testmeasurements[$testmeasurement->outputid][] = $testmeasurement;
$testid_to_testmeasurements[$testmeasurement->testid][] = $testmeasurement;
}

// Rows of test data to be displayed to the user.
Expand Down Expand Up @@ -462,7 +462,7 @@ public function getResponse()
}

if ($this->hasProcessors || $this->numExtraMeasurements > 0) {
$this->addExtraMeasurements($test, $outputid_to_testmeasurements[(int) $row->outputid] ?? []);
$this->addExtraMeasurements($test, $testid_to_testmeasurements[(int) $row->buildtestid] ?? []);
}

$tests[] = $test;
Expand Down
21 changes: 13 additions & 8 deletions app/cdash/app/Controller/Api/TestDetails.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public function getResponse(): JsonResponse|StreamedResponse
name
FROM testmeasurement
WHERE
outputid = ?
testid = ?
AND type = 'file'
ORDER BY id
", [$this->buildtest->outputid])[0];
", [$this->buildtest->id])[0];

return response()->streamDownload(
function () use ($query) {
Expand All @@ -69,14 +69,19 @@ function () use ($query) {
$project_response['showtesttime'] = $this->project->ShowTestTime;
$response['project'] = $project_response;

$stmt = $this->db->prepare(
'SELECT * FROM build2test b2t
JOIN testoutput ON testoutput.id = b2t.outputid
WHERE b2t.id = :buildtestid');
$stmt = $this->db->prepare('
SELECT
*,
b2t.id as testid
FROM build2test b2t
JOIN testoutput ON (testoutput.id = b2t.outputid)
WHERE b2t.id = :buildtestid
');
$this->db->execute($stmt, [':buildtestid' => $this->buildtest->id]);
$testRow = $stmt->fetch();
$testName = $testRow['testname'];
$outputid = $testRow['outputid'];
$testid = $testRow['testid'];

$menu = [];
$menu['back'] = "viewTest.php?buildid={$this->build->Id}";
Expand Down Expand Up @@ -242,9 +247,9 @@ function () use ($query) {
$measurements_response = [];
$stmt = $this->db->prepare(
'SELECT name, type, value FROM testmeasurement
WHERE outputid = :outputid
WHERE testid = :testid
ORDER BY id');
$this->db->execute($stmt, [':outputid' => $outputid]);
$this->db->execute($stmt, [':testid' => $testid]);
$fileid = 1;
$test_response['environment'] = '';
$preformatted_measurements = [];
Expand Down
2 changes: 1 addition & 1 deletion app/cdash/app/Controller/Api/TestGraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function getResponse()
'data' => [],
];
$this->testHistoryQueryExtraColumns = ', tm.value';
$this->testHistoryQueryExtraJoins = 'JOIN testmeasurement tm ON (b2t.outputid = tm.outputid)';
$this->testHistoryQueryExtraJoins = 'JOIN testmeasurement tm ON (b2t.id = tm.testid)';
$this->testHistoryQueryExtraWheres = 'AND tm.name = :measurementname';
$this->testHistoryQueryParams[':measurementname'] = $measurement_name;
break;
Expand Down
2 changes: 1 addition & 1 deletion app/cdash/app/Controller/Api/ViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ public function getResponse()
build2test.time
FROM build2test
JOIN build ON (build.id = build2test.buildid)
JOIN testmeasurement ON (build2test.outputid = testmeasurement.outputid)
JOIN testmeasurement ON (build2test.id = testmeasurement.testid)
JOIN measurement ON (build.projectid=measurement.projectid AND testmeasurement.name=measurement.name)
WHERE build.$buildid_field = :buildid
$onlydelta_extra
Expand Down
1 change: 0 additions & 1 deletion app/cdash/include/common.php
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,6 @@ function remove_build($buildid)
// 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)) {
delete_rows_chunked('DELETE FROM testmeasurement WHERE outputid IN ', $testoutputs_to_delete);
delete_rows_chunked('DELETE FROM testoutput WHERE id IN ', $testoutputs_to_delete);

$testoutputs_to_delete_prepare_array = $db->createPreparedArray(count($testoutputs_to_delete));
Expand Down
3 changes: 1 addition & 2 deletions app/cdash/tests/test_namedmeasurements.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ public function testNamedMeasurements()
$results = DB::select("
SELECT testmeasurement.value
FROM testmeasurement
JOIN testoutput ON (testmeasurement.outputid = testoutput.id)
JOIN build2test ON (testoutput.id = build2test.outputid)
JOIN build2test ON (testmeasurement.testid = build2test.id)
JOIN build ON (build2test.buildid = build.id)
WHERE build.projectid = :projectid
AND testmeasurement.name = 'archive directory'
Expand Down
2 changes: 0 additions & 2 deletions app/cdash/tests/test_removebuilds.php
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,6 @@ public function testBuildRemovalWorksAsExpected()

$outputids =
$this->verify_get_rows('build2test', 'outputid', 'buildid', '=', $build->Id, 2);
$this->verify('testmeasurement', 'outputid', 'IN', $outputids, 2);
$imgids = $this->verify_get_rows('test2image', 'imgid', 'outputid', 'IN', $outputids, 2);
$this->verify('image', 'id', 'IN', $imgids, 2);

Expand Down Expand Up @@ -476,7 +475,6 @@ public function testBuildRemovalWorksAsExpected()
$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('testmeasurement', 'outputid', 'IN', $outputids, 1, true);
$this->verify('updatefile', 'updateid', '=', $updateid, 1, true);
$this->verify('uploadfile', 'id', 'IN', $uploadfileids, 1, true);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('testmeasurement', function (Blueprint $table) {
$table->unsignedInteger('testid')
->nullable(); // Temporarily make the column nullable
});

DB::insert('
INSERT INTO testmeasurement (
outputid,
name,
type,
value,
testid
)
SELECT
testmeasurement.outputid,
testmeasurement.name,
testmeasurement.type,
testmeasurement.value,
build2test.id
FROM testmeasurement
JOIN build2test ON testmeasurement.outputid = build2test.outputid
');

// Delete any entries which will fail the FK constraint (including the old values which now have a null testid)
DB::delete('
DELETE FROM testmeasurement
WHERE
testid IS NULL OR
testid NOT IN (
SELECT id from build2test
)
');

Schema::table('testmeasurement', function (Blueprint $table) {
$table->unsignedInteger('testid')
->nullable(false) // Add a not-null constraint
->index()
->change();
$table->foreign('testid')->references('id')->on('build2test')->cascadeOnDelete();
$table->dropColumn('outputid');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('testmeasurement', function (Blueprint $table) {
$table->unsignedInteger('testid')
->nullable()
->change();

$table->integer('outputid')
->nullable(); // Temporarily make the column nullable
});

DB::insert('
INSERT INTO testmeasurement (
outputid,
name,
type,
value
)
SELECT
build2test.outputid,
testmeasurement.name,
testmeasurement.type,
testmeasurement.value
FROM testmeasurement
JOIN build2test ON testmeasurement.testid = build2test.id
GROUP BY
build2test.outputid,
testmeasurement.name,
testmeasurement.type,
testmeasurement.value
');

// Delete all of the old entries
DB::delete('DELETE FROM testmeasurement WHERE outputid IS NULL');

Schema::table('testmeasurement', function (Blueprint $table) {
$table->dropForeign(['testid']);
$table->dropColumn('testid');
$table->integer('outputid')
->nullable(false) // Revert back to a not-null column
->index()
->change();
});
}
};
3 changes: 3 additions & 0 deletions tests/Feature/TestSchemaMigration.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public function testMigrationOfTestTables()
'--force' => true]);

// Rollback some migrations to drop the relevant tables.
Artisan::call('migrate:rollback', [
'--path' => 'database/migrations/2024_07_09_025240_find_test_measurements_by_testid.php',
'--force' => true]);
Artisan::call('migrate:rollback', [
'--path' => 'database/migrations/2024_04_17_183212_remove_test_table.php',
'--force' => true]);
Expand Down