[Issue #16] - Abstracted benchmarks from tests via BenchmarkProfile model, to allow for linking benchmarks with different runtime settings
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Gregory Ballantine
2025-09-11 16:09:00 -04:00
parent a736113abd
commit b19c95187b
8 changed files with 128 additions and 15 deletions

View File

@@ -0,0 +1,97 @@
Sequel.migration do
up do
# 1. Create benchmark_profiles
create_table(:benchmark_profiles) do
primary_key :id
String :label, null: false
String :settings, null: false
foreign_key :benchmark_id, :benchmarks, null: false, on_delete: :cascade
DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP
DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP
end
# 2. Create join table (tests <-> benchmark_profiles)
create_table(:benchmark_profiles_tests) do
primary_key :id
foreign_key :test_id, :tests, null: false, on_delete: :cascade
foreign_key :benchmark_profile_id, :benchmark_profiles, null: false, on_delete: :cascade
index [:test_id, :benchmark_profile_id], unique: true
end
# 3. Add benchmark_profile_id to results
alter_table(:results) do
add_foreign_key :benchmark_profile_id, :benchmark_profiles, null: true, on_delete: :cascade
end
# 4. Migrate data from old schema
from(:benchmarks).each do |b_row|
# Create a BenchmarkProfile for this (test, benchmark) pair
bp_id = self[:benchmark_profiles].insert(
benchmark_id: b_row[:id],
label: 'Default',
settings: '{}'
)
from(:benchmarks_tests).each do |bt_row|
if bt_row[:benchmark_id] == b_row[:id]
# Link it to the test
self[:benchmark_profiles_tests].insert(
test_id: bt_row[:test_id],
benchmark_profile_id: bp_id
)
# Update results belonging to this test + benchmark pair
self[:results]
.where(test_id: bt_row[:test_id], benchmark_id: bt_row[:benchmark_id])
.update(benchmark_profile_id: bp_id)
end
end
end
# 5. Clean up old schema
alter_table(:results) do
drop_foreign_key :benchmark_id
end
drop_table(:benchmarks_tests)
end
down do
# 1. Recreate old join table
create_table(:benchmarks_tests) do
foreign_key :test_id, :tests, null: false
foreign_key :benchmark_id, :benchmarks, null: false
end
# 2. Add benchmark_id back to results
alter_table(:results) do
add_foreign_key :benchmark_id, :benchmarks, null: true
end
# 3. Restore data
from(:benchmark_profiles_tests).each do |bpt_row|
bp = self[:benchmark_profiles][id: bpt_row[:benchmark_profile_id]]
next unless bp # safety check
# Recreate old benchmarks_tests entry
self[:benchmarks_tests].insert(
test_id: bpt_row[:test_id],
benchmark_id: bp[:benchmark_id]
)
# Update results to point back to benchmark_id
self[:results]
.where(test_id: bpt_row[:test_id], benchmark_profile_id: bp[:id])
.update(benchmark_id: bp[:benchmark_id])
end
# 4. Remove new schema
alter_table(:results) do
drop_foreign_key :benchmark_profile_id
end
drop_table(:benchmark_profiles_tests)
drop_table(:benchmark_profiles)
end
end

View File

@@ -2,6 +2,7 @@
require_relative 'base_controller' require_relative 'base_controller'
require_relative '../models/test' require_relative '../models/test'
require_relative '../models/benchmark_profile'
# / (top-level) routes # / (top-level) routes
class IndexController < BaseController class IndexController < BaseController

View File

@@ -3,7 +3,6 @@
# Benchmark - database model for PC benchmarks # Benchmark - database model for PC benchmarks
class Benchmark < Sequel::Model class Benchmark < Sequel::Model
many_to_many :tests one_to_many :benchmark_profiles
one_to_many :results
end end

View File

@@ -0,0 +1,14 @@
# frozen_string_literal: true
# BenchmarkProfile - database model for benchmark settings profile
class BenchmarkProfile < Sequel::Model
many_to_one :benchmark
many_to_many :tests
one_to_many :results
def display_name
"#{benchmark.name} @ #{label}"
end
end

View File

@@ -4,7 +4,7 @@
class Result < Sequel::Model class Result < Sequel::Model
many_to_one :test many_to_one :test
many_to_one :benchmark many_to_one :benchmark_profile
def formatted_score def formatted_score
return @avg_score return @avg_score

View File

@@ -5,10 +5,10 @@ class Test < Sequel::Model
one_to_many :result one_to_many :result
many_to_one :hardware many_to_one :hardware
many_to_many :benchmarks many_to_many :benchmark_profiles
def benchmark?(benchmark_id) def benchmark?(benchmark_id)
return benchmarks_dataset.where(Sequel[:benchmarks][:id] => benchmark_id).any? return benchmark_profiles_dataset.where(Sequel[:benchmark][:id] => benchmark_id).any?
end end
end end

View File

@@ -21,29 +21,31 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h3 class="mb-3">Tests using this benchmark:</h3> <h3 class="mb-3">Profiles created for this benchmark:</h3>
<% if benchmark.tests.length > 0 %> <% if benchmark.benchmark_profiles.length > 0 %>
<table class="table table-hover table-responsive"> <table class="table table-hover table-responsive">
<thead class="table-light"> <thead class="table-light">
<tr> <tr>
<th>Test title</th> <th>Profile Label</th>
<th>Benchmarks</th> <th>Tests Linked</th>
<th>Created at</th>
<th>Last updated</th> <th>Last updated</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% benchmark.tests.each do |t| %> <% benchmark.benchmark_profiles.each do |bp| %>
<tr> <tr>
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td> <td><%= bp.display_name %></td>
<td><%= t.benchmarks.length %></td> <td><%= bp.tests.length %></td>
<td><%= t.updated_at %></td> <td><%= bp.created_at %></td>
<td><%= bp.updated_at %></td>
</tr> </tr>
<% end %> <% end %>
</tbody> </tbody>
</table> </table>
<% else %> <% else %>
<p>There are no tests associated with this benchmark.</p> <p>There are no profiles associated with this benchmark.</p>
<% end %> <% end %>
</div> </div>
</div> </div>

View File

@@ -17,7 +17,7 @@
<% tests.each do |t| %> <% tests.each do |t| %>
<tr> <tr>
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td> <td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
<td><%= t.benchmarks.length %></td> <td><%= t.benchmark_profiles.length %></td>
<td><%= t.updated_at %></td> <td><%= t.updated_at %></td>
</tr> </tr>
<% end %> <% end %>