polytrix 0.0.1 → 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (238) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/.rspec +1 -6
  4. data/.rubocop-todo.yml +19 -0
  5. data/.rubocop.yml +10 -0
  6. data/.travis.yml +11 -0
  7. data/Gemfile +0 -16
  8. data/README.md +119 -28
  9. data/Rakefile +18 -123
  10. data/bin/polytrix +5 -0
  11. data/doc-src/_markdown.md +5 -0
  12. data/doc-src/default_bootstrap.md +13 -0
  13. data/docs/influences.md +28 -0
  14. data/docs/samples/code2doc/java/HelloWorld.md +13 -0
  15. data/docs/samples/code2doc/java/Quine.md +33 -0
  16. data/docs/samples/code2doc/python/hello_world.md +3 -0
  17. data/docs/samples/code2doc/python/quine.md +4 -0
  18. data/docs/samples/code2doc/ruby/hello_world.md +7 -0
  19. data/features/execution.feature +67 -0
  20. data/features/fixtures/configs/empty.yml +12 -0
  21. data/features/fixtures/configs/hello_world.yml +10 -0
  22. data/features/fixtures/spec/polytrix_merge.rb +5 -0
  23. data/features/fixtures/spec/polytrix_spec.rb +10 -0
  24. data/features/reporting.feature +140 -0
  25. data/features/step_definitions/sdk_steps.rb +12 -0
  26. data/features/support/env.rb +8 -0
  27. data/lib/polytrix/challenge.rb +20 -7
  28. data/lib/polytrix/challenge_runner.rb +9 -44
  29. data/lib/polytrix/cli/add.rb +67 -0
  30. data/lib/polytrix/cli/report.rb +88 -0
  31. data/lib/polytrix/cli/reports/hash_reporter.rb +30 -0
  32. data/lib/polytrix/cli/reports/json_reporter.rb +14 -0
  33. data/lib/polytrix/cli/reports/markdown_reporter.rb +23 -0
  34. data/lib/polytrix/cli/reports/yaml_reporter.rb +14 -0
  35. data/lib/polytrix/cli.rb +158 -0
  36. data/lib/polytrix/configuration.rb +65 -4
  37. data/lib/polytrix/core/file_system_helper.rb +75 -0
  38. data/lib/polytrix/core/implementor.rb +31 -3
  39. data/lib/polytrix/documentation/code_segmenter.rb +168 -0
  40. data/lib/polytrix/documentation/comment_styles.rb +87 -0
  41. data/lib/polytrix/documentation/helpers/code_helper.rb +85 -0
  42. data/lib/polytrix/documentation/view_helper.rb +21 -0
  43. data/lib/polytrix/documentation_generator.rb +59 -10
  44. data/lib/polytrix/executor.rb +89 -0
  45. data/lib/polytrix/logger.rb +17 -0
  46. data/lib/polytrix/manifest.rb +64 -7
  47. data/lib/polytrix/result.rb +16 -2
  48. data/lib/polytrix/rspec/documentation_formatter.rb +41 -16
  49. data/lib/polytrix/rspec/yaml_report.rb +51 -0
  50. data/lib/polytrix/rspec.rb +32 -53
  51. data/lib/polytrix/runners/middleware/feature_executor.rb +4 -3
  52. data/lib/polytrix/runners/middleware/setup_env_vars.rb +6 -4
  53. data/lib/polytrix/validation.rb +20 -0
  54. data/lib/polytrix/validations.rb +23 -0
  55. data/lib/polytrix/validator.rb +20 -0
  56. data/lib/polytrix/validator_registry.rb +34 -0
  57. data/lib/polytrix/version.rb +1 -1
  58. data/lib/polytrix.rb +125 -22
  59. data/polytrix.gemspec +7 -2
  60. data/polytrix.rb +6 -0
  61. data/polytrix_tests.yml +20 -0
  62. data/resources/code_sample.tt +2 -0
  63. data/samples/.gitignore +2 -0
  64. data/samples/_markdown.md +5 -0
  65. data/samples/default_bootstrap.rb +14 -0
  66. data/samples/polytrix.rb +28 -0
  67. data/samples/polytrix_cli.sh +7 -0
  68. data/samples/polytrix_tests.yml +10 -0
  69. data/{sdks/fog → samples}/scripts/bootstrap +0 -2
  70. data/samples/scripts/wrapper +7 -0
  71. data/samples/sdks/custom/polytrix.yml +2 -0
  72. data/samples/sdks/java/.gitignore +2 -0
  73. data/samples/sdks/java/build.gradle +14 -0
  74. data/samples/sdks/java/challenges/HelloWorld.java +10 -0
  75. data/samples/sdks/java/challenges/Quine.java +31 -0
  76. data/samples/sdks/java/code_sample.tt +11 -0
  77. data/samples/sdks/java/scripts/bootstrap +2 -0
  78. data/samples/sdks/java/scripts/wrapper +8 -0
  79. data/samples/sdks/python/challenges/hello_world.py +2 -0
  80. data/samples/sdks/python/challenges/quine.py +2 -0
  81. data/{sdks/pkgcloud → samples/sdks/python}/scripts/wrapper +1 -1
  82. data/samples/sdks/ruby/challenges/hello_world.rb +4 -0
  83. data/scripts/bootstrap +1 -9
  84. data/scripts/wrapper +7 -0
  85. data/spec/fabricators/challenge_fabricator.rb +17 -0
  86. data/spec/fabricators/manifest_fabricator.rb +50 -0
  87. data/spec/fabricators/validator_fabricator.rb +12 -0
  88. data/spec/fixtures/{polytrix.yml → polytrix_tests.yml} +0 -0
  89. data/spec/fixtures/src-doc/_scenario.md.erb +1 -0
  90. data/spec/polytrix/challenge_runner_spec.rb +3 -3
  91. data/spec/polytrix/challenge_spec.rb +3 -4
  92. data/spec/polytrix/cli_spec.rb +39 -0
  93. data/spec/polytrix/configuration_spec.rb +45 -1
  94. data/spec/polytrix/documentation/helpers/code_helper_spec.rb +120 -0
  95. data/spec/polytrix/documentation_generator_spec.rb +41 -20
  96. data/spec/polytrix/file_finder_spec.rb +4 -3
  97. data/spec/polytrix/implementor_spec.rb +33 -0
  98. data/spec/polytrix/manifest_spec.rb +32 -14
  99. data/spec/polytrix/middleware/feature_executor_spec.rb +1 -1
  100. data/spec/polytrix/result_spec.rb +49 -0
  101. data/spec/polytrix/validations_spec.rb +16 -0
  102. data/spec/polytrix/validator_registry_spec.rb +39 -0
  103. data/spec/polytrix/validator_spec.rb +63 -0
  104. data/spec/polytrix_spec.rb +33 -7
  105. data/spec/spec_helper.rb +14 -1
  106. data/spec/thor_spy.rb +64 -0
  107. metadata +177 -160
  108. data/.rspec_parallel +0 -10
  109. data/Vagrantfile +0 -41
  110. data/features/0_identity_spec.rb +0 -40
  111. data/features/1_cloud_files_spec.rb +0 -48
  112. data/features/2_servers_spec.rb +0 -19
  113. data/features/features_helper.rb +0 -46
  114. data/features/helpers/cloudfiles_helper.rb +0 -31
  115. data/features/helpers/pacto_helper.rb +0 -33
  116. data/features/helpers/teardown_helper.rb +0 -49
  117. data/features/pacto/extensions/loaders/api_blueprint_loader.rb +0 -63
  118. data/features/pacto/extensions/loaders/simple_loader.rb +0 -55
  119. data/features/pacto/extensions/loaders/yaml_or_json_loader.rb +0 -17
  120. data/features/pacto/extensions/matchers.rb +0 -38
  121. data/features/phase2/feature_coverage_report.rb +0 -109
  122. data/features/phase2/run_all_features.rb +0 -14
  123. data/features/static_site/fixtures/index.html +0 -6
  124. data/lib/polytrix/challenge_builder.rb +0 -16
  125. data/lib/polytrix/core/file_finder.rb +0 -43
  126. data/lib/polytrix/core/result_tracker.rb +0 -25
  127. data/lib/polytrix/runners/middleware/pacto.rb +0 -59
  128. data/packer/.gitignore +0 -3
  129. data/packer/Berksfile +0 -15
  130. data/packer/Gemfile +0 -5
  131. data/packer/Vagrantfile +0 -128
  132. data/packer/cookbooks/drg/metadata.rb +0 -27
  133. data/packer/cookbooks/drg/recipes/admins.rb +0 -22
  134. data/packer/cookbooks/drg/recipes/default.rb +0 -9
  135. data/packer/cookbooks/drg/recipes/dotnet.rb +0 -4
  136. data/packer/cookbooks/drg/recipes/golang.rb +0 -4
  137. data/packer/cookbooks/drg/recipes/java.rb +0 -5
  138. data/packer/cookbooks/drg/recipes/php.rb +0 -10
  139. data/packer/cookbooks/drg/recipes/ruby.rb +0 -29
  140. data/packer/cookbooks/drg/recipes/system.rb +0 -13
  141. data/packer/create_box.sh +0 -10
  142. data/packer/http/preseed.cfg +0 -87
  143. data/packer/packer.json +0 -91
  144. data/packer/scripts/root_setup.sh +0 -37
  145. data/packer/scripts/setup.sh +0 -32
  146. data/pacto/config/pacto_server.rb +0 -40
  147. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/extensions.json +0 -64
  148. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/flavors/id.json +0 -100
  149. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/images/id.json +0 -176
  150. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers/id.json +0 -189
  151. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers.json +0 -63
  152. data/pacto/contracts/dns.api.rackspacecloud.com/v1.0/_tenant_id/domains.json +0 -62
  153. data/pacto/contracts/identity.api.rackspacecloud.com/v2.0/tokens.json +0 -192
  154. data/pacto/contracts/monitoring.api.rackspacecloud.com/v1.0/_tenant_id/account.json +0 -39
  155. data/pacto/contracts/ord.autoscale.api.rackspacecloud.com/v1.0/_tenant_id/groups.json +0 -38
  156. data/pacto/contracts/ord.blockstorage.api.rackspacecloud.com/v1/_tenant_id/volumes.json +0 -30
  157. data/pacto/contracts/ord.databases.api.rackspacecloud.com/v1.0/_tenant_id/instances.json +0 -30
  158. data/pacto/contracts/ord.loadbalancers.api.rackspacecloud.com/v1.0/_tenant_id/loadbalancers.json +0 -114
  159. data/pacto/contracts/ord.queues.api.rackspacecloud.com/v1/_tenant_id/queues.json +0 -13
  160. data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/os-networksv2.json +0 -46
  161. data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/servers/detail.json +0 -230
  162. data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account/container/object.json +0 -15
  163. data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account.json +0 -43
  164. data/pacto/contracts/storage101.ord1.clouddrive.com/v1/_mosso_id.json +0 -44
  165. data/pacto/pacto_server.rb +0 -100
  166. data/pacto/rackspace_uri_map.yaml +0 -229
  167. data/scripts/cibuild +0 -4
  168. data/sdks/fog/.gitignore +0 -1
  169. data/sdks/fog/Gemfile +0 -5
  170. data/sdks/fog/challenges/all_connections.rb +0 -45
  171. data/sdks/fog/challenges/authenticate_token.rb +0 -15
  172. data/sdks/fog/challenges/cdn_enable_container.rb +0 -20
  173. data/sdks/fog/challenges/create_a_container.rb +0 -17
  174. data/sdks/fog/challenges/create_server.rb +0 -36
  175. data/sdks/fog/challenges/get_object_metadata.rb +0 -13
  176. data/sdks/fog/challenges/list_containers.rb +0 -10
  177. data/sdks/fog/challenges/provision_scalable_webapp.rb +0 -30
  178. data/sdks/fog/challenges/upload_folder.rb +0 -25
  179. data/sdks/fog/scripts/bootstrap.ps1 +0 -1
  180. data/sdks/fog/scripts/wrapper +0 -2
  181. data/sdks/fog/scripts/wrapper.ps1 +0 -1
  182. data/sdks/gophercloud/.gitignore +0 -2
  183. data/sdks/gophercloud/challenges/authenticate_token.go +0 -23
  184. data/sdks/gophercloud/scripts/bootstrap +0 -6
  185. data/sdks/gophercloud/scripts/wrapper +0 -10
  186. data/sdks/jclouds/.gitignore +0 -1
  187. data/sdks/jclouds/challenges/AuthenticateToken.java +0 -115
  188. data/sdks/jclouds/pom.xml +0 -34
  189. data/sdks/jclouds/scripts/bootstrap +0 -3
  190. data/sdks/jclouds/scripts/wrapper +0 -7
  191. data/sdks/openstack.net/.gitignore +0 -4
  192. data/sdks/openstack.net/.nuget/Microsoft.Build.dll +0 -0
  193. data/sdks/openstack.net/.nuget/NuGet.Config +0 -6
  194. data/sdks/openstack.net/.nuget/NuGet.exe +0 -0
  195. data/sdks/openstack.net/.nuget/NuGet.targets +0 -136
  196. data/sdks/openstack.net/Challenge.cs +0 -10
  197. data/sdks/openstack.net/RunChallenge.cs +0 -19
  198. data/sdks/openstack.net/challenges/AuthenticateToken.cs +0 -24
  199. data/sdks/openstack.net/challenges/Weird.cs +0 -133
  200. data/sdks/openstack.net/openstack.net.csproj +0 -58
  201. data/sdks/openstack.net/openstack.net.sln +0 -27
  202. data/sdks/openstack.net/openstack.net.userprefs +0 -8
  203. data/sdks/openstack.net/packages.config +0 -6
  204. data/sdks/openstack.net/scripts/bootstrap +0 -2
  205. data/sdks/openstack.net/scripts/bootstrap.ps1 +0 -2
  206. data/sdks/openstack.net/scripts/wrapper +0 -7
  207. data/sdks/openstack.net/scripts/wrapper.ps1 +0 -1
  208. data/sdks/php-opencloud/.gitignore +0 -4
  209. data/sdks/php-opencloud/challenges/all_connections.php +0 -64
  210. data/sdks/php-opencloud/challenges/authenticate_token.php +0 -14
  211. data/sdks/php-opencloud/challenges/create_server.php +0 -39
  212. data/sdks/php-opencloud/challenges/get_object_metadata.php +0 -19
  213. data/sdks/php-opencloud/composer.json +0 -5
  214. data/sdks/php-opencloud/scripts/bootstrap +0 -4
  215. data/sdks/php-opencloud/scripts/bootstrap.ps1 +0 -2
  216. data/sdks/php-opencloud/scripts/wrapper +0 -2
  217. data/sdks/php-opencloud/scripts/wrapper.ps1 +0 -1
  218. data/sdks/pkgcloud/.gitignore +0 -1
  219. data/sdks/pkgcloud/challenges/authenticate_token.js +0 -17
  220. data/sdks/pkgcloud/challenges/get_object_metadata.js +0 -18
  221. data/sdks/pkgcloud/scripts/bootstrap +0 -2
  222. data/sdks/pkgcloud/scripts/bootstrap.ps1 +0 -1
  223. data/sdks/pkgcloud/scripts/wrapper.ps1 +0 -1
  224. data/sdks/pyrax/.gitignore +0 -2
  225. data/sdks/pyrax/challenges/all_connections.py +0 -61
  226. data/sdks/pyrax/challenges/authenticate_token.py +0 -17
  227. data/sdks/pyrax/challenges/cdn_enable_container.py +0 -22
  228. data/sdks/pyrax/challenges/create_a_container.py +0 -21
  229. data/sdks/pyrax/challenges/create_server.py +0 -35
  230. data/sdks/pyrax/challenges/get_object_metadata.py +0 -17
  231. data/sdks/pyrax/challenges/upload_folder.py +0 -32
  232. data/sdks/pyrax/requirements.txt +0 -21
  233. data/sdks/pyrax/scripts/bootstrap +0 -9
  234. data/sdks/pyrax/scripts/bootstrap.ps1 +0 -7
  235. data/sdks/pyrax/scripts/wrapper +0 -3
  236. data/sdks/pyrax/scripts/wrapper.ps1 +0 -2
  237. data/spec/polytrix/challenge_builder_spec.rb +0 -16
  238. data/spec/rspec_spec.rb +0 -17
