polytrix 0.0.1 → 0.1.0.pre
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 +2 -2
- data/.rspec +1 -6
- data/.rubocop-todo.yml +19 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +11 -0
- data/Gemfile +0 -16
- data/README.md +119 -28
- data/Rakefile +18 -123
- data/bin/polytrix +5 -0
- data/doc-src/_markdown.md +5 -0
- data/doc-src/default_bootstrap.md +13 -0
- data/docs/influences.md +28 -0
- data/docs/samples/code2doc/java/HelloWorld.md +13 -0
- data/docs/samples/code2doc/java/Quine.md +33 -0
- data/docs/samples/code2doc/python/hello_world.md +3 -0
- data/docs/samples/code2doc/python/quine.md +4 -0
- data/docs/samples/code2doc/ruby/hello_world.md +7 -0
- data/features/execution.feature +67 -0
- data/features/fixtures/configs/empty.yml +12 -0
- data/features/fixtures/configs/hello_world.yml +10 -0
- data/features/fixtures/spec/polytrix_merge.rb +5 -0
- data/features/fixtures/spec/polytrix_spec.rb +10 -0
- data/features/reporting.feature +140 -0
- data/features/step_definitions/sdk_steps.rb +12 -0
- data/features/support/env.rb +8 -0
- data/lib/polytrix/challenge.rb +20 -7
- data/lib/polytrix/challenge_runner.rb +9 -44
- data/lib/polytrix/cli/add.rb +67 -0
- data/lib/polytrix/cli/report.rb +88 -0
- data/lib/polytrix/cli/reports/hash_reporter.rb +30 -0
- data/lib/polytrix/cli/reports/json_reporter.rb +14 -0
- data/lib/polytrix/cli/reports/markdown_reporter.rb +23 -0
- data/lib/polytrix/cli/reports/yaml_reporter.rb +14 -0
- data/lib/polytrix/cli.rb +158 -0
- data/lib/polytrix/configuration.rb +65 -4
- data/lib/polytrix/core/file_system_helper.rb +75 -0
- data/lib/polytrix/core/implementor.rb +31 -3
- data/lib/polytrix/documentation/code_segmenter.rb +168 -0
- data/lib/polytrix/documentation/comment_styles.rb +87 -0
- data/lib/polytrix/documentation/helpers/code_helper.rb +85 -0
- data/lib/polytrix/documentation/view_helper.rb +21 -0
- data/lib/polytrix/documentation_generator.rb +59 -10
- data/lib/polytrix/executor.rb +89 -0
- data/lib/polytrix/logger.rb +17 -0
- data/lib/polytrix/manifest.rb +64 -7
- data/lib/polytrix/result.rb +16 -2
- data/lib/polytrix/rspec/documentation_formatter.rb +41 -16
- data/lib/polytrix/rspec/yaml_report.rb +51 -0
- data/lib/polytrix/rspec.rb +32 -53
- data/lib/polytrix/runners/middleware/feature_executor.rb +4 -3
- data/lib/polytrix/runners/middleware/setup_env_vars.rb +6 -4
- data/lib/polytrix/validation.rb +20 -0
- data/lib/polytrix/validations.rb +23 -0
- data/lib/polytrix/validator.rb +20 -0
- data/lib/polytrix/validator_registry.rb +34 -0
- data/lib/polytrix/version.rb +1 -1
- data/lib/polytrix.rb +125 -22
- data/polytrix.gemspec +7 -2
- data/polytrix.rb +6 -0
- data/polytrix_tests.yml +20 -0
- data/resources/code_sample.tt +2 -0
- data/samples/.gitignore +2 -0
- data/samples/_markdown.md +5 -0
- data/samples/default_bootstrap.rb +14 -0
- data/samples/polytrix.rb +28 -0
- data/samples/polytrix_cli.sh +7 -0
- data/samples/polytrix_tests.yml +10 -0
- data/{sdks/fog → samples}/scripts/bootstrap +0 -2
- data/samples/scripts/wrapper +7 -0
- data/samples/sdks/custom/polytrix.yml +2 -0
- data/samples/sdks/java/.gitignore +2 -0
- data/samples/sdks/java/build.gradle +14 -0
- data/samples/sdks/java/challenges/HelloWorld.java +10 -0
- data/samples/sdks/java/challenges/Quine.java +31 -0
- data/samples/sdks/java/code_sample.tt +11 -0
- data/samples/sdks/java/scripts/bootstrap +2 -0
- data/samples/sdks/java/scripts/wrapper +8 -0
- data/samples/sdks/python/challenges/hello_world.py +2 -0
- data/samples/sdks/python/challenges/quine.py +2 -0
- data/{sdks/pkgcloud → samples/sdks/python}/scripts/wrapper +1 -1
- data/samples/sdks/ruby/challenges/hello_world.rb +4 -0
- data/scripts/bootstrap +1 -9
- data/scripts/wrapper +7 -0
- data/spec/fabricators/challenge_fabricator.rb +17 -0
- data/spec/fabricators/manifest_fabricator.rb +50 -0
- data/spec/fabricators/validator_fabricator.rb +12 -0
- data/spec/fixtures/{polytrix.yml → polytrix_tests.yml} +0 -0
- data/spec/fixtures/src-doc/_scenario.md.erb +1 -0
- data/spec/polytrix/challenge_runner_spec.rb +3 -3
- data/spec/polytrix/challenge_spec.rb +3 -4
- data/spec/polytrix/cli_spec.rb +39 -0
- data/spec/polytrix/configuration_spec.rb +45 -1
- data/spec/polytrix/documentation/helpers/code_helper_spec.rb +120 -0
- data/spec/polytrix/documentation_generator_spec.rb +41 -20
- data/spec/polytrix/file_finder_spec.rb +4 -3
- data/spec/polytrix/implementor_spec.rb +33 -0
- data/spec/polytrix/manifest_spec.rb +32 -14
- data/spec/polytrix/middleware/feature_executor_spec.rb +1 -1
- data/spec/polytrix/result_spec.rb +49 -0
- data/spec/polytrix/validations_spec.rb +16 -0
- data/spec/polytrix/validator_registry_spec.rb +39 -0
- data/spec/polytrix/validator_spec.rb +63 -0
- data/spec/polytrix_spec.rb +33 -7
- data/spec/spec_helper.rb +14 -1
- data/spec/thor_spy.rb +64 -0
- metadata +177 -160
- data/.rspec_parallel +0 -10
- data/Vagrantfile +0 -41
- data/features/0_identity_spec.rb +0 -40
- data/features/1_cloud_files_spec.rb +0 -48
- data/features/2_servers_spec.rb +0 -19
- data/features/features_helper.rb +0 -46
- data/features/helpers/cloudfiles_helper.rb +0 -31
- data/features/helpers/pacto_helper.rb +0 -33
- data/features/helpers/teardown_helper.rb +0 -49
- data/features/pacto/extensions/loaders/api_blueprint_loader.rb +0 -63
- data/features/pacto/extensions/loaders/simple_loader.rb +0 -55
- data/features/pacto/extensions/loaders/yaml_or_json_loader.rb +0 -17
- data/features/pacto/extensions/matchers.rb +0 -38
- data/features/phase2/feature_coverage_report.rb +0 -109
- data/features/phase2/run_all_features.rb +0 -14
- data/features/static_site/fixtures/index.html +0 -6
- data/lib/polytrix/challenge_builder.rb +0 -16
- data/lib/polytrix/core/file_finder.rb +0 -43
- data/lib/polytrix/core/result_tracker.rb +0 -25
- data/lib/polytrix/runners/middleware/pacto.rb +0 -59
- data/packer/.gitignore +0 -3
- data/packer/Berksfile +0 -15
- data/packer/Gemfile +0 -5
- data/packer/Vagrantfile +0 -128
- data/packer/cookbooks/drg/metadata.rb +0 -27
- data/packer/cookbooks/drg/recipes/admins.rb +0 -22
- data/packer/cookbooks/drg/recipes/default.rb +0 -9
- data/packer/cookbooks/drg/recipes/dotnet.rb +0 -4
- data/packer/cookbooks/drg/recipes/golang.rb +0 -4
- data/packer/cookbooks/drg/recipes/java.rb +0 -5
- data/packer/cookbooks/drg/recipes/php.rb +0 -10
- data/packer/cookbooks/drg/recipes/ruby.rb +0 -29
- data/packer/cookbooks/drg/recipes/system.rb +0 -13
- data/packer/create_box.sh +0 -10
- data/packer/http/preseed.cfg +0 -87
- data/packer/packer.json +0 -91
- data/packer/scripts/root_setup.sh +0 -37
- data/packer/scripts/setup.sh +0 -32
- data/pacto/config/pacto_server.rb +0 -40
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/extensions.json +0 -64
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/flavors/id.json +0 -100
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/images/id.json +0 -176
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers/id.json +0 -189
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers.json +0 -63
- data/pacto/contracts/dns.api.rackspacecloud.com/v1.0/_tenant_id/domains.json +0 -62
- data/pacto/contracts/identity.api.rackspacecloud.com/v2.0/tokens.json +0 -192
- data/pacto/contracts/monitoring.api.rackspacecloud.com/v1.0/_tenant_id/account.json +0 -39
- data/pacto/contracts/ord.autoscale.api.rackspacecloud.com/v1.0/_tenant_id/groups.json +0 -38
- data/pacto/contracts/ord.blockstorage.api.rackspacecloud.com/v1/_tenant_id/volumes.json +0 -30
- data/pacto/contracts/ord.databases.api.rackspacecloud.com/v1.0/_tenant_id/instances.json +0 -30
- data/pacto/contracts/ord.loadbalancers.api.rackspacecloud.com/v1.0/_tenant_id/loadbalancers.json +0 -114
- data/pacto/contracts/ord.queues.api.rackspacecloud.com/v1/_tenant_id/queues.json +0 -13
- data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/os-networksv2.json +0 -46
- data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/servers/detail.json +0 -230
- data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account/container/object.json +0 -15
- data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account.json +0 -43
- data/pacto/contracts/storage101.ord1.clouddrive.com/v1/_mosso_id.json +0 -44
- data/pacto/pacto_server.rb +0 -100
- data/pacto/rackspace_uri_map.yaml +0 -229
- data/scripts/cibuild +0 -4
- data/sdks/fog/.gitignore +0 -1
- data/sdks/fog/Gemfile +0 -5
- data/sdks/fog/challenges/all_connections.rb +0 -45
- data/sdks/fog/challenges/authenticate_token.rb +0 -15
- data/sdks/fog/challenges/cdn_enable_container.rb +0 -20
- data/sdks/fog/challenges/create_a_container.rb +0 -17
- data/sdks/fog/challenges/create_server.rb +0 -36
- data/sdks/fog/challenges/get_object_metadata.rb +0 -13
- data/sdks/fog/challenges/list_containers.rb +0 -10
- data/sdks/fog/challenges/provision_scalable_webapp.rb +0 -30
- data/sdks/fog/challenges/upload_folder.rb +0 -25
- data/sdks/fog/scripts/bootstrap.ps1 +0 -1
- data/sdks/fog/scripts/wrapper +0 -2
- data/sdks/fog/scripts/wrapper.ps1 +0 -1
- data/sdks/gophercloud/.gitignore +0 -2
- data/sdks/gophercloud/challenges/authenticate_token.go +0 -23
- data/sdks/gophercloud/scripts/bootstrap +0 -6
- data/sdks/gophercloud/scripts/wrapper +0 -10
- data/sdks/jclouds/.gitignore +0 -1
- data/sdks/jclouds/challenges/AuthenticateToken.java +0 -115
- data/sdks/jclouds/pom.xml +0 -34
- data/sdks/jclouds/scripts/bootstrap +0 -3
- data/sdks/jclouds/scripts/wrapper +0 -7
- data/sdks/openstack.net/.gitignore +0 -4
- data/sdks/openstack.net/.nuget/Microsoft.Build.dll +0 -0
- data/sdks/openstack.net/.nuget/NuGet.Config +0 -6
- data/sdks/openstack.net/.nuget/NuGet.exe +0 -0
- data/sdks/openstack.net/.nuget/NuGet.targets +0 -136
- data/sdks/openstack.net/Challenge.cs +0 -10
- data/sdks/openstack.net/RunChallenge.cs +0 -19
- data/sdks/openstack.net/challenges/AuthenticateToken.cs +0 -24
- data/sdks/openstack.net/challenges/Weird.cs +0 -133
- data/sdks/openstack.net/openstack.net.csproj +0 -58
- data/sdks/openstack.net/openstack.net.sln +0 -27
- data/sdks/openstack.net/openstack.net.userprefs +0 -8
- data/sdks/openstack.net/packages.config +0 -6
- data/sdks/openstack.net/scripts/bootstrap +0 -2
- data/sdks/openstack.net/scripts/bootstrap.ps1 +0 -2
- data/sdks/openstack.net/scripts/wrapper +0 -7
- data/sdks/openstack.net/scripts/wrapper.ps1 +0 -1
- data/sdks/php-opencloud/.gitignore +0 -4
- data/sdks/php-opencloud/challenges/all_connections.php +0 -64
- data/sdks/php-opencloud/challenges/authenticate_token.php +0 -14
- data/sdks/php-opencloud/challenges/create_server.php +0 -39
- data/sdks/php-opencloud/challenges/get_object_metadata.php +0 -19
- data/sdks/php-opencloud/composer.json +0 -5
- data/sdks/php-opencloud/scripts/bootstrap +0 -4
- data/sdks/php-opencloud/scripts/bootstrap.ps1 +0 -2
- data/sdks/php-opencloud/scripts/wrapper +0 -2
- data/sdks/php-opencloud/scripts/wrapper.ps1 +0 -1
- data/sdks/pkgcloud/.gitignore +0 -1
- data/sdks/pkgcloud/challenges/authenticate_token.js +0 -17
- data/sdks/pkgcloud/challenges/get_object_metadata.js +0 -18
- data/sdks/pkgcloud/scripts/bootstrap +0 -2
- data/sdks/pkgcloud/scripts/bootstrap.ps1 +0 -1
- data/sdks/pkgcloud/scripts/wrapper.ps1 +0 -1
- data/sdks/pyrax/.gitignore +0 -2
- data/sdks/pyrax/challenges/all_connections.py +0 -61
- data/sdks/pyrax/challenges/authenticate_token.py +0 -17
- data/sdks/pyrax/challenges/cdn_enable_container.py +0 -22
- data/sdks/pyrax/challenges/create_a_container.py +0 -21
- data/sdks/pyrax/challenges/create_server.py +0 -35
- data/sdks/pyrax/challenges/get_object_metadata.py +0 -17
- data/sdks/pyrax/challenges/upload_folder.py +0 -32
- data/sdks/pyrax/requirements.txt +0 -21
- data/sdks/pyrax/scripts/bootstrap +0 -9
- data/sdks/pyrax/scripts/bootstrap.ps1 +0 -7
- data/sdks/pyrax/scripts/wrapper +0 -3
- data/sdks/pyrax/scripts/wrapper.ps1 +0 -2
- data/spec/polytrix/challenge_builder_spec.rb +0 -16
- data/spec/rspec_spec.rb +0 -17
|
@@ -0,0 +1,50 @@
|
|
|
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(:manifest, from: Polytrix::Manifest) do
|
|
12
|
+
initialize_with { @_klass.new to_hash } # Hash based initialization
|
|
13
|
+
transient suite_count: 3
|
|
14
|
+
transient samples_per_suite: 3
|
|
15
|
+
global_env do
|
|
16
|
+
{
|
|
17
|
+
VAR1: 1,
|
|
18
|
+
VAR2: 2
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
suites do |attr|
|
|
22
|
+
suite_count = attr[:suite_count]
|
|
23
|
+
if suite_count
|
|
24
|
+
suites = attr[:suite_count].times.reduce({}) do |h, i|
|
|
25
|
+
name = LANGUAGES[i] ||= "suite_#{i}"
|
|
26
|
+
h[name] = Fabricate(:suite, name: name, sample_count: attr[:samples_per_suite])
|
|
27
|
+
h
|
|
28
|
+
end
|
|
29
|
+
suites
|
|
30
|
+
else
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
Fabricator(:suite, from: Hashie::Mash) do
|
|
37
|
+
initialize_with { @_klass.new to_hash } # Hash based initialization
|
|
38
|
+
transient name: LANGUAGES[0]
|
|
39
|
+
transient sample_count: 3
|
|
40
|
+
samples do |attr|
|
|
41
|
+
sample_count = attr[:sample_count]
|
|
42
|
+
if sample_count
|
|
43
|
+
attr[:sample_count].times.map do |i|
|
|
44
|
+
SAMPLE_NAMES[i] ||= "sample_#{i}"
|
|
45
|
+
end
|
|
46
|
+
else
|
|
47
|
+
nil
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'hashie/mash'
|
|
2
|
+
|
|
3
|
+
Fabricator(:validator, from: Polytrix::Validator) do
|
|
4
|
+
initialize_with do
|
|
5
|
+
callback = @_transient_attributes.delete :callback
|
|
6
|
+
scope = @_transient_attributes
|
|
7
|
+
@_klass.new(scope, &callback)
|
|
8
|
+
end # Hash based initialization
|
|
9
|
+
transient suite: LANGUAGES.sample
|
|
10
|
+
transient sample: SAMPLE_NAMES.sample
|
|
11
|
+
transient callback: Proc.new { Proc.new { |challenge| } } # rubocop:disable Proc
|
|
12
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I am a generic template that is being used for the <%= scenario %> scenario.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module Polytrix
|
|
2
2
|
describe ChallengeRunner do
|
|
3
|
-
subject(:runner) { ChallengeRunner.
|
|
3
|
+
subject(:runner) { ChallengeRunner.create_runner }
|
|
4
4
|
let(:challenge) do
|
|
5
|
-
|
|
5
|
+
Fabricate(:challenge, name: 'factorial', source_file: 'spec/fixtures/factorial.py', basedir: 'spec/fixtures')
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
describe '#run_challenge' do
|
|
@@ -11,4 +11,4 @@ module Polytrix
|
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
|
-
end
|
|
14
|
+
end
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
module Polytrix
|
|
2
2
|
describe Challenge do
|
|
3
3
|
subject(:challenge) do
|
|
4
|
-
implementor = Polytrix::Implementor.new :
|
|
5
|
-
|
|
6
|
-
builder.build :name => 'factorial', :vars => {}
|
|
4
|
+
implementor = Polytrix::Implementor.new name: 'some_sdk', basedir: 'spec/fixtures'
|
|
5
|
+
implementor.build_challenge name: 'factorial', vars: {}
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
describe '#run' do
|
|
@@ -17,4 +16,4 @@ module Polytrix
|
|
|
17
16
|
end
|
|
18
17
|
end
|
|
19
18
|
end
|
|
20
|
-
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'polytrix/cli'
|
|
3
|
+
|
|
4
|
+
module Polytrix
|
|
5
|
+
module CLI
|
|
6
|
+
describe Main do
|
|
7
|
+
let(:kernel) { double(:kernel) }
|
|
8
|
+
subject { ThorSpy.on(described_class, kernel) }
|
|
9
|
+
describe 'bootstrap' do
|
|
10
|
+
context 'with no args' do
|
|
11
|
+
it 'calls Polytrix.bootstrap' do
|
|
12
|
+
expect(kernel).to receive(:exit).with(0)
|
|
13
|
+
expect(Polytrix).to receive(:bootstrap)
|
|
14
|
+
subject.bootstrap
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'with an existing SDK' do
|
|
19
|
+
before do
|
|
20
|
+
@implementor = Polytrix.configuration.implementor name: 'test', basedir: '.'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'calls bootstrap on the SDK' do
|
|
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
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'with an non-existant SDK' do
|
|
32
|
+
it 'fails' do
|
|
33
|
+
expect { subject.bootstrap('missing') }.to raise_error(SystemExit, 'SDK missing not found')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -3,8 +3,52 @@ module Polytrix
|
|
|
3
3
|
subject(:configuration) { Configuration.new }
|
|
4
4
|
|
|
5
5
|
it 'creates a logger' do
|
|
6
|
-
expect(configuration.logger).to be_kind_of Logger
|
|
6
|
+
expect(configuration.logger).to be_kind_of ::Logger
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
describe '.test_manifest' do
|
|
10
|
+
it 'parses the YAML file and registers the manifest' do
|
|
11
|
+
original_manifest = configuration.test_manifest
|
|
12
|
+
configuration.test_manifest = 'spec/fixtures/polytrix_tests.yml'
|
|
13
|
+
new_manifest = configuration.test_manifest
|
|
14
|
+
expect(original_manifest).to_not eq(new_manifest)
|
|
15
|
+
expect(new_manifest).to(be_an_instance_of(Polytrix::Manifest))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe '.implementor' do
|
|
20
|
+
context 'argument is a Hash' do
|
|
21
|
+
it 'creates and registers Implementors' do
|
|
22
|
+
# This'd be a bit nicer w/ rspec 3...
|
|
23
|
+
expect do
|
|
24
|
+
configuration.implementor name: 'test', basedir: '.'
|
|
25
|
+
end.to change {
|
|
26
|
+
configuration.implementors
|
|
27
|
+
}.from(be_empty).to be_an_instance_of(Array)
|
|
28
|
+
|
|
29
|
+
expect(configuration.implementors.first).to be_an_instance_of Polytrix::Implementor
|
|
30
|
+
expect(configuration.implementors.first.name).to eq('test')
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
context 'argument is a String' do
|
|
34
|
+
context 'directory exists' do
|
|
35
|
+
context 'polytrix.yml does not exist' do
|
|
36
|
+
it 'builds an implementor with default settings' do
|
|
37
|
+
implementor = configuration.implementor('samples/sdks/ruby')
|
|
38
|
+
expect(implementor).to be_an_instance_of(Polytrix::Implementor)
|
|
39
|
+
expect(implementor.name).to eq('ruby') # directory name
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'polytrix_tests.yml exists' do
|
|
44
|
+
it 'loads settings from polytrix.yml' do
|
|
45
|
+
implementor = configuration.implementor('samples/sdks/custom')
|
|
46
|
+
expect(implementor).to be_an_instance_of(Polytrix::Implementor)
|
|
47
|
+
expect(implementor.name).to eq('My Custom project')
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
9
53
|
end
|
|
10
54
|
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
module Polytrix
|
|
2
|
+
module Documentation
|
|
3
|
+
module Helpers
|
|
4
|
+
describe CodeHelper do
|
|
5
|
+
let(:challenge) { Fabricate(:challenge, name: 'test', source_file: @source_file) }
|
|
6
|
+
let(:source) do
|
|
7
|
+
%q[
|
|
8
|
+
# This snippet should not be in the output.
|
|
9
|
+
puts "Random: #{rand}"
|
|
10
|
+
|
|
11
|
+
# Snippet: Hello, world!
|
|
12
|
+
puts 'Hello, world!'
|
|
13
|
+
|
|
14
|
+
# Nor should this snippet
|
|
15
|
+
puts 'Done'
|
|
16
|
+
]
|
|
17
|
+
end
|
|
18
|
+
let(:expected_snippet) do
|
|
19
|
+
%q[
|
|
20
|
+
puts 'Hello, world!'
|
|
21
|
+
]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
around do | example |
|
|
25
|
+
with_files(source: source) do | files |
|
|
26
|
+
@source_file = files.first
|
|
27
|
+
example.run
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '#snippet_after' do
|
|
32
|
+
it 'returns the code block after the match (string)' do
|
|
33
|
+
snippet = challenge.snippet_after 'Snippet: Hello, world!'
|
|
34
|
+
expect(snippet.strip).to eq(expected_snippet.strip)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'returns the code block after the match (regex)' do
|
|
38
|
+
snippet = challenge.snippet_after(/Snippet: .*/)
|
|
39
|
+
expect(snippet.strip).to eq(expected_snippet.strip)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'returns nothing if no match is found' do
|
|
43
|
+
snippet = challenge.snippet_after 'Nothing matches'
|
|
44
|
+
expect(snippet).to be_empty
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe '#snippet_between' do
|
|
49
|
+
# Yes, whitespace doesn't work very well w/ snippet_between
|
|
50
|
+
let(:expected_snippet) do
|
|
51
|
+
%q[
|
|
52
|
+
puts "Random: #{rand}"
|
|
53
|
+
# Snippet: Hello, world!
|
|
54
|
+
puts 'Hello, world!'
|
|
55
|
+
]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'inserts all code blocks between the matching regexes' do
|
|
59
|
+
snippet = challenge.snippet_between 'This snippet should not be in the output', 'Nor should this snippet'
|
|
60
|
+
expect(snippet.strip).to eq(expected_snippet.strip)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'inserts nothing unless both matches are found' do
|
|
64
|
+
# Neither match
|
|
65
|
+
snippet = challenge.snippet_between 'foo', 'bar'
|
|
66
|
+
expect(snippet.strip).to be_empty
|
|
67
|
+
|
|
68
|
+
# First matches
|
|
69
|
+
snippet = challenge.snippet_between 'This snippet should not be in the output', 'foo'
|
|
70
|
+
expect(snippet.strip).to be_empty
|
|
71
|
+
|
|
72
|
+
# Last matches
|
|
73
|
+
snippet = challenge.snippet_between 'foo', 'Nor should this snippet'
|
|
74
|
+
expect(snippet.strip).to be_empty
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe '#code_block' do
|
|
80
|
+
it 'generates markdown code blocks by default' do
|
|
81
|
+
expected = "```ruby\n" + source + "\n```\n"
|
|
82
|
+
code_block = challenge.code_block(challenge.source, 'ruby')
|
|
83
|
+
expect(code_block).to eq(expected)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'generates rst for format :rst' do
|
|
87
|
+
indented_source = source.lines.map do|line|
|
|
88
|
+
" #{line}"
|
|
89
|
+
end.join("\n")
|
|
90
|
+
expected = ".. code-block:: ruby\n" + indented_source + "\n"
|
|
91
|
+
code_block = challenge.code_block(challenge.source, 'ruby', format: :rst)
|
|
92
|
+
expect(code_block).to eq(expected)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def generate_doc_for(template_file, source_file)
|
|
97
|
+
doc_gen = DocumentationGenerator.new(template_file, 'testing')
|
|
98
|
+
challenge = Fabricate(:challenge, name: 'test', source_file: source_file)
|
|
99
|
+
doc_gen.process(challenge)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def with_files(files)
|
|
103
|
+
tmpfiles = []
|
|
104
|
+
begin
|
|
105
|
+
files.each do |k, v|
|
|
106
|
+
file = Tempfile.new(k.to_s)
|
|
107
|
+
file.write(v)
|
|
108
|
+
file.close
|
|
109
|
+
tmpfiles << file
|
|
110
|
+
end
|
|
111
|
+
yield tmpfiles.map(&:path)
|
|
112
|
+
ensure
|
|
113
|
+
tmpfiles.each { |tmpfile| tmpfile.unlink }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -1,35 +1,56 @@
|
|
|
1
1
|
module Polytrix
|
|
2
2
|
describe DocumentationGenerator do
|
|
3
|
-
let(:
|
|
3
|
+
let(:scenario_name) { 'Quine' }
|
|
4
|
+
# let(:search_path) { 'spec/fixtures/src-doc' }
|
|
4
5
|
let(:bound_data) { double }
|
|
5
|
-
subject(:generator) { DocumentationGenerator.new(search_path) }
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
describe 'process' do
|
|
8
|
+
let(:generated_doc) { generator.process bound_data }
|
|
9
|
+
|
|
10
|
+
context 'when template is readable' do
|
|
11
|
+
subject(:generator) { DocumentationGenerator.new('spec/fixtures/src-doc/quine.md.erb', scenario_name) }
|
|
12
|
+
|
|
13
|
+
it 'processes the template' do
|
|
14
|
+
expect(generated_doc).to include 'Examples for Quine scenario:'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'when template is not readable' do
|
|
19
|
+
subject(:generator) { DocumentationGenerator.new('non_existant_file.md', scenario_name) }
|
|
20
|
+
it 'processes the template' do
|
|
21
|
+
expect(generated_doc).to be_nil
|
|
22
|
+
end
|
|
10
23
|
end
|
|
11
24
|
end
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
describe 'code2doc' do
|
|
27
|
+
subject(:generator) { DocumentationGenerator.new }
|
|
14
28
|
|
|
15
|
-
let(:
|
|
29
|
+
let(:source_code) do
|
|
30
|
+
<<-eos.gsub(/^( |\t)+/, '')
|
|
31
|
+
#!/usr/bin/env ruby
|
|
16
32
|
|
|
17
|
-
|
|
18
|
-
|
|
33
|
+
# Comments are documentation
|
|
34
|
+
puts 'And this is a code block'
|
|
35
|
+
eos
|
|
19
36
|
end
|
|
20
37
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
fail 'This test requires implementors' unless Polytrix.implementors
|
|
38
|
+
let(:source_file) do
|
|
39
|
+
file = Tempfile.new(['source', '.rb'])
|
|
40
|
+
file.write source_code
|
|
41
|
+
file.close
|
|
42
|
+
file.path
|
|
43
|
+
end
|
|
28
44
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
45
|
+
it 'converts source code to documentation' do
|
|
46
|
+
expect(generator.code2doc(source_file, 'ruby')).to eq(
|
|
47
|
+
<<-eos.gsub(/^( |\t)+/, '')
|
|
48
|
+
Comments are documentation
|
|
49
|
+
```ruby
|
|
50
|
+
puts 'And this is a code block'
|
|
51
|
+
```
|
|
52
|
+
eos
|
|
53
|
+
)
|
|
33
54
|
end
|
|
34
55
|
end
|
|
35
56
|
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module Polytrix
|
|
2
2
|
module Core
|
|
3
|
-
describe
|
|
3
|
+
describe FileSystemHelper do
|
|
4
4
|
subject(:finder) do
|
|
5
|
-
Object.new.extend(Polytrix::Core::
|
|
5
|
+
Object.new.extend(Polytrix::Core::FileSystemHelper)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
it 'finds files within the search path' do
|
|
@@ -12,10 +12,11 @@ module Polytrix
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it 'raises FileNotFound except if a file is not found' do
|
|
15
|
-
expect { finder.find_file 'spec/fixtures/src-doc', 'quinez' }.to raise_error
|
|
15
|
+
expect { finder.find_file 'spec/fixtures/src-doc', 'quinez' }.to raise_error FileSystemHelper::FileNotFound
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
private
|
|
19
|
+
|
|
19
20
|
def path(p)
|
|
20
21
|
Pathname.new p
|
|
21
22
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Polytrix
|
|
4
|
+
describe Implementor do
|
|
5
|
+
subject(:implementor) { described_class.new(name: 'test', language: 'ruby', basedir: 'sdks/test') }
|
|
6
|
+
let(:executor) { double('executor') }
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
subject.executor = executor
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe '#bootstrap' do
|
|
13
|
+
it 'executes script/bootstrap' do
|
|
14
|
+
expect(executor).to receive(:execute).with('./scripts/bootstrap', cwd: Pathname.new(File.absolute_path('sdks/test')), prefix: 'test')
|
|
15
|
+
implementor.bootstrap
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe '#build_challenge' do
|
|
20
|
+
subject(:implementor) { Polytrix::Implementor.new name: 'some_sdk', basedir: File.absolute_path('spec/fixtures') }
|
|
21
|
+
let(:challenge) { Fabricate(:challenge, name: 'factorial', vars: {}) }
|
|
22
|
+
|
|
23
|
+
it 'builds a Challenge' do
|
|
24
|
+
expect(challenge).to be_an_instance_of Polytrix::Challenge
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'finds the source' do
|
|
28
|
+
expected_file = Pathname.new 'spec/fixtures/factorial.py'
|
|
29
|
+
expect(challenge.source_file).to eq(expected_file)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,26 +1,44 @@
|
|
|
1
1
|
module Polytrix
|
|
2
|
-
|
|
3
|
-
describe
|
|
4
|
-
|
|
5
|
-
subject(:manifest) { described_class.from_yaml 'spec/fixtures/polytrix.yml' }
|
|
2
|
+
describe Manifest do
|
|
3
|
+
describe '#from_yaml' do
|
|
4
|
+
subject(:manifest) { described_class.from_yaml 'spec/fixtures/polytrix_tests.yml' }
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
it 'initializes a manifest' do
|
|
7
|
+
expect(manifest).to be_an_instance_of Polytrix::Manifest
|
|
8
|
+
end
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
it 'processes ERB' do
|
|
11
|
+
expect(manifest.global_env['LOCALE']).to eq(ENV['LANG'])
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'parses global_env' do
|
|
15
|
+
expect(manifest.global_env).to be_an_instance_of Polytrix::Manifest::Environment
|
|
16
|
+
end
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
it 'parses suites' do
|
|
19
|
+
expect(manifest.suites).to be_an_instance_of Polytrix::Manifest::Suites
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe '#find_suite' do
|
|
23
|
+
before(:each) do
|
|
24
|
+
Polytrix.configuration.test_manifest = 'samples/polytrix_tests.yml'
|
|
25
|
+
end
|
|
26
|
+
it 'returns nil if no suite matches' do
|
|
27
|
+
suite = subject.find_suite('none')
|
|
28
|
+
expect(suite).to be_nil
|
|
17
29
|
end
|
|
18
30
|
|
|
19
|
-
it '
|
|
20
|
-
|
|
31
|
+
it 'returns the suite if one is found' do
|
|
32
|
+
suite = subject.find_suite('Katas')
|
|
33
|
+
expect(suite).to be_an_instance_of Polytrix::Manifest::Suite
|
|
21
34
|
end
|
|
22
35
|
|
|
36
|
+
it 'is not case sensitive' do
|
|
37
|
+
suite = subject.find_suite('katas')
|
|
38
|
+
expect(suite).to be_an_instance_of Polytrix::Manifest::Suite
|
|
39
|
+
end
|
|
23
40
|
end
|
|
41
|
+
|
|
24
42
|
end
|
|
25
43
|
end
|
|
26
44
|
end
|
|
@@ -19,7 +19,7 @@ module Polytrix
|
|
|
19
19
|
|
|
20
20
|
before do
|
|
21
21
|
allow(challenge_runner).to receive(:challenge_command).with(env[:env_file], Pathname.new('test.js')).and_return('some command to execute')
|
|
22
|
-
allow(challenge_runner).to receive(:run_command).with('some command to execute').and_return Polytrix::Result.new(
|
|
22
|
+
allow(challenge_runner).to receive(:run_command).with('some command to execute').and_return Polytrix::Result.new(execution_result: 'a', source_file: 'b')
|
|
23
23
|
allow(app).to receive(:call).with(env)
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Polytrix
|
|
4
|
+
describe Result do
|
|
5
|
+
describe '#status' do
|
|
6
|
+
context 'mixed pass/fail' do
|
|
7
|
+
let(:subject) do
|
|
8
|
+
Polytrix::Result.new(
|
|
9
|
+
validations: [
|
|
10
|
+
{ validated_by: 'max', result: 'passed' },
|
|
11
|
+
{ validated_by: 'polytrix', result: 'failed' }
|
|
12
|
+
]
|
|
13
|
+
).status
|
|
14
|
+
end
|
|
15
|
+
it 'reports the failed status' do
|
|
16
|
+
is_expected.to eq('failed')
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
context 'mix passed/pending/skipped' do
|
|
20
|
+
let(:subject) do
|
|
21
|
+
Polytrix::Result.new(
|
|
22
|
+
validations: [
|
|
23
|
+
{ validated_by: 'max', result: 'passed' },
|
|
24
|
+
{ validated_by: 'polytrix', result: 'pending' },
|
|
25
|
+
{ validated_by: 'john doe', result: 'skipped' }
|
|
26
|
+
]
|
|
27
|
+
).status
|
|
28
|
+
end
|
|
29
|
+
it 'reports the passed status' do
|
|
30
|
+
is_expected.to eq('passed')
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
context 'mix pending/skipped' do
|
|
34
|
+
let(:subject) do
|
|
35
|
+
Polytrix::Result.new(
|
|
36
|
+
validations: [
|
|
37
|
+
{ validated_by: 'max', result: 'pending' },
|
|
38
|
+
{ validated_by: 'polytrix', result: 'pending' },
|
|
39
|
+
{ validated_by: 'john doe', result: 'skipped' }
|
|
40
|
+
]
|
|
41
|
+
).status
|
|
42
|
+
end
|
|
43
|
+
it 'reports the pending status' do
|
|
44
|
+
is_expected.to eq('pending')
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Polytrix
|
|
4
|
+
describe Validations do
|
|
5
|
+
describe '#coerce' do
|
|
6
|
+
it 'accepts an array when built via Result' do
|
|
7
|
+
Polytrix::Result.new(
|
|
8
|
+
validations: [
|
|
9
|
+
{ validated_by: 'max', result: 'passed' },
|
|
10
|
+
{ validated_by: 'polytrix', result: 'skipped' }
|
|
11
|
+
]
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Polytrix
|
|
2
|
+
describe 'ValidatorRegistry' do
|
|
3
|
+
subject(:registry) { Polytrix::ValidatorRegistry }
|
|
4
|
+
|
|
5
|
+
describe '#register' do
|
|
6
|
+
it 'registers a validator' do
|
|
7
|
+
callback = proc do |challenge|
|
|
8
|
+
expect(challenge[:result].execution_result.exitstatus).to eq(0)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
expect(registry.validators).to be_empty
|
|
12
|
+
registry.register suite: 'java', sample: 'hello world', &callback
|
|
13
|
+
validator = registry.validators.first
|
|
14
|
+
expect(validator.suite).to eql('java')
|
|
15
|
+
expect(validator.sample).to eql('hello world')
|
|
16
|
+
expect(validator.instance_variable_get('@callback')).to eql(callback)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#validators_for' do
|
|
21
|
+
let(:java_hello_world_validator) { Fabricate(:validator, suite: 'java', sample: 'hello world') }
|
|
22
|
+
let(:java_validator) { Fabricate(:validator, suite: 'java', sample: //) }
|
|
23
|
+
let(:ruby_validator) { Fabricate(:validator, suite: 'ruby') }
|
|
24
|
+
|
|
25
|
+
before do
|
|
26
|
+
registry.register(java_hello_world_validator)
|
|
27
|
+
registry.register(java_validator)
|
|
28
|
+
registry.register(ruby_validator)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'returns registered validators that match the scope of the challenge' do
|
|
32
|
+
challenge = Fabricate(:challenge, suite: 'java', name: 'hello world')
|
|
33
|
+
validators = registry.validators_for challenge
|
|
34
|
+
expect(validators).to include(java_hello_world_validator, java_validator)
|
|
35
|
+
expect(validators).to_not include(ruby_validator)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|