Fix execution of code via Ajax.

Add output message for program runs without any output
This commit is contained in:
Sebastian Serth
2018-12-13 13:55:45 +01:00
parent d45a68a123
commit 4a1cd3037c
5 changed files with 18 additions and 10 deletions

View File

@ -122,7 +122,7 @@ class SubmissionsController < ApplicationController
def run def run
# TODO reimplement SSEs with websocket commands # TODO reimplement SSEs with websocket commands
# with_server_sent_events do |server_sent_event| # with_server_sent_events do |server_sent_event|
# output = @docker_client.execute_run_command(@submission, params[:filename]) # output = @docker_client.execute_run_command(@submission, sanitize_filename)
# server_sent_event.write({stdout: output[:stdout]}, event: 'output') if output[:stdout] # server_sent_event.write({stdout: output[:stdout]}, event: 'output') if output[:stdout]
# server_sent_event.write({stderr: output[:stderr]}, event: 'output') if output[:stderr] # server_sent_event.write({stderr: output[:stderr]}, event: 'output') if output[:stderr]
@ -147,7 +147,7 @@ class SubmissionsController < ApplicationController
# give the docker_client the tubesock object, so that it can send messages (timeout) # give the docker_client the tubesock object, so that it can send messages (timeout)
@docker_client.tubesock = tubesock @docker_client.tubesock = tubesock
result = @docker_client.execute_run_command(@submission, params[:filename]) result = @docker_client.execute_run_command(@submission, sanitize_filename)
tubesock.send_data JSON.dump({'cmd' => 'status', 'status' => result[:status]}) tubesock.send_data JSON.dump({'cmd' => 'status', 'status' => result[:status]})
if result[:status] == :container_running if result[:status] == :container_running
@ -200,6 +200,10 @@ class SubmissionsController < ApplicationController
# save the output of this "run" as a "testrun" (scoring runs are saved in submission_scoring.rb) # save the output of this "run" as a "testrun" (scoring runs are saved in submission_scoring.rb)
save_run_output save_run_output
if @run_output.blank?
parse_message t('exercises.implement.no_output', timestamp: l(Time.now, format: :short)), 'stdout', tubesock
end
# Hijacked connection needs to be notified correctly # Hijacked connection needs to be notified correctly
tubesock.send_data JSON.dump({'cmd' => 'exit'}) tubesock.send_data JSON.dump({'cmd' => 'exit'})
tubesock.close tubesock.close
@ -219,8 +223,8 @@ class SubmissionsController < ApplicationController
@run_output = 'timeout: ' + @run_output # add information that this run timed out to the buffer @run_output = 'timeout: ' + @run_output # add information that this run timed out to the buffer
else else
# Filter out information about run_command, test_command, user or working directory # Filter out information about run_command, test_command, user or working directory
run_command = @submission.execution_environment.run_command % command_substitutions(params[:filename]) run_command = @submission.execution_environment.run_command % command_substitutions(sanitize_filename)
test_command = @submission.execution_environment.test_command % command_substitutions(params[:filename]) test_command = @submission.execution_environment.test_command % command_substitutions(sanitize_filename)
unless /root|workspace|#{run_command}|#{test_command}/.match(message) unless /root|workspace|#{run_command}|#{test_command}/.match(message)
parse_message(message, 'stdout', tubesock) parse_message(message, 'stdout', tubesock)
end end
@ -331,7 +335,7 @@ class SubmissionsController < ApplicationController
private :set_docker_client private :set_docker_client
def set_file def set_file
@file = @files.detect { |file| file.name_with_extension == params[:filename] } @file = @files.detect { |file| file.name_with_extension == sanitize_filename }
head :not_found unless @file head :not_found unless @file
end end
private :set_file private :set_file
@ -372,7 +376,7 @@ class SubmissionsController < ApplicationController
hijack do |tubesock| hijack do |tubesock|
Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive?
output = @docker_client.execute_test_command(@submission, params[:filename]) output = @docker_client.execute_test_command(@submission, sanitize_filename)
# tubesock is the socket to the client # tubesock is the socket to the client
tubesock.send_data JSON.dump(output) tubesock.send_data JSON.dump(output)
@ -416,4 +420,8 @@ class SubmissionsController < ApplicationController
end end
path path
end end
def sanitize_filename
params[:filename].gsub(/\.json$/, '')
end
end end

