Merge remote-tracking branch 'origin/master' into exercise-anomaly-detection

# Conflicts:
#	Capfile
#	Gemfile.lock
#	db/schema.rb
This commit is contained in:
Maximilian Grundke
2018-02-28 16:48:14 +01:00
44 changed files with 330 additions and 226 deletions

View File

@ -5,20 +5,18 @@ services:
addons: addons:
code_climate: code_climate:
repo_token: 53a2c2608c848714e96f6a1fc0365dcfdfec051f7827d50cea965ea625f49734 repo_token:
postgresql: "9.5" secure: "cZoMNjQKB/D7W4B7JDk9PXooy2WCDypu7R4C/Vi0DziZCU9HRwLbdt9aoH5hgHFa7Fe2rHFgflPAAP7h698ozvP0waFtPqLAj+PbEt27LbBDvW8JcvNkKXA0rj5wyTkzuc/0kD+kPB4oDXMak6gZlB9HCJDsa3kdXScQGTVuPdU="
postgresql: "9.6"
before_install: before_install:
- export DISPLAY=:99.0 - export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start - sh -e /etc/init.d/xvfb start
# Config to run docker tests - doesn't work so far - echo 'DOCKER_OPTS="-H tcp://127.0.0.1:2376 -H unix:///var/run/docker.sock --iptables=false"' | sudo tee /etc/default/docker > /dev/null
# - sudo apt-get update - sudo service docker restart
# - sudo apt-get upgrade lxc-docker - sleep 5
# - echo 'DOCKER_OPTS="-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock --iptables=false"' | sudo tee /etc/default/docker > /dev/null - docker pull openhpi/co_execenv_python
# - export DOCKER_HOST=tcp://192.168.23.75:2375 - docker pull openhpi/co_execenv_java
# - sudo service docker restart
# - sleep 5
# - docker pull openhpi/docker_ruby
before_script: before_script:
- cp .rspec.travis .rspec - cp .rspec.travis .rspec
@ -26,18 +24,13 @@ before_script:
- cp config/code_ocean.yml.travis config/code_ocean.yml - cp config/code_ocean.yml.travis config/code_ocean.yml
- cp config/database.yml.travis config/database.yml - cp config/database.yml.travis config/database.yml
- cp config/secrets.yml.travis config/secrets.yml - cp config/secrets.yml.travis config/secrets.yml
- cp config/docker.yml.erb.travis config/docker.yml.erb
- psql --command='CREATE DATABASE travis_ci_test;' --username=postgres - psql --command='CREATE DATABASE travis_ci_test;' --username=postgres
- bundle exec rake db:schema:load RAILS_ENV=test - bundle exec rake db:schema:load RAILS_ENV=test
cache: bundler cache: bundler
language: ruby language: ruby
rvm: rvm:
- 2.3.1 - 2.3.6
# - 2.1.5
# - 2.2.1
script: bundle exec rspec --color --format documentation --require spec_helper --require rails_helper --tag ~docker
# one of the solutions I've found
# - sudo docker run --rm=true -v `pwd`:/ansible-apache:rw weldpua2008/docker-ansible:${OS_TYPE}${OS_VERSION}_v${ANSIBLE_VERSION} /bin/bash -c "/ansible-apache/tests/test-in-docker-image.sh ${OS_TYPE} ${OS_VERSION} ${ANSIBLE_VERSION}"
script: bundle exec rspec --color --format documentation --require spec_helper --require rails_helper && bundle exec codeclimate-test-reporter

View File

@ -1,8 +1,13 @@
require 'capistrano/setup' require 'capistrano/setup'
require 'capistrano/deploy' require 'capistrano/deploy'
require 'capistrano/scm/git'
require 'capistrano/puma' require 'capistrano/puma'
require 'capistrano/puma/nginx' require 'capistrano/puma/nginx'
require 'capistrano/rails' require 'capistrano/rails'
require 'capistrano/rvm' require 'capistrano/rvm'
require 'capistrano/upload-config' require 'capistrano/upload-config'
require "whenever/capistrano" require 'whenever/capistrano'
install_plugin Capistrano::SCM::Git
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Nginx

41
Gemfile
View File

@ -1,42 +1,43 @@
source 'https://rubygems.org' source 'https://rubygems.org'
gem 'activerecord-jdbcpostgresql-adapter', platform: :jruby gem 'activerecord-jdbcpostgresql-adapter', platform: :jruby
gem 'bcrypt', '~> 3.1.7' gem 'bcrypt'
gem 'bootstrap-will_paginate' gem 'bootstrap-will_paginate'
gem 'carrierwave' gem 'carrierwave'
gem 'coffee-rails', '~> 4.0.0' gem 'coffee-rails'
gem 'concurrent-ruby', '~> 1.0.1' gem 'concurrent-ruby'
gem 'concurrent-ruby-ext', '~> 1.0.1', platform: :ruby gem 'concurrent-ruby-ext', platform: :ruby
gem 'docker-api','~> 1.25.0', require: 'docker' gem 'docker-api', require: 'docker'
gem 'factory_bot_rails', '~> 4.8.2' gem 'factory_bot_rails'
gem 'forgery' gem 'forgery'
gem 'highline' gem 'highline'
gem 'jbuilder', '~> 2.0' gem 'jbuilder'
gem 'jquery-rails' gem 'jquery-rails'
gem 'jquery-turbolinks' gem 'jquery-turbolinks'
gem 'ims-lti' gem 'ims-lti', '1.1.10' # version 1.1.13 will crash, because @provider.valid_request?(request) on lti.rb line 89 will return false.
gem 'kramdown' gem 'kramdown'
gem 'newrelic_rpm' gem 'newrelic_rpm'
gem 'pg', platform: :ruby gem 'pg', '< 1.0', platform: :ruby
gem 'pry-byebug' gem 'pry-byebug'
gem 'puma', '~> 2.15.3' gem 'puma'
gem 'pundit' gem 'pundit'
gem 'rails', '4.2.5' gem 'rails', '4.2.10'
gem 'rails-i18n', '~> 4.0.0' gem 'rails-i18n'
gem 'ransack' gem 'ransack'
gem 'rubytree' gem 'rubytree'
gem 'sass-rails', '~> 4.0.3' gem 'sass-rails'
gem 'sdoc', '~> 0.4.0', group: :doc gem 'sdoc', group: :doc
gem 'slim' gem 'slim'
gem 'bootstrap_pagedown' gem 'bootstrap_pagedown'
gem 'pagedown-rails', '~> 1.1.4' gem 'pagedown-rails'
gem 'sorcery' gem 'sorcery'
gem 'thread_safe' gem 'thread_safe'
gem 'turbolinks' gem 'turbolinks', '< 5.0.0' # newer versions prevent loading ACE if the page containing is not accessed directly / refreshed
gem 'uglifier', '>= 1.3.0' gem 'uglifier'
gem 'will_paginate', '~> 3.0' gem 'will_paginate'
gem 'tubesock' gem 'tubesock'
gem 'faye-websocket' 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
gem 'nokogiri' gem 'nokogiri'
gem 'd3-rails' gem 'd3-rails'
gem 'rest-client' gem 'rest-client'
@ -46,7 +47,7 @@ gem 'whenever', require: false
group :development, :staging do group :development, :staging do
gem 'better_errors', platform: :ruby gem 'better_errors', platform: :ruby
gem 'binding_of_caller', platform: :ruby gem 'binding_of_caller', platform: :ruby
gem 'capistrano', '~> 3.3.0' gem 'capistrano'
gem 'capistrano3-puma' gem 'capistrano3-puma'
gem 'capistrano-rails' gem 'capistrano-rails'
gem 'capistrano-rvm' gem 'capistrano-rvm'
@ -54,7 +55,7 @@ group :development, :staging do
gem 'rack-mini-profiler' gem 'rack-mini-profiler'
gem 'rubocop', require: false gem 'rubocop', require: false
gem 'rubocop-rspec' gem 'rubocop-rspec'
gem 'web-console', '~> 2.0', platform: :ruby gem 'web-console', platform: :ruby
end end
group :development, :test, :staging do group :development, :test, :staging do

