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_point(@screen.w, @screen.h/2)
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}")
23 @vm.list_shares.each do |share|
24 @vm.execute("mkdir -p #{share}")
25 @vm.execute("mount -t 9p -o trans=virtio #{share} #{share}")
29 def deactivate_filesystem_shares
30 @vm.list_shares.each do |share|
31 @vm.execute("umount #{share}")
34 # XXX-9p: See XXX-9p above
35 #for mod in ["9p", "9pnet_virtio"] do
36 # @vm.execute("modprobe -r #{mod}")
40 def restore_background
41 @vm.restore_snapshot($background_snapshot)
42 @vm.wait_until_remote_shell_is_up
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.
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")
63 def run_dialog_picture
66 return 'WindowsRunDialog.png'
68 return 'GnomeRunDialog.png'
72 Given /^a computer$/ do
74 @vm = VM.new($vm_xml_path, $x_display)
77 Given /^the computer has (\d+) ([[:alpha:]]+) of RAM$/ do |size, unit|
78 next if @skip_steps_while_restoring_background
79 @vm.set_ram_size(size, unit)
82 Given /^the computer is set to boot from the Tails DVD$/ do
83 next if @skip_steps_while_restoring_background
84 @vm.set_cdrom_boot($tails_iso)
87 Given /^the computer is set to boot from (.+?) drive "(.+?)"$/ do |type, name|
88 next if @skip_steps_while_restoring_background
89 @vm.set_disk_boot(name, type.downcase)
92 Given /^I plug ([[:alpha:]]+) drive "([^"]+)"$/ do |bus, name|
93 next if @skip_steps_while_restoring_background
94 @vm.plug_drive(name, bus.downcase)
96 step "drive \"#{name}\" is detected by Tails"
100 Then /^drive "([^"]+)" is detected by Tails$/ do |name|
101 next if @skip_steps_while_restoring_background
103 try_for(10, :msg => "Drive '#{name}' is not detected by Tails") {
104 @vm.disk_detected?(name)
107 STDERR.puts "Cannot tell if drive '#{name}' is detected by Tails: " +
108 "Tails is not running"
112 Given /^the network is plugged$/ do
113 next if @skip_steps_while_restoring_background
117 Given /^the network is unplugged$/ do
118 next if @skip_steps_while_restoring_background
122 Given /^I capture all network traffic$/ do
123 # Note: We don't want skip this particular stpe if
124 # @skip_steps_while_restoring_background is set since it starts
125 # something external to the VM state.
126 @sniffer = Sniffer.new("TestSniffer", @vm.net.bridge_name)
130 Given /^I set Tails to boot with options "([^"]*)"$/ do |options|
131 next if @skip_steps_while_restoring_background
132 @boot_options = options
135 When /^I start the computer$/ do
136 next if @skip_steps_while_restoring_background
137 assert(!@vm.is_running?,
138 "Trying to start a VM that is already running")
143 When /^I power off the computer$/ do
144 next if @skip_steps_while_restoring_background
145 assert(@vm.is_running?,
146 "Trying to power off an already powered off VM")
150 When /^I cold reboot the computer$/ do
151 next if @skip_steps_while_restoring_background
152 step "I power off the computer"
153 step "I start the computer"
156 When /^I destroy the computer$/ do
157 next if @skip_steps_while_restoring_background
161 Given /^the computer boots Tails$/ do
162 next if @skip_steps_while_restoring_background
163 @screen.wait('TailsBootSplash.png', 30)
164 @screen.wait('TailsBootSplashTabMsg.png', 10)
165 @screen.type(Sikuli::Key.TAB)
166 @screen.waitVanish('TailsBootSplashTabMsg.png', 1)
167 @screen.type(" autotest_never_use_this_option #{@boot_options}" +
169 @screen.wait('TailsGreeter.png', 30*60)
170 @vm.wait_until_remote_shell_is_up
171 activate_filesystem_shares
174 Given /^I log in to a new session$/ do
175 next if @skip_steps_while_restoring_background
176 @screen.wait_and_click('TailsGreeterLoginButton.png', 10)
179 Given /^I enable more Tails Greeter options$/ do
180 next if @skip_steps_while_restoring_background
181 match = @screen.find('TailsGreeterMoreOptions.png')
182 @screen.click(match.getCenter.offset(match.w/2, match.h*2))
183 @screen.wait_and_click('TailsGreeterForward.png', 10)
184 @screen.wait('TailsGreeterLoginButton.png', 20)
187 Given /^I set sudo password "([^"]*)"$/ do |password|
188 @sudo_password = password
189 next if @skip_steps_while_restoring_background
190 @screen.wait("TailsGreeterAdminPassword.png", 20)
191 @screen.type(@sudo_password)
192 @screen.type(Sikuli::Key.TAB)
193 @screen.type(@sudo_password)
196 Given /^Tails Greeter has dealt with the sudo password$/ do
197 next if @skip_steps_while_restoring_background
198 f1 = "/etc/sudoers.d/tails-greeter"
199 f2 = "#{f1}-no-password-lecture"
201 @vm.execute("test -e '#{f1}' -o -e '#{f2}'").success?
205 Given /^GNOME has started$/ do
206 next if @skip_steps_while_restoring_background
209 desktop_started_picture = 'WindowsStartButton.png'
211 desktop_started_picture = 'GnomeApplicationsMenu.png'
213 @screen.wait(desktop_started_picture, 180)
216 Then /^Tails seems to have booted normally$/ do
217 next if @skip_steps_while_restoring_background
218 step "GNOME has started"
221 Given /^Tor is ready$/ do
222 next if @skip_steps_while_restoring_background
223 @screen.wait("GnomeTorIsReady.png", 300)
224 @screen.waitVanish("GnomeTorIsReady.png", 15)
226 # Having seen the "Tor is ready" notification implies that Tor has
227 # built a circuit, but let's check it directly to be on the safe side.
228 step "Tor has built a circuit"
230 step "the time has synced"
233 Given /^Tor has built a circuit$/ do
234 next if @skip_steps_while_restoring_background
235 wait_until_tor_is_working
238 Given /^the time has synced$/ do
239 next if @skip_steps_while_restoring_background
240 ["/var/run/tordate/done", "/var/run/htpdate/success"].each do |file|
241 try_for(300) { @vm.execute("test -e #{file}").success? }
245 Given /^available upgrades have been checked$/ do
246 next if @skip_steps_while_restoring_background
248 @vm.execute("test -e '/var/run/tails-upgrader/checked_upgrades'").success?
252 Given /^Iceweasel has started and is not loading a web page$/ do
253 next if @skip_steps_while_restoring_background
256 iceweasel_picture = "WindowsIceweaselWindow.png"
258 iceweasel_picture = "IceweaselWindow.png"
261 # Stop iceweasel to load its home page. We do this to prevent Tor
262 # from getting confused in case we save and restore a snapshot in
263 # the middle of loading a page.
264 @screen.wait_and_click(iceweasel_picture, 120)
265 @screen.type("l", Sikuli::KeyModifier.CTRL)
266 @screen.type("about:blank" + Sikuli::Key.ENTER)
269 Given /^all notifications have disappeared$/ do
270 next if @skip_steps_while_restoring_background
273 notification_picture = "WindowsNotificationX.png"
275 notification_picture = "GnomeNotificationX.png"
277 @screen.waitVanish(notification_picture, 60)
280 Given /^I save the state so the background can be restored next scenario$/ do
281 if @skip_steps_while_restoring_background
282 assert(File.size?($background_snapshot),
283 "We have been skipping steps but there is no snapshot to restore")
285 # To be sure we run the feature from scratch we remove any
286 # leftover snapshot that wasn't removed.
287 if File.exist?($background_snapshot)
288 File.delete($background_snapshot)
290 # Workaround: when libvirt takes ownership of the snapshot it may
291 # become unwritable for the user running this script so it cannot
292 # be removed during clean up.
293 FileUtils.touch($background_snapshot)
294 FileUtils.chmod(0666, $background_snapshot)
296 # Snapshots cannot be saved while filesystem shares are mounted
297 # XXX-9p: See XXX-9p above.
298 #deactivate_filesystem_shares
300 @vm.save_snapshot($background_snapshot)
303 # Now we stop skipping steps from the snapshot restore.
304 @skip_steps_while_restoring_background = false
307 Then /^I see "([^"]*)" after at most (\d+) seconds$/ do |image, time|
308 next if @skip_steps_while_restoring_background
309 @screen.wait(image, time.to_i)
312 Then /^all Internet traffic has only flowed through Tor$/ do
313 next if @skip_steps_while_restoring_background
314 leaks = FirewallLeakCheck.new(@sniffer.pcap_file, get_tor_relays)
316 if !leaks.ipv4_tcp_leaks.empty?
317 puts "The following IPv4 TCP non-Tor Internet hosts were contacted:"
318 puts leaks.ipv4_tcp_leaks.join("\n")
321 if !leaks.ipv4_nontcp_leaks.empty?
322 puts "The following IPv4 non-TCP Internet hosts were contacted:"
323 puts leaks.ipv4_nontcp_leaks.join("\n")
326 if !leaks.ipv6_leaks.empty?
327 puts "The following IPv6 Internet hosts were contacted:"
328 puts leaks.ipv6_leaks.join("\n")
331 if !leaks.nonip_leaks.empty?
332 puts "Some non-IP packets were sent\n"
335 raise "There were network leaks!"
339 When /^I open the GNOME run dialog$/ do
340 next if @skip_steps_while_restoring_background
341 @screen.type(Sikuli::Key.F2, Sikuli::KeyModifier.ALT)
342 @screen.wait(run_dialog_picture, 10)
345 When /^I run "([^"]*)"$/ do |program|
346 next if @skip_steps_while_restoring_background
347 step "I open the GNOME run dialog"
348 @screen.type(program)
350 @screen.type(Sikuli::Key.ENTER)
353 Given /^I enter the sudo password in the gksu prompt$/ do
354 next if @skip_steps_while_restoring_background
355 @screen.wait('GksuAuthPrompt.png', 60)
356 sleep 1 # wait for weird fade-in to unblock the "Ok" button
357 @screen.type(@sudo_password)
358 @screen.type(Sikuli::Key.ENTER)
359 @screen.waitVanish('GksuAuthPrompt.png', 10)
362 Given /^I enter the sudo password in the pkexec prompt$/ do
363 next if @skip_steps_while_restoring_background
364 step "I enter the \"#{@sudo_password}\" password in the pkexec prompt"
367 def deal_with_polkit_prompt (image, password)
368 @screen.wait(image, 60)
369 sleep 1 # wait for weird fade-in to unblock the "Ok" button
370 @screen.type(password)
371 @screen.type(Sikuli::Key.ENTER)
372 @screen.waitVanish(image, 10)
375 Given /^I enter the "([^"]*)" password in the pkexec prompt$/ do |password|
376 next if @skip_steps_while_restoring_background
377 deal_with_polkit_prompt('PolicyKitAuthPrompt.png', password)
380 Given /^process "([^"]+)" is running$/ do |process|
381 next if @skip_steps_while_restoring_background
382 assert(@vm.has_process?(process),
383 "Process '#{process}' is not running")
386 Given /^process "([^"]+)" is running within (\d+) seconds$/ do |process, time|
387 next if @skip_steps_while_restoring_background
388 try_for(time.to_i, :msg => "Process '#{process}' is not running after " +
389 "waiting for #{time} seconds") do
390 @vm.has_process?(process)
394 Given /^process "([^"]+)" is not running$/ do |process|
395 next if @skip_steps_while_restoring_background
396 assert(!@vm.has_process?(process),
397 "Process '#{process}' is running")
400 Given /^I kill the process "([^"]+)"$/ do |process|
401 next if @skip_steps_while_restoring_background
402 @vm.execute("killall #{process}")
403 try_for(10, :msg => "Process '#{process}' could not be killed") {
404 !@vm.has_process?(process)
408 Then /^Tails eventually shuts down$/ do
409 next if @skip_steps_while_restoring_background
410 nr_gibs_of_ram = (detected_ram_in_MiB.to_f/(2**10)).ceil
411 timeout = nr_gibs_of_ram*5*60
412 try_for(timeout, :msg => "VM is still running after #{timeout} seconds") do
417 Then /^Tails eventually restarts$/ do
418 next if @skip_steps_while_restoring_background
419 nr_gibs_of_ram = (detected_ram_in_MiB.to_f/(2**10)).ceil
420 @screen.wait('TailsBootSplashPostReset.png', nr_gibs_of_ram*5*60)
423 Given /^I shutdown Tails and wait for the computer to power off$/ do
424 next if @skip_steps_while_restoring_background
425 @vm.execute("poweroff")
426 step 'Tails eventually shuts down'
429 When /^I request a shutdown using the emergency shutdown applet$/ do
430 next if @skip_steps_while_restoring_background
432 @screen.wait_and_click('TailsEmergencyShutdownButton.png', 10)
434 @screen.wait_and_click('TailsEmergencyShutdownHalt.png', 10)
437 When /^I request a reboot using the emergency shutdown applet$/ do
438 next if @skip_steps_while_restoring_background
440 @screen.wait_and_click('TailsEmergencyShutdownButton.png', 10)
442 @screen.wait_and_click('TailsEmergencyShutdownReboot.png', 10)
445 Given /^package "([^"]+)" is installed$/ do |package|
446 next if @skip_steps_while_restoring_background
447 assert(@vm.execute("dpkg -s '#{package}' 2>/dev/null | grep -qs '^Status:.*installed$'").success?,
448 "Package '#{package}' is not installed")