rocksteady 0.8.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.
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ v0.8.0. Initial release. Basic functionality and tests.
data/Manifest ADDED
@@ -0,0 +1,13 @@
1
+ CHANGELOG
2
+ lib/rocksteady/corpus.rb
3
+ lib/rocksteady/helpers.rb
4
+ lib/rocksteady/output.rb
5
+ lib/rocksteady/scenario.rb
6
+ lib/rocksteady/session.rb
7
+ lib/rocksteady/tasks.rb
8
+ lib/rocksteady/version.rb
9
+ lib/rocksteady.rb
10
+ Manifest
11
+ Rakefile
12
+ README.rdoc
13
+ test/rocksteady_test.rb
data/README.rdoc ADDED
@@ -0,0 +1,143 @@
1
+ = Rocksteady
2
+
3
+ Often you need to test bits of code you write with bits of code other people write, across varying revisions. This is tedious, requiring a lot of custom work and infrastructure, so you probably don't do it enough. I know I don't, and it's a bad habit.
4
+
5
+ Rocksteady is meant to ease the process of switching out different versions of inter-dependent code, providing you with a simple _scenario_ metaphor to write build and test code within. It's test framework agnostic (it just uses exit codes), and extremely flexible.
6
+
7
+ Below you can read an example of testing different versions of Rails against different versions of a plugin; more in-depth examples can be found on the wiki (http://github.com/bruce/rocksteady/wikis/examples).
8
+
9
+ <i>Please let me know how you're using Rocksteady; it's nice to have feedback</i>.
10
+
11
+ Bruce Williams (http://codefluency.com)
12
+ http://github.com/bruce
13
+
14
+
15
+ == Installation
16
+
17
+ Get it from RubyForge (once released):
18
+ sudo gem install rocksteady
19
+
20
+ === Dependencies
21
+
22
+ * rake
23
+ sudo gem install rake
24
+ * ruport
25
+ sudo gem install ruport
26
+ * mojombo-grit >= 0.8.0
27
+ sudo gem install mojombo-grit -s http://gems.github.com
28
+ * (git in your PATH)
29
+
30
+ == Defining Scenarios
31
+
32
+ Create a new directory, and toss a <tt>Rakefile</tt> in it. Make it look like this:
33
+
34
+ require 'rubygems'
35
+ require 'rocksteady'
36
+
37
+ Now, point it at the git repos that are holding the code you'd like to test. You could <tt>clone</tt> the repos somewhere in this directory, if you'd like. For this example, we'll be testing a Rails plugin we've written against various versions of Rails, so it like look something like this (assuming we cloned bare <tt>.git</tt> repos into the current directory)
38
+
39
+ repos 'rails.git', 'our_plugin.git'
40
+
41
+ Okay, now let just create a single scenario. In general, a scenario will be some set of configuration you'd like to test. For this example we won't be doing anything fancy (just a simple drop in <tt>vendor/plugins</tt>) so it might look like this:
42
+
43
+ scenario "Installed in vendor/plugins" do
44
+ generate_rails_app
45
+ install_plugin
46
+ verify_loads_environment
47
+ end
48
+
49
+ You see 3 things need to happen in the scenario; we've broken these out for clarity and just define them underneath:
50
+
51
+ First, let's generate a fresh Rails app for testing with:
52
+
53
+ def generate_rails_app
54
+ ruby "#{rails_path}/railties/bin/rails rails_app"
55
+ end
56
+
57
+ A few notes on what you see above:
58
+
59
+ 0. <tt>ruby</tt> is simply a <tt>rake</tt> convenience method that calls out to a new <tt>ruby</tt> interpreter
60
+ 0. <tt>rails_path</tt> is the absolute path to a fresh clone of the <tt>rails.git</tt> repo we defined at the beginning of the file, checked-out to the reference point we're currently checking (more on how that's set later). <tt>*_path</tt> convenience methods are generated for all the repos you've defined; you'll see the other one in <tt>install_plugin</tt>.
61
+ 0. We're calling out to the <tt>rails</tt> executable in the checked-out source directly so we can generate an accurate skeleton app for that version. The <tt>rails_app</tt> argument is just the name of the directory where it will be generated.
62
+
63
+ It's worth noting that when scenarios are being run, the current working directory is changed for you automatically; right now you're actually sitting in <tt>build/<timestamp>/scenarios/installed_in_vendor_plugins</tt>, where <tt>rails_app</tt> will be generated as a subdirectory.
64
+
65
+ Let's install the plugin now:
66
+
67
+ def install_plugin
68
+ cp_r our_plugin_path, 'rails_app/vendor/plugins'
69
+ end
70
+
71
+ 0. <tt>cp_r</tt> is another <tt>rake</tt> convenience method that does a recursive copy.
72
+ 0. <tt>our_plugin_path</tt> is the <tt>*_path</tt> method generated automatically for our plugin repo.
73
+
74
+ So, that was simple; for this quick example we just copy the plugin directly in.
75
+
76
+ Now let's do something that just verifies the Rails app code will load successfully across the standard environments, just by printing the Rails version from <tt>script/runner</tt>:
77
+
78
+ def verify_loads_environment
79
+ Dir.chdir 'rails_app' do
80
+ %w(test development production).each do |env|
81
+ ENV['RAILS_ENV'] = env
82
+ ruby "script/runner 'p Rails::VERSION'"
83
+ end
84
+ end
85
+ end
86
+
87
+ The great thing about the convenience methods that <tt>rake</tt> provides (eg, <tt>ruby</tt>, <tt>sh</tt>, <tt>cp_r</tt>, etc) is that the raise an exception if the system call they make returns a bad exit code; the scenario automatically catches them and assigns a _failure_ to the scenario. If you're not using these convenience methods and need to assign a failure, you can raise an exception manually to get the same result.
88
+
89
+ == Running against arbitrary references
90
+
91
+ Here are some examples on how we could run the scenario, with plain English explanations:
92
+
93
+ Run all scenarios, with all repos set to <tt>master</tt>:
94
+
95
+ $ rake rocksteady
96
+
97
+ Run just the first scenario (you can use <tt>rake -T</tt> to see them all), with all repos set to <tt>master</tt>:
98
+
99
+ $ rake rocksteady:scenario:1
100
+
101
+ The same, but setting <tt>rails</tt> to <tt>v2.0.2</tt>:
102
+
103
+ $ rake rocksteady:scenario:1 REFS=rails:v2.0.2
104
+
105
+ and now with <tt>our_plugin</tt> set to the <tt>experimental</tt> branch:
106
+
107
+ $ rake rocksteady:scenario:1 REFS=rails:v2.0.2,our_plugin:experimental
108
+
109
+ You can also use full references:
110
+
111
+ $ rake rocksteady:scenario:1 REFS=rails:refs/tags/v2.0.2,our_plugin:refs/heads/experimental
112
+
113
+ == Output
114
+
115
+ Currently the output is a simple text-based table. You'll need to refer to the output in the terminal to find _where_ your failures occur. More granular, labelled scenario-level logging is on the roadmap.
116
+
117
+ == License
118
+
119
+ Copyright (c) 2008 Bruce R. Williams
120
+
121
+ Permission is hereby granted, free of charge, to any person
122
+ obtaining a copy of this software and associated documentation
123
+ files (the "Software"), to deal in the Software without
124
+ restriction, including without limitation the rights to use,
125
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
126
+ copies of the Software, and to permit persons to whom the
127
+ Software is furnished to do so, subject to the following
128
+ conditions:
129
+
130
+ The above copyright notice and this permission notice shall be
131
+ included in all copies or substantial portions of the Software.
132
+
133
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
134
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
135
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
136
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
137
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
138
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
139
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
140
+ OTHER DEALINGS IN THE SOFTWARE.
141
+
142
+
143
+
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+
4
+ require File.dirname(__FILE__) << "/lib/rocksteady/version"
5
+
6
+ Echoe.new 'rocksteady' do |p|
7
+ p.version = Rocksteady::Version::STRING
8
+ p.author = "Bruce Williams"
9
+ p.email = 'bruce@codefluency.com'
10
+ p.project = 'codefluency'
11
+ p.summary = "Run arbitrary scenarios across disparate sets of git repo revisions"
12
+ p.url = "http://github.com/bruce/rocksteady"
13
+ p.dependencies = ['rake', ['mojombo-grit', '>= 0.8.0'], 'ruport']
14
+ p.include_rakefile = true
15
+ end
16
+
data/lib/rocksteady.rb ADDED
@@ -0,0 +1,5 @@
1
+ Dir[File.dirname(__FILE__) << "/rocksteady/**/*.rb"].each do |file|
2
+ require file
3
+ end
4
+
5
+ include Rocksteady::Helpers
@@ -0,0 +1,83 @@
1
+ require 'rubygems'
2
+ require 'mojombo-grit'
3
+
4
+ module Rocksteady
5
+
6
+ class Corpus
7
+
8
+ attr_reader :app
9
+ def initialize(app)
10
+ @app = app
11
+ end
12
+
13
+ # SCENARIOS
14
+
15
+ def scenarios
16
+ @scenarios ||= []
17
+ end
18
+
19
+ def add_scenario(*args, &block)
20
+ scenario = Scenario.new(self, *args, &block)
21
+ scenarios << scenario
22
+ scenario
23
+ end
24
+
25
+ # REPOS
26
+
27
+ def repos
28
+ @repos ||= {}
29
+ end
30
+
31
+ def add_repos(*paths)
32
+ paths.each do |path|
33
+ repo = Grit::Repo.new(path)
34
+ repos[name_of(repo)] = repo
35
+ end
36
+ end
37
+
38
+ # REFS
39
+
40
+ def refs
41
+ @refs ||= {}
42
+ end
43
+
44
+ def default_refs!
45
+ repos.each_key do |repo_name|
46
+ refs[repo_name] ||= 'master'
47
+ end
48
+ end
49
+
50
+ def verify_refs!
51
+ refs.each do |repo_name, ref|
52
+ repo = repos[repo_name]
53
+ unless repo.log(ref).any?
54
+ raise ArgumentError, "Could not find #{repo_name} ref `#{ref}'"
55
+ end
56
+ end
57
+ end
58
+
59
+ def session
60
+ @session ||= Session.new(self)
61
+ end
62
+
63
+ def schedule
64
+ @schedule ||= []
65
+ end
66
+
67
+ #######
68
+ private
69
+ #######
70
+
71
+ # Extract the canonical name of the git repository
72
+ def name_of(repo)
73
+ case repo.path
74
+ when /#{File::SEPARATOR}\.git$/
75
+ File.basename(File.dirname(repo.path))
76
+ else
77
+ File.basename(repo.path, '.git')
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,38 @@
1
+ module Rocksteady
2
+
3
+ module Helpers
4
+
5
+ def corpus
6
+ @corpus ||= Rocksteady::Corpus.new(self)
7
+ end
8
+
9
+ def repos(*paths)
10
+ corpus.add_repos(*paths.flatten)
11
+ end
12
+
13
+ def scenario(opts, &block)
14
+ title, deps = if opts.is_a?(Hash)
15
+ [opts.keys.first, Array(opts.values.first)]
16
+ else
17
+ [opts, []]
18
+ end
19
+ scenario = corpus.add_scenario(title, &block)
20
+ generate_scenario_task scenario, deps
21
+ end
22
+
23
+ #######
24
+ private
25
+ #######
26
+
27
+ # Create the scenario task
28
+ def generate_scenario_task(scenario, deps)
29
+ deps.unshift 'rocksteady:refs:check'
30
+ desc scenario.title
31
+ task "rocksteady:scenario:#{corpus.scenarios.size}" => deps do |t|
32
+ scenario.schedule!
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'ruport'
3
+
4
+ # FIXME: This is a total hackjob.
5
+ # TODO: Support other output types
6
+ at_exit do
7
+ corpus.session.run! do |scenarios|
8
+ table = Ruport::Data::Table.new :column_names => ['Scenario', corpus.session.title] do |t|
9
+ scenarios.sort_by { |s| s.title }.each do |scenario|
10
+ t << [scenario.title, scenario.result.is_a?(Exception) ? "FAIL" : 'PASS']
11
+ end
12
+ end
13
+ puts table
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ module Rocksteady
2
+
3
+ class Scenario
4
+
5
+ attr_reader :corpus, :title, :operation
6
+ def initialize(corpus, title, &operation)
7
+ @corpus = corpus
8
+ @title = title
9
+ @operation = operation
10
+ end
11
+
12
+ def schedule!
13
+ corpus.schedule << self
14
+ end
15
+
16
+ def name
17
+ @name ||= title.gsub(/[^[:alnum:]]+/, '_').downcase
18
+ end
19
+
20
+ def result
21
+ @result ||= begin
22
+ operation.call
23
+ rescue Exception => e
24
+ e
25
+ end
26
+ end
27
+ alias :run! :result
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,79 @@
1
+ module Rocksteady
2
+
3
+ class Session
4
+
5
+ attr_reader :corpus
6
+ def initialize(corpus)
7
+ @corpus = corpus
8
+ end
9
+
10
+ def title
11
+ @title ||= corpus.refs.map { |k, v| "#{k} `#{v}'" }.join(' vs ')
12
+ end
13
+
14
+ def timestamp
15
+ @timestamp ||= Time.now.to_i
16
+ end
17
+
18
+ def run!
19
+ return if corpus.schedule.empty?
20
+ create_timestamp_directory
21
+ clone_repos
22
+ corpus.schedule.each do |scenario|
23
+ focus_on scenario do
24
+ scenario.run!
25
+ end
26
+ end
27
+ yield corpus.schedule
28
+ end
29
+
30
+ #######
31
+ private
32
+ #######
33
+
34
+ def timestamp_directory
35
+ File.expand_path("build/#{timestamp}")
36
+ end
37
+
38
+ def create_timestamp_directory
39
+ mkdir_p timestamp_directory
40
+ end
41
+
42
+ # FIXME: Cleanup
43
+ def clone_repos
44
+ Dir.chdir timestamp_directory do
45
+ mkdir_p 'repos'
46
+ corpus.refs.each do |repo_name, ref|
47
+ repo = corpus.repos[repo_name]
48
+ path = File.expand_path("repos/#{repo_name}")
49
+ (class << corpus.app; self; end).send(:define_method, "#{repo_name}_path") { path }
50
+ sh "git clone -q '#{repo.path}' '#{path}'"
51
+ Dir.chdir path do
52
+ sh "git checkout -q '#{ref}'"
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ def focus_on(scenario, &block)
59
+ directory = directory_for(scenario)
60
+ (class << corpus.app; self; end).send(:define_method, "scenario_log") { logfile_for(scenario) }
61
+ mkdir_p directory
62
+ Dir.chdir(directory, &block)
63
+ end
64
+
65
+ #######
66
+ private
67
+ #######
68
+
69
+ def logfile_for(scenario)
70
+ File.join(directory_for(scenario), 'scenario.log')
71
+ end
72
+
73
+ def directory_for(scenario)
74
+ File.join("#{timestamp_directory}/scenarios/#{scenario.name}")
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,71 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ namespace :rocksteady do
5
+
6
+ desc "Remove build files"
7
+ task :clean do
8
+ rm_rf 'build' rescue nil
9
+ end
10
+
11
+ namespace :refs do
12
+
13
+ task :check => :default do
14
+ begin
15
+ corpus.verify_refs!
16
+ rescue ArgumentError => e
17
+ abort e.message
18
+ end
19
+ end
20
+
21
+ task :default => :add_from_env do
22
+ corpus.default_refs!
23
+ end
24
+
25
+ task :add_from_env => 'rocksteady:repos:check' do
26
+ if ENV['REFS']
27
+ pairs = ENV['REFS'].split(',').map
28
+ pairs.each do |pair|
29
+ repo_name, ref = pair.split(':')
30
+ ref ||= 'master'
31
+ if (repo = corpus.repos[repo_name])
32
+ corpus.refs[repo_name] = ref
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ namespace :repos do
41
+
42
+ desc "Show configured source repositories"
43
+ task :show => :check do
44
+ corpus.repos.sort_by { |k, v| k }.each do |name, repo|
45
+ puts "#{name}: #{repo.path}"
46
+ end
47
+ end
48
+
49
+ task :check => :add_from_env do
50
+ unless corpus.repos.any?
51
+ abort "Could not find repositories.\nSet ENV['REPOS'] or use `repos' method in Rakefile to set repo paths."
52
+ end
53
+ end
54
+
55
+ task :add_from_env do
56
+ if ENV['REPOS']
57
+ paths = ENV['REPOS'].split(',')
58
+ corpus.add_repos(*paths)
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ desc "Run all corpus scenarios"
67
+ task :rocksteady => 'rocksteady:refs:check' do
68
+ corpus.scenarios.each do |scenario|
69
+ scenario.schedule!
70
+ end
71
+ end
@@ -0,0 +1,78 @@
1
+ # (The MIT License)
2
+ #
3
+ # Copyright (c) 2008 Jamis Buck <jamis@37signals.com>,
4
+ # with modifications by Bruce Williams <bruce@codefluency.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # 'Software'), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ module Rocksteady
25
+
26
+ # A class for describing the current version of a library. The version
27
+ # consists of three parts: the +major+ number, the +minor+ number, and the
28
+ # +tiny+ (or +patch+) number.
29
+ class Version
30
+
31
+ include Comparable
32
+
33
+ # A convenience method for instantiating a new Version instance with the
34
+ # given +major+, +minor+, and +tiny+ components.
35
+ def self.[](major, minor, tiny)
36
+ new(major, minor, tiny)
37
+ end
38
+
39
+ attr_reader :major, :minor, :tiny
40
+
41
+ # Create a new Version object with the given components.
42
+ def initialize(major, minor, tiny)
43
+ @major, @minor, @tiny = major, minor, tiny
44
+ end
45
+
46
+ # Compare this version to the given +version+ object.
47
+ def <=>(version)
48
+ to_i <=> version.to_i
49
+ end
50
+
51
+ # Converts this version object to a string, where each of the three
52
+ # version components are joined by the '.' character. E.g., 2.0.0.
53
+ def to_s
54
+ @to_s ||= [@major, @minor, @tiny].join(".")
55
+ end
56
+
57
+ # Converts this version to a canonical integer that may be compared
58
+ # against other version objects.
59
+ def to_i
60
+ @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
61
+ end
62
+
63
+ def to_a
64
+ [@major, @minor, @tiny]
65
+ end
66
+
67
+ MAJOR = 0
68
+ MINOR = 8
69
+ TINY = 0
70
+
71
+ # The current version as a Version instance
72
+ CURRENT = new(MAJOR, MINOR, TINY)
73
+ # The current version as a String
74
+ STRING = CURRENT.to_s
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,50 @@
1
+
2
+ # Gem::Specification for Rocksteady-0.8.0
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{rocksteady}
7
+ s.version = "0.8.0"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Bruce Williams"]
13
+ s.date = %q{2008-06-07}
14
+ s.description = %q{Run arbitrary scenarios across disparate sets of git repo revisions}
15
+ s.email = %q{bruce@codefluency.com}
16
+ s.extra_rdoc_files = ["CHANGELOG", "lib/rocksteady/corpus.rb", "lib/rocksteady/helpers.rb", "lib/rocksteady/output.rb", "lib/rocksteady/scenario.rb", "lib/rocksteady/session.rb", "lib/rocksteady/tasks.rb", "lib/rocksteady/version.rb", "lib/rocksteady.rb", "README.rdoc"]
17
+ s.files = ["CHANGELOG", "lib/rocksteady/corpus.rb", "lib/rocksteady/helpers.rb", "lib/rocksteady/output.rb", "lib/rocksteady/scenario.rb", "lib/rocksteady/session.rb", "lib/rocksteady/tasks.rb", "lib/rocksteady/version.rb", "lib/rocksteady.rb", "Manifest", "Rakefile", "README.rdoc", "test/rocksteady_test.rb", "rocksteady.gemspec"]
18
+ s.has_rdoc = true
19
+ s.homepage = %q{http://github.com/bruce/rocksteady}
20
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rocksteady", "--main", "README.rdoc"]
21
+ s.require_paths = ["lib"]
22
+ s.rubyforge_project = %q{codefluency}
23
+ s.rubygems_version = %q{1.1.1}
24
+ s.summary = %q{Run arbitrary scenarios across disparate sets of git repo revisions}
25
+ s.test_files = ["test/rocksteady_test.rb"]
26
+
27
+ s.add_dependency(%q<rake>, [">= 0"])
28
+ s.add_dependency(%q<mojombo-grit>, [">= 0.8.0"])
29
+ s.add_dependency(%q<ruport>, [">= 0"])
30
+ end
31
+
32
+
33
+ # # Original Rakefile source (requires the Echoe gem):
34
+ #
35
+ # require 'rubygems'
36
+ # require 'echoe'
37
+ #
38
+ # require File.dirname(__FILE__) << "/lib/rocksteady/version"
39
+ #
40
+ # Echoe.new 'rocksteady' do |p|
41
+ # p.version = Rocksteady::Version::STRING
42
+ # p.author = "Bruce Williams"
43
+ # p.email = 'bruce@codefluency.com'
44
+ # p.project = 'codefluency'
45
+ # p.summary = "Run arbitrary scenarios across disparate sets of git repo revisions"
46
+ # p.url = "http://github.com/bruce/rocksteady"
47
+ # p.dependencies = ['rake', ['mojombo-grit', '>= 0.8.0'], 'ruport']
48
+ # p.include_rakefile = true
49
+ # end
50
+ #
@@ -0,0 +1,95 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'Shoulda'
4
+
5
+ $:.unshift(File.dirname(__FILE__) << "/../lib")
6
+ require 'rocksteady/corpus'
7
+ require 'rocksteady/helpers'
8
+
9
+ class RSTarget
10
+ include Rocksteady::Helpers
11
+ end
12
+
13
+ class RocksteadyTest < Test::Unit::TestCase
14
+
15
+ context "Rocksteady" do
16
+
17
+ tmp_dir = File.dirname(__FILE__) << "/tmp"
18
+
19
+ repo_dirs = (1..3).to_a.map do |n|
20
+ "#{tmp_dir}/repo#{n}"
21
+ end
22
+
23
+ setup do
24
+ @r = RSTarget.new
25
+ repo_dirs.each do |dir|
26
+ FileUtils.mkdir_p dir
27
+ Dir.chdir(dir) do
28
+ system "git init > /dev/null 2>&1"
29
+ File.open('stub', 'w') { |f| f.puts 'nothing' }
30
+ system 'git add . > /dev/null 2>&1'
31
+ system 'git commit -m "stub" > /dev/null 2>&1'
32
+ end
33
+ end
34
+ end
35
+
36
+ teardown do
37
+ FileUtils.rm_rf tmp_dir
38
+ end
39
+
40
+ populate = lambda { @r.corpus.add_repos(*Dir["#{tmp_dir}/*"]) }
41
+
42
+ context "Helpers" do
43
+ should "have corpus accessor added as a helper" do
44
+ assert @r.respond_to?(:corpus)
45
+ end
46
+ end
47
+
48
+ context "Core" do
49
+
50
+ should "start without repos" do
51
+ assert @r.corpus.repos.empty?
52
+ end
53
+
54
+ should "start without refs" do
55
+ assert @r.corpus.refs.empty?
56
+ end
57
+
58
+ should "add repos by paths" do
59
+ instance_eval(&populate)
60
+ assert @r.corpus.repos.size == repo_dirs.size
61
+ assert @r.corpus.repos.keys.all? { |r| r =~ /^repo\d+$/ }
62
+ assert @r.corpus.repos.values.all? { |r| r.is_a?(Grit::Repo) }
63
+ assert @r.corpus.refs.empty?
64
+ end
65
+
66
+ should "default refs for existing repos without explicit ref" do
67
+ instance_eval(&populate)
68
+ assert @r.corpus.refs.empty?
69
+ @r.corpus.refs['repo1'] = explicit = 'explicit-ref-for-this-repo'
70
+ @r.corpus.default_refs!
71
+ masters, explicits = @r.corpus.refs.partition { |k, v| v == 'master' }
72
+ assert_equal 2, masters.size
73
+ assert_equal 1, explicits.size
74
+ end
75
+
76
+ should "allow verification of refs" do
77
+ instance_eval(&populate)
78
+ assert @r.corpus.refs.empty?
79
+ @r.corpus.default_refs!
80
+ assert_nothing_raised do
81
+ @r.corpus.verify_refs!
82
+ end
83
+ @r.corpus.refs.clear
84
+ @r.corpus.refs['repo1'] = 'this-does-not-exist'
85
+ @r.corpus.default_refs!
86
+ assert_raises ArgumentError do
87
+ @r.corpus.verify_refs!
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rocksteady
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.0
5
+ platform: ruby
6
+ authors:
7
+ - Bruce Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-07 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: mojombo-grit
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 0.8.0
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: ruport
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ description: Run arbitrary scenarios across disparate sets of git repo revisions
43
+ email: bruce@codefluency.com
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ extra_rdoc_files:
49
+ - CHANGELOG
50
+ - lib/rocksteady/corpus.rb
51
+ - lib/rocksteady/helpers.rb
52
+ - lib/rocksteady/output.rb
53
+ - lib/rocksteady/scenario.rb
54
+ - lib/rocksteady/session.rb
55
+ - lib/rocksteady/tasks.rb
56
+ - lib/rocksteady/version.rb
57
+ - lib/rocksteady.rb
58
+ - README.rdoc
59
+ files:
60
+ - CHANGELOG
61
+ - lib/rocksteady/corpus.rb
62
+ - lib/rocksteady/helpers.rb
63
+ - lib/rocksteady/output.rb
64
+ - lib/rocksteady/scenario.rb
65
+ - lib/rocksteady/session.rb
66
+ - lib/rocksteady/tasks.rb
67
+ - lib/rocksteady/version.rb
68
+ - lib/rocksteady.rb
69
+ - Manifest
70
+ - Rakefile
71
+ - README.rdoc
72
+ - test/rocksteady_test.rb
73
+ - rocksteady.gemspec
74
+ has_rdoc: true
75
+ homepage: http://github.com/bruce/rocksteady
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --line-numbers
79
+ - --inline-source
80
+ - --title
81
+ - Rocksteady
82
+ - --main
83
+ - README.rdoc
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ version:
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: "0"
97
+ version:
98
+ requirements: []
99
+
100
+ rubyforge_project: codefluency
101
+ rubygems_version: 1.1.1
102
+ signing_key:
103
+ specification_version: 2
104
+ summary: Run arbitrary scenarios across disparate sets of git repo revisions
105
+ test_files:
106
+ - test/rocksteady_test.rb