View File

@ -2,43 +2,42 @@ GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
ZenTest (4.11.0) ZenTest (4.11.0)
actionmailer (4.2.5) actionmailer (4.2.10)
actionpack (= 4.2.5) actionpack (= 4.2.10)
actionview (= 4.2.5) actionview (= 4.2.10)
activejob (= 4.2.5) activejob (= 4.2.10)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.5) actionpack (4.2.10)
actionview (= 4.2.5) actionview (= 4.2.10)
activesupport (= 4.2.5) activesupport (= 4.2.10)
rack (~> 1.6) rack (~> 1.6)
rack-test (~> 0.6.2) rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.5) actionview (4.2.10)
activesupport (= 4.2.5) activesupport (= 4.2.10)
builder (~> 3.1) builder (~> 3.1)
erubis (~> 2.7.0) erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (4.2.5) activejob (4.2.10)
activesupport (= 4.2.5) activesupport (= 4.2.10)
globalid (>= 0.3.0) globalid (>= 0.3.0)
activemodel (4.2.5) activemodel (4.2.10)
activesupport (= 4.2.5) activesupport (= 4.2.10)
builder (~> 3.1) builder (~> 3.1)
activerecord (4.2.5) activerecord (4.2.10)
activemodel (= 4.2.5) activemodel (= 4.2.10)
activesupport (= 4.2.5) activesupport (= 4.2.10)
arel (~> 6.0) arel (~> 6.0)
activerecord-jdbc-adapter (1.3.19) activerecord-jdbc-adapter (1.3.19)
activerecord (>= 2.2) activerecord (>= 2.2)
activerecord-jdbcpostgresql-adapter (1.3.19) activerecord-jdbcpostgresql-adapter (1.3.19)
activerecord-jdbc-adapter (~> 1.3.19) activerecord-jdbc-adapter (~> 1.3.19)
jdbc-postgres (>= 9.1) jdbc-postgres (>= 9.1)
activesupport (4.2.5) activesupport (4.2.10)
i18n (~> 0.7) i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1) minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4) thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1) tzinfo (~> 1.1)
@ -59,7 +58,7 @@ GEM
will_paginate will_paginate
bootstrap_pagedown (1.1.0) bootstrap_pagedown (1.1.0)
rails (>= 3.2) rails (>= 3.2)
builder (3.2.2) builder (3.2.3)
byebug (8.2.2) byebug (8.2.2)
capistrano (3.3.5) capistrano (3.3.5)
capistrano-stats (~> 1.1.0) capistrano-stats (~> 1.1.0)
@ -110,6 +109,7 @@ GEM
concurrent-ruby (1.0.2-java) concurrent-ruby (1.0.2-java)
concurrent-ruby-ext (1.0.2) concurrent-ruby-ext (1.0.2)
concurrent-ruby (~> 1.0.2) concurrent-ruby (~> 1.0.2)
crass (1.0.3)
d3-rails (3.5.11) d3-rails (3.5.11)
railties (>= 3.1) railties (>= 3.1)
database_cleaner (1.5.1) database_cleaner (1.5.1)
@ -139,13 +139,14 @@ GEM
ffi (1.9.10) ffi (1.9.10)
ffi (1.9.10-java) ffi (1.9.10-java)
forgery (0.6.0) forgery (0.6.0)
globalid (0.3.7) globalid (0.4.1)
activesupport (>= 4.1.0) activesupport (>= 4.2.0)
highline (1.7.8) highline (1.7.8)
hike (1.2.3) hike (1.2.3)
http-cookie (1.0.2) http-cookie (1.0.2)
domain_name (~> 0.5) domain_name (~> 0.5)
i18n (0.7.0) i18n (0.9.5)
concurrent-ruby (~> 1.0)
ims-lti (1.1.10) ims-lti (1.1.10)
builder builder
oauth (~> 0.4.5) oauth (~> 0.4.5)
@ -159,19 +160,21 @@ GEM
jquery-turbolinks (2.1.0) jquery-turbolinks (2.1.0)
railties (>= 3.1.0) railties (>= 3.1.0)
turbolinks turbolinks
json (1.8.3) json (1.8.6)
json (1.8.3-java) json (1.8.6-java)
jwt (1.5.1) jwt (1.5.1)
kramdown (1.9.0) kramdown (1.9.0)
loofah (2.0.3) loofah (2.2.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.6.4) mail (2.7.0)
mime-types (>= 1.16, < 4) mini_mime (>= 0.1.1)
method_source (0.8.2) method_source (0.8.2)
mime-types (2.99.3) mime-types (2.99.3)
mini_portile2 (2.1.0) mini_mime (1.0.0)
minitest (5.10.1) mini_portile2 (2.3.0)
multi_json (1.12.1) minitest (5.11.3)
multi_json (1.13.1)
multi_xml (0.5.5) multi_xml (0.5.5)
multipart-post (2.0.0) multipart-post (2.0.0)
net-scp (1.2.1) net-scp (1.2.1)
@ -179,9 +182,9 @@ GEM
net-ssh (3.0.2) net-ssh (3.0.2)
netrc (0.10.3) netrc (0.10.3)
newrelic_rpm (3.14.3.313) newrelic_rpm (3.14.3.313)
nokogiri (1.7.0.1) nokogiri (1.8.2)
mini_portile2 (~> 2.1.0) mini_portile2 (~> 2.3.0)
nokogiri (1.7.0.1-java) nokogiri (1.8.2-java)
nyan-cat-formatter (0.11) nyan-cat-formatter (0.11)
rspec (>= 2.99, >= 2.14.2, < 4) rspec (>= 2.99, >= 2.14.2, < 4)
oauth (0.4.7) oauth (0.4.7)
@ -203,6 +206,11 @@ GEM
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
pry (0.10.3-java)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
spoon (~> 0.0)
pry-byebug (3.3.0) pry-byebug (3.3.0)
byebug (~> 8.0) byebug (~> 8.0)
pry (~> 0.10) pry (~> 0.10)
@ -210,26 +218,26 @@ GEM
puma (2.15.3-java) puma (2.15.3-java)
pundit (1.1.0) pundit (1.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
rack (1.6.5) rack (1.6.9)
rack-mini-profiler (0.10.1) rack-mini-profiler (0.10.1)
rack (>= 1.2.0) rack (>= 1.2.0)
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (4.2.5) rails (4.2.10)
actionmailer (= 4.2.5) actionmailer (= 4.2.10)
actionpack (= 4.2.5) actionpack (= 4.2.10)
actionview (= 4.2.5) actionview (= 4.2.10)
activejob (= 4.2.5) activejob (= 4.2.10)
activemodel (= 4.2.5) activemodel (= 4.2.10)
activerecord (= 4.2.5) activerecord (= 4.2.10)
activesupport (= 4.2.5) activesupport (= 4.2.10)
bundler (>= 1.3.0, < 2.0) bundler (>= 1.3.0, < 2.0)
railties (= 4.2.5) railties (= 4.2.10)
sprockets-rails sprockets-rails
rails-deprecated_sanitizer (1.0.3) rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha) activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.8) rails-dom-testing (1.0.9)
activesupport (>= 4.2.0.beta, < 5.0) activesupport (>= 4.2.0, < 5.0)
nokogiri (~> 1.6) nokogiri (~> 1.6)
rails-deprecated_sanitizer (>= 1.0.1) rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.3) rails-html-sanitizer (1.0.3)
@ -237,13 +245,13 @@ GEM
rails-i18n (4.0.8) rails-i18n (4.0.8)
i18n (~> 0.7) i18n (~> 0.7)
railties (~> 4.0) railties (~> 4.0)
railties (4.2.5) railties (4.2.10)
actionpack (= 4.2.5) actionpack (= 4.2.10)
activesupport (= 4.2.5) activesupport (= 4.2.10)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.2.1) rainbow (2.2.1)
rake (12.0.0) rake (12.3.0)
ransack (1.7.0) ransack (1.7.0)
actionpack (>= 3.0) actionpack (>= 3.0)
activerecord (>= 3.0) activerecord (>= 3.0)
@ -319,6 +327,8 @@ GEM
bcrypt (~> 3.1) bcrypt (~> 3.1)
oauth (~> 0.4, >= 0.4.4) oauth (~> 0.4, >= 0.4.4)
oauth2 (>= 0.8.0) oauth2 (>= 0.8.0)
spoon (0.0.6)
ffi
spring (1.6.3) spring (1.6.3)
sprockets (2.12.4) sprockets (2.12.4)
hike (~> 1.2) hike (~> 1.2)
@ -334,16 +344,16 @@ GEM
net-ssh (>= 2.8.0) net-ssh (>= 2.8.0)
structured_warnings (0.2.0) structured_warnings (0.2.0)
temple (0.7.6) temple (0.7.6)
thor (0.19.4) thor (0.20.0)
thread_safe (0.3.5) thread_safe (0.3.6)
thread_safe (0.3.5-java) thread_safe (0.3.6-java)
tilt (1.4.1) tilt (1.4.1)
tubesock (0.2.5) tubesock (0.2.5)
rack (>= 1.5.0) rack (>= 1.5.0)
websocket (>= 1.1.0) websocket (>= 1.1.0)
turbolinks (2.5.3) turbolinks (2.5.3)
coffee-rails coffee-rails
tzinfo (1.2.2) tzinfo (1.2.5)
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (2.7.2) uglifier (2.7.2)
execjs (>= 0.3.0) execjs (>= 0.3.0)
@ -377,13 +387,13 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
activerecord-jdbcpostgresql-adapter activerecord-jdbcpostgresql-adapter
autotest-rails autotest-rails
bcrypt (~> 3.1.7) bcrypt
better_errors better_errors
binding_of_caller binding_of_caller
bootstrap-will_paginate bootstrap-will_paginate
bootstrap_pagedown bootstrap_pagedown
byebug byebug
capistrano (~> 3.3.0) capistrano
capistrano-rails capistrano-rails
capistrano-rvm capistrano-rvm
capistrano-upload-config capistrano-upload-config
@ -391,32 +401,33 @@ DEPENDENCIES
capybara capybara
carrierwave carrierwave
codeclimate-test-reporter codeclimate-test-reporter
coffee-rails (~> 4.0.0) coffee-rails
concurrent-ruby (~> 1.0.1) concurrent-ruby
concurrent-ruby-ext (~> 1.0.1) concurrent-ruby-ext
d3-rails d3-rails
database_cleaner database_cleaner
docker-api (~> 1.25.0) docker-api
factory_bot_rails (~> 4.8.2) eventmachine (= 1.0.9.1)
factory_bot_rails
faye-websocket faye-websocket
forgery forgery
highline highline
ims-lti ims-lti (= 1.1.10)
jbuilder (~> 2.0) jbuilder
jquery-rails jquery-rails
jquery-turbolinks jquery-turbolinks
kramdown kramdown
newrelic_rpm newrelic_rpm
nokogiri nokogiri
nyan-cat-formatter nyan-cat-formatter
pagedown-rails (~> 1.1.4) pagedown-rails
pg pg (< 1.0)
pry-byebug pry-byebug
puma (~> 2.15.3) puma
pundit pundit
rack-mini-profiler rack-mini-profiler
rails (= 4.2.5) rails (= 4.2.10)
rails-i18n (~> 4.0.0) rails-i18n
rake rake
ransack ransack
rest-client rest-client
@ -426,8 +437,8 @@ DEPENDENCIES
rubocop-rspec rubocop-rspec
rubytree rubytree
rubyzip rubyzip
sass-rails (~> 4.0.3) sass-rails
sdoc (~> 0.4.0) sdoc
selenium-webdriver selenium-webdriver
simplecov simplecov
slim slim
@ -435,8 +446,11 @@ DEPENDENCIES
spring spring
thread_safe thread_safe
tubesock tubesock
turbolinks turbolinks (< 5.0.0)
uglifier (>= 1.3.0) uglifier
web-console (~> 2.0) web-console
whenever whenever
will_paginate (~> 3.0) will_paginate
BUNDLED WITH
1.16.1

