mumukit 2.17.0 → 2.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b678748b9bbd865a42951a22eb71244968362faf551452fdfe4d0a9f14889fda
4
- data.tar.gz: 42ea663c41b564d65222f11d7baa5b7447a2e49b053eb8579b4ec2d8ad814268
3
+ metadata.gz: aa9b52569d8acc92b3996ab2797748cb26b04c8b424eabe47c8ea1fcd8f554a0
4
+ data.tar.gz: 18a004a9b5ccf64c278952ac02ac3fc1f5942c3acbd06ed583c5623c8c422f49
5
5
  SHA512:
6
- metadata.gz: bbb8f3d2905dc3b02b600efb96609bbfb888410228822d40ad55977e59aee51683d1842afb8faa5816b3c76a846639bd4de364f707bc0600d4817c8184b6f785
7
- data.tar.gz: 0cfadb4c1dc8c55e3ed8b903c0d3d05c2217f56d39845bca17fcc97ac6888b8d5bfa7ca2c48f87f714849ed52a86302eb2893d3168b64c553d915bb975331ba5
6
+ metadata.gz: 7c403421b59fde8fb7a27ca8448d43a1331b86d590199278b5bf26f7ae76c165220ab67d97bf6eff63c8a082aa1b3de59ab51e1b90968dbf7056c2db36182603
7
+ data.tar.gz: a03dba8b04f49b4dfa4a0127db26021f47d6d9ca550ef8bd0ac30c2578c660ac990701622e887120293369c7c2efdebd290c87a2cf8c4b6763ab9abe2a7b44fb
data/lib/locales/en.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  en:
2
2
  mumukit:
3
- memory_exceeded: Memory limit exceeded. Is your program trying to allocate to much memory?
3
+ memory_exceeded: Memory limit exceeded. Is your program trying to allocate too much memory?
4
4
  time_exceeded: Execution time limit of %{limit}s exceeded. Is your program performing an infinite loop or recursion?
5
5
  masked_tempfile_basename: solution
6
6
  interactive:
@@ -8,6 +8,8 @@ en:
8
8
  check_last_query_fails: "query should fail but it passed"
9
9
  check_last_query_matches: "query does not match regex %{regex}"
10
10
  check_last_query_outputs: "query output should be '%{expected}' but was '%{actual}'"
11
+ check_last_query_includes: "query output should include '%{expected}' but was '%{actual}'"
12
+ check_last_query_like: "query output should be like '%{expected}' but was '%{actual}'"
11
13
  check_last_query_passes: "query should pass but it failed"
12
14
  check_query_fails: "query '%{query}' should fail but it passed"
13
15
  check_query_outputs: "query '%{query}' output should be '%{expected}' but was '%{actual}'"
data/lib/locales/es.yml CHANGED
@@ -8,6 +8,8 @@ es:
8
8
  check_last_query_fails: "La consulta debería fallar pero pasó"
9
9
  check_last_query_matches: "La consulta no cumple con la expresión regular %{regex}"
10
10
  check_last_query_outputs: "La consulta debería devolver '%{expected}' pero devolvió '%{actual}'"
11
+ check_last_query_includes: "La consulta debería incluir '%{expected}' pero devolvió '%{actual}'"
12
+ check_last_query_like: "La consulta debería ser como '%{expected}' pero devolvió '%{actual}'"
11
13
  check_last_query_passes: "La consulta debería pasar pero falló"
12
14
  check_query_fails: "La consulta '%{query}' debería fallar pero pasó"
13
15
  check_query_outputs: "La consulta '%{query}' debería devolver '%{expected}' pero devolvió '%{actual}'"