@@ -4,12 +4,13 @@ module Polytrix
4
4
  module Runners
5
5
  module Middleware
6
6
  class SetupEnvVars
7
+ include Polytrix::Core::FileSystemHelper
8
+
7
9
  def initialize(app)
8
10
  @app = app
9
11
  end
10
12
 
11
13
  def call(env)
12
- challenge_runner = env[:challenge_runner]
13
14
  vars = begin
14
15
  Polytrix.manifest[:global_env].dup
15
16
  rescue
@@ -17,15 +18,16 @@ module Polytrix
17
18
  end
18
19
  vars = vars.merge env[:vars].dup
19
20
 
20
- env[:env_file] = setup_env_vars(vars, challenge_runner)
21
+ env[:env_file] = setup_env_vars(env[:name], vars, env[:challenge_runner])
21
22
  @app.call env
22
23
  end
23
24
 
24
25
  private
25
26
 
26
- def setup_env_vars(vars, challenge_runner)
27
+ def setup_env_vars(challenge_name, vars, challenge_runner)
27
28
  FileUtils.mkdir_p 'tmp'
28
- file = File.open("tmp/vars.#{challenge_runner.script_extension}", 'w')
29
+ extension = challenge_runner.script_extension
30
+ file = File.open(slugify("tmp/#{challenge_name}_vars.#{extension}"), 'w')
29
31
  vars.each do |key, value|
