mumuki-sqlite-runner 2.2.1 → 3.0.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
- SHA1:
3
- metadata.gz: e574ef63ec53b93d7841532738042a3be0899079
4
- data.tar.gz: a87d92c79f8af4546ef46eb34e6faa7e0d26572c
2
+ SHA256:
3
+ metadata.gz: 2ff96b8daaf98e39b42e29a2e4a0fda7447ede4b33db3a496bbe09d76b021456
4
+ data.tar.gz: 124dd0f35e776db7a7ffde818afdb6e3cd4779d8f1c248d0e61e3391dfd5dc08
5
5
  SHA512:
6
- metadata.gz: 28dca88c0eae83a3d5e34173b47b6702d805e1bc3d3ff70a99d7d546001c157386f91ca9d6e8b93c13b43561576caf0b1d2e0e4329b598d79c73e5ab1f8ca4b4
7
- data.tar.gz: aeba550111b462b085d48c9b590822ddd03fdefa874303ccadb13c89867c55120c06612ded7402f871fb3cdaffb95c3d2297e45cd4310c2af36a167ed4e66240
6
+ metadata.gz: a503486ccbe2dddbbdfdf0274d50574585fa95b1b578e609c874578c1f8369aeaea33acbb58e4ee537c2ba0af2ccb3a3f42935e7a6e2e668dab3eb5ba340c186
7
+ data.tar.gz: 3c2e5a3d94069b7122dbe584ce81c8e76c2cf0ac6866c3987687f8995fc5e0f7671740c923632ad7e8d2a71cc141dafe406c5a2ee1aca062c95b3ccaf642ff6a
data/lib/checker.rb CHANGED
@@ -12,25 +12,27 @@ module Sqlite
12
12
  when :equals
13
13
  success(name, result)
14
14
  when :distinct_columns
15
- failed(name, result, solution, (I18n.t 'failure.columns'))
15
+ failed(name, result, solution, 'columns')
16
16
  when :distinct_rows
17
- failed(name, result, solution, (I18n.t 'failure.rows'))
17
+ failed(name, result, solution, 'rows')
18
18
  else
19
- failed(name, result, solution, (I18n.t 'failure.query'))
19
+ failed(name, result, solution, 'query')
20
20
  end
21
21
  end
22
22
 
23
23
  def success(name, result)
24
- [name, :passed, render_success(result)]
24
+ message = I18n.t 'message.success.query'
25
+ [name, :passed, render_success(result, message)]
25
26
  end
26
27
 
27
28
  def failed(name, result, solution, error)
29
+ error = I18n.t "message.failure.#{error}"
28
30
  [name, :failed, render_error(result, solution, error)]
29
31
  end
30
32
 
31
33
  # Return success page rendered with results
32
- def render_success(result)
33
- renderer.render_success result
34
+ def render_success(result, message)
35
+ renderer.render_success result, message
34
36
  end
35
37
 
36
38
  # Return error page rendered with results & solutions
data/lib/html_renderer.rb CHANGED
@@ -3,9 +3,10 @@ require 'active_support/inflector'
3
3
  module Sqlite
4
4
  class HtmlRenderer
5
5
 
6
- def render_success(result)
7
- @header = result[:dataset].header
8
- @rows = result[:dataset].rows
6
+ def render_success(result, message)
7
+ @message = message
8
+ @header = result[:dataset].header
9
+ @rows = result[:dataset].rows
9
10
  template_file_success.result binding
10
11
  end
11
12
 
data/lib/locales/en.yml CHANGED
@@ -1,8 +1,9 @@
1
1
  en:
2
2
  dataset: "Dataset %{number}"
3
- success:
4
- query: 'Correct Query!'
5
- failure:
6
- columns: 'Columns do not match'
7
- rows: 'Rows do not match'
8
- query: 'Queries do not match'
3
+ message:
4
+ success:
5
+ query: 'Correct Query!'
6
+ failure:
7
+ columns: 'Columns do not match'
8
+ rows: 'Rows do not match'
9
+ query: 'Queries do not match'
data/lib/locales/es.yml CHANGED
@@ -1,8 +1,9 @@
1
1
  es:
