apt.rb 6.63 KB
Newer Older
1
2
require 'uri'

3
4
def apt_sources
  $vm.execute_successfully(
5
    'cat /etc/apt/sources.list /etc/apt/sources.list.d/*'
6
7
8
  ).stdout
end

9
10
Given /^the only hosts in APT sources are "([^"]*)"$/ do |hosts_str|
  hosts = hosts_str.split(',')
11
  apt_sources.chomp.each_line do |line|
12
    next unless line.start_with? 'deb'
13

14
    source_host = URI(line.split[1]).host
15
    raise "Bad APT source '#{line}'" unless hosts.include?(source_host)
16
  end
17
18
end

19
20
21
22
Given /^no proposed-updates APT suite is enabled$/ do
  assert_no_match(/\s\S+-proposed-updates\s/, apt_sources)
end

23
24
25
26
27
Given /^no experimental APT suite is enabled for deb[.]torproject[.]org$/ do
  # sdscoq7snqtznauu.onion == deb.torproject.org
  assert_no_match(/sdscoq7snqtznauu[.]onion.*experimental/, apt_sources)
end

28
When /^I configure APT to use non-onion sources$/ do
29
  script = <<-SCRIPT
30
31
32
33
34
35
  use strict;
  use warnings FATAL => "all";
  s{vwakviie2ienjx6t[.]onion}{ftp.us.debian.org};
  s{sgvtcaew4bxjd7ln[.]onion}{security.debian.org};
  s{sdscoq7snqtznauu[.]onion}{deb.torproject.org};
  s{jenw7xbd6tf7vfhp[.]onion}{deb.tails.boum.org};
36
  SCRIPT
37
38
39
40
41
42
43
44
  # VMCommand:s cannot handle newlines, and they're irrelevant in the
  # above perl script any way
  script.delete!("\n")
  $vm.execute_successfully(
    "perl -pi -E '#{script}' /etc/apt/sources.list /etc/apt/sources.list.d/*"
  )
end

45
When /^I update APT using apt$/ do
intrigeri's avatar
intrigeri committed
46
  recovery_proc = proc do
bertagaz's avatar
bertagaz committed
47
    step 'I kill the process "apt"'
48
    $vm.execute('rm -rf /var/lib/apt/lists/*')
49
50
  end
  retry_tor(recovery_proc) do
51
    Timeout.timeout(15 * 60) do
52
      $vm.execute_successfully("echo #{@sudo_password} | " \
53
                               'sudo -S apt update', user: LIVE_USER)
54
    end
55
56
57
  end
end

58
def wait_for_package_installation(package)
59
  try_for(2 * 60, delay: 3) do
60
61
    $vm.execute_successfully("dpkg -s '#{package}' 2>/dev/null " \
                             "| grep -qs '^Status:.*installed$'")
62
63
64
  end
end

65
Then /^I install "(.+)" using apt$/ do |package|
intrigeri's avatar
intrigeri committed
66
  recovery_proc = proc do
67
    step 'I kill the process "apt"'
68
69
    # We can't use execute_successfully here: the package might not be
    # installed at this point, and then "apt purge" would return non-zero.
70
71
72
    $vm.execute("apt purge #{package}")
  end
  retry_tor(recovery_proc) do
73
    Timeout.timeout(3 * 60) do
74
      $vm.execute("echo #{@sudo_password} | " \
75
                  "sudo -S DEBIAN_PRIORITY=critical apt -y install #{package}",
76
                  user:  LIVE_USER,
77
                  spawn: true)
78
      wait_for_package_installation(package)
79
    end
80
81
82
  end
end

83
def wait_for_package_removal(package)
84
  try_for(3 * 60, delay: 3) do
85
86
    # Once purged, a package is removed from the installed package status
    # database and "dpkg -s" returns a non-zero exit code
87
    !$vm.execute("dpkg -s #{package}").success?
88
89
90
  end
end

91
Then /^I uninstall "(.+)" using apt$/ do |package|
92
  $vm.execute_successfully("echo #{@sudo_password} | " \
93
                               "sudo -S apt -y purge #{package}",
94
                           user:  LIVE_USER,
95
                           spawn: true)
96
  wait_for_package_removal(package)
97
98
end

99
When /^I configure APT to prefer an old version of cowsay$/ do
100
  apt_source = 'deb tor+http://deb.tails.boum.org/ asp-test-upgrade-cowsay main'
101
  apt_pref = <<~PREF
102
103
104
    Package: cowsay
    Pin: release o=Tails,a=asp-test-upgrade-cowsay
    Pin-Priority: 999