@@ -0,0 +1,17 @@
1
+ pt:
2
+ mumukit:
3
+ memory_exceeded: Limite de memoria excedido. ¿Tu programa está alocando demasiada memoria?
4
+ time_exceeded: Limite de tempo de execução de %{limit}s excedido. O seu programa está executando um loop ou recursão infinito?
5
+ masked_tempfile_basename: solução
6
+ interactive:
7
+ check_last_query_equals: "a consulta deve ser '%{expected}' mas foi '%{actual}'"
8
+ check_last_query_fails: "a consulta deve falhar, mas passou"
9
+ check_last_query_matches: "A consulta não corresponde a regex %{regex}"
10
+ check_last_query_outputs: "O resultado da consulta deve ser '%{expected}', mas foi '%{actual}'"
11
+ check_last_query_includes: "O resultado da consulta deve incluir '%{expected}', mas foi '%{actual}'"
12
+ check_last_query_like: "O resultado da consulta deve ser como '%{expected}', mas foi '%{actual}'"
13
+ check_last_query_passes: "A consulta deve passar, mas falhou"
14
+ check_query_fails: "a consulta '%{query}' deve falhar, mas passou"
15
+ check_query_outputs: "a consulta '%{query}' deve ser '%{expected}', mas foi '%{actual}'"
16
+ check_query_passes: "a consulta '%{query}' deve passar, mas falhou"
17
+ goal_passed: "O objetivo foi alcançado com sucesso"
@@ -0,0 +1,5 @@
1
+ class Mumukit::Defaults::PrecompileHook < Mumukit::Hook
2
+ def compile(request)
3
+ request
4
+ end
5
+ end
@@ -9,5 +9,6 @@ require_relative './defaults/default_query_hook'
9
9
  require_relative './defaults/default_feedback_hook'
10
10
  require_relative './defaults/default_validation_hook'
11
11
  require_relative './defaults/default_test_hook'
12
+ require_relative './defaults/default_precompile_hook'
12
13
  require_relative './defaults/default_try_hook'
13
- require_relative './defaults/default_metadata_hook'
14
+ require_relative './defaults/default_metadata_hook'
@@ -1,10 +1,39 @@
1
1
  module Mumukit::Metatest
2
2
  class Checker
3
- def check(result, example)
4
- example[:postconditions].each { |key, arg| check_assertion key, result, arg, example }
5
- [example[:name], :passed, render_success_output(result)]
3
+
4
+ ## Check an input against a metatest example.
5
+ ## The example has the following shape:
6
+ ##
7
+ ## ```
8
+ ## {
9
+ ## name: 'an example name',
10
+ ## postconditions: {
11
+ ## an_assertion: assertion_config,
12
+ ## another_assertion: assertion_config,
13
+ ## }
14
+ ## }
15
+ ## ```
16
+ ##
17
+ ## Alternatively, the `postconditions` key may be omitted:
18
+ ##
19
+ ## ```
20
+ ## {
21
+ ## name: 'an example name',
22
+ ## an_assertion: assertion_config,
23
+ ## another_assertion: assertion_config,
24
+ ## }
25
+ ##
26
+ def check(input, example)
27
+ check_assertions input, postconditions_for(example), example
28
+ [example[:name], :passed, render_success_output(input)]
6
29
  rescue => e
7
- [example[:name], :failed, render_error_output(result, e.message)]
30
+ [example[:name], :failed, render_error_output(input, e.message)]
31
+ end
32
+
33
+ ## If no postconditions are included in the example,
34
+ ## all the example except by the name is considered as postconditions
35
+ def postconditions_for(example)
36
+ example[:postconditions] || example.except(:name)
8
37
  end
9
38
 
10
39
  def render_success_output(value)
@@ -15,8 +44,14 @@ module Mumukit::Metatest
15
44
  error
16
45
  end
17
46
 
18
- def check_assertion(key, result, arg, example)
19
- send "check_#{key}", result, arg
47
+ def check_assertions(input, assertions_hash, example)
48
+ assertions_hash.each do |assertion_name, assertion_config|
49
+ check_assertion assertion_name, input, assertion_config, example
50
+ end
51
+ end
52
+
53
+ def check_assertion(assertion_name, input, assertion_config, _example)
54
+ send "check_#{assertion_name}", input, assertion_config
20
55
  end
21
56
 
22
57
  def fail(message)
@@ -31,4 +66,4 @@ module Mumukit::Metatest
31
66
  raise Mumukit::Metatest::Errored, message
32
67
  end
33
68
  end
34
- end
69
+ end
@@ -6,42 +6,54 @@ module Mumukit::Metatest
6
6
  end
7
7
 
8
8
  def check_last_query_equals(_result, goal)
9
- expected = goal[:query]
10
- actual = @request.query
9
+ expected = goal[:value]
10
+ actual = @request.query.strip
11
11
  fail_t :check_last_query_equals, expected: expected, actual: actual unless expected == actual
12
12
  end
13
13
 
14
14
  def check_last_query_matches(_result, goal)
15
- regex = goal[:regex]
15
+ regex = goal[:regexp]
16
16
  fail_t :check_last_query_matches, regex: regex.inspect unless regex.matches? @request.query