2
2
  dataset: "Set de datos %{number}"
3
- success:
4
- query: '¡Consulta correcta!'
5
- failure:
6
- columns: 'Las columnas no coinciden'
7
- rows: 'Las filas no coinciden'
8
- query: 'Las consultas no coinciden'
3
+ message:
4
+ success:
5
+ query: '¡Consulta correcta!'
6
+ failure:
7
+ columns: 'Las columnas no coinciden'
8
+ rows: 'Las filas no coinciden'
9
+ query: 'Las consultas no coinciden'
@@ -0,0 +1,27 @@
1
+ module Sqlite
2
+ module CommonTestParser
3
+
4
+ COMMENT = '-- NONE'
5
+ attr_reader :result, :final
6
+ required :parse, 'You need to implement parse method when use CommonTestParse mixin!'
7
+
8
+ def initialize(test)
9
+ @result = parse test
10
+ end
11
+
12
+ def choose(solution)
13
+ solution
14
+ end
15
+
16
+ protected
17
+
18
+ def final_parse(test, override = {})
19
+ seed = test[:seed].blank? ? '' : test[:seed].strip
20
+ {
21
+ seed: override[:seed] || seed,
22
+ expected: override[:expected] || test[:expected].strip
23
+ }
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ module Sqlite
2
+ class DatasetTestParser
3
+
4
+ include Sqlite::CommonTestParser
5
+
6
+ def initialize(test)
7
+ @test = test
8
+ @result = parse test
9
+ end
10
+
11
+ # test = {
12
+ # type: dataset,
13
+ # seed: INSERT INTO ...,
14
+ # expected: |
15
+ # id|field
16
+ # 1|row 1
17
+ # ...
18
+ # }
19
+ #
20
+ # return {
21
+ # seed: INSERT INTO ...,
22
+ # expected: -- NONE
23
+ # }
24
+ def parse(test)
25
+ @solutions = test[:expected].to_s.split("\n").map(&:strip).join("\n")
26
+ final_parse test, {expected: '-- NONE'}
27
+ end
28
+
29
+ def choose(_solution)
30
+ @solutions
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,10 @@
1
+ module Sqlite
2
+ class FinalDatasetTestParser < DatasetTestParser
3
+
4
+ def initialize(test)
5
+ super(test)
6
+ @final = test[:query] || test[:final]
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ module Sqlite
2
+ class InvalidTestParser
3
+
4
+ include Sqlite::CommonTestParser
5
+
6
+ # return {
7
+ # seed: -- NONE,
8
+ # expected: -- NONE
9
+ # }
10
+ def parse(test)
11
+ final_parse(test, {
12
+ seed: COMMENT,
13
+ expected: COMMENT
14
+ })
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ module Sqlite
2
+ class QueryTestParser
3
+
4
+ include Sqlite::CommonTestParser
5
+
6
+ # test = {
7
+ # type: query,
8
+ # seed: INSERT INTO ...,
9
+ # expected: SELECT * FROM ...
10
+ # }
11
+ #
12
+ # return {
13
+ # seed: INSERT INTO ...,
14
+ # expected: SELECT * FROM ...
15
+ # }
16
+ def parse(test)
17
+ final_parse test
18
+ end
19
+
20
+ end
21
+ end
data/lib/sqlite_runner.rb CHANGED
@@ -5,12 +5,11 @@ I18n.load_translations_path File.join(__dir__, 'locales', '*.yml')
5
5
 
6
6
  Mumukit.runner_name = 'sqlite'
7
7
  Mumukit.configure do |config|
8
- config.docker_image = 'mumuki/mumuki-sqlite-worker'
8
+ config.docker_image = 'mumuki/mumuki-sqlite-worker:v3-rc1'
9
9
  config.content_type = 'html'