30
32
  file.puts challenge_runner.save_environment_variable(key, value)
31
33
  end
@@ -0,0 +1,20 @@
1
+ require 'hashie/dash'
2
+
3
+ module Polytrix
4
+ class Validation < Hashie::Dash
5
+ ALLOWABLE_STATES = %w(passed pending failed skipped)
6
+ property :validated_by, required: true
7
+ property :result
8
+
9
+ def result=(state)
10
+ fail invalidate_state_error unless ALLOWABLE_STATES.include? state
11
+ super
12
+ end
13
+
14
+ protected
15
+
16
+ def invalidate_state_error(state)
17
+ ArgumentError.new "Invalid result state: #{state}, should be one of #{ALLOWABLE_STATES.inspect}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ require 'hashie/dash'
2
+
3
+ module Polytrix
4
+ class Validations < Set
5
+ def to_hash
6
+ map do |v|
7
+ v.to_hash
8
+ end
9
+ end
10
+
11
+ def to_yaml
12
+ to_hash.to_yaml
13
+ end
14
+
15
+ # Hashie Coercion - automatically treat all values as Validation
16
+ def self.coerce(obj)
17
+ data = obj.map do |value|
18
+ Validation.new(value)
19
+ end
20
+ new data
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module Polytrix
2
+ class Validator
3
+ UNIVERSAL_MATCHER = //
4
+ attr_reader :suite, :sample, :callback
5
+
6
+ def initialize(scope = {}, &validator)
7
+ @suite = scope[:suite] ||= UNIVERSAL_MATCHER
8
+ @sample = scope[:sample] ||= UNIVERSAL_MATCHER
9
+ @callback = validator
10
+ end
11
+
12
+ def should_validate?(challenge)
13
+ !!(@suite.match(challenge.suite) && @sample.match(challenge.name))
14
+ end
15
+
16
+ # def validate(challenge)
17
+ # instance_exec challenge, @callback if should_validate?(challenge)
18
+ # end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ require 'singleton'
2
+
3
+ module Polytrix
4
+ class ValidatorRegistry
5
+ include Singleton
6
+
7
+ def validators
8
+ @validator ||= []
9
+ end
10
+
11
+ class << self
12
+ def validators
13
+ instance.validators
14
+ end
15
+
16
+ def register(validator, &callback)
17
+ if block_given?
18
+ match_rules = validator
19
+ validator = Validator.new(match_rules, &callback)
20
+ end
21
+ validators << validator
22
+ end
23
+
24
+ def validators_for(challenge)
25
+ selected_validators = validators.select { |v| v.should_validate? challenge }
26
+ selected_validators.empty? ? [Polytrix.configuration.default_validator] : selected_validators
27
+ end
28
+
29
+ def clear
30
+ validators.clear
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module Polytrix
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0.pre'
3
3
  end