17
17
  end
18
18
 
19
19
  def check_last_query_fails(result, _goal)
20
- fail_t :check_last_query_fails unless result[:query][:status] == :failed
20
+ fail_t :check_last_query_fails unless result[:query][:status].failed?
21
21
  end
22
22
 
23
23
  def check_last_query_outputs(result, goal)
24
- expected = goal.with_indifferent_access[:output]
24
+ compare_last_query_by(:check_last_query_outputs, result, goal) { |expected, actual| expected == actual }
25
+ end
26
+
27
+ def check_last_query_output_includes(result, goal)
28
+ compare_last_query_by(:check_last_query_output_includes, result, goal) { |expected, actual| actual.include? expected }
29
+ end
30
+
31
+ def check_last_query_output_like(result, goal)
32
+ compare_last_query_by(:check_last_query_output_like, result, goal) { |expected, actual| normalize(expected) == normalize(actual) }
33
+ end
34
+
35
+ def compare_last_query_by(sym, result, goal, &condition)
36
+ expected = goal[:output]
25
37
  actual = result[:query][:result]
26
- fail_t :check_last_query_outputs, expected: expected, actual: actual unless expected == actual
38
+ fail_t sym, expected: expected, actual: actual unless condition.call expected, actual
27
39
  end
28
40
 
29
41
  def check_last_query_passes(result, _goal)
30
- fail_t :check_last_query_passes unless result[:query][:status] == :passed
42
+ fail_t :check_last_query_passes unless result[:query][:status].passed?
31
43
  end
32
44
 
33
45
  def check_query_passes(result, goal)
34
- fail_t :check_query_passes, query: goal.with_indifferent_access[:query] unless result[:status] == :passed
46
+ fail_t :check_query_passes, query: goal[:query] unless result[:status].passed?
35
47
  end
36
48
 
37
49
  def check_query_fails(result, goal)
38
- fail_t :check_query_fails, query: goal.with_indifferent_access[:query] unless result[:status] == :failed
50
+ fail_t :check_query_fails, query: goal[:query] unless result[:status].failed?
39
51
  end
40
52
 
41
53
  def check_query_outputs(result, goal)
42
- expected = goal.with_indifferent_access[:output]
54
+ expected = goal[:output]
43
55
  actual = result[:goal]
44
- fail_t :check_query_outputs, query: goal.with_indifferent_access[:query], expected: expected, actual: actual unless expected == actual
56
+ fail_t :check_query_outputs, query: goal[:query], expected: expected, actual: actual unless expected == actual
45
57
  end
46
58
 
47
59
  def render_success_output(_value)
@@ -55,5 +67,10 @@ module Mumukit::Metatest
55
67
  def locale(sym)
56
68
  'mumukit.interactive.' + sym.to_s
57
69
  end
70
+
71
+ def normalize(a_string)
72
+ a_string.delete(" \t\r\n").downcase
73
+ end
74
+
58
75
  end
59
76
  end
@@ -11,6 +11,12 @@ class Mumukit::Runner
11
11
  yield @config
12
12
  end
13
13
 
14
+ def reconfigure(&block)
15
+ @config = nil
16
+ @pipeline = nil
17
+ configure &block
18
+ end
19
+
14
20
  def configure_runtime(config)
15
21
  @runtime = Mumukit::Runtime.new(config)
16
22
  end
@@ -30,16 +36,29 @@ class Mumukit::Runner
30
36
  def new_directives_pipeline
31
37
  if config.preprocessor_enabled
32
38
  Mumukit::Directives::Pipeline.new(
33
- [Mumukit::Directives::Sections.new,
34
- Mumukit::Directives::Interpolations.new('test'),
35
- Mumukit::Directives::Interpolations.new('extra'),
36
- Mumukit::Directives::Flags.new],
39
+ [new_sections_directive,
40
+ new_interpolations_directive('test'),
41
+ new_interpolations_directive('extra'),
42
+ new_interpolations_directive('content'),
43
+ new_flags_directive],
37
44
  config.comment_type)
38
45
  else
39
46
  Mumukit::Directives::NullPipeline
40
47
  end
41
48
  end
42
49
 