10
10
  config.structured = true
11
11
  end
12
12
 
13
- require_relative './extensions/hash_extension'
14
13
  require_relative './version_hook'
15
14
  require_relative './test_hook'
16
15
  require_relative './metadata_hook'
@@ -18,6 +17,9 @@ require_relative './checker'
18
17
  require_relative './multiple_executions_runner'
19
18
  require_relative './html_renderer'
20
19
  require_relative './dataset'
21
- require_relative './dataset_solution_parser'
22
- require_relative './query_solution_parser'
20
+ require_relative './parsers/common_test_parser'
21
+ require_relative './parsers/query_test_parser'
22
+ require_relative './parsers/dataset_test_parser'
23
+ require_relative './parsers/final_dataset_test_parser'
24
+ require_relative './parsers/invalid_test_parser'
23
25
  require_relative './errors'
data/lib/test_hook.rb CHANGED
@@ -9,6 +9,16 @@ class SqliteTestHook < Mumukit::Templates::FileHook
9
9
  # Define that worker runs on a freshly-cleaned environment
10
10
  isolated
11
11
 
12
+ def initialize(config = nil)
13
+ super(config)
14
+ @test_parsers = {
15
+ query: Sqlite::QueryTestParser,
16
+ datasets: Sqlite::DatasetTestParser,
17
+ final_dataset: Sqlite::FinalDatasetTestParser,
18
+ }
19
+ @test_parsers.default = Sqlite::InvalidTestParser
20
+ end
21
+
12
22
  # Just define file extension
13
23
  def tempfile_extension
14
24
  '.json'
@@ -19,35 +29,36 @@ class SqliteTestHook < Mumukit::Templates::FileHook
19
29
  "runsql #{filename}"
20
30
  end
21
31
 
22
- # Define the .json file template from request structure
23
- # Input: request = {
24
- # test: (yaml string) teacher's code that define which testing verification student code should pass,
25
- # extra: (sql string) teacher's code that prepare field where student code should run,
26
- # content: (sql string) student code,
27
- # expectations: [] not using for now
32
+ # Transform Mumuki Request into Docker file style
33
+ # Request = {
34
+ # test: {
35
+ # type: (string) query|dataset,
36
+ # seed: (string) sql code to populate tables,
37
+ # expected: (string) query sentence | resulting table
38
+ # },
39
+ # extra: (string) sql code to create tables,
40
+ # content: (string) student's solution,
41
+ # expectations: [] # not using
28
42
  # }
29
43
  #
30
44
  def compile_file_content(request)
31
- solution, data = parse_test request.test
32
-
33
- content = {
34
- init: request.extra.strip,
35
- solution: solution,
36
- student: request.content.strip,
37
- datasets: data
38
- }
39
-
40
- content.to_json
45
+ tests = parse_tests request.test
46
+ final = get_final_query
47
+ {
48
+ init: request.extra.strip,
49
+ student: request.content.strip << final,
50
+ tests: tests
51
+ }.to_json
41
52
  end
42
53
 
43
54
  # Define how output results
44
55
  # Expected:
45
56
  # {
46
- # "solutions": [
57
+ # "expected": [
47
58
  # "name\nTest 1.1\nTest 1.2\nTest 1.3\n",
48
59
  # "name\nTest 2.1\nTest 2.2\nTest 2.3\n"
49
60
  # ],
50
- # "results": [
61
+ # "student": [
51
62
  # "id|name\n1|Test 1.1\n2|Test 1.2\n3|Test 1.3\n",
52
63
  # "id|name\n1|Test 2.1\n2|Test 2.2\n3|Test 2.3\n"
53
64
  # ]
@@ -57,8 +68,8 @@ class SqliteTestHook < Mumukit::Templates::FileHook
57
68
 
58
69
  case status
59
70
  when :passed
60
- solutions, results = parse_output output
61
- framework.test solutions, results
71
+ expected, student = parse_output output
72
+ framework.test expected, student
62
73
  when :failed
