From d22d24df4daa286f921c1d00b586e1eb3aeedc9a Mon Sep 17 00:00:00 2001 From: Konrad Hanff Date: Tue, 1 Jun 2021 14:39:30 +0200 Subject: [PATCH] Add tests for execution environment copy to Poseidon --- .../execution_environments_controller_spec.rb | 22 +++++- spec/factories/execution_environment.rb | 13 ++++ spec/models/execution_environment_spec.rb | 75 +++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/spec/controllers/execution_environments_controller_spec.rb b/spec/controllers/execution_environments_controller_spec.rb index 6736a18b..3507fc8a 100644 --- a/spec/controllers/execution_environments_controller_spec.rb +++ b/spec/controllers/execution_environments_controller_spec.rb @@ -6,7 +6,10 @@ describe ExecutionEnvironmentsController do let(:execution_environment) { FactoryBot.create(:ruby) } let(:user) { FactoryBot.create(:admin) } - before { allow(controller).to receive(:current_user).and_return(user) } + before do + allow(controller).to receive(:current_user).and_return(user) + allow(controller).to receive(:copy_execution_environment_to_poseidon).and_return(nil) + end describe 'POST #create' do before { allow(DockerClient).to receive(:image_tags).at_least(:once).and_return([]) } @@ -23,6 +26,10 @@ describe ExecutionEnvironmentsController do expect { perform_request.call }.to change(ExecutionEnvironment, :count).by(1) end + it 'registers the execution environment with Poseidon' do + expect(controller).to have_received(:copy_execution_environment_to_poseidon) + end + expect_redirect(ExecutionEnvironment.last) end @@ -32,6 +39,10 @@ describe ExecutionEnvironmentsController do expect_assigns(execution_environment: ExecutionEnvironment) expect_status(200) expect_template(:new) + + it 'does not register the execution environment with Poseidon' do + expect(controller).not_to have_received(:copy_execution_environment_to_poseidon) + end end end @@ -156,12 +167,17 @@ describe ExecutionEnvironmentsController do context 'with a valid execution environment' do before do allow(DockerClient).to receive(:image_tags).at_least(:once).and_return([]) + allow(controller).to receive(:copy_execution_environment_to_poseidon).and_return(nil) put :update, params: {execution_environment: FactoryBot.attributes_for(:ruby), id: execution_environment.id} end expect_assigns(docker_images: Array) expect_assigns(execution_environment: ExecutionEnvironment) expect_redirect(:execution_environment) + + it 'updates the execution environment at Poseidon' do + expect(controller).to have_received(:copy_execution_environment_to_poseidon) + end end context 'with an invalid execution environment' do @@ -170,6 +186,10 @@ describe ExecutionEnvironmentsController do expect_assigns(execution_environment: ExecutionEnvironment) expect_status(200) expect_template(:edit) + + it 'does not update the execution environment at Poseidon' do + expect(controller).not_to have_received(:copy_execution_environment_to_poseidon) + end end end end diff --git a/spec/factories/execution_environment.rb b/spec/factories/execution_environment.rb index 2b671575..9d145031 100644 --- a/spec/factories/execution_environment.rb +++ b/spec/factories/execution_environment.rb @@ -4,6 +4,7 @@ FactoryBot.define do factory :coffee_script, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'hklement/ubuntu-coffee:latest' } file_type { association :dot_coffee, user: user } help @@ -18,6 +19,7 @@ FactoryBot.define do factory :html, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'hklement/ubuntu-html:latest' } file_type { association :dot_html, user: user } help @@ -34,6 +36,7 @@ FactoryBot.define do factory :java, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'openhpi/co_execenv_java:8' } file_type { association :dot_java, user: user } help @@ -50,6 +53,7 @@ FactoryBot.define do factory :jruby, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'hklement/ubuntu-jruby:latest' } file_type { association :dot_rb, user: user } help @@ -66,6 +70,7 @@ FactoryBot.define do factory :node_js, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'hklement/ubuntu-node:latest' } file_type { association :dot_js, user: user } help @@ -80,6 +85,7 @@ FactoryBot.define do factory :python, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'openhpi/co_execenv_python:3.4' } file_type { association :dot_py, user: user } help @@ -96,6 +102,7 @@ FactoryBot.define do factory :ruby, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'hklement/ubuntu-ruby:latest' } file_type { association :dot_rb, user: user } help @@ -112,6 +119,7 @@ FactoryBot.define do factory :sinatra, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'hklement/ubuntu-sinatra:latest' } file_type { association :dot_rb, user: user } exposed_ports { '4567' } @@ -129,6 +137,7 @@ FactoryBot.define do factory :sqlite, class: 'ExecutionEnvironment' do created_by_teacher default_memory_limit + default_cpu_limit docker_image { 'hklement/ubuntu-sqlite:latest' } file_type { association :dot_sql, user: user } help @@ -146,6 +155,10 @@ FactoryBot.define do memory_limit { DockerClient::DEFAULT_MEMORY_LIMIT } end + trait :default_cpu_limit do + cpu_limit { 20 } + end + trait :help do help { Forgery(:lorem_ipsum).words(Forgery(:basic).number(at_least: 50, at_most: 100)) } end diff --git a/spec/models/execution_environment_spec.rb b/spec/models/execution_environment_spec.rb index b2edd346..54e01111 100644 --- a/spec/models/execution_environment_spec.rb +++ b/spec/models/execution_environment_spec.rb @@ -30,6 +30,21 @@ describe ExecutionEnvironment do expect(execution_environment.errors[:memory_limit]).to be_present end + it 'validates the minimum value of the cpu limit' do + execution_environment.update(cpu_limit: 0) + expect(execution_environment.errors[:cpu_limit]).to be_present + end + + it 'validates that cpu limit is an integer' do + execution_environment.update(cpu_limit: Math::PI) + expect(execution_environment.errors[:cpu_limit]).to be_present + end + + it 'validates the presence of a cpu limit' do + execution_environment.update(cpu_limit: nil) + expect(execution_environment.errors[:cpu_limit]).to be_present + end + it 'validates the presence of a name' do expect(execution_environment.errors[:name]).to be_present end @@ -69,6 +84,14 @@ describe ExecutionEnvironment do expect(execution_environment.errors[:user_type]).to be_present end + it 'validates the format of the exposed ports' do + execution_environment.update(exposed_ports: '1,') + expect(execution_environment.errors[:exposed_ports]).to be_present + + execution_environment.update(exposed_ports: '1,a') + expect(execution_environment.errors[:exposed_ports]).to be_present + end + describe '#valid_test_setup?' do context 'with a test command and a testing framework' do before { execution_environment.update(test_command: FactoryBot.attributes_for(:ruby)[:test_command], testing_framework: FactoryBot.attributes_for(:ruby)[:testing_framework]) } @@ -153,4 +176,56 @@ describe ExecutionEnvironment do end end end + + describe '#exposed_ports_list' do + it 'returns an empty array if no ports are exposed' do + execution_environment.exposed_ports = nil + expect(execution_environment.exposed_ports_list).to eq([]) + end + + it 'returns an array of integers representing the exposed ports' do + execution_environment.exposed_ports = '1,2,3' + expect(execution_environment.exposed_ports_list).to eq([1, 2, 3]) + + execution_environment.exposed_ports_list.each do |port| + expect(execution_environment.exposed_ports).to include(port.to_s) + end + end + end + + describe '#copy_to_poseidon' do + let(:execution_environment) { FactoryBot.create(:ruby) } + + it 'makes the correct request to Poseidon' do + allow(Faraday).to receive(:put).and_return(Faraday::Response.new(status: 201)) + execution_environment.copy_to_poseidon + expect(Faraday).to have_received(:put) do |url, body, headers| + expect(url).to match(%r{execution-environments/#{execution_environment.id}\z}) + expect(body).to eq(execution_environment.to_json) + expect(headers).to include({'Content-Type' => 'application/json'}) + end + end + + shared_examples 'returns true when the api request was successful' do |status| + it "returns true on status #{status}" do + allow(Faraday).to receive(:put).and_return(Faraday::Response.new(status: status)) + expect(execution_environment.copy_to_poseidon).to be_truthy + end + end + + shared_examples 'returns false when the api request failed' do |status| + it "returns false on status #{status}" do + allow(Faraday).to receive(:put).and_return(Faraday::Response.new(status: status)) + expect(execution_environment.copy_to_poseidon).to be_falsey + end + end + + [201, 204].each do |status| + include_examples 'returns true when the api request was successful', status + end + + [400, 500].each do |status| + include_examples 'returns false when the api request failed', status + end + end end