50
+ def new_interpolations_directive(key)
51
+ Mumukit::Directives::Interpolations.new(key)
52
+ end
53
+
54
+ def new_sections_directive
55
+ Mumukit::Directives::Sections.new nest_sections: Mumukit.config.multifile
56
+ end
57
+
58
+ def new_flags_directive
59
+ Mumukit::Directives::Flags.new
60
+ end
61
+
43
62
  def self.default_config
44
63
  @default_config
45
64
  end
@@ -48,4 +67,4 @@ class Mumukit::Runner
48
67
  @default_config ||= OpenStruct.new
49
68
  yield @default_config
50
69
  end
51
- end
70
+ end
@@ -6,19 +6,22 @@ module Mumukit::RuntimeInfo
6
6
  escualo_base_version: ENV['ESCUALO_BASE_VERSION'],
7
7
  escualo_service_version: ENV['ESCUALO_SERVICE_VERSION'],
8
8
  mumukit_version: Mumukit::VERSION,
9
+ worker_image: Mumukit.config.docker_image,
9
10
  output_content_type: Mumukit.config.content_type,
10
11
  comment_type: Mumukit.config.comment_type,
11
12
  features: {
12
- query: query_hook?,
13
- try: try_hook?,
14
- expectations: expectations_hook?,
15
- feedback: feedback_hook?,
16
- secure: validation_hook?,
17
- stateful: Mumukit.config.stateful,
18
- preprocessor: Mumukit.config.preprocessor_enabled,
13
+ precompile: precompile_hook?,
14
+ query: query_hook?,
15
+ try: try_hook?,
16
+ expectations: expectations_hook?,
17
+ feedback: feedback_hook?,
18
+ secure: validation_hook?,
19
+ stateful: Mumukit.config.stateful,
20
+ multifile: Mumukit.config.multifile,
21
+ preprocessor: Mumukit.config.preprocessor_enabled,
19
22
 
20
- sandboxed: any_hook_include?([:test, :query], Mumukit::Templates::WithIsolatedEnvironment),
21
- structured: any_hook_include?([:test], Mumukit::Templates::WithStructuredResults) || Mumukit.config.structured
23
+ sandboxed: any_hook_include?([:test, :query], Mumukit::Templates::WithIsolatedEnvironment),
24
+ structured: any_hook_include?([:test], Mumukit::Templates::WithStructuredResults) || Mumukit.config.structured
22
25
  }
23
26
  }
24
27
  end
@@ -28,4 +31,4 @@ module Mumukit::RuntimeInfo
28
31
  def any_hook_include?(hooks, mixin)
29
32
  hooks.any? { |it| hook_includes?(it, mixin) }
30
33
  end
31
- end
34
+ end
@@ -6,7 +6,7 @@ require 'json'
6
6
  class Mumukit::Server::App < Sinatra::Base
7
7
  configure do
8
8
  set :mumuki_url, 'http://mumuki.io'
9
- set :show_exceptions, :after_handler
9
+ set :show_exceptions, false
10
10
  enable :logging
11
11
  end
12
12
 
@@ -65,11 +65,8 @@ class Mumukit::Server::App < Sinatra::Base
65
65
 
66
66
  error StandardError do
67
67
  content_type :json
68
- status 200
69
-
68
+ status 500
70
69
  message = Mumukit::ContentType::Plain.format_exception env['sinatra.error']
71
- logger.error "Unhandled error #{message}"
72
-
73
- {status: :errored, exit: message}.to_json
70
+ {exit: :errored, out: message}.to_json
74
71
  end
75
72
  end
@@ -10,7 +10,10 @@ class Mumukit::Server::TestServer
10
10
  end
11
11
 
12
12
  def info(url)
13
- runtime.info.merge(runtime.metadata_hook.metadata).merge(url: url)
13
+ runtime.info
14
+ .merge(repo_url: default_repo_url)
15
+ .merge(runtime.metadata_hook.metadata)
16
+ .merge(url: url)
14
17
  end
15
18
 
16
19
  def start_request!(_request)
@@ -58,13 +61,13 @@ class Mumukit::Server::TestServer
58
61
  end
59
62
 
60
63
  def run_tests!(request)
61
- return ['', :passed] if request.test.blank?
64
+ return ['', :passed] if should_skip_tests?(request.test)
62
65
 
63
66
  compile_and_run runtime.test_hook, request
64
67
  end
65
68
 
66
69
  def run_expectations!(request)
67
- return [] if request.expectations.nil? || request.content.nil?
70
+ return [] if should_skip_expectations?(request)
68
71
 
