tbooster 0.0.0 → 0.2.0
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/.gitignore +5 -0
- data/README.md +4 -0
- data/bin/tbooster +27 -0
- data/lib/tbooster/command.rb +30 -0
- data/lib/tbooster/commands/invalid.rb +5 -0
- data/lib/tbooster/commands/reload_file.rb +40 -0
- data/lib/tbooster/commands/test_runner.rb +29 -0
- data/lib/tbooster.rb +119 -1
- data/tbooster.gemspec +17 -0
- metadata +30 -7
data/README.md
ADDED
data/bin/tbooster
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'tbooster'
|
3
|
+
|
4
|
+
if !Tbooster.runned_from_rails_root?
|
5
|
+
puts "must be in rails root"
|
6
|
+
exit
|
7
|
+
end
|
8
|
+
|
9
|
+
if ARGV && ARGV[0] == "reload"
|
10
|
+
Tbooster.reload
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
|
14
|
+
if ARGV && ARGV[0] == "exit"
|
15
|
+
puts "tbooster shutting down"
|
16
|
+
Tbooster.close_all_and_cleanup
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
|
20
|
+
if !Tbooster.listeners_loaded?
|
21
|
+
Tbooster.close_all_and_cleanup
|
22
|
+
Tbooster.send(ARGV)
|
23
|
+
Tbooster.start_listeners #listener needs the pipe which is created by the send command
|
24
|
+
else
|
25
|
+
Tbooster.send(ARGV)
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Command
|
2
|
+
attr_accessor :file, :args
|
3
|
+
|
4
|
+
def self.get(arg)
|
5
|
+
args = arg.gsub("\n","").split(' ')
|
6
|
+
|
7
|
+
if args.length < 2
|
8
|
+
return InvalidCommand.new
|
9
|
+
end
|
10
|
+
|
11
|
+
cmd = args[0]
|
12
|
+
file = args[1]
|
13
|
+
|
14
|
+
case cmd
|
15
|
+
when 'reload_file'
|
16
|
+
return ReloadFileCommand.new(file)
|
17
|
+
when 'run'
|
18
|
+
return TestRunnerCommand.new(file, args[1..-1] || [])
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
return Command.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def run
|
26
|
+
puts "unknown command"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class ReloadFileCommand < Command
|
2
|
+
@@to_reload = {}
|
3
|
+
def to_reload
|
4
|
+
@@to_reload
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(file)
|
8
|
+
self.file = file
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
return if !ReloadFileCommand.is_reloadable_file(file)
|
13
|
+
|
14
|
+
if to_reload[file] == nil
|
15
|
+
reload
|
16
|
+
else
|
17
|
+
last_reload_time = Time.now - to_reload[file]
|
18
|
+
if last_reload_time > 5 #more than 5 seconds passed since the last file reload
|
19
|
+
reload
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def reload
|
25
|
+
#ActiveRecord::Base.establish_connection ENV['RAILS_ENV']
|
26
|
+
to_reload[file] = Time.now
|
27
|
+
puts "change detected for: #{file}"
|
28
|
+
load file
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.is_reloadable_file(file)
|
32
|
+
return true if (file =~ watchable_file)
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.watchable_file
|
37
|
+
/((app\/(models|controllers|helpers))|lib)\/(.*)\.rb$/
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class TestRunnerCommand < Command
|
2
|
+
def initialize(file, args)
|
3
|
+
self.file = file
|
4
|
+
self.args = args
|
5
|
+
end
|
6
|
+
|
7
|
+
def run
|
8
|
+
if !is_test_file
|
9
|
+
puts "this is not a test file"
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
test_start = Time.now
|
14
|
+
|
15
|
+
fork do
|
16
|
+
ActiveRecord::Base.establish_connection ENV['RAILS_ENV']
|
17
|
+
|
18
|
+
puts "running: #{file}"
|
19
|
+
ARGV.replace(args)
|
20
|
+
require(file.gsub(".rb", ""))
|
21
|
+
|
22
|
+
test_end = Time.now
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def is_test_file
|
27
|
+
file =~ /test\/(.*)\/(.*)_test\.rb$/
|
28
|
+
end
|
29
|
+
end
|
data/lib/tbooster.rb
CHANGED
@@ -1 +1,119 @@
|
|
1
|
-
|
1
|
+
class Tbooster
|
2
|
+
#poor mans man check to verify if we're in a rails root
|
3
|
+
def self.runned_from_rails_root?
|
4
|
+
File.directory?("./app/views") && File.directory?("./app/models") && File.directory?("./app/controllers")
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.pid
|
8
|
+
"#{File.expand_path(Dir.pwd)}/tmp/tbooster.pid"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.pipe
|
12
|
+
"#{File.expand_path(Dir.pwd)}/tmp/tbooster_pipe"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.listeners_loaded?
|
16
|
+
if File.exists?(pid) && listener_processes_exist?
|
17
|
+
return true
|
18
|
+
end
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.listener_processes_exist?
|
23
|
+
listener_pids = (%x( cat #{pid} ) || "").split(" ").map{|pid| pid.to_i}.select{|pid| pid > 0}
|
24
|
+
return false if listener_pids.length != 2
|
25
|
+
|
26
|
+
processes_exist = true
|
27
|
+
|
28
|
+
listener_pids.each do |pid|
|
29
|
+
begin
|
30
|
+
Process.kill 0, pid
|
31
|
+
rescue Exception => e
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
processes_exist
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.close_all_and_cleanup
|
40
|
+
%x( rm -f #{pipe} ) if File.exists?(pipe)
|
41
|
+
if File.exists?(pid)
|
42
|
+
kill_opened_processes
|
43
|
+
%x( rm -f #{pid} )
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.kill_opened_processes
|
48
|
+
%x( kill -9 `cat #{pid}` )
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.start_listeners
|
52
|
+
puts "starting listeners"
|
53
|
+
command_listener
|
54
|
+
file_listener
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.command_listener
|
58
|
+
fork do
|
59
|
+
puts 'starting testing environment'
|
60
|
+
require 'test/test_helper'
|
61
|
+
puts 'loaded testing environment'
|
62
|
+
File.open(pid, "a") { |f| f<<" #{Process.pid}" }
|
63
|
+
input = File.open(pipe, "r+")
|
64
|
+
while true do
|
65
|
+
cmd = Command.get(input.gets)
|
66
|
+
|
67
|
+
begin
|
68
|
+
cmd.run
|
69
|
+
rescue Exception => e
|
70
|
+
puts "Message: #{e.message}"
|
71
|
+
puts "Stack: #{e.backtrace}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
puts "closed command listener process"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.file_listener
|
80
|
+
fork do
|
81
|
+
File.open(pid, "a") { |f| f<< " #{Process.pid}" }
|
82
|
+
|
83
|
+
require 'rubygems'
|
84
|
+
require 'listen'
|
85
|
+
output = open(pipe, "w+")
|
86
|
+
|
87
|
+
Listen.to('./', :filter => ReloadFileCommand.watchable_file) do |modified, added, removed|
|
88
|
+
output.puts "reload_file #{modified || added}"
|
89
|
+
output.flush
|
90
|
+
end
|
91
|
+
|
92
|
+
puts "closed watcher"
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.send(args)
|
98
|
+
unless File.exist?(pipe)
|
99
|
+
%x( mkfifo #{pipe} )
|
100
|
+
end
|
101
|
+
|
102
|
+
if args.length > 0
|
103
|
+
output = open(pipe, "w+")
|
104
|
+
output.puts "run #{args.join(' ')}"
|
105
|
+
output.flush
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.reload
|
110
|
+
Tbooster.close_all_and_cleanup
|
111
|
+
Tbooster.start_listeners
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
require 'tbooster/command'
|
116
|
+
require 'tbooster/commands/invalid'
|
117
|
+
require 'tbooster/commands/reload_file'
|
118
|
+
require 'tbooster/commands/test_runner'
|
119
|
+
|
data/tbooster.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "tbooster"
|
3
|
+
s.version = "0.2.0"
|
4
|
+
s.date = "2012-12-07"
|
5
|
+
s.summary = "Test booster"
|
6
|
+
s.description = "Runs unit tests faster by not reloading the testing environment every time"
|
7
|
+
s.authors = ["Razvan Dimescu"]
|
8
|
+
s.email = 'ssaricu@gmail.com'
|
9
|
+
s.homepage = 'http://rubygems.org/gems/tbooster'
|
10
|
+
|
11
|
+
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.executables << 'tbooster'
|
15
|
+
|
16
|
+
s.add_dependency "listen", ">= 0.6.0"
|
17
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tbooster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 2
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Razvan Dimescu
|
@@ -16,18 +16,41 @@ bindir: bin
|
|
16
16
|
cert_chain: []
|
17
17
|
|
18
18
|
date: 2012-12-07 00:00:00 Z
|
19
|
-
dependencies:
|
20
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: listen
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 7
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 6
|
32
|
+
- 0
|
33
|
+
version: 0.6.0
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
21
36
|
description: Runs unit tests faster by not reloading the testing environment every time
|
22
37
|
email: ssaricu@gmail.com
|
23
|
-
executables:
|
24
|
-
|
38
|
+
executables:
|
39
|
+
- tbooster
|
25
40
|
extensions: []
|
26
41
|
|
27
42
|
extra_rdoc_files: []
|
28
43
|
|
29
44
|
files:
|
45
|
+
- .gitignore
|
46
|
+
- README.md
|
47
|
+
- bin/tbooster
|
30
48
|
- lib/tbooster.rb
|
49
|
+
- lib/tbooster/command.rb
|
50
|
+
- lib/tbooster/commands/invalid.rb
|
51
|
+
- lib/tbooster/commands/reload_file.rb
|
52
|
+
- lib/tbooster/commands/test_runner.rb
|
53
|
+
- tbooster.gemspec
|
31
54
|
homepage: http://rubygems.org/gems/tbooster
|
32
55
|
licenses: []
|
33
56
|
|