View File

@ -26,4 +26,4 @@
//= require markdown.converter //= require markdown.converter
//= require markdown.sanitizer //= require markdown.sanitizer
//= require markdown.editor //= require markdown.editor
//= require ../../../vendor/assets/javascripts/ace/ext-language_tools //= require ace/ext-language_tools

View File

@ -3,7 +3,7 @@
} }
.chosen-container { .chosen-container {
width: 100% !important; width: 250px !important;
} }
.code-field { .code-field {

View File

@ -9,7 +9,7 @@ module SubmissionScoring
assessment = assessor.assess(output) assessment = assessor.assess(output)
passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0)) 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 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| submission.exercise.execution_environment.error_templates.each do |template|
pattern = Regexp.new(template.signature).freeze pattern = Regexp.new(template.signature).freeze
if pattern.match(testrun_output) if pattern.match(testrun_output)
@ -47,6 +47,14 @@ module SubmissionScoring
end end
end end
submission.update(score: score) submission.update(score: score)
if submission.normalized_score == 1.0
Thread.new do
RequestForComment.where(exercise_id: submission.exercise_id, user_id: submission.user_id, user_type: submission.user_type).each{ |rfc|
rfc.full_score_reached = true
rfc.save
}
end
end
outputs outputs
end end
end end