69
72
  compile_and_run runtime.expectations_hook, request
70
73
  end
@@ -91,19 +94,30 @@ class Mumukit::Server::TestServer
91
94
  end
92
95
 
93
96
  def preprocess(request)
94
- Mumukit.directives_pipeline.transform(request)
97
+ runtime.precompile_hook.compile Mumukit.directives_pipeline.transform(request)
95
98
  end
96
99
 
97
100
  def validate_request!(request)
98
101
  runtime.validation_hook.validate! request
99
102
  end
100
103
 
104
+ def should_skip_expectations?(request)
105
+ request.expectations.nil? || (request.content.nil? && !Mumukit.config.process_expectations_on_empty_content)
106
+ end
107
+
108
+ def should_skip_tests?(tests)
109
+ tests.blank? && !Mumukit.config.run_test_hook_on_empty_test
110
+ end
111
+
101
112
  def respond_to(request)
102
113
  yield preprocess request.tap { |r| validate_request! r }
103
114
  rescue Mumukit::RequestValidationError => e
104
115
  {exit: :aborted, out: e.message}
105
- rescue Exception => e
116
+ rescue => e
106
117
  {exit: :errored, out: content_type.format_exception(e)}
107
118
  end
108
119
 
120
+ def default_repo_url
121
+ "https://github.com/mumuki/mumuki-#{Mumukit.runner_name}-runner"
122
+ end
109
123
  end
@@ -0,0 +1,81 @@
1
+ require 'mumukit/inspection'
2
+
3
+ module Mumukit
4
+ class Templates::ExpectationsHook < Mumukit::Hook
5
+ SOURCE_EXPECTATION_EVALUATORS = {
6
+ 'SourceRepeats' => lambda { |source, target| source.scan(target).count > 1 },
7
+ 'SourceContains' => lambda { |source, target| source.include? target },
8
+ 'SourceEquals' => lambda { |source, target| source == target },
9
+ 'SourceEqualsIgnoreSpaces' => lambda { |source, target| source.delete(' ') == target.delete(' ') }
10
+ }
11
+ SOURCE_EXPECTATIONS = SOURCE_EXPECTATION_EVALUATORS.keys.flat_map { |it| [it, "Not:#{it}"] }
12
+
13
+ def compile(request)
14
+ { request: request, expectations: compile_expectations(request) }
15
+ end
16
+
17
+ def run!(spec)
18
+ spec[:expectations][:source].map { |it| it.evaluate spec[:request][:content] }
19
+ end
20
+
21
+ private
22
+
23
+ def compile_expectations(request)
24
+ expectations = {ast: [], source: [], exceptions: []}
25
+ request[:expectations].each do |it|
26
+ fill_expectations it.deep_symbolize_keys, expectations
27
+ end
28
+ expectations
29
+ end
30
+
31
+ def fill_expectations(expectation, expectations)
32
+ inspection = expectation[:inspection]
33
+ if inspection&.start_with? 'Except:'
34
+ expectations[:exceptions] << inspection[7..-1]
35
+ elsif SOURCE_EXPECTATIONS.any? { |it| inspection.starts_with? it }
36
+ expectations[:source] << compile_source_expectation(expectation)
37
+ else
38
+ expectations[:ast] << compile_expectation(expectation)
39
+ end
40
+ end
41
+
42
+ def compile_expectation(expectation)
43
+ Mumukit::Inspection::Expectation.parse(expectation).as_v2.to_h
44
+ end
45
+
46
+ def compile_source_expectation(expectation)
47
+ SourceExpectation.parse(expectation)
48
+ end
49
+
50
+ class SourceExpectation
51
+ def initialize(expectation, evaluator)
52
+ @expectation = expectation
53
+ @evaluator = evaluator
54
+ end
55
+
56
+ def evaluate(content)
57
+ { result: evaluate_inspection(content), expectation: @expectation.to_h }
58
+ end
59
+
60
+ def inspection
61
+ @expectation.inspection
62
+ end
63
+
64
+ def self.parse(expectation)
65
+ parsed = Mumukit::Inspection::Expectation.parse(expectation)
66
+ evaluator = parse_evaluator(parsed.inspection)
67
+ new parsed, evaluator
68
+ end
69
+
70
+ private
71
+
72
+ def evaluate_inspection(content)
73
+ inspection.negated? ^ @evaluator.call(content, inspection.target.value)
74
+ end
75
+
76
+ def self.parse_evaluator(inspection)
77
+ SOURCE_EXPECTATION_EVALUATORS[inspection.type]
78
+ end
79
+ end
80
+ end
81
+ end
@@ -4,7 +4,6 @@ module Mumukit
4
4
 
