rush3 3.0.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 +15 -0
- data/Gemfile.lock +93 -0
- data/README.rdoc +124 -0
- data/Rakefile +58 -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 +16 -0
- data/lib/rush/box.rb +130 -0
- data/lib/rush/commands.rb +94 -0
- data/lib/rush/config.rb +147 -0
- data/lib/rush/dir.rb +159 -0
- data/lib/rush/embeddable_shell.rb +26 -0
- data/lib/rush/entry.rb +238 -0
- data/lib/rush/exceptions.rb +32 -0
- data/lib/rush/file.rb +100 -0
- data/lib/rush/find_by.rb +39 -0
- data/lib/rush/head_tail.rb +11 -0
- data/lib/rush/integer_ext.rb +18 -0
- data/lib/rush/local.rb +404 -0
- data/lib/rush/path.rb +9 -0
- data/lib/rush/process.rb +59 -0
- data/lib/rush/process_set.rb +62 -0
- data/lib/rush/search_results.rb +71 -0
- data/lib/rush/shell.rb +118 -0
- data/lib/rush/shell/completion.rb +108 -0
- data/lib/rush/string_ext.rb +33 -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 +162 -0
- data/spec/file_spec.rb +95 -0
- data/spec/find_by_spec.rb +58 -0
- data/spec/integer_ext_spec.rb +19 -0
- data/spec/local_spec.rb +363 -0
- data/spec/path_spec.rb +13 -0
- data/spec/process_set_spec.rb +50 -0
- data/spec/process_spec.rb +89 -0
- data/spec/rush_spec.rb +28 -0
- data/spec/search_results_spec.rb +44 -0
- data/spec/shell_spec.rb +39 -0
- data/spec/ssh_tunnel_spec.rb +122 -0
- data/spec/string_ext_spec.rb +23 -0
- metadata +228 -0
data/spec/entry_spec.rb
ADDED
@@ -0,0 +1,162 @@
|
|
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
|
+
expect(@entry.name).to eq File.basename(@filename)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'knows its parent dir' do
|
23
|
+
expect(@entry.parent).to be_kind_of(Rush::Dir)
|
24
|
+
expect(@entry.parent.name).to eq File.basename(@sandbox_dir)
|
25
|
+
expect(@entry.parent.full_path).to eq @sandbox_dir
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'cleans its pathname' do
|
29
|
+
expect(Rush::Entry.new('/a//b//c').full_path).to eq '/a/b/c'
|
30
|
+
expect(Rush::Entry.new('/1/2/../3').full_path).to eq '/1/3'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'knows its changed_at time' do
|
34
|
+
expect(@entry.changed_at).to eq File.stat(@filename).ctime
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'knows its last_modified time' do
|
38
|
+
expect(@entry.last_modified).to eq File.stat(@filename).mtime
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'knows its last_accessed time' do
|
42
|
+
expect(@entry.last_accessed).to eq File.stat(@filename).atime
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'considers itself equal to other instances with the same full path' do
|
46
|
+
expect(Rush::Entry.new('/not/the/same')).to_not eq @entry
|
47
|
+
expect(Rush::Entry.new(@entry.full_path)).to eq @entry
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can rename itself' do
|
51
|
+
new_file = 'test2'
|
52
|
+
|
53
|
+
@entry.rename(new_file)
|
54
|
+
|
55
|
+
expect(File.exist?(@filename)).to eq false
|
56
|
+
expect(File.exist?("#{@sandbox_dir}/#{new_file}")).to eq true
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'rename returns the renamed file' do
|
60
|
+
expect(@entry.rename('file2')).to eq @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
|
+
expect { @entry.rename(new_file) }.to raise_error(Rush::NameAlreadyExists, /#{new_file}/)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "can't rename itself to something with a slash in it" do
|
71
|
+
expect { @entry.rename('has/slash') }.to raise_error(Rush::NameCannotContainSlash, /slash/)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'can duplicate itself within the directory' do
|
75
|
+
expect(@entry.duplicate('newfile')).to eq 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
|
+
expect(File.exist?(@filename)).to eq false
|
86
|
+
expect(File.exist?("#{newdir}/#{@entry.name}")).to eq 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
|
+
expect(File.exist?(@filename)).to eq true
|
97
|
+
expect(File.exist?("#{newdir}/#{@entry.name}")).to eq true
|
98
|
+
|
99
|
+
expect(@copied_dir.full_path).to eq "#{@sandbox_dir}newdir/#{@entry.name}"
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'can symlink itself as file' do
|
103
|
+
newdir = "#{@sandbox_dir}newdir"
|
104
|
+
system "mkdir -p #{newdir}"
|
105
|
+
|
106
|
+
dst = newdir + "/link"
|
107
|
+
link = @entry.symlink(dst)
|
108
|
+
|
109
|
+
expect(File.exist?(dst)).to eq true
|
110
|
+
expect(File.symlink?(dst)).to eq true
|
111
|
+
expect(link.symlink?).to eq true
|
112
|
+
|
113
|
+
expect(link.full_path).to eq dst
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'can symlink itself as directory' do
|
117
|
+
newdir = "#{@sandbox_dir}newdir"
|
118
|
+
system "mkdir -p #{newdir}"
|
119
|
+
dir = Rush::Dir.new( newdir + "/direct/")
|
120
|
+
dir.create
|
121
|
+
|
122
|
+
dst = newdir + "/linked"
|
123
|
+
link = dir.symlink(dst)
|
124
|
+
|
125
|
+
expect(Dir.exist?(dst)).to eq true
|
126
|
+
expect(File.symlink?(dst)).to eq true
|
127
|
+
|
128
|
+
expect(link.full_path).to eq dst + '/'
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'considers dotfiles to be hidden' do
|
132
|
+
expect(Rush::Entry.new("#{@sandbox_dir}/show")).to_not be_hidden
|
133
|
+
expect(Rush::Entry.new("#{@sandbox_dir}/.dont_show")).to be_hidden
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'is considered equal to entries with the same full path and on the same box' do
|
137
|
+
same = Rush::Entry.new(@entry.full_path, @entry.box)
|
138
|
+
expect(@entry).to eq same
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'is considered not equal to entries with the same full path on a different box' do
|
142
|
+
same = Rush::Entry.new(@entry.full_path, Rush::Box.new('dummy'))
|
143
|
+
expect(@entry).to_not eq same
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'can mimic another entry' do
|
147
|
+
copy = Rush::Entry.new('abc', :dummy)
|
148
|
+
copy.mimic(@entry)
|
149
|
+
expect(copy.path).to eq @entry.path
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'can update the read access permission' do
|
153
|
+
system "chmod 666 #{@filename}"
|
154
|
+
@entry.access = { :user_can => :read }
|
155
|
+
expect(`ls -l #{@filename}`).to match(/^-r--------/)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'reads the file permissions in the access hash' do
|
159
|
+
system "chmod 640 #{@filename}"
|
160
|
+
expect(@entry.access).to eq({ user_can_read: true, user_can_write: true, group_can_read: true })
|
161
|
+
end
|
162
|
+
end
|
data/spec/file_spec.rb
ADDED
@@ -0,0 +1,95 @@
|
|
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
|
+
expect(@file).to be_kind_of(Rush::Entry)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'is not a dir' do
|
25
|
+
expect(@file).to_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
|
+
expect(create_me.create).to eq create_me
|
31
|
+
expect(File.exist?("#{@sandbox_dir}/create_me")).to eq true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'can hardlink itself' do
|
35
|
+
newdir = "#{@sandbox_dir}newdir"
|
36
|
+
system "mkdir -p #{newdir}"
|
37
|
+
|
38
|
+
dst = newdir + "/link"
|
39
|
+
link = @file.link(dst)
|
40
|
+
|
41
|
+
expect(File.exist?(dst)).to eq true
|
42
|
+
|
43
|
+
expect(link.full_path).to eq dst
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'knows its size in bytes' do
|
47
|
+
expect(@file.size).to eq @contents.length
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can read its contents' do
|
51
|
+
expect(@file.contents).to eq @contents
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'read is an alias for contents' do
|
55
|
+
expect(@file.read).to eq @contents
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'can write new contents' do
|
59
|
+
@file.write('write test')
|
60
|
+
expect(@file.contents).to eq 'write test'
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'can count the number of lines it contains' do
|
64
|
+
@file.write("1\n2\n3\n")
|
65
|
+
expect(@file.line_count).to eq 3
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'searches its contents for matching lines' do
|
69
|
+
@file.write("a\n1\nb\n2\n")
|
70
|
+
expect(@file.search(/\d/)).to eq %w(1 2)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'search returns nil if no lines match' do
|
74
|
+
@file.write("a\nb\nc\n")
|
75
|
+
expect(@file.search(/\d/)).to eq nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'find-in-file replace' do
|
79
|
+
@file.replace_contents!(/\d/, 'x')
|
80
|
+
expect(@file.contents).to eq "xxxx\n"
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'can destroy itself' do
|
84
|
+
@file.destroy
|
85
|
+
expect(::File.exist?(@filename)).to eq false
|
86
|
+
end
|
87
|
+
|
88
|
+
it "can fetch contents or blank if doesn't exist" do
|
89
|
+
expect(Rush::File.new('/does/not/exist').contents_or_blank).to eq ''
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'can fetch lines, or empty if doesn\'t exist' do
|
93
|
+
expect(Rush::File.new('/does/not/exist').lines_or_empty).to eq []
|
94
|
+
end
|
95
|
+
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
|
+
expect(@list.compare_or_match('1', '1')).to eq true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "compare_or_match exact match failure" do
|
24
|
+
expect(@list.compare_or_match('1', '2')).to eq false
|
25
|
+
end
|
26
|
+
|
27
|
+
it "compare_or_match regexp match success" do
|
28
|
+
expect(@list.compare_or_match('123', /2/)).to eq true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "compare_or_match regexp match failure" do
|
32
|
+
expect(@list.compare_or_match('123', /x/)).to eq false
|
33
|
+
end
|
34
|
+
|
35
|
+
it "find_by_ extact match" do
|
36
|
+
expect(@list.find_by_bar('two')).to eq @two
|
37
|
+
end
|
38
|
+
|
39
|
+
it "find_by_ regexp match" do
|
40
|
+
expect(@list.find_by_bar(/.hree/)).to eq @three
|
41
|
+
end
|
42
|
+
|
43
|
+
it "find_all_by_ exact match" do
|
44
|
+
expect(@list.find_all_by_bar('one')).to eq [ @one ]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "find_all_by_ regexp match" do
|
48
|
+
expect(@list.find_all_by_bar(/^...$/)).to eq [ @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
|
+
expect { @list.does_not_exist }.to raise_error(NoMethodError)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
describe Integer do
|
4
|
+
before do
|
5
|
+
@num = 2
|
6
|
+
end
|
7
|
+
|
8
|
+
it "counts kb" do
|
9
|
+
expect(@num.kb).to eq 2*1024
|
10
|
+
end
|
11
|
+
|
12
|
+
it "counts mb" do
|
13
|
+
expect(@num.mb).to eq 2*1024*1024
|
14
|
+
end
|
15
|
+
|
16
|
+
it "counts gb" do
|
17
|
+
expect(@num.gb).to eq 2*1024*1024*1024
|
18
|
+
end
|
19
|
+
end
|
data/spec/local_spec.rb
ADDED
@@ -0,0 +1,363 @@
|
|
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
|
+
expect(@con).to 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
|
+
expect(@con).to 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
|
+
expect(@con).to receive(:file_contents).with('file').and_return('the contents')
|
27
|
+
expect(@con.receive(:action => 'file_contents', :full_path => 'file')).to eq 'the contents'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "receive -> destroy(file or dir)" do
|
31
|
+
expect(@con).to receive(:destroy).with('file')
|
32
|
+
@con.receive(:action => 'destroy', :full_path => 'file')
|
33
|
+
end
|
34
|
+
|
35
|
+
it "receive -> purge(dir)" do
|
36
|
+
expect(@con).to receive(:purge).with('dir')
|
37
|
+
@con.receive(:action => 'purge', :full_path => 'dir')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "receive -> create_dir(path)" do
|
41
|
+
expect(@con).to 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
|
+
expect(@con).to 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
|
+
expect(@con).to 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
|
+
expect(@con).to receive(:read_archive).with('full_path').and_return('archive data')
|
57
|
+
expect(@con.receive(:action => 'read_archive', :full_path => 'full_path')).to eq 'archive data'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "receive -> write_archive(archive, dir)" do
|
61
|
+
expect(@con).to 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
|
+
expect(@con).to receive(:index).with('base_path', '*').and_return(%w(1 2))
|
67
|
+
expect(@con.receive(:action => 'index', :base_path => 'base_path', :glob => '*')).to eq "1\n2\n"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "receive -> stat(full_path)" do
|
71
|
+
expect(@con).to receive(:stat).with('full_path').and_return(1 => 2)
|
72
|
+
expect(@con.receive(:action => 'stat', :full_path => 'full_path')).to eq YAML.dump(1 => 2)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "receive -> set_access(full_path, user, group, permissions)" do
|
76
|
+
access = double("access")
|
77
|
+
expect(Rush::Access).to receive(:from_hash).with(:action => 'set_access', :full_path => 'full_path', :user => 'joe').and_return(access)
|
78
|
+
|
79
|
+
expect(@con).to 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
|
+
expect(@con).to receive(:size).with('full_path').and_return("1024")
|
85
|
+
expect(@con.receive(:action => 'size', :full_path => 'full_path')).to eq "1024"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "receive -> chown(full_path, user, group, options)" do
|
89
|
+
options = { noop: true }
|
90
|
+
expect(@con).to 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
|
+
expect(@con).to receive(:processes).with(no_args).and_return([ { :pid => 1 } ])
|
96
|
+
expect(@con.receive(:action => 'processes')).to eq YAML.dump([ { :pid => 1 } ])
|
97
|
+
end
|
98
|
+
|
99
|
+
it "receive -> process_alive" do
|
100
|
+
expect(@con).to receive(:process_alive).with(123).and_return(true)
|
101
|
+
expect(@con.receive(:action => 'process_alive', :pid => 123)).to eq '1'
|
102
|
+
end
|
103
|
+
|
104
|
+
it "receive -> kill_process" do
|
105
|
+
expect(@con).to 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
|
+
expect(@con).to receive(:bash).with('cmd', 'user', false, true).and_return('output')
|
111
|
+
expect(@con.receive(:action => 'bash', :payload => 'cmd', :user => 'user', :background => 'false', :reset_environment => 'true')).to eq 'output'
|
112
|
+
end
|
113
|
+
|
114
|
+
it "receive -> bash (foreground)" do
|
115
|
+
expect(@con).to receive(:bash).with('cmd', 'user', false, false).and_return('output')
|
116
|
+
expect(@con.receive(:action => 'bash', :payload => 'cmd', :user => 'user', :background => 'false')).to eq 'output'
|
117
|
+
end
|
118
|
+
|
119
|
+
it "receive -> bash (background)" do
|
120
|
+
expect(@con).to receive(:bash).with('cmd', 'user', true, false).and_return('output')
|
121
|
+
expect(@con.receive(:action => 'bash', :payload => 'cmd', :user => 'user', :background => 'true')).to eq 'output'
|
122
|
+
end
|
123
|
+
|
124
|
+
it "receive -> unknown action exception" do
|
125
|
+
expect { @con.receive(:action => 'does_not_exist') }.to 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
|
+
expect(File.read(fname)).to eq 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
|
+
expect(File.read(fname)).to eq "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
|
+
expect(@con.file_contents(fname)).to eq "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
|
+
expect { @con.file_contents(fname) }.to 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
|
+
expect(File.exists?(fname)).to eq 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
|
+
expect(File.exists?(@sandbox_dir)).to eq true
|
164
|
+
expect(Dir.glob("#{@sandbox_dir}/*")).to eq([])
|
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
|
+
expect(File.exist?(@sandbox_dir)).to eq true
|
171
|
+
expect(`cd #{@sandbox_dir}; ls -lA | grep -v total | wc -l`.to_i).to eq 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
|
+
expect(File.directory?(fname)).to eq 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
|
+
expect(File.exists?("#{@sandbox_dir}/a")).to eq false
|
184
|
+
expect(File.exists?("#{@sandbox_dir}/b")).to eq 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
|
+
expect(File.exists?("#{@sandbox_dir}/a")).to eq true
|
192
|
+
expect(File.exists?("#{@sandbox_dir}/subdir/a")).to eq 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
|
+
expect { @con.copy('/does/not/exist', '/tmp') }.to 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
|
+
expect { @con.copy('/tmp', '/does/not/exist') }.to 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
|
+
expect(@con.read_archive(@sandbox_dir).size).to be > 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
|
+
expect(@con.read_archive("#{@sandbox_dir}/with space").size).to be > 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
|
+
expect(File.directory?("#{@sandbox_dir}/dst/a")).to eq true
|
218
|
+
expect(File.exist?("#{@sandbox_dir}/dst/a/b")).to eq 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
|
+
expect(File.directory?("#{@sandbox_dir}/with space/a")).to eq true
|
226
|
+
expect(File.exists?("#{@sandbox_dir}/with space/a/b")).to eq 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
|
+
expect(@con.index(@sandbox_dir, '')).to eq([ '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
|
+
expect(@con.index(@sandbox_dir, '*.rb')).to eq [ 'a.rb' ]
|
237
|
+
end
|
238
|
+
|
239
|
+
it "index raises DoesNotExist when the base path is invalid" do
|
240
|
+
expect { @con.index('/does/not/exist', '*') }.to raise_error(Rush::DoesNotExist, '/does/not/exist')
|
241
|
+
end
|
242
|
+
|
243
|
+
it "stat gives file stats like size and timestamps" do
|
244
|
+
expect(@con.stat(@sandbox_dir)).to have_key(:ctime)
|
245
|
+
expect(@con.stat(@sandbox_dir)).to have_key(:size)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "stat fetches the octal permissions" do
|
249
|
+
expect(@con.stat(@sandbox_dir)[:mode]).to be_kind_of(Integer)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "stat raises DoesNotExist if the entry does not exist" do
|
253
|
+
fname = "#{@sandbox_dir}/does_not_exist"
|
254
|
+
expect { @con.stat(fname) }.to raise_error(Rush::DoesNotExist, fname)
|
255
|
+
end
|
256
|
+
|
257
|
+
it "set_access invokes the access object" do
|
258
|
+
access = double("access")
|
259
|
+
expect(access).to receive(:apply).with('/some/path')
|
260
|
+
@con.set_access('/some/path', access)
|
261
|
+
end
|
262
|
+
|
263
|
+
it "size gives size of a directory and all its contents recursively" do
|
264
|
+
system "mkdir -p #{@sandbox_dir}/a/b/; echo 1234 > #{@sandbox_dir}/a/b/c"
|
265
|
+
expect(@con.size(@sandbox_dir)).to eq (::File.stat(@sandbox_dir).size*3 + 5)
|
266
|
+
end
|
267
|
+
|
268
|
+
it "parses ps output on os x" do
|
269
|
+
expect(@con.parse_ps("21712 501 21711 1236 0 /usr/bin/vi somefile.rb")).to eq({
|
270
|
+
:pid => "21712",
|
271
|
+
:uid => "501",
|
272
|
+
:parent_pid => 21711,
|
273
|
+
:mem => 1236,
|
274
|
+
:cpu => 0,
|
275
|
+
:command => '/usr/bin/vi',
|
276
|
+
:cmdline => '/usr/bin/vi somefile.rb',
|
277
|
+
})
|
278
|
+
end
|
279
|
+
|
280
|
+
it "gets the list of processes on os x via the ps command" do
|
281
|
+
expect(@con).to receive(:os_x_raw_ps).and_return <<EOPS
|
282
|
+
PID UID PPID RSS CPU COMMAND
|
283
|
+
1 0 1 1111 0 cmd1 args
|
284
|
+
2 501 1 222 1 cmd2
|
285
|
+
EOPS
|
286
|
+
expect(@con.os_x_processes).to eq [
|
287
|
+
{ :pid => "1", :uid => "0", :parent_pid => 1, :mem => 1111, :cpu => 0, :command => "cmd1", :cmdline => "cmd1 args" },
|
288
|
+
{ :pid => "2", :uid => "501", :parent_pid => 1, :mem => 222, :cpu => 1, :command => "cmd2", :cmdline => "cmd2" },
|
289
|
+
]
|
290
|
+
end
|
291
|
+
|
292
|
+
it "the current process should be alive" do
|
293
|
+
expect(@con.process_alive(Process.pid)).to eq true
|
294
|
+
end
|
295
|
+
|
296
|
+
it "a made-up process should not be alive" do
|
297
|
+
expect(@con.process_alive(99999)).to eq false
|
298
|
+
end
|
299
|
+
|
300
|
+
it "kills a process by pid sending a TERM" do
|
301
|
+
allow(@con).to receive(:process_alive).and_return(false)
|
302
|
+
expect(::Process).to receive(:kill).with('TERM', 123).once
|
303
|
+
@con.kill_process(123)
|
304
|
+
end
|
305
|
+
|
306
|
+
it "kills a process by pid sending a KILL signal if TERM doesn't work" do
|
307
|
+
allow(@con).to receive(:process_alive).and_return(true)
|
308
|
+
expect(::Process).to receive(:kill).with('TERM', 123).at_least(:twice)
|
309
|
+
expect(::Process).to receive(:kill).with('KILL', 123)
|
310
|
+
@con.kill_process(123)
|
311
|
+
end
|
312
|
+
|
313
|
+
it "kills a process by pid without sending TERM if :wait is zero" do
|
314
|
+
expect(::Process).to_not receive(:kill).with('TERM', 123)
|
315
|
+
expect(::Process).to receive(:kill).with('KILL', 123)
|
316
|
+
@con.kill_process(123, :wait => 0)
|
317
|
+
end
|
318
|
+
|
319
|
+
it "does not raise an error if the process is already dead" do
|
320
|
+
expect(::Process).to receive(:kill).and_raise(Errno::ESRCH)
|
321
|
+
expect { @con.kill_process(123) }.to_not raise_error
|
322
|
+
end
|
323
|
+
|
324
|
+
it "executes a bash command, returning stdout when successful" do
|
325
|
+
expect(@con.bash("echo test")).to eq "test\n"
|
326
|
+
end
|
327
|
+
|
328
|
+
it "executes a bash command, raising and error (with stderr as the message) when return value is nonzero" do
|
329
|
+
expect { @con.bash("no_such_bin") }.to raise_error(Rush::BashFailed, /command not found/)
|
330
|
+
end
|
331
|
+
|
332
|
+
it "executes a bash command as another user using sudo" do
|
333
|
+
expect(@con.bash("echo test2", ENV['USER'])).to eq "test2\n"
|
334
|
+
end
|
335
|
+
|
336
|
+
it "executes a bash command in the background, returning the pid" do
|
337
|
+
expect(@con.bash("true", nil, true)).to be > 0
|
338
|
+
end
|
339
|
+
|
340
|
+
it "ensure_tunnel to match with remote connection" do
|
341
|
+
@con.ensure_tunnel
|
342
|
+
end
|
343
|
+
|
344
|
+
it "always returns true on alive?" do
|
345
|
+
expect(@con).to be_alive
|
346
|
+
end
|
347
|
+
|
348
|
+
it "resolves a unix uid to a user" do
|
349
|
+
expect(@con.resolve_unix_uid_to_user(0)).to eq "root"
|
350
|
+
expect(@con.resolve_unix_uid_to_user('0')).to eq "root"
|
351
|
+
end
|
352
|
+
|
353
|
+
it "returns nil if the unix uid does not exist" do
|
354
|
+
expect(@con.resolve_unix_uid_to_user(9999)).to eq nil
|
355
|
+
end
|
356
|
+
|
357
|
+
it "iterates through a process list and resolves the unix uid for each" do
|
358
|
+
list = [ { :uid => 0, :command => 'pureftpd' }, { :uid => 9999, :command => 'defunk' } ]
|
359
|
+
expect(@con.resolve_unix_uids(list))
|
360
|
+
.to eq([{ :uid => 0, :user => 'root', :command => 'pureftpd' },
|
361
|
+
{ :uid => 9999, :command => 'defunk', :user => nil }])
|
362
|
+
end
|
363
|
+
end
|