rush2 0.7.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.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +86 -0
- data/README.rdoc +125 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/bin/rush +13 -0
- data/bin/rushd +7 -0
- data/lib/rush.rb +91 -0
- data/lib/rush/access.rb +121 -0
- data/lib/rush/array_ext.rb +19 -0
- data/lib/rush/box.rb +124 -0
- data/lib/rush/commands.rb +76 -0
- data/lib/rush/config.rb +147 -0
- data/lib/rush/dir.rb +166 -0
- data/lib/rush/embeddable_shell.rb +26 -0
- data/lib/rush/entry.rb +229 -0
- data/lib/rush/exceptions.rb +32 -0
- data/lib/rush/file.rb +94 -0
- data/lib/rush/find_by.rb +39 -0
- data/lib/rush/fixnum_ext.rb +18 -0
- data/lib/rush/head_tail.rb +11 -0
- data/lib/rush/local.rb +377 -0
- data/lib/rush/process.rb +59 -0
- data/lib/rush/process_set.rb +62 -0
- data/lib/rush/remote.rb +33 -0
- data/lib/rush/search_results.rb +71 -0
- data/lib/rush/shell.rb +111 -0
- data/lib/rush/shell/completion.rb +110 -0
- data/lib/rush/string_ext.rb +16 -0
- data/spec/access_spec.rb +134 -0
- data/spec/array_ext_spec.rb +15 -0
- data/spec/base.rb +22 -0
- data/spec/box_spec.rb +76 -0
- data/spec/commands_spec.rb +47 -0
- data/spec/config_spec.rb +108 -0
- data/spec/dir_spec.rb +163 -0
- data/spec/embeddable_shell_spec.rb +17 -0
- data/spec/entry_spec.rb +133 -0
- data/spec/file_spec.rb +83 -0
- data/spec/find_by_spec.rb +58 -0
- data/spec/fixnum_ext_spec.rb +19 -0
- data/spec/local_spec.rb +365 -0
- data/spec/process_set_spec.rb +50 -0
- data/spec/process_spec.rb +73 -0
- data/spec/remote_spec.rb +140 -0
- data/spec/rush_spec.rb +28 -0
- data/spec/search_results_spec.rb +44 -0
- data/spec/shell_spec.rb +35 -0
- data/spec/ssh_tunnel_spec.rb +122 -0
- data/spec/string_ext_spec.rb +23 -0
- metadata +209 -0
data/spec/entry_spec.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
describe Rush::Entry do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_spec.#{Process.pid}/"
|
6
|
+
system "rm -rf #{@sandbox_dir}; mkdir -p #{@sandbox_dir}"
|
7
|
+
|
8
|
+
@filename = "#{@sandbox_dir}/test_file"
|
9
|
+
system "touch #{@filename}"
|
10
|
+
|
11
|
+
@entry = Rush::Entry.new(@filename)
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
system "rm -rf #{@sandbox_dir}"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "knows its name" do
|
19
|
+
@entry.name.should == File.basename(@filename)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "knows its parent dir" do
|
23
|
+
@entry.parent.should be_kind_of(Rush::Dir)
|
24
|
+
@entry.parent.name.should == File.basename(@sandbox_dir)
|
25
|
+
@entry.parent.full_path.should == @sandbox_dir
|
26
|
+
end
|
27
|
+
|
28
|
+
it "cleans its pathname" do
|
29
|
+
Rush::Entry.new('/a//b//c').full_path.should == '/a/b/c'
|
30
|
+
Rush::Entry.new('/1/2/../3').full_path.should == '/1/3'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "knows its changed_at time" do
|
34
|
+
@entry.changed_at.should == File.stat(@filename).ctime
|
35
|
+
end
|
36
|
+
|
37
|
+
it "knows its last_modified time" do
|
38
|
+
@entry.last_modified.should == File.stat(@filename).mtime
|
39
|
+
end
|
40
|
+
|
41
|
+
it "knows its last_accessed time" do
|
42
|
+
@entry.last_accessed.should == File.stat(@filename).atime
|
43
|
+
end
|
44
|
+
|
45
|
+
it "considers itself equal to other instances with the same full path" do
|
46
|
+
Rush::Entry.new('/not/the/same').should_not == @entry
|
47
|
+
Rush::Entry.new(@entry.full_path).should == @entry
|
48
|
+
end
|
49
|
+
|
50
|
+
it "can rename itself" do
|
51
|
+
new_file = "test2"
|
52
|
+
|
53
|
+
@entry.rename(new_file)
|
54
|
+
|
55
|
+
File.exists?(@filename).should be_false
|
56
|
+
File.exists?("#{@sandbox_dir}/#{new_file}").should be_true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "rename returns the renamed file" do
|
60
|
+
@entry.rename('file2').should == @entry.parent['file2']
|
61
|
+
end
|
62
|
+
|
63
|
+
it "can't rename itself if another file already exists with that name" do
|
64
|
+
new_file = "test3"
|
65
|
+
system "touch #{@sandbox_dir}/#{new_file}"
|
66
|
+
|
67
|
+
lambda { @entry.rename(new_file) }.should raise_error(Rush::NameAlreadyExists, /#{new_file}/)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "can't rename itself to something with a slash in it" do
|
71
|
+
lambda { @entry.rename('has/slash') }.should raise_error(Rush::NameCannotContainSlash, /slash/)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can duplicate itself within the directory" do
|
75
|
+
@entry.duplicate('newfile').should == Rush::File.new("#{@sandbox_dir}/newfile")
|
76
|
+
end
|
77
|
+
|
78
|
+
it "can move itself to another dir" do
|
79
|
+
newdir = "#{@sandbox_dir}/newdir"
|
80
|
+
system "mkdir -p #{newdir}"
|
81
|
+
|
82
|
+
dst = Rush::Dir.new(newdir)
|
83
|
+
@entry.move_to(dst)
|
84
|
+
|
85
|
+
File.exists?(@filename).should be_false
|
86
|
+
File.exists?("#{newdir}/#{@entry.name}").should be_true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "can copy itself to another directory" do
|
90
|
+
newdir = "#{@sandbox_dir}/newdir"
|
91
|
+
system "mkdir -p #{newdir}"
|
92
|
+
|
93
|
+
dst = Rush::Dir.new(newdir)
|
94
|
+
@copied_dir = @entry.copy_to(dst)
|
95
|
+
|
96
|
+
File.exists?(@filename).should be_true
|
97
|
+
File.exists?("#{newdir}/#{@entry.name}").should be_true
|
98
|
+
|
99
|
+
@copied_dir.full_path.should == "#{@sandbox_dir}newdir/#{@entry.name}"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "considers dotfiles to be hidden" do
|
103
|
+
Rush::Entry.new("#{@sandbox_dir}/show").should_not be_hidden
|
104
|
+
Rush::Entry.new("#{@sandbox_dir}/.dont_show").should be_hidden
|
105
|
+
end
|
106
|
+
|
107
|
+
it "is considered equal to entries with the same full path and on the same box" do
|
108
|
+
same = Rush::Entry.new(@entry.full_path, @entry.box)
|
109
|
+
@entry.should == same
|
110
|
+
end
|
111
|
+
|
112
|
+
it "is considered not equal to entries with the same full path on a different box" do
|
113
|
+
same = Rush::Entry.new(@entry.full_path, Rush::Box.new('dummy'))
|
114
|
+
@entry.should_not == same
|
115
|
+
end
|
116
|
+
|
117
|
+
it "can mimic another entry" do
|
118
|
+
copy = Rush::Entry.new('abc', :dummy)
|
119
|
+
copy.mimic(@entry)
|
120
|
+
copy.path.should == @entry.path
|
121
|
+
end
|
122
|
+
|
123
|
+
it "can update the read access permission" do
|
124
|
+
system "chmod 666 #{@filename}"
|
125
|
+
@entry.access = { :user_can => :read }
|
126
|
+
`ls -l #{@filename}`.should match(/^-r--------/)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "reads the file permissions in the access hash" do
|
130
|
+
system "chmod 640 #{@filename}"
|
131
|
+
@entry.access.should == { :user_can_read => true, :user_can_write => true, :group_can_read => true }
|
132
|
+
end
|
133
|
+
end
|
data/spec/file_spec.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
describe Rush::File do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_spec.#{Process.pid}"
|
6
|
+
system "rm -rf #{@sandbox_dir}; mkdir -p #{@sandbox_dir}"
|
7
|
+
|
8
|
+
@filename = "#{@sandbox_dir}/test_file"
|
9
|
+
@contents = "1234"
|
10
|
+
system "echo #{@contents} > #{@filename}"
|
11
|
+
@contents += "\n"
|
12
|
+
|
13
|
+
@file = Rush::File.new(@filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
system "rm -rf #{@sandbox_dir}"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "is a child of Rush::Entry" do
|
21
|
+
@file.should be_kind_of(Rush::Entry)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "is not a dir" do
|
25
|
+
@file.should_not be_dir
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can create itself as a blank file, and return itself" do
|
29
|
+
create_me = Rush::File.new("#{@sandbox_dir}/create_me")
|
30
|
+
create_me.create.should == create_me
|
31
|
+
File.exists?("#{@sandbox_dir}/create_me").should == true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "knows its size in bytes" do
|
35
|
+
@file.size.should == @contents.length
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can read its contents" do
|
39
|
+
@file.contents.should == @contents
|
40
|
+
end
|
41
|
+
|
42
|
+
it "read is an alias for contents" do
|
43
|
+
@file.read.should == @contents
|
44
|
+
end
|
45
|
+
|
46
|
+
it "can write new contents" do
|
47
|
+
@file.write('write test')
|
48
|
+
@file.contents.should == 'write test'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can count the number of lines it contains" do
|
52
|
+
@file.write("1\n2\n3\n")
|
53
|
+
@file.line_count.should == 3
|
54
|
+
end
|
55
|
+
|
56
|
+
it "searches its contents for matching lines" do
|
57
|
+
@file.write("a\n1\nb\n2\n")
|
58
|
+
@file.search(/\d/).should == %w(1 2)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "search returns nil if no lines match" do
|
62
|
+
@file.write("a\nb\nc\n")
|
63
|
+
@file.search(/\d/).should be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it "find-in-file replace" do
|
67
|
+
@file.replace_contents!(/\d/, 'x')
|
68
|
+
@file.contents.should == "xxxx\n"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "can destroy itself" do
|
72
|
+
@file.destroy
|
73
|
+
::File.exists?(@filename).should be_false
|
74
|
+
end
|
75
|
+
|
76
|
+
it "can fetch contents or blank if doesn't exist" do
|
77
|
+
Rush::File.new('/does/not/exist').contents_or_blank.should == ""
|
78
|
+
end
|
79
|
+
|
80
|
+
it "can fetch lines, or empty if doesn't exist" do
|
81
|
+
Rush::File.new('/does/not/exist').lines_or_empty.should == []
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
describe Rush::FindBy do
|
4
|
+
before do
|
5
|
+
class Foo
|
6
|
+
attr_accessor :bar
|
7
|
+
|
8
|
+
def initialize(bar)
|
9
|
+
@bar = bar
|
10
|
+
end end
|
11
|
+
|
12
|
+
@one = Foo.new('one')
|
13
|
+
@two = Foo.new('two')
|
14
|
+
@three = Foo.new('three')
|
15
|
+
|
16
|
+
@list = [ @one, @two, @three ]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "compare_or_match exact match success" do
|
20
|
+
@list.compare_or_match('1', '1').should == true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "compare_or_match exact match failure" do
|
24
|
+
@list.compare_or_match('1', '2').should == false
|
25
|
+
end
|
26
|
+
|
27
|
+
it "compare_or_match regexp match success" do
|
28
|
+
@list.compare_or_match('123', /2/).should == true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "compare_or_match regexp match failure" do
|
32
|
+
@list.compare_or_match('123', /x/).should == false
|
33
|
+
end
|
34
|
+
|
35
|
+
it "find_by_ extact match" do
|
36
|
+
@list.find_by_bar('two').should == @two
|
37
|
+
end
|
38
|
+
|
39
|
+
it "find_by_ regexp match" do
|
40
|
+
@list.find_by_bar(/.hree/).should == @three
|
41
|
+
end
|
42
|
+
|
43
|
+
it "find_all_by_ exact match" do
|
44
|
+
@list.find_all_by_bar('one').should == [ @one ]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "find_all_by_ regexp match" do
|
48
|
+
@list.find_all_by_bar(/^...$/).should == [ @one, @two ]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "find_by_ with field not recognized by objects raises no errors" do
|
52
|
+
@list.find_by_nothing('x')
|
53
|
+
end
|
54
|
+
|
55
|
+
it "raises NoMethodError for things other than find_by" do
|
56
|
+
lambda { @list.does_not_exist }.should raise_error(NoMethodError)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
describe Fixnum do
|
4
|
+
before do
|
5
|
+
@num = 2
|
6
|
+
end
|
7
|
+
|
8
|
+
it "counts kb" do
|
9
|
+
@num.kb.should == 2*1024
|
10
|
+
end
|
11
|
+
|
12
|
+
it "counts mb" do
|
13
|
+
@num.mb.should == 2*1024*1024
|
14
|
+
end
|
15
|
+
|
16
|
+
it "counts gb" do
|
17
|
+
@num.gb.should == 2*1024*1024*1024
|
18
|
+
end
|
19
|
+
end
|
data/spec/local_spec.rb
ADDED
@@ -0,0 +1,365 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
describe Rush::Connection::Local do
|
4
|
+
before do
|
5
|
+
@sandbox_dir = "/tmp/rush_spec.#{Process.pid}"
|
6
|
+
system "rm -rf #{@sandbox_dir}; mkdir -p #{@sandbox_dir}"
|
7
|
+
|
8
|
+
@con = Rush::Connection::Local.new
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
system "rm -rf #{@sandbox_dir}"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "receive -> write_file(file, contents)" do
|
16
|
+
@con.should_receive(:write_file).with('file', 'contents')
|
17
|
+
@con.receive(:action => 'write_file', :full_path => 'file', :payload => 'contents')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "receive -> append_to_file(file, contents)" do
|
21
|
+
@con.should_receive(:append_to_file).with('file', 'contents')
|
22
|
+
@con.receive(:action => 'append_to_file', :full_path => 'file', :payload => 'contents')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "receive -> file_contents(file)" do
|
26
|
+
@con.should_receive(:file_contents).with('file').and_return('the contents')
|
27
|
+
@con.receive(:action => 'file_contents', :full_path => 'file').should == 'the contents'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "receive -> destroy(file or dir)" do
|
31
|
+
@con.should_receive(:destroy).with('file')
|
32
|
+
@con.receive(:action => 'destroy', :full_path => 'file')
|
33
|
+
end
|
34
|
+
|
35
|
+
it "receive -> purge(dir)" do
|
36
|
+
@con.should_receive(:purge).with('dir')
|
37
|
+
@con.receive(:action => 'purge', :full_path => 'dir')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "receive -> create_dir(path)" do
|
41
|
+
@con.should_receive(:create_dir).with('dir')
|
42
|
+
@con.receive(:action => 'create_dir', :full_path => 'dir')
|
43
|
+
end
|
44
|
+
|
45
|
+
it "receive -> rename(path, name, new_name)" do
|
46
|
+
@con.should_receive(:rename).with('path', 'name', 'new_name')
|
47
|
+
@con.receive(:action => 'rename', :path => 'path', :name => 'name', :new_name => 'new_name')
|
48
|
+
end
|
49
|
+
|
50
|
+
it "receive -> copy(src, dst)" do
|
51
|
+
@con.should_receive(:copy).with('src', 'dst')
|
52
|
+
@con.receive(:action => 'copy', :src => 'src', :dst => 'dst')
|
53
|
+
end
|
54
|
+
|
55
|
+
it "receive -> read_archive(full_path)" do
|
56
|
+
@con.should_receive(:read_archive).with('full_path').and_return('archive data')
|
57
|
+
@con.receive(:action => 'read_archive', :full_path => 'full_path').should == 'archive data'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "receive -> write_archive(archive, dir)" do
|
61
|
+
@con.should_receive(:write_archive).with('archive', 'dir')
|
62
|
+
@con.receive(:action => 'write_archive', :dir => 'dir', :payload => 'archive')
|
63
|
+
end
|
64
|
+
|
65
|
+
it "receive -> index(base_path, glob)" do
|
66
|
+
@con.should_receive(:index).with('base_path', '*').and_return(%w(1 2))
|
67
|
+
@con.receive(:action => 'index', :base_path => 'base_path', :glob => '*').should == "1\n2\n"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "receive -> stat(full_path)" do
|
71
|
+
@con.should_receive(:stat).with('full_path').and_return(1 => 2)
|
72
|
+
@con.receive(:action => 'stat', :full_path => 'full_path').should == YAML.dump(1 => 2)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "receive -> set_access(full_path, user, group, permissions)" do
|
76
|
+
access = double("access")
|
77
|
+
Rush::Access.should_receive(:from_hash).with(:action => 'set_access', :full_path => 'full_path', :user => 'joe').and_return(access)
|
78
|
+
|
79
|
+
@con.should_receive(:set_access).with('full_path', access)
|
80
|
+
@con.receive(:action => 'set_access', :full_path => 'full_path', :user => 'joe')
|
81
|
+
end
|
82
|
+
|
83
|
+
it "receive -> size(full_path)" do
|
84
|
+
@con.should_receive(:size).with('full_path').and_return("1024")
|
85
|
+
@con.receive(:action => 'size', :full_path => 'full_path').should == "1024"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "receive -> chown(full_path, user, group, options)" do
|
89
|
+
options = { noop: true }
|
90
|
+
@con.should_receive(:chown).with('full_path', 'username', 'groupname', options )
|
91
|
+
@con.receive(:action => 'chown', :full_path => 'full_path', user: 'username', group: 'groupname', options: options)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "receive -> processes" do
|
95
|
+
@con.should_receive(:processes).with().and_return([ { :pid => 1 } ])
|
96
|
+
@con.receive(:action => 'processes').should == YAML.dump([ { :pid => 1 } ])
|
97
|
+
end
|
98
|
+
|
99
|
+
it "receive -> process_alive" do
|
100
|
+
@con.should_receive(:process_alive).with(123).and_return(true)
|
101
|
+
@con.receive(:action => 'process_alive', :pid => 123).should == '1'
|
102
|
+
end
|
103
|
+
|
104
|
+
it "receive -> kill_process" do
|
105
|
+
@con.should_receive(:kill_process).with(123, :wait => 10).and_return(true)
|
106
|
+
@con.receive(:action => 'kill_process', :pid => '123', :payload => YAML.dump(:wait => 10))
|
107
|
+
end
|
108
|
+
|
109
|
+
it "receive -> bash (reset environment)" do
|
110
|
+
@con.should_receive(:bash).with('cmd', 'user', false, true).and_return('output')
|
111
|
+
@con.receive(:action => 'bash', :payload => 'cmd', :user => 'user', :background => 'false', :reset_environment => 'true').should == 'output'
|
112
|
+
end
|
113
|
+
|
114
|
+
it "receive -> bash (foreground)" do
|
115
|
+
@con.should_receive(:bash).with('cmd', 'user', false, false).and_return('output')
|
116
|
+
@con.receive(:action => 'bash', :payload => 'cmd', :user => 'user', :background => 'false').should == 'output'
|
117
|
+
end
|
118
|
+
|
119
|
+
it "receive -> bash (background)" do
|
120
|
+
@con.should_receive(:bash).with('cmd', 'user', true, false).and_return('output')
|
121
|
+
@con.receive(:action => 'bash', :payload => 'cmd', :user => 'user', :background => 'true').should == 'output'
|
122
|
+
end
|
123
|
+
|
124
|
+
it "receive -> unknown action exception" do
|
125
|
+
lambda { @con.receive(:action => 'does_not_exist') }.should raise_error(Rush::Connection::Local::UnknownAction)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "write_file writes contents to a file" do
|
129
|
+
fname = "#{@sandbox_dir}/a_file"
|
130
|
+
data = "some data"
|
131
|
+
@con.write_file(fname, data)
|
132
|
+
File.read(fname).should == data
|
133
|
+
end
|
134
|
+
|
135
|
+
it "append_to_file appends contents to a file" do
|
136
|
+
fname = "#{@sandbox_dir}/a_file"
|
137
|
+
system "echo line1 > #{fname}"
|
138
|
+
@con.append_to_file(fname, 'line2')
|
139
|
+
File.read(fname).should == "line1\nline2"
|
140
|
+
end
|
141
|
+
|
142
|
+
it "file_contents reads a file's contents" do
|
143
|
+
fname = "#{@sandbox_dir}/a_file"
|
144
|
+
system "echo stuff > #{fname}"
|
145
|
+
@con.file_contents(fname).should == "stuff\n"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "file_contents raises DoesNotExist if the file does not exist" do
|
149
|
+
fname = "#{@sandbox_dir}/does_not_exist"
|
150
|
+
lambda { @con.file_contents(fname) }.should raise_error(Rush::DoesNotExist, fname)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "destroy to destroy a file or dir" do
|
154
|
+
fname = "#{@sandbox_dir}/delete_me"
|
155
|
+
system "touch #{fname}"
|
156
|
+
@con.destroy(fname)
|
157
|
+
File.exists?(fname).should be_false
|
158
|
+
end
|
159
|
+
|
160
|
+
it "purge to purge a dir" do
|
161
|
+
system "cd #{@sandbox_dir}; touch {1,2}; mkdir 3; touch 3/4"
|
162
|
+
@con.purge(@sandbox_dir)
|
163
|
+
File.exists?(@sandbox_dir).should be_true
|
164
|
+
Dir.glob("#{@sandbox_dir}/*").should == []
|
165
|
+
end
|
166
|
+
|
167
|
+
it "purge kills hidden (dotfile) entries too" do
|
168
|
+
system "cd #{@sandbox_dir}; touch .killme"
|
169
|
+
@con.purge(@sandbox_dir)
|
170
|
+
File.exists?(@sandbox_dir).should be_true
|
171
|
+
`cd #{@sandbox_dir}; ls -lA | grep -v total | wc -l`.to_i.should == 0
|
172
|
+
end
|
173
|
+
|
174
|
+
it "create_dir creates a directory" do
|
175
|
+
fname = "#{@sandbox_dir}/a/b/c/"
|
176
|
+
@con.create_dir(fname)
|
177
|
+
File.directory?(fname).should be_true
|
178
|
+
end
|
179
|
+
|
180
|
+
it "rename to rename entries within a dir" do
|
181
|
+
system "touch #{@sandbox_dir}/a"
|
182
|
+
@con.rename(@sandbox_dir, 'a', 'b')
|
183
|
+
File.exists?("#{@sandbox_dir}/a").should be_false
|
184
|
+
File.exists?("#{@sandbox_dir}/b").should be_true
|
185
|
+
end
|
186
|
+
|
187
|
+
it "copy to copy an entry to another dir on the same box" do
|
188
|
+
system "mkdir #{@sandbox_dir}/subdir"
|
189
|
+
system "touch #{@sandbox_dir}/a"
|
190
|
+
@con.copy("#{@sandbox_dir}/a", "#{@sandbox_dir}/subdir")
|
191
|
+
File.exists?("#{@sandbox_dir}/a").should be_true
|
192
|
+
File.exists?("#{@sandbox_dir}/subdir/a").should be_true
|
193
|
+
end
|
194
|
+
|
195
|
+
it "copy raises DoesNotExist with source path if it doesn't exist or otherwise can't be accessed" do
|
196
|
+
lambda { @con.copy('/does/not/exist', '/tmp') }.should raise_error(Rush::DoesNotExist, '/does/not/exist')
|
197
|
+
end
|
198
|
+
|
199
|
+
it "copy raises DoesNotExist with destination path if it can't access the destination" do
|
200
|
+
lambda { @con.copy('/tmp', '/does/not/exist') }.should raise_error(Rush::DoesNotExist, '/does/not')
|
201
|
+
end
|
202
|
+
|
203
|
+
it "read_archive to pull an archive of a dir into a byte stream" do
|
204
|
+
system "touch #{@sandbox_dir}/a"
|
205
|
+
@con.read_archive(@sandbox_dir).size.should > 50
|
206
|
+
end
|
207
|
+
|
208
|
+
it "read_archive works for paths with spaces" do
|
209
|
+
system "mkdir -p #{@sandbox_dir}/with\\ space; touch #{@sandbox_dir}/with\\ space/a"
|
210
|
+
@con.read_archive("#{@sandbox_dir}/with space").size.should > 50
|
211
|
+
end
|
212
|
+
|
213
|
+
it "write_archive to turn a byte stream into a dir" do
|
214
|
+
system "cd #{@sandbox_dir}; mkdir -p a; touch a/b; tar cf xfer.tar a; mkdir dst"
|
215
|
+
archive = File.read("#{@sandbox_dir}/xfer.tar")
|
216
|
+
@con.write_archive(archive, "#{@sandbox_dir}/dst")
|
217
|
+
File.directory?("#{@sandbox_dir}/dst/a").should be_true
|
218
|
+
File.exists?("#{@sandbox_dir}/dst/a/b").should be_true
|
219
|
+
end
|
220
|
+
|
221
|
+
it "write_archive works for paths with spaces" do
|
222
|
+
system "cd #{@sandbox_dir}; mkdir -p a; touch a/b; tar cf xfer.tar a; mkdir with\\ space"
|
223
|
+
archive = File.read("#{@sandbox_dir}/xfer.tar")
|
224
|
+
@con.write_archive(archive, "#{@sandbox_dir}/with space")
|
225
|
+
File.directory?("#{@sandbox_dir}/with space/a").should be_true
|
226
|
+
File.exists?("#{@sandbox_dir}/with space/a/b").should be_true
|
227
|
+
end
|
228
|
+
|
229
|
+
it "index fetches list of all files and dirs in a dir when pattern is empty" do
|
230
|
+
system "cd #{@sandbox_dir}; mkdir dir; touch file"
|
231
|
+
@con.index(@sandbox_dir, '').should == [ 'dir/', 'file' ]
|
232
|
+
end
|
233
|
+
|
234
|
+
it "index fetches only files with a certain extension with a flat pattern, *.rb" do
|
235
|
+
system "cd #{@sandbox_dir}; touch a.rb; touch b.txt"
|
236
|
+
@con.index(@sandbox_dir, '*.rb').should == [ 'a.rb' ]
|
237
|
+
end
|
238
|
+
|
239
|
+
it "index raises DoesNotExist when the base path is invalid" do
|
240
|
+
lambda { @con.index('/does/not/exist', '*') }.should raise_error(Rush::DoesNotExist, '/does/not/exist')
|
241
|
+
end
|
242
|
+
|
243
|
+
it "stat gives file stats like size and timestamps" do
|
244
|
+
@con.stat(@sandbox_dir).should have_key(:ctime)
|
245
|
+
@con.stat(@sandbox_dir).should have_key(:size)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "stat fetches the octal permissions" do
|
249
|
+
@con.stat(@sandbox_dir)[:mode].should be_kind_of(Fixnum)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "stat raises DoesNotExist if the entry does not exist" do
|
253
|
+
fname = "#{@sandbox_dir}/does_not_exist"
|
254
|
+
lambda { @con.stat(fname) }.should raise_error(Rush::DoesNotExist, fname)
|
255
|
+
end
|
256
|
+
|
257
|
+
it "set_access invokes the access object" do
|
258
|
+
access = double("access")
|
259
|
+
access.should_receive(:apply).with('/some/path')
|
260
|
+
@con.set_access('/some/path', access)
|
261
|
+
end
|
262
|
+
|
263
|
+
it "chown should change the ownership of a file"
|
264
|
+
|
265
|
+
if !RUBY_PLATFORM.match(/darwin/) # doesn't work on OS X 'cause du switches are different
|
266
|
+
it "size gives size of a directory and all its contents recursively" do
|
267
|
+
system "mkdir -p #{@sandbox_dir}/a/b/; echo 1234 > #{@sandbox_dir}/a/b/c"
|
268
|
+
@con.size(@sandbox_dir).should == (4096*3 + 5)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
it "parses ps output on os x" do
|
273
|
+
@con.parse_ps("21712 501 21711 1236 0 /usr/bin/vi somefile.rb").should == {
|
274
|
+
:pid => "21712",
|
275
|
+
:uid => "501",
|
276
|
+
:parent_pid => 21711,
|
277
|
+
:mem => 1236,
|
278
|
+
:cpu => 0,
|
279
|
+
:command => '/usr/bin/vi',
|
280
|
+
:cmdline => '/usr/bin/vi somefile.rb',
|
281
|
+
}
|
282
|
+
end
|
283
|
+
|
284
|
+
it "gets the list of processes on os x via the ps command" do
|
285
|
+
@con.should_receive(:os_x_raw_ps).and_return <<EOPS
|
286
|
+
PID UID PPID RSS CPU COMMAND
|
287
|
+
1 0 1 1111 0 cmd1 args
|
288
|
+
2 501 1 222 1 cmd2
|
289
|
+
EOPS
|
290
|
+
@con.os_x_processes.should == [
|
291
|
+
{ :pid => "1", :uid => "0", :parent_pid => 1, :mem => 1111, :cpu => 0, :command => "cmd1", :cmdline => "cmd1 args" },
|
292
|
+
{ :pid => "2", :uid => "501", :parent_pid => 1, :mem => 222, :cpu => 1, :command => "cmd2", :cmdline => "cmd2" },
|
293
|
+
]
|
294
|
+
end
|
295
|
+
|
296
|
+
it "the current process should be alive" do
|
297
|
+
@con.process_alive(Process.pid).should be_true
|
298
|
+
end
|
299
|
+
|
300
|
+
it "a made-up process should not be alive" do
|
301
|
+
@con.process_alive(99999).should be_false
|
302
|
+
end
|
303
|
+
|
304
|
+
it "kills a process by pid sending a TERM" do
|
305
|
+
@con.stub(:process_alive).and_return(false)
|
306
|
+
::Process.should_receive(:kill).with('TERM', 123).once
|
307
|
+
@con.kill_process(123)
|
308
|
+
end
|
309
|
+
|
310
|
+
it "kills a process by pid sending a KILL signal if TERM doesn't work" do
|
311
|
+
@con.stub(:process_alive).and_return(true)
|
312
|
+
::Process.should_receive(:kill).with('TERM', 123).at_least(:twice)
|
313
|
+
::Process.should_receive(:kill).with('KILL', 123)
|
314
|
+
@con.kill_process(123)
|
315
|
+
end
|
316
|
+
|
317
|
+
it "kills a process by pid without sending TERM if :wait is zero" do
|
318
|
+
::Process.should_not_receive(:kill).with('TERM', 123)
|
319
|
+
::Process.should_receive(:kill).with('KILL', 123)
|
320
|
+
@con.kill_process(123, :wait => 0)
|
321
|
+
end
|
322
|
+
|
323
|
+
it "does not raise an error if the process is already dead" do
|
324
|
+
::Process.should_receive(:kill).and_raise(Errno::ESRCH)
|
325
|
+
lambda { @con.kill_process(123) }.should_not raise_error
|
326
|
+
end
|
327
|
+
|
328
|
+
it "executes a bash command, returning stdout when successful" do
|
329
|
+
@con.bash("echo test").should == "test\n"
|
330
|
+
end
|
331
|
+
|
332
|
+
it "executes a bash command, raising and error (with stderr as the message) when return value is nonzero" do
|
333
|
+
lambda { @con.bash("no_such_bin") }.should raise_error(Rush::BashFailed, /command not found/)
|
334
|
+
end
|
335
|
+
|
336
|
+
it "executes a bash command as another user using sudo" do
|
337
|
+
@con.bash("echo test2", ENV['USER']).should == "test2\n"
|
338
|
+
end
|
339
|
+
|
340
|
+
it "executes a bash command in the background, returning the pid" do
|
341
|
+
@con.bash("true", nil, true).should > 0
|
342
|
+
end
|
343
|
+
|
344
|
+
it "ensure_tunnel to match with remote connection" do
|
345
|
+
@con.ensure_tunnel
|
346
|
+
end
|
347
|
+
|
348
|
+
it "always returns true on alive?" do
|
349
|
+
@con.should be_alive
|
350
|
+
end
|
351
|
+
|
352
|
+
it "resolves a unix uid to a user" do
|
353
|
+
@con.resolve_unix_uid_to_user(0).should == "root"
|
354
|
+
@con.resolve_unix_uid_to_user('0').should == "root"
|
355
|
+
end
|
356
|
+
|
357
|
+
it "returns nil if the unix uid does not exist" do
|
358
|
+
@con.resolve_unix_uid_to_user(9999).should be_nil
|
359
|
+
end
|
360
|
+
|
361
|
+
it "iterates through a process list and resolves the unix uid for each" do
|
362
|
+
list = [ { :uid => 0, :command => 'pureftpd' }, { :uid => 9999, :command => 'defunk' } ]
|
363
|
+
@con.resolve_unix_uids(list).should == [ { :uid => 0, :user => 'root', :command => 'pureftpd' }, { :uid => 9999, :command => 'defunk', :user => nil } ]
|
364
|
+
end
|
365
|
+
end
|