5
5
  attr_accessor :request
6
6
 
7
-
8
7
  def compile(request)
9
8
  self.request = request
10
9
  write_tempfile! compile_file_content(request)
@@ -1,29 +1,31 @@
1
- require 'mumukit/inspection'
2
1
  require 'mulang'
3
2
 
4
3
  module Mumukit
5
- class Templates::MulangExpectationsHook < Mumukit::Hook
4
+ class Templates::MulangExpectationsHook < Mumukit::Templates::ExpectationsHook
6
5
  LOGIC_SMELLS = %w(UsesCut UsesFail UsesUnificationOperator HasRedundantReduction)
7
6
  FUNCTIONAL_SMELLS = %w(HasRedundantParameter HasRedundantGuards)
8
7
  OBJECT_ORIENTED_SMELLS = %w(DoesNullTest ReturnsNull)
9
8
  IMPERATIVE_SMELLS = %w(HasRedundantLocalVariableReturn HasAssignmentReturn)
10
9
  EXPRESSIVENESS_SMELLS = %w(HasTooShortBindings HasWrongCaseBindings HasMisspelledBindings)
11
- GENERIC_SMELLS = %w(IsLongCode HasCodeDuplication HasRedundantLambda HasRedundantIf DoesTypeTest HasRedundantBooleanComparison)
10
+ GENERIC_SMELLS = %w(IsLongCode HasCodeDuplication HasRedundantLambda HasRedundantIf DoesTypeTest HasRedundantBooleanComparison HasEmptyIfBranches)
12
11
 
13
12
  required :language, 'You have to provide a Mulang-compatible language in order to use this hook'
14
13
 
15
- def compile(request)
16
- expectations, exceptions = compile_expectations_and_exceptions request
14
+ def run!(spec)
15
+ super(spec) + run_mulang_analysis(compile_mulang_analysis(spec[:request], spec[:expectations]))
16
+ end
17
+
18
+ def compile_mulang_analysis(request, expectations)
17
19
  mulang_code(request).analysis(
18
- expectations: expectations,
20
+ expectations: expectations[:ast],
19
21
  smellsSet: {
20
22
  tag: 'AllSmells',
21
- exclude: (exceptions + default_smell_exceptions)
23
+ exclude: (expectations[:exceptions] + default_smell_exceptions)
22
24
  },
23
25
  domainLanguage: domain_language)
24
26
  end
25
27
 
26
- def run!(analysis)
28
+ def run_mulang_analysis(analysis)
27
29
  parse_response Mulang.analyse(analysis)
28
30
  rescue JSON::ParserError
29
31
  raise Mumukit::CompilationError, "Can not handle mulang results for analysis #{analysis}"
@@ -50,32 +52,10 @@ module Mumukit
50
52
  language == 'Mulang' ? Mulang::Language::External.new : Mulang::Language::Native.new(language)
51
53
  end
52
54
 
53
- def compile_expectations_and_exceptions(request)
54
- expectations = []
55
- exceptions = []
56
- request[:expectations].each do |it|
57
- fill_expectations_and_excetions it.deep_symbolize_keys, expectations, exceptions
58
- end
59
- [expectations, exceptions]
60
- end
61
-
62
- def fill_expectations_and_excetions(expectation, expectations, exceptions)
63
- inspection = expectation[:inspection]
64
- if inspection&.start_with? 'Except:'
65
- exceptions << inspection[7..-1]
66
- else
67
- expectations << compile_expectation(expectation)
68
- end
69
- end
70
-
71
55
  def compile_content(content)
72
56
  content
73
57
  end
74
58
 
75
- def compile_expectation(expectation)
76
- Mumukit::Inspection::Expectation.parse(expectation).as_v2.to_h
77
- end
78
-
79
59
  def parse_response(response)
80
60
  if response['tag'] == 'AnalysisFailed'
81
61
  raise Mumukit::CompilationError, response['reason']
