
https://svn.lrde.epita.fr/svn/ranch/trunk Index: ChangeLog from Nicolas Despr�s <nicolas.despres@gmail.com> Regression chart handle the system. * web/ranch/test/unit/system_test.rb: Test find_id_by_hostname. * web/ranch/test/functional/benches_controller_test.rb: Make test more strict. * web/ranch/test/fixtures/outputs.yml: Generate measure for quotient on several changing systems and several revision. * web/ranch/test/fixtures/systems.yml: Generate two systems that change three times. * web/ranch/app/helpers/graph_helper.rb: Give the chosen hostname to the graph controller. * web/ranch/app/helpers/benches_helper.rb: Add an helper that render the system modification table. * web/ranch/app/models/system.rb: Add the find_id_by_hostname class method. * web/ranch/app/controllers/graph_controller.rb: Handle the system hostname and do not query the database with raw SQL. * web/ranch/app/controllers/benches_controller.rb: Query the systems modification. * web/ranch/app/views/benches/regression.rhtml: Render the system changes if needed. app/controllers/benches_controller.rb | 31 +++++++++++-- app/controllers/graph_controller.rb | 41 +++++++++++------ app/helpers/benches_helper.rb | 47 ++++++++++++++++++++ app/helpers/graph_helper.rb | 4 + app/models/system.rb | 8 +++ app/views/benches/regression.rhtml | 30 ++++++------ test/fixtures/outputs.yml | 31 +++++++------ test/fixtures/systems.yml | 56 ++++------------------- test/functional/benches_controller_test.rb | 68 +++++++++++++++-------------- test/unit/system_test.rb | 5 ++ 10 files changed, 195 insertions(+), 126 deletions(-) Index: web/ranch/test/unit/system_test.rb --- web/ranch/test/unit/system_test.rb (revision 63) +++ web/ranch/test/unit/system_test.rb (working copy) @@ -22,4 +22,9 @@ assert 1, system.errors.count end + def test_find_id_by_hostname + systems = System.find_id_by_hostname "ouagadougou" + assert_equal 3, systems.size + end + end Index: web/ranch/test/functional/benches_controller_test.rb --- web/ranch/test/functional/benches_controller_test.rb (revision 63) +++ web/ranch/test/functional/benches_controller_test.rb (working copy) @@ -17,7 +17,7 @@ get :index, { :project_id => 1 } assert_response :redirect assert_redirected_to(:action => 'show', :bench_id => 1) - assert_not_nil assigns(:project) + assert_equal 1, assigns(:project).id assert_not_nil assigns(:benches) end @@ -25,9 +25,9 @@ get :show, { :bench_id => 1 } assert_response :success assert_template 'show' - assert_not_nil assigns(:project) - assert_not_nil assigns(:benches) - assert_not_nil assigns(:bench) + assert_equal 1, assigns(:project).id + assert ! assigns(:benches).empty? + assert_equal 1, assigns(:bench).id end def test_regression @@ -35,11 +35,11 @@ assert_response :success assert_template 'regression' - assert_not_nil assigns(:project) - assert_not_nil assigns(:bench) + assert_equal 1, assigns(:project).id + assert_equal 1, assigns(:bench).id assert_not_nil assigns(:output_arg_num) - assert_not_nil assigns(:inputs) - assert_not_nil assigns(:systems) + assert ! assigns(:inputs).empty? + assert ! assigns(:systems).empty? assert_kind_of Hash, assigns(:revision) assert assigns(:revision)[:start] < assigns(:revision)[:stop] assert assigns(:revision)[:start] >= 1 @@ -53,12 +53,12 @@ assert_response :success assert_template 'regression' - assert_not_nil assigns(:project) - assert_not_nil assigns(:bench) + assert_equal 1, assigns(:project).id + assert_equal 1, assigns(:bench).id assert_not_nil assigns(:output_arg_num) - assert_not_nil assigns(:inputs) + assert ! assigns(:inputs).empty? assert_not_nil assigns(:input_set_num) - assert_not_nil assigns(:systems) + assert ! assigns(:systems).empty? assert_kind_of Hash, assigns(:revision) assert_equal 2, assigns(:revision)[:start] assert_equal 8, assigns(:revision)[:stop] @@ -73,12 +73,12 @@ assert_response :success assert_template 'regression' - assert_not_nil assigns(:project) - assert_not_nil assigns(:bench) + assert_equal 1, assigns(:project).id + assert_equal 1, assigns(:bench).id assert_not_nil assigns(:output_arg_num) - assert_not_nil assigns(:inputs) + assert ! assigns(:inputs).empty? assert_not_nil assigns(:input_set_num) - assert_not_nil assigns(:systems) + assert ! assigns(:systems).empty? assert_kind_of Hash, assigns(:revision) assert_equal 1, assigns(:revision)[:start] assert_equal assigns(:project).head_revision, assigns(:revision)[:stop] @@ -94,12 +94,12 @@ assert_template 'regression' assert_equal 1, assigns(:project).id - assert_equal 'determinize', assigns(:bench).name + assert_equal 1, assigns(:bench).id assert(flash.has_key?(:error)) assert_not_nil assigns(:output_arg_num) - assert_not_nil assigns(:inputs) + assert ! assigns(:inputs).empty? assert_not_nil assigns(:input_set_num) - assert_not_nil assigns(:systems) + assert ! assigns(:systems).empty? assert_not_nil flash[:error] end @@ -113,12 +113,12 @@ assert_template 'regression' assert_equal 1, assigns(:project).id - assert_equal 'determinize', assigns(:bench).name + assert_equal 1, assigns(:bench).id assert_equal 0, assigns(:output_arg_num) assert_equal 3, assigns(:output_arg_nb) - assert_not_nil assigns(:inputs) + assert ! assigns(:inputs).empty? assert_not_nil assigns(:input_set_num) - assert_not_nil assigns(:systems) + assert ! assigns(:systems).empty? assert_nil flash[:error] end @@ -131,25 +131,29 @@ assert_template 'regression' assert_equal 1, assigns(:project).id - assert_equal 'determinize', assigns(:bench).name + assert_equal 1, assigns(:bench).id assert(flash.has_key?(:error)) - assert_not_nil assigns(:output_arg_num) - assert_not_nil assigns(:inputs) + assert_equal 0, assigns(:output_arg_num) + assert ! assigns(:inputs).empty? assert_not_nil assigns(:input_set_num) - assert_not_nil assigns(:systems) + assert ! assigns(:systems).empty? assert_not_nil flash[:error] end def test_systems_list_is_grouped_by_hostname - post :regression, { :bench_id => 2 } + post :regression, { + :bench_id => 2, + :revision => { :range => "1-10" } + } assert_response :success assert_template 'regression' - assert_not_nil assigns(:project) - assert_not_nil assigns(:bench) - assert_not_nil assigns(:output_arg_num) - assert_not_nil assigns(:inputs) - assert_equal 1, assigns(:systems).size + assert_equal 1, assigns(:project).id + assert_equal 2, assigns(:bench).id + assert_equal 0, assigns(:output_arg_num) + assert ! assigns(:inputs).empty? + assert_equal 2, assigns(:systems).size + assert_equal 10, assigns(:system_changes).size end end Index: web/ranch/test/fixtures/outputs.yml --- web/ranch/test/fixtures/outputs.yml (revision 63) +++ web/ranch/test/fixtures/outputs.yml (working copy) @@ -34,24 +34,27 @@ # Outputs for the quotient (id = 2) bench. -quotient_r1_utime_1: - id: <%= id += 1 %> - name: utime - unit: sec - value: 5 - bench_id: 2 - arg_num: 1 - set_num: 0 - system_id: 1 - revision: 1 +<% (0..1).each do |sys| %> + + <% 10.downto(1) do |rev| %> -quotient_r2_utime_1: +<%= "quotient_r#{rev}_utime_1_sys#{sys}:" %> id: <%= id += 1 %> name: utime unit: sec - value: 10 + value: <%= rev * 5 + sys * 10 %> bench_id: 2 arg_num: 1 set_num: 0 - system_id: 2 - revision: 2 + system_id: <%= sys * 3 + (if rev <= 3 + 1 + elsif rev <= 6 + 2 + else + 3 + end) %> + revision: <%= rev %> + + <% end %> +<% end %> + Index: web/ranch/test/fixtures/systems.yml --- web/ranch/test/fixtures/systems.yml (revision 63) +++ web/ranch/test/fixtures/systems.yml (working copy) @@ -1,6 +1,8 @@ <% id = 0 %> -ouagadougou1: +<% (1..3).each do |i| %> + +<%= "ouagadougou#{i}:" %> id: <%= id += 1 %> hostname: ouagadougou kernel_name: Linux @@ -13,7 +15,7 @@ comp_flags: -02 -W -Wall mem_size: 256664 cpu_name: "AMD Athlon(tm) XP 2000+" - cpu_frequency: 1661.957 + cpu_frequency: <%= 1000.10 * i %> info: | Running action system SYSTEM UNAME: CYGWIN_NT-5.1 pau 1.5.18(0.132/4/2) 2005-07-02 20:30 i686 unknown unknown Cygwin @@ -44,51 +46,11 @@ This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -ouagadougou2: - id: <%= id += 1 %> - hostname: ouagadougou - kernel_name: Linux - kernel_revision: "2.4.27-2-k7" - kernel_version: "#1 Tue Aug 16 17:30:14" - host_type: i686 - os_name: GNU/Linux - comp_name: g++ - comp_version: 4.0.3 - comp_flags: -02 -W -Wall - mem_size: 256664 - cpu_name: "AMD Athlon(tm) XP 2000+" - cpu_frequency: 3000.00 - info: | - Running action system - SYSTEM UNAME: CYGWIN_NT-5.1 pau 1.5.18(0.132/4/2) 2005-07-02 20:30 i686 unknown unknown Cygwin - BUILD DATE: Mon Nov 14 10:13:51 2005 - BUILD SHORTDATE: 14/11 10:13 - HIGHEST SVN REVISION: 26 - BUILD REVISION: 6 - PKG_CONFIG_PATH: - PATH: /cygdrive/d/build_farm/prefix/monoburg/bin:/usr/local/bin:/bin:/cygdrive/c/ghc/ghc-6.4/bin:/cygdrive/c/program files/imagemagick-6.2.5-q16:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/Intel/DMIX:/bin - BF_DEPS: - - CFLAGS: - CXXFLAGS: - CC: ccache gcc - CXX: ccache g++ - CONFIGURE OPTIONS: --prefix=/cygdrive/d/build_farm/prefix/ranch - DISTCHECK_CONFIGURE_FLAGS: +<% end %> - --- gcc (/bin/gcc) --- - gcc (GCC) 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125) - Copyright (C) 2004 Free Software Foundation, Inc. - This is free software; see the source for copying conditions. There is NO - warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - --- g++ (/bin/g++) --- - g++ (GCC) 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125) - Copyright (C) 2004 Free Software Foundation, Inc. - This is free software; see the source for copying conditions. There is NO - warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +<% (1..3).each do |i| %> -vaucanson: +<%= "vaucanson#{i}:" %> id: <%= id += 1 %> hostname: vaucanson kernel_name: Linux @@ -101,7 +63,7 @@ comp_flags: -02 -W -Wall mem_size: 4151600 cpu_name: "Intel(R) Xeon(TM) CPU 3.20GHz" - cpu_frequency: 3194.224 + cpu_frequency: <%= 2000.10 * i %> info: | Running action system SYSTEM UNAME: CYGWIN_NT-5.1 pau 1.5.18(0.132/4/2) 2005-07-02 20:30 i686 unknown unknown Cygwin @@ -131,3 +93,5 @@ Copyright (C) 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +<% end %> Index: web/ranch/app/helpers/graph_helper.rb --- web/ranch/app/helpers/graph_helper.rb (revision 63) +++ web/ranch/app/helpers/graph_helper.rb (working copy) @@ -5,6 +5,7 @@ rev_stop, arg_num, input_set_num, + system_hostname, options={}) url = { :controller => 'graph', @@ -13,7 +14,8 @@ :rev_start => rev_start, :rev_stop => rev_stop, :arg_num => arg_num, - :input_set_num => input_set_num + :input_set_num => input_set_num, + :system_hostname => system_hostname } options = url.merge(options) "<img src=\"#{url_for options}\" " + Index: web/ranch/app/helpers/benches_helper.rb --- web/ranch/app/helpers/benches_helper.rb (revision 63) +++ web/ranch/app/helpers/benches_helper.rb (working copy) @@ -1,2 +1,49 @@ module BenchesHelper + + def system_change_tag(hostname, changes, rev_start, rev_stop) + ret = %( + <p> + The configuration of the system #{hostname} has changed + between revision #{rev_start} and #{rev_stop}. + </p><p> + Beware that these modification may influence the benchmark results. + Look at the table below to check the modification. + </p><p> + <table> + <tr> + #{content_tag "td", hostname} + #{content_tag "td", "revision"} + </tr> + ) + prev = changes.first + changed = false + for change in changes do + if change.system_id != prev.system_id + changed = true + ret += change_tag(prev, change) + prev = change + end + end + if prev.revision != changes.last.revision + ret += change_tag(prev, changes.last) + end + ret += "</table></p>" + changed ? ret : "" + end + + protected + + def change_tag(change1, change2) + %( + <tr><td> + #{link_to(change1.system_id, + :controller => "systems", + :action => "show", + :system_id => change1.system_id)} + </td><td> + #{change1.revision}-#{change2.revision} + </td></tr> + ) + end + end Index: web/ranch/app/models/system.rb --- web/ranch/app/models/system.rb (revision 63) +++ web/ranch/app/models/system.rb (working copy) @@ -23,6 +23,14 @@ validates_length_of :cpu_name, :maximum => 128 validates_numericality_of :cpu_frequency + def self.find_id_by_hostname(hostname) + systems = System.find(:all, + :select => "id", + :conditions => [ "hostname = ?", hostname ]) + systems.collect! { |system| system.id } + systems + end + protected def validate Index: web/ranch/app/controllers/graph_controller.rb --- web/ranch/app/controllers/graph_controller.rb (revision 63) +++ web/ranch/app/controllers/graph_controller.rb (working copy) @@ -6,26 +6,39 @@ @bench = Bench.find_by_id params[:bench_id] @project = @bench.project - results = Bench.find_by_sql "SELECT value, name, unit, revision " + - "FROM outputs " + - "WHERE bench_id = #{@bench.id} " + - "AND arg_num = #{params[:arg_num]} " + - "AND set_num = #{params[:input_set_num]} " + - "AND #{params[:rev_start]} <= revision " + - "AND revision <= #{params[:rev_stop]} " + - "ORDER BY revision" + arg_num = params[:arg_num].to_i + input_set_num = params[:input_set_num].to_i + rev_start = params[:rev_start].to_i + rev_stop = params[:rev_stop].to_i + hostname = params[:system_hostname] + systems = System.find_id_by_hostname(hostname) + + results = Output.find(:all, + :select => "value, name, unit, revision", + :conditions => [ %(bench_id = ? AND + arg_num = ? AND + set_num = ? AND + ? <= revision AND + revision <= ? AND + system_id IN (?)), + @bench.id, + arg_num, + input_set_num, + rev_start, + rev_stop, + systems ], + :order => "revision") + + title = "#{@project.name}: #{@bench.name} (#{hostname})" + ylabel = "#{results.first.name}(#{results.first.unit})" data = results.collect { |v| v.value.to_f } labels = results.collect { |v| "r#{v.revision}" } - filename = "regression_#{@project.name}_#@bench_name" + filename = "regression_#{@project.name}_#{@bench.name}" Tempfile.open(filename) do |f| File.open(f.path, 'w') do |io| - Grapher.regression(io, - "#{@project.name}: #@bench_name", - "#{results.first.name}(#{results.first.unit})", - data, - labels) + Grapher.regression(io, title, ylabel, data, labels) end send_file(f.path, :disposition => 'inline', Index: web/ranch/app/controllers/benches_controller.rb --- web/ranch/app/controllers/benches_controller.rb (revision 63) +++ web/ranch/app/controllers/benches_controller.rb (working copy) @@ -2,7 +2,7 @@ layout 'benches' - helper :graph, :graph_form + helper :graph, :graph_form, :benches before_filter :list @@ -17,8 +17,10 @@ def regression flash[:error] = nil + @inputs = @bench.input @input_set_num = params[:input_set_num].to_i + @output_arg_num = params[:output_arg_num].to_i if @output_arg_num.zero? @output_arg_nb = Output.find_by_sql "SELECT outputs.arg_num " + @@ -29,6 +31,7 @@ "ORDER BY outputs.arg_num " @output_arg_nb = @output_arg_nb.size end + @systems = System.find_by_sql %( SELECT systems.hostname FROM systems, outputs @@ -36,12 +39,32 @@ AND outputs.bench_id = #{@bench.id} GROUP BY systems.hostname ORDER BY systems.hostname) + @system_hostname = params[:system_hostname] + @system_hostname = @systems.first.hostname if @system_hostname.nil? + if params[:revision].nil? or params[:revision][:range].nil? @revision = {} @revision[:stop], @revision[:start] = default_revision else @revision = get_revision_range(params[:revision][:range]) end + + if flash[:error].nil? + systems = System.find_id_by_hostname(@system_hostname) + @system_changes = Output.find(:all, + :select => "system_id, revision", + :conditions => [ %(bench_id = ? AND + ? <= revision AND + revision <= ? AND + system_id IN (?)), + @bench.id, + @revision[:start], + @revision[:stop], + systems + ], + :order => "revision") + end + end protected @@ -60,11 +83,9 @@ stop_rev, start_rev = default_revision(head_rev) result = { :stop => stop_rev, :start => start_rev } if revision =~ /^(-?\d+)-(-?\d+)$/ - result[:start] = $1 - result[:stop] = $2 - result[:stop] = result[:stop].to_i + result[:start] = $1.to_i + result[:stop] = $2.to_i result[:stop] = head_rev if result[:stop] > head_rev - result[:start] = result[:start].to_i result[:start] = 1 if result[:start] < 1 if result[:start] > result[:stop] flash[:error] = 'Start revision greater than stop revision.' Index: web/ranch/app/views/benches/regression.rhtml --- web/ranch/app/views/benches/regression.rhtml (revision 63) +++ web/ranch/app/views/benches/regression.rhtml (working copy) @@ -54,28 +54,22 @@ <tr> <td>Output:</td> - <td> - <table> - <tr> <td><%= outputs_tag "output_arg_num", @bench.name, @output_arg_num %></td> </tr> - </table> - </td> -</tr> <!-- SYSTEMS --> <tr> <td>System:</td> <td> - <table> - <tr> - <select id="system" name="system"> + <select id="system_hostname" name="system_hostname"> <% for system in @systems do %> - <%= content_tag "option", system.hostname, :value => system.hostname %> + <% option_opt = { :value => system.hostname } + if @system_hostname == system.hostname + option_opt[:selected] = "selected" + end %> + <%= content_tag "option", system.hostname, option_opt %> <% end %> - </tr> - </table> </td> </tr> @@ -93,18 +87,26 @@ <% if flash[:error] %> <p style="color: red;"><%= flash[:error] %></p> <% else %> + + <!-- SYSTEM CHANGE --> + + <%= system_change_tag @system_hostname, @system_changes, + @revision[:start], @revision[:stop] %> + + <!-- GRAPH --> + <% if @output_arg_num.zero? %> <% 1.upto(@output_arg_nb) do |i| %> <p> <%= graph_reg_tag @bench.id, @revision[:start], @revision[:stop], - i, @input_set_num %> + i, @input_set_num, @system_hostname %> </p> <% end %> <% else %> <%= graph_reg_tag @bench.id, @revision[:start], @revision[:stop], - @output_arg_num, @input_set_num %> + @output_arg_num, @input_set_num, @system_hostname %> <% end %> <% end %>