polytrix 0.1.0.pre → 0.1.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 +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -2
- data/.travis.yml +2 -1
- data/Gemfile +1 -0
- data/README.md +190 -98
- data/Rakefile +8 -6
- data/bin/polytrix +2 -1
- data/docs/samples/code2doc/java/HelloWorld.md +4 -0
- data/docs/samples/code2doc/java/Quine.md +2 -0
- data/docs/samples/code2doc/python/hello_world.md +2 -0
- data/docs/samples/code2doc/python/quine.md +2 -0
- data/docs/samples/code2doc/ruby/hello_world.md +4 -0
- data/features/bootstrapping.feature +36 -0
- data/features/cloning.feature +34 -0
- data/features/execution.feature +2 -16
- data/features/fixtures/configs/empty.yml +12 -1
- data/features/fixtures/configs/hello_world.yml +11 -1
- data/features/fixtures/spec/polytrix_spec.rb +1 -4
- data/features/solo.feature +12 -0
- data/features/states.feature +40 -0
- data/features/step_definitions/sdk_steps.rb +11 -1
- data/features/support/env.rb +2 -1
- data/lib/polytrix/challenge.rb +211 -13
- data/lib/polytrix/challenge_result.rb +9 -0
- data/lib/polytrix/challenge_runner.rb +4 -11
- data/lib/polytrix/challenges.rb +16 -0
- data/lib/polytrix/cli/report.rb +0 -4
- data/lib/polytrix/cli.rb +229 -137
- data/lib/polytrix/color.rb +40 -0
- data/lib/polytrix/command/action.rb +26 -0
- data/lib/polytrix/command/list.rb +53 -0
- data/lib/polytrix/command/rundoc.rb +27 -0
- data/lib/polytrix/command/test.rb +24 -0
- data/lib/polytrix/command.rb +209 -0
- data/lib/polytrix/configuration.rb +30 -40
- data/lib/polytrix/core/file_system_helper.rb +2 -5
- data/lib/polytrix/core/hashie.rb +14 -0
- data/lib/polytrix/core/implementor.rb +52 -12
- data/lib/polytrix/core/manifest_section.rb +4 -0
- data/lib/polytrix/core/string_helpers.rb +15 -0
- data/lib/polytrix/documentation/helpers/code_helper.rb +3 -1
- data/lib/polytrix/error.rb +209 -0
- data/lib/polytrix/logger.rb +365 -8
- data/lib/polytrix/logging.rb +34 -0
- data/lib/polytrix/manifest.rb +40 -26
- data/lib/polytrix/result.rb +1 -0
- data/lib/polytrix/rspec.rb +7 -5
- data/lib/polytrix/runners/buff_shellout_executor.rb +19 -0
- data/lib/polytrix/runners/executor.rb +32 -0
- data/lib/polytrix/runners/mixlib_shellout_executor.rb +83 -0
- data/lib/polytrix/state_file.rb +60 -0
- data/lib/polytrix/util.rb +155 -0
- data/lib/polytrix/validation.rb +1 -1
- data/lib/polytrix/validator.rb +9 -5
- data/lib/polytrix/version.rb +1 -1
- data/lib/polytrix.rb +55 -33
- data/polytrix.gemspec +4 -2
- data/polytrix.rb +0 -5
- data/{polytrix_tests.yml → polytrix.yml} +5 -0
- data/samples/default_bootstrap.rb +0 -7
- data/samples/polytrix.rb +0 -9
- data/samples/{polytrix_tests.yml → polytrix.yml} +11 -0
- data/samples/polytrix_cli.sh +1 -1
- data/spec/fabricators/implementor_fabricator.rb +20 -0
- data/spec/fabricators/manifest_fabricator.rb +4 -1
- data/spec/fixtures/{polytrix_tests.yml → polytrix.yml} +10 -0
- data/spec/polytrix/challenge_runner_spec.rb +3 -2
- data/spec/polytrix/challenge_spec.rb +5 -4
- data/spec/polytrix/cli_spec.rb +23 -26
- data/spec/polytrix/configuration_spec.rb +4 -43
- data/spec/polytrix/documentation/helpers/code_helper_spec.rb +1 -1
- data/spec/polytrix/documentation_generator_spec.rb +2 -0
- data/spec/polytrix/implementor_spec.rb +44 -2
- data/spec/polytrix/manifest_spec.rb +7 -4
- data/spec/polytrix_spec.rb +9 -11
- data/spec/thor_spy.rb +2 -0
- metadata +66 -16
- data/features/fixtures/spec/polytrix_merge.rb +0 -5
- data/features/reporting.feature +0 -140
- data/lib/polytrix/executor.rb +0 -89
- data/samples/sdks/custom/polytrix.yml +0 -2
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
|
3
|
+
module Polytrix
|
4
|
+
class StateFileLoadError < StandardError; end
|
5
|
+
class StateFile
|
6
|
+
def initialize(polytrix_root, name)
|
7
|
+
@file_name = File.expand_path(
|
8
|
+
File.join(polytrix_root, '.polytrix', "#{name}.yml")
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
def read
|
13
|
+
if File.exist?(file_name)
|
14
|
+
Hashie::Mash.load(file_name).dup
|
15
|
+
else
|
16
|
+
Hashie::Mash.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def write(state)
|
21
|
+
dir = File.dirname(file_name)
|
22
|
+
serialized_string = serialize_hash(Util.stringified_hash(state))
|
23
|
+
|
24
|
+
FileUtils.mkdir_p(dir) unless File.directory?(dir)
|
25
|
+
File.open(file_name, 'wb') { |f| f.write(serialized_string) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def destroy
|
29
|
+
FileUtils.rm_f(file_name) if File.exist?(file_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def diagnose
|
33
|
+
raw = read
|
34
|
+
result = {}
|
35
|
+
raw.keys.sort.each { |k| result[k] = raw[k] }
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
attr_reader :file_name
|
42
|
+
|
43
|
+
# @api private
|
44
|
+
def read_file
|
45
|
+
IO.read(file_name)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @api private
|
49
|
+
def deserialize_string(string)
|
50
|
+
SafeYAML.load(string)
|
51
|
+
rescue SyntaxError, Psych::SyntaxError => ex
|
52
|
+
raise StateFileLoadError, "Error parsing #{file_name} (#{ex.message})"
|
53
|
+
end
|
54
|
+
|
55
|
+
# @api private
|
56
|
+
def serialize_hash(hash)
|
57
|
+
::YAML.dump(hash)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012, 2013, 2014, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
module Polytrix
|
20
|
+
# Stateless utility methods used in different contexts. Essentially a mini
|
21
|
+
# PassiveSupport library.
|
22
|
+
module Util
|
23
|
+
# Returns the standard library Logger level constants for a given symbol
|
24
|
+
# representation.
|
25
|
+
#
|
26
|
+
# @param symbol [Symbol] symbol representation of a logger level (:debug,
|
27
|
+
# :info, :warn, :error, :fatal)
|
28
|
+
# @return [Integer] Logger::Severity constant value or nil if input is not
|
29
|
+
# valid
|
30
|
+
def self.to_logger_level(symbol)
|
31
|
+
return nil unless [:debug, :info, :warn, :error, :fatal].include?(symbol)
|
32
|
+
|
33
|
+
Logger.const_get(symbol.to_s.upcase)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the symbol represenation of a logging levels for a given
|
37
|
+
# standard library Logger::Severity constant.
|
38
|
+
#
|
39
|
+
# @param const [Integer] Logger::Severity constant value for a logging
|
40
|
+
# level (Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR,
|
41
|
+
# Logger::FATAL)
|
42
|
+
# @return [Symbol] symbol representation of the logging level
|
43
|
+
def self.from_logger_level(const)
|
44
|
+
case const
|
45
|
+
when Logger::DEBUG then :debug
|
46
|
+
when Logger::INFO then :info
|
47
|
+
when Logger::WARN then :warn
|
48
|
+
when Logger::ERROR then :error
|
49
|
+
else :fatal
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns a new Hash with all key values coerced to symbols. All keys
|
54
|
+
# within a Hash are coerced by calling #to_sym and hashes within arrays
|
55
|
+
# and other hashes are traversed.
|
56
|
+
#
|
57
|
+
# @param obj [Object] the hash to be processed. While intended for
|
58
|
+
# hashes, this method safely processes arbitrary objects
|
59
|
+
# @return [Object] a converted hash with all keys as symbols
|
60
|
+
def self.symbolized_hash(obj)
|
61
|
+
if obj.is_a?(Hash)
|
62
|
+
obj.reduce({}) do |h, (k, v)|
|
63
|
+
h[k.to_sym] = symbolized_hash(v)
|
64
|
+
h
|
65
|
+
end
|
66
|
+
elsif obj.is_a?(Array)
|
67
|
+
obj.reduce([]) do |a, e|
|
68
|
+
a << symbolized_hash(e)
|
69
|
+
a
|
70
|
+
end
|
71
|
+
else
|
72
|
+
obj
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns a new Hash with all key values coerced to strings. All keys
|
77
|
+
# within a Hash are coerced by calling #to_s and hashes with arrays
|
78
|
+
# and other hashes are traversed.
|
79
|
+
#
|
80
|
+
# @param obj [Object] the hash to be processed. While intended for
|
81
|
+
# hashes, this method safely processes arbitrary objects
|
82
|
+
# @return [Object] a converted hash with all keys as strings
|
83
|
+
def self.stringified_hash(obj)
|
84
|
+
if obj.is_a?(Hash)
|
85
|
+
obj.reduce({}) do |h, (k, v)|
|
86
|
+
h[k.to_s] = stringified_hash(v)
|
87
|
+
h
|
88
|
+
end
|
89
|
+
elsif obj.is_a?(Array)
|
90
|
+
obj.reduce([]) do |a, e|
|
91
|
+
a << stringified_hash(e)
|
92
|
+
a
|
93
|
+
end
|
94
|
+
else
|
95
|
+
obj
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns a formatted string representing a duration in seconds.
|
100
|
+
#
|
101
|
+
# @param total [Integer] the total number of seconds
|
102
|
+
# @return [String] a formatted string of the form (XmYY.00s)
|
103
|
+
def self.duration(total)
|
104
|
+
total = 0 if total.nil?
|
105
|
+
minutes = (total / 60).to_i
|
106
|
+
seconds = (total - (minutes * 60))
|
107
|
+
format('(%dm%.2fs)', minutes, seconds)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Generates a command (or series of commands) wrapped so that it can be
|
111
|
+
# invoked on a remote instance or locally.
|
112
|
+
#
|
113
|
+
# This method uses the Bourne shell (/bin/sh) to maximize the chance of
|
114
|
+
# cross platform portability on Unixlike systems.
|
115
|
+
#
|
116
|
+
# @param [String] the command
|
117
|
+
# @return [String] a wrapped command string
|
118
|
+
def self.wrap_command(cmd)
|
119
|
+
cmd = 'false' if cmd.nil?
|
120
|
+
cmd = 'true' if cmd.to_s.empty?
|
121
|
+
cmd = cmd.sub(/\n\Z/, '') if cmd =~ /\n\Z/
|
122
|
+
|
123
|
+
"sh -c '\n#{cmd}\n'"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Modifes the given string to strip leading whitespace on each line, the
|
127
|
+
# amount which is calculated by using the first line of text.
|
128
|
+
#
|
129
|
+
# @example
|
130
|
+
#
|
131
|
+
# string = <<-STRING
|
132
|
+
# a
|
133
|
+
# b
|
134
|
+
# c
|
135
|
+
# STRING
|
136
|
+
# Util.outdent!(string) # => "a\n b\nc\n"
|
137
|
+
#
|
138
|
+
# @param string [String] the string that will be modified
|
139
|
+
# @return [String] the modified string
|
140
|
+
def self.outdent!(string)
|
141
|
+
string.gsub!(/^ {#{string.index(/[^ ]/)}}/, '')
|
142
|
+
end
|
143
|
+
|
144
|
+
# Returns a set of Bourne Shell (AKA /bin/sh) compatible helper
|
145
|
+
# functions. This function is usually called inline in a string that
|
146
|
+
# will be executed remotely on a test instance.
|
147
|
+
#
|
148
|
+
# @return [String] a string representation of useful helper functions
|
149
|
+
def self.shell_helpers
|
150
|
+
IO.read(File.join(
|
151
|
+
File.dirname(__FILE__), %w[.. .. support download_helpers.sh]
|
152
|
+
))
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
data/lib/polytrix/validation.rb
CHANGED
data/lib/polytrix/validator.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
1
3
|
module Polytrix
|
2
4
|
class Validator
|
5
|
+
include RSpec::Matchers
|
6
|
+
|
3
7
|
UNIVERSAL_MATCHER = //
|
4
|
-
attr_reader :suite, :sample, :callback
|
8
|
+
attr_reader :suite, :sample, :level, :callback
|
5
9
|
|
6
10
|
def initialize(scope = {}, &validator)
|
7
11
|
@suite = scope[:suite] ||= UNIVERSAL_MATCHER
|
@@ -10,11 +14,11 @@ module Polytrix
|
|
10
14
|
end
|
11
15
|
|
12
16
|
def should_validate?(challenge)
|
13
|
-
!!(@suite.match(challenge.suite) && @sample.match(challenge.name))
|
17
|
+
!!(@suite.match(challenge.suite.to_s) && @sample.match(challenge.name.to_s))
|
14
18
|
end
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
def validate(challenge)
|
21
|
+
instance_exec challenge, &@callback if should_validate?(challenge)
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
data/lib/polytrix/version.rb
CHANGED
data/lib/polytrix.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
require 'pathname'
|
2
|
-
require '
|
3
|
-
require 'hashie
|
4
|
-
require '
|
2
|
+
require 'polytrix/error'
|
3
|
+
require 'polytrix/core/hashie'
|
4
|
+
require 'polytrix/core/string_helpers'
|
5
5
|
require 'polytrix/version'
|
6
|
+
require 'polytrix/util'
|
7
|
+
require 'polytrix/color'
|
6
8
|
require 'polytrix/logger'
|
9
|
+
require 'polytrix/logging'
|
10
|
+
require 'polytrix/state_file'
|
7
11
|
require 'polytrix/core/file_system_helper'
|
8
|
-
require 'polytrix/executor'
|
12
|
+
require 'polytrix/runners/executor'
|
13
|
+
require 'polytrix/core/manifest_section'
|
9
14
|
require 'polytrix/core/implementor'
|
10
15
|
require 'polytrix/challenge_runner'
|
16
|
+
require 'polytrix/challenge_result'
|
11
17
|
require 'polytrix/challenge'
|
18
|
+
require 'polytrix/challenges'
|
12
19
|
require 'polytrix/manifest'
|
13
20
|
require 'polytrix/configuration'
|
14
21
|
require 'polytrix/validation'
|
@@ -21,11 +28,15 @@ require 'polytrix/validator_registry'
|
|
21
28
|
require 'polytrix/rspec'
|
22
29
|
|
23
30
|
module Polytrix
|
24
|
-
include Polytrix::
|
31
|
+
include Polytrix::DefaultLogger
|
32
|
+
include Polytrix::Logging
|
25
33
|
|
26
34
|
class << self
|
27
35
|
include Polytrix::Core::FileSystemHelper
|
28
36
|
|
37
|
+
# @return [Mutex] a common mutex for global coordination
|
38
|
+
attr_accessor :mutex
|
39
|
+
|
29
40
|
def reset
|
30
41
|
@configuration = nil
|
31
42
|
Polytrix::ValidatorRegistry.clear
|
@@ -33,12 +44,12 @@ module Polytrix
|
|
33
44
|
|
34
45
|
# The {Polytrix::Manifest} that describes the test scenarios known to Polytrix.
|
35
46
|
def manifest
|
36
|
-
configuration.
|
47
|
+
configuration.manifest
|
37
48
|
end
|
38
49
|
|
39
50
|
# The set of {Polytrix::Implementor}s registered with Polytrix.
|
40
51
|
def implementors
|
41
|
-
|
52
|
+
manifest.implementors.values
|
42
53
|
end
|
43
54
|
|
44
55
|
def find_implementor(file)
|
@@ -49,12 +60,17 @@ module Polytrix
|
|
49
60
|
end
|
50
61
|
return existing_implementor if existing_implementor
|
51
62
|
|
52
|
-
implementor_basedir = recursive_parent_search(File.dirname(file), 'polytrix.yml')
|
53
|
-
return Polytrix.configuration.implementor implementor_basedir if implementor_basedir
|
54
|
-
|
55
63
|
nil
|
56
64
|
end
|
57
65
|
|
66
|
+
# Invokes the clone action for each SDK.
|
67
|
+
# @see Polytrix::Implementor#clone
|
68
|
+
def clone(*sdks)
|
69
|
+
select_implementors(sdks).each do |implementor|
|
70
|
+
implementor.clone
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
58
74
|
# Invokes the bootstrap action for each SDK.
|
59
75
|
# @see Polytrix::Implementor#bootstrap
|
60
76
|
def bootstrap(*sdks)
|
@@ -63,18 +79,24 @@ module Polytrix
|
|
63
79
|
end
|
64
80
|
end
|
65
81
|
|
66
|
-
def exec(
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
82
|
+
def exec(*files)
|
83
|
+
# files.map do | file |
|
84
|
+
# Dir.glob file
|
85
|
+
# end.flatten
|
86
|
+
|
87
|
+
files.each do | file |
|
88
|
+
implementor = find_implementor(file) # || exec_options[:default_implementor]
|
89
|
+
|
90
|
+
extension = File.extname(file)
|
91
|
+
name = File.basename(file, extension)
|
92
|
+
challenge_data = {
|
93
|
+
name: name,
|
94
|
+
# language: extension,
|
95
|
+
source_file: File.expand_path(file, Dir.pwd)
|
96
|
+
}
|
97
|
+
challenge = implementor.build_challenge challenge_data
|
98
|
+
challenge.exec
|
99
|
+
end
|
78
100
|
end
|
79
101
|
|
80
102
|
# Registers a {Polytrix::Validator} that will be used during test
|
@@ -91,11 +113,12 @@ module Polytrix
|
|
91
113
|
end
|
92
114
|
|
93
115
|
def load_tests
|
116
|
+
manifest.build_challenges
|
94
117
|
Polytrix::RSpec.run_manifest(manifest)
|
95
118
|
end
|
96
119
|
|
97
120
|
# Runs all of the tests described in the {manifest}
|
98
|
-
def
|
121
|
+
def verify(implementors = [])
|
99
122
|
test_env = ENV['TEST_ENV_NUMBER'].to_i
|
100
123
|
rspec_options = %W[--color -f documentation -f Polytrix::RSpec::YAMLReport -o reports/test_report#{test_env}.yaml]
|
101
124
|
rspec_options.concat Polytrix.configuration.rspec_options.split if Polytrix.configuration.rspec_options
|
@@ -128,15 +151,12 @@ module Polytrix
|
|
128
151
|
yield(configuration)
|
129
152
|
end
|
130
153
|
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
merged_results.deep_merge! YAML.load(File.read(result_file))
|
138
|
-
end
|
139
|
-
YAML.dump(merged_results.to_hash)
|
154
|
+
# Returns whether or not standard output is associated with a terminal
|
155
|
+
# device (tty).
|
156
|
+
#
|
157
|
+
# @return [true,false] is there a tty?
|
158
|
+
def tty?
|
159
|
+
$stdout.tty?
|
140
160
|
end
|
141
161
|
|
142
162
|
protected
|
@@ -149,7 +169,7 @@ module Polytrix
|
|
149
169
|
sdk_dir = File.absolute_path(sdk)
|
150
170
|
implementors.find { |i| File.absolute_path(i.basedir) == sdk_dir } || configuration.implementor(sdk_dir)
|
151
171
|
else
|
152
|
-
implementor = implementors.find { |i| i.name == sdk }
|
172
|
+
implementor = implementors.find { |i| i.name.to_s.downcase == sdk.to_s.downcase }
|
153
173
|
fail ArgumentError, "SDK #{sdk} not found" if implementor.nil?
|
154
174
|
implementor
|
155
175
|
end
|
@@ -157,3 +177,5 @@ module Polytrix
|
|
157
177
|
end
|
158
178
|
end
|
159
179
|
end
|
180
|
+
|
181
|
+
Polytrix.mutex = Mutex.new
|
data/polytrix.gemspec
CHANGED
@@ -19,10 +19,12 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "thor", "~> 0.19"
|
22
|
-
spec.add_dependency "
|
22
|
+
spec.add_dependency "logging", "~> 1.8"
|
23
|
+
spec.add_dependency "mixlib-shellout", "~> 1.3" # Used for MRI
|
24
|
+
spec.add_dependency "buff-shell_out", "~> 0.1" # Used for JRuby
|
23
25
|
spec.add_dependency "middleware", "~> 0.1"
|
24
26
|
spec.add_dependency "rspec", "~> 2.99"
|
25
|
-
spec.add_dependency "hashie", "~>
|
27
|
+
spec.add_dependency "hashie", "~> 3.0"
|
26
28
|
spec.add_dependency "padrino-helpers", "~> 0.12"
|
27
29
|
spec.add_development_dependency "bundler", "~> 1.5"
|
28
30
|
spec.add_development_dependency "rake"
|
data/polytrix.rb
CHANGED
@@ -3,12 +3,5 @@
|
|
3
3
|
# This example shows the default behavior of `Polytrix#bootstrap`
|
4
4
|
require 'polytrix'
|
5
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
6
|
# Snippet: bootstrap
|
14
7
|
Polytrix.bootstrap
|
data/samples/polytrix.rb
CHANGED
@@ -1,14 +1,5 @@
|
|
1
1
|
require 'polytrix'
|
2
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
3
|
RSpec.configure do |c|
|
13
4
|
c.expose_current_running_example_as :example
|
14
5
|
end
|
@@ -1,4 +1,15 @@
|
|
1
1
|
---
|
2
|
+
implementors:
|
3
|
+
ruby:
|
4
|
+
language: 'ruby'
|
5
|
+
basedir: 'sdks/ruby'
|
6
|
+
java:
|
7
|
+
language: 'java'
|
8
|
+
basedir: 'sdks/java'
|
9
|
+
python:
|
10
|
+
language: 'python'
|
11
|
+
basedir: 'sdks/python'
|
12
|
+
|
2
13
|
global_env: # global_env defines input available for all scenarios
|
3
14
|
LOCALE: <%= ENV['LANG'] %> # templating is allowed
|
4
15
|
suites:
|
data/samples/polytrix_cli.sh
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env bash -e
|
2
2
|
bundle exec polytrix bootstrap
|
3
3
|
bundle exec polytrix exec sdks/ruby/challenges/*.rb --code2doc --target-dir=docs/ruby/
|
4
|
-
bundle exec polytrix test
|
4
|
+
# bundle exec polytrix test
|
5
5
|
bundle exec polytrix report summary
|
6
6
|
bundle exec polytrix report summary --format=markdown
|
7
7
|
bundle exec polytrix report summary --format=yaml
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'hashie/mash'
|
2
|
+
|
3
|
+
# Fabricates test manifests (.polytrix.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(:implementor, from: Polytrix::Implementor) do
|
12
|
+
initialize_with { @_klass.new to_hash } # Hash based initialization
|
13
|
+
language { LANGUAGES.sample }
|
14
|
+
name do |attr|
|
15
|
+
"my_#{attr[:language]}_project"
|
16
|
+
end
|
17
|
+
basedir do |attr|
|
18
|
+
"sdks/#{attr[:name]}"
|
19
|
+
end
|
20
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'hashie/mash'
|
2
2
|
|
3
|
-
# Fabricates test manifests (.
|
3
|
+
# Fabricates test manifests (.polytrix.yml files)
|
4
4
|
LANGUAGES = %w(java ruby python nodejs c# golang php)
|
5
5
|
SAMPLE_NAMES = [
|
6
6
|
'hello world',
|
@@ -12,6 +12,9 @@ Fabricator(:manifest, from: Polytrix::Manifest) do
|
|
12
12
|
initialize_with { @_klass.new to_hash } # Hash based initialization
|
13
13
|
transient suite_count: 3
|
14
14
|
transient samples_per_suite: 3
|
15
|
+
implementors do
|
16
|
+
Fabricate(:implementor)
|
17
|
+
end
|
15
18
|
global_env do
|
16
19
|
{
|
17
20
|
VAR1: 1,
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module Polytrix
|
2
2
|
describe ChallengeRunner do
|
3
3
|
subject(:runner) { ChallengeRunner.create_runner }
|
4
|
+
let(:implementor) { Fabricate(:implementor) }
|
4
5
|
let(:challenge) do
|
5
|
-
Fabricate(:challenge, name: 'factorial', source_file: 'spec/fixtures/factorial.py', basedir: 'spec/fixtures')
|
6
|
+
Fabricate(:challenge, name: 'factorial', source_file: 'spec/fixtures/factorial.py', basedir: 'spec/fixtures', implementor: implementor)
|
6
7
|
end
|
7
8
|
|
8
9
|
describe '#run_challenge' do
|
9
10
|
it 'executes a challenge' do
|
10
|
-
expect(runner.run_challenge challenge).to be_an_instance_of
|
11
|
+
expect(runner.run_challenge challenge).to be_an_instance_of Result
|
11
12
|
end
|
12
13
|
end
|
13
14
|
end
|
@@ -5,14 +5,15 @@ module Polytrix
|
|
5
5
|
implementor.build_challenge name: 'factorial', vars: {}
|
6
6
|
end
|
7
7
|
|
8
|
-
describe '#
|
8
|
+
describe '#exec' do
|
9
9
|
it 'executes the challenge and returns itself' do
|
10
|
-
expect(challenge.
|
11
|
-
expect(challenge.
|
10
|
+
expect(challenge.exec).to be_an_instance_of Challenge
|
11
|
+
expect(challenge.exec).to eq(challenge)
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'stores the result' do
|
15
|
-
|
15
|
+
result = challenge.exec[:result]
|
16
|
+
expect(result).to be_an_instance_of Result
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
data/spec/polytrix/cli_spec.rb
CHANGED
@@ -2,36 +2,33 @@ require 'spec_helper'
|
|
2
2
|
require 'polytrix/cli'
|
3
3
|
|
4
4
|
module Polytrix
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
5
|
+
describe CLI do
|
6
|
+
let(:kernel) { double(:kernel) }
|
7
|
+
subject { ThorSpy.on(described_class, kernel) }
|
8
|
+
describe 'bootstrap' do
|
9
|
+
context 'with no args' do
|
10
|
+
it 'calls bootstrap on each implementor' do
|
11
|
+
expect(kernel).to receive(:exit).with(0)
|
12
|
+
# TODO: Any way to test each implementor is called? We can't use
|
13
|
+
# `Polytrix.implementors` because it will be reloaded.
|
14
|
+
subject.bootstrap
|
16
15
|
end
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
expect(@implementor).to receive(:bootstrap)
|
25
|
-
expect(kernel).to receive(:exit).with(0)
|
26
|
-
expect(subject.stderr.string).to eq('')
|
27
|
-
subject.bootstrap('test')
|
28
|
-
end
|
18
|
+
context 'with an existing SDK' do
|
19
|
+
xit 'calls bootstrap on the SDK' do
|
20
|
+
# expect(@implementor).to receive(:bootstrap)
|
21
|
+
expect(kernel).to receive(:exit).with(0)
|
22
|
+
expect(subject.stderr.string).to eq('')
|
23
|
+
subject.bootstrap('test')
|
29
24
|
end
|
25
|
+
end
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
27
|
+
context 'with an non-existant SDK' do
|
28
|
+
it 'fails' do
|
29
|
+
expect(kernel).to receive(:exit).with(1)
|
30
|
+
subject.bootstrap('missing')
|
31
|
+
expect(subject.stdout.string).to include('No scenarios for regex')
|
35
32
|
end
|
36
33
|
end
|
37
34
|
end
|