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 Given /^a computer$/ do
65 @vm = VM.new($vm_xml_path, $x_display)
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)
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)
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)
83 Given /^I plug ([[:alpha:]]+) drive "([^"]+)"$/ do |bus, name|
84 next if @skip_steps_while_restoring_background
85 @vm.plug_drive(name, bus.downcase)
87 step "drive \"#{name}\" is detected by Tails"
91 Then /^drive "([^"]+)" is detected by Tails$/ do |name|
92 next if @skip_steps_while_restoring_background
94 try_for(10, :msg => "Drive '#{name}' is not detected by Tails") {
95 @vm.disk_detected?(name)
98 STDERR.puts "Cannot tell if drive '#{name}' is detected by Tails: " +
99 "Tails is not running"
103 Given /^the network is plugged$/ do
104 next if @skip_steps_while_restoring_background
108 Given /^the network is unplugged$/ do
109 next if @skip_steps_while_restoring_background
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)
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")
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")
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
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(Sikuli::Key.TAB)
157 @screen.waitVanish('TailsBootSplashTabMsg.png', 1)
158 @screen.type(" autotest_never_use_this_option #{@boot_options}" +
160 @screen.wait('TailsGreeter.png', 30*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 @screen.click(match.getCenter.offset(match.w/2, match.h*2))
174 @screen.wait_and_click('TailsGreeterForward.png', 10)
175 @screen.wait('TailsGreeterLoginButton.png', 20)
178 Given /^I set sudo password "([^"]*)"$/ do |password|
179 @sudo_password = password
180 next if @skip_steps_while_restoring_background
181 @screen.wait("TailsGreeterAdminPassword.png", 20)
182 @screen.type(@sudo_password)
183 @screen.type(Sikuli::Key.TAB)
184 @screen.type(@sudo_password)
187 Given /^Tails Greeter has dealt with the sudo password$/ do
188 next if @skip_steps_while_restoring_background
189 f1 = "/etc/sudoers.d/tails-greeter"
190 f2 = "#{f1}-no-password-lecture"
192 @vm.execute("test -e '#{f1}' -o -e '#{f2}'").success?
196 Given /^GNOME has started$/ do
197 next if @skip_steps_while_restoring_background
200 desktop_started_picture = 'WindowsStartButton.png'
202 desktop_started_picture = 'GnomeApplicationsMenu.png'
204 @screen.wait(desktop_started_picture, 180)
207 Then /^Tails seems to have booted normally$/ do
208 next if @skip_steps_while_restoring_background
209 step "GNOME has started"
212 Given /^Tor is ready$/ do
213 next if @skip_steps_while_restoring_background
214 @screen.wait("GnomeTorIsReady.png", 300)
215 @screen.waitVanish("GnomeTorIsReady.png", 15)
217 # Having seen the "Tor is ready" notification implies that Tor has
218 # built a circuit, but let's check it directly to be on the safe side.
219 step "Tor has built a circuit"
221 step "the time has synced"
224 Given /^Tor has built a circuit$/ do
225 next if @skip_steps_while_restoring_background
226 wait_until_tor_is_working
229 Given /^the time has synced$/ do
230 next if @skip_steps_while_restoring_background
231 ["/var/run/tordate/done", "/var/run/htpdate/success"].each do |file|
232 try_for(300) { @vm.execute("test -e #{file}").success? }
236 Given /^available upgrades have been checked$/ do
237 next if @skip_steps_while_restoring_background
239 @vm.execute("test -e '/var/run/tails-upgrader/checked_upgrades'").success?
243 Given /^Iceweasel has started and is not loading a web page$/ do
244 next if @skip_steps_while_restoring_background
247 iceweasel_picture = "WindowsIceweaselWindow.png"
249 iceweasel_picture = "IceweaselWindow.png"
252 # Stop iceweasel to load its home page. We do this to prevent Tor
253 # from getting confused in case we save and restore a snapshot in
254 # the middle of loading a page.
255 @screen.wait_and_click(iceweasel_picture, 120)
256 @screen.type("l", Sikuli::KeyModifier.CTRL)
257 @screen.type("about:blank" + Sikuli::Key.ENTER)
260 Given /^all notifications have disappeared$/ do
261 next if @skip_steps_while_restoring_background
264 notification_picture = "WindowsNotificationX.png"
266 notification_picture = "GnomeNotificationX.png"
268 @screen.waitVanish(notification_picture, 60)
271 Given /^I save the state so the background can be restored next scenario$/ do
272 if @skip_steps_while_restoring_background
273 assert(File.size?($background_snapshot),
274 "We have been skipping steps but there is no snapshot to restore")
276 # To be sure we run the feature from scratch we remove any
277 # leftover snapshot that wasn't removed.
278 if File.exist?($background_snapshot)
279 File.delete($background_snapshot)
281 # Workaround: when libvirt takes ownership of the snapshot it may
282 # become unwritable for the user running this script so it cannot
283 # be removed during clean up.
284 FileUtils.touch($background_snapshot)
285 FileUtils.chmod(0666, $background_snapshot)
287 # Snapshots cannot be saved while filesystem shares are mounted
288 # XXX-9p: See XXX-9p above.
289 #deactivate_filesystem_shares
291 @vm.save_snapshot($background_snapshot)
294 # Now we stop skipping steps from the snapshot restore.
295 @skip_steps_while_restoring_background = false
298 Then /^I see "([^"]*)" after at most (\d+) seconds$/ do |image, time|
299 next if @skip_steps_while_restoring_background
300 @screen.wait(image, time.to_i)
303 Then /^all Internet traffic has only flowed through Tor$/ do
304 next if @skip_steps_while_restoring_background
305 leaks = FirewallLeakCheck.new(@sniffer.pcap_file, get_tor_relays)
307 if !leaks.ipv4_tcp_leaks.empty?
308 puts "The following IPv4 TCP non-Tor Internet hosts were contacted:"
309 puts leaks.ipv4_tcp_leaks.join("\n")
312 if !leaks.ipv4_nontcp_leaks.empty?
313 puts "The following IPv4 non-TCP Internet hosts were contacted:"
314 puts leaks.ipv4_nontcp_leaks.join("\n")
317 if !leaks.ipv6_leaks.empty?
318 puts "The following IPv6 Internet hosts were contacted:"
319 puts leaks.ipv6_leaks.join("\n")
322 if !leaks.nonip_leaks.empty?
323 puts "Some non-IP packets were sent\n"
326 raise "There were network leaks!"
330 Given /^I enter the sudo password in the gksu prompt$/ do
331 next if @skip_steps_while_restoring_background
332 @screen.wait('GksuAuthPrompt.png', 60)
333 sleep 1 # wait for weird fade-in to unblock the "Ok" button
334 @screen.type(@sudo_password)
335 @screen.type(Sikuli::Key.ENTER)
336 @screen.waitVanish('GksuAuthPrompt.png', 10)
339 Given /^I enter the sudo password in the pkexec prompt$/ do
340 next if @skip_steps_while_restoring_background
341 step "I enter the \"#{@sudo_password}\" password in the pkexec prompt"
344 def deal_with_polkit_prompt (image, password)
345 @screen.wait(image, 60)
346 sleep 1 # wait for weird fade-in to unblock the "Ok" button
347 @screen.type(password)
348 @screen.type(Sikuli::Key.ENTER)
349 @screen.waitVanish(image, 10)
352 Given /^I enter the "([^"]*)" password in the pkexec prompt$/ do |password|
353 next if @skip_steps_while_restoring_background
354 deal_with_polkit_prompt('PolicyKitAuthPrompt.png', password)
357 Given /^process "([^"]+)" is running$/ do |process|
358 next if @skip_steps_while_restoring_background
359 assert(@vm.has_process?(process),
360 "Process '#{process}' is not running")
363 Given /^process "([^"]+)" is running within (\d+) seconds$/ do |process, time|
364 next if @skip_steps_while_restoring_background
365 try_for(time.to_i, :msg => "Process '#{process}' is not running after " +
366 "waiting for #{time} seconds") do
367 @vm.has_process?(process)
371 Given /^process "([^"]+)" is not running$/ do |process|
372 next if @skip_steps_while_restoring_background
373 assert(!@vm.has_process?(process),
374 "Process '#{process}' is running")
377 Given /^I kill the process "([^"]+)"$/ do |process|
378 next if @skip_steps_while_restoring_background
379 @vm.execute("killall #{process}")
380 try_for(10, :msg => "Process '#{process}' could not be killed") {
381 !@vm.has_process?(process)
385 Then /^Tails eventually shuts down$/ do
386 next if @skip_steps_while_restoring_background
387 nr_gibs_of_ram = (detected_ram_in_MiB.to_f/(2**10)).ceil
388 timeout = nr_gibs_of_ram*5*60
389 try_for(timeout, :msg => "VM is still running after #{timeout} seconds") do
394 Then /^Tails eventually restarts$/ do
395 next if @skip_steps_while_restoring_background
396 nr_gibs_of_ram = (detected_ram_in_MiB.to_f/(2**10)).ceil
397 @screen.wait('TailsBootSplashPostReset.png', nr_gibs_of_ram*5*60)
400 Given /^I shutdown Tails and wait for the computer to power off$/ do
401 next if @skip_steps_while_restoring_background
402 @vm.execute("poweroff")
403 step 'Tails eventually shuts down'
406 When /^I request a shutdown using the emergency shutdown applet$/ do
407 next if @skip_steps_while_restoring_background
409 @screen.wait_and_click('TailsEmergencyShutdownButton.png', 10)
411 @screen.wait_and_click('TailsEmergencyShutdownHalt.png', 10)
414 When /^I request a reboot using the emergency shutdown applet$/ do
415 next if @skip_steps_while_restoring_background
417 @screen.wait_and_click('TailsEmergencyShutdownButton.png', 10)
419 @screen.wait_and_click('TailsEmergencyShutdownReboot.png', 10)
422 Given /^package "([^"]+)" is installed$/ do |package|
423 next if @skip_steps_while_restoring_background
424 assert(@vm.execute("dpkg -s '#{package}' 2>/dev/null | grep -qs '^Status:.*installed$'").success?,
425 "Package '#{package}' is not installed")
428 When /^I start Iceweasel$/ do
429 next if @skip_steps_while_restoring_background
432 step 'I click the start menu'
433 @screen.wait_and_click("WindowsApplicationsInternet.png", 10)
434 @screen.wait_and_click("WindowsApplicationsIceweasel.png", 10)
436 @screen.wait_and_click("GnomeApplicationsMenu.png", 10)
437 @screen.wait_and_click("GnomeApplicationsInternet.png", 10)
438 @screen.wait_and_click("GnomeApplicationsIceweasel.png", 10)
442 Given /^I add a wired DHCP NetworkManager connection called "([^"]+)"$/ do |con_name|
443 next if @skip_steps_while_restoring_background
450 uuid=bbc60668-1be0-11e4-a9c6-2f1ce0e75bf1
460 con_content.split("\n").each do |line|
461 @vm.execute("echo '#{line}' >> /tmp/NM.#{con_name}")
463 @vm.execute("install -m 0600 '/tmp/NM.#{con_name}' '/etc/NetworkManager/system-connections/#{con_name}'")
465 nm_con_list = @vm.execute("nmcli --terse --fields NAME con list").stdout
466 nm_con_list.split("\n").include? "#{con_name}"
470 Given /^I switch to the "([^"]+)" NetworkManager connection$/ do |con_name|
471 next if @skip_steps_while_restoring_background
472 @vm.execute("nmcli con up id #{con_name}")
474 @vm.execute("nmcli --terse --fields NAME,STATE con status").stdout.chomp == "#{con_name}:activated"