tlb-rspec2 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,20 @@
1
+ require 'rspec/core/reporter'
2
+ require 'tlb/rspec/spec_formatter'
3
+
4
+ module Tlb::RSpec::ReporterInflection
5
+ def self.included base
6
+ base.class_eval do
7
+ alias_method :report_post_formatter_injection, :report
8
+ remove_method :report
9
+ end
10
+ end
11
+
12
+ def report *args, &block
13
+ @formatters << Tlb::RSpec::SpecFormatter.new(nil)
14
+ report_post_formatter_injection *args, &block
15
+ end
16
+ end
17
+
18
+ RSpec::Core::Reporter.class_eval do
19
+ include Tlb::RSpec::ReporterInflection
20
+ end
@@ -0,0 +1,44 @@
1
+ require 'rspec/core/formatters/base_formatter'
2
+ require 'tlb/run_data'
3
+ require 'stringio'
4
+
5
+ class Tlb::RSpec::SpecFormatter < RSpec::Core::Formatters::BaseFormatter
6
+ include Tlb::RunData
7
+
8
+ def initialize(*args)
9
+ super(*args)
10
+ end
11
+
12
+ def example_group_started(example_group)
13
+ suite_started(example_file_name(example_group))
14
+ end
15
+
16
+ def example_group_finished(example_group)
17
+ record_suite_data(example_group)
18
+ end
19
+
20
+ def example_passed(example)
21
+ record_suite_data(example)
22
+ end
23
+
24
+ def example_failed(example)
25
+ update_suite_failed(example_file_name(example))
26
+ end
27
+
28
+ def example_pending(example)
29
+ record_suite_data(example)
30
+ end
31
+
32
+ def start_dump
33
+ report_all_suite_data
34
+ end
35
+
36
+ private
37
+ def record_suite_data example
38
+ update_suite_data(example_file_name(example))
39
+ end
40
+
41
+ def example_file_name example
42
+ Tlb.relative_file_path(example.file_path)
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ class Tlb::RSpec::SpecTask < RSpec::Core::RakeTask
4
+ def initialize *args
5
+ path_to_tlb = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'tlb'))
6
+ super do |this|
7
+ yield this if block_given?
8
+ this.rspec_opts ||= ''
9
+ this.rspec_opts = " --require #{path_to_tlb} --require tlb/rspec/reporter_inflection " + this.rspec_opts
10
+ end
11
+ end
12
+
13
+ alias_method :rspec_files_to_run, :files_to_run
14
+
15
+ def files_to_run
16
+ balanced_and_reordered = Tlb.balance_and_order(relative_paths(rspec_files_to_run.to_a))
17
+ FileList[*balanced_and_reordered]
18
+ end
19
+
20
+ def relative_paths file_name_with_quotes
21
+ file_name_with_quotes.map { |path_with_quotes| Tlb.relative_file_path(path_with_quotes.sub(/^"/, "").sub(/"$/, "")) }
22
+ end
23
+ end
@@ -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
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,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tlb-rspec2
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
+ - !ruby/object:Gem::Dependency
53
+ name: rspec
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 2
63
+ - 3
64
+ - 0
65
+ version: 2.3.0
66
+ type: :runtime
67
+ version_requirements: *id003
68
+ description: |
69
+ TLB ruby implementation base, which provides support for load balancing tests written in rspec-2.x.
70
+ TLB_rb test suite is not bundled, please check http://github.com/test-load-balancer/tlb_rb for tests.
71
+ Detailed configuration documentation can be found at https://github.com/test-load-balancer/tlb/wiki.
72
+
73
+ email: singh.janmejay@gmail.com;itspanzi@gmail.com
74
+ executables: []
75
+
76
+ extensions: []
77
+
78
+ extra_rdoc_files:
79
+ - README.markdown
80
+ files:
81
+ - .emacs_project
82
+ - .gitignore
83
+ - .gitmodules
84
+ - README.markdown
85
+ - Rakefile
86
+ - gem_common.rb
87
+ - lib/tasks/tlb.rake
88
+ - lib/tlb.rb
89
+ - lib/tlb/rspec/reporter_inflection.rb
90
+ - lib/tlb/rspec/spec_formatter.rb
91
+ - lib/tlb/rspec/spec_task.rb
92
+ - lib/tlb/run_data.rb
93
+ - tlb-rspec2.gemspec
94
+ - tlb-testunit.gemspec
95
+ - tlb-all-gv0.2-9-g1f1a4aa.jar
96
+ has_rdoc: true
97
+ homepage: http://github.com/test-load-balancer/tlb_rb
98
+ licenses: []
99
+
100
+ post_install_message: |
101
+ -------------------------------------------------------------------------
102
+ Documentation: Detailed configuration documentation can be found at https://github.com/test-load-balancer/tlb/wiki.
103
+ -----------------------------
104
+ 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.
105
+ 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.
106
+ -----------------------------
107
+ 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.
108
+ -------------------------------------------------------------------------
109
+
110
+ rdoc_options:
111
+ - --charset=UTF-8
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ hash: 3
129
+ segments:
130
+ - 0
131
+ version: "0"
132
+ requirements: []
133
+
134
+ rubyforge_project: tlb-rb
135
+ rubygems_version: 1.3.7
136
+ signing_key:
137
+ specification_version: 3
138
+ summary: tlb-rspec2-0.1.1
139
+ test_files: []
140
+