summaryrefslogtreecommitdiffstats
path: root/cucumber/features/step_definitions/usb.rb
diff options
context:
space:
mode:
Diffstat (limited to 'cucumber/features/step_definitions/usb.rb')
-rw-r--r--cucumber/features/step_definitions/usb.rb347
1 files changed, 249 insertions, 98 deletions
diff --git a/cucumber/features/step_definitions/usb.rb b/cucumber/features/step_definitions/usb.rb
index 76f94d2f..e030f68e 100644
--- a/cucumber/features/step_definitions/usb.rb
+++ b/cucumber/features/step_definitions/usb.rb
@@ -48,6 +48,14 @@ def persistent_volumes_mountpoints
$vm.execute("ls -1 -d /live/persistence/*_unlocked/").stdout.chomp.split
end
+def recover_from_upgrader_failure
+ $vm.execute('killall tails-upgrade-frontend tails-upgrade-frontend-wrapper zenity')
+ # Remove unnecessary sleep for retry
+ $vm.execute_successfully('sed -i "/^sleep 30$/d" ' +
+ '/usr/local/bin/tails-upgrade-frontend-wrapper')
+ $vm.spawn('tails-upgrade-frontend-wrapper', user: LIVE_USER)
+end
+
Given /^I clone USB drive "([^"]+)" to a new USB drive "([^"]+)"$/ do |from, to|
$vm.storage.clone_to_new_disk(from, to)
end
@@ -65,66 +73,105 @@ Given /^the computer is set to boot in UEFI mode$/ do
@os_loader = 'UEFI'
end
+def tails_installer_selected_device
+ @installer.child('Target Device:', roleName: 'label').parent
+ .child('', roleName: 'combo box', recursive: false).name
+end
+
+def tails_installer_is_device_selected?(name)
+ device = $vm.disk_dev(name)
+ tails_installer_selected_device[/#{device}\d*$/]
+end
+
+def tails_installer_match_status(pattern)
+ @installer.child('', roleName: 'text').text[pattern]
+end
+
class UpgradeNotSupported < StandardError
end
def usb_install_helper(name)
- @screen.wait('USBTailsLogo.png', 10)
- if @screen.exists("USBCannotUpgrade.png")
+ if tails_installer_match_status(/It is impossible to upgrade the device .+ #{$vm.disk_dev(name)}\d* /)
raise UpgradeNotSupported
end
- @screen.wait_and_click('USBCreateLiveUSB.png', 10)
- @screen.wait('USBCreateLiveUSBConfirmWindow.png', 10)
- @screen.wait_and_click('USBCreateLiveUSBConfirmYes.png', 10)
- @screen.wait('USBInstallationComplete.png', 30*60)
+ assert(tails_installer_is_device_selected?(name))
+ begin
+ @installer.button('Install Tails').click
+ @installer.child('Question', roleName: 'alert').button('Yes').click
+ try_for(30*60) do
+ @installer
+ .child('Information', roleName: 'alert')
+ .child('Installation complete!', roleName: 'label')
+ true
+ end
+ rescue FindFailed => e
+ path = $vm.execute_successfully('ls -1 /tmp/tails-installer-*').stdout.chomp
+ debug_log("Tails Installer debug log:\n" + $vm.file_content(path))
+ raise e
+ end
end
-When /^I start Tails Installer$/ do
- step 'I start "TailsInstaller" via the GNOME "Tails" applications menu'
- @screen.wait('USBCloneAndInstall.png', 30)
+When /^I start Tails Installer in "([^"]+)" mode$/ do |mode|
+ step 'I run "export DEBUG=1 ; tails-installer-launcher" in GNOME Terminal'
+ installer_launcher = Dogtail::Application.new('tails-installer-launcher')
+ .child('Tails Installer', roleName: 'frame')
+ # Sometimes Dogtail will find the button and click it before it is
+ # shown (searchShowingOnly is not perfect) which generally means
+ # clicking somewhere on the Terminal => the click is lost *and* the
+ # installer does no go to the foreground. So let's wait a bit extra.
+ sleep 3
+ installer_launcher.button(mode).click
+ @installer = Dogtail::Application.new('tails-installer')
+ @installer.child('Tails Installer', roleName: 'frame')
+ # ... and something similar (for consecutive steps) again.
+ sleep 3
+ $vm.focus_window('Tails Installer')
end
-When /^I start Tails Installer in "([^"]+)" mode$/ do |mode|
- step 'I start Tails Installer'
- case mode
- when 'Clone & Install'
- @screen.wait_and_click('USBCloneAndInstall.png', 10)
- when 'Clone & Upgrade'
- @screen.wait_and_click('USBCloneAndUpgrade.png', 10)
- when 'Upgrade from ISO'
- @screen.wait_and_click('USBUpgradeFromISO.png', 10)
- else
- raise "Unsupported mode '#{mode}'"
+Then /^Tails Installer detects that a device is too small$/ do
+ try_for(10) do
+ tails_installer_match_status(/^The device .* is too small to install Tails/)
end
end
-Then /^Tails Installer detects that a device is too small$/ do
- @screen.wait('TailsInstallerTooSmallDevice.png', 10)
+When /^I am told that the destination device cannot be upgraded$/ do
+ try_for(10) do
+ tails_installer_match_status(/^It is impossible to upgrade the device/)
+ end
end
-When /^I "Clone & Install" Tails to USB drive "([^"]+)"$/ do |name|
- step 'I start Tails Installer in "Clone & Install" mode'
- usb_install_helper(name)
+When /^I am suggested to do a "Install by cloning"$/ do
+ try_for(10) do
+ tails_installer_match_status(
+ /You should instead use "Install by cloning" to upgrade Tails/
+ )
+ end
end
-When /^I "Clone & Upgrade" Tails to USB drive "([^"]+)"$/ do |name|
- step 'I start Tails Installer in "Clone & Upgrade" mode'
- usb_install_helper(name)
+Then /^a suitable USB device is (?:still )?not found$/ do
+ @installer.child(
+ 'No device suitable to install Tails could be found', roleName: 'label'
+ )
end
-When /^I try a "Clone & Upgrade" Tails to USB drive "([^"]+)"$/ do |name|
- begin
- step "I \"Clone & Upgrade\" Tails to USB drive \"#{name}\""
- rescue UpgradeNotSupported
- # this is what we expect
- else
- raise "The USB installer should not succeed"
+Then /^(no|the "([^"]+)") USB drive is selected$/ do |mode, name|
+ try_for(30) do
+ if mode == 'no'
+ tails_installer_selected_device == ''
+ else
+ tails_installer_is_device_selected?(name)
+ end
end
end
-When /^I try to "Upgrade from ISO" USB drive "([^"]+)"$/ do |name|
+When /^I "([^"]*)" Tails to USB drive "([^"]+)"$/ do |mode, name|
+ step "I start Tails Installer in \"#{mode}\" mode"
+ usb_install_helper(name)
+end
+
+When /^I fail to "([^"]*)" Tails to USB drive "([^"]+)"$/ do |mode, name|
begin
- step "I do a \"Upgrade from ISO\" on USB drive \"#{name}\""
+ step "I \"#{mode}\" Tails to USB drive \"#{name}\""
rescue UpgradeNotSupported
# this is what we expect
else
@@ -132,35 +179,20 @@ When /^I try to "Upgrade from ISO" USB drive "([^"]+)"$/ do |name|
end
end
-When /^I am suggested to do a "Clone & Install"$/ do
- @screen.find("USBCannotUpgrade.png")
-end
-
-When /^I am told that the destination device cannot be upgraded$/ do
- @screen.find("USBCannotUpgrade.png")
-end
-
-Given /^I setup a filesystem share containing the Tails ISO$/ do
- shared_iso_dir_on_host = "#{$config["TMPDIR"]}/shared_iso_dir"
- @shared_iso_dir_on_guest = "/tmp/shared_iso_dir"
- FileUtils.mkdir_p(shared_iso_dir_on_host)
- FileUtils.cp(TAILS_ISO, shared_iso_dir_on_host)
- add_after_scenario_hook { FileUtils.rm_r(shared_iso_dir_on_host) }
- $vm.add_share(shared_iso_dir_on_host, @shared_iso_dir_on_guest)
+Given /^I plug and mount a USB drive containing the Tails ISO$/ do
+ iso_dir = share_host_files(TAILS_ISO)
+ @iso_path = "#{iso_dir}/#{File.basename(TAILS_ISO)}"
end
When /^I do a "Upgrade from ISO" on USB drive "([^"]+)"$/ do |name|
step 'I start Tails Installer in "Upgrade from ISO" mode'
- @screen.wait('USBUseLiveSystemISO.png', 10)
- match = @screen.find('USBUseLiveSystemISO.png')
- @screen.click(match.getCenter.offset(0, match.h*2))
- @screen.wait('USBSelectISO.png', 10)
- @screen.wait_and_click('GnomeFileDiagHome.png', 10)
+ @installer.child('Use existing Live system ISO:', roleName: 'label')
+ .parent.button('(None)').click
+ file_chooser = @installer.child('Select a File', roleName: 'file chooser')
@screen.type("l", Sikuli::KeyModifier.CTRL)
- @screen.wait('GnomeFileDiagTypeFilename.png', 10)
- iso = "#{@shared_iso_dir_on_guest}/#{File.basename(TAILS_ISO)}"
- @screen.type(iso)
- @screen.wait_and_click('GnomeFileDiagOpenButton.png', 10)
+ # The only visible text element will be the path entry
+ file_chooser.child(roleName: 'text').typeText(@iso_path + '\n')
+ file_chooser.button('Open').click
usb_install_helper(name)
end
@@ -174,13 +206,22 @@ Given /^I enable all persistence presets$/ do
@screen.type(Sikuli::Key.TAB + Sikuli::Key.SPACE)
end
@screen.wait_and_click('PersistenceWizardSave.png', 10)
+ @screen.wait('PersistenceWizardDone.png', 60)
+ @screen.type(Sikuli::Key.F4, Sikuli::KeyModifier.ALT)
+end
+
+When /^I disable the first persistence preset$/ do
+ step 'I start "Configure persistent volume" via GNOME Activities Overview'
+ @screen.wait('PersistenceWizardPresets.png', 300)
+ @screen.type(Sikuli::Key.SPACE)
+ @screen.wait_and_click('PersistenceWizardSave.png', 10)
@screen.wait('PersistenceWizardDone.png', 30)
@screen.type(Sikuli::Key.F4, Sikuli::KeyModifier.ALT)
end
Given /^I create a persistent partition$/ do
- step 'I start "ConfigurePersistentVolume" via the GNOME "Tails" applications menu'
- @screen.wait('PersistenceWizardStart.png', 20)
+ step 'I start "Configure persistent volume" via GNOME Activities Overview'
+ @screen.wait('PersistenceWizardStart.png', 60)
@screen.type(@persistence_password + "\t" + @persistence_password + Sikuli::Key.ENTER)
@screen.wait('PersistenceWizardPresets.png', 300)
step "I enable all persistence presets"
@@ -254,10 +295,9 @@ Then /^the running Tails is installed on USB drive "([^"]+)"$/ do |target_name|
end
Then /^the ISO's Tails is installed on USB drive "([^"]+)"$/ do |target_name|
- iso = "#{@shared_iso_dir_on_guest}/#{File.basename(TAILS_ISO)}"
iso_root = "/mnt/iso"
$vm.execute("mkdir -p #{iso_root}")
- $vm.execute("mount -o loop #{iso} #{iso_root}")
+ $vm.execute("mount -o loop #{@iso_path} #{iso_root}")
tails_is_installed_helper(target_name, iso_root, "isolinux")
$vm.execute("umount #{iso_root}")
end
@@ -274,10 +314,10 @@ Then /^a Tails persistence partition exists on USB drive "([^"]+)"$/ do |name|
# The LUKS container may already be opened, e.g. by udisks after
# we've run tails-persistence-setup.
- c = $vm.execute("ls -1 /dev/mapper/")
+ c = $vm.execute("ls -1 --hide 'control' /dev/mapper/")
if c.success?
for candidate in c.stdout.split("\n")
- luks_info = $vm.execute("cryptsetup status #{candidate}")
+ luks_info = $vm.execute("cryptsetup status '#{candidate}'")
if luks_info.success? and luks_info.stdout.match("^\s+device:\s+#{dev}$")
luks_dev = "/dev/mapper/#{candidate}"
break
@@ -300,7 +340,7 @@ Then /^a Tails persistence partition exists on USB drive "([^"]+)"$/ do |name|
mount_dir = "/mnt/#{name}"
$vm.execute("mkdir -p #{mount_dir}")
- c = $vm.execute("mount #{luks_dev} #{mount_dir}")
+ c = $vm.execute("mount '#{luks_dev}' #{mount_dir}")
assert(c.success?,
"Couldn't mount opened LUKS device '#{dev}' on drive '#{name}'")
@@ -310,12 +350,9 @@ Then /^a Tails persistence partition exists on USB drive "([^"]+)"$/ do |name|
end
Given /^I enable persistence$/ do
- @screen.wait('TailsGreeterPersistence.png', 10)
- @screen.type(Sikuli::Key.SPACE)
- @screen.wait('TailsGreeterPersistencePassphrase.png', 10)
- match = @screen.find('TailsGreeterPersistencePassphrase.png')
- @screen.click(match.getCenter.offset(match.w*2, match.h/2))
- @screen.type(@persistence_password)
+ @screen.wait_and_click('TailsGreeterPersistencePassphrase.png', 10)
+ @screen.type(@persistence_password + Sikuli::Key.ENTER)
+ @screen.wait('TailsGreeterPersistenceUnlocked.png', 30)
end
def tails_persistence_enabled?
@@ -325,13 +362,21 @@ def tails_persistence_enabled?
'test "$TAILS_PERSISTENCE_ENABLED" = true').success?
end
-Given /^all persistence presets(| from the old Tails version) are enabled$/ do |old_tails|
+Given /^all persistence presets(| from the old Tails version)(| but the first one) are enabled$/ do |old_tails, except_first|
+ assert(old_tails.empty? || except_first.empty?, "Unsupported case.")
try_for(120, :msg => "Persistence is disabled") do
tails_persistence_enabled?
end
+ unexpected_mounts = Array.new
# Check that all persistent directories are mounted
if old_tails.empty?
expected_mounts = persistent_mounts
+ if ! except_first.empty?
+ first_expected_mount_source = expected_mounts.keys[0]
+ first_expected_mount_destination = expected_mounts[first_expected_mount_source]
+ expected_mounts.delete(first_expected_mount_source)
+ unexpected_mounts = [first_expected_mount_destination]
+ end
else
assert_not_nil($remembered_persistence_mounts)
expected_mounts = $remembered_persistence_mounts
@@ -341,17 +386,16 @@ Given /^all persistence presets(| from the old Tails version) are enabled$/ do |
assert(mount.include?("on #{dir} "),
"Persistent directory '#{dir}' is not mounted")
end
+ for dir in unexpected_mounts do
+ assert(! mount.include?("on #{dir} "),
+ "Persistent directory '#{dir}' is mounted")
+ end
end
Given /^persistence is disabled$/ do
assert(!tails_persistence_enabled?, "Persistence is enabled")
end
-Given /^I enable read-only persistence$/ do
- step "I enable persistence"
- @screen.wait_and_click('TailsGreeterPersistenceReadOnly.png', 10)
-end
-
def boot_device
# Approach borrowed from
# config/chroot_local_includes/lib/live/config/998-permissions
@@ -374,23 +418,21 @@ end
Then /^Tails is running from (.*) drive "([^"]+)"$/ do |bus, name|
bus = bus.downcase
case bus
- when "ide"
+ when "sata"
expected_bus = "ata"
else
expected_bus = bus
end
assert_equal(expected_bus, boot_device_type)
actual_dev = boot_device
- # The boot partition differs between a "normal" install using the
- # USB installer and isohybrid installations
- expected_dev_normal = $vm.disk_dev(name) + "1"
- expected_dev_isohybrid = $vm.disk_dev(name) + "4"
- assert(actual_dev == expected_dev_normal ||
- actual_dev == expected_dev_isohybrid,
+ # The boot partition differs between an using Tails installer and
+ # isohybrids. There's also a strange case isohybrids are thought to
+ # be booting from the "raw" device, and not a partition of it
+ # (#10504).
+ expected_devs = ['', '1', '4'].map { |e| $vm.disk_dev(name) + e }
+ assert(expected_devs.include?(actual_dev),
"We are running from device #{actual_dev}, but for #{bus} drive " +
- "'#{name}' we expected to run from either device " +
- "#{expected_dev_normal} (when installed via the USB installer) " +
- "or #{expected_dev_isohybrid} (when installed from an isohybrid)")
+ "'#{name}' we expected to run from one of #{expected_devs}")
end
Then /^the boot device has safe access rights$/ do
@@ -493,6 +535,12 @@ When /^I write some files expected to persist$/ do
end
end
+When /^I write some dotfile expected to persist$/ do
+ assert($vm.execute("touch /live/persistence/TailsData_unlocked/dotfiles/.XXX_persist",
+ :user => LIVE_USER).success?,
+ "Could not create a file in the dotfiles persistence.")
+end
+
When /^I remove some files expected to persist$/ do
persistent_mounts.each do |_, dir|
owner = $vm.execute("stat -c %U #{dir}").stdout.chomp
@@ -529,6 +577,14 @@ Then /^the expected persistent files(| created with the old Tails version) are p
end
end
+Then /^the expected persistent dotfile is present in the filesystem$/ do
+ expected_dirs = persistent_dirs
+ assert($vm.execute("test -L #{expected_dirs['dotfiles']}/.XXX_persist").success?,
+ "Could not find expected persistent dotfile link.")
+ assert($vm.execute("test -e $(readlink -f #{expected_dirs['dotfiles']}/.XXX_persist)").success?,
+ "Could not find expected persistent dotfile link target.")
+end
+
Then /^only the expected files are present on the persistence partition on USB drive "([^"]+)"$/ do |name|
assert(!$vm.is_running?)
disk = {
@@ -568,8 +624,8 @@ Then /^only the expected files are present on the persistence partition on USB d
end
When /^I delete the persistent partition$/ do
- step 'I start "DeletePersistentVolume" via the GNOME "Tails" applications menu'
- @screen.wait("PersistenceWizardDeletionStart.png", 20)
+ step 'I start "Delete persistent volume" via GNOME Activities Overview'
+ @screen.wait("PersistenceWizardDeletionStart.png", 120)
@screen.type(" ")
@screen.wait("PersistenceWizardDone.png", 120)
end
@@ -583,14 +639,109 @@ Given /^I create a ([[:alpha:]]+) label on disk "([^"]+)"$/ do |type, name|
$vm.storage.disk_mklabel(name, type)
end
-Then /^a suitable USB device is (?:still )?not found$/ do
- @screen.wait("TailsInstallerNoQEMUHardDisk.png", 30)
+Given /^the file system changes introduced in version (.+) are (not )?present(?: in the (\S+) Browser's chroot)?$/ do |version, not_present, chroot_browser|
+ assert_equal('1.1~test', version)
+ upgrade_applied = not_present.nil?
+ chroot_browser = "#{chroot_browser.downcase}-browser" if chroot_browser
+ changes = [
+ {
+ filesystem: :rootfs,
+ path: 'some_new_file',
+ status: :added,
+ new_content: <<-EOF
+Some content
+ EOF
+ },
+ {
+ filesystem: :rootfs,
+ path: 'etc/amnesia/version',
+ status: :modified,
+ new_content: <<-EOF
+#{version} - 20380119
+ffffffffffffffffffffffffffffffffffffffff
+live-build: 3.0.5+really+is+2.0.12-0.tails2
+live-boot: 4.0.2-1
+live-config: 4.0.4-1
+ EOF
+ },
+ {
+ filesystem: :rootfs,
+ path: 'etc/os-release',
+ status: :modified,
+ new_content: <<-EOF
+TAILS_PRODUCT_NAME="Tails"
+TAILS_VERSION_ID="#{version}"
+ EOF
+ },
+ {
+ filesystem: :rootfs,
+ path: 'usr/share/common-licenses/BSD',
+ status: :removed
+ },
+ {
+ filesystem: :medium,
+ path: 'utils/linux/syslinux',
+ status: :removed
+ },
+ ]
+ changes.each do |change|
+ case change[:filesystem]
+ when :rootfs
+ path = '/'
+ path += "var/lib/#{chroot_browser}/chroot/" if chroot_browser
+ path += change[:path]
+ when :medium
+ path = '/lib/live/mount/medium/' + change[:path]
+ else
+ raise "Unknown filesysten '#{change[:filesystem]}'"
+ end
+ case change[:status]
+ when :removed
+ assert_equal(!upgrade_applied, $vm.file_exist?(path))
+ when :added
+ assert_equal(upgrade_applied, $vm.file_exist?(path))
+ if upgrade_applied && change[:new_content]
+ assert_equal(change[:new_content], $vm.file_content(path))
+ end
+ when :modified
+ assert($vm.file_exist?(path))
+ if upgrade_applied
+ assert_not_nil(change[:new_content])
+ assert_equal(change[:new_content], $vm.file_content(path))
+ end
+ else
+ raise "Unknown status '#{change[:status]}'"
+ end
+ end
+end
+
+Then /^I am proposed to install an incremental upgrade to version (.+)$/ do |version|
+ recovery_proc = Proc.new do
+ recover_from_upgrader_failure
+ end
+ failure_pic = 'TailsUpgraderFailure.png'
+ success_pic = "TailsUpgraderUpgradeTo#{version}.png"
+ retry_tor(recovery_proc) do
+ match, _ = @screen.waitAny([success_pic, failure_pic], 2*60)
+ assert_equal(success_pic, match)
+ end
end
-Then /^the "(?:[^"]+)" USB drive is selected$/ do
- @screen.wait("TailsInstallerQEMUHardDisk.png", 30)
+When /^I agree to install the incremental upgrade$/ do
+ @screen.click('TailsUpgraderUpgradeNowButton.png')
end
-Then /^no USB drive is selected$/ do
- @screen.wait("TailsInstallerNoQEMUHardDisk.png", 30)
+Then /^I can successfully install the incremental upgrade to version (.+)$/ do |version|
+ step 'I agree to install the incremental upgrade'
+ recovery_proc = Proc.new do
+ recover_from_upgrader_failure
+ step "I am proposed to install an incremental upgrade to version #{version}"
+ step 'I agree to install the incremental upgrade'
+ end
+ failure_pic = 'TailsUpgraderFailure.png'
+ success_pic = "TailsUpgraderDone.png"
+ retry_tor(recovery_proc) do
+ match, _ = @screen.waitAny([success_pic, failure_pic], 2*60)
+ assert_equal(success_pic, match)
+ end
end