From 32c274d45529a20fb8066797a82d6c28921fe4ea Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 29 Nov 2017 10:39:05 +0100 Subject: [PATCH 1/5] Rename attribute and restructure conditions --- app/controllers/concerns/submission_scoring.rb | 2 +- app/controllers/submissions_controller.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/concerns/submission_scoring.rb b/app/controllers/concerns/submission_scoring.rb index 35de4ba5..f90b16ee 100644 --- a/app/controllers/concerns/submission_scoring.rb +++ b/app/controllers/concerns/submission_scoring.rb @@ -9,7 +9,7 @@ module SubmissionScoring assessment = assessor.assess(output) passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0)) testrun_output = passed ? nil : 'message: ' + output[:message].to_s + "\n stdout: " + output[:stdout].to_s + "\n stderr: " + output[:stderr].to_s - if !testrun_output.blank? + unless testrun_output.blank? submission.exercise.execution_environment.error_templates.each do |template| pattern = Regexp.new(template.signature).freeze if pattern.match(testrun_output) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 73db8c25..2fa518ec 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -203,11 +203,11 @@ class SubmissionsController < ApplicationController end def extract_errors - if !@message_buffer.blank? + unless @run_output.blank? @submission.exercise.execution_environment.error_templates.each do |template| pattern = Regexp.new(template.signature).freeze - if pattern.match(@message_buffer) - StructuredError.create_from_template(template, @message_buffer) + if pattern.match(@run_output) + StructuredError.create_from_template(template, @run_output) end end end From e51865c5619ea2e502339ff105baa817e7b55249 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Mon, 29 Jan 2018 16:18:40 +0100 Subject: [PATCH 2/5] Lint --- app/controllers/submissions_controller.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 2fa518ec..55eec4e6 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -216,7 +216,7 @@ class SubmissionsController < ApplicationController def handle_message(message, tubesock, container) @run_output ||= "" # Handle special commands first - if (/^#exit/.match(message)) + if /^#exit/.match(message) # Just call exit_container on the docker_client. # Do not call kill_socket for the websocket to the client here. # @docker_client.exit_container closes the socket to the container, @@ -228,17 +228,17 @@ class SubmissionsController < ApplicationController # Filter out information about run_command, test_command, user or working directory run_command = @submission.execution_environment.run_command % command_substitutions(params[:filename]) test_command = @submission.execution_environment.test_command % command_substitutions(params[:filename]) - if !(/root|workspace|#{run_command}|#{test_command}/.match(message)) + unless /root|workspace|#{run_command}|#{test_command}/.match(message) parse_message(message, 'stdout', tubesock) end end end def parse_message(message, output_stream, socket, recursive = true) - parsed = ''; + parsed = '' begin parsed = JSON.parse(message) - if(parsed.class == Hash && parsed.key?('cmd')) + if parsed.class == Hash and parsed.key?('cmd') socket.send_data message Rails.logger.info('parse_message sent: ' + message) else @@ -248,24 +248,24 @@ class SubmissionsController < ApplicationController end rescue JSON::ParserError => e # Check wether the message contains multiple lines, if true try to parse each line - if ((recursive == true) && (message.include? "\n")) + if recursive and message.include? "\n" for part in message.split("\n") self.parse_message(part,output_stream,socket,false) end - elsif(message.include? "")) + elsif @buffering and message.include? '/>' @buffer += message parsed = {'cmd'=>'write','stream'=>output_stream,'data'=>@buffer} socket.send_data JSON.dump(parsed) #socket.send_data @buffer @buffering = false #Rails.logger.info('Sent complete buffer') - elsif(@buffering) + elsif @buffering @buffer += message #Rails.logger.info('Appending to buffer') else @@ -281,7 +281,7 @@ class SubmissionsController < ApplicationController end def save_run_output - if !@run_output.blank? + unless @run_output.blank? @run_output = @run_output[(0..max_run_output_buffer_size-1)] # trim the string to max_message_buffer_size chars Testrun.create(file: @file, cause: 'run', submission: @submission, output: @run_output) end From f172f168db3e4390485c18cc377c4e8bba9978b3 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Tue, 30 Jan 2018 11:06:17 +0100 Subject: [PATCH 3/5] Refactor structured error attribute creation --- app/models/structured_error_attribute.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/structured_error_attribute.rb b/app/models/structured_error_attribute.rb index 6eb17fc4..65bda05e 100644 --- a/app/models/structured_error_attribute.rb +++ b/app/models/structured_error_attribute.rb @@ -3,15 +3,13 @@ class StructuredErrorAttribute < ActiveRecord::Base belongs_to :error_template_attribute def self.create_from_template(attribute, structured_error, message_buffer) - match = false value = nil result = message_buffer.match(attribute.regex) if result != nil - match = true if result.captures.size > 0 value = result.captures[0] end end - self.create(structured_error: structured_error, error_template_attribute: attribute, value: value, match: match) + self.create(structured_error: structured_error, error_template_attribute: attribute, value: value, match: result != nil) end end From 7768d342759450b73fefe7ca5d43f58af3a9f596 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Tue, 30 Jan 2018 11:08:00 +0100 Subject: [PATCH 4/5] Fix error detection in run output --- app/controllers/submissions_controller.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 55eec4e6..0b05f687 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -203,18 +203,19 @@ class SubmissionsController < ApplicationController end def extract_errors - unless @run_output.blank? + unless @raw_output.blank? @submission.exercise.execution_environment.error_templates.each do |template| pattern = Regexp.new(template.signature).freeze - if pattern.match(@run_output) - StructuredError.create_from_template(template, @run_output) + if pattern.match(@raw_output) + StructuredError.create_from_template(template, @raw_output) end end end end def handle_message(message, tubesock, container) - @run_output ||= "" + @raw_output ||= '' + @run_output ||= '' # Handle special commands first if /^#exit/.match(message) # Just call exit_container on the docker_client. @@ -275,6 +276,7 @@ class SubmissionsController < ApplicationController Rails.logger.info('parse_message sent: ' + JSON.dump(parsed)) end ensure + @raw_output += parsed['data'] if parsed.class == Hash and parsed.key? 'data' # save the data that was send to the run_output if there is enough space left. this will be persisted as a testrun with cause "run" @run_output += JSON.dump(parsed) if @run_output.size <= max_run_output_buffer_size end From 40fe5c4e69c595dc490974f5c24d643fab22b95b Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Tue, 30 Jan 2018 11:28:29 +0100 Subject: [PATCH 5/5] Save submission alongside structured error --- app/controllers/submissions_controller.rb | 22 +++++++++---------- app/models/structured_error.rb | 5 +++-- app/models/submission.rb | 1 + ...645_add_submission_to_structured_errors.rb | 5 +++++ db/schema.rb | 5 ++++- 5 files changed, 24 insertions(+), 14 deletions(-) create mode 100644 db/migrate/20180130101645_add_submission_to_structured_errors.rb diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 0b05f687..3e24af1c 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -202,17 +202,6 @@ class SubmissionsController < ApplicationController tubesock.close end - def extract_errors - unless @raw_output.blank? - @submission.exercise.execution_environment.error_templates.each do |template| - pattern = Regexp.new(template.signature).freeze - if pattern.match(@raw_output) - StructuredError.create_from_template(template, @raw_output) - end - end - end - end - def handle_message(message, tubesock, container) @raw_output ||= '' @run_output ||= '' @@ -289,6 +278,17 @@ class SubmissionsController < ApplicationController end end + def extract_errors + unless @raw_output.blank? + @submission.exercise.execution_environment.error_templates.each do |template| + pattern = Regexp.new(template.signature).freeze + if pattern.match(@raw_output) + StructuredError.create_from_template(template, @raw_output, @submission) + end + end + end + end + def score hijack do |tubesock| Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? diff --git a/app/models/structured_error.rb b/app/models/structured_error.rb index 2f03ec54..c1f6669c 100644 --- a/app/models/structured_error.rb +++ b/app/models/structured_error.rb @@ -1,9 +1,10 @@ class StructuredError < ActiveRecord::Base belongs_to :error_template + belongs_to :submission belongs_to :file, class_name: 'CodeOcean::File' - def self.create_from_template(template, message_buffer) - instance = self.create(error_template: template) + def self.create_from_template(template, message_buffer, submission) + instance = self.create(error_template: template, submission: submission) template.error_template_attributes.each do |attribute| StructuredErrorAttribute.create_from_template(attribute, instance, message_buffer) end diff --git a/app/models/submission.rb b/app/models/submission.rb index d75d6019..c27d01bd 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -8,6 +8,7 @@ class Submission < ActiveRecord::Base belongs_to :exercise has_many :testruns + has_many :structured_errors has_many :comments, through: :files delegate :execution_environment, to: :exercise diff --git a/db/migrate/20180130101645_add_submission_to_structured_errors.rb b/db/migrate/20180130101645_add_submission_to_structured_errors.rb new file mode 100644 index 00000000..3f7d2a5e --- /dev/null +++ b/db/migrate/20180130101645_add_submission_to_structured_errors.rb @@ -0,0 +1,5 @@ +class AddSubmissionToStructuredErrors < ActiveRecord::Migration + def change + add_reference :structured_errors, :submission, index: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 3ed07240..9ab33939 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171120153705) do +ActiveRecord::Schema.define(version: 20180130101645) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -305,8 +305,11 @@ ActiveRecord::Schema.define(version: 20171120153705) do t.integer "file_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "submission_id" end + add_index "structured_errors", ["submission_id"], name: "index_structured_errors_on_submission_id", using: :btree + create_table "submissions", force: :cascade do |t| t.integer "exercise_id" t.float "score"