From d9d3dc42d4a0902ae628c047f1af99eb7192472b Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Thu, 9 Aug 2018 15:14:52 +0200 Subject: [PATCH 01/66] remove all A/B testing code no longer in use. --- app/controllers/exercises_controller.rb | 27 +----- app/helpers/request_for_comments_helper.rb | 2 - app/models/proxy_exercise.rb | 85 ++++++------------- app/models/submission.rb | 6 +- .../request_for_comments/index.html.slim | 3 +- lib/user_group_separator.rb | 48 ----------- 6 files changed, 30 insertions(+), 141 deletions(-) delete mode 100644 app/helpers/request_for_comments_helper.rb delete mode 100644 lib/user_group_separator.rb diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 8855228e..37b43813 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -184,28 +184,8 @@ class ExercisesController < ApplicationController count_interventions_today = UserExerciseIntervention.where(user: current_user).where("created_at >= ?", Time.zone.now.beginning_of_day).count user_got_intervention_in_exercise = UserExerciseIntervention.where(user: current_user, exercise: @exercise).size >= max_intervention_count_per_exercise user_got_enough_interventions = count_interventions_today >= max_intervention_count_per_day or user_got_intervention_in_exercise - @is_experimental_course = @course_token and experimental_course?(@course_token) - - @experiment_group = UserGroupSeparator.getInterventionGroup(current_user) - - showInterventions = (@is_experimental_course and not user_solved_exercise and not user_got_enough_interventions) ? "true" : "false" - - case @experiment_group - when :rfc_intervention_stale_rfc - @show_rfc_interventions = showInterventions - when :break_intervention_stale_rfc - @show_break_interventions = showInterventions - when :no_intervention_stale_rfc - when :no_intervention_hide_rfc - @hide_rfc_button = "true" - when :break_intervention_show_rfc - @show_break_interventions = showInterventions - when :no_intervention_show_rfc - when :rfc_intervention_show_rfc - @show_rfc_interventions = showInterventions - end - + @show_rfc_interventions = (not user_solved_exercise and not user_got_enough_interventions) ? "true" : "false" @search = Search.new @@ -426,11 +406,6 @@ class ExercisesController < ApplicationController return end - if @is_experimental_course and (@rfc_group == :hide_rfc) - redirect_to_lti_return_path - return - end - rfc = @submission.own_unsolved_rfc if rfc # set a message that informs the user that his own RFC should be closed. diff --git a/app/helpers/request_for_comments_helper.rb b/app/helpers/request_for_comments_helper.rb deleted file mode 100644 index f46a73e4..00000000 --- a/app/helpers/request_for_comments_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module RequestForCommentsHelper -end diff --git a/app/models/proxy_exercise.rb b/app/models/proxy_exercise.rb index c6da3870..461b5b67 100644 --- a/app/models/proxy_exercise.rb +++ b/app/models/proxy_exercise.rb @@ -37,30 +37,14 @@ class ProxyExercise < ActiveRecord::Base assigned_user_proxy_exercise.exercise else matching_exercise = - if (token.eql? "e85689d5") - Rails.logger.debug("Proxy exercise with token e85689d5, split user in groups..") - group = UserGroupSeparator.getGroupExerciseDescriptionTesting(user) - Rails.logger.debug("user assigned to group #{group}") - case group - when :group_a - exercises.where(id: 557).first - when :group_b - exercises.where(id: 558).first - when :group_c - exercises.where(id: 559).first - when :group_d - exercises.where(id: 560).first - end - else - Rails.logger.debug("find new matching exercise for user #{user.id}" ) - begin - find_matching_exercise(user) - rescue => e #fallback - Rails.logger.error("finding matching exercise failed. Fall back to random exercise! Error: #{$!}" ) - @reason[:reason] = "fallback because of error" - @reason[:error] = "#{$!}:\n\t#{e.backtrace.join("\n\t")}" - exercises.where("expected_difficulty > 1").shuffle.first # difficulty should be > 1 to prevent dummy exercise from being chosen. - end + Rails.logger.debug("find new matching exercise for user #{user.id}" ) + begin + find_matching_exercise(user) + rescue => e #fallback + Rails.logger.error("finding matching exercise failed. Fall back to random exercise! Error: #{$!}" ) + @reason[:reason] = "fallback because of error" + @reason[:error] = "#{$!}:\n\t#{e.backtrace.join("\n\t")}" + exercises.where("expected_difficulty > 1").shuffle.first # difficulty should be > 1 to prevent dummy exercise from being chosen. end user.user_proxy_exercise_exercises << UserProxyExerciseExercise.create(user: user, exercise: matching_exercise, proxy_exercise: self, reason: @reason.to_json) matching_exercise @@ -69,42 +53,27 @@ class ProxyExercise < ActiveRecord::Base end def find_matching_exercise(user) - user_group = UserGroupSeparator.getProxyExerciseGroup(user) - case user_group - when :dummy_assigment - rec_ex = select_easiest_exercise(exercises) - @reason[:reason] = "dummy group" - Rails.logger.debug("assigned user to dummy group, and gave him exercise: #{rec_ex.title}") - rec_ex - when :random_assigment - @reason[:reason] = "random group" - ex = exercises.where("expected_difficulty > 1").shuffle.first - Rails.logger.debug("assigned user to random group, and gave him exercise: #{ex.title}") - ex - when :recommended_assignment - exercises_user_has_accessed = user.submissions.where("cause IN ('submit','assess')").map{|s| s.exercise}.uniq.compact - tags_user_has_seen = exercises_user_has_accessed.map{|ex| ex.tags}.uniq.flatten - Rails.logger.debug("exercises_user_has_accessed #{exercises_user_has_accessed.map{|e|e.id}.join(",")}") + exercises_user_has_accessed = user.submissions.where("cause IN ('submit','assess')").map{|s| s.exercise}.uniq.compact + tags_user_has_seen = exercises_user_has_accessed.map{|ex| ex.tags}.uniq.flatten + Rails.logger.debug("exercises_user_has_accessed #{exercises_user_has_accessed.map{|e|e.id}.join(",")}") - # find exercises - potential_recommended_exercises = [] - exercises.where("expected_difficulty >= 1").each do |ex| - ## find exercises which have only tags the user has already seen - if (ex.tags - tags_user_has_seen).empty? - potential_recommended_exercises << ex - end + # find exercises + potential_recommended_exercises = [] + exercises.where("expected_difficulty >= 1").each do |ex| + ## find exercises which have only tags the user has already seen + if (ex.tags - tags_user_has_seen).empty? + potential_recommended_exercises << ex end - Rails.logger.debug("potential_recommended_exercises: #{potential_recommended_exercises.map{|e|e.id}}") - # if all exercises contain tags which the user has never seen, recommend easiest exercise - if potential_recommended_exercises.empty? - Rails.logger.debug("matched easiest exercise in pool") - @reason[:reason] = "easiest exercise in pool. empty potential exercises" - select_easiest_exercise(exercises) - else - select_best_matching_exercise(user, exercises_user_has_accessed, potential_recommended_exercises) - end - end - + end + Rails.logger.debug("potential_recommended_exercises: #{potential_recommended_exercises.map{|e|e.id}}") + # if all exercises contain tags which the user has never seen, recommend easiest exercise + if potential_recommended_exercises.empty? + Rails.logger.debug("matched easiest exercise in pool") + @reason[:reason] = "easiest exercise in pool. empty potential exercises" + select_easiest_exercise(exercises) + else + select_best_matching_exercise(user, exercises_user_has_accessed, potential_recommended_exercises) + end end private :find_matching_exercise diff --git a/app/models/submission.rb b/app/models/submission.rb index 763e1366..c27d01bd 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -66,10 +66,6 @@ class Submission < ActiveRecord::Base end def unsolved_rfc - # old query - # RequestForComment.unsolved.where(exercise_id: exercise).where.not(question: nil).order("RANDOM()").find { | rfc_element |(rfc_element.comments_count < MAX_COMMENTS_ON_RECOMMENDED_RFC) } - - # experimental query: - RequestForComment.unsolved.joins('JOIN exercise_collection_items eci ON eci.exercise_id = request_for_comments.exercise_id').where('eci.exercise_collection_id != 3 OR user_id%10 > 3').where(exercise_id: exercise).where.not(question: nil).order("RANDOM()").find { | rfc_element |(rfc_element.comments_count < MAX_COMMENTS_ON_RECOMMENDED_RFC) } + RequestForComment.unsolved.where(exercise_id: exercise).where.not(question: nil).order("RANDOM()").find { | rfc_element |(rfc_element.comments_count < MAX_COMMENTS_ON_RECOMMENDED_RFC) } end end diff --git a/app/views/request_for_comments/index.html.slim b/app/views/request_for_comments/index.html.slim index d253f0ab..aa7ea033 100644 --- a/app/views/request_for_comments/index.html.slim +++ b/app/views/request_for_comments/index.html.slim @@ -23,8 +23,7 @@ h1 = RequestForComment.model_name.human(count: 2) th = t('activerecord.attributes.request_for_comments.last_update') tbody - @request_for_comments.each do |request_for_comment| - - do_not_answer = [:rfc_intervention_stale_rfc, :break_intervention_stale_rfc, :no_intervention_stale_rfc].include?(UserGroupSeparator.getInterventionGroup(request_for_comment.user)) and current_user.internal_user? - tr data-id=request_for_comment.id class=('do-not-answer' if do_not_answer) + tr data-id=request_for_comment.id - if request_for_comment.solved? td span class="fa fa-check" aria-hidden="true" diff --git a/lib/user_group_separator.rb b/lib/user_group_separator.rb deleted file mode 100644 index 2333b686..00000000 --- a/lib/user_group_separator.rb +++ /dev/null @@ -1,48 +0,0 @@ -class UserGroupSeparator - - # seperates user into 20% no intervention, 20% break intervention, 60% rfc intervention - def self.getInterventionGroup(user) - lastDigitId = user.id % 10 - if lastDigitId < 1 # 0 - :rfc_intervention_stale_rfc - elsif lastDigitId < 2 # 1 - :break_intervention_stale_rfc - elsif lastDigitId < 3 # 2 - :no_intervention_stale_rfc - elsif lastDigitId < 4 # 3 - :no_intervention_hide_rfc - elsif lastDigitId < 5 # 4 - :break_intervention_show_rfc - elsif lastDigitId < 6 # 5 - :no_intervention_show_rfc - else # 6,7,8,9 - :rfc_intervention_show_rfc - end - end - - # seperates user into 20% dummy assignment, 20% random assignemnt, 60% recommended assignment - def self.getProxyExerciseGroup(user) - lastDigitCreatedAt = user.created_at.to_i % 10 - if lastDigitCreatedAt < 2 # 0,1 - :dummy_assigment - elsif lastDigitCreatedAt < 4 # 2,3 - :random_assigment - else # 4,5,6,7,8,9 - :recommended_assignment - end - end - - def self.getGroupExerciseDescriptionTesting(user) - groupById = user.id % 4 - if groupById == 0 - :group_a - elsif groupById == 1 - :group_b - elsif groupById == 2 - :group_c - else # 3 - :group_d - end - end - -end \ No newline at end of file From 5a90d20e5482b50bad168a9a6ed8e400a67c3c67 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Thu, 9 Aug 2018 15:26:39 +0200 Subject: [PATCH 02/66] prevent RFC with empty questions from being picked --- app/models/submission.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/submission.rb b/app/models/submission.rb index c27d01bd..6a41eda9 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -66,6 +66,6 @@ class Submission < ActiveRecord::Base end def unsolved_rfc - RequestForComment.unsolved.where(exercise_id: exercise).where.not(question: nil).order("RANDOM()").find { | rfc_element |(rfc_element.comments_count < MAX_COMMENTS_ON_RECOMMENDED_RFC) } + RequestForComment.unsolved.where(exercise_id: exercise).where.not(question: nil).order("RANDOM()").find { | rfc_element |( (rfc_element.comments_count < MAX_COMMENTS_ON_RECOMMENDED_RFC) && (!rfc_element.question.empty?)) } end end From 400eef3118162495a7c5a53ced366ae851af52d6 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 15 Aug 2018 15:43:37 +0200 Subject: [PATCH 03/66] move logging statement up to be sure that its result is not assigned to matching_exercise if an error might be thrown. --- app/models/proxy_exercise.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/proxy_exercise.rb b/app/models/proxy_exercise.rb index 461b5b67..cd187eb2 100644 --- a/app/models/proxy_exercise.rb +++ b/app/models/proxy_exercise.rb @@ -36,8 +36,8 @@ class ProxyExercise < ActiveRecord::Base Rails.logger.debug("retrieved assigned exercise for user #{user.id}: Exercise #{assigned_user_proxy_exercise.exercise}" ) assigned_user_proxy_exercise.exercise else + Rails.logger.debug("find new matching exercise for user #{user.id}" ) matching_exercise = - Rails.logger.debug("find new matching exercise for user #{user.id}" ) begin find_matching_exercise(user) rescue => e #fallback From c1bcc0c95c1b4619c017df0c89c4ba7f79a8ca61 Mon Sep 17 00:00:00 2001 From: rteusner Date: Mon, 24 Sep 2018 17:04:32 +0200 Subject: [PATCH 04/66] Update exercises_controller.rb ? "true" : "false" --> .to_s --- app/controllers/exercises_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 37b43813..b6634260 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -185,7 +185,7 @@ class ExercisesController < ApplicationController user_got_intervention_in_exercise = UserExerciseIntervention.where(user: current_user, exercise: @exercise).size >= max_intervention_count_per_exercise user_got_enough_interventions = count_interventions_today >= max_intervention_count_per_day or user_got_intervention_in_exercise - @show_rfc_interventions = (not user_solved_exercise and not user_got_enough_interventions) ? "true" : "false" + @show_rfc_interventions = (not user_solved_exercise and not user_got_enough_interventions).to_s @search = Search.new From 4e6d7f8b8a413da27064b7db2849b9a959b0e138 Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Sun, 30 Sep 2018 00:39:56 +0200 Subject: [PATCH 05/66] Order files by name by default Explicit ordering in the view (!) is now no longer necessary. --- app/models/code_ocean/file.rb | 2 ++ app/views/exercises/show.html.slim | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/code_ocean/file.rb b/app/models/code_ocean/file.rb index 22c6e877..9ae40b19 100644 --- a/app/models/code_ocean/file.rb +++ b/app/models/code_ocean/file.rb @@ -47,6 +47,8 @@ module CodeOcean scope :"#{role}s", -> { where(role: role) } end + default_scope { order(name: :asc) } + validates :feedback_message, if: :teacher_defined_test?, presence: true validates :feedback_message, absence: true, unless: :teacher_defined_test? validates :file_type_id, presence: true diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim index e3dfc7d5..c2e8dd5b 100644 --- a/app/views/exercises/show.html.slim +++ b/app/views/exercises/show.html.slim @@ -25,7 +25,7 @@ h1 h2 = t('activerecord.attributes.exercise.files') ul.list-unstyled.panel-group#files - - @exercise.files.order('name').each do |file| + - @exercise.files.each do |file| li.panel.panel-default .panel-heading role="tab" id="heading" a.file-heading data-toggle="collapse" data-parent="#files" href=".collapse#{file.id}" From 88f4189651b374c84da1c1f9b635cb4dcf183a12 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Fri, 5 Oct 2018 15:18:01 +0200 Subject: [PATCH 06/66] Remove broken badge --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 65d36819..7df97f26 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ Code Ocean [![Build Status](https://travis-ci.org/openHPI/codeocean.svg?branch=master)](https://travis-ci.org/openHPI/codeocean) [![Code Climate](https://codeclimate.com/github/openHPI/codeocean/badges/gpa.svg)](https://codeclimate.com/github/openHPI/codeocean) [![Test Coverage](https://codeclimate.com/github/openHPI/codeocean/badges/coverage.svg)](https://codeclimate.com/github/openHPI/codeocean) -[![Dependency Status](https://gemnasium.com/openHPI/codeocean.svg)](https://gemnasium.com/openHPI/codeocean) ## Development Setup From 2bb5ea138c49cdc777a9316c40d7945d83491b7e Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 10 Oct 2018 13:41:05 +0200 Subject: [PATCH 07/66] Display branch and commit info in dashboard --- app/views/admin/dashboard/show.html.slim | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/views/admin/dashboard/show.html.slim b/app/views/admin/dashboard/show.html.slim index 805f7819..c09c7f82 100644 --- a/app/views/admin/dashboard/show.html.slim +++ b/app/views/admin/dashboard/show.html.slim @@ -4,6 +4,15 @@ h1 = t('breadcrumbs.dashboard.show') +h2 Version + +div + = "Branch:" + pre = `git rev-parse --abbrev-ref HEAD` +div + = "Commit:" + pre = `git log -n 1 --pretty` + h2 Docker - if DockerContainerPool.config[:active] From 131f6101168c9da990cba06f61e470398d448803 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 16 Oct 2018 17:20:58 +0200 Subject: [PATCH 08/66] call text() again to prevent execution of javascript --- app/assets/javascripts/editor/evaluation.js.erb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/editor/evaluation.js.erb b/app/assets/javascripts/editor/evaluation.js.erb index 19f57ce3..feced0eb 100644 --- a/app/assets/javascripts/editor/evaluation.js.erb +++ b/app/assets/javascripts/editor/evaluation.js.erb @@ -152,23 +152,23 @@ CodeOceanEditorEvaluation = { var element = this.findOrCreateOutputElement(index); if (!colorize) { if (output.stdout != undefined && output.stdout != '') { - element.append(output.stdout) - //element.text(element.text() + output.stdout) + //element.append(output.stdout) + element.text(element.text() + output.stdout) } if (output.stderr != undefined && output.stderr != '') { - element.append('StdErr: ' + output.stderr); - //element.text('StdErr: ' + element.text() + output.stderr); + //element.append('StdErr: ' + output.stderr); + element.text('StdErr: ' + element.text() + output.stderr); } } else if (output.stderr) { - element.addClass('text-warning').append(output.stderr); - //element.addClass('text-warning').text(element.text() + output.stderr); + //element.addClass('text-warning').append(output.stderr); + element.addClass('text-warning').text(element.text() + output.stderr); this.flowrOutputBuffer += output.stderr; this.QaApiOutputBuffer.stderr += output.stderr; } else if (output.stdout) { - element.addClass('text-success').append(output.stdout); - //element.addClass('text-success').text(element.text() + output.stdout); + //element.addClass('text-success').append(output.stdout); + element.addClass('text-success').text(element.text() + output.stdout); this.flowrOutputBuffer += output.stdout; this.QaApiOutputBuffer.stdout += output.stdout; } else { From ab30e0c9a9483b39a2365d7064ad61af55278b5d Mon Sep 17 00:00:00 2001 From: Jochen Staerk Date: Tue, 16 Oct 2018 21:45:20 +0200 Subject: [PATCH 09/66] Update LOCAL_SETUP.md rails server will not be bridged to host unless listening on 0.0.0.0. There were no errors when deployed on vagrant/virtualbox on mac, nevertheless the password "admin" would still not work :-( --- LOCAL_SETUP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LOCAL_SETUP.md b/LOCAL_SETUP.md index 402ad33f..dbe5876c 100644 --- a/LOCAL_SETUP.md +++ b/LOCAL_SETUP.md @@ -59,7 +59,7 @@ All problems that have occurred resulted from a more restrictive rights manageme ### Start server vagrant ssh cd /vagrant -rails s -p 3000 +rails s -p 3000 -b 0.0.0.0 ### Login to CodeOcean 192.168.59.104:3000 From db9557108ceb69de5fec90a632c4c3b8e2c103f9 Mon Sep 17 00:00:00 2001 From: Jan Graichen Date: Thu, 18 Oct 2018 21:03:46 +0200 Subject: [PATCH 10/66] Fix missing dot Actually call replace on the filename. --- app/assets/javascripts/editor/submissions.js.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/editor/submissions.js.erb b/app/assets/javascripts/editor/submissions.js.erb index 21250f7e..a111a77f 100644 --- a/app/assets/javascripts/editor/submissions.js.erb +++ b/app/assets/javascripts/editor/submissions.js.erb @@ -174,7 +174,7 @@ CodeOceanEditorSubmissions = { this.createSubmission('#test', null, function(response) { this.showSpinner($('#test')); $('#score_div').addClass('hidden'); - var url = response.test_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filenamereplace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor + var url = response.test_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor this.initializeSocketForTesting(url); }.bind(this)); } From 629c925e77203b8e4270a9c2feb3166a68f76d72 Mon Sep 17 00:00:00 2001 From: Jan Graichen Date: Fri, 19 Oct 2018 12:34:12 +0200 Subject: [PATCH 11/66] Fix setting active file in editor The file select hook did construct an active_file but did not assign it to the actual variables. This commit changes the hook to use the existing setActiveFile helper function. --- app/assets/javascripts/editor/editor.js.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/editor/editor.js.erb b/app/assets/javascripts/editor/editor.js.erb index 1e254dd3..0ff03915 100644 --- a/app/assets/javascripts/editor/editor.js.erb +++ b/app/assets/javascripts/editor/editor.js.erb @@ -269,11 +269,11 @@ configureEditors: function () { initializeFileTree: function () { $('#files').jstree($('#files').data('entries')); $('#files').on('click', 'li.jstree-leaf', function (event) { - active_file = { + this.setActiveFile( filename: $(event.target).parent().text(), id: parseInt($(event.target).parent().attr('id')) - }; - var frame = $('[data-file-id="' + active_file.id + '"]').parent(); + ); + var frame = $('[data-file-id="' + this.active_file.id + '"]').parent(); this.showFrame(frame); this.toggleButtonStates(); }.bind(this)); From 730d5541bda70a35a1c10f09a1b693536c05a9de Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Fri, 19 Oct 2018 15:25:05 +0200 Subject: [PATCH 12/66] allow running, testing and scoring of files in subfolders by using the full filepath --- app/assets/javascripts/editor/editor.js.erb | 4 ++-- app/assets/javascripts/editor/execution.js.erb | 5 +++-- app/models/code_ocean/file.rb | 8 ++++++++ lib/docker_client.rb | 12 +++++++++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/editor/editor.js.erb b/app/assets/javascripts/editor/editor.js.erb index 0ff03915..6bb6dc27 100644 --- a/app/assets/javascripts/editor/editor.js.erb +++ b/app/assets/javascripts/editor/editor.js.erb @@ -270,8 +270,8 @@ configureEditors: function () { $('#files').jstree($('#files').data('entries')); $('#files').on('click', 'li.jstree-leaf', function (event) { this.setActiveFile( - filename: $(event.target).parent().text(), - id: parseInt($(event.target).parent().attr('id')) + $(event.target).parent().text(), + parseInt($(event.target).parent().attr('id')) ); var frame = $('[data-file-id="' + this.active_file.id + '"]').parent(); this.showFrame(frame); diff --git a/app/assets/javascripts/editor/execution.js.erb b/app/assets/javascripts/editor/execution.js.erb index a5126462..5f8aa248 100644 --- a/app/assets/javascripts/editor/execution.js.erb +++ b/app/assets/javascripts/editor/execution.js.erb @@ -2,8 +2,9 @@ CodeOceanEditorWebsocket = { websocket: null, createSocketUrl: function(url) { - var sockURL = new URL(window.location); - sockURL.pathname = url; + var sockURL = new URL(url, window.location); + // not needed any longer, we put it directly into the url: sockURL.pathname = url; + // sanitize socket protocol string, strip trailing slash and other malicious chars if they are there sockURL.protocol = '<%= DockerClient.config['ws_client_protocol']&.match(/(\w+):*\/*/)&.to_a&.at(1) %>:'; diff --git a/app/models/code_ocean/file.rb b/app/models/code_ocean/file.rb index 9ae40b19..380f4989 100644 --- a/app/models/code_ocean/file.rb +++ b/app/models/code_ocean/file.rb @@ -80,6 +80,14 @@ module CodeOcean end private :content_present? + def filepath + if path.present? + ::File.join(path, name_with_extension) + else + name_with_extension + end + end + def hash_content self.hashed_content = Digest::MD5.new.hexdigest(file_type.try(:binary?) ? ::File.new(native_file.file.path, 'r').read : content) end diff --git a/lib/docker_client.rb b/lib/docker_client.rb index b44191aa..55c458ca 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -32,7 +32,11 @@ class DockerClient end def command_substitutions(filename) - {class_name: File.basename(filename, File.extname(filename)).camelize, filename: filename, module_name: File.basename(filename, File.extname(filename)).underscore} + { + class_name: File.basename(filename, File.extname(filename)).camelize, + filename: filename, + module_name: File.basename(filename, File.extname(filename)).underscore + } end private :command_substitutions @@ -310,7 +314,8 @@ class DockerClient """ Run commands by attaching a websocket to Docker. """ - command = submission.execution_environment.run_command % command_substitutions(filename) + filepath = submission.collect_files.find{|f| f.name_with_extension == filename}.filepath + command = submission.execution_environment.run_command % command_substitutions(filepath) create_workspace_files = proc { create_workspace_files(container, submission) } open_websocket_connection(command, create_workspace_files, block) # actual run command is run in the submissions controller, after all listeners are attached. @@ -320,7 +325,8 @@ class DockerClient """ Stick to existing Docker API with exec command. """ - command = submission.execution_environment.test_command % command_substitutions(filename) + filepath = submission.collect_files.find{|f| f.name_with_extension == filename}.filepath + command = submission.execution_environment.test_command % command_substitutions(filepath) create_workspace_files = proc { create_workspace_files(container, submission) } execute_command(command, create_workspace_files, block) end From 574e870bd169fa285c6dd589938c58d25dd3bdae Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Fri, 19 Oct 2018 15:27:14 +0200 Subject: [PATCH 13/66] fix reset for user created files (where therefore no original file is available) --- app/assets/javascripts/editor/submissions.js.erb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/editor/submissions.js.erb b/app/assets/javascripts/editor/submissions.js.erb index 21250f7e..1221b464 100644 --- a/app/assets/javascripts/editor/submissions.js.erb +++ b/app/assets/javascripts/editor/submissions.js.erb @@ -113,7 +113,9 @@ CodeOceanEditorSubmissions = { var file = _.find(response.files, function(file) { return file.id === file_id; }); - editor.setValue(file.content); + if(file){ + editor.setValue(file.content); + } }.bind(this)); }.bind(this)); }, From ac31afbd2a4f49d509b55fd55027e765504ea853 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 11 Sep 2018 10:49:36 +0200 Subject: [PATCH 14/66] Clean Gemfile and perform bundle update Signed-off-by: Sebastian Serth --- Gemfile | 11 +- Gemfile.lock | 158 +++++++++++-------------- app/assets/javascripts/application.js | 3 - app/assets/stylesheets/application.css | 1 - lib/docker_container_pool.rb | 4 +- spec/lib/docker_container_pool_spec.rb | 4 +- 6 files changed, 75 insertions(+), 106 deletions(-) diff --git a/Gemfile b/Gemfile index 11c91e55..0329ec07 100644 --- a/Gemfile +++ b/Gemfile @@ -1,12 +1,9 @@ source 'https://rubygems.org' -gem 'activerecord-jdbcpostgresql-adapter', platform: :jruby gem 'bcrypt' gem 'bootstrap-will_paginate' gem 'carrierwave' gem 'concurrent-ruby' -gem 'concurrent-ruby-ext', platform: :ruby -gem 'activerecord-deprecated_finders', require: 'active_record/deprecated_finders' gem 'docker-api', require: 'docker' gem 'factory_bot_rails' gem 'forgery' @@ -26,15 +23,11 @@ gem 'rails-i18n' gem 'ransack' gem 'rubytree' gem 'sass-rails', '>= 5.0.7' -gem 'sdoc', group: :doc gem 'slim-rails' -gem 'bootstrap_pagedown', '>= 1.1.0' -gem 'pagedown-rails' +gem 'bootstrap_pagedown' gem 'sorcery' -gem 'thread_safe' gem 'turbolinks', '< 5.0.0' # newer versions prevent loading ACE if the page containing is not accessed directly / refreshed gem 'uglifier' -gem 'will_paginate' gem 'tubesock' gem 'faye-websocket' gem 'eventmachine', '1.0.9.1' # explicitly added, this is used by faye-websocket, version 1.2.5 still has an error in eventmachine.rb:202: [BUG] Segmentation fault, which is not yet fixed and causes the whole ruby process to crash @@ -60,7 +53,6 @@ group :development, :staging do end group :development, :test, :staging do - gem 'byebug', platform: :ruby gem 'spring' end @@ -72,7 +64,6 @@ group :test do gem 'codeclimate-test-reporter', require: false gem 'database_cleaner' gem 'nyan-cat-formatter' - gem 'rake' gem 'rspec-autotest' gem 'rspec-rails' gem 'simplecov', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 0c196110..b5219e5d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -31,7 +31,6 @@ GEM activemodel (= 4.2.10) activesupport (= 4.2.10) arel (~> 6.0) - activerecord-deprecated_finders (1.0.4) activesupport (4.2.10) i18n (~> 0.7) minitest (~> 5.1) @@ -46,8 +45,8 @@ GEM ast (2.4.0) autotest-rails (4.2.1) ZenTest (~> 4.5) - bcrypt (3.1.11) - better_errors (2.4.0) + bcrypt (3.1.12) + better_errors (2.5.0) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -60,8 +59,8 @@ GEM builder (3.2.3) bunny (2.11.0) amq-protocol (~> 2.3.0) - byebug (10.0.0) - capistrano (3.10.1) + byebug (10.0.2) + capistrano (3.11.0) airbrussh (>= 1.0.0) i18n rake (>= 10.0.0) @@ -69,7 +68,7 @@ GEM capistrano-bundler (1.3.0) capistrano (~> 3.1) sshkit (~> 1.2) - capistrano-rails (1.3.1) + capistrano-rails (1.4.0) capistrano (~> 3.1) capistrano-bundler (~> 1.1) capistrano-rvm (0.1.2) @@ -81,7 +80,7 @@ GEM capistrano (~> 3.7) capistrano-bundler puma (~> 3.4) - capybara (3.3.1) + capybara (3.7.1) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) @@ -91,7 +90,7 @@ GEM capybara-selenium (0.0.6) capybara selenium-webdriver - carrierwave (1.2.2) + carrierwave (1.2.3) activemodel (>= 4.0.0) activesupport (>= 4.0.0) mime-types (>= 1.16) @@ -109,29 +108,27 @@ GEM execjs coffee-script-source (1.12.2) concurrent-ruby (1.0.5) - concurrent-ruby-ext (1.0.5) - concurrent-ruby (= 1.0.5) crass (1.0.4) d3-rails (4.13.0) railties (>= 3.1) - database_cleaner (1.6.2) + database_cleaner (1.7.0) debug_inspector (0.0.3) diff-lcs (1.3) - docile (1.1.5) - docker-api (1.34.1) + docile (1.3.1) + docker-api (1.34.2) excon (>= 0.47.0) multi_json - domain_name (0.5.20170404) + domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) erubi (1.7.1) erubis (2.7.0) eventmachine (1.0.9.1) - excon (0.60.0) + excon (0.62.0) execjs (2.7.0) - factory_bot (4.8.2) + factory_bot (4.11.1) activesupport (>= 3.0.0) - factory_bot_rails (4.8.2) - factory_bot (~> 4.8.2) + factory_bot_rails (4.11.1) + factory_bot (~> 4.11.1) railties (>= 3.0.0) faraday (0.12.2) multipart-post (>= 1.2, < 3) @@ -143,7 +140,7 @@ GEM globalid (0.4.1) activesupport (>= 4.2.0) headless (2.3.1) - highline (1.7.10) + highline (2.0.0) http-cookie (1.0.3) domain_name (~> 0.5) i18n (0.9.5) @@ -151,10 +148,11 @@ GEM ims-lti (1.1.10) builder oauth (~> 0.4.5) + jaro_winkler (1.5.1) jbuilder (2.7.0) activesupport (>= 4.2.0) multi_json (>= 1.2) - jquery-rails (4.3.1) + jquery-rails (4.3.3) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -163,17 +161,17 @@ GEM turbolinks json (2.1.0) jwt (1.5.6) - kramdown (1.16.2) + kramdown (1.17.0) loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) mini_mime (>= 0.1.1) method_source (0.9.0) - mime-types (3.1) + mime-types (3.2.2) mime-types-data (~> 3.2015) - mime-types-data (3.2016.0521) - mini_mime (1.0.0) + mime-types-data (3.2018.0812) + mini_mime (1.0.1) mini_portile2 (2.3.0) minitest (5.11.3) mnemosyne-ruby (1.5.1) @@ -184,10 +182,10 @@ GEM multipart-post (2.0.0) net-scp (1.2.1) net-ssh (>= 2.6.5) - net-ssh (4.2.0) + net-ssh (5.0.2) netrc (0.11.0) - newrelic_rpm (4.8.0.341) - nokogiri (1.8.3) + newrelic_rpm (5.3.0.346) + nokogiri (1.8.4) mini_portile2 (~> 2.3.0) nyan-cat-formatter (0.12.0) rspec (>= 2.99, >= 2.14.2, < 4) @@ -198,27 +196,23 @@ GEM multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) - pagedown-rails (1.1.4) - railties (> 3.1) parallel (1.12.1) - parser (2.5.0.3) + parser (2.5.1.2) ast (~> 2.4.0) pg (0.21.0) - polyamorous (1.3.3) - activerecord (>= 3.0) - powerpack (0.1.1) + powerpack (0.1.2) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) pry-byebug (3.6.0) byebug (~> 10.0) pry (~> 0.10) - public_suffix (3.0.2) - puma (3.11.3) - pundit (1.1.0) + public_suffix (3.0.3) + puma (3.12.0) + pundit (2.0.0) activesupport (>= 3.0.0) rack (1.6.10) - rack-mini-profiler (0.10.7) + rack-mini-profiler (1.0.0) rack (>= 1.2.0) rack-test (0.6.3) rack (>= 1.0) @@ -251,58 +245,57 @@ GEM thor (>= 0.18.1, < 2.0) rainbow (3.0.0) rake (12.3.1) - ransack (1.8.7) - actionpack (>= 3.0) - activerecord (>= 3.0) - activesupport (>= 3.0) + ransack (1.8.9) + actionpack (>= 3.0, <= 5.1.1) + activerecord (>= 3.0, <= 5.1.1) + activesupport (>= 3.0, <= 5.1.1) i18n - polyamorous (~> 1.3.2) rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) - rdoc (6.0.1) rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rspec (3.7.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-autotest (1.0.0) + rspec (3.8.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-autotest (1.0.2) rspec-core (>= 2.99.0.beta1, < 4.0.0) - rspec-core (3.7.1) - rspec-support (~> 3.7.0) - rspec-expectations (3.7.0) + rspec-core (3.8.0) + rspec-support (~> 3.8.0) + rspec-expectations (3.8.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-mocks (3.7.0) + rspec-support (~> 3.8.0) + rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-rails (3.7.2) + rspec-support (~> 3.8.0) + rspec-rails (3.8.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-support (~> 3.7.0) - rspec-support (3.7.1) - rubocop (0.53.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-support (~> 3.8.0) + rspec-support (3.8.0) + rubocop (0.59.0) + jaro_winkler (~> 1.5.1) parallel (~> 1.10) - parser (>= 2.5) + parser (>= 2.5, != 2.5.1.1) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) - rubocop-rspec (1.24.0) - rubocop (>= 0.53.0) - ruby-progressbar (1.9.0) + rubocop-rspec (1.29.1) + rubocop (>= 0.58.0) + ruby-progressbar (1.10.0) rubytree (1.0.0) json (~> 2.1) structured_warnings (~> 0.3) - rubyzip (1.2.1) - sass (3.5.6) + rubyzip (1.2.2) + sass (3.5.7) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) @@ -313,13 +306,11 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - sdoc (1.0.0) - rdoc (>= 5.0) - selenium-webdriver (3.13.0) + selenium-webdriver (3.14.0) childprocess (~> 0.5) rubyzip (~> 1.2) - simplecov (0.15.1) - docile (~> 1.1.0) + simplecov (0.16.1) + docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) @@ -330,7 +321,7 @@ GEM actionpack (>= 3.1) railties (>= 3.1) slim (~> 3.0) - sorcery (0.11.0) + sorcery (0.12.0) bcrypt (~> 3.1) oauth (~> 0.4, >= 0.4.4) oauth2 (~> 1.0, >= 0.8.0) @@ -343,7 +334,7 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sshkit (1.16.0) + sshkit (1.17.0) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) structured_warnings (0.3.0) @@ -358,17 +349,17 @@ GEM coffee-rails tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (4.1.6) + uglifier (4.1.18) execjs (>= 0.3.0, < 3) unf (0.1.4) unf_ext unf_ext (0.0.7.5) - unicode-display_width (1.3.0) + unicode-display_width (1.4.0) web-console (3.3.0) activemodel (>= 4.2) debug_inspector railties (>= 4.2) - websocket (1.2.5) + websocket (1.2.8) websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) @@ -382,15 +373,12 @@ PLATFORMS ruby DEPENDENCIES - activerecord-deprecated_finders - activerecord-jdbcpostgresql-adapter autotest-rails bcrypt better_errors binding_of_caller bootstrap-will_paginate - bootstrap_pagedown (>= 1.1.0) - byebug + bootstrap_pagedown capistrano capistrano-rails capistrano-rvm @@ -401,7 +389,6 @@ DEPENDENCIES carrierwave codeclimate-test-reporter concurrent-ruby - concurrent-ruby-ext d3-rails (~> 4.0) database_cleaner docker-api @@ -420,7 +407,6 @@ DEPENDENCIES newrelic_rpm nokogiri nyan-cat-formatter - pagedown-rails pg (< 1.0) pry-byebug puma @@ -428,7 +414,6 @@ DEPENDENCIES rack-mini-profiler rails (= 4.2.10) rails-i18n - rake ransack rest-client rspec-autotest @@ -438,18 +423,15 @@ DEPENDENCIES rubytree rubyzip sass-rails (>= 5.0.7) - sdoc simplecov slim-rails sorcery spring - thread_safe tubesock turbolinks (< 5.0.0) uglifier web-console whenever - will_paginate BUNDLED WITH - 1.16.1 + 1.16.3 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 9ccb9815..22b06a61 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -23,7 +23,4 @@ //= require_tree ../../../lib //= require_tree . //= require bootstrap_pagedown -//= require markdown.converter -//= require markdown.sanitizer -//= require markdown.editor //= require ace/ext-language_tools \ No newline at end of file diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 47163008..e21a40df 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -15,5 +15,4 @@ *= require_tree ../../../vendor/assets/stylesheets/ *= require_self *= require bootstrap_pagedown - *= require markdown */ diff --git a/lib/docker_container_pool.rb b/lib/docker_container_pool.rb index a2dc1a2e..64cd847c 100644 --- a/lib/docker_container_pool.rb +++ b/lib/docker_container_pool.rb @@ -4,9 +4,9 @@ require 'concurrent/timer_task' class DockerContainerPool - @containers = ThreadSafe::Hash[ExecutionEnvironment.all.map { |execution_environment| [execution_environment.id, ThreadSafe::Array.new] }] + @containers = Concurrent::Hash[ExecutionEnvironment.all.map { |execution_environment| [execution_environment.id, Concurrent::Array.new] }] #as containers are not containing containers in use - @all_containers = ThreadSafe::Hash[ExecutionEnvironment.all.map { |execution_environment| [execution_environment.id, ThreadSafe::Array.new] }] + @all_containers = Concurrent::Hash[ExecutionEnvironment.all.map { |execution_environment| [execution_environment.id, Concurrent::Array.new] }] def self.clean_up Rails.logger.info('Container Pool is now performing a cleanup. ') diff --git a/spec/lib/docker_container_pool_spec.rb b/spec/lib/docker_container_pool_spec.rb index 1ff39657..b6f6f42f 100644 --- a/spec/lib/docker_container_pool_spec.rb +++ b/spec/lib/docker_container_pool_spec.rb @@ -14,8 +14,8 @@ describe DockerContainerPool do end it 'uses thread-safe data structures' do - expect(described_class.instance_variable_get(:@containers)).to be_a(ThreadSafe::Hash) - expect(described_class.instance_variable_get(:@containers)[@execution_environment.id]).to be_a(ThreadSafe::Array) + expect(described_class.instance_variable_get(:@containers)).to be_a(Concurrent::Hash) + expect(described_class.instance_variable_get(:@containers)[@execution_environment.id]).to be_a(Concurrent::Array) end describe '.clean_up' do From 1f12b39731a99a3a92ec569141f7d2cd12085a89 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 11 Sep 2018 10:53:58 +0200 Subject: [PATCH 15/66] Hide FactoryBot deprecation warning by changing static assignment Signed-off-by: Sebastian Serth --- spec/factories/code_ocean/file.rb | 8 +- spec/factories/consumer.rb | 2 +- spec/factories/error.rb | 2 +- spec/factories/execution_environment.rb | 140 +++++++++++------------ spec/factories/exercise.rb | 56 ++++----- spec/factories/file_type.rb | 130 ++++++++++----------- spec/factories/hint.rb | 74 ++++++------ spec/factories/internal_user.rb | 10 +- spec/factories/lti_parameter.rb | 4 +- spec/factories/proxy_exercise.rb | 4 +- spec/factories/submission.rb | 2 +- spec/factories/user_exercise_feedback.rb | 2 +- 12 files changed, 217 insertions(+), 217 deletions(-) diff --git a/spec/factories/code_ocean/file.rb b/spec/factories/code_ocean/file.rb index bc672045..186ad1d1 100644 --- a/spec/factories/code_ocean/file.rb +++ b/spec/factories/code_ocean/file.rb @@ -3,13 +3,13 @@ require 'seeds_helper' module CodeOcean FactoryBot.define do factory :file, class: CodeOcean::File do - content '' + content { '' } association :context, factory: :submission association :file_type, factory: :dot_rb - hidden false + hidden { false } name { SecureRandom.hex } - read_only false - role 'main_file' + read_only { false } + role { 'main_file' } end end end diff --git a/spec/factories/consumer.rb b/spec/factories/consumer.rb index a4f32ca8..59b05b8d 100644 --- a/spec/factories/consumer.rb +++ b/spec/factories/consumer.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :consumer do - name 'openHPI' + name { 'openHPI' } oauth_key { SecureRandom.hex } oauth_secret { SecureRandom.hex } singleton_consumer diff --git a/spec/factories/error.rb b/spec/factories/error.rb index c10d47bf..427fee7d 100644 --- a/spec/factories/error.rb +++ b/spec/factories/error.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :error, class: Error do association :execution_environment, factory: :ruby - message "exercise.rb:4:in `
': undefined local variable or method `foo' for main:Object (NameError)" + message { "exercise.rb:4:in `
': undefined local variable or method `foo' for main:Object (NameError)" } end end diff --git a/spec/factories/execution_environment.rb b/spec/factories/execution_environment.rb index 013a041b..7eaaa49b 100644 --- a/spec/factories/execution_environment.rb +++ b/spec/factories/execution_environment.rb @@ -2,146 +2,146 @@ FactoryBot.define do factory :coffee_script, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'hklement/ubuntu-coffee:latest' + docker_image { 'hklement/ubuntu-coffee:latest' } association :file_type, factory: :dot_coffee help - name 'CoffeeScript' - network_enabled false - permitted_execution_time 10.seconds - pool_size 0 - run_command 'coffee' + name { 'CoffeeScript' } + network_enabled { false } + permitted_execution_time { 10.seconds } + pool_size { 0 } + run_command { 'coffee' } singleton_execution_environment end factory :html, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'hklement/ubuntu-html:latest' + docker_image { 'hklement/ubuntu-html:latest' } association :file_type, factory: :dot_html help - name 'HTML5' - network_enabled false - permitted_execution_time 10.seconds - pool_size 0 - run_command 'touch' + name { 'HTML5' } + network_enabled { false } + permitted_execution_time { 10.seconds } + pool_size { 0 } + run_command { 'touch' } singleton_execution_environment - test_command 'rspec %{filename} --format documentation' - testing_framework 'RspecAdapter' + test_command { 'rspec %{filename} --format documentation' } + testing_framework { 'RspecAdapter' } end factory :java, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'openhpi/co_execenv_java:latest' + docker_image { 'openhpi/co_execenv_java:latest' } association :file_type, factory: :dot_java help - name 'Java 8' - network_enabled false - permitted_execution_time 10.seconds - pool_size 0 - run_command 'make run' + name { 'Java 8' } + network_enabled { false } + permitted_execution_time { 10.seconds } + pool_size { 0 } + run_command { 'make run' } singleton_execution_environment - test_command 'make test CLASS_NAME="%{class_name}" FILENAME="%{filename}"' - testing_framework 'JunitAdapter' + test_command { 'make test CLASS_NAME="%{class_name}" FILENAME="%{filename}"' } + testing_framework { 'JunitAdapter' } end factory :jruby, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'hklement/ubuntu-jruby:latest' + docker_image { 'hklement/ubuntu-jruby:latest' } association :file_type, factory: :dot_rb help - name 'JRuby 1.7' - network_enabled false - permitted_execution_time 10.seconds - pool_size 0 - run_command 'jruby %{filename}' + name { 'JRuby 1.7' } + network_enabled { false } + permitted_execution_time { 10.seconds } + pool_size { 0 } + run_command { 'jruby %{filename}' } singleton_execution_environment - test_command 'rspec %{filename} --format documentation' - testing_framework 'RspecAdapter' + test_command { 'rspec %{filename} --format documentation' } + testing_framework { 'RspecAdapter' } end factory :node_js, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'hklement/ubuntu-node:latest' + docker_image { 'hklement/ubuntu-node:latest' } association :file_type, factory: :dot_js help - name 'Node.js' - network_enabled false - permitted_execution_time 10.seconds - pool_size 0 - run_command 'node %{filename}' + name { 'Node.js' } + network_enabled { false } + permitted_execution_time { 10.seconds } + pool_size { 0 } + run_command { 'node %{filename}' } singleton_execution_environment end factory :python, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'openhpi/co_execenv_python:latest' + docker_image { 'openhpi/co_execenv_python:latest' } association :file_type, factory: :dot_py help - name 'Python 3.4' - network_enabled false - permitted_execution_time 10.seconds - pool_size 0 - run_command 'python3 %{filename}' + name { 'Python 3.4' } + network_enabled { false } + permitted_execution_time { 10.seconds } + pool_size { 0 } + run_command { 'python3 %{filename}' } singleton_execution_environment - test_command 'python3 -m unittest --verbose %{module_name}' - testing_framework 'PyUnitAdapter' + test_command { 'python3 -m unittest --verbose %{module_name}' } + testing_framework { 'PyUnitAdapter' } end factory :ruby, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'hklement/ubuntu-ruby:latest' + docker_image { 'hklement/ubuntu-ruby:latest' } association :file_type, factory: :dot_rb help - name 'Ruby 2.2' - network_enabled false - permitted_execution_time 10.seconds - pool_size 0 - run_command 'ruby %{filename}' + name { 'Ruby 2.2' } + network_enabled { false } + permitted_execution_time { 10.seconds } + pool_size { 0 } + run_command { 'ruby %{filename}' } singleton_execution_environment - test_command 'rspec %{filename} --format documentation' - testing_framework 'RspecAdapter' + test_command { 'rspec %{filename} --format documentation' } + testing_framework { 'RspecAdapter' } end factory :sinatra, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'hklement/ubuntu-sinatra:latest' + docker_image { 'hklement/ubuntu-sinatra:latest' } association :file_type, factory: :dot_rb - exposed_ports '4567' + exposed_ports { '4567' } help - name 'Sinatra' - network_enabled true - permitted_execution_time 15.minutes - pool_size 0 - run_command 'ruby %{filename}' + name { 'Sinatra' } + network_enabled { true } + permitted_execution_time { 15.minutes } + pool_size { 0 } + run_command { 'ruby %{filename}' } singleton_execution_environment - test_command 'rspec %{filename} --format documentation' - testing_framework 'RspecAdapter' + test_command { 'rspec %{filename} --format documentation' } + testing_framework { 'RspecAdapter' } end factory :sqlite, class: ExecutionEnvironment do created_by_teacher default_memory_limit - docker_image 'hklement/ubuntu-sqlite:latest' + docker_image { 'hklement/ubuntu-sqlite:latest' } association :file_type, factory: :dot_sql help - name 'SQLite' - network_enabled false - permitted_execution_time 1.minute - pool_size 0 - run_command 'sqlite3 /database.db -init %{filename} -html' + name { 'SQLite' } + network_enabled { false } + permitted_execution_time { 1.minute } + pool_size { 0 } + run_command { 'sqlite3 /database.db -init %{filename} -html' } singleton_execution_environment - test_command 'ruby %{filename}' - testing_framework 'SqlResultSetComparatorAdapter' + test_command { 'ruby %{filename}' } + testing_framework { 'SqlResultSetComparatorAdapter' } end trait :default_memory_limit do - memory_limit DockerClient::DEFAULT_MEMORY_LIMIT + memory_limit { DockerClient::DEFAULT_MEMORY_LIMIT } end trait :help do diff --git a/spec/factories/exercise.rb b/spec/factories/exercise.rb index 2fcd7e07..92ed180f 100644 --- a/spec/factories/exercise.rb +++ b/spec/factories/exercise.rb @@ -16,10 +16,10 @@ end FactoryBot.define do factory :audio_video, class: Exercise do created_by_teacher - description "Try HTML's audio and video capabilities." + description { "Try HTML's audio and video capabilities." } association :execution_environment, factory: :html - instructions 'Build a simple website including an HTML