tlb-cucumber 0.3.1
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/.emacs_project.template +21 -0
- data/.gitignore +8 -0
- data/.gitmodules +3 -0
- data/README.markdown +66 -0
- data/Rakefile +27 -0
- data/gem_common.rb +64 -0
- data/lib/tasks/tlb.rake +12 -0
- data/lib/tlb.rb +238 -0
- data/lib/tlb/cucumber/lib/configuration_inflection.rb +39 -0
- data/lib/tlb/cucumber/lib/run_data_formatter.rb +38 -0
- data/lib/tlb/cucumber/lib/test_splitter.rb +14 -0
- data/lib/tlb/cucumber/rake/cucumber_task.rb +21 -0
- data/lib/tlb/run_data.rb +55 -0
- data/lib/tlb/util.rb +11 -0
- data/spike/Rakefile +12 -0
- data/spike/features/step_definitions/addition.rb +18 -0
- data/spike/features/step_definitions/answer.rb +13 -0
- data/spike/features/step_definitions/sub.rb +18 -0
- data/spike/features/sub.feature +6 -0
- data/spike/features/sum.feature +6 -0
- data/spike/features/the_answer.feature +6 -0
- data/test.sh +42 -0
- data/tlb-cucumber.gemspec +9 -0
- data/tlb-rspec2.gemspec +10 -0
- data/tlb-testunit.gemspec +8 -0
- metadata +148 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
;; copy me as .emacs_project in project root if using .emacs.d = git://github.com/janmejay/emacs.git
|
|
2
|
+
;; after copying it across, modify the file to make it relevant to local rvm setup
|
|
3
|
+
(setq rspec-executable "rspec")
|
|
4
|
+
(setq rb_platform "jruby")
|
|
5
|
+
(setq rb_platform "mri")
|
|
6
|
+
|
|
7
|
+
(unless (getenv "ORIG_PATH")
|
|
8
|
+
(setenv "ORIG_PATH" (getenv "PATH")))
|
|
9
|
+
|
|
10
|
+
(defun add-gem-bin (gem-bin)
|
|
11
|
+
(setenv "PATH" (concat gem-bin ":" (getenv "ORIG_PATH"))))
|
|
12
|
+
|
|
13
|
+
(if (equal rb_platform "jruby")
|
|
14
|
+
(progn
|
|
15
|
+
(setenv "GEM_HOME" "/home/janmejay/.rvm/gems/jruby-1.5.6@tlb")
|
|
16
|
+
(setenv "GEM_PATH" "/home/janmejay/.rvm/gems/jruby-1.5.6@tlb:/home/janmejay/.rvm/gems/jruby-1.5.6@global")
|
|
17
|
+
(add-gem-bin "/home/janmejay/.rvm/gems/jruby-1.5.6@tlb/bin"))
|
|
18
|
+
(progn
|
|
19
|
+
(setenv "GEM_HOME" "/home/janmejay/.rvm/gems/ruby-1.8.7-p334@tlb")
|
|
20
|
+
(setenv "GEM_PATH" "/home/janmejay/.rvm/gems/ruby-1.8.7-p334@tlb:/home/janmejay/.rvm/gems/ruby-1.8.7-p334@global")
|
|
21
|
+
(add-gem-bin "/home/janmejay/.rvm/gems/ruby-1.8.7-p334@tlb/bin")))
|
data/.gitignore
ADDED
data/.gitmodules
ADDED
data/README.markdown
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
## Using tlb_rb:
|
|
2
|
+
|
|
3
|
+
tlb.rb uses [tlb](https://github.com/test-load-balancer/tlb "TLB") under the hood. It runs a sub-process which talks to the actual tlb-server(or equivallent) to balance and post run-feedback.
|
|
4
|
+
Balancer process is actually an HTTP server which listen to a certain TCP port so tlb-ruby library can talk to it.
|
|
5
|
+
This is controlled by an environment variable named *'TLB_BALANCER_PORT'*, which can be set to any port number(integer between 1024 to 65535) that is guaranteed to remain un-bound while the build runs.
|
|
6
|
+
|
|
7
|
+
In addition to this extra environment variable, the usual TLB environment variable setup is required(so the balancer knows things like what partitioning algorithm to use or what server to talk to).
|
|
8
|
+
Detailed documentation of TLB environment variable configuration is available at [http://test-load-balancer.github.com](http://test-load-balancer.github.com "Tlb Documentation")
|
|
9
|
+
|
|
10
|
+
As of now, tlb.rb supports RSpec(1.x and 2.x) and Test::Unit, which are the two most widely used testing frameworks in Ruby. We plan to add support for other ruby-testing-frameworks soon.
|
|
11
|
+
|
|
12
|
+
## Setting it up for your project
|
|
13
|
+
|
|
14
|
+
Please refer the [sample_projects](http://github.com/test-load-balancer/sample_projects "Tlb setup examples") to see the details of how to set it up.
|
|
15
|
+
|
|
16
|
+
Usually, something equivallent of this in one of your Rake files should suffice:
|
|
17
|
+
__RSpec-1.x__:
|
|
18
|
+
require 'rubygems'
|
|
19
|
+
gem 'tlb-rspec1'
|
|
20
|
+
require 'tlb/spec_task'
|
|
21
|
+
|
|
22
|
+
Tlb::SpecTask.new(:balanced_specs) do |t|
|
|
23
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
|
24
|
+
t.spec_opts << "--format progress"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
load 'tasks/tlb.rake'
|
|
28
|
+
desc "run specs load-balanced(based on environment variables)"
|
|
29
|
+
task :bal => ['tlb:start', :balanced_specs]
|
|
30
|
+
|
|
31
|
+
__RSpec-2.x__:
|
|
32
|
+
require 'rubygems'
|
|
33
|
+
gem 'tlb-rspec2'
|
|
34
|
+
require 'tlb/rspec/spec_task'
|
|
35
|
+
|
|
36
|
+
Tlb::RSpec::SpecTask.new(:run_balanced) do |t|
|
|
37
|
+
t.pattern = 'spec/**/*_spec.rb'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
load 'tasks/tlb.rake'
|
|
41
|
+
desc "run specs load-balanced(based on environment variables)"
|
|
42
|
+
task :bal => ['tlb:start', :run_balanced]
|
|
43
|
+
|
|
44
|
+
__Test::Unit__:
|
|
45
|
+
require 'rake'
|
|
46
|
+
require 'rubygems'
|
|
47
|
+
gem 'tlb-testunit'
|
|
48
|
+
require 'tlb/test_unit/test_task'
|
|
49
|
+
|
|
50
|
+
Tlb::TestUnit::TestTask.new(:test_balanced) do |t|
|
|
51
|
+
t.libs << "test"
|
|
52
|
+
t.test_files = FileList['test/**/*_test.rb']
|
|
53
|
+
t.verbose = true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
load 'tasks/tlb.rake'
|
|
57
|
+
|
|
58
|
+
task :bal => ['tlb:start', :test_balanced]
|
|
59
|
+
|
|
60
|
+
Where __bal__ is the task you invoke at the top-level(invoked externally).
|
|
61
|
+
|
|
62
|
+
## RSpec source-control and release-version/environment compatibility
|
|
63
|
+
The branch '__master__' supports __Test::Unit__ and __RSpec-2.x__. If you use __RSpec-1__(i.e. __1.3.x__ etc), please use the branch named '__rspec-1__'.
|
|
64
|
+
Having said that, we encourage end-users to use the released gem versions insteed of using upstream snapshot. Detailed documentation for every released version is available at http://test-load-balancer.github.com.
|
|
65
|
+
Please post any issues on our [Issue Tracker](http://code.google.com/p/tlb/issues/list "Issue Tracker").
|
|
66
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'rspec/core/rake_task'
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
|
|
4
|
+
task :test => ['test:rspec', 'test:test_unit']
|
|
5
|
+
|
|
6
|
+
namespace :test do
|
|
7
|
+
RSpec::Core::RakeTask.new(:rspec) do |t|
|
|
8
|
+
t.pattern = 'tests/**/*_spec.rb'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Rake::TestTask.new(:test_unit) do |t|
|
|
12
|
+
t.test_files = FileList['tests/**/*_test.rb']
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
task :build_tlb do
|
|
17
|
+
[Dir.glob("tlb-alien*.jar"), Dir.glob("tlb-server*.jar")].flatten.each { |jar| FileUtils.rm(jar) }
|
|
18
|
+
sh '(cd tlb && ant clean package -Doffline=t)'
|
|
19
|
+
Dir.glob('tlb/target/tlb-alien*').each { |file| FileUtils.copy(file, ".") }
|
|
20
|
+
Dir.glob('tlb/target/tlb-server*').each { |file| FileUtils.copy(file, "tests/") }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
task :package do
|
|
24
|
+
`gem build tlb-rspec2.gemspec`
|
|
25
|
+
`gem build tlb-testunit.gemspec`
|
|
26
|
+
`gem build tlb-cucumber.gemspec`
|
|
27
|
+
end
|
data/gem_common.rb
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
BASE_DIR = File.dirname(__FILE__)
|
|
2
|
+
LIB_TLB = File.join(BASE_DIR, "lib", "tlb")
|
|
3
|
+
TEST_DIR = File.join(BASE_DIR, "tests")
|
|
4
|
+
TAG_VERSION = `git describe --abbrev=0`.gsub(/^v/, '')
|
|
5
|
+
CODE_VERSION = `git describe --always`
|
|
6
|
+
AUTHORS = ["Janmejay Singh", "Pavan KS"]
|
|
7
|
+
EMAIL = "singh.janmejay@gmail.com;itspanzi@gmail.com"
|
|
8
|
+
HOME_PAGE = "http://github.com/test-load-balancer/tlb.rb"
|
|
9
|
+
SUMMARY = "#{$name}-#{CODE_VERSION}"
|
|
10
|
+
DESC = <<END
|
|
11
|
+
TLB ruby implementation base, which provides support for load balancing tests written in #{$framework}.
|
|
12
|
+
TLB.rb test suite is not bundled, please check http://github.com/test-load-balancer/tlb.rb for tests.
|
|
13
|
+
Detailed documentation is available at http://test-load-balancer.github.com.
|
|
14
|
+
END
|
|
15
|
+
POST_INSTALL_MESSAGE = <<END
|
|
16
|
+
-------------------------------------------------------------------------
|
|
17
|
+
TLB Documentation: Detailed configuration documentation can be found at http://test-load-balancer.github.com. Documentation section in this website hosts documentation for every public release.
|
|
18
|
+
|
|
19
|
+
-------------------------------------------------------------------------
|
|
20
|
+
TLB Example(s): We maintain a directory of tlb-enabled dummy projects written in different languages using different testing and build frameworks to help new TLB users get started and provide people a working project to refer to while hooking up TLB on their project(s). Each of these projects have a shell script(named run_balanced.sh) that is meant to demonstrate a typical tlb-enabled build(by starting a local tlb server, and executing two partitions that run dummy tests locally).
|
|
21
|
+
For demonstration purpose, aforementioned shell script executes partitions in the example-project one after another(serially). However, partitions will be executed parallely on different machines in a real-world setup(hence cutting the build time).
|
|
22
|
+
We recommend playing with the configuration-variable values being set in the shell-script(s) to understand the effect different values have on load-balancing/reordering behavior. You may want to check http://test-load-balancer.github.com, which links to 'detailed documentation' that covers each configuration variable and explains its purpose, effect and implication.
|
|
23
|
+
|
|
24
|
+
Examples archive is released along-with TLB, and is available for download at http://code.google.com/p/tlb/downloads/list.
|
|
25
|
+
|
|
26
|
+
To execute the example project, drop into the example project directory(examples/rspec2_example for instance) and invoke the './run_balanced.sh'.
|
|
27
|
+
|
|
28
|
+
-------------------------------------------------------------------------
|
|
29
|
+
TLB Issue Tracker: Please report/port bugs/enhancements/feature-requests on http://code.google.com/p/tlb/issues/list. Github, Rubyforge or any other issue trackers are not monitored or updated.
|
|
30
|
+
|
|
31
|
+
-------------------------------------------------------------------------
|
|
32
|
+
END
|
|
33
|
+
RUBYFORGE_PROJECT = "tlb-rb"
|
|
34
|
+
RUBYGEMS_VERSION = "1.3.7"
|
|
35
|
+
|
|
36
|
+
def files *exclude_dirs
|
|
37
|
+
files = `git ls-files`.split("\n")
|
|
38
|
+
files += Dir.glob(File.join(File.dirname(__FILE__), "*.jar")).map { |path| File.basename(path) }
|
|
39
|
+
exclude_dirs.inject(files) { |files, dir| files - `git ls-files #{dir}`.split("\n") }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def configure_tlb s
|
|
44
|
+
s.name = $name
|
|
45
|
+
s.version = TAG_VERSION
|
|
46
|
+
s.platform = Gem::Platform::RUBY
|
|
47
|
+
s.authors = AUTHORS
|
|
48
|
+
s.email = EMAIL
|
|
49
|
+
s.homepage = HOME_PAGE
|
|
50
|
+
s.summary = SUMMARY
|
|
51
|
+
s.description = DESC
|
|
52
|
+
|
|
53
|
+
s.rubyforge_project = RUBYFORGE_PROJECT
|
|
54
|
+
s.rubygems_version = RUBYGEMS_VERSION
|
|
55
|
+
|
|
56
|
+
s.post_install_message = POST_INSTALL_MESSAGE
|
|
57
|
+
|
|
58
|
+
s.extra_rdoc_files = [ "README.markdown" ]
|
|
59
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
|
60
|
+
s.require_path = "lib"
|
|
61
|
+
|
|
62
|
+
s.add_runtime_dependency 'open4', '>= 1.0.1'
|
|
63
|
+
s.add_runtime_dependency 'rake'
|
|
64
|
+
end
|
data/lib/tasks/tlb.rake
ADDED
data/lib/tlb.rb
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'open4'
|
|
3
|
+
require 'net/http'
|
|
4
|
+
|
|
5
|
+
TLB_RB_LIB = File.expand_path(File.dirname(__FILE__))
|
|
6
|
+
unless $LOAD_PATH.include? TLB_RB_LIB
|
|
7
|
+
$LOAD_PATH << TLB_RB_LIB
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module Tlb
|
|
11
|
+
TLB_OUT_FILE = 'TLB_OUT_FILE'
|
|
12
|
+
TLB_ERR_FILE = 'TLB_ERR_FILE'
|
|
13
|
+
TLB_APP = 'TLB_APP'
|
|
14
|
+
|
|
15
|
+
module Balancer
|
|
16
|
+
TLB_BALANCER_PORT = 'TLB_BALANCER_PORT'
|
|
17
|
+
BALANCE_PATH = '/balance'
|
|
18
|
+
SUITE_TIME_REPORTING_PATH = '/suite_time'
|
|
19
|
+
SUITE_RESULT_REPORTING_PATH = '/suite_result'
|
|
20
|
+
|
|
21
|
+
def self.host
|
|
22
|
+
'localhost'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.port
|
|
26
|
+
ENV[TLB_BALANCER_PORT] || '8019'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.send path, data
|
|
30
|
+
Net::HTTP.start(host, port) do |h|
|
|
31
|
+
res = h.post(path, data)
|
|
32
|
+
res.value
|
|
33
|
+
res.body
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.get path
|
|
38
|
+
Net::HTTP.get_response(host, path, port).body
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.running?
|
|
42
|
+
get("/control/status") == "RUNNING"
|
|
43
|
+
rescue
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.terminate
|
|
48
|
+
get("/control/suicide")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.wait_for_start
|
|
52
|
+
loop do
|
|
53
|
+
begin
|
|
54
|
+
break if running?
|
|
55
|
+
rescue
|
|
56
|
+
#ignore
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
module RSpec
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
module TestUnit
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.relative_file_path file_name
|
|
69
|
+
abs_file_name = File.expand_path(file_name)
|
|
70
|
+
rel_file_name = abs_file_name.sub(/^#{Dir.pwd}/, '.')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.relative_file_paths file_names
|
|
74
|
+
file_names.map { |file_name| relative_file_path(file_name) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.balance_and_order file_set
|
|
78
|
+
ensure_server_running
|
|
79
|
+
Balancer.send(Balancer::BALANCE_PATH, file_set.join("\n")).split("\n")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def self.suite_result suite_name, result
|
|
83
|
+
ensure_server_running
|
|
84
|
+
Balancer.send(Balancer::SUITE_RESULT_REPORTING_PATH, "#{suite_name}: #{result}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.suite_time suite_name, mills
|
|
88
|
+
ensure_server_running
|
|
89
|
+
Balancer.send(Balancer::SUITE_TIME_REPORTING_PATH, "#{suite_name}: #{mills}")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.fail_as_balancer_is_not_running
|
|
93
|
+
raise "Balancer server must be started before tests are run."
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.ensure_server_running
|
|
97
|
+
server_running? || fail_as_balancer_is_not_running
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def self.server_running?
|
|
101
|
+
Balancer.running?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def self.root_dir
|
|
105
|
+
File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def self.tlb_jar
|
|
109
|
+
File.expand_path(Dir.glob(File.join(root_dir, "tlb-alien*")).first)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def self.server_command
|
|
113
|
+
"java -jar #{tlb_jar}"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def self.can_fork?
|
|
117
|
+
RUBY_PLATFORM != 'java'
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
class BalancerProcess
|
|
121
|
+
class StreamPumper
|
|
122
|
+
def initialize stream, file
|
|
123
|
+
@stream, @file = stream, file
|
|
124
|
+
@thd = Thread.new { pump }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def pump
|
|
128
|
+
loop do
|
|
129
|
+
data_available? && flush_stream
|
|
130
|
+
Thread.current[:stop_pumping] && break
|
|
131
|
+
sleep 0.1
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def flush_stream
|
|
136
|
+
File.open(ENV[@file], 'a') do |h|
|
|
137
|
+
h.write(read)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def stop_pumping!
|
|
142
|
+
@thd[:stop_pumping] = true
|
|
143
|
+
@thd.join
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def initialize server_command
|
|
148
|
+
pumper_type, out, err = start(server_command)
|
|
149
|
+
@out_pumper = pumper_type.new(out, TLB_OUT_FILE)
|
|
150
|
+
@err_pumper = pumper_type.new(err, TLB_ERR_FILE)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def stop_pumping
|
|
154
|
+
@out_pumper.stop_pumping!
|
|
155
|
+
@err_pumper.stop_pumping!
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def die
|
|
159
|
+
Balancer.terminate
|
|
160
|
+
stop_pumping
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
class ForkBalancerProcess < BalancerProcess
|
|
165
|
+
def start server_command
|
|
166
|
+
@pid, input, out, err = Open4.popen4(server_command)
|
|
167
|
+
unless (out)
|
|
168
|
+
raise "out was nil"
|
|
169
|
+
end
|
|
170
|
+
return Class.new(StreamPumper) do
|
|
171
|
+
def data_available?
|
|
172
|
+
not @stream.eof?
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def read
|
|
176
|
+
@stream.read
|
|
177
|
+
end
|
|
178
|
+
end, out, err
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def die
|
|
182
|
+
super
|
|
183
|
+
@pid = nil
|
|
184
|
+
Process.wait
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
class JavaBalancerProcess < BalancerProcess
|
|
189
|
+
def start server_command
|
|
190
|
+
require 'java'
|
|
191
|
+
pb = java.lang.ProcessBuilder.new(server_command.split)
|
|
192
|
+
ENV.each do |key, val|
|
|
193
|
+
pb.environment[key] = val
|
|
194
|
+
end
|
|
195
|
+
@process = pb.start()
|
|
196
|
+
return Class.new(StreamPumper) do
|
|
197
|
+
def data_available?
|
|
198
|
+
@stream.ready
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def read
|
|
202
|
+
@stream.read_line
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def stop_pumping!
|
|
206
|
+
super
|
|
207
|
+
@stream.close
|
|
208
|
+
end
|
|
209
|
+
end, buf_reader(@process.input_stream), buf_reader(@process.error_stream)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def buf_reader stream
|
|
213
|
+
java.io.BufferedReader.new(java.io.InputStreamReader.new(stream))
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def die
|
|
217
|
+
super
|
|
218
|
+
@process.destroy
|
|
219
|
+
@process.waitFor
|
|
220
|
+
@process = nil
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def self.balancer_process_type
|
|
225
|
+
can_fork? ? ForkBalancerProcess : JavaBalancerProcess
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def self.start_server
|
|
229
|
+
ENV[TLB_APP] = 'tlb.balancer.BalancerInitializer'
|
|
230
|
+
bal_klass = balancer_process_type
|
|
231
|
+
@balancer_process = bal_klass.new(server_command)
|
|
232
|
+
Balancer.wait_for_start
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def self.stop_server
|
|
236
|
+
@balancer_process.die
|
|
237
|
+
end
|
|
238
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'tlb'))
|
|
2
|
+
require 'cucumber/cli/configuration'
|
|
3
|
+
require 'tlb/cucumber/lib/test_splitter'
|
|
4
|
+
require 'tlb/cucumber/lib/run_data_formatter'
|
|
5
|
+
|
|
6
|
+
module Tlb
|
|
7
|
+
module Cucumber
|
|
8
|
+
module Lib
|
|
9
|
+
module ConfigurationInflection
|
|
10
|
+
include Tlb::Cucumber::Lib::TestSplitter
|
|
11
|
+
|
|
12
|
+
def self.included base
|
|
13
|
+
unless base.included_modules.include?(InstanceMethods)
|
|
14
|
+
base.send(:alias_method, :all_feature_files, :feature_files)
|
|
15
|
+
base.send(:remove_method, :feature_files)
|
|
16
|
+
base.send(:alias_method, :all_formatters, :formatters)
|
|
17
|
+
base.send(:remove_method, :formatters)
|
|
18
|
+
base.send(:include, InstanceMethods)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module InstanceMethods
|
|
23
|
+
def feature_files
|
|
24
|
+
prune_features(all_feature_files)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def formatters(step_mother)
|
|
28
|
+
formatters = all_formatters(step_mother)
|
|
29
|
+
formatters << Tlb::Cucumber::Lib::RunDataFormatter.new
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
Cucumber::Cli::Configuration.class_eval do
|
|
38
|
+
include Tlb::Cucumber::Lib::ConfigurationInflection
|
|
39
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'tlb'))
|
|
2
|
+
require 'tlb/run_data'
|
|
3
|
+
|
|
4
|
+
module Tlb
|
|
5
|
+
module Cucumber
|
|
6
|
+
module Lib
|
|
7
|
+
class RunDataFormatter
|
|
8
|
+
include Tlb::RunData
|
|
9
|
+
|
|
10
|
+
def initialize(*args)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def before_feature(*args)
|
|
14
|
+
suite_started(feature_file args)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def after_feature(*args)
|
|
18
|
+
update_suite_failed(feature_file args) if @failed
|
|
19
|
+
update_suite_data(feature_file args)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def after_step_result(*args)
|
|
23
|
+
@failed = args[3] != :passed && args[3] != :pending
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def after_features(*args)
|
|
27
|
+
report_all_suite_data
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def feature_file args
|
|
33
|
+
args[0].file
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'tlb'))
|
|
2
|
+
|
|
3
|
+
module Tlb
|
|
4
|
+
module Cucumber
|
|
5
|
+
module Lib
|
|
6
|
+
module TestSplitter
|
|
7
|
+
|
|
8
|
+
def prune_features(feature_file_paths)
|
|
9
|
+
Tlb.balance_and_order(Tlb.relative_file_paths(feature_file_paths))
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'cucumber/rake/task'
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'tlb'))
|
|
3
|
+
require 'tlb/util'
|
|
4
|
+
require 'tlb/cucumber/lib/configuration_inflection'
|
|
5
|
+
|
|
6
|
+
module Tlb
|
|
7
|
+
module Cucumber
|
|
8
|
+
module Rake
|
|
9
|
+
class CucumberTask < ::Cucumber::Rake::Task
|
|
10
|
+
|
|
11
|
+
def initialize(*args)
|
|
12
|
+
super(args) do |this|
|
|
13
|
+
yield this if block_given?
|
|
14
|
+
this.cucumber_opts ||= []
|
|
15
|
+
this.cucumber_opts = [this.cucumber_opts, "#{File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))}", 'features'].flatten
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/tlb/run_data.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'tlb'))
|
|
2
|
+
|
|
3
|
+
module Tlb::RunData
|
|
4
|
+
class Suite < Struct.new(:identity, :start_time, :end_time, :failed)
|
|
5
|
+
MILLS_PER_SEC = 1000
|
|
6
|
+
|
|
7
|
+
def initialize(identity, start_time)
|
|
8
|
+
super(identity, start_time, start_time, false)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def run_time
|
|
12
|
+
((end_time - start_time)*MILLS_PER_SEC).to_i
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def for_id? new_identity
|
|
16
|
+
identity == new_identity
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def report_to_tlb
|
|
20
|
+
Tlb.suite_time(identity, run_time)
|
|
21
|
+
Tlb.suite_result(identity, failed)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def suite_started identity
|
|
26
|
+
unless (suites.last && suites.last.for_id?(identity))
|
|
27
|
+
suites << Tlb::RunData::Suite.new(identity, Time.now)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def update_suite_data identity
|
|
32
|
+
if (suite = suites.last) #stupid framework :: retarded fix (this is necessary since rspec-1[don't know if rspec-2 is as stupid too] creates example_proxies for every example it runs, as though its an independent spec-group)
|
|
33
|
+
suite.end_time = Time.now
|
|
34
|
+
block_given? && yield(suite)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def update_suite_failed identity
|
|
39
|
+
update_suite_data(identity) do |suite|
|
|
40
|
+
suite.failed = true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def report_all_suite_data
|
|
45
|
+
suites.each do |suite_time|
|
|
46
|
+
suite_time.report_to_tlb
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def suites
|
|
53
|
+
@suites ||= []
|
|
54
|
+
end
|
|
55
|
+
end
|
data/lib/tlb/util.rb
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'tlb'))
|
|
2
|
+
|
|
3
|
+
module Tlb::Util
|
|
4
|
+
def self.quote_path *fragments
|
|
5
|
+
single_quote(File.expand_path(File.join(*fragments)))
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.single_quote arg
|
|
9
|
+
"'#{arg.gsub(/'/, "\\'")}'"
|
|
10
|
+
end
|
|
11
|
+
end
|
data/spike/Rakefile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'cucumber'
|
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'tlb'))
|
|
4
|
+
require 'tlb/cucumber/rake/cucumber_task'
|
|
5
|
+
|
|
6
|
+
Tlb::Cucumber::Rake::CucumberTask.new(:cucumber_tests)
|
|
7
|
+
|
|
8
|
+
load 'tasks/tlb.rake'
|
|
9
|
+
desc "Run Cucumber features in a load-balanced fashion (based on environment variables)"
|
|
10
|
+
task :bal => ['tlb:start', :cucumber_tests]
|
|
11
|
+
|
|
12
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require ('test/unit/assertions')
|
|
2
|
+
|
|
3
|
+
World(Test::Unit::Assertions)
|
|
4
|
+
|
|
5
|
+
Given /There are two numbers (\d+) and (\d+)/ do |one, two|
|
|
6
|
+
instance_variable_set("@first", one)
|
|
7
|
+
instance_variable_set("@second", two)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
When /I add them together/ do
|
|
11
|
+
one = instance_variable_get("@first")
|
|
12
|
+
two = instance_variable_get("@second")
|
|
13
|
+
instance_variable_set("@sum", one.to_i + two.to_i)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Then /I should get (\d+)/ do |expected_sum|
|
|
17
|
+
assert_equal expected_sum.to_i, instance_variable_get("@sum")
|
|
18
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require ('test/unit/assertions')
|
|
2
|
+
|
|
3
|
+
World(Test::Unit::Assertions)
|
|
4
|
+
|
|
5
|
+
Given /I am wondering what the hell is the answer/ do
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
When /I ask Deep thought/ do
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Then /Deep Thought should say "(\d+)"/ do |answer|
|
|
12
|
+
assert_equal 42, answer.to_i
|
|
13
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require ('test/unit/assertions')
|
|
2
|
+
|
|
3
|
+
World(Test::Unit::Assertions)
|
|
4
|
+
|
|
5
|
+
Given /There are two numbers for subtraction (\d+) and (\d+)/ do |one, two|
|
|
6
|
+
instance_variable_set("@first", one)
|
|
7
|
+
instance_variable_set("@second", two)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
When /I subtract second from the first/ do
|
|
11
|
+
one = instance_variable_get("@first")
|
|
12
|
+
two = instance_variable_get("@second")
|
|
13
|
+
instance_variable_set("@diff", one.to_i - two.to_i)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Then /I should get the difference (\d+)/ do |expected_difference|
|
|
17
|
+
assert_equal expected_difference.to_i, instance_variable_get("@diff")
|
|
18
|
+
end
|
data/test.sh
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# this is a smart hack strictly meant for developer convinience, not for CI. -janmejay
|
|
4
|
+
|
|
5
|
+
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
|
|
6
|
+
|
|
7
|
+
sep() {
|
|
8
|
+
in_red "-----------------------------------------------------------------"
|
|
9
|
+
echo
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function in_red {
|
|
13
|
+
tput sgr0
|
|
14
|
+
tput setaf 1;
|
|
15
|
+
tput setab 7;
|
|
16
|
+
echo -n $1;
|
|
17
|
+
tput sgr0
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function show_running_with {
|
|
21
|
+
echo -e "\n"
|
|
22
|
+
sep
|
|
23
|
+
in_red "|"
|
|
24
|
+
echo -n " "
|
|
25
|
+
tput setaf 4
|
|
26
|
+
echo -n "Running tests with: "
|
|
27
|
+
tput bold;
|
|
28
|
+
tput setaf 0
|
|
29
|
+
ruby --version
|
|
30
|
+
sep
|
|
31
|
+
echo
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
run_tests_with() {
|
|
35
|
+
rvm use $1
|
|
36
|
+
show_running_with
|
|
37
|
+
rake test
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
run_tests_with ruby-1.8.7-p334@tlb
|
|
41
|
+
|
|
42
|
+
run_tests_with jruby-1.5.6@tlb
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
$name="tlb-cucumber"
|
|
2
|
+
$framework='cucumber'
|
|
3
|
+
require File.join(File.dirname(__FILE__), 'gem_common')
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
configure_tlb(s)
|
|
7
|
+
s.files = files('tests', File.join('lib', 'tlb', 'rspec'), File.join('lib', 'tlb', 'test_unit'))
|
|
8
|
+
s.add_runtime_dependency 'cucumber', '>= 0.10.2'
|
|
9
|
+
end
|
data/tlb-rspec2.gemspec
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
$name="tlb-rspec2"
|
|
2
|
+
$framework='rspec-2.x'
|
|
3
|
+
require File.join(File.dirname(__FILE__), 'gem_common')
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
configure_tlb(s)
|
|
7
|
+
s.files = files('tests', File.join('lib', 'tlb', 'test_unit'), File.join('lib', 'tlb', 'cucumber'))
|
|
8
|
+
s.add_runtime_dependency 'rspec', '>= 2.3.0'
|
|
9
|
+
end
|
|
10
|
+
|
metadata
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: tlb-cucumber
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
prerelease: false
|
|
5
|
+
segments:
|
|
6
|
+
- 0
|
|
7
|
+
- 3
|
|
8
|
+
- 1
|
|
9
|
+
version: 0.3.1
|
|
10
|
+
platform: ruby
|
|
11
|
+
authors:
|
|
12
|
+
- Janmejay Singh
|
|
13
|
+
- Pavan KS
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2011-05-11 00:00:00 +05:30
|
|
19
|
+
default_executable:
|
|
20
|
+
dependencies:
|
|
21
|
+
- !ruby/object:Gem::Dependency
|
|
22
|
+
name: open4
|
|
23
|
+
prerelease: false
|
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
segments:
|
|
29
|
+
- 1
|
|
30
|
+
- 0
|
|
31
|
+
- 1
|
|
32
|
+
version: 1.0.1
|
|
33
|
+
type: :runtime
|
|
34
|
+
version_requirements: *id001
|
|
35
|
+
- !ruby/object:Gem::Dependency
|
|
36
|
+
name: rake
|
|
37
|
+
prerelease: false
|
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
segments:
|
|
43
|
+
- 0
|
|
44
|
+
version: "0"
|
|
45
|
+
type: :runtime
|
|
46
|
+
version_requirements: *id002
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: cucumber
|
|
49
|
+
prerelease: false
|
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
segments:
|
|
55
|
+
- 0
|
|
56
|
+
- 10
|
|
57
|
+
- 2
|
|
58
|
+
version: 0.10.2
|
|
59
|
+
type: :runtime
|
|
60
|
+
version_requirements: *id003
|
|
61
|
+
description: |
|
|
62
|
+
TLB ruby implementation base, which provides support for load balancing tests written in cucumber.
|
|
63
|
+
TLB.rb test suite is not bundled, please check http://github.com/test-load-balancer/tlb.rb for tests.
|
|
64
|
+
Detailed documentation is available at http://test-load-balancer.github.com.
|
|
65
|
+
|
|
66
|
+
email: singh.janmejay@gmail.com;itspanzi@gmail.com
|
|
67
|
+
executables: []
|
|
68
|
+
|
|
69
|
+
extensions: []
|
|
70
|
+
|
|
71
|
+
extra_rdoc_files:
|
|
72
|
+
- README.markdown
|
|
73
|
+
files:
|
|
74
|
+
- .emacs_project.template
|
|
75
|
+
- .gitignore
|
|
76
|
+
- .gitmodules
|
|
77
|
+
- README.markdown
|
|
78
|
+
- Rakefile
|
|
79
|
+
- gem_common.rb
|
|
80
|
+
- lib/tasks/tlb.rake
|
|
81
|
+
- lib/tlb.rb
|
|
82
|
+
- lib/tlb/cucumber/lib/configuration_inflection.rb
|
|
83
|
+
- lib/tlb/cucumber/lib/run_data_formatter.rb
|
|
84
|
+
- lib/tlb/cucumber/lib/test_splitter.rb
|
|
85
|
+
- lib/tlb/cucumber/rake/cucumber_task.rb
|
|
86
|
+
- lib/tlb/run_data.rb
|
|
87
|
+
- lib/tlb/util.rb
|
|
88
|
+
- spike/Rakefile
|
|
89
|
+
- spike/features/step_definitions/addition.rb
|
|
90
|
+
- spike/features/step_definitions/answer.rb
|
|
91
|
+
- spike/features/step_definitions/sub.rb
|
|
92
|
+
- spike/features/sub.feature
|
|
93
|
+
- spike/features/sum.feature
|
|
94
|
+
- spike/features/the_answer.feature
|
|
95
|
+
- test.sh
|
|
96
|
+
- tlb-cucumber.gemspec
|
|
97
|
+
- tlb-rspec2.gemspec
|
|
98
|
+
- tlb-testunit.gemspec
|
|
99
|
+
- tlb-alien-g0.3.0-4-g1077d1b.jar
|
|
100
|
+
has_rdoc: true
|
|
101
|
+
homepage: http://github.com/test-load-balancer/tlb.rb
|
|
102
|
+
licenses: []
|
|
103
|
+
|
|
104
|
+
post_install_message: |
|
|
105
|
+
-------------------------------------------------------------------------
|
|
106
|
+
TLB Documentation: Detailed configuration documentation can be found at http://test-load-balancer.github.com. Documentation section in this website hosts documentation for every public release.
|
|
107
|
+
|
|
108
|
+
-------------------------------------------------------------------------
|
|
109
|
+
TLB Example(s): We maintain a directory of tlb-enabled dummy projects written in different languages using different testing and build frameworks to help new TLB users get started and provide people a working project to refer to while hooking up TLB on their project(s). Each of these projects have a shell script(named run_balanced.sh) that is meant to demonstrate a typical tlb-enabled build(by starting a local tlb server, and executing two partitions that run dummy tests locally).
|
|
110
|
+
For demonstration purpose, aforementioned shell script executes partitions in the example-project one after another(serially). However, partitions will be executed parallely on different machines in a real-world setup(hence cutting the build time).
|
|
111
|
+
We recommend playing with the configuration-variable values being set in the shell-script(s) to understand the effect different values have on load-balancing/reordering behavior. You may want to check http://test-load-balancer.github.com, which links to 'detailed documentation' that covers each configuration variable and explains its purpose, effect and implication.
|
|
112
|
+
|
|
113
|
+
Examples archive is released along-with TLB, and is available for download at http://code.google.com/p/tlb/downloads/list.
|
|
114
|
+
|
|
115
|
+
To execute the example project, drop into the example project directory(examples/rspec2_example for instance) and invoke the './run_balanced.sh'.
|
|
116
|
+
|
|
117
|
+
-------------------------------------------------------------------------
|
|
118
|
+
TLB Issue Tracker: Please report/port bugs/enhancements/feature-requests on http://code.google.com/p/tlb/issues/list. Github, Rubyforge or any other issue trackers are not monitored or updated.
|
|
119
|
+
|
|
120
|
+
-------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
rdoc_options:
|
|
123
|
+
- --charset=UTF-8
|
|
124
|
+
require_paths:
|
|
125
|
+
- lib
|
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
segments:
|
|
131
|
+
- 0
|
|
132
|
+
version: "0"
|
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
segments:
|
|
138
|
+
- 0
|
|
139
|
+
version: "0"
|
|
140
|
+
requirements: []
|
|
141
|
+
|
|
142
|
+
rubyforge_project: tlb-rb
|
|
143
|
+
rubygems_version: 1.3.6
|
|
144
|
+
signing_key:
|
|
145
|
+
specification_version: 3
|
|
146
|
+
summary: tlb-cucumber-0.3.1
|
|
147
|
+
test_files: []
|
|
148
|
+
|