From 08a56d2af2c1e07592a5365c9b568b3d4855824f Mon Sep 17 00:00:00 2001 From: Joel Scheuner Date: Thu, 1 Sep 2016 11:26:41 +0200 Subject: [PATCH] Provide a message for unsatisfiable recommendations to fix #122 * Parse the `stderr` yielded if a recommendation is unsatisfiable * Append the corresponding line as `unsatisfiable_message` in more_attributes --- app/models/deployment_recommendation.rb | 27 ++++++++++++++++--- test/models/deployment_recommendation_test.rb | 1 + 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app/models/deployment_recommendation.rb b/app/models/deployment_recommendation.rb index 25342d4..cb42a0f 100644 --- a/app/models/deployment_recommendation.rb +++ b/app/models/deployment_recommendation.rb @@ -47,10 +47,10 @@ def generate ingredients.write self.ingredients_data ingredients.close - command = "minizinc -G or-tools -f fzn-or-tools #{Rails.root}/lib/stove.mzn #{resources.path} #{ingredients.path}" + command = "minizinc -G or-tools -f fzn-or-tools #{minizinc_model} #{resources.path} #{ingredients.path}" stdout, stderr, status = Open3.capture3(command) if status.success? - parse_result(stdout) + parse_result(stdout, stderr) else fail [ 'Error executing MiniZinc!', '----------stdout----------', @@ -65,7 +65,11 @@ def generate ingredients.unlink end - def parse_result(stdout) + def minizinc_model + "#{Rails.root}/lib/stove.mzn" + end + + def parse_result(stdout, stderr) result = extract_result(stdout) if satisfiable?(result) self.more_attributes = result @@ -85,10 +89,27 @@ def parse_result(stdout) self.save! else self.status = UNSATISFIABLE + self.more_attributes = unsatisfiable_msg(stderr) self.save! end end + def unsatisfiable_msg(stderr) + line = line_with_error(stderr) + { unsatisfiable_message: line_from_minizinc_model(line) } + rescue NoMethodError + { unsatisfiable_message: 'Could not localize MiniZinc error!' } + end + + def line_from_minizinc_model(line) + File.readlines(minizinc_model)[line - 1].strip + end + + MINIZINC_ERROR_REGEX = /lib\/stove\.mzn:(\d+):/ + def line_with_error(stderr) + MINIZINC_ERROR_REGEX.match(stderr)[1].to_i + end + def extract_result(output) output.gsub!(', ]', ']') results = output.split(SOLN_SEP) diff --git a/test/models/deployment_recommendation_test.rb b/test/models/deployment_recommendation_test.rb index c8797ab..29c3fb8 100644 --- a/test/models/deployment_recommendation_test.rb +++ b/test/models/deployment_recommendation_test.rb @@ -98,5 +98,6 @@ def load_seed(name) recommendation = DeploymentRecommendation.construct(rails_app) # Google provider factories have no instance available to satisfy the 4G RAM constraint assert_equal 'unsatisfiable', recommendation.status + assert_equal 'constraint forall(i in Ingredients)(ram[assignments[i]] >= min_ram[i]);', recommendation.more_attributes['unsatisfiable_message'] end end