Merge remote-tracking branch 'origin/bugfix/additional-software-upgrade-failed-messag...
[tails-test.git] / features / step_definitions / common_steps.rb
blobaa0268db9b5aeaf2586bafc499a62c9a8ea13e94
1 require 'fileutils'
3 def post_vm_start_hook
4   # Sometimes the first click is lost (presumably it's used to give
5   # focus to virt-viewer or similar) so we do that now rather than
6   # having an important click lost. The point we click should be
7   # somewhere where no clickable elements generally reside.
8   @screen.click(@screen.width, @screen.height/2)
9 end
11 def activate_filesystem_shares
12   # XXX-9p: First of all, filesystem shares cannot be mounted while we
13   # do a snapshot save+restore, so unmounting+remounting them seems
14   # like a good idea. However, the 9p modules get into a broken state
15   # during the save+restore, so we also would like to unload+reload
16   # them, but loading of 9pnet_virtio fails after a restore with
17   # "probe of virtio2 failed with error -2" (in dmesg) which makes the
18   # shares unavailable. Hence we leave this code commented for now.
19   #for mod in ["9pnet_virtio", "9p"] do
20   #  @vm.execute("modprobe #{mod}")
21   #end
23   @vm.list_shares.each do |share|
24     @vm.execute("mkdir -p #{share}")
25     @vm.execute("mount -t 9p -o trans=virtio #{share} #{share}")
26   end
27 end
29 def deactivate_filesystem_shares
30   @vm.list_shares.each do |share|
31     @vm.execute("umount #{share}")
32   end
34   # XXX-9p: See XXX-9p above
35   #for mod in ["9p", "9pnet_virtio"] do
36   #  @vm.execute("modprobe -r #{mod}")
37   #end
38 end
40 def restore_background
41   @vm.restore_snapshot($background_snapshot)
42   @vm.wait_until_remote_shell_is_up
43   post_vm_start_hook
45   # XXX-9p: See XXX-9p above
46   #activate_filesystem_shares
48   # The guest's Tor's circuits' states are likely to get out of sync
49   # with the other relays, so we ensure that we have fresh circuits.
50   # Time jumps and incorrect clocks also confuses Tor in many ways.
51   if @vm.has_network?
52     if @vm.execute("service tor status").success?
53       @vm.execute("service tor stop")
54       @vm.execute("killall vidalia")
55       @vm.host_to_guest_time_sync
56       @vm.execute("service tor start")
57       wait_until_tor_is_working
58       @vm.spawn("/usr/local/sbin/restart-vidalia")
59     end
60   end
61 end
63 Given /^a computer$/ do
64   @vm.destroy if @vm
65   @vm = VM.new($vm_xml_path, $x_display)
66 end
68 Given /^the computer has (\d+) ([[:alpha:]]+) of RAM$/ do |size, unit|
69   next if @skip_steps_while_restoring_background
70   @vm.set_ram_size(size, unit)
71 end
73 Given /^the computer is set to boot from the Tails DVD$/ do
74   next if @skip_steps_while_restoring_background
75   @vm.set_cdrom_boot($tails_iso)
76 end
78 Given /^the computer is set to boot from (.+?) drive "(.+?)"$/ do |type, name|
79   next if @skip_steps_while_restoring_background
80   @vm.set_disk_boot(name, type.downcase)
81 end
83 Given /^I plug ([[:alpha:]]+) drive "([^"]+)"$/ do |bus, name|
84   next if @skip_steps_while_restoring_background
85   @vm.plug_drive(name, bus.downcase)
86   if @vm.is_running?
87     step "drive \"#{name}\" is detected by Tails"
88   end
89 end
91 Then /^drive "([^"]+)" is detected by Tails$/ do |name|
92   next if @skip_steps_while_restoring_background
93   if @vm.is_running?
94     try_for(10, :msg => "Drive '#{name}' is not detected by Tails") {
95       @vm.disk_detected?(name)
96     }
97   else
98     STDERR.puts "Cannot tell if drive '#{name}' is detected by Tails: " +
99                 "Tails is not running"
100   end
103 Given /^the network is plugged$/ do
104   next if @skip_steps_while_restoring_background
105   @vm.plug_network
108 Given /^the network is unplugged$/ do
109   next if @skip_steps_while_restoring_background
110   @vm.unplug_network
113 Given /^I capture all network traffic$/ do
114   # Note: We don't want skip this particular stpe if
115   # @skip_steps_while_restoring_background is set since it starts
116   # something external to the VM state.
117   @sniffer = Sniffer.new("TestSniffer", @vm.net.bridge_name, @vm.mac)
118   @sniffer.capture
121 Given /^I set Tails to boot with options "([^"]*)"$/ do |options|
122   next if @skip_steps_while_restoring_background
123   @boot_options = options
126 When /^I start the computer$/ do
127   next if @skip_steps_while_restoring_background
128   assert(!@vm.is_running?,
129          "Trying to start a VM that is already running")
130   @vm.start
131   post_vm_start_hook
134 When /^I power off the computer$/ do
135   next if @skip_steps_while_restoring_background
136   assert(@vm.is_running?,
137          "Trying to power off an already powered off VM")
138   @vm.power_off
141 When /^I cold reboot the computer$/ do
142   next if @skip_steps_while_restoring_background
143   step "I power off the computer"
144   step "I start the computer"
147 When /^I destroy the computer$/ do
148   next if @skip_steps_while_restoring_background
149   @vm.destroy
152 Given /^the computer boots Tails$/ do
153   next if @skip_steps_while_restoring_background
154   @screen.wait('TailsBootSplash.png', 30)
155   @screen.wait('TailsBootSplashTabMsg.png', 10)
156   @screen.type("\t")
157   @screen.waitVanish('TailsBootSplashTabMsg.png', 1)
158   @screen.type(" autotest_never_use_this_option #{@boot_options}" +
159                Sikuli::KEY_RETURN)
160   @screen.wait('TailsGreeter.png', 15*60)
161   @vm.wait_until_remote_shell_is_up
162   activate_filesystem_shares
165 Given /^I log in to a new session$/ do
166   next if @skip_steps_while_restoring_background
167   @screen.wait_and_click('TailsGreeterLoginButton.png', 10)
170 Given /^I enable more Tails Greeter options$/ do
171   next if @skip_steps_while_restoring_background
172   match = @screen.find('TailsGreeterMoreOptions.png')
173   pos_x = match.x + match.width/2
174   # height*2 may seem odd, but we want to click the button below the
175   # match. This may even work accross different screen resolutions.
176   pos_y = match.y + match.height*2
177   @screen.click(pos_x, pos_y)
178   @screen.wait_and_click('TailsGreeterForward.png', 10)
179   @screen.wait('TailsGreeterLoginButton.png', 20)
182 Given /^I set sudo password "([^"]*)"$/ do |password|
183   @sudo_password = password
184   next if @skip_steps_while_restoring_background
185   @screen.wait("TailsGreeterAdminPassword.png", 20)
186   match = @screen.find('TailsGreeterPassword.png')
187   # width*3 may seem odd, but we want to click the field right of the
188   # match. This may even work accross different screen resolutions.
189   pos_x = match.x + match.width*3
190   pos_y = match.y + match.height/2
191   @screen.click(pos_x, pos_y)
192   @screen.type(@sudo_password + "\t" + @sudo_password)
195 Given /^Tails Greeter has dealt with the sudo password$/ do
196   next if @skip_steps_while_restoring_background
197   f1 = "/etc/sudoers.d/tails-greeter"
198   f2 = "#{f1}-no-password-lecture"
199   try_for(20) {
200     @vm.execute("test -e '#{f1}' -o -e '#{f2}'").success?
201   }
204 Given /^GNOME has started$/ do
205   next if @skip_steps_while_restoring_background
206   case @theme
207   when "winxp"
208     desktop_started_picture = 'WinXPStartButton.png'
209   else
210     desktop_started_picture = 'GnomeApplicationsMenu.png'
211   end
212   @screen.wait(desktop_started_picture, 180)
215 Then /^Tails seems to have booted normally$/ do
216   next if @skip_steps_while_restoring_background
217   step "GNOME has started"
220 Given /^I have a network connection$/ do
221   next if @skip_steps_while_restoring_background
222   try_for(120) { @vm.has_network? }
225 Given /^Tor has built a circuit$/ do
226   next if @skip_steps_while_restoring_background
227   wait_until_tor_is_working
230 Given /^the time has synced$/ do
231   next if @skip_steps_while_restoring_background
232   ["/var/run/tordate/done", "/var/run/htpdate/success"].each do |file|
233     try_for(300) { @vm.execute("test -e #{file}").success? }
234   end
237 Given /^Iceweasel has autostarted and is not loading a web page$/ do
238   next if @skip_steps_while_restoring_background
239   case @theme
240   when "winxp"
241     iceweasel_picture = "WinXPIceweaselWindow.png"
242   else
243     iceweasel_picture = "IceweaselRunning.png"
244   end
246   # Stop iceweasel to load its home page. We do this to prevent Tor
247   # from getting confused in case we save and restore a snapshot in
248   # the middle of loading a page.
249   @screen.wait_and_click(iceweasel_picture, 120)
250   @screen.type("l", Sikuli::KEY_CTRL)
251   @screen.type("about:blank" + Sikuli::KEY_RETURN)
254 Given /^I have closed all annoying notifications$/ do
255   next if @skip_steps_while_restoring_background
256   case @theme
257   when "winxp"
258     notification_picture = "WinXPNotificationX.png"
259   else
260     notification_picture = "GnomeNotificationX.png"
261   end
263   # First we wait a short while to give notifications a chance to show
264   begin
265     @screen.wait(notification_picture, 10)
266   rescue
267     # noop
268   end
270   begin
271     # note that we cannot use find_all as the resulting matches will
272     # have the positions from before we start closing notificatios,
273     # but closing them will change the positions.
274     while match = @screen.find(notification_picture)
275       @screen.click(match.x + match.width/2, match.y + match.height/2)
276     end
277   rescue Sikuli::ImageNotFound
278     # noop
279   end
282 Given /^I save the state so the background can be restored next scenario$/ do
283   if @skip_steps_while_restoring_background
284     assert(File.size?($background_snapshot),
285            "We have been skipping steps but there is no snapshot to restore")
286   else
287     # To be sure we run the feature from scratch we remove any
288     # leftover snapshot that wasn't removed.
289     if File.exist?($background_snapshot)
290       File.delete($background_snapshot)
291     end
292     # Workaround: when libvirt takes ownership of the snapshot it may
293     # become unwritable for the user running this script so it cannot
294     # be removed during clean up.
295     FileUtils.touch($background_snapshot)
296     FileUtils.chmod(0666, $background_snapshot)
298     # Snapshots cannot be saved while filesystem shares are mounted
299     # XXX-9p: See XXX-9p above.
300     #deactivate_filesystem_shares
302     @vm.save_snapshot($background_snapshot)
303   end
304   restore_background
305   # Now we stop skipping steps from the snapshot restore.
306   @skip_steps_while_restoring_background = false
309 Then /^I see "([^"]*)" after at most (\d+) seconds$/ do |image, time|
310   next if @skip_steps_while_restoring_background
311   @screen.wait(image, time.to_i)
314 Then /^all Internet traffic has only flowed through Tor$/ do
315   next if @skip_steps_while_restoring_background
316   leaks = FirewallLeakCheck.new(@sniffer.pcap_file, get_tor_relays)
317   if !leaks.empty?
318     if !leaks.ipv4_tcp_leaks.empty?
319       puts "The following IPv4 TCP non-Tor Internet hosts were contacted:"
320       puts leaks.ipv4_tcp_leaks.join("\n")
321       puts
322     end
323     if !leaks.ipv4_nontcp_leaks.empty?
324       puts "The following IPv4 non-TCP Internet hosts were contacted:"
325       puts leaks.ipv4_nontcp_leaks.join("\n")
326       puts
327     end
328     if !leaks.ipv6_leaks.empty?
329       puts "The following IPv6 Internet hosts were contacted:"
330       puts leaks.ipv6_leaks.join("\n")
331       puts
332     end
333     if !leaks.nonip_leaks.empty?
334       puts "Some non-IP packets were sent\n"
335     end
336     save_pcap_file
337     raise "There were network leaks!"
338   end
341 When /^I open the GNOME run dialog$/ do
342   next if @skip_steps_while_restoring_background
343   @screen.type(Sikuli::KEY_F2, Sikuli::KEY_ALT)
344   case @theme
345   when "winxp"
346     run_dialog_picture = 'WinXPRunDialog.png'
347   else
348     run_dialog_picture = 'GnomeRunDialog.png'
349   end
350   @screen.wait(run_dialog_picture, 10)
353 When /^I run "([^"]*)"$/ do |program|
354   next if @skip_steps_while_restoring_background
355   step "I open the GNOME run dialog"
356   @screen.type(program + Sikuli::KEY_RETURN)
359 Given /^I enter the sudo password in the gksu prompt$/ do
360   next if @skip_steps_while_restoring_background
361   @screen.wait('GksuAuthPrompt.png', 60)
362   sleep 1 # wait for weird fade-in to unblock the "Ok" button
363   @screen.type(@sudo_password)
364   @screen.type(Sikuli::KEY_RETURN)
365   @screen.waitVanish('GksuAuthPrompt.png', 10)
368 Given /^I enter the sudo password in the PolicyKit prompt$/ do
369   next if @skip_steps_while_restoring_background
370   step "I enter the \"#{@sudo_password}\" password in the PolicyKit prompt"
373 Given /^I enter the "([^"]*)" password in the PolicyKit prompt$/ do |password|
374   next if @skip_steps_while_restoring_background
375   @screen.wait('PolicyKitAuthPrompt.png', 60)
376   sleep 1 # wait for weird fade-in to unblock the "Ok" button
377   @screen.type(password)
378   @screen.type(Sikuli::KEY_RETURN)
379   @screen.waitVanish('PolicyKitAuthPrompt.png', 10)
382 Given /^process "([^"]+)" is running$/ do |process|
383   next if @skip_steps_while_restoring_background
384   assert(@vm.has_process?(process),
385          "Process '#{process}' is not running")
388 Given /^process "([^"]+)" is not running$/ do |process|
389   next if @skip_steps_while_restoring_background
390   assert(!@vm.has_process?(process),
391          "Process '#{process}' is running")
394 Given /^I kill the process "([^"]+)"$/ do |process|
395   next if @skip_steps_while_restoring_background
396   @vm.execute("killall #{process}")
397   try_for(10, :msg => "Process '#{process}' could not be killed") {
398     !@vm.has_process?(process)
399   }
402 Given /^I completely shutdown Tails$/ do
403   next if @skip_steps_while_restoring_background
404   @screen.hide_cursor
405   @screen.wait_and_click('TailsEmergencyShutdownButton.png', 10)
406   @screen.hide_cursor
407   @screen.wait_and_click('TailsEmergencyShutdownHalt.png', 10)
408   nr_gibs_of_ram = (detected_ram_in_bytes.to_f/(2**30)).ceil
409   try_for(nr_gibs_of_ram*5*60, :msg => "VM is still running") do
410     ! @vm.is_running?
411   end
414 Given /^package "([^"]+)" is installed$/ do |package|
415   next if @skip_steps_while_restoring_background
416   assert(@vm.execute("dpkg -s '#{package}' 2>/dev/null | grep -qs '^Status:.*installed$'").success?,
417          "Package '#{package}' is not installed")