@@ -0,0 +1,49 @@
1
+ module Mumukit
2
+ class Templates::MultiFilePrecompileHook < Mumukit::Hook
3
+ include Mumukit::Templates::WithMultipleFiles
4
+
5
+ def compile(request)
6
+ request
7
+ .to_h
8
+ .merge(content: files_content(request))
9
+ .to_struct
10
+ end
11
+
12
+ def main_file
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def consolidate(main_content, files)
17
+ raise NotImplementedError
18
+ end
19
+
20
+ private
21
+
22
+ def files_content(request)
23
+ files = files_of request
24
+ if files.empty?
25
+ no_files_content request
26
+ elsif files.count == 1
27
+ single_file_content files
28
+ else
29
+ multi_file_content files
30
+ end
31
+ end
32
+
33
+ def no_files_content(request)
34
+ request.content
35
+ end
36
+
37
+ def single_file_content(files)
38
+ files.values.first
39
+ end
40
+
41
+ def multi_file_content(files)
42
+ consolidate main_file_content(files), files
43
+ end
44
+
45
+ def main_file_content(files)
46
+ files[main_file] || ''
47
+ end
48
+ end
49
+ end
@@ -1,7 +1,9 @@
1
1
  module Mumukit
2
2
  class Templates::TryHook < Templates::FileHook
3
3
  def compile(request)
4
- @goal = {postconditions: [[request.goal.with_indifferent_access[:kind], request.goal]]}
4
+ request_goal = request.goal.with_indifferent_access
5
+
6
+ @goal = {postconditions: [[request_goal[:kind], request_goal]]}
5
7
  @checker = Metatest::InteractiveChecker.new request
6
8
  super request
7
9
  end
@@ -0,0 +1,6 @@
1
+ module Mumukit::Templates::WithMultipleFiles
2
+ def files_of(request)
3
+ raise 'You need to enable Mumukit.config.multifile first!' unless Mumukit.config.multifile
4
+ request.content.is_a?(Hash) ? request.content : {}
5
+ end
6
+ end
@@ -3,8 +3,6 @@ module Mumukit
3
3
  end
4
4
  end
5
5
 
6
- require_relative './templates/file_hook'
7
- require_relative './templates/try_hook'
8
6
  require_relative './templates/with_structured_results'
9
7
  require_relative './templates/with_metatest'
10
8
  require_relative './templates/with_metatest_results'
@@ -12,6 +10,12 @@ require_relative './templates/with_mashup_file_content'
12
10
  require_relative './templates/with_embedded_environment'
13
11
  require_relative './templates/with_isolated_environment'
14
12
  require_relative './templates/with_line_number_offset'
15
- require_relative './templates/mulang_expectations_hook'
13
+ require_relative './templates/with_multiple_files'
16
14
  require_relative './templates/with_code_smells'
17
15
  require_relative './templates/with_cookie'
16
+
17
+ require_relative './templates/file_hook'
18
+ require_relative './templates/try_hook'
19
+ require_relative './templates/expectations_hook'
20
+ require_relative './templates/mulang_expectations_hook'
21
+ require_relative './templates/multi_file_precompile_hook'
@@ -1,3 +1,3 @@
1
1
  module Mumukit
2
- VERSION = '2.17.0'
2
+ VERSION = '2.27.0'
3
3
  end
data/lib/mumukit.rb CHANGED
@@ -22,12 +22,16 @@ module Mumukit
22
22
  current_runner.name
23
23
  end
24
24
 
25
+ def self.runner_url
26
+ Rack::Request.new(Mumukit::Env.env).base_url
27
+ end
28
+
25
29
  def self.configure_defaults(&block)
26
30
  Mumukit::Runner.configure_defaults(&block)
27
31
  end
28
32
 
29
33
  class << self
30
- delegate :prefix, :config, :configure, :runtime, :configure_runtime, :directives_pipeline, to: :current_runner
34
+ delegate :prefix, :config, :configure, :reconfigure, :runtime, :configure_runtime, :directives_pipeline, to: :current_runner
31
35
  end
32
36
  end
33
37
 
@@ -42,6 +46,9 @@ Mumukit.configure_defaults do |config|
42
46
  config.stateful = false
43
47
  config.command_time_limit = 4
44
48
  config.command_size_limit = 1024
49
+ config.process_expectations_on_empty_content = false
50
+ config.run_test_hook_on_empty_test = false
51
+ config.multifile = false
45
52
  end
46
53
 
47
54
  require 'mumukit/content_type'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumukit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.17.0
4
+ version: 2.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Leonardo Bulgarelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-16 00:00:00.000000000 Z
11
+ date: 2018-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rack-test
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: sinatra
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +184,14 @@ dependencies:
170
184
  requirements:
