specjour 0.2.2 → 0.2.3

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/History.markdown CHANGED
@@ -1,6 +1,18 @@
1
1
  History
2
2
  =======
3
3
 
4
+ 0.2.3
5
+ -----
6
+ *2010-04-25*
7
+
8
+ * [fixed] Absolute paths in rsyncd.conf restrict portability. The rsync daemon
9
+ completely fails when it can't find the path to serve which typically happens
10
+ running specjour on another computer. Remove your rsyncd.conf to regenerate a
11
+ new one. Back it up first if you've made changes to it.
12
+ **Backwards Incompatible**
13
+
14
+ * [fixed] CPU core detection works on OSX Core i7 (thanks Hashrocket!)
15
+
4
16
  0.2.2
5
17
  -----
6
18
  *2010-04-22*
data/README.markdown CHANGED
@@ -37,19 +37,31 @@ Run the rake task to distribute the features among the managers you started.
37
37
  $ rake specjour:cucumber
38
38
 
39
39
  ## Rails
40
- Edit your config/environment.rb
41
-
42
- config.gem 'specjour'
43
-
44
40
  Each worker should run their specs in an isolated database. Modify the test database name in your `config/database.yml` to include the following environment variable (Influenced by [parallel_tests](http://github.com/grosser/parallel_tests)):
45
41
 
46
42
  test:
47
43
  database: blog_test<%=ENV['TEST_ENV_NUMBER']%>
48
44
 
49
- Each worker will attempt to clear its database tables before running any specs via `DELETE FROM <table_name>;`. Additionally, test databases will be created if they don't exist (i.e. `CREATE DATABASE blog_test8` for the 8th worker) and will load your schema when it has fallen behind.
45
+ Add the specjour gem to your project:
46
+
47
+ config.gem 'specjour'
48
+
49
+ Doing this enables a rails plugin wherein each worker will attempt to clear its database tables before running any specs via `DELETE FROM <table_name>;`. Additionally, test databases will be created if they don't exist (i.e. `CREATE DATABASE blog_test8` for the 8th worker) and your schema will be loaded when the database is out of date.
50
+
51
+ ### Customizing database setup
52
+ If the plugin doesn't set up the database properly for your test suite, bypass it entirely. Remove specjour as a project gem and create your own initializer to setup the database. Specjour sets the environment variable PREPARE_DB when it runs your specs so you can look for that when setting up the database.
53
+
54
+ # config/initializers/specjour.rb
55
+
56
+ if ENV['PREPARE_DB']
57
+ load 'Rakefile'
58
+
59
+ # clear the db and load db/seeds.rb
60
+ Rake::Task['db:reset'].invoke
61
+ end
50
62
 
51
63
  ## Only listen to supported projects
52
- By default, a manager will listen to all projects trying to distribute specs over the network. Sometimes you'll only want a manager to respond to one specific spec suite. You can accomplish this with the `--projects` flags.
64
+ By default, a manager will listen to all projects trying to distribute specs over the network. Sometimes you'll only want a manager to respond to one specific spec suite. You can accomplish this with the `--projects` flag.
53
65
 
54
66
  $ specjour --projects bizconf # only run specs for the bizconf project
55
67
 
@@ -72,10 +84,14 @@ Distributed testing doesn't have to happen over multiple machines, just multiple
72
84
  * shayarnett - Cucumber support, pairing and other various patches
73
85
  * voxdolo - Endless support, alpha testing, various patches
74
86
  * leshill - Made rsync daemon configurable
87
+ * testjour - Ripped off your name
88
+ * parallel_tests - Made my test suite twice as fast
75
89
 
76
90
  ## Note on Patches/Pull Requests
77
91
 
78
92
  * Fork the project.
93
+ * `$ source .dev` to ensure you're using the local specjour binary, not the
94
+ rubygems version
79
95
  * Make your feature addition or bug fix.
80
96
  * Add tests for it. This is important so I don't break it in a
81
97
  future version unintentionally.
data/Rakefile CHANGED
@@ -13,6 +13,7 @@ begin
13
13
  gem.add_dependency "dnssd", "1.3.1"
14
14
  gem.add_dependency "rspec"
15
15
  gem.add_development_dependency "rspec", "1.3.0"
16
+ gem.add_development_dependency "rr", "0.10.11"
16
17
  gem.add_development_dependency "yard", "0.5.3"
17
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
19
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.2.3
data/lib/specjour/cpu.rb CHANGED
@@ -1,13 +1,19 @@
1
1
  module Specjour
2
2
  module CPU
3
- # inspired by github.com/grosser/parallel
4
3
  def self.cores
5
4
  case RUBY_PLATFORM
6
5
  when /darwin/
7
- `hwprefs cpu_count`.to_i
6
+ command('hostinfo') =~ /^(\d+).+logically/
7
+ $1.to_i
8
8
  when /linux/
9
- `grep --count processor /proc/cpuinfo`.to_i
9
+ command('grep --count processor /proc/cpuinfo').to_i
10
10
  end
11
11
  end
12
+
13
+ protected
14
+
15
+ def self.command(cmd)
16
+ %x(#{cmd})
17
+ end
12
18
  end
13
19
  end
@@ -61,6 +61,7 @@ module Specjour
61
61
 
62
62
  def start
63
63
  drb_start
64
+ puts "Workers ready: #{worker_size}"
64
65
  bonjour_announce
65
66
  Signal.trap('INT') { puts; puts "Shutting down manager..."; exit }
66
67
  DRb.thread.join
@@ -3,6 +3,12 @@ module Specjour
3
3
  require 'fileutils'
4
4
  include SocketHelpers
5
5
 
6
+ # Corresponds to the version of specjour that changed the configuration
7
+ # file.
8
+ CONFIG_VERSION = "0.2.3".freeze
9
+ CONFIG_FILE_NAME = "rsyncd.conf"
10
+ PID_FILE_NAME = "rsyncd.pid"
11
+
6
12
  attr_reader :project_path, :project_name
7
13
 
8
14
  def initialize(project_path, project_name)
@@ -15,7 +21,7 @@ module Specjour
15
21
  end
16
22
 
17
23
  def config_file
18
- @config_file ||= File.join(config_directory, "rsyncd.conf")
24
+ @config_file ||= File.join(config_directory, CONFIG_FILE_NAME)
19
25
  end
20
26
 
21
27
  def pid
@@ -25,13 +31,15 @@ module Specjour
25
31
  end
26
32
 
27
33
  def pid_file
28
- File.join(config_directory, "rsync_daemon.pid")
34
+ File.join(config_directory, PID_FILE_NAME)
29
35
  end
30
36
 
31
37
  def start
32
38
  write_config
33
- system *command
34
- at_exit { stop }
39
+ Dir.chdir(project_path) do
40
+ Kernel.system *command
41
+ end
42
+ Kernel.at_exit { stop }
35
43
  end
36
44
 
37
45
  def stop
@@ -43,38 +51,56 @@ module Specjour
43
51
 
44
52
  protected
45
53
 
54
+ def command
55
+ ["rsync", "--daemon", "--config=#{config_file}", "--port=8989"]
56
+ end
57
+
58
+ def check_config_version
59
+ File.read(config_file) =~ /\A# (\d+.\d+.\d+)/
60
+ if out_of_date? Regexp.last_match(1)
61
+ $stderr.puts <<-WARN
62
+
63
+ Specjour has made changes to the way #{CONFIG_FILE_NAME} is generated.
64
+ Back up '#{config_file}'
65
+ and re-run the dispatcher to generate the new config file.
66
+
67
+ WARN
68
+ end
69
+ end
70
+
71
+ def out_of_date?(version)
72
+ CONFIG_VERSION != version
73
+ end
74
+
46
75
  def write_config
47
- unless File.exists? config_file
76
+ if File.exists? config_file
77
+ check_config_version
78
+ else
48
79
  FileUtils.mkdir_p config_directory
49
-
50
80
  File.open(config_file, 'w') do |f|
51
81
  f.write config
52
82
  end
53
83
  end
54
84
  end
55
85
 
56
- def command
57
- ["rsync", "--daemon", "--config=#{config_file}", "--port=8989"]
58
- end
59
-
60
86
  def config
61
87
  <<-CONFIG
62
- # #{Specjour::VERSION}
63
- # Anonymous rsync daemon config for #{project_name}
88
+ # #{CONFIG_VERSION}
89
+ # Rsync daemon config for #{project_name}
64
90
  #
65
91
  # Serve this project with the following command:
66
- # $ #{command.join(' ')}
92
+ # $ #{(command | ['--no-detach']).join(' ')}
67
93
  #
68
94
  # Rsync with the following command:
69
- # $ rsync -a --port=8989 #{hostname}::#{project_name} ~/#{project_name}
95
+ # $ rsync -a --port=8989 #{hostname}::#{project_name} /tmp/#{project_name}
70
96
  #
71
97
  use chroot = no
72
98
  timeout = 20
73
99
  read only = yes
74
- pid file = #{pid_file}
100
+ pid file = ./.specjour/#{PID_FILE_NAME}
75
101
 
76
102
  [#{project_name}]
77
- path = #{project_path}
103
+ path = .
78
104
  exclude = .git* .specjour doc tmp/* log script
79
105
  CONFIG
80
106
  end
data/lib/specjour.rb CHANGED
@@ -23,7 +23,7 @@ module Specjour
23
23
  autoload :Cucumber, 'specjour/cucumber'
24
24
  autoload :Rspec, 'specjour/rspec'
25
25
 
26
- VERSION = "0.2.2".freeze
26
+ VERSION = "0.2.3".freeze
27
27
 
28
28
  class Error < StandardError; end
29
29
 
data/spec/cpu_spec.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Specjour::CPU do
4
+ context "on a Mac" do
5
+ let(:hostinfo) do
6
+ %(
7
+ Mach kernel version:
8
+ Darwin Kernel Version 10.2.0: Tue Nov 3 10:37:10 PST 2009; root:xnu-1486.2.11~1/RELEASE_I386
9
+ Kernel configured for up to 2 processors.
10
+ 2 processors are physically available.
11
+ 220 processors are logically available.
12
+ Processor type: i486 (Intel 80486)
13
+ Processors active: 0 1
14
+ Primary memory available: 4.00 gigabytes
15
+ Default processor set: 72 tasks, 310 threads, 2 processors
16
+ Load average: 0.09, Mach factor: 1.90
17
+ )
18
+ end
19
+
20
+ before do
21
+ stub(Specjour::CPU).command.returns(hostinfo)
22
+ end
23
+
24
+ it "returns the number of logically available processors" do
25
+ Specjour::CPU.cores.should == 220
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Specjour::Manager do
4
+ describe "#available_for?" do
5
+ it "is available for all projects by default" do
6
+ subject.available_for?(rand.to_s).should be_true
7
+ end
8
+
9
+ it "is available for one project" do
10
+ manager = Specjour::Manager.new :registered_projects => %w(one)
11
+ manager.available_for?('one').should be_true
12
+ end
13
+
14
+ it "is available for many projects" do
15
+ manager = Specjour::Manager.new :registered_projects => %w(one two)
16
+ manager.available_for?('one').should be_true
17
+ manager.available_for?('two').should be_true
18
+ end
19
+ end
20
+ end
@@ -6,32 +6,31 @@ describe Specjour::RsyncDaemon do
6
6
  end
7
7
 
8
8
  before do
9
- stub(:system)
10
- stub(:at_exit)
11
- subject.stub(:write_config)
9
+ stub(Kernel).system
10
+ stub(Kernel).at_exit
11
+ stub(Dir).chdir
12
+ stub(File).open
13
+ stub(File).read
12
14
  end
13
15
 
14
- describe "#config_directory" do
15
- specify { subject.config_directory.should == '/tmp/seasonal/.specjour' }
16
- end
17
-
18
- describe "#config_file" do
19
- specify { subject.config_file.should == '/tmp/seasonal/.specjour/rsyncd.conf' }
20
- end
16
+ specify { subject.config_directory.should == '/tmp/seasonal/.specjour' }
17
+ specify { subject.config_file.should == '/tmp/seasonal/.specjour/rsyncd.conf' }
21
18
 
22
19
  describe "#start" do
23
20
  it "writes the config" do
24
- subject.should_receive(:write_config)
21
+ mock(subject).write_config
25
22
  subject.start
26
23
  end
27
24
 
28
- it "executes the system command" do
29
- subject.should_receive(:system).with(*subject.send(:command))
25
+ it "executes the system command in the project directory" do
26
+ mock(Kernel).system(*subject.send(:command))
27
+ mock(Dir).chdir(subject.project_path).yields
30
28
  subject.start
31
29
  end
32
30
 
33
31
  it "stops at_exit" do
34
- subject.should_receive(:at_exit)
32
+ mock(subject).stop
33
+ mock.proxy(Kernel).at_exit.yields(subject)
35
34
  subject.start
36
35
  end
37
36
  end
@@ -39,27 +38,51 @@ describe Specjour::RsyncDaemon do
39
38
  describe "#stop" do
40
39
  context "with pid" do
41
40
  before do
42
- subject.stub(:pid => 100_000_000)
43
- Process.stub(:kill)
44
- FileUtils.stub(:rm)
41
+ stub(subject).pid.returns(100_000_000)
42
+ stub(Process).kill
43
+ stub(FileUtils).rm
45
44
  end
46
45
 
47
46
  it "kills the pid with TERM" do
48
- Process.should_receive(:kill).with('TERM', subject.pid)
47
+ mock(Process).kill('TERM', subject.pid)
49
48
  subject.stop
50
49
  end
51
50
 
52
51
  it "removes the pid file" do
53
- FileUtils.should_receive(:rm).with(subject.pid_file)
52
+ mock(FileUtils).rm(subject.pid_file)
54
53
  subject.stop
55
54
  end
56
55
  end
57
56
 
58
57
  context "without pid" do
59
58
  it "does nothing" do
60
- subject.stub(:pid => nil)
59
+ stub(subject).pid
61
60
  subject.stop.should be_nil
62
61
  end
63
62
  end
64
63
  end
64
+
65
+ describe "#check_config_version" do
66
+ it "warns when the version is out of date" do
67
+ stub(File).read { "# 0.0.0\n" }
68
+ mock($stderr).puts(/made changes/)
69
+ subject.send(:check_config_version)
70
+ end
71
+
72
+ it "doesn't warn when the version isn't out of date" do
73
+ stub(File).read { "# #{Specjour::RsyncDaemon::CONFIG_VERSION}\n" }
74
+ dont_allow($stderr).puts
75
+ subject.send(:check_config_version)
76
+ end
77
+ end
78
+
79
+ describe "#write_config" do
80
+ context "config exists" do
81
+ it "checks if the config is out of date" do
82
+ stub(File).exists?(anything) { true }
83
+ mock(subject).check_config_version
84
+ subject.send(:write_config)
85
+ end
86
+ end
87
+ end
65
88
  end
data/spec/spec_helper.rb CHANGED
@@ -4,5 +4,5 @@ require 'specjour'
4
4
  require 'spec/autorun'
5
5
 
6
6
  Spec::Runner.configure do |config|
7
-
7
+ config.mock_with :rr
8
8
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 2
9
- version: 0.2.2
8
+ - 3
9
+ version: 0.2.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Sandro Turriate
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-22 00:00:00 -04:00
17
+ date: 2010-04-26 00:00:00 -04:00
18
18
  default_executable: specjour
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -58,9 +58,23 @@ dependencies:
58
58
  type: :development
59
59
  version_requirements: *id003
60
60
  - !ruby/object:Gem::Dependency
61
- name: yard
61
+ name: rr
62
62
  prerelease: false
63
63
  requirement: &id004 !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ - 10
70
+ - 11
71
+ version: 0.10.11
72
+ type: :development
73
+ version_requirements: *id004
74
+ - !ruby/object:Gem::Dependency
75
+ name: yard
76
+ prerelease: false
77
+ requirement: &id005 !ruby/object:Gem::Requirement
64
78
  requirements:
65
79
  - - "="
66
80
  - !ruby/object:Gem::Version
@@ -70,7 +84,7 @@ dependencies:
70
84
  - 3
71
85
  version: 0.5.3
72
86
  type: :development
73
- version_requirements: *id004
87
+ version_requirements: *id005
74
88
  description: Distribute your spec suite amongst your LAN via Bonjour.
75
89
  email: sandro.turriate@gmail.com
76
90
  executables:
@@ -112,7 +126,9 @@ files:
112
126
  - lib/specjour/tasks/specjour.rb
113
127
  - lib/specjour/worker.rb
114
128
  - rails/init.rb
129
+ - spec/cpu_spec.rb
115
130
  - spec/lib/specjour/worker_spec.rb
131
+ - spec/manager_spec.rb
116
132
  - spec/rsync_daemon_spec.rb
117
133
  - spec/spec.opts
118
134
  - spec/spec_helper.rb
@@ -148,7 +164,9 @@ signing_key:
148
164
  specification_version: 3
149
165
  summary: Distribute your spec suite amongst your LAN via Bonjour.
150
166
  test_files:
167
+ - spec/cpu_spec.rb
151
168
  - spec/lib/specjour/worker_spec.rb
169
+ - spec/manager_spec.rb
152
170
  - spec/rsync_daemon_spec.rb
153
171
  - spec/spec_helper.rb
154
172
  - spec/specjour_spec.rb