View File

@ -416,6 +416,9 @@ class ExercisesController < ApplicationController
flash[:notice] = I18n.t('exercises.submit.full_score_redirect_to_rfc') flash[:notice] = I18n.t('exercises.submit.full_score_redirect_to_rfc')
flash.keep(:notice) flash.keep(:notice)
# increase counter 'times_featured' in rfc
rfc.increment!(:times_featured)
respond_to do |format| respond_to do |format|
format.html {redirect_to(rfc)} format.html {redirect_to(rfc)}
format.json {render(json: {redirect: url_for(rfc)})} format.json {render(json: {redirect: url_for(rfc)})}

View File

@ -14,46 +14,40 @@ class RequestForCommentsController < ApplicationController
def index def index
@search = RequestForComment @search = RequestForComment
.last_per_user(2) .last_per_user(2)
.joins('join "submissions" s on s.id = request_for_comments.submission_id .with_last_activity
left outer join "files" f on f.context_id = s.id
left outer join "comments" on comments.file_id = f.id')
.group('request_for_comments.id, request_for_comments.user_id, request_for_comments.exercise_id,
request_for_comments.file_id, request_for_comments.question, request_for_comments.created_at,
request_for_comments.updated_at, request_for_comments.user_type, request_for_comments.solved,
request_for_comments.submission_id, request_for_comments.row_number') # ugly, but rails wants it this way
.select('request_for_comments.*, max(comments.updated_at) as last_comment')
.search(params[:q]) .search(params[:q])
@request_for_comments = @search.result.order('created_at DESC').paginate(page: params[:page], total_entries: @search.result.length) @request_for_comments = @search.result
.order('created_at DESC')
.paginate(page: params[:page], total_entries: @search.result.length)
authorize! authorize!
end end
# GET /my_request_for_comments
def get_my_comment_requests def get_my_comment_requests
@search = RequestForComment @search = RequestForComment
.with_last_activity
.where(user_id: current_user.id) .where(user_id: current_user.id)
.joins('join "submissions" s on s.id = request_for_comments.submission_id
left outer join "files" f on f.context_id = s.id
left outer join "comments" on comments.file_id = f.id')
.group('request_for_comments.id')
.select('request_for_comments.*, max(comments.updated_at) as last_comment')
.search(params[:q]) .search(params[:q])
@request_for_comments = @search.result.order('created_at DESC').paginate(page: params[:page]) @request_for_comments = @search.result
.order('created_at DESC')
.paginate(page: params[:page])
render 'index' render 'index'
end end
# GET /my_rfc_activity
def get_rfcs_with_my_comments def get_rfcs_with_my_comments
@search = RequestForComment @search = RequestForComment
.with_last_activity
.joins(:comments) # we don't need to outer join here, because we know the user has commented on these .joins(:comments) # we don't need to outer join here, because we know the user has commented on these
.where(comments: {user_id: current_user.id}) .where(comments: {user_id: current_user.id})
.joins('join "submissions" s on s.id = request_for_comments.submission_id
left outer join "files" f on f.context_id = s.id
left outer join "comments" as c on c.file_id = f.id')
.group('request_for_comments.id')
.select('request_for_comments.*, max(c.updated_at) as last_comment')
.search(params[:q]) .search(params[:q])
@request_for_comments = @search.result.order('last_comment DESC').paginate(page: params[:page]) @request_for_comments = @search.result
.order('last_comment DESC')
.paginate(page: params[:page])
render 'index' render 'index'
end end
# GET /request_for_comments/1/mark_as_solved
def mark_as_solved def mark_as_solved
authorize! authorize!
@request_for_comment.solved = true @request_for_comment.solved = true
@ -66,6 +60,7 @@ class RequestForCommentsController < ApplicationController
end end
end end
# POST /request_for_comments/1/set_thank_you_note
def set_thank_you_note def set_thank_you_note
authorize! authorize!
@request_for_comment.thank_you_note = params[:note] @request_for_comment.thank_you_note = params[:note]
@ -82,10 +77,6 @@ class RequestForCommentsController < ApplicationController
end end
end end
def submit
end
# GET /request_for_comments/1 # GET /request_for_comments/1
# GET /request_for_comments/1.json # GET /request_for_comments/1.json
def show def show
@ -146,10 +137,6 @@ class RequestForCommentsController < ApplicationController
authorize! authorize!
end end
def comment_params
params.permit(:exercise_id, :feedback_text).merge(user_id: current_user.id, user_type: current_user.class.name)
end
private private
# Use callbacks to share common setup or constraints between actions. # Use callbacks to share common setup or constraints between actions.
def set_request_for_comment def set_request_for_comment
@ -162,4 +149,8 @@ class RequestForCommentsController < ApplicationController
params.require(:request_for_comment).permit(:exercise_id, :file_id, :question, :requested_at, :solved, :submission_id).merge(user_id: current_user.id, user_type: current_user.class.name) params.require(:request_for_comment).permit(:exercise_id, :file_id, :question, :requested_at, :solved, :submission_id).merge(user_id: current_user.id, user_type: current_user.class.name)
end end
def comment_params
params.permit(:exercise_id, :feedback_text).merge(user_id: current_user.id, user_type: current_user.class.name)
end
end end

View File

@ -202,21 +202,11 @@ class SubmissionsController < ApplicationController
tubesock.close tubesock.close
end end
def extract_errors
if !@message_buffer.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)
end
end
end
end
def handle_message(message, tubesock, container) def handle_message(message, tubesock, container)
@run_output ||= "" @raw_output ||= ''
@run_output ||= ''
# Handle special commands first # Handle special commands first
if (/^#exit/.match(message)) if /^#exit/.match(message)
# Just call exit_container on the docker_client. # Just call exit_container on the docker_client.
# Do not call kill_socket for the websocket to the client here. # Do not call kill_socket for the websocket to the client here.
# @docker_client.exit_container closes the socket to the container, # @docker_client.exit_container closes the socket to the container,
@ -228,17 +218,17 @@ class SubmissionsController < ApplicationController
# 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(params[:filename])
test_command = @submission.execution_environment.test_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) parse_message(message, 'stdout', tubesock)
end end
end end
end end
def parse_message(message, output_stream, socket, recursive = true) def parse_message(message, output_stream, socket, recursive = true)
parsed = ''; parsed = ''
begin begin
parsed = JSON.parse(message) parsed = JSON.parse(message)
if(parsed.class == Hash && parsed.key?('cmd')) if parsed.class == Hash and parsed.key?('cmd')
socket.send_data message socket.send_data message
Rails.logger.info('parse_message sent: ' + message) Rails.logger.info('parse_message sent: ' + message)
else else
@ -248,24 +238,24 @@ class SubmissionsController < ApplicationController
end end
rescue JSON::ParserError => e rescue JSON::ParserError => e
# Check wether the message contains multiple lines, if true try to parse each line # 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") for part in message.split("\n")
self.parse_message(part,output_stream,socket,false) self.parse_message(part,output_stream,socket,false)
end end
elsif(message.include? "<img") elsif message.include? '<img'
#Rails.logger.info('img foung') #Rails.logger.info('img foung')
@buffering = true @buffering = true
@buffer = "" @buffer = ''
@buffer += message @buffer += message
#Rails.logger.info('Starting to buffer') #Rails.logger.info('Starting to buffer')
elsif(@buffering && (message.include? "/>")) elsif @buffering and message.include? '/>'
@buffer += message @buffer += message
parsed = {'cmd'=>'write','stream'=>output_stream,'data'=>@buffer} parsed = {'cmd'=>'write','stream'=>output_stream,'data'=>@buffer}
socket.send_data JSON.dump(parsed) socket.send_data JSON.dump(parsed)
#socket.send_data @buffer #socket.send_data @buffer
@buffering = false @buffering = false
#Rails.logger.info('Sent complete buffer') #Rails.logger.info('Sent complete buffer')
elsif(@buffering) elsif @buffering
@buffer += message @buffer += message
#Rails.logger.info('Appending to buffer') #Rails.logger.info('Appending to buffer')
else else
@ -275,18 +265,30 @@ class SubmissionsController < ApplicationController
Rails.logger.info('parse_message sent: ' + JSON.dump(parsed)) Rails.logger.info('parse_message sent: ' + JSON.dump(parsed))
end end
ensure 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" # 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 @run_output += JSON.dump(parsed) if @run_output.size <= max_run_output_buffer_size
end end
end end
def save_run_output 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 @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) Testrun.create(file: @file, cause: 'run', submission: @submission, output: @run_output)
end end
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 def score
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?

View File

@ -47,7 +47,7 @@ class ExecutionEnvironment < ActiveRecord::Base
private :validate_docker_image? private :validate_docker_image?
def working_docker_image? def working_docker_image?
DockerClient.pull(docker_image) unless DockerClient.image_tags.include?(docker_image) DockerClient.pull(docker_image) unless DockerClient.find_image_by_tag(docker_image).blank?
output = DockerClient.new(execution_environment: self).execute_arbitrary_command(VALIDATION_COMMAND) output = DockerClient.new(execution_environment: self).execute_arbitrary_command(VALIDATION_COMMAND)
errors.add(:docker_image, "error: #{output[:stderr]}") if output[:stderr].present? errors.add(:docker_image, "error: #{output[:stderr]}") if output[:stderr].present?
rescue DockerClient::Error => error rescue DockerClient::Error => error

View File

@ -10,7 +10,13 @@ class RequestForComment < ActiveRecord::Base
scope :unsolved, -> { where(solved: [false, nil]) } scope :unsolved, -> { where(solved: [false, nil]) }
def self.last_per_user(n = 5) def self.last_per_user(n = 5)
from("(#{row_number_user_sql}) as request_for_comments").where("row_number <= ?", n) from("(#{row_number_user_sql}) as request_for_comments")
.where("row_number <= ?", n)
.group('request_for_comments.id, request_for_comments.user_id, request_for_comments.exercise_id,
request_for_comments.file_id, request_for_comments.question, request_for_comments.created_at,
request_for_comments.updated_at, request_for_comments.user_type, request_for_comments.solved,
request_for_comments.full_score_reached, request_for_comments.submission_id, request_for_comments.row_number')
# ugly, but necessary
end end
# not used right now, finds the last submission for the respective user and exercise. # not used right now, finds the last submission for the respective user and exercise.
@ -46,12 +52,20 @@ class RequestForComment < ActiveRecord::Base
commenters.uniq {|user| user.id} commenters.uniq {|user| user.id}
end end
def self.with_last_activity
self.joins('join "submissions" s on s.id = request_for_comments.submission_id
left outer join "files" f on f.context_id = s.id
left outer join "comments" c on c.file_id = f.id')
.group('request_for_comments.id')
.select('request_for_comments.*, max(c.updated_at) as last_comment')
end
def to_s def to_s
"RFC-" + self.id.to_s "RFC-" + self.id.to_s
end end
private private
def self.row_number_user_sql def self.row_number_user_sql
select("id, user_id, exercise_id, file_id, question, created_at, updated_at, user_type, solved, submission_id, row_number() OVER (PARTITION BY user_id ORDER BY created_at DESC) as row_number").to_sql select("id, user_id, exercise_id, file_id, question, created_at, updated_at, user_type, solved, full_score_reached, submission_id, row_number() OVER (PARTITION BY user_id ORDER BY created_at DESC) as row_number").to_sql
end end
end end

View File

@ -1,9 +1,10 @@
class StructuredError < ActiveRecord::Base class StructuredError < ActiveRecord::Base
belongs_to :error_template belongs_to :error_template
belongs_to :submission
belongs_to :file, class_name: 'CodeOcean::File' belongs_to :file, class_name: 'CodeOcean::File'
def self.create_from_template(template, message_buffer) def self.create_from_template(template, message_buffer, submission)
instance = self.create(error_template: template) instance = self.create(error_template: template, submission: submission)
template.error_template_attributes.each do |attribute| template.error_template_attributes.each do |attribute|
StructuredErrorAttribute.create_from_template(attribute, instance, message_buffer) StructuredErrorAttribute.create_from_template(attribute, instance, message_buffer)
end end

View File

@ -3,15 +3,13 @@ class StructuredErrorAttribute < ActiveRecord::Base
belongs_to :error_template_attribute belongs_to :error_template_attribute
def self.create_from_template(attribute, structured_error, message_buffer) def self.create_from_template(attribute, structured_error, message_buffer)
match = false
value = nil value = nil
result = message_buffer.match(attribute.regex) result = message_buffer.match(attribute.regex)
if result != nil if result != nil
match = true
if result.captures.size > 0 if result.captures.size > 0
value = result.captures[0] value = result.captures[0]
end end
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
end end

View File

@ -8,6 +8,7 @@ class Submission < ActiveRecord::Base
belongs_to :exercise belongs_to :exercise
has_many :testruns has_many :testruns
has_many :structured_errors
has_many :comments, through: :files has_many :comments, through: :files
delegate :execution_environment, to: :exercise delegate :execution_environment, to: :exercise

View File

@ -1,4 +1,5 @@
#flash.fixed_error_messages data-message-failure=t('shared.message_failure') #flash-container
#flash.container.fixed_error_messages data-message-failure=t('shared.message_failure')
- %w[alert danger info notice success warning].each do |severity| - %w[alert danger info notice success warning].each do |severity|
div.alert.flash class="alert-#{{'alert' => 'warning', 'notice' => 'success'}.fetch(severity, severity)}" div.alert.flash class="alert-#{{'alert' => 'warning', 'notice' => 'success'}.fetch(severity, severity)}"
p id="flash-#{severity}" = flash[severity] p id="flash-#{severity}" = flash[severity]

View File

@ -32,8 +32,8 @@ html lang='en'
li = link_to(t('shared.help.link'), '#modal-help', data: {toggle: 'modal'}) li = link_to(t('shared.help.link'), '#modal-help', data: {toggle: 'modal'})
= render('session') = render('session')
.container data-controller=controller_name .container data-controller=controller_name
= render('breadcrumbs')
= render('flash') = render('flash')
= render('breadcrumbs')
- if (controller_name == "exercises" && action_name == "implement") - if (controller_name == "exercises" && action_name == "implement")
.container-fluid .container-fluid
= yield = yield

View File

@ -27,6 +27,9 @@ h1 = RequestForComment.model_name.human(count: 2)
- if request_for_comment.solved? - if request_for_comment.solved?
td td
span class="fa fa-check" aria-hidden="true" span class="fa fa-check" aria-hidden="true"
- elsif request_for_comment.full_score_reached
td
span class="fa fa-check" style="color:darkgrey" aria-hidden="true"
- else - else
td = '' td = ''
td = link_to(request_for_comment.exercise.title, request_for_comment) td = link_to(request_for_comment.exercise.title, request_for_comment)

View File

@ -17,7 +17,7 @@ namespace :deploy do
after :compile_assets, :copy_vendor_assets do after :compile_assets, :copy_vendor_assets do
on roles(fetch(:assets_roles)) do on roles(fetch(:assets_roles)) do
within release_path do within release_path do
execute :cp, 'vendor/assets/images/*', 'public/assets/' execute :cp, '-r', 'vendor/assets/images/', 'public/assets/'
execute :cp, '-r', 'vendor/assets/javascripts/ace', 'public/assets/' execute :cp, '-r', 'vendor/assets/javascripts/ace', 'public/assets/'
end end
end end

View File

@ -34,7 +34,21 @@ production:
ws_host: ws://localhost:4243 #url to connect rails server to docker host ws_host: ws://localhost:4243 #url to connect rails server to docker host
ws_client_protocol: wss:// #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production) ws_client_protocol: wss:// #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production)
staging:
<<: *default
host: unix:///var/run/docker.sock
pool:
active: true
refill:
async: false
batch_size: 8
interval: 15
timeout: 60
workspace_root: <%= Rails.root.join('tmp', 'files', Rails.env) %>
ws_host: ws://localhost:4243 #url to connect rails server to docker host
ws_client_protocol: 'wss:' #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production)
test: test:
<<: *default <<: *default
host: tcp://192.168.59.104:2376 host: tcp://127.0.0.1:2376
workspace_root: <%= File.join('/', 'shared', Rails.env) %> workspace_root: <%= File.join('/', 'shared', Rails.env) %>

View File

@ -32,7 +32,7 @@ production:
timeout: 60 timeout: 60
workspace_root: <%= Rails.root.join('tmp', 'files', Rails.env) %> workspace_root: <%= Rails.root.join('tmp', 'files', Rails.env) %>
ws_host: ws://localhost:4243 #url to connect rails server to docker host ws_host: ws://localhost:4243 #url to connect rails server to docker host
ws_client_protocol: 'wss:' #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production) ws_client_protocol: wss:// #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production)
staging: staging:
<<: *default <<: *default
@ -50,5 +50,5 @@ staging:
test: test:
<<: *default <<: *default
host: tcp://192.168.59.104:2376 host: tcp://127.0.0.1:2376
workspace_root: <%= File.join('/', 'shared', Rails.env) %> workspace_root: <%= File.join('/', 'shared', Rails.env) %>

View File

@ -35,6 +35,9 @@ Rails.application.configure do
# yet still be able to expire them through the digest params. # yet still be able to expire them through the digest params.
config.assets.digest = true config.assets.digest = true
# Suppress logger output for asset requests.
config.assets.quiet = true
# Adds additional error checking when serving assets at runtime. # Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies. # Checks for improperly declared sprockets dependencies.
# Raises helpful error messages. # Raises helpful error messages.

View File

@ -0,0 +1,5 @@
class AddSubmissionToStructuredErrors < ActiveRecord::Migration
def change
add_reference :structured_errors, :submission, index: true
end
end

View File

@ -0,0 +1,15 @@
class AddReachedFullScoreToRequestForComment < ActiveRecord::Migration
def up
add_column :request_for_comments, :full_score_reached, :boolean, default: false
RequestForComment.find_each { |rfc|
if rfc.submission.present? and rfc.submission.exercise.has_user_solved(rfc.user)
rfc.full_score_reached = true
rfc.save
end
}
end
def down
remove_column :request_for_comments, :full_score_reached
end
end

View File

@ -0,0 +1,5 @@
class AddTimesFeaturedToRequestForComments < ActiveRecord::Migration
def change
add_column :request_for_comments, :times_featured, :integer, default: 0
end
end

View File

@ -0,0 +1,10 @@
class FixTimestampsOnFeedback < ActiveRecord::Migration
def up
change_column_default(:user_exercise_feedbacks, :created_at, nil)
change_column_default(:user_exercise_feedbacks, :updated_at, nil)
end
def down
end
end

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180226131340) do ActiveRecord::Schema.define(version: 20180222145909) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -301,6 +301,8 @@ ActiveRecord::Schema.define(version: 20180226131340) do
t.boolean "solved", default: false t.boolean "solved", default: false
t.integer "submission_id" t.integer "submission_id"
t.text "thank_you_note" t.text "thank_you_note"
t.boolean "full_score_reached", default: false
t.integer "times_featured", default: 0
end end
create_table "searches", force: :cascade do |t| create_table "searches", force: :cascade do |t|
@ -326,8 +328,11 @@ ActiveRecord::Schema.define(version: 20180226131340) do
t.integer "file_id" t.integer "file_id"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.integer "submission_id"
end end
add_index "structured_errors", ["submission_id"], name: "index_structured_errors_on_submission_id", using: :btree
create_table "submissions", force: :cascade do |t| create_table "submissions", force: :cascade do |t|
t.integer "exercise_id" t.integer "exercise_id"
t.float "score" t.float "score"
@ -375,8 +380,8 @@ ActiveRecord::Schema.define(version: 20180226131340) do
t.integer "working_time_seconds" t.integer "working_time_seconds"
t.string "feedback_text" t.string "feedback_text"
t.integer "user_estimated_worktime" t.integer "user_estimated_worktime"
t.datetime "created_at", default: '2017-11-20 18:20:25', null: false t.datetime "created_at", null: false
t.datetime "updated_at", default: '2017-11-20 18:20:25', null: false t.datetime "updated_at", null: false
end end
create_table "user_exercise_interventions", force: :cascade do |t| create_table "user_exercise_interventions", force: :cascade do |t|

View File

@ -1,3 +1,8 @@
#flash-container {
position: relative;
top: -21px;
}
.flash { .flash {
display: none; display: none;
@ -10,14 +15,10 @@
} }
.fixed_error_messages { .fixed_error_messages {
position: fixed; position: absolute;
z-index: 1000; z-index: 1000;
top: 20px; padding: inherit;
left: 0;
width: 100%; width: 100%;
padding-left: 10%;
padding-right: 10%;
padding-top: 0;
} }

View File

@ -13,7 +13,7 @@ add-apt-repository ppa:chris-lea/node.js
apt-get update apt-get update
# code_ocean # code_ocean
apt-get install -y postgresql-client postgresql-9.5 postgresql-server-dev-9.5 vagrant apt-get install -y postgresql-client postgresql-10 postgresql-server-dev-10 vagrant
# Docker # Docker
if [ ! -f /etc/default/docker ] if [ ! -f /etc/default/docker ]
@ -49,18 +49,18 @@ apt-get install -y libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3 gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
curl -L https://get.rvm.io | bash -s stable curl -L https://get.rvm.io | bash -s stable
source /etc/profile.d/rvm.sh source /etc/profile.d/rvm.sh
rvm install 2.3.1 rvm install 2.3.6
rvm use 2.3.1 --default rvm use 2.3.6 --default
ruby -v ruby -v
# rails # rails
apt-get -y install nodejs apt-get -y install nodejs
gem install rails -v 4.2.1 gem install rails -v 4.2.10
# drop postgres access control # drop postgres access control
if ! grep -q code_ocean /etc/postgresql/9.5/main/pg_hba.conf if ! grep -q code_ocean /etc/postgresql/10/main/pg_hba.conf
then then
cat >/etc/postgresql/9.3/main/pg_hba.conf <<EOF cat >/etc/postgresql/10/main/pg_hba.conf <<EOF
# code_ocean: drop access control # code_ocean: drop access control
local all all trust local all all trust
host all all 127.0.0.1/32 trust host all all 127.0.0.1/32 trust
@ -110,7 +110,7 @@ passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
server { server {
server_name codeocean.local; server_name codeocean.local;
root /vagrant/public; root /vagrant/public;
passenger_ruby /usr/local/rvm/gems/ruby-2.1.5/wrappers/ruby; passenger_ruby /usr/local/rvm/gems/ruby-2.3.6/wrappers/ruby;
passenger_sticky_sessions on; passenger_sticky_sessions on;
passenger_enabled on; passenger_enabled on;
passenger_app_env development; passenger_app_env development;

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

View File

@ -98,7 +98,7 @@ describe Lti do
let(:consumer) { FactoryBot.create(:consumer) } let(:consumer) { FactoryBot.create(:consumer) }
let(:score) { 0.5 } let(:score) { 0.5 }
let(:submission) { FactoryBot.create(:submission) } let(:submission) { FactoryBot.create(:submission) }
let!(:lti_parameter) { FactoryBot.create(:lti_parameter)} let!(:lti_parameter) { FactoryBot.create(:lti_parameter, consumers_id: consumer.id, external_users_id: submission.user_id, exercises_id: submission.exercise_id)}
context 'with an invalid score' do context 'with an invalid score' do
it 'raises an exception' do it 'raises an exception' do
@ -114,7 +114,6 @@ describe Lti do
context 'when grading is not supported' do context 'when grading is not supported' do
it 'returns a corresponding status' do it 'returns a corresponding status' do
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
expect_any_instance_of(IMS::LTI::ToolProvider).to receive(:outcome_service?).and_return(false) expect_any_instance_of(IMS::LTI::ToolProvider).to receive(:outcome_service?).and_return(false)
expect(controller.send(:send_score, submission.exercise_id, score, submission.user_id)[:status]).to eq('unsupported') expect(controller.send(:send_score, submission.exercise_id, score, submission.user_id)[:status]).to eq('unsupported')
end end
@ -133,12 +132,10 @@ describe Lti do
end end
it 'sends the score' do it 'sends the score' do
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
controller.send(:send_score, submission.exercise_id, score, submission.user_id) controller.send(:send_score, submission.exercise_id, score, submission.user_id)
end end
it 'returns code, message, and status' do it 'returns code, message, and status' do
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
result = controller.send(:send_score, submission.exercise_id, score, submission.user_id) result = controller.send(:send_score, submission.exercise_id, score, submission.user_id)
expect(result[:code]).to eq(response.response_code) expect(result[:code]).to eq(response.response_code)
expect(result[:message]).to eq(response.body) expect(result[:message]).to eq(response.body)

View File

@ -2,6 +2,7 @@ FactoryBot.define do
factory :user_exercise_feedback, class: UserExerciseFeedback do factory :user_exercise_feedback, class: UserExerciseFeedback do
created_by_external_user created_by_external_user
feedback_text 'Most suitable exercise ever' feedback_text 'Most suitable exercise ever'
association :exercise, factory: :math
end end
end end

View File

@ -2,12 +2,22 @@ require 'rails_helper'
require 'seeds_helper' require 'seeds_helper'
describe DockerClient, docker: true do describe DockerClient, docker: true do
WORKSPACE_PATH = '/tmp/code_ocean_test'
let(:command) { 'whoami' } let(:command) { 'whoami' }
let(:docker_client) { described_class.new(execution_environment: FactoryBot.build(:java), user: FactoryBot.build(:admin)) } let(:docker_client) { described_class.new(execution_environment: FactoryBot.build(:java), user: FactoryBot.build(:admin)) }
let(:execution_environment) { FactoryBot.build(:java) } let(:execution_environment) { FactoryBot.build(:java) }
let(:image) { double } let(:image) { double }
let(:submission) { FactoryBot.create(:submission) } let(:submission) { FactoryBot.create(:submission) }
let(:workspace_path) { '/tmp' } let(:workspace_path) { WORKSPACE_PATH }
before(:all) do
FileUtils.mkdir_p(WORKSPACE_PATH)
end
after(:all) do
FileUtils.rm_rf(WORKSPACE_PATH)
end
describe '.check_availability!' do describe '.check_availability!' do
context 'when a socket error occurs' do context 'when a socket error occurs' do
@ -129,7 +139,7 @@ describe DockerClient, docker: true do
after(:each) { docker_client.send(:create_workspace_files, container, submission) } after(:each) { docker_client.send(:create_workspace_files, container, submission) }
it 'creates submission-specific directories' do it 'creates submission-specific directories' do
expect(Dir).to receive(:mkdir).at_least(:once) expect(Dir).to receive(:mkdir).at_least(:once).and_call_original
end end
it 'copies binary files' do it 'copies binary files' do

View File

@ -16,13 +16,8 @@
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
unless RUBY_PLATFORM == 'java' unless RUBY_PLATFORM == 'java'
if ENV['CODECLIMATE_REPO_TOKEN']
require 'codeclimate-test-reporter'
CodeClimate::TestReporter.start
else
require 'simplecov' require 'simplecov'
SimpleCov.start('rails') SimpleCov.start('rails')
end
end end
RSpec.configure do |config| RSpec.configure do |config|

View File

@ -1,6 +1,5 @@
FactoryBot.define do FactoryBot.define do
factory :error_template_attribute do factory :error_template_attribute do
error_template nil
key "MyString" key "MyString"
regex "MyString" regex "MyString"
end end

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long