171
185
  - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: '3.3'
187
+ version: '4.0'
174
188
  type: :runtime
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
- version: '3.3'
194
+ version: '4.0'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: mumukit-inspection
183
197
  requirement: !ruby/object:Gem::Requirement
@@ -196,36 +210,30 @@ dependencies:
196
210
  name: mumukit-core
197
211
  requirement: !ruby/object:Gem::Requirement
198
212
  requirements:
199
- - - ">="
200
- - !ruby/object:Gem::Version
201
- version: '0.2'
202
- - - "<"
213
+ - - "~>"
203
214
  - !ruby/object:Gem::Version
204
- version: '2'
215
+ version: '1.3'
205
216
  type: :runtime
206
217
  prerelease: false
207
218
  version_requirements: !ruby/object:Gem::Requirement
208
219
  requirements:
209
- - - ">="
210
- - !ruby/object:Gem::Version
211
- version: '0.2'
212
- - - "<"
220
+ - - "~>"
213
221
  - !ruby/object:Gem::Version
214
- version: '2'
222
+ version: '1.3'
215
223
  - !ruby/object:Gem::Dependency
216
224
  name: mumukit-directives
217
225
  requirement: !ruby/object:Gem::Requirement
218
226
  requirements:
219
227
  - - "~>"
220
228
  - !ruby/object:Gem::Version
221
- version: '0.3'
229
+ version: '0.4'
222
230
  type: :runtime
223
231
  prerelease: false
224
232
  version_requirements: !ruby/object:Gem::Requirement
225
233
  requirements:
226
234
  - - "~>"
227
235
  - !ruby/object:Gem::Version
228
- version: '0.3'
236
+ version: '0.4'
229
237
  - !ruby/object:Gem::Dependency
230
238
  name: mumukit-content-type
231
239
  requirement: !ruby/object:Gem::Requirement
@@ -256,6 +264,7 @@ files:
256
264
  - bin/limit
257
265
  - lib/locales/en.yml
258
266
  - lib/locales/es.yml
267
+ - lib/locales/pt.yml
259
268
  - lib/mumukit.rb
260
269
  - lib/mumukit/compilation_error.rb
261
270
  - lib/mumukit/cookie.rb
@@ -263,6 +272,7 @@ files:
263
272
  - lib/mumukit/defaults/default_expectations_hook.rb
264
273
  - lib/mumukit/defaults/default_feedback_hook.rb
265
274
  - lib/mumukit/defaults/default_metadata_hook.rb
275
+ - lib/mumukit/defaults/default_precompile_hook.rb
266
276
  - lib/mumukit/defaults/default_query_hook.rb
267
277
  - lib/mumukit/defaults/default_test_hook.rb
268
278
  - lib/mumukit/defaults/default_try_hook.rb
@@ -291,8 +301,10 @@ files:
291
301
  - lib/mumukit/server/test_pipeline.rb
292
302
  - lib/mumukit/server/test_server.rb
293
303
  - lib/mumukit/templates.rb
304
+ - lib/mumukit/templates/expectations_hook.rb
294
305
  - lib/mumukit/templates/file_hook.rb
295
306
  - lib/mumukit/templates/mulang_expectations_hook.rb
307
+ - lib/mumukit/templates/multi_file_precompile_hook.rb
296
308
  - lib/mumukit/templates/try_hook.rb
297
309
  - lib/mumukit/templates/with_code_smells.rb
298
310
  - lib/mumukit/templates/with_cookie.rb
@@ -302,6 +314,7 @@ files:
302
314
  - lib/mumukit/templates/with_mashup_file_content.rb
303
315
  - lib/mumukit/templates/with_metatest.rb
304
316
  - lib/mumukit/templates/with_metatest_results.rb
317
+ - lib/mumukit/templates/with_multiple_files.rb
305
318
  - lib/mumukit/templates/with_structured_results.rb
306
319
  - lib/mumukit/version.rb
307
320
  - lib/mumukit/with_command_line.rb
@@ -328,7 +341,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
328
341
  version: '0'
329
342
  requirements: []
330
343
  rubyforge_project:
331
- rubygems_version: 2.7.2
344
+ rubygems_version: 2.7.7
332
345
  signing_key:
333
346
  specification_version: 4
334
347
  summary: Mumuki Test Server Development Kit