Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

msfupdate_spec.rb 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. require 'spec_helper'
  2. load Metasploit::Framework.root.join('msfupdate').to_path
  3. RSpec.describe Msfupdate do
  4. def dummy_pathname
  5. Pathname.new(File.dirname(__FILE__)).join('dummy')
  6. end
  7. def dummy_git_pathname
  8. dummy_pathname.join('gitbase')
  9. end
  10. def dummy_install_pathname
  11. dummy_pathname.join('installbase').join('msf3')
  12. end
  13. def dummy_apt_pathname
  14. dummy_pathname.join('aptbase')
  15. end
  16. let(:msfbase_dir) do
  17. dummy_git_pathname
  18. end
  19. let(:stdin) { StringIO.new("", "rb") }
  20. let(:stdout) { StringIO.new("", "wb") }
  21. let(:stderr) { StringIO.new("", "wb") }
  22. subject do
  23. Msfupdate.new(msfbase_dir, stdin, stdout, stderr)
  24. end
  25. before(:context) do
  26. # Create some fake directories to mock our different install environments
  27. dummy_pathname.mkpath
  28. dummy_apt_pathname.join('.apt').mkpath
  29. dummy_git_pathname.join('.git').mkpath
  30. dummy_install_pathname.mkpath
  31. dummy_install_pathname.join('..', 'engine').mkpath
  32. FileUtils.touch(dummy_install_pathname.join('..', 'engine', 'update.rb'))
  33. end
  34. after(:context) do
  35. dummy_pathname.rmtree
  36. end
  37. before(:example) do
  38. # By default, we want to ensure tests never actually try to execute any
  39. # of the update methods unless we are explicitly testing them
  40. allow(subject).to receive(:update_binary_install!)
  41. allow(subject).to receive(:update_git!)
  42. end
  43. context "#parse_args" do
  44. it "doesn't alter ARGV" do
  45. ARGV.clear
  46. ARGV << 'foo'
  47. subject.parse_args(['x', 'y'])
  48. expect(ARGV).to eq ['foo']
  49. end
  50. context "with --help" do
  51. let(:args) { ['--help'] }
  52. it "calls usage" do
  53. expect(subject).to receive(:usage)
  54. begin
  55. subject.parse_args(args)
  56. rescue SystemExit
  57. end
  58. end
  59. it "exits before updating" do
  60. expect {subject.parse_args(args)}.to raise_error(SystemExit)
  61. end
  62. end
  63. context "with --git-branch" do
  64. let(:git_branch) { 'foo' }
  65. let(:args) { ['--git-branch', git_branch] }
  66. it "sets @git_branch" do
  67. subject.parse_args(args)
  68. expect(subject.instance_variable_get(:@git_branch)).to eq git_branch
  69. end
  70. context "without a space" do
  71. let(:args) { ["--git-branch=#{git_branch}"] }
  72. it "sets @git_branch" do
  73. subject.parse_args(args)
  74. expect(subject.instance_variable_get(:@git_branch)).to eq git_branch
  75. end
  76. end
  77. end
  78. context "with --git-remote" do
  79. let(:git_remote) { 'foo' }
  80. let(:args) { ['--git-remote', git_remote] }
  81. it "sets @git_remote" do
  82. subject.parse_args(args)
  83. expect(subject.instance_variable_get(:@git_remote)).to eq git_remote
  84. end
  85. context "without a space" do
  86. let(:args) { ["--git-remote=#{git_remote}"] }
  87. it "sets @git_remote" do
  88. subject.parse_args(args)
  89. expect(subject.instance_variable_get(:@git_remote)).to eq git_remote
  90. end
  91. end
  92. end
  93. context "with --offline-file" do
  94. let(:offline_file) { 'foo' }
  95. let(:args) { ['--offline-file', offline_file] }
  96. it "sets @offline_file" do
  97. subject.parse_args(args)
  98. expect(subject.instance_variable_get(:@offline_file)).to match Regexp.new(Regexp.escape(offline_file))
  99. end
  100. context "with relative path" do
  101. it "transforms argument into an absolute path" do
  102. subject.parse_args(args)
  103. expect(subject.instance_variable_get(:@offline_file)).to eq File.join(Dir.pwd, offline_file)
  104. end
  105. end
  106. context "with absolute path" do
  107. let(:offline_file) { '/tmp/foo' }
  108. it "accepts an absolute path" do
  109. subject.parse_args(args)
  110. expect(subject.instance_variable_get(:@offline_file)).to eq offline_file
  111. end
  112. end
  113. context "without a space" do
  114. let(:args) { ["--offline-file=#{offline_file}"] }
  115. it "sets @offline_file" do
  116. subject.parse_args(["--offline-file=#{offline_file}"])
  117. expect(subject.instance_variable_get(:@offline_file)).to match Regexp.new(Regexp.escape(offline_file))
  118. end
  119. end
  120. end
  121. context "with wait" do
  122. let(:args) { ['wait'] }
  123. it "sets @actually_wait" do
  124. subject.parse_args(args)
  125. expect(subject.instance_variable_get(:@actually_wait)).to eq true
  126. end
  127. end
  128. context "with nowait" do
  129. let(:args) { ['nowait'] }
  130. it "sets @actually_wait" do
  131. subject.parse_args(args)
  132. expect(subject.instance_variable_get(:@actually_wait)).to eq false
  133. end
  134. end
  135. end
  136. context "#run!" do
  137. before(:example) do
  138. subject.parse_args(args)
  139. end
  140. let(:args) { [] }
  141. it "calls validate_args" do
  142. expect(subject).to receive(:validate_args) { true }
  143. subject.run!
  144. end
  145. it "exits if arguments are invalid" do
  146. allow(subject).to receive(:validate_args).and_return(false)
  147. expect(subject).to receive(:maybe_wait_and_exit).and_raise(SystemExit)
  148. expect { subject.run! }.to raise_error(SystemExit)
  149. end
  150. end
  151. context "in an apt installation" do
  152. let(:msfbase_dir) { dummy_apt_pathname }
  153. it { expect(subject.apt?).to be_truthy }
  154. it { expect(subject.binary_install?).to be_falsey }
  155. it { expect(subject.git?).to be_falsey }
  156. context "#validate_args" do
  157. before(:example) do
  158. subject.parse_args(args)
  159. end
  160. context "with no args" do
  161. let(:args) { [] }
  162. it { expect(subject.validate_args).to be_truthy }
  163. end
  164. context "with --git-remote" do
  165. let(:args) { ['--git-remote', 'foo'] }
  166. it { expect(subject.validate_args).to be_falsey }
  167. end
  168. context "with --git-branch" do
  169. let(:args) { ['--git-branch', 'foo'] }
  170. it { expect(subject.validate_args).to be_falsey }
  171. end
  172. context "with --offline-file" do
  173. let(:args) { ['--offline-file', 'foo'] }
  174. it { expect(subject.validate_args).to be_falsey }
  175. end
  176. end
  177. context "#run!" do
  178. it "does not call update_binary_install!" do
  179. expect(subject).not_to receive(:update_binary_install!)
  180. subject.run!
  181. end
  182. it "does not call update_git!" do
  183. expect(subject).not_to receive(:update_git!)
  184. subject.run!
  185. end
  186. end
  187. end
  188. context "in a binary installation" do
  189. let(:msfbase_dir) { dummy_install_pathname }
  190. it { expect(subject.apt?).to be_falsey }
  191. it { expect(subject.binary_install?).to be_truthy }
  192. it { expect(subject.git?).to be_falsey }
  193. context "#validate_args" do
  194. before(:example) do
  195. subject.parse_args(args)
  196. end
  197. context "with no args" do
  198. let(:args) { [] }
  199. it { expect(subject.validate_args).to be_truthy }
  200. end
  201. context "with --git-remote" do
  202. let(:args) { ['--git-remote', 'foo'] }
  203. it { expect(subject.validate_args).to be_falsey }
  204. end
  205. context "with --git-branch" do
  206. let(:args) { ['--git-branch', 'foo'] }
  207. it { expect(subject.validate_args).to be_falsey }
  208. end
  209. context "with --offline-file" do
  210. let(:args) { ['--offline-file', 'foo'] }
  211. it { expect(subject.validate_args).to be_truthy }
  212. end
  213. end
  214. context "#run!" do
  215. it "calls update_binary_install!" do
  216. expect(subject).to receive(:update_binary_install!)
  217. subject.run!
  218. end
  219. it "does not call update_git!" do
  220. expect(subject).not_to receive(:update_git!)
  221. subject.run!
  222. end
  223. end
  224. context "#update_binary_install!" do
  225. # TODO: Add more tests!
  226. end
  227. end
  228. context "in a git installation" do
  229. let(:msfbase_dir) { dummy_git_pathname }
  230. it { expect(subject.apt?).to be_falsey }
  231. it { expect(subject.binary_install?).to be_falsey }
  232. it { expect(subject.git?).to be_truthy }
  233. context "#validate_args" do
  234. before(:example) do
  235. subject.parse_args(args)
  236. end
  237. context "with no args" do
  238. let(:args) { [] }
  239. it { expect(subject.validate_args).to be_truthy }
  240. end
  241. context "with --git-remote" do
  242. let(:args) { ['--git-remote', 'foo'] }
  243. it { expect(subject.validate_args).to be_truthy }
  244. end
  245. context "with --git-branch" do
  246. let(:args) { ['--git-branch', 'foo'] }
  247. it { expect(subject.validate_args).to be_truthy }
  248. end
  249. context "with --offline-file" do
  250. let(:args) { ['--offline-file', 'foo'] }
  251. it { expect(subject.validate_args).to be_falsey }
  252. end
  253. end
  254. context "#run!" do
  255. it "does not call update_binary_install!" do
  256. expect(subject).not_to receive(:update_binary_install!)
  257. subject.run!
  258. end
  259. it "calls update_git!" do
  260. expect(subject).to receive(:update_git!)
  261. subject.run!
  262. end
  263. end
  264. context "#update_git!" do
  265. # TODO: Add more tests!
  266. end
  267. end
  268. end