tlb-core 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown ADDED
@@ -0,0 +1,46 @@
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 the type of server it has to talk to etc).
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
+ __tlb.rb__ supports RSpec(1.x and 2.x), Cucumber and Test::Unit, which are the most widely used testing frameworks in the Ruby world.
11
+
12
+ __tlb.rb__ is fully compatible with both Ruby 1.9 and 1.8 across __MRI__ and __JRuby__. However, 1.9 support will be available only version 0.3.2 onwards.
13
+
14
+ We test __tlb.rb__ on MRI and JRuby, however it should work with other flavours of Ruby(like REE) as well.
15
+
16
+ ## Getting tlb.rb:
17
+
18
+ __RSpec2__ support(both __1.9__ and __1.8__):
19
+ $ gem install tlb-rspec2
20
+
21
+ __Cucumber__ support(both __1.9__ and __1.8__):
22
+ $ gem install tlb-cucumber
23
+
24
+ __RSpec1__ support(both __1.9__ and __1.8__):
25
+ $ gem install tlb-rspec1
26
+
27
+ __Test::Unit__ support on Ruby __1.9__:(available 0.3.2 onwards)
28
+ $ gem install tlb-testunit19
29
+
30
+ __Test::Unit__ support on Ruby __1.8__:(available 0.3.2 onwards)
31
+ $ gem install tlb-testunit18
32
+
33
+ If a version older than 0.3.2, please use
34
+ $ gem install tlb-testunit
35
+ for Test::Unit support.
36
+
37
+ ## Setting it up for your project
38
+
39
+ Please refer documentation on [http://test-load-balancer.github.com/](http://test-load-balancer.github.com/ "TLB Website") for detailed setup instructions.
40
+
41
+ Documentation also explains TLB concepts and customization options in fair amount of detail. We highly recomend going through the TLB documentation.
42
+
43
+ ## Want a feature? Found a bug?
44
+
45
+ Post it at [Issue Tracker](http://code.google.com/p/tlb/issues/list "Issue Tracker").
46
+
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'tlb'
3
+
4
+ namespace :tlb do
5
+ task :start do
6
+ Tlb.start_server
7
+ at_exit do
8
+ $stderr.write "terminating tlb server\n"
9
+ Tlb.stop_server
10
+ end
11
+ end
12
+ end
13
+
data/core/lib/tlb.rb ADDED
@@ -0,0 +1,243 @@
1
+ require 'rubygems'
2
+ require 'open4'
3
+ require 'net/http'
4
+ require 'timeout'
5
+
6
+ module Tlb
7
+ TLB_OUT_FILE = 'TLB_OUT_FILE'
8
+ TLB_ERR_FILE = 'TLB_ERR_FILE'
9
+ TLB_APP = 'TLB_APP'
10
+ DEFAULT_TLB_BALANCER_STARTUP_TIME = '120'
11
+
12
+ module Balancer
13
+ TLB_BALANCER_PORT = 'TLB_BALANCER_PORT'
14
+ BALANCE_PATH = '/balance'
15
+ SUITE_TIME_REPORTING_PATH = '/suite_time'
16
+ SUITE_RESULT_REPORTING_PATH = '/suite_result'
17
+
18
+ def self.host
19
+ 'localhost'
20
+ end
21
+
22
+ def self.port
23
+ ENV[TLB_BALANCER_PORT] || '8019'
24
+ end
25
+
26
+ def self.send path, data
27
+ Net::HTTP.start(host, port) do |h|
28
+ res = h.post(path, data)
29
+ res.value
30
+ res.body
31
+ end
32
+ end
33
+
34
+ def self.get path
35
+ Net::HTTP.get_response(host, path, port).body
36
+ end
37
+
38
+ def self.running?
39
+ get("/control/status") == "RUNNING"
40
+ rescue
41
+ false
42
+ end
43
+
44
+ def self.terminate
45
+ get("/control/suicide")
46
+ end
47
+
48
+ def self.wait_for_start
49
+ loop do
50
+ begin
51
+ break if running?
52
+ rescue
53
+ #ignore
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ module RSpec
60
+ end
61
+
62
+ module TestUnit
63
+ end
64
+
65
+ def self.relative_file_path file_name
66
+ abs_file_name = File.expand_path(file_name)
67
+ rel_file_name = abs_file_name.sub(/^#{Dir.pwd}/, '.')
68
+ end
69
+
70
+ def self.relative_file_paths file_names
71
+ file_names.map { |file_name| relative_file_path(file_name) }
72
+ end
73
+
74
+ def self.balance_and_order file_set
75
+ ensure_server_running
76
+ Balancer.send(Balancer::BALANCE_PATH, file_set.join("\n")).split("\n")
77
+ end
78
+
79
+ def self.suite_result suite_name, result
80
+ ensure_server_running
81
+ Balancer.send(Balancer::SUITE_RESULT_REPORTING_PATH, "#{suite_name}: #{result}")
82
+ end
83
+
84
+ def self.suite_time suite_name, mills
85
+ ensure_server_running
86
+ Balancer.send(Balancer::SUITE_TIME_REPORTING_PATH, "#{suite_name}: #{mills}")
87
+ end
88
+
89
+ def self.fail_as_balancer_is_not_running
90
+ raise "Balancer server must be started before tests are run."
91
+ end
92
+
93
+ def self.ensure_server_running
94
+ server_running? || fail_as_balancer_is_not_running
95
+ end
96
+
97
+ def self.server_running?
98
+ Balancer.running?
99
+ end
100
+
101
+ def self.root_dir
102
+ File.expand_path(File.join(File.dirname(__FILE__), ".."))
103
+ end
104
+
105
+ def self.tlb_jar
106
+ File.expand_path(Dir.glob(File.join(root_dir, "tlb-alien*")).first)
107
+ end
108
+
109
+ def self.server_command
110
+ "java -jar #{tlb_jar}"
111
+ end
112
+
113
+ def self.can_fork?
114
+ RUBY_PLATFORM != 'java'
115
+ end
116
+
117
+ class BalancerProcess
118
+ class StreamPumper
119
+ def initialize stream, file
120
+ @stream, @file = stream, file
121
+ @thd = Thread.new { pump }
122
+ end
123
+
124
+ def pump
125
+ loop do
126
+ data_available? && flush_stream
127
+ Thread.current[:stop_pumping] && break
128
+ sleep 0.1
129
+ end
130
+ end
131
+
132
+ def flush_stream
133
+ File.open(ENV[@file], 'a') do |h|
134
+ h.write(read)
135
+ end
136
+ end
137
+
138
+ def stop_pumping!
139
+ @thd[:stop_pumping] = true
140
+ @thd.join
141
+ end
142
+ end
143
+
144
+ def initialize server_command
145
+ pumper_type, out, err = start(server_command)
146
+ @out_pumper = pumper_type.new(out, TLB_OUT_FILE)
147
+ @err_pumper = pumper_type.new(err, TLB_ERR_FILE)
148
+ end
149
+
150
+ def stop_pumping
151
+ @out_pumper.stop_pumping!
152
+ @err_pumper.stop_pumping!
153
+ end
154
+
155
+ def die
156
+ Balancer.terminate
157
+ stop_pumping
158
+ end
159
+ end
160
+
161
+ class ForkBalancerProcess < BalancerProcess
162
+ def start server_command
163
+ @pid, input, out, err = Open4.popen4(server_command)
164
+ unless (out)
165
+ raise "out was nil"
166
+ end
167
+ return Class.new(StreamPumper) do
168
+ def data_available?
169
+ not @stream.eof?
170
+ end
171
+
172
+ def read
173
+ @stream.read
174
+ end
175
+ end, out, err
176
+ end
177
+
178
+ def die
179
+ super
180
+ @pid = nil
181
+ Process.wait
182
+ end
183
+ end
184
+
185
+ class JavaBalancerProcess < BalancerProcess
186
+ def start server_command
187
+ require 'java'
188
+ pb = java.lang.ProcessBuilder.new(server_command.split)
189
+ ENV.each do |key, val|
190
+ pb.environment[key] = val
191
+ end
192
+ @process = pb.start()
193
+ return Class.new(StreamPumper) do
194
+ def data_available?
195
+ @stream.ready
196
+ end
197
+
198
+ def read
199
+ @stream.read_line
200
+ end
201
+
202
+ def stop_pumping!
203
+ super
204
+ @stream.close
205
+ end
206
+ end, buf_reader(@process.input_stream), buf_reader(@process.error_stream)
207
+ end
208
+
209
+ def buf_reader stream
210
+ java.io.BufferedReader.new(java.io.InputStreamReader.new(stream))
211
+ end
212
+
213
+ def die
214
+ super
215
+ @process.destroy
216
+ @process.waitFor
217
+ @process = nil
218
+ end
219
+ end
220
+
221
+ def self.balancer_process_type
222
+ can_fork? ? ForkBalancerProcess : JavaBalancerProcess
223
+ end
224
+
225
+ def self.max_startup_time
226
+ (ENV['TLB_BALANCER_STARTUP_MAXTIME'] || DEFAULT_TLB_BALANCER_STARTUP_TIME).to_i
227
+ end
228
+
229
+ def self.start_server
230
+ Timeout::timeout(max_startup_time) do
231
+ ENV[TLB_APP] = 'tlb.balancer.BalancerInitializer'
232
+ bal_klass = balancer_process_type
233
+ @balancer_process = bal_klass.new(server_command)
234
+ Balancer.wait_for_start
235
+ end
236
+ rescue Timeout::Error => e
237
+ raise "TLB server failed to start in 2 seconds. This usually happens when TLB configuration(environment variables) is incorrect. Please check your environment variable configuration."
238
+ end
239
+
240
+ def self.stop_server
241
+ @balancer_process.die
242
+ end
243
+ end
@@ -0,0 +1,55 @@
1
+ require '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
@@ -0,0 +1,15 @@
1
+ require '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 str
9
+ "'#{escape_quote(str)}'"
10
+ end
11
+
12
+ def self.escape_quote str
13
+ str.gsub(/'/, "\\'")
14
+ end
15
+ end
Binary file
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tlb-core
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.3.2
6
+ platform: ruby
7
+ authors:
8
+ - Janmejay Singh
9
+ - Pavan KS
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2011-05-27 00:00:00 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rake
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: open4
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: 1.0.1
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ description: |
39
+ TLB-Ruby base library that provides common test-load-balancing infrastructure for Ruby testing tools. Core in itself is framework agnostic. It exposes APIs that allow any framework specific libraries to load-balance.
40
+
41
+ email: singh.janmejay@gmail.com;itspanzi@gmail.com
42
+ executables: []
43
+
44
+ extensions: []
45
+
46
+ extra_rdoc_files:
47
+ - README.markdown
48
+ files:
49
+ - core/lib/tasks/tlb.rake
50
+ - core/lib/tlb.rb
51
+ - core/lib/tlb/run_data.rb
52
+ - core/lib/tlb/util.rb
53
+ - ./core/tlb-alien-0.3.2.jar
54
+ - README.markdown
55
+ homepage: http://github.com/test-load-balancer/tlb.rb
56
+ licenses: []
57
+
58
+ post_install_message: |
59
+ =========================================================================
60
+ 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.
61
+
62
+ -------------------------------------------------------------------------
63
+ TLB Setup: You'll need a TLB-Server in your network that is reachable over the network from the machines you use to execute your project's test-suite. Please refer the TLB documentation for details.
64
+
65
+ -------------------------------------------------------------------------
66
+ Note: Core is just the base library that implements common infrastructure for test-load-balancing in Ruby and is completely testing-framework agnostic. It exposes APIs that allow other ruby libraries to load-balance tests. You'll need to install one of the testing-framework specific libraries to make use of it.
67
+
68
+ =========================================================================
69
+
70
+ rdoc_options:
71
+ - --charset=UTF-8
72
+ require_paths:
73
+ - core/lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ requirements: []
87
+
88
+ rubyforge_project: tlb-rb
89
+ rubygems_version: 1.8.3
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: tlb-core-0.3.2
93
+ test_files: []
94
+