63
74
  [output['output'], status]
64
75
  else
@@ -69,33 +80,29 @@ class SqliteTestHook < Mumukit::Templates::FileHook
69
80
  protected
70
81
 
71
82
  def parse_output(output)
72
- results = output['results']
73
- solutions = output['solutions']
74
- unless @solution_parser.nil?
75
- solutions = @solution_parser.choose solutions
83
+ student = output['student']
84
+ expected = output['expected']
85
+ expected.map!.with_index do |expect, i|
86
+ @expected_parser[i].choose expect
76
87
  end
77
88
 
78
- diff(solutions, results)
89
+ diff(expected, student)
79
90
  end
80
91
 
81
- def diff(solutions, results)
82
- zipped = solutions.zip(results).map do |solution, result|
83
-
84
- diff = Diffy::SplitDiff.new result << "\n", solution << "\n"
85
-
86
- if diff.left.blank?
87
- [solution, result]
88
- else
89
- res = post_process_diff diff.left
90
- sol = post_process_diff diff.right
91
- [sol, res]
92
- end
93
-
92
+ def diff(expected, student)
93
+ zipped = expected.zip(student).map do |expected_i, student_i|
94
+ diff = Diffy::SplitDiff.new student_i << "\n", expected_i << "\n"
95
+ choose_left_right(diff, expected_i, student_i).map { |e| post_process_diff e }
94
96
  end
95
-
96
97
  zipped.transpose.map { |dataset| post_process_datasets dataset }
97
98
  end
98
99
 
100
+ def choose_left_right(diff, expected, student)
101
+ expected = diff.left unless diff.left.blank?
102
+ student = diff.right unless diff.right.blank?
103
+ [expected, student]
104
+ end
105
+
99
106
  def post_process_diff(data)
100
107
  data.scan(/^(\s|-|\+)(.+)/)
101
108
  .map { |mark, content| mark << '|' << content }
@@ -112,37 +119,33 @@ class SqliteTestHook < Mumukit::Templates::FileHook
112
119
  end
113
120
  end
114
121
 
115
- # Test should have one of these formats:
122
+ # This method receives a list of test cases.
123
+ # Each one could be like one of these:
116
124
  #
117
- # Solution by query:
118
- # { solution_type: 'query',
119
- # solution_query: 'SELECT * FROM ...',
120
- # examples: [
121
- # { data: "INSERT INTO..." }
122
- # ]
123
- # }
125
+ # type: query
126
+ # seed: INSERT INTO ...
127
+ # expected: SELECT * FROM ...
124
128
  #
125
- # Solution by datasets:
126
- # { solution_type: 'datasets',
127
- # examples: [
128
- # { data: "INSERT INTO...",
129
- # solution: "id|field\n1|row1..."
130
- # }
131
- # ]
132
- # }
133
- def parse_test(test)
134
- test = OpenStruct.new YAML.load(test).deep_symbolize_keys
135
-
136
- case test.solution_type.to_sym
137
- when :query
138
- @solution_parser = Sqlite::QuerySolutionParser.new
139
- when :datasets
140
- @solution_parser = Sqlite::DatasetSolutionParser.new
141
- else
142
- raise Sqlite::TestSolutionTypeError
129
+ # type: dataset
130
+ # seed: INSERT INTO ...
131
+ # expected: |
132
+ # id|field
133
+ # 1|row 1
134
+ # ...
135
+ def parse_tests(tests)
136
+ tests = YAML.load tests
137
+ @tests = tests.map do | test |
138
+ test = test.to_struct
139
+ @test_parsers[test.type.to_sym].new test
143
140
  end
144
141
 
145
- @solution_parser.parse_test test
142
+ @expected_parser = @tests
143
+ @tests.map(&:result)
144
+ end
145
+
146
+ def get_final_query
147
+ parsers = @expected_parser.select { |parser| !parser.final.blank? }
148
+ parsers.empty? ? '' : parsers.first.final
146
149
  end
147
150
 
148
151
  # Initialize Metatest Framework with Checker & Runner
data/lib/version_hook.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module SqliteVersionHook
2
- VERSION = '2.2.1'
2
+ VERSION = '3.0.0'
3
3
  end
@@ -20,7 +20,7 @@
20
20
  }
21
21
  </style>
22
22
 
23
- <h5><%= I18n.t 'success.query' %></h5>
23
+ <h5><%= message %></h5>
24
24
  <table class="table table-bordered sqlite_success">
25
25
  <thead>
26
26
  <tr>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumuki-sqlite-runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leandro Di Lorenzo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-12 00:00:00.000000000 Z
11
+ date: 2017-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mumukit
@@ -173,15 +173,17 @@ extra_rdoc_files: []
173
173
  files:
174
174
  - lib/checker.rb
175
175
  - lib/dataset.rb
176
- - lib/dataset_solution_parser.rb
177
176
  - lib/errors.rb
178
- - lib/extensions/hash_extension.rb
179
177
  - lib/html_renderer.rb
180
178
  - lib/locales/en.yml
181
179
  - lib/locales/es.yml
182
180
  - lib/metadata_hook.rb
183
181
  - lib/multiple_executions_runner.rb
184
- - lib/query_solution_parser.rb
182
+ - lib/parsers/common_test_parser.rb
183
+ - lib/parsers/dataset_test_parser.rb
184
+ - lib/parsers/final_dataset_test_parser.rb
185
+ - lib/parsers/invalid_test_parser.rb
186
+ - lib/parsers/query_test_parser.rb
185
187
  - lib/sqlite_runner.rb
186
188
  - lib/test_hook.rb
187
189
  - lib/version_hook.rb
@@ -207,7 +209,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
207
209
  version: '0'
208
210
  requirements: []
209
211
  rubyforge_project:
210
- rubygems_version: 2.6.14
212
+ rubygems_version: 2.7.3
211
213
  signing_key:
212
214
  specification_version: 4
213
215
  summary: SQLite Runner for Mumuki
@@ -1,34 +0,0 @@
1
- module Sqlite
2
- class DatasetSolutionParser
3
-
4
- # If solutions comes in an explicit datasets,
5
- # it was stored in instance variable.
6
- # Expected input:
7
- # OpenStruct#{
8
- # solution_type: 'datasets',
9
- # examples: [
10
- # {
11
- # dataset: "INSERT INTO ...\nINSERT INTO ...",
12
- # solution_dataset: "id|field\n1|row1..."
13
- # }
14
- # ]
15
- # }
16
- def parse_test(test)
17
- data = []
18
- @solutions = []
19
- solution_query = '-- none'
20
-
21
- test.examples.each do |item|
22
- @solutions << item[:solution_dataset].scan(/(?!\|).+(?<!\|)/).join("\n")
23
- data.append item[:data]
24
- end
25
-
26
- return solution_query, data
27
- end
28
-
29
- def choose(_solution)
30
- @solutions
31
- end
32
-
33
- end
34
- end
@@ -1,6 +0,0 @@
1
-
2
- class Hash
3
- def to_yaml
4
- super.sub('---', '').strip
5
- end
6
- end
@@ -1,25 +0,0 @@
1
- module Sqlite
2
- class QuerySolutionParser
3
-
4
- # Expected input:
5
- # OpenStruct#{
6
- # solution_type: 'query',
7
- # solution_query: 'select * from motores;',
8
- # examples: [
9
- # { dataset: "INSERT INTO ...\nINSERT INTO ..." }
10
- # ]
11
- # }
12
- def parse_test(test)
13
- data = test.examples.map do |item|
14
- item[:data]
15
- end
16
-
17
- return test.solution_query, data
18
- end
19
-
20
- def choose(solution)
21
- solution
22
- end
23
-
24
- end
25
- end