View File

@ -4,5 +4,5 @@ h1 = @execution_environment
.form-group .form-group
label for='command' = t('.command') label for='command' = t('.command')
input#command.form-control type='text' input#command.form-control type='text'
pre#output data-message-no-output=t('exercises.implement.no_output') pre#output data-message-no-output=t('exercises.implement.no_output', timestamp: l(Time.now, format: :short))
p = t('exercises.implement.no_output_yet') p = t('exercises.implement.no_output_yet')

View File

@ -1,6 +1,6 @@
div id='output_sidebar_collapsed' div id='output_sidebar_collapsed'
= render('editor_button', classes: 'btn-block btn-primary btn', data: {:'data-toggle' => 'tooltip', :'data-placement' => 'left'}, title: t('exercises.editor.expand_output_sidebar'), icon: 'fa fa-plus-square', id: 'toggle-sidebar-output-collapsed', label: '') = render('editor_button', classes: 'btn-block btn-primary btn', data: {:'data-toggle' => 'tooltip', :'data-placement' => 'left'}, title: t('exercises.editor.expand_output_sidebar'), icon: 'fa fa-plus-square', id: 'toggle-sidebar-output-collapsed', label: '')
div.h-100 id='output_sidebar_uncollapsed' class='d-none col-sm-12 enforce-bottom-margin' data-message-no-output=t('exercises.implement.no_output') div.h-100 id='output_sidebar_uncollapsed' class='d-none col-sm-12 enforce-bottom-margin' data-message-no-output=t('exercises.implement.no_output_yet')
.row .row
= render('editor_button', classes: 'btn-block btn-primary btn', icon: 'fa fa-minus-square', id: 'toggle-sidebar-output', label: t('exercises.editor.collapse_output_sidebar')) = render('editor_button', classes: 'btn-block btn-primary btn', icon: 'fa fa-minus-square', id: 'toggle-sidebar-output', label: t('exercises.editor.collapse_output_sidebar'))

View File

@ -300,7 +300,7 @@ de:
file: 'Test-Datei <span class="number">%{number}</span> (<span class="filename">%{filename}</span>)' file: 'Test-Datei <span class="number">%{number}</span> (<span class="filename">%{filename}</span>)'
hint: Tipp hint: Tipp
no_files: Die Aufgabe umfasst noch keine sichtbaren Dateien. no_files: Die Aufgabe umfasst noch keine sichtbaren Dateien.
no_output: Die letzte Code-Ausführung hat keine Ausgabe erzeugt. no_output: Die letzte Code-Ausführung terminierte am %{timestamp} ohne Ausgabe.
no_output_yet: Bisher existiert noch keine Ausgabe. no_output_yet: Bisher existiert noch keine Ausgabe.
output: Programm-Ausgabe output: Programm-Ausgabe
passed_tests: Erfolgreiche Tests passed_tests: Erfolgreiche Tests

View File

@ -300,7 +300,7 @@ en:
file: 'Test File <span class="number">%{number}</span> (<span class="filename">%{filename}</span>)' file: 'Test File <span class="number">%{number}</span> (<span class="filename">%{filename}</span>)'
hint: Hint hint: Hint
no_files: The exercise does not comprise visible files yet. no_files: The exercise does not comprise visible files yet.
no_output: The last code run has not generated any output. no_output: The last code run finished on %{timestamp} without any output.
no_output_yet: There is no output yet. no_output_yet: There is no output yet.
output: Program Output output: Program Output
passed_tests: Passed Tests passed_tests: Passed Tests