105
  PREF
106
107
  $vm.file_overwrite('/etc/apt/sources.list.d/asp-test-upgrade-cowsay.list',
                     apt_source)
108
  $vm.file_overwrite('/etc/apt/preferences.d/asp-test-upgrade-cowsay', apt_pref)
109
110
end

111
When /^I install an old version "([^"]*)" of the cowsay package using apt$/ do |version|
112
  step 'I update APT using apt'
113
  step 'I install "cowsay" using apt'
114
  step "the installed version of package \"cowsay\" is \"#{version}\""
115
116
end

117
When /^I revert the APT tweaks that made it prefer an old version of cowsay$/ do
118
119
120
121
  $vm.execute_successfully(
    'rm -f /etc/apt/sources.list.d/asp-test-upgrade-cowsay.list ' \
    '/etc/apt/preferences.d/asp-test-upgrade-cowsay'
  )
122
123
end

124
When /^the installed version of package "([^"]*)" is( newer than)? "([^"]*)"( after Additional Software has been started)?$/ do |package, newer_than, version, asp|
125
  step 'the Additional Software installation service has started' if asp
126
127
128
  current_version = $vm.execute_successfully(
    "dpkg-query -W -f='${Version}' #{package}"
  ).stdout
129
  if newer_than
130
    cmd_helper("dpkg --compare-versions '#{version}' lt '#{current_version}'")
131
  else
132
    assert_equal(version, current_version)
133
  end
134
135
end

anonym's avatar
anonym committed
136
When /^I start Synaptic$/ do
anonym's avatar
anonym committed
137
  step 'I start "Synaptic Package Manager" via GNOME Activities Overview'
anonym's avatar
anonym committed
138
139
140
141
  deal_with_polkit_prompt(@sudo_password)
  @synaptic = Dogtail::Application.new('synaptic')
  # The seemingly spurious space is needed because that is how this
  # frame is named...
142
143
144
  @synaptic.child(
    'Synaptic Package Manager ', roleName: 'frame', recursive: false
  )
anonym's avatar
anonym committed
145
146
end

147
When /^I update APT using Synaptic$/ do
intrigeri's avatar
intrigeri committed
148
  recovery_proc = proc do
bertagaz's avatar
bertagaz committed
149
    step 'I kill the process "synaptic"'
150
    step 'I start Synaptic'
151
152
  end
  retry_tor(recovery_proc) do
anonym's avatar
anonym committed
153
    @synaptic.button('Reload').click
154
    sleep 10 # It might take some time before APT starts downloading
155
    try_for(15 * 60, msg: 'Took too much time to download the APT data') do
156
      !$vm.process_running?('/usr/lib/apt/methods/tor+http')
157
    end
158
    assert_raise(Dogtail::Failure) do
159
      @synaptic.child(roleName: 'dialog', recursive: false)
160
               .child('Error', roleName: 'icon', retry: false)
161
    end
162
    unless $vm.process_running?('synaptic')
163
      raise 'Synaptic process vanished, did it segfault again?'
164
    end
165
  end
166
167
end

168
Then /^I install "(.+)" using Synaptic$/ do |package_name|
intrigeri's avatar
intrigeri committed
169
  recovery_proc = proc do
bertagaz's avatar
bertagaz committed
170
    step 'I kill the process "synaptic"'
171
172
    # We can't use execute_successfully here: the package might not be
    # installed at this point, and then "apt purge" would return non-zero.
anonym's avatar
anonym committed
173
    $vm.execute("apt -y purge #{package_name}")
174
    step 'I start Synaptic'
175
176
  end
  retry_tor(recovery_proc) do
anonym's avatar
anonym committed
177
178
179
180
181
182
183
184
185
    @synaptic.button('Search').click
    find_dialog = @synaptic.dialog('Find')
    find_dialog.child(roleName: 'text').typeText(package_name)
    find_dialog.button('Search').click
    package_list = @synaptic.child('Installed Version',
                                   roleName: 'table column header').parent
    package_entry = package_list.child(package_name, roleName: 'table cell')
    package_entry.doubleClick
    @synaptic.button('Apply').click
186
    apply_prompt = nil
187
    try_for(60) do
188
189
      apply_prompt = @synaptic.dialog('Summary')
      true
190
    end
anonym's avatar
anonym committed
191
    apply_prompt.button('Apply').click
192
    try_for(4 * 60) do
193
194
195
      @synaptic.child('Changes applied', roleName: 'frame', recursive: false)
      true
    end
196
    step 'I kill the process "synaptic"'
anonym's avatar
anonym committed
197
  end
198
end