data/lib/polytrix.rb CHANGED
@@ -1,56 +1,159 @@
1
+ require 'pathname'
2
+ require 'hashie/dash'
3
+ require 'hashie/mash'
4
+ require 'hashie/extensions/coercion'
1
5
  require 'polytrix/version'
2
- require 'polytrix/manifest'
6
+ require 'polytrix/logger'
7
+ require 'polytrix/core/file_system_helper'
8
+ require 'polytrix/executor'
3
9
  require 'polytrix/core/implementor'
4
- require 'polytrix/core/result_tracker'
5
- require 'polytrix/core/file_finder'
6
10
  require 'polytrix/challenge_runner'
7
11
  require 'polytrix/challenge'
8
- require 'polytrix/challenge_builder'
12
+ require 'polytrix/manifest'
9
13
  require 'polytrix/configuration'
14
+ require 'polytrix/validation'
15
+ require 'polytrix/validations'
10
16
  require 'polytrix/result'
11
17
  require 'polytrix/documentation_generator'
18
+ require 'polytrix/validator'
19
+ require 'polytrix/validator_registry'
12
20
 
13
21
  require 'polytrix/rspec'
14
22
 
15
23
  module Polytrix
24
+ include Polytrix::Logger
25
+
16
26
  class << self
17
- attr_accessor :implementors
18
- attr_accessor :manifest
19
- attr_accessor :default_validator_callback
27
+ include Polytrix::Core::FileSystemHelper
28
+
29
+ def reset
30
+ @configuration = nil
31
+ Polytrix::ValidatorRegistry.clear
32
+ end
33
+
34
+ # The {Polytrix::Manifest} that describes the test scenarios known to Polytrix.
35
+ def manifest
36
+ configuration.test_manifest
37
+ end
38
+
39
+ # The set of {Polytrix::Implementor}s registered with Polytrix.
40
+ def implementors
41
+ configuration.implementors
42
+ end
43
+
44
+ def find_implementor(file)
45
+ existing_implementor = recursive_parent_search(File.dirname(file)) do |path|
46
+ implementors.find do |implementor|
47
+ File.absolute_path(implementor.basedir) == File.absolute_path(path)
48
+ end
49
+ end
50
+ return existing_implementor if existing_implementor
51
+
52
+ implementor_basedir = recursive_parent_search(File.dirname(file), 'polytrix.yml')
53
+ return Polytrix.configuration.implementor implementor_basedir if implementor_basedir
54
+
55
+ nil
56
+ end
20
57
 
21
- def default_validator_callback
22
- @default_validator_callback ||= proc{ |challenge|
23
- expect(challenge[:result].process.exitstatus).to eq(0)
58
+ # Invokes the bootstrap action for each SDK.
59
+ # @see Polytrix::Implementor#bootstrap
60
+ def bootstrap(*sdks)
61
+ select_implementors(sdks).each do |implementor|
62
+ implementor.bootstrap
63
+ end
64
+ end
65
+
66
+ def exec(file, exec_options)
67
+ implementor = find_implementor(file) || exec_options[:default_implementor]
68
+
69
+ extension = File.extname(file)
70
+ name = File.basename(file, extension)
71
+ challenge_data = {
72
+ name: name,
73
+ # language: extension,
74
+ source_file: File.expand_path(file, Dir.pwd)
24
75
  }
76
+ challenge = implementor.build_challenge challenge_data
77
+ challenge.run
25
78
  end
26
79
 
27
- def default_validator_callback=(callback)
28
- @default_validator_callback = callback
80
+ # Registers a {Polytrix::Validator} that will be used during test
81
+ # execution on matching {Polytrix::Challenge}s.
82
+ def validate(scope = { suite: //, sample: // }, validator = nil, &block)
83
+ if block_given?
84
+ validator = Polytrix::Validator.new(scope, &block)
85
+ elsif validator.nil?
86
+ fail ArgumentError 'You must a block or a Validator as the second argument'
87
+ end
88
+
89
+ Polytrix::ValidatorRegistry.register validator
90
+ validator
29
91
  end
30
92
 
93
+ def load_tests
94
+ Polytrix::RSpec.run_manifest(manifest)
95
+ end
96
+
97
+ # Runs all of the tests described in the {manifest}
98
+ def run_tests(implementors = [])
99
+ test_env = ENV['TEST_ENV_NUMBER'].to_i
100
+ rspec_options = %W[--color -f documentation -f Polytrix::RSpec::YAMLReport -o reports/test_report#{test_env}.yaml]
101
+ rspec_options.concat Polytrix.configuration.rspec_options.split if Polytrix.configuration.rspec_options
102
+ unless implementors.empty?
103
+ target_sdks = implementors.map(&:name)
104
+ Polytrix.implementors.map(&:name).each do |sdk|
105
+ # We don't have an "or" for tags, so it's easier to exclude than include multiple tags
106
+ rspec_options.concat %W[-t ~#{sdk.to_sym}] unless target_sdks.include? sdk
107
+ end
108
+ end
109
+
110
+ load_tests
111
+ logger.info "polytrix:test\tTesting with rspec options: #{rspec_options.join ' '}"
112
+ ::RSpec::Core::Runner.run rspec_options
113
+ logger.info "polytrix:test\tTest execution completed"
114
+ end
115
+
116
+ def reset
117
+ @configuration = nil
118
+ end
119
+
120
+ # @see Polytrix::Configuration
31
121
  def configuration
32
122
  fail "configuration doesn't take a block, use configure" if block_given?
33
123
  @configuration ||= Configuration.new
34
124
  end
35
125
 
126
+ # @see Polytrix::Configuration
36
127
  def configure
37
128
  yield(configuration)
38
129
  end
39
130
 
40
- def sdk_dir(sdk)
41
- "sdks/#{sdk}"
131
+ # Merges multiple test results files produced the rspec {Polytrix::RSpec::YAMLReport} formatter.
132
+ # @param result_files [Array] the location of the files to merge.
133
+ # @return [String] the merged content
134
+ def merge_results(result_files)
135
+ merged_results = Polytrix::Manifest.new
136
+ result_files.each do |result_file|
137
+ merged_results.deep_merge! YAML.load(File.read(result_file))
138
+ end
139
+ YAML.dump(merged_results.to_hash)
42
140
  end
43
141
 
44
- def load_manifest(yaml_file)
45
- @manifest = Polytrix::Manifest.from_yaml yaml_file
46
- end
142
+ protected
47
143
 
48
- def results
49
- Polytrix::ResultTracker.instance
50
- end
144
+ def select_implementors(sdks)
145
+ return implementors if sdks.empty?
51
146
 
52
- def run_tests
53
- Polytrix::RSpec.run_manifest(@manifest)
147
+ sdks.map do |sdk|
148
+ if File.directory? sdk
149
+ sdk_dir = File.absolute_path(sdk)
150
+ implementors.find { |i| File.absolute_path(i.basedir) == sdk_dir } || configuration.implementor(sdk_dir)
151
+ else
152
+ implementor = implementors.find { |i| i.name == sdk }
153
+ fail ArgumentError, "SDK #{sdk} not found" if implementor.nil?
154
+ implementor
155
+ end
156
+ end
54
157
  end
55
158
  end
56
159
  end
data/polytrix.gemspec CHANGED
@@ -18,10 +18,15 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "thor", "~> 0.19"
21
22
  spec.add_dependency "mixlib-shellout", "~> 1.3"
22
23
  spec.add_dependency "middleware", "~> 0.1"
23
- spec.add_dependency "rspec", "~> 2.14"
24
- spec.add_dependency "hashie", "~> 2.0"
24
+ spec.add_dependency "rspec", "~> 2.99"
25
+ spec.add_dependency "hashie", "~> 2.1"
26
+ spec.add_dependency "padrino-helpers", "~> 0.12"
25
27
  spec.add_development_dependency "bundler", "~> 1.5"
26
28
  spec.add_development_dependency "rake"
29
+ spec.add_development_dependency "aruba", "~> 0.5"
30
+ spec.add_development_dependency 'rubocop', '~> 0.18.0'
31
+ spec.add_development_dependency 'fabrication', '~> 2.11'
27
32
  end
data/polytrix.rb ADDED
@@ -0,0 +1,6 @@
1
+ Polytrix.configuration.default_doc_template = 'doc-src/_markdown.md'
2
+
3
+ Polytrix.configure do |polytrix|
4
+ polytrix.test_manifest = 'polytrix_tests.yml'
5
+ polytrix.implementor name: 'polytrix', language: 'ruby', basedir: 'samples/'
6
+ end
@@ -0,0 +1,20 @@
1
+ ---
2
+ global_env: # global_env defines input available for all scenarios
3
+ LOCALE: <%= ENV['LANG'] %> # templating is allowed
4
+ FAVORITE_NUMBER: 5
5
+ suites:
6
+ Bootstrapping:
7
+ samples:
8
+ - default bootstrap
9
+ - custom bootstrap
10
+ Testing: # "Katas" is the name of the first suite
11
+ env: # These "env" values are only available within the "Katas" suite
12
+ NAME: 'Max'
13
+ samples: # samples defines the individual tests in a suite
14
+ - default validation
15
+ - custom validation
16
+ Plugins: # "Tutorials" is the name of the second suite
17
+ env:
18
+ samples:
19
+ - validating
20
+ - reporting
@@ -0,0 +1,2 @@
1
+ <%= commented "Sample for #{@scenario.name}" %>
2
+ <%= commented @scenario.description if @scenario.description %>
@@ -0,0 +1,2 @@
1
+ reports/
2
+ tmp/
@@ -0,0 +1,5 @@
1
+ <% challenges.compact.each do |challenge| %>
2
+ ``` <%= challenge.implementor.language %>
3
+ <%= File.read(challenge.source_file) %>
4
+ ```
5
+ <% end %>
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This example shows the default behavior of `Polytrix#bootstrap`
4
+ require 'polytrix'
5
+
6
+ Polytrix.configure do |polytrix|
7
+ Dir['sdks/*'].each do |sdk|
8
+ name = File.basename(sdk)
9
+ polytrix.implementor name: name, basedir: sdk
10
+ end
11
+ end
12
+
13
+ # Snippet: bootstrap
14
+ Polytrix.bootstrap
@@ -0,0 +1,28 @@
1
+ require 'polytrix'
2
+
3
+ basedir = File.expand_path('..', __FILE__)
4
+
5
+ Polytrix.configure do |polytrix|
6
+ Dir["#{basedir}/sdks/*"].each do |sdk|
7
+ name = File.basename(sdk)
8
+ polytrix.implementor name: name, basedir: sdk
9
+ end
10
+ end
11
+
12
+ RSpec.configure do |c|
13
+ c.expose_current_running_example_as :example
14
+ end
15
+
16
+ Polytrix.validate suite: 'Katas', sample: 'hello world' do |challenge|
17
+ expect(challenge.result.stdout).to eq "Hello, world!\n"
18
+ end
19
+
20
+ Polytrix.validate suite: 'Katas', sample: 'quine' do |challenge|
21
+ expect(challenge.result.stdout).to eq(challenge.source)
22
+ end
23
+
24
+ Polytrix.validate do |challenge|
25
+ expect(challenge.result.exitstatus).to eq(0)
26
+ expect(challenge.result.stderr).to be_empty
27
+ expect(challenge.result.stdout).to end_with "\n"
28
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash -e
2
+ bundle exec polytrix bootstrap
3
+ bundle exec polytrix exec sdks/ruby/challenges/*.rb --code2doc --target-dir=docs/ruby/
4
+ bundle exec polytrix test
5
+ bundle exec polytrix report summary
6
+ bundle exec polytrix report summary --format=markdown
7
+ bundle exec polytrix report summary --format=yaml
@@ -0,0 +1,10 @@
1
+ ---
2
+ global_env: # global_env defines input available for all scenarios
3
+ LOCALE: <%= ENV['LANG'] %> # templating is allowed
4
+ suites:
5
+ Katas: # "Katas" is the name of the first test suite
6
+ env: # Unlike global_env, these variables are only for the Katas suite
7
+ COLOR: red
8
+ samples: # Test scenarios within Katas
9
+ - hello world
10
+ - quine
@@ -1,4 +1,2 @@
1
1
  #!/bin/bash
2
-
3
2
  bundle install
4
-
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ if [[ "$1" == *.rb ]]
3
+ then
4
+ bundle exec ruby "$@"
5
+ else
6
+ bundle exec "$@"
7
+ fi
@@ -0,0 +1,2 @@
1
+ ---
2
+ name: My Custom project
@@ -0,0 +1,2 @@
1
+ .gradle/
2
+ build/
@@ -0,0 +1,14 @@
1
+ apply plugin: 'java'
2
+ sourceSets {
3
+ main {
4
+ java {
5
+ srcDir 'challenges'
6
+ }
7
+ }
8
+ }
9
+ version = '1.0'
10
+ jar {
11
+ manifest {
12
+ attributes 'Implementation-Title': 'Java Samples', 'Implementation-Version': version
13
+ }
14
+ }
@@ -0,0 +1,10 @@
1
+ // This is an example of the standard [Hello World](http://en.wikipedia.org/wiki/Hello_world_program)
2
+ // program written in [Java][java].
3
+ public class HelloWorld {
4
+ // A Java CLI application is defined by creating a main method with this signature:
5
+ public static void main(String[] args) {
6
+ System.out.println("Hello, world!");
7
+ }
8
+ }
9
+
10
+ // [java]: http://en.wikipedia.org/wiki/Java_(programming_language)
@@ -0,0 +1,31 @@
1
+ public class Quine
2
+ {
3
+ public static void main(String[] args)
4
+ {
5
+ char q = 34; // Quotation mark character
6
+ String[] l = { // Array of source code
7
+ "public class Quine",
8
+ "{",
9
+ " public static void main(String[] args)",
10
+ " {",
11
+ " char q = 34; // Quotation mark character",
12
+ " String[] l = { // Array of source code",
13
+ " ",
14
+ " };",
15
+ " for(int i = 0; i < 6; i++ ) // Print opening code",
16
+ " System.out.println(l[i]);",
17
+ " for(int i = 0; i < l.length; i++) // Print string array",
18
+ " System.out.println( l[6] + q + l[i] + q + ',' );",
19
+ " for(int i = 7; i < l.length; i++) // Print this code",
20
+ " System.out.println( l[i] );",
21
+ " }",
22
+ "}",
23
+ };
24
+ for(int i = 0; i < 6; i++ ) // Print opening code
25
+ System.out.println(l[i]);
26
+ for(int i = 0; i < l.length; i++) // Print string array
27
+ System.out.println( l[6] + q + l[i] + q + ',' );
28
+ for(int i = 7; i < l.length; i++) // Print this code
29
+ System.out.println( l[i] );
30
+ }
31
+ }
@@ -0,0 +1,11 @@
1
+ public class <%= @scenario.name %> {
2
+ public static void main(String[] args) {
3
+ <%= commented @scenario.name %>
4
+ <%= commented """
5
+ This is
6
+ a multi line
7
+ test
8
+ """ %>
9
+ <%= commented "This is\nanother multi line\ntest\n" %>
10
+ }
11
+ }
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ gradle build
@@ -0,0 +1,8 @@
1
+ #!/bin/bash
2
+ SOURCE_FILE=$1
3
+ CLASSNAME=`basename $SOURCE_FILE .java`
4
+ #NAMESPACE=org.example.
5
+ CLASS="${NAMESPACE}${CLASSNAME}"
6
+ gradle assemble --quiet
7
+ java -classpath build/libs/java-1.0.jar $CLASS
8
+
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env python
2
+ print 'Hello, world!'
@@ -0,0 +1,2 @@
1
+ s = 's = %r\nprint(s%%s)'
2
+ print(s%s)
@@ -1,2 +1,2 @@
1
1
  #!/bin/bash
2
- node "$@"
2
+ python "$@"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ name = 'world'
3
+ # This will print Hello, world!
4
+ puts "Hello, #{name}!"
data/scripts/bootstrap CHANGED
@@ -1,10 +1,2 @@
1
1
  #!/bin/bash
2
- gem install bundler --no-ri --no-rdoc
3
- rbenv rehash
4
- bundle update
5
- virtualenv polytrix
6
- source polytrix/bin/activate
7
- pip install pygments
8
- npm install groc
9
- export PATH="$PATH:`pwd`/node_modules/.bin"
10
- bundle exec rake bootstrap
2
+ bundle install
data/scripts/wrapper ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ if [[ "$1" == *.rb ]]
3
+ then
4
+ bundle exec ruby "$@"
5
+ else
6
+ bundle exec "$@"
7
+ fi
@@ -0,0 +1,17 @@
1
+ require 'hashie/mash'
2
+
3
+ # Fabricates test manifests (.polytrix_tests.yml files)
4
+ LANGUAGES = %w(java ruby python nodejs c# golang php)
5
+ SAMPLE_NAMES = [
6
+ 'hello world',
7
+ 'quine',
8
+ 'my_kata'
9
+ ]
10
+
11
+ Fabricator(:challenge, from: Polytrix::Challenge) do
12
+ initialize_with { @_klass.new to_hash } # Hash based initialization
13
+ name { SAMPLE_NAMES.sample }
14
+ suite { LANGUAGES.sample }
15
+ source_file { 'spec/fixtures/factorial.py' }
16
+ basedir { 'spec/fixtures' }
17
+ end