ronin-post_ex 0.1.0.beta1 → 0.1.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 +4 -4
- data/.github/workflows/ruby.yml +1 -0
- data/.yardopts +1 -1
- data/README.md +2 -1
- data/gemspec.yml +4 -3
- data/lib/ronin/post_ex/cli/shell_shell.rb +1 -1
- data/lib/ronin/post_ex/cli/system_shell.rb +1 -1
- data/lib/ronin/post_ex/remote_dir.rb +1 -1
- data/lib/ronin/post_ex/remote_file/stat.rb +1 -1
- data/lib/ronin/post_ex/remote_file.rb +2 -2
- data/lib/ronin/post_ex/remote_process.rb +2 -2
- data/lib/ronin/post_ex/resource.rb +1 -1
- data/lib/ronin/post_ex/sessions/bind_shell.rb +1 -1
- data/lib/ronin/post_ex/sessions/remote_shell_session.rb +1 -1
- data/lib/ronin/post_ex/sessions/reverse_shell.rb +1 -1
- data/lib/ronin/post_ex/sessions/rpc_session.rb +1 -1
- data/lib/ronin/post_ex/sessions/session.rb +1 -1
- data/lib/ronin/post_ex/sessions/shell_session.rb +1 -1
- data/lib/ronin/post_ex/system/fs.rb +2 -2
- data/lib/ronin/post_ex/system/process.rb +1 -1
- data/lib/ronin/post_ex/system/shell.rb +1 -1
- data/lib/ronin/post_ex/system.rb +1 -1
- data/lib/ronin/post_ex/version.rb +2 -2
- data/lib/ronin/post_ex.rb +1 -1
- data/ronin-post_ex.gemspec +2 -1
- metadata +8 -22
- data/spec/sessions/bind_shell_spec.rb +0 -31
- data/spec/sessions/remote_shell_session_spec.rb +0 -28
- data/spec/sessions/reverse_shell_spec.rb +0 -49
- data/spec/sessions/rpc_session_spec.rb +0 -500
- data/spec/sessions/session_spec.rb +0 -61
- data/spec/sessions/shell_session_spec.rb +0 -482
- data/spec/spec_helper.rb +0 -9
- data/spec/system_spec.rb +0 -66
@@ -1,482 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/post_ex/sessions/shell_session'
|
3
|
-
|
4
|
-
require 'socket'
|
5
|
-
|
6
|
-
describe Ronin::PostEx::Sessions::ShellSession do
|
7
|
-
let(:pipe) { UNIXSocket.pair }
|
8
|
-
let(:io) { pipe[0] }
|
9
|
-
let(:shell) { pipe[1] }
|
10
|
-
|
11
|
-
subject { described_class.new(io) }
|
12
|
-
|
13
|
-
describe "#initialize" do
|
14
|
-
it "must set #io" do
|
15
|
-
expect(subject.io).to be(io)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "#shell_gets" do
|
20
|
-
it "must read a line of text from #io" do
|
21
|
-
thread = Thread.new do
|
22
|
-
sleep 0.1
|
23
|
-
shell.write("foo bar\n")
|
24
|
-
end
|
25
|
-
|
26
|
-
expect(subject.shell_gets).to eq("foo bar\n")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "#shell_puts" do
|
31
|
-
let(:line) { "foo bar" }
|
32
|
-
|
33
|
-
it "must write a line of text to #io" do
|
34
|
-
subject.shell_puts(line)
|
35
|
-
|
36
|
-
expect(shell.gets).to eq("#{line}\n")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "#shell_exec" do
|
41
|
-
let(:command) { 'ls' }
|
42
|
-
let(:output) do
|
43
|
-
[
|
44
|
-
"API_SPEC.md",
|
45
|
-
"ChangeLog.md",
|
46
|
-
"COPYING.txt",
|
47
|
-
"Gemfile",
|
48
|
-
"Gemfile.lock",
|
49
|
-
"gemspec.yml",
|
50
|
-
"lib",
|
51
|
-
"Rakefile",
|
52
|
-
"README.md",
|
53
|
-
"ronin-post_ex.gemspec",
|
54
|
-
"spec",
|
55
|
-
"vendor"
|
56
|
-
].map { |line| "#{line}\n" }.join
|
57
|
-
end
|
58
|
-
|
59
|
-
it "must print a beginning deliminator, pipe the command into base64, and print an ending deliminator" do
|
60
|
-
thread = Thread.new do
|
61
|
-
sleep 0.1
|
62
|
-
subject.shell_exec(command)
|
63
|
-
end
|
64
|
-
|
65
|
-
expect(shell.gets).to eq("echo #{described_class::DELIMINATOR}; #{command} 2>/dev/null | base64; echo #{described_class::DELIMINATOR}\n")
|
66
|
-
shell.puts(described_class::DELIMINATOR)
|
67
|
-
shell.write(Base64.encode64(output))
|
68
|
-
shell.puts(described_class::DELIMINATOR)
|
69
|
-
end
|
70
|
-
|
71
|
-
it "must return the output of the command" do
|
72
|
-
thread = Thread.new do
|
73
|
-
sleep 0.1
|
74
|
-
|
75
|
-
shell.gets
|
76
|
-
shell.puts(described_class::DELIMINATOR)
|
77
|
-
shell.write(Base64.encode64(output))
|
78
|
-
shell.puts(described_class::DELIMINATOR)
|
79
|
-
end
|
80
|
-
|
81
|
-
expect(subject.shell_exec(command)).to eq(output)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
describe "#sys_time" do
|
86
|
-
let(:timestamp) { 1668692783 }
|
87
|
-
let(:output) { "#{timestamp}\n" }
|
88
|
-
|
89
|
-
it "must run the 'date +%s' and parse the output as an Integer" do
|
90
|
-
expect(subject).to receive(:shell_exec).with('date +%s').and_return(output)
|
91
|
-
|
92
|
-
expect(subject.sys_time).to eq(timestamp)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe "#sys_hostname" do
|
97
|
-
let(:hostname) { 'computer' }
|
98
|
-
let(:output) { "#{hostname}\n" }
|
99
|
-
|
100
|
-
it "must run the 'echo $HOSTNAME' and parse the output as an Integer" do
|
101
|
-
expect(subject).to receive(:shell_exec).with('echo $HOSTNAME').and_return(output)
|
102
|
-
|
103
|
-
expect(subject.sys_hostname).to eq(hostname)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe "#fs_getcwd" do
|
108
|
-
let(:pwd) { '/current/directory' }
|
109
|
-
let(:output) { "#{pwd}\n" }
|
110
|
-
|
111
|
-
it "must run the 'pwd' command and return the path" do
|
112
|
-
expect(subject).to receive(:shell_exec).with('pwd').and_return(output)
|
113
|
-
|
114
|
-
expect(subject.fs_getcwd).to eq(pwd)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
describe "#fs_chdir" do
|
119
|
-
let(:new_dir) { '/path/to/directory' }
|
120
|
-
let(:output) { "\n" }
|
121
|
-
|
122
|
-
it "must run the 'cd <path> 2>/dev/null' command" do
|
123
|
-
expect(subject).to receive(:shell_puts).with("cd #{new_dir} 2>/dev/null")
|
124
|
-
|
125
|
-
subject.fs_chdir(new_dir)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe "#fs_readfile" do
|
130
|
-
let(:path) { '/path/to/file' }
|
131
|
-
let(:contents) { "foo bar\nbaz qux\n" }
|
132
|
-
|
133
|
-
it "must run the 'cat <path>' command and return the file contents" do
|
134
|
-
expect(subject).to receive(:command_exec).with('cat',path).and_return(contents)
|
135
|
-
|
136
|
-
expect(subject.fs_readfile(path)).to eq(contents)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe "#fs_readlink" do
|
141
|
-
let(:path) { '/path/to/link' }
|
142
|
-
let(:dest_path) { 'path/to/file' }
|
143
|
-
let(:output) { "#{dest_path}\n" }
|
144
|
-
|
145
|
-
it "must run the 'readlink -f <path>' command and return the link's path" do
|
146
|
-
expect(subject).to receive(:command_exec).with('readlink','-f',path).and_return(output)
|
147
|
-
|
148
|
-
expect(subject.fs_readlink(path)).to eq(dest_path)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
describe "#fs_readdir" do
|
153
|
-
let(:path) { '/path/to/dir' }
|
154
|
-
let(:entries) do
|
155
|
-
%w[
|
156
|
-
API_SPEC.md
|
157
|
-
ChangeLog.md
|
158
|
-
COPYING.txt
|
159
|
-
examples
|
160
|
-
Gemfile
|
161
|
-
Gemfile.lock
|
162
|
-
gemspec.yml
|
163
|
-
lib
|
164
|
-
Rakefile
|
165
|
-
README.md
|
166
|
-
ronin-post_ex.gemspec
|
167
|
-
spec
|
168
|
-
vendor
|
169
|
-
]
|
170
|
-
end
|
171
|
-
let(:output) { "#{entries.join("\n")}\n" }
|
172
|
-
|
173
|
-
it "must run the 'ls <path>' command and return the directories entries" do
|
174
|
-
expect(subject).to receive(:command_exec).with('ls',path).and_return(output)
|
175
|
-
|
176
|
-
expect(subject.fs_readdir(path)).to eq(entries)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
describe "#fs_glob" do
|
181
|
-
let(:pattern) { '*.md' }
|
182
|
-
let(:entries) do
|
183
|
-
%w[
|
184
|
-
API_SPEC.md
|
185
|
-
ChangeLog.md
|
186
|
-
README.md
|
187
|
-
]
|
188
|
-
end
|
189
|
-
let(:output) { "#{entries.join("\n")}\n" }
|
190
|
-
|
191
|
-
it "must run the 'ls <pattern>' command and return the matching paths" do
|
192
|
-
expect(subject).to receive(:shell_exec).with("ls #{pattern}").and_return(output)
|
193
|
-
|
194
|
-
expect(subject.fs_glob(pattern)).to eq(entries)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
describe "#fs_mktemp" do
|
199
|
-
let(:basename) { 'ronin-XXXX.txt' }
|
200
|
-
let(:tempfile) { 'ronin-LtFK.txt' }
|
201
|
-
let(:output) { "#{tempfile}\n" }
|
202
|
-
|
203
|
-
it "must run the 'mktemp <basename>' command and return the tempfile name" do
|
204
|
-
expect(subject).to receive(:command_exec).with('mktemp',basename).and_return(output)
|
205
|
-
|
206
|
-
expect(subject.fs_mktemp(basename)).to eq(tempfile)
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
describe "#fs_mkdir" do
|
211
|
-
let(:path) { '/path/to/new_dir' }
|
212
|
-
|
213
|
-
it "must run the 'mkdir <pattern>' command" do
|
214
|
-
expect(subject).to receive(:command_exec).with('mkdir',path)
|
215
|
-
|
216
|
-
subject.fs_mkdir(path)
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
describe "#fs_copy" do
|
221
|
-
let(:src) { '/path/to/src' }
|
222
|
-
let(:dest) { '/path/to/dest' }
|
223
|
-
|
224
|
-
it "must run the 'cp -r <src> <dest>' command" do
|
225
|
-
expect(subject).to receive(:command_exec).with('cp','-r',src,dest)
|
226
|
-
|
227
|
-
subject.fs_copy(src,dest)
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
describe "#fs_unlink" do
|
232
|
-
let(:path) { '/path/to/file' }
|
233
|
-
|
234
|
-
it "must run the 'rm <path>' command" do
|
235
|
-
expect(subject).to receive(:command_exec).with('rm',path)
|
236
|
-
|
237
|
-
subject.fs_unlink(path)
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
describe "#fs_rmdir" do
|
242
|
-
let(:path) { '/path/to/dir' }
|
243
|
-
|
244
|
-
it "must run the 'rmdir <path>' command" do
|
245
|
-
expect(subject).to receive(:command_exec).with('rmdir',path)
|
246
|
-
|
247
|
-
subject.fs_rmdir(path)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
describe "#fs_move" do
|
252
|
-
let(:src) { '/path/to/src' }
|
253
|
-
let(:dest) { '/path/to/dest' }
|
254
|
-
|
255
|
-
it "must run the 'mv <src> <dest>' command" do
|
256
|
-
expect(subject).to receive(:command_exec).with('mv',src,dest)
|
257
|
-
|
258
|
-
subject.fs_move(src,dest)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
describe "#fs_link" do
|
263
|
-
let(:src) { '/path/to/src' }
|
264
|
-
let(:dest) { '/path/to/dest' }
|
265
|
-
|
266
|
-
it "must run the 'ln -s <src> <dest>' command" do
|
267
|
-
expect(subject).to receive(:command_exec).with('ln','-s',src,dest)
|
268
|
-
|
269
|
-
subject.fs_link(src,dest)
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
describe "#fs_chgrp" do
|
274
|
-
let(:group) { 'wheel' }
|
275
|
-
let(:path) { '/path/to/file' }
|
276
|
-
|
277
|
-
it "must run the 'chgrp <group> <path>' command" do
|
278
|
-
expect(subject).to receive(:command_exec).with('chgrp',group,path)
|
279
|
-
|
280
|
-
subject.fs_chgrp(group,path)
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
describe "#fs_chown" do
|
285
|
-
let(:user) { 'root' }
|
286
|
-
let(:path) { '/path/to/file' }
|
287
|
-
|
288
|
-
it "must run the 'chown <user> <path>' command" do
|
289
|
-
expect(subject).to receive(:command_exec).with('chown',user,path)
|
290
|
-
|
291
|
-
subject.fs_chown(user,path)
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
describe "#fs_chmod" do
|
296
|
-
let(:mode) { 0777 }
|
297
|
-
let(:umask) { "%.4o" % mode }
|
298
|
-
let(:path) { '/path/to/file' }
|
299
|
-
|
300
|
-
it "must run the 'chown <user> <path>' command" do
|
301
|
-
expect(subject).to receive(:command_exec).with('chmod',umask,path)
|
302
|
-
|
303
|
-
subject.fs_chmod(mode,path)
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
describe "#fs_stat" do
|
308
|
-
let(:path) { '/path/to/file' }
|
309
|
-
let(:size) { 420 }
|
310
|
-
let(:blocks) { 16 }
|
311
|
-
let(:uid) { 1000 }
|
312
|
-
let(:gid) { 1000 }
|
313
|
-
let(:inode) { 12345 }
|
314
|
-
let(:links) { 1 }
|
315
|
-
let(:atime) { Time.at(1668608914) }
|
316
|
-
let(:mtime) { Time.at(1668427627) }
|
317
|
-
let(:ctime) { Time.at(1668427627) }
|
318
|
-
let(:blocksize) { 1668427627 }
|
319
|
-
|
320
|
-
let(:output) do
|
321
|
-
"#{path} #{size} #{blocks} 81a4 #{uid} #{gid} fd01 #{inode} #{links} 0 0 #{atime.to_i} #{mtime.to_i} #{ctime.to_i} #{blocksize} 4096 unconfined_u:object_r:unlabeled_t:s0\n"
|
322
|
-
end
|
323
|
-
|
324
|
-
it "must run the 'stat -t <path>' command and return a Hash of parsed stat information" do
|
325
|
-
expect(subject).to receive(:command_exec).with('stat','-t',path).and_return(output)
|
326
|
-
|
327
|
-
expect(subject.fs_stat(path)).to eq(
|
328
|
-
{
|
329
|
-
path: path,
|
330
|
-
size: size,
|
331
|
-
blocks: blocks,
|
332
|
-
uid: uid,
|
333
|
-
gid: gid,
|
334
|
-
inode: inode,
|
335
|
-
links: links,
|
336
|
-
atime: atime,
|
337
|
-
mtime: mtime,
|
338
|
-
ctime: ctime,
|
339
|
-
blocksize: blocksize
|
340
|
-
}
|
341
|
-
)
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
describe "#process_getpid" do
|
346
|
-
let(:pid) { 1234 }
|
347
|
-
let(:output) { "#{pid}\n" }
|
348
|
-
|
349
|
-
it "must run the 'echo $$' command and return the parsed PID" do
|
350
|
-
expect(subject).to receive(:shell_exec).with('echo $$').and_return(output)
|
351
|
-
|
352
|
-
expect(subject.process_getpid).to eq(pid)
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
describe "#process_getppid" do
|
357
|
-
let(:ppid) { 1234 }
|
358
|
-
let(:output) { "#{ppid}\n" }
|
359
|
-
|
360
|
-
it "must run the 'echo $PPID' command and return the parsed PPID" do
|
361
|
-
expect(subject).to receive(:shell_exec).with('echo $PPID').and_return(output)
|
362
|
-
|
363
|
-
expect(subject.process_getppid).to eq(ppid)
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
describe "#process_getuid" do
|
368
|
-
let(:uid) { 1000 }
|
369
|
-
let(:output) { "#{uid}\n" }
|
370
|
-
|
371
|
-
it "must run the 'id -u' command and return the parsed UID" do
|
372
|
-
expect(subject).to receive(:command_exec).with('id','-u').and_return(output)
|
373
|
-
|
374
|
-
expect(subject.process_getuid).to eq(uid)
|
375
|
-
end
|
376
|
-
end
|
377
|
-
|
378
|
-
describe "#process_getgid" do
|
379
|
-
let(:gid) { 1000 }
|
380
|
-
let(:output) { "#{gid}\n" }
|
381
|
-
|
382
|
-
it "must run the 'id -g' command and return the parsed GID" do
|
383
|
-
expect(subject).to receive(:command_exec).with('id','-g').and_return(output)
|
384
|
-
|
385
|
-
expect(subject.process_getgid).to eq(gid)
|
386
|
-
end
|
387
|
-
end
|
388
|
-
|
389
|
-
describe "#process_getgid" do
|
390
|
-
let(:env) do
|
391
|
-
{
|
392
|
-
'FOO' => 'foo',
|
393
|
-
'BAR' => 'bar'
|
394
|
-
}
|
395
|
-
end
|
396
|
-
let(:output) do
|
397
|
-
"#{env.keys[0]}=#{env.values[0]}\n#{env.keys[1]}=#{env.values[1]}\n"
|
398
|
-
end
|
399
|
-
|
400
|
-
it "must run the 'env' command and return the parsed env Hash" do
|
401
|
-
expect(subject).to receive(:command_exec).with('env').and_return(output)
|
402
|
-
|
403
|
-
expect(subject.process_environ).to eq(env)
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
|
-
describe "#process_getenv" do
|
408
|
-
let(:name) { 'FOO' }
|
409
|
-
let(:value) { 'foo bar baz' }
|
410
|
-
let(:output) { "#{value}\n" }
|
411
|
-
|
412
|
-
it "must run the 'echo $<name>' command and return the parsed value" do
|
413
|
-
expect(subject).to receive(:shell_exec).with("echo $#{name}").and_return(output)
|
414
|
-
|
415
|
-
expect(subject.process_getenv(name)).to eq(value)
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
|
-
describe "#process_setenv" do
|
420
|
-
let(:name) { 'FOO' }
|
421
|
-
let(:value) { 'foo bar baz' }
|
422
|
-
|
423
|
-
it "must run the 'export <name>=<value>' command and return the parsed value" do
|
424
|
-
expect(subject).to receive(:shell_puts).with("export #{name}=#{value}")
|
425
|
-
|
426
|
-
subject.process_setenv(name,value)
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
describe "#process_unsetenv" do
|
431
|
-
let(:name) { 'FOO' }
|
432
|
-
|
433
|
-
it "must run the 'unset <name>' command" do
|
434
|
-
expect(subject).to receive(:shell_puts).with("unset #{name}")
|
435
|
-
|
436
|
-
subject.process_unsetenv(name)
|
437
|
-
end
|
438
|
-
end
|
439
|
-
|
440
|
-
describe "#process_kill" do
|
441
|
-
let(:pid) { 1234 }
|
442
|
-
let(:signal) { 'TERM' }
|
443
|
-
|
444
|
-
it "must run the 'kill -s <signal> <pid>' command" do
|
445
|
-
expect(subject).to receive(:command_exec).with('kill','-s',signal,pid)
|
446
|
-
|
447
|
-
subject.process_kill(pid,signal)
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
describe "#process_spawn" do
|
452
|
-
let(:command_name) { 'cmd' }
|
453
|
-
let(:arguments) { ['foo', 'bar baz'] }
|
454
|
-
|
455
|
-
let(:pid) { 1234 }
|
456
|
-
let(:output) { "#{pid}\n" }
|
457
|
-
|
458
|
-
it "must run the command with arguments and return the parsed PID" do
|
459
|
-
command = Shellwords.join([command_name, *arguments])
|
460
|
-
|
461
|
-
expect(subject).to receive(:shell_exec).with("#{command} 2>&1 >/dev/null &; echo $!").and_return(output)
|
462
|
-
|
463
|
-
expect(subject.process_spawn(command_name,*arguments)).to eq(pid)
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
describe "#process_exit" do
|
468
|
-
it "must run the 'exit' command" do
|
469
|
-
expect(subject).to receive(:shell_puts).with('exit')
|
470
|
-
|
471
|
-
subject.process_exit
|
472
|
-
end
|
473
|
-
end
|
474
|
-
|
475
|
-
describe "#close" do
|
476
|
-
it "must call #close on #io" do
|
477
|
-
expect(io).to receive(:close)
|
478
|
-
|
479
|
-
subject.close
|
480
|
-
end
|
481
|
-
end
|
482
|
-
end
|
data/spec/spec_helper.rb
DELETED
data/spec/system_spec.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/post_ex/system'
|
3
|
-
require 'ronin/post_ex/sessions/session'
|
4
|
-
|
5
|
-
describe Ronin::PostEx::System do
|
6
|
-
let(:session) { Ronin::PostEx::Sessions::Session.new }
|
7
|
-
|
8
|
-
subject { described_class.new(session) }
|
9
|
-
|
10
|
-
describe "#initialize" do
|
11
|
-
it "must set #session" do
|
12
|
-
expect(subject.session).to be(session)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "must initialize #fs" do
|
16
|
-
expect(subject.fs).to be_kind_of(described_class::FS)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "must initialize #process" do
|
20
|
-
expect(subject.process).to be_kind_of(described_class::Process)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "must initialize #shell" do
|
24
|
-
expect(subject.shell).to be_kind_of(described_class::Shell)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "#fs" do
|
29
|
-
it "must return a System::FS object" do
|
30
|
-
expect(subject.fs).to be_kind_of(described_class::FS)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "#process" do
|
35
|
-
it "must return a System::Process object" do
|
36
|
-
expect(subject.process).to be_kind_of(described_class::Process)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "#shell" do
|
41
|
-
it "must return a System::Shell object" do
|
42
|
-
expect(subject.shell).to be_kind_of(described_class::Shell)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe "#time" do
|
47
|
-
let(:unix_timestamp) { 1642775495 }
|
48
|
-
let(:time) { Time.at(unix_timestamp) }
|
49
|
-
|
50
|
-
it "must call the 'sys_time' API function and return a Time object" do
|
51
|
-
expect(session).to receive(:sys_time).and_return(unix_timestamp)
|
52
|
-
|
53
|
-
expect(subject.time).to eq(time)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "#hostname" do
|
58
|
-
let(:hostname) { 'computer' }
|
59
|
-
|
60
|
-
it "must call the 'sys_hostname' API function and return the hostname" do
|
61
|
-
expect(session).to receive(:sys_hostname).and_return(hostname)
|
62
|
-
|
63
|
-
expect(subject.hostname).to eq(hostname)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|