tlb-rspec2 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+