codgen 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.idea/.name +1 -0
  4. data/.idea/.rakeTasks +7 -0
  5. data/.idea/codgen.iml +142 -0
  6. data/.idea/encodings.xml +5 -0
  7. data/.idea/idea/.name +1 -0
  8. data/.idea/idea/codgen.iml +140 -0
  9. data/.idea/idea/encodings.xml +5 -0
  10. data/.idea/idea/misc.xml +5 -0
  11. data/.idea/idea/modules.xml +9 -0
  12. data/.idea/idea/scopes/scope_settings.xml +5 -0
  13. data/.idea/idea/vcs.xml +7 -0
  14. data/.idea/idea/workspace.xml +830 -0
  15. data/.idea/inspectionProfiles/Project_Default.xml +7 -0
  16. data/.idea/inspectionProfiles/profiles_settings.xml +7 -0
  17. data/.idea/misc.xml +5 -0
  18. data/.idea/modules.xml +9 -0
  19. data/.idea/scopes/scope_settings.xml +5 -0
  20. data/.idea/vcs.xml +7 -0
  21. data/.idea/workspace.xml +1213 -0
  22. data/Gemfile +4 -0
  23. data/LICENSE.txt +22 -0
  24. data/README.md +32 -0
  25. data/Rakefile +2 -0
  26. data/bin/codgen.rb +50 -0
  27. data/codgen.gemspec +27 -0
  28. data/lib/codgen/auto_style.rb +111 -0
  29. data/lib/codgen/constants.rb +5 -0
  30. data/lib/codgen/debug_helper.rb +15 -0
  31. data/lib/codgen/flattener.rb +32 -0
  32. data/lib/codgen/logger.rb +8 -0
  33. data/lib/codgen/mapping.rb +40 -0
  34. data/lib/codgen/statement.rb +163 -0
  35. data/lib/codgen/template.rb +40 -0
  36. data/lib/codgen/version.rb +3 -0
  37. data/lib/codgen.rb +59 -0
  38. data/test/behavior/basic_test.rb +10 -0
  39. data/test/behavior/output_spec.rb +36 -0
  40. data/test/behavior/test_utils.rb +16 -0
  41. data/test/data/Input/CreateDatabase.sql +10 -0
  42. data/test/data/Input/DbContextTemplate.cs +18 -0
  43. data/test/data/Input/ModelTemplate.cs +26 -0
  44. data/test/data/Input/example-data.json +75 -0
  45. data/test/data/Input/hello_world.txt.mustache +1 -0
  46. data/test/data/Input/model_template.rb.ctemp +8 -0
  47. data/test/data/Input/test_conditionals +7 -0
  48. data/test/data/Input/test_escapes +6 -0
  49. data/test/data/Map.json +36 -0
  50. data/test/data/Output/CreateMyBlogDatabase.sql +17 -0
  51. data/test/data/Output/MsMvc/MyBlog/DAL/MyBlogContext.cs +17 -0
  52. data/test/data/Output/MsMvc/MyBlog/Models/Comment.cs +14 -0
  53. data/test/data/Output/MsMvc/MyBlog/Models/Post.cs +17 -0
  54. data/test/data/Output/Ruby/my_blog/Models/comment.rb +3 -0
  55. data/test/data/Output/Ruby/my_blog/Models/post.rb +3 -0
  56. data/test/data/config.json +25 -0
  57. data/test/data/expected_output/MsMvc/MyBlog/DAL/MyBlogContext.cs +17 -0
  58. data/test/data/expected_output/MsMvc/MyBlog/Models/Comment.cs +14 -0
  59. data/test/data/expected_output/MsMvc/MyBlog/Models/Post.cs +17 -0
  60. data/test/data/expected_output/Ruby/my_blog/Models/comment.rb +3 -0
  61. data/test/data/expected_output/Ruby/my_blog/Models/post.rb +3 -0
  62. data/test/data/test.mustache +5 -0
  63. data/test/unit/codgen_engine_spec.rb +12 -0
  64. data/test/unit/flattener_spec.rb +51 -0
  65. data/test/unit/template_spec.rb +30 -0
  66. metadata +222 -0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in codgen.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Matthew Beatty
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Codgen
2
+
3
+ A cross language template base code generator, capable of generating multiple applications from a common model.
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'codgen'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install codgen
21
+
22
+ ## Usage
23
+
24
+ $ codgen codgen_config.json
25
+
26
+ ## Contributing
27
+
28
+ 1. Fork it ( https://github.com/[my-github-username]/codgen/fork )
29
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
30
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
31
+ 4. Push to the branch (`git push origin my-new-feature`)
32
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/codgen.rb ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ require 'ostruct'
3
+ require 'json'
4
+ require_relative '../lib/codgen'
5
+ require_relative '../lib/codgen/logger'
6
+ require 'fileutils'
7
+
8
+ class CommandLineArguments
9
+ def initialize(arguments)
10
+ if arguments.count < 1
11
+ puts 'Help file placeholder'
12
+ exit 0
13
+ end
14
+
15
+ if arguments.count == 1
16
+ @json_config = arguments[0]
17
+ end
18
+ end
19
+
20
+ attr_reader :json_config
21
+ end
22
+
23
+ def get_file_contents(filepath)
24
+ if File.exist?(filepath)
25
+ File.read(filepath)
26
+ else
27
+ Logger.error('Could not find file "'+filepath+'"')
28
+ end
29
+ end
30
+
31
+
32
+ def write_file_contents(filepath, content)
33
+ dir = File.dirname(filepath)
34
+ FileUtils.mkpath(dir) unless Dir.exists?(dir)
35
+ File.write(filepath, content)
36
+ end
37
+
38
+
39
+ def main(args)
40
+ if args.json_config != nil
41
+ json_config_text = get_file_contents(args.json_config)
42
+ json_config = JSON.parse(json_config_text)
43
+ output = Codgen.run(json_config)
44
+ output.each do |path, text|
45
+ write_file_contents(path, text)
46
+ end
47
+ end
48
+ end
49
+
50
+ main(CommandLineArguments.new(ARGV))
data/codgen.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'codgen/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "codgen"
8
+ spec.version = Codgen::VERSION
9
+ spec.authors = ["Matthew Beatty"]
10
+ spec.email = ["beattyml1@gmail.com"]
11
+ spec.summary = 'Generate multiple applications from a common model written in JSON using template'
12
+ spec.description = ''
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_runtime_dependency "mustache"
25
+ spec.add_runtime_dependency "json"
26
+ spec.add_runtime_dependency "activerecord"
27
+ end
@@ -0,0 +1,111 @@
1
+ require 'active_support/inflector'
2
+ require 'ostruct'
3
+ module Codgen
4
+ module AutoStyle
5
+ public
6
+ def self.style(json_object)
7
+ if json_object.is_a?(Array)
8
+ json_object.each { |child| style(child) }
9
+ end
10
+
11
+ add_props = Hash.new
12
+ if json_object.is_a?(Hash)
13
+ json_object.each do |key, value|
14
+ if value.is_a?(Hash) || value.is_a?(Array)
15
+ style(value)
16
+ next
17
+ end
18
+
19
+ if key.index(/[@$ #]/)
20
+ add_props.store(key, value)
21
+ end
22
+ end
23
+ end
24
+
25
+ add_props.each do |key, value|
26
+ add_property_group(json_object, key, value, AutoStyle.method(:to_camel), '!camelCase')
27
+ add_property_group(json_object, key, value, AutoStyle.method(:to_cap_camel), '!CapCamel')
28
+ add_property_group(json_object, key, value, AutoStyle.method(:to_underscore), '!underscored')
29
+ add_property_group(json_object, key, value, AutoStyle.method(:to_camel), '!CAPS_UNDERSCORE')
30
+ end
31
+ end
32
+
33
+
34
+ def self.style_state_variable(input_string)
35
+ [to_camel(input_string), to_cap_camel(input_string), to_underscore(input_string), to_underscore(input_string)]
36
+ end
37
+
38
+
39
+ private
40
+ def self.add_property_group(json_object, key, value, translate, explicit_postfix)
41
+ should_translate_val = value != nil && value.is_a?(String) && key.index('@')
42
+ is_plural = key.index('?plural')
43
+
44
+ new_key = translate.call(key)
45
+ new_value = should_translate_val ? translate.call(value) : value
46
+ explicit_key = new_key + explicit_postfix
47
+
48
+ requantified = pluralize_singularize(new_key, explicit_key, new_value, is_plural, should_translate_val)
49
+
50
+ try_add_prop(json_object, new_key, new_value)
51
+ try_add_prop(json_object, explicit_key, new_value)
52
+ try_add_prop(json_object, requantified.short_key, requantified.value)
53
+ try_add_prop(json_object, requantified.explicit_key, requantified.value)
54
+ end
55
+
56
+ def self.pluralize_singularize(short_key, explicit_key, value, is_plural, should_translate_value)
57
+ return_obj = OpenStruct.new
58
+ if is_plural
59
+ return_obj.short_key = short_key.singularize
60
+ return_obj.explicit_key = explicit_key.singularize
61
+ return_obj.value = should_translate_value ? value.singularize : value
62
+ else
63
+ return_obj.short_key = short_key.pluralize
64
+ return_obj.explicit_key = explicit_key.pluralize
65
+ return_obj.value = should_translate_value ? value.pluralize : value
66
+ end
67
+ return_obj
68
+ end
69
+
70
+
71
+ def self.try_add_prop(json_object, key, value)
72
+ unless json_object.has_key?(key)
73
+ json_object.store(key, value)
74
+ end
75
+ end
76
+
77
+
78
+ def self.to_universal(input_string)
79
+ output_string = input_string.tr('$?@', '')
80
+ output_string.split(' ')
81
+ end
82
+
83
+
84
+ def self.to_cap_camel(input_string)
85
+ universal = to_universal(input_string)
86
+ universal.each {|word| word[0] = word[0].upcase}
87
+ universal.join('')
88
+ end
89
+
90
+
91
+ def self.to_camel(input_string)
92
+ universal = to_universal(input_string)
93
+ universal[1...universal.count].each {|word| word[0] = word[0].upcase}
94
+ universal.join('')
95
+ end
96
+
97
+
98
+ def self.to_underscore(input_string)
99
+ universal = to_universal(input_string)
100
+ output = universal.join('_')
101
+ output.downcase
102
+ end
103
+
104
+
105
+ def self.to_allcaps_underscore(input_string)
106
+ universal = to_universal(input_string)
107
+ output = universal.join('_')
108
+ output.upcase
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,5 @@
1
+ module Codgen
2
+ module RegularExpressions
3
+ IDENTIFIER_REGEX = /[a-zA-Z0-9_%]+/
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ module DebugHelper
2
+ @@event_log = nil
3
+
4
+ def self.write_file(name, text)
5
+ File.write('../debug_data/'+name, text)
6
+ end
7
+
8
+ def self.log_event(message)
9
+ if @@event_log == nil
10
+ @@event_log = File.new('../debug_data/event_log', 'w+')
11
+ end
12
+
13
+ @@event_log.write("#{Time.now}: #{message}\n")
14
+ end
15
+ end
@@ -0,0 +1,32 @@
1
+ module Codgen
2
+ module Flattener
3
+
4
+ # @param [Hash] data_root: the JSON root hash
5
+ # @param [Array[String]] properties
6
+ # @return [Array, Hash]
7
+ def self.merge(data_root, properties)
8
+ current = data_root
9
+ obj_out = Hash.new
10
+ properties.each { |property|
11
+ current.each {|prop, val| obj_out[prop] = val}
12
+ current = current[property]
13
+ }
14
+
15
+ if current.is_a?(Hash)
16
+ current.each {|prop, val| obj_out[prop] = val}
17
+ return obj_out
18
+ elsif current.is_a?(Array)
19
+ array_out = Array.new
20
+ current.each { |child|
21
+ if child.is_a?(Hash)
22
+ array_obj = Hash.new
23
+ obj_out.each {|prop, val| array_obj[prop] = val}
24
+ child.each {|prop, val| array_obj[prop] = val}
25
+ array_out.push(array_obj)
26
+ end
27
+ }
28
+ return array_out
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,8 @@
1
+ module Codgen
2
+ module Logger
3
+ def self.error(message)
4
+ puts message
5
+ exit 1
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,40 @@
1
+ module Codgen
2
+ module Mapping
3
+ def self.map_object(json_data, json_map_data)
4
+ if json_data != nil && json_data.is_a?(Array)
5
+ json_data.each do |item|
6
+ map_object(item, json_map_data)
7
+ end
8
+ return
9
+ end
10
+
11
+ add_entries = Hash.new
12
+ json_data.each do |key, value|
13
+ if value != nil && value.is_a?(Array) || value.is_a?(Hash)
14
+ map_object(value, json_map_data)
15
+ next
16
+ end
17
+
18
+ map = json_map_data[key]
19
+ if map != nil
20
+ map.each do |output_key, value_map|
21
+ unless json_data.has_key?(output_key)
22
+ output_value = value
23
+ value_map.each do |match_expr, map_value|
24
+ if Regexp.new(match_expr).match(value)
25
+ output_value = map_value
26
+ break
27
+ end
28
+ end
29
+ add_entries.store(output_key, output_value)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ add_entries.each do |key, value|
36
+ json_data.store(key, value)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,163 @@
1
+ require_relative 'constants'
2
+ require_relative 'logger'
3
+
4
+ # Not currently used but will be for an up coming feature that used be implemented in an older version
5
+ module Codgen
6
+ class Statement
7
+ include RegularExpressions
8
+ def initialize(operator=nil)
9
+ @words = Array.new
10
+ @operator = operator
11
+ end
12
+
13
+ def evaluate(get_val)
14
+ if @operator == nil
15
+ expand
16
+ end
17
+
18
+ current_val = nil
19
+ @words.each do |child|
20
+ current_val = accumulate(current_val, child, @operator, get_val)
21
+ end
22
+ current_val
23
+ end
24
+
25
+ attr_reader :operator
26
+ attr_reader :words
27
+
28
+ def accumulate(before, child, operator, get_val)
29
+ if operator == nil && child.is_a?(Statement)
30
+ accumulate(before, child, child.operator, get_val)
31
+ else
32
+ value = child.is_a?(String) ? get_val.call(child) : child.evaluate(get_val)
33
+ case operator
34
+ when :and
35
+ before = before != nil ? before : true
36
+ before && value
37
+ when :or
38
+ before = before != nil ? before : false
39
+ before || value
40
+ when :not
41
+ !value
42
+ else
43
+ value
44
+ end
45
+ end
46
+ end
47
+
48
+ def expand
49
+ expand_not
50
+ expand_and
51
+ expand_or
52
+ end
53
+
54
+ def parse(text)
55
+ count = -1
56
+ text.each_char do |current_char|
57
+ count+=1
58
+ if current_char == ' '
59
+ next 1
60
+ end
61
+
62
+ if current_char.index(IDENTIFIER_REGEX)
63
+ if @words.length > 0 && @words[-1].index(IDENTIFIER_REGEX)
64
+ @words[-1] = @words[-1] + current_char
65
+ else
66
+ @words.push(current_char)
67
+ end
68
+ elsif current_char.index(/[&|!]/)
69
+ @words.push(current_char)
70
+ elsif current_char == '('
71
+ @words.push(Statement.new)
72
+ count += @words[-1].parse(text[count...text.length])
73
+ elsif current_char == ')'
74
+ return count
75
+ end
76
+ end
77
+ end
78
+
79
+ def expand_not
80
+ new_words = Array.new
81
+ @words.each do |word|
82
+ if word.is_a?(Statement)
83
+ new_words.push(word)
84
+ elsif word.index(/not|!/)
85
+ if new_words[-1].is_a?(Statement) && new_words[-1].operator == :not
86
+ new_words.delete_at(-1)
87
+ else
88
+ new_words.push(Statement.new(:not))
89
+ end
90
+ else
91
+ if new_words[-1].is_a?(Statement) && new_words[-1].operator == :not && new_words[-1].words.count == 0
92
+ new_words[-1].words.push(word)
93
+ else
94
+ new_words.push(word)
95
+ end
96
+ end
97
+ end
98
+ @words = new_words
99
+ end
100
+
101
+ def expand_and
102
+ new_words = Array.new
103
+ index = -1
104
+ skip = false
105
+ @words.each do |word|
106
+ index+=1
107
+ if skip
108
+ skip = false
109
+ next
110
+ end
111
+ if word.is_a?(Statement)
112
+ new_words.push(word)
113
+ elsif word.index(/and|&/)
114
+ if new_words.count > 0 && @words.count > index + 1
115
+ left = new_words[-1]
116
+ new_words.delete_at(-1)
117
+ new_words.push(Statement.new(:and))
118
+ new_words[-1].words.push(left)
119
+ new_words[-1].words.push(@words[index+1])
120
+ skip = true
121
+ next
122
+ else
123
+ throw 'Operator must have a left and a right side'
124
+ end
125
+ else
126
+ new_words.push(word)
127
+ end
128
+ end
129
+ @words = new_words
130
+ end
131
+
132
+ def expand_or
133
+ new_words = Array.new
134
+ index = -1
135
+ skip = false
136
+ @words.each do |word|
137
+ index+=1
138
+ if skip
139
+ skip = false
140
+ next
141
+ end
142
+ if word.is_a?(Statement)
143
+ new_words.push(word)
144
+ elsif word.index(/or|\|/)
145
+ if new_words.count > 0 && @words.count > index + 1
146
+ left = new_words[-1]
147
+ new_words.delete_at(-1)
148
+ new_words.push(Statement.new(:or))
149
+ new_words[-1].words.push(left)
150
+ new_words[-1].words.push(@words[index+1])
151
+ skip = true
152
+ next
153
+ else
154
+ throw 'Operator must have a left and a right side'
155
+ end
156
+ else
157
+ new_words.push(word)
158
+ end
159
+ end
160
+ @words = new_words
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,40 @@
1
+ require 'mustache'
2
+ require_relative 'flattener'
3
+ require_relative 'logger'
4
+
5
+ module Codgen
6
+ class Template
7
+ # @param [JSON_Hash] template_info
8
+ # @param [JSON_Hash] data_root
9
+ def initialize(template_info, data_root)
10
+ @input_path = template_info['in']
11
+ @out_raw = template_info['out']
12
+ source_raw = template_info['source']
13
+ source_location = source_raw != nil ? source_raw.split('.') : []
14
+ @data = Flattener.merge(data_root, source_location)
15
+ @template = Template.get_template(@input_path)
16
+ end
17
+
18
+ def fill_template
19
+ if @data.is_a?(Array)
20
+ output = Hash.new
21
+ @data.each { |data|
22
+ output.store(Mustache.render(@out_raw, data), Mustache.render(@template, data))
23
+ }
24
+ return output
25
+ elsif @data.is_a?(Hash)
26
+ return { Mustache.render(@out_raw, data) => Mustache.render(@template, @data) }
27
+ end
28
+ end
29
+
30
+ def self.get_template(path)
31
+ if File.exist?(path)
32
+ File.read(path)
33
+ else
34
+ Logger.error('Could not find file "'+path+'"')
35
+ end
36
+ end
37
+
38
+ attr_reader :data, :input_path, :template # Used to unit test
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module Codgen
2
+ VERSION = "0.0.1"
3
+ end
data/lib/codgen.rb ADDED
@@ -0,0 +1,59 @@
1
+ require_relative 'codgen/version'
2
+ require_relative 'codgen/auto_style'
3
+ require_relative 'codgen/mapping'
4
+ require_relative 'codgen/logger'
5
+ require_relative 'codgen/template'
6
+
7
+ module Codgen
8
+ def self.run(json_config)
9
+ map = json_config['map']
10
+ map = get_data_if_not_data(map)
11
+
12
+ json_data = json_config['data']
13
+ json_data = get_data_if_not_data(json_data)
14
+ json_data = map_and_style(map, json_data)
15
+
16
+ #File.write('temp.json', JSON.pretty_unparse(json_data)) # frequently used debug code
17
+
18
+ filled_templates = Array.new
19
+
20
+ templates = json_config['templates']
21
+ templates.each do |template_info|
22
+
23
+ template = Template.new(template_info, json_data)
24
+ template.fill_template.each {|filled_template| filled_templates.push(filled_template)}
25
+ end
26
+
27
+ filled_templates
28
+ end
29
+
30
+ def self.get_data_if_not_data(filepath_or_data)
31
+ if filepath_or_data != nil
32
+ if filepath_or_data.is_a?(String)
33
+ file = File.read(filepath_or_data)
34
+ JSON.parse(file)
35
+ elsif filepath_or_data.is_a?(Hash)
36
+ filepath_or_data
37
+ else
38
+ Logger.error('In json config file: "map" must be either a filepath or a json object.')
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+ class FilledTemplate
45
+ attr_accessor :path
46
+ attr_accessor :text
47
+ end
48
+
49
+
50
+ def self.map_and_style(map_data, json_data)
51
+ if map_data
52
+ Mapping.map_object(json_data, map_data)
53
+ end
54
+
55
+ AutoStyle.style(json_data)
56
+
57
+ json_data
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ require 'fileutils'
2
+ require_relative 'test_utils'
3
+
4
+ puts `ruby ../Source/codgen.rb config.json`
5
+
6
+ error = TestUtils.recursive_compare('expected_output', 'Output')
7
+
8
+ unless error
9
+ puts 'Success!'
10
+ end
@@ -0,0 +1,36 @@
1
+ require 'rspec'
2
+ require 'fileutils'
3
+ require_relative 'test_utils'
4
+
5
+ describe 'Application' do
6
+ $expectation_directory = 'expected_output'
7
+ $output_directory = 'Output'
8
+ before :all do
9
+
10
+ FileUtils.rm_rf($output_directory)
11
+
12
+ puts `../../bin/codgen.rb config.json`
13
+ end
14
+
15
+ it 'should produce all expected files' do
16
+ files_and_folders = Dir.glob($expectation_directory+'/**/*')
17
+ files_and_folders.each do |expected_file_path|
18
+ if File.file?(expected_file_path)
19
+ output_file_path = expected_file_path.sub($expectation_directory, $output_directory)
20
+ expect(File.exist?(output_file_path)).to be_truthy
21
+ end
22
+ end
23
+ end
24
+
25
+
26
+ files_and_folders = Dir.glob($expectation_directory+'/**/*')
27
+ files_and_folders.each do |expected_file_path|
28
+ if File.file?(expected_file_path)
29
+ output_file_path = expected_file_path.sub($expectation_directory, $output_directory)
30
+ it "should produce file: '#{output_file_path}' that is the same as '#{expected_file_path}'" do
31
+ expect(File.exist?(output_file_path)).to be_truthy
32
+ expect(FileUtils.cmp(output_file_path, expected_file_path)).to be_truthy
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ module TestUtils
2
+ def self.recursive_compare(expectation_directory, output_directory)
3
+ files_and_folders = Dir.glob(expectation_directory+'/**/*')
4
+ error = false
5
+ files_and_folders.each do |expected_file_path|
6
+ if File.file?(expected_file_path)
7
+ output_file_path = expected_file_path.sub(expectation_directory, output_directory)
8
+ unless FileUtils.cmp(expected_file_path, output_file_path)
9
+ puts "Error: '#{output_file_path}' does not match '#{expected_file_path}"
10
+ error = true
11
+ end
12
+ end
13
+ end
14
+ return error
15
+ end
16
+ end