tlb-testunit 0.1.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 ADDED
@@ -0,0 +1 @@
1
+ (setq rspec-executable "rspec")
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ TAGS
2
+ tmp
3
+ tlb_store
4
+ tlb-all*.jar
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "tlb"]
2
+ path = tlb
3
+ url = git://github.com/test-load-balancer/tlb.git
data/README.markdown ADDED
@@ -0,0 +1,33 @@
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(java 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 needs to listen to a certain TCP port so that tlb-ruby implementation 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 [https://github.com/test-load-balancer/tlb/wiki/Configuration-Variables](https://github.com/test-load-balancer/tlb/wiki/Configuration-Variables "Tlb config reference")
9
+
10
+ As of now, rspec is the only test framework that tlb_rb supports. 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
+
18
+ PATH_TO_TLB = File.join(RAILS_ROOT, 'vendor', 'plugins', 'tlb_rb', 'lib', 'tlb')
19
+ require PATH_TO_TLB
20
+ require File.join(PATH_TO_TLB, 'spec_task')
21
+
22
+ Tlb::SpecTask.new(:balanced_specs) do |t|
23
+ t.spec_files = FileList['spec/**/*_spec.rb']
24
+ t.spec_opts << "--require #{PATH_TO_TLB},#{File.join(PATH_TO_TLB, 'spec_formatter')} --format 'Tlb::SpecFormatter:/dev/null' --format nested"
25
+ end
26
+
27
+ desc "load balanced spec"
28
+ task :run_balanced => ['tlb:start', :balanced_specs]
29
+
30
+ Where run_balanced is the task you invoke at the top-level(invoked externally).
31
+
32
+ ## RSpec version compatibility
33
+ The branch '__master__' is __RSpec-2.x__ compatible. If you use __RSpec-1__(i.e. __1.3.x__ etc, please use branch named '__rspec-1__'. If you come across any bugs with eiher RSpec-2 or 1 support, please post it as an bug on the issue tracker on github project page.
data/Rakefile ADDED
@@ -0,0 +1,25 @@
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-all*.jar").each { |jar| FileUtils.rm(jar) }
18
+ sh 'ant -f tlb/build.xml package'
19
+ Dir.glob('tlb/target/tlb-all*').each { |file| FileUtils.copy(file, ".") }
20
+ end
21
+
22
+ task :package do
23
+ `gem build tlb-rspec2.gemspec`
24
+ `gem build tlb-testunit.gemspec`
25
+ end
data/gem_common.rb ADDED
@@ -0,0 +1,56 @@
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 configuration documentation can be found at https://github.com/test-load-balancer/tlb/wiki.
14
+ END
15
+ POST_INSTALL_MESSAGE = <<END
16
+ -------------------------------------------------------------------------
17
+ Documentation: Detailed configuration documentation can be found at https://github.com/test-load-balancer/tlb/wiki.
18
+ -----------------------------
19
+ Example: https://github.com/test-load-balancer/sample_projects has examples projects and shell script to demonstrate a typical build(by starting a local tlb server, and executing two partitions locally). While partitions in these examples execute one after another, in an actual CI/pre-checkin build, they will actually run parallely on different machines.
20
+ Its a good idea to play with the environment variables values being used in these shell-scripts to understand how they affect TLB's behaviour. You may want to check https://github.com/test-load-balancer/tlb/wiki/Configuration-Variables, which documents each variable and its effect.
21
+ -----------------------------
22
+ Issue tracker: Please report bugs/enhancements/feature-requests at http://code.google.com/p/tlb/issues/list. Github, Rubyforge or any other issue trackers are not monitored or updated.
23
+ -------------------------------------------------------------------------
24
+ END
25
+ RUBYFORGE_PROJECT = "tlb-rb"
26
+ RUBYGEMS_VERSION = "1.3.7"
27
+
28
+ def files *exclude_dirs
29
+ files = `git ls-files`.split("\n")
30
+ files += Dir.glob(File.join(File.dirname(__FILE__), "*.jar")).map { |path| File.basename(path) }
31
+ exclude_dirs.inject(files) { |files, dir| files - `git ls-files #{dir}`.split("\n") }
32
+ end
33
+
34
+
35
+ def configure_tlb s
36
+ s.name = $name
37
+ s.version = TAG_VERSION
38
+ s.platform = Gem::Platform::RUBY
39
+ s.authors = AUTHORS
40
+ s.email = EMAIL
41
+ s.homepage = HOME_PAGE
42
+ s.summary = SUMMARY
43
+ s.description = DESC
44
+
45
+ s.rubyforge_project = RUBYFORGE_PROJECT
46
+ s.rubygems_version = RUBYGEMS_VERSION
47
+
48
+ s.post_install_message = POST_INSTALL_MESSAGE
49
+
50
+ s.extra_rdoc_files = [ "README.markdown" ]
51
+ s.rdoc_options = ["--charset=UTF-8"]
52
+ s.require_path = "lib"
53
+
54
+ s.add_runtime_dependency 'open4', '>= 1.0.1'
55
+ s.add_runtime_dependency 'rake'
56
+ end
@@ -0,0 +1,12 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'tlb'))
2
+
3
+ namespace :tlb do
4
+ task :start do
5
+ Tlb.start_server
6
+ at_exit do
7
+ $stderr.write "terminating tlb server\n"
8
+ Tlb.stop_server
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,53 @@
1
+ module Tlb::RunData
2
+ class Suite < Struct.new(:identity, :start_time, :end_time, :failed)
3
+ MILLS_PER_SEC = 1000
4
+
5
+ def initialize(identity, start_time)
6
+ super(identity, start_time, start_time, false)
7
+ end
8
+
9
+ def run_time
10
+ ((end_time - start_time)*MILLS_PER_SEC).to_i
11
+ end
12
+
13
+ def for_id? new_identity
14
+ identity == new_identity
15
+ end
16
+
17
+ def report_to_tlb
18
+ Tlb.suite_time(identity, run_time)
19
+ Tlb.suite_result(identity, failed)
20
+ end
21
+ end
22
+
23
+ def suite_started identity
24
+ unless (suites.last && suites.last.for_id?(identity))
25
+ suites << Tlb::RunData::Suite.new(identity, Time.now)
26
+ end
27
+ end
28
+
29
+ def update_suite_data identity
30
+ 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)
31
+ suite.end_time = Time.now
32
+ block_given? && yield(suite)
33
+ end
34
+ end
35
+
36
+ def update_suite_failed identity
37
+ update_suite_data(identity) do |suite|
38
+ suite.failed = true
39
+ end
40
+ end
41
+
42
+ def report_all_suite_data
43
+ suites.each do |suite_time|
44
+ suite_time.report_to_tlb
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def suites
51
+ @suites ||= []
52
+ end
53
+ end
@@ -0,0 +1,27 @@
1
+ require 'tlb/test_unit/test_splitter'
2
+ require 'tlb/test_unit/test_observer'
3
+ require 'test/unit/ui/testrunnermediator'
4
+
5
+ module Tlb::TestUnit::MediatorInflection
6
+ def self.included base
7
+ base.send(:alias_method, :run_suite_without_tlb, :run_suite)
8
+ base.send(:remove_method, :run_suite)
9
+ base.send(:include, InstanceMethods)
10
+
11
+ base.send(:include, Tlb::TestUnit::TestSplitter)
12
+ base.send(:include, Tlb::TestUnit::TestObserver)
13
+ end
14
+
15
+ module InstanceMethods
16
+ def run_suite
17
+ register_observers
18
+ prune_suite
19
+ run_suite_without_tlb
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ Test::Unit::UI::TestRunnerMediator.class_eval do
26
+ include Tlb::TestUnit::MediatorInflection
27
+ end
@@ -0,0 +1,36 @@
1
+ require 'tlb/run_data'
2
+
3
+ module Tlb::TestUnit::TestObserver
4
+ class TestUnitRunData
5
+ include Tlb::RunData
6
+
7
+ def suite_failed(failure)
8
+ update_suite_failed(suite_name_for(failure.test_name))
9
+ end
10
+
11
+ def suite_name_for(test_name)
12
+ test_name.scan(/\((.+)\)$/).flatten.first
13
+ end
14
+ end
15
+
16
+ def register_observers
17
+ run_data = TestUnitRunData.new
18
+
19
+ add_listener(Test::Unit::TestResult::FAULT) do |fault|
20
+ run_data.suite_failed(fault)
21
+ end
22
+
23
+ add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED) do |*elapsed_time|
24
+ run_data.report_all_suite_data
25
+ end
26
+
27
+ add_listener(Test::Unit::TestSuite::STARTED) do |suite_name|
28
+ run_data.suite_started(suite_name)
29
+ end
30
+
31
+
32
+ add_listener(Test::Unit::TestSuite::FINISHED) do |suite_name|
33
+ run_data.update_suite_data(suite_name)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,8 @@
1
+ module Tlb::TestUnit::TestSplitter
2
+ def prune_suite
3
+ name_suite_map = @suite.tests.inject({}) { |map, test| map[test.name] = test; map }
4
+ names_to_run = Tlb.balance_and_order(@suite.tests.map { |test| test.name })
5
+ tests_to_run = names_to_run.inject([]) { |tests, name| tests << name_suite_map[name]; tests }
6
+ @suite.instance_variable_set('@tests', tests_to_run)
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ class Tlb::TestUnit::TestTask < Rake::TestTask
5
+ def initialize *args
6
+ super do |this|
7
+ this.ruby_opts.unshift " -r#{File.join('tlb', 'test_unit', 'mediator_inflection')} "
8
+ this.ruby_opts.unshift " -r#{File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'tlb'))} "
9
+ yield this if block_given?
10
+ end
11
+ end
12
+ end
data/lib/tlb.rb ADDED
@@ -0,0 +1,142 @@
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]
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.wait_for_start
48
+ loop do
49
+ begin
50
+ TCPSocket.new(host, port)
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.balance_and_order file_set
71
+ ensure_server_running
72
+ Balancer.send(Balancer::BALANCE_PATH, file_set.join("\n")).split("\n")
73
+ end
74
+
75
+ def self.suite_result suite_name, result
76
+ ensure_server_running
77
+ Balancer.send(Balancer::SUITE_RESULT_REPORTING_PATH, "#{suite_name}: #{result}")
78
+ end
79
+
80
+ def self.suite_time suite_name, mills
81
+ ensure_server_running
82
+ Balancer.send(Balancer::SUITE_TIME_REPORTING_PATH, "#{suite_name}: #{mills}")
83
+ end
84
+
85
+ def self.fail_as_balancer_is_not_running
86
+ raise "Balancer server must be started before tests are run."
87
+ end
88
+
89
+ def self.ensure_server_running
90
+ server_running? || fail_as_balancer_is_not_running
91
+ end
92
+
93
+ def self.server_running?
94
+ Balancer.running?
95
+ end
96
+
97
+ def self.root_dir
98
+ File.expand_path(File.join(File.dirname(__FILE__), ".."))
99
+ end
100
+
101
+ def self.tlb_jar
102
+ File.expand_path(Dir.glob(File.join(root_dir, "tlb-all*")).first)
103
+ end
104
+
105
+ def self.server_command
106
+ "java -jar #{tlb_jar}"
107
+ end
108
+
109
+ def self.write_to_file file_var, clob
110
+ File.open(ENV[file_var], 'a') do |h|
111
+ h.write(clob)
112
+ end
113
+ end
114
+
115
+ def self.start_server
116
+ ENV[TLB_APP] = 'com.github.tlb.balancer.BalancerInitializer'
117
+ @pid, input, out, err = Open4.popen4(server_command)
118
+ @out_pumper = stream_pumper_for(out, TLB_OUT_FILE)
119
+ @err_pumper = stream_pumper_for(err, TLB_ERR_FILE)
120
+ Balancer.wait_for_start
121
+ end
122
+
123
+ def self.stream_pumper_for stream, dump_file
124
+ Thread.new do
125
+ loop do
126
+ stream.eof? || write_to_file(dump_file, stream.read)
127
+ Thread.current[:stop_pumping] && break
128
+ sleep 1
129
+ end
130
+ end
131
+ end
132
+
133
+ def self.stop_server
134
+ Process.kill(Signal.list["TERM"], @pid)
135
+ @pid = nil
136
+ @out_pumper[:stop_pumping] = true
137
+ @err_pumper[:stop_pumping] = true
138
+ @out_pumper.join
139
+ @err_pumper.join
140
+ Process.wait
141
+ end
142
+ end
Binary file
@@ -0,0 +1,11 @@
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
+
8
+ s.files = files('tests', File.join('lib', 'tlb', 'test_unit'))
9
+
10
+ s.add_runtime_dependency 'rspec', '>= 2.3.0'
11
+ end
@@ -0,0 +1,9 @@
1
+ $name="tlb-testunit"
2
+ $framework='test::unit'
3
+ require File.join(File.dirname(__FILE__), 'gem_common')
4
+
5
+ Gem::Specification.new do |s|
6
+ configure_tlb(s)
7
+
8
+ s.files = files('tests', File.join('lib', 'tlb', 'rspec'))
9
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tlb-testunit
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Janmejay Singh
14
+ - Pavan KS
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-12-22 00:00:00 +05:30
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: open4
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 21
31
+ segments:
32
+ - 1
33
+ - 0
34
+ - 1
35
+ version: 1.0.1
36
+ type: :runtime
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ name: rake
40
+ prerelease: false
41
+ requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 3
47
+ segments:
48
+ - 0
49
+ version: "0"
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ description: |
53
+ TLB ruby implementation base, which provides support for load balancing tests written in test::unit.
54
+ TLB_rb test suite is not bundled, please check http://github.com/test-load-balancer/tlb_rb for tests.
55
+ Detailed configuration documentation can be found at https://github.com/test-load-balancer/tlb/wiki.
56
+
57
+ email: singh.janmejay@gmail.com;itspanzi@gmail.com
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ extra_rdoc_files:
63
+ - README.markdown
64
+ files:
65
+ - .emacs_project
66
+ - .gitignore
67
+ - .gitmodules
68
+ - README.markdown
69
+ - Rakefile
70
+ - gem_common.rb
71
+ - lib/tasks/tlb.rake
72
+ - lib/tlb.rb
73
+ - lib/tlb/run_data.rb
74
+ - lib/tlb/test_unit/mediator_inflection.rb
75
+ - lib/tlb/test_unit/test_observer.rb
76
+ - lib/tlb/test_unit/test_splitter.rb
77
+ - lib/tlb/test_unit/test_task.rb
78
+ - tlb-rspec2.gemspec
79
+ - tlb-testunit.gemspec
80
+ - tlb-all-gv0.2-9-g1f1a4aa.jar
81
+ has_rdoc: true
82
+ homepage: http://github.com/test-load-balancer/tlb_rb
83
+ licenses: []
84
+
85
+ post_install_message: |
86
+ -------------------------------------------------------------------------
87
+ Documentation: Detailed configuration documentation can be found at https://github.com/test-load-balancer/tlb/wiki.
88
+ -----------------------------
89
+ Example: https://github.com/test-load-balancer/sample_projects has examples projects and shell script to demonstrate a typical build(by starting a local tlb server, and executing two partitions locally). While partitions in these examples execute one after another, in an actual CI/pre-checkin build, they will actually run parallely on different machines.
90
+ Its a good idea to play with the environment variables values being used in these shell-scripts to understand how they affect TLB's behaviour. You may want to check https://github.com/test-load-balancer/tlb/wiki/Configuration-Variables, which documents each variable and its effect.
91
+ -----------------------------
92
+ Issue tracker: Please report bugs/enhancements/feature-requests at http://code.google.com/p/tlb/issues/list. Github, Rubyforge or any other issue trackers are not monitored or updated.
93
+ -------------------------------------------------------------------------
94
+
95
+ rdoc_options:
96
+ - --charset=UTF-8
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project: tlb-rb
120
+ rubygems_version: 1.3.7
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: tlb-testunit-0.1.1
124
+ test_files: []
125
+