~dpniel/ubiquity/fix-runner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
#!/bin/sh

#
# This script runs autopilot
#

# Copyright © 2013-2014 Canonical Ltd.
# Author: Jean-baptiste Lallement <jean-baptiste.lallement@canonical.com>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 2, as published by the
# Free Software Foundation.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
set -eu

# Lock management to prevent this script of running twice
LOCKFILE=/tmp/$(basename $0).lock
if [ -e ${LOCKFILE} ] && kill -0 $(cat ${LOCKFILE}); then
    echo "W: $(basename $0) already running. Exiting!"
    exit
fi
echo $$>${LOCKFILE}

# The following variables can be overridden with a configuration file
TSBRANCH=lp:ubiquity
EXTRAPACKAGES=""
ARTIFACTS=""
AP_OPTS="-v"
SHUTDOWN=1
TIMEOUT=1200  # 20min timeout
DEBUG=0
SHAREDVOL=""

# Custom configuration
# Do not use the variable TESTBASE because we don't want it to be overridden
[ -f /var/local/autopilot/config ] && . /var/local/autopilot/config

TESTBASE=/var/local/autopilot/
AP_ARTIFACTS=$TESTBASE/videos/
AP_RESULTS=$TESTBASE/junit/
AP_LOGS=$TESTBASE/logs/
AP_TESTSUITES=$TESTBASE/testsuites
AP_LOGFILE=$AP_LOGS/autopilot.log
AP_SUMMARY=$AP_LOGS/summary.log
AP_INFO=$AP_LOGS/build_info.txt
RMD_OPTS="-r -rd $AP_ARTIFACTS --record-options=--fps=6,--no-wm-check"
SPOOLDIR=$TESTBASE/spool
TSEXPORT=$HOME/ubiquity-autopilot
SESSION_LOG=""
# Append mandatory artifacts
ARTIFACTS="$TESTBASE /var/log/installer /var/log/syslog $HOME/.cache/upstart /var/crash $ARTIFACTS"


# Specific configurations for various DE
if [ -n "${SESSION+1}" ]; then
    case $SESSION in
        ubuntu)    # Covers Ubuntu and Edubuntu
            SESSION_LOG=$HOME/.cache/upstart/gnome-session.log
            ;;
        xubuntu)
            SESSION_LOG=$HOME/.cache/upstart/startxfce4.log
            ;;
        Lubuntu)
            SESSION_LOG=$HOME/.cache/lxsession/Lubuntu/run.log
            ARTIFACTS="$ARTIFACTS $HOME/.cache/lxsession"
            ;;
    esac
elif [ -n "${DESKTOP_SESSION+1}" ]; then
    # These 2 don't seem to log apt stuff to syslog
    # And there doesn't seem to be a user session log???
    # So let's tail it and also include in the artifacts
    case $DESKTOP_SESSION in
        mate)    # Covers Ubuntu-mate
            SESSION_LOG=/var/log/apt/term.log
            ARTIFACTS="$ARTIFACTS /var/log/apt"
            ;;
        gnome) #ubuntu-gnome
            SESSION_LOG=/var/log/apt/term.log
            ARTIFACTS="$ARTIFACTS /var/log/apt"
            ;;
    esac
else
    echo "I: Unknown SESSION"
    exit 1
fi

PACKAGES="bzr ssh python3-autopilot libautopilot-gtk python3-xlib \
    recordmydesktop"

export DEBIAN_FRONTEND=noninteractive

on_exit() {
    # Exit handler
    echo "I: Archiving artifacts"
    archive=/tmp/artifacts

    # Attempt to retrieve crash information
    if [ -n "$(ls /var/crash/)" ]; then
        export CRASH_DB_URL=https://daisy.ubuntu.com 
        export CRASH_DB_IDENTIFIER=$(echo ubiquity_autopilot_$(lsb_release -sc)_$(arch)|sha512sum|cut -d' ' -f1)
        sudo -E whoopsie||true
        sleep 3
        [ -x "/usr/share/apport/whoopsie-upload-all" ] && echo "I: Uploading crash files" && sudo -E /usr/share/apport/whoopsie-upload-all -t 300
        chmod og+r /var/crash/* 2>/dev/null || true
    fi

    for artifact in $ARTIFACTS; do
        [ -e "$artifact" ] && sudo tar rf ${archive}.tar $artifact || true
    done

    # Find a better way. ttys are a bit limited and sometimes output is
    # truncated or messages are skipped by the kernel if it goes too fast.
    if [ -f ${archive}.tar ]; then
        sudo stty -F /dev/ttyS1 raw speed 115200
        gzip -9 -c ${archive}.tar > ${archive}.tgz
        sudo sh -c "cat ${archive}.tgz>/dev/ttyS1"
    fi

    rm -f ${LOCKFILE}
    shutdown_host
}
trap on_exit EXIT INT QUIT ABRT PIPE TERM

usage() {
    # Display usage and exit
    cat<<EOF
Usage: $(basename $0) [OPTIONS...]
Run autopilot tests in $SPOOLDIR

Options:
  -h, --help      This help
  -d, --debug     Enable debug mode
  -N, --new       Restart all the tests in $AP_TESTSUITES otherwise
                  only the remaining tests in $SPOOLDIR are run
  -R, --norecord  Do not use recordmydesktop.
  -S, --noshutdown
                  Do not shutdown the system after the tests

EOF
    exit 1
}

# retry command a certain number of time
# $1 is the number of retry
# $2 is the delay in second between retries
# the command is then passed
retry_cmd() {
    # Tries to execute $@ $loop times with a delay of $delay between retries
    # before aborting
    loop=$1
    loopcnt=$1  # Just used to print the status on failure
    delay=$2
    shift
    shift
    while [ $loop -gt 0 ]; do
        rc=0
        $@ || rc=$?
        [ $rc -eq 0 ] && return
        loop=$((loop - 1))
        sleep $delay
    done

    echo "E: Command failed after $loopcnt tries: $@"
    echo "E: Aborting!"
    exit 1
}

setup_tests() {
    # Prepares the environment for the tests
    flag=$HOME/.ap_setup_done

    [ -e "$flag" ] && return 0

    if [ $DEBUG -ne 0 ]; then
        # Put here everything you want to run in debug mode
        xterm &  # Easier to debug from a live session, and rarely broken
    fi

    sudo stty -F /dev/ttyS0 raw speed 115200

    # Adjust the name of the release in any apt .list file
    sudo find /etc/apt -name "*.list" -exec sed -i "s/RELEASE/$(lsb_release -sc)/" {} \;
    
    tail_logs $SESSION_LOG /var/log/syslog
    # Disable notifications and screensaver
    if which gsettings >/dev/null 2>&1; then 
        echo "I: Disabling crash notifications"
        gsettings set com.ubuntu.update-notifier show-apport-crashes false
        echo "I: Disabling screensaver"
        gsettings set org.gnome.desktop.screensaver idle-activation-enabled false
    fi

    # Loads the list of test and queue them in test spool
    sudo mkdir -p $SPOOLDIR $AP_ARTIFACTS $AP_RESULTS $AP_LOGS
    sudo chown -R $USER:$USER $TESTBASE $SPOOLDIR $AP_ARTIFACTS $AP_RESULTS $AP_LOGS

    echo "I: Installating additional packages"
    retry_cmd 3 30 sudo apt-get update
    retry_cmd 3 30 sudo apt-get install -yq $PACKAGES $EXTRAPACKAGES
    echo "I: Purging ubiquity-slideshow"
    sudo apt-get autoremove --purge -y $(dpkg -l "ubiquity-slideshow-*"|awk '/^ii/ {print $2}')||true

    if [ -n "$SHAREDVOL" ]; then
        echo "I: Mounting $SHAREDVOL on $TSEXPORT"
        mkdir -p $TSEXPORT
        sudo mount -t 9p -o trans=virtio,access=any $SHAREDVOL $TSEXPORT
        sudo chmod 777 $TSEXPORT
    else
        echo "I: Branch $TSBRANCH"
        bzr export $TSEXPORT $TSBRANCH
    fi

    if [ -e "$AP_TESTSUITES" ]; then
        (cd $SPOOLDIR; touch $(cat $AP_TESTSUITES))
    fi

    cat>$AP_INFO<<EOF
Image Id:      $(cat /cdrom/.disk/info)
Ubiquity:      $(dpkg-query -f '${Version}' -W ubiquity)
Test branch:   ${TSBRANCH}
Test revno:    $(bzr revno $TSBRANCH)
EOF
    
    cat<<EOF

============================== Test Info ============================== 
$(cat $AP_INFO)
======================================================================= 

EOF
    touch $flag

    dpkg -l > $AP_LOGS/packages.list
}

shutdown_host() {
    # Shutdown host
    sleep 10
    if [ $SHUTDOWN -eq 1 ]; then
        echo "I: Shutting down test environment"
        sudo shutdown -h now
    else
        echo "I: Shutdown disabled, host will keep running"
    fi
}

tail_logs() {
    # Tail log files in -F mode in background
    #   
    # $@ List of log files
    for log in $@; do
        if [ -f "$log" ]; then
            sudo sh -c "/bin/busybox tail -n0 -f $log | mawk -Winteractive -v logfile=\"$log\" '{print logfile\":\",\$0}' > /dev/ttyS0" &
        fi
    done
    }


run_tests() {
    # Runs all the tests in spooldir
    #
    # $1: Spool directory
    spooldir=$1
    apbin=autopilot3
    if [ ! -d $spooldir ]; then
        echo "E: '$spooldir is not a directory. Exiting!"
        exit 1
    fi

    if ! which $apbin >/dev/null 2>&1; then
        echo "E: $apbin not found in path. It is required to run autopilot tests"
        echo "autopilot_installed (see autopilot.log for details): ERROR" >> $AP_SUMMARY
        exit 1
    fi
    echo "autopilot_installed: PASS" >> $AP_SUMMARY

    exec >>$AP_LOGFILE
    exec 2>&1
    touch $AP_LOGFILE
    tail_logs $AP_LOGFILE

    echo "I: Launching Ubiquity"
    cd $TSEXPORT/autopilot
    sudo dbus-launch ubiquity --autopilot &
    sleep 30
    tail_logs /var/log/installer/debug
    for testfile in $(ls -d $spooldir/* 2>/dev/null); do
        testname=$(basename $testfile)
        echo "I: Running autopilot run $testname $AP_OPTS -o $AP_RESULTS/$testname.xml"
        aprc=0
        timeout -s 9 -k 30 $TIMEOUT ./autopilot run $testname $AP_OPTS -f xml -o $AP_RESULTS/${testname}.xml||aprc=$?
        if [ $aprc -gt 0 ]; then
            echo "${testname}: FAIL" >> $AP_SUMMARY
        else
            echo "${testname}: DONE" >> $AP_SUMMARY
        fi
        sudo rm -f $testfile
    done
}

reset_test() {
    # Reset the tests for a new run
    rm -f $HOME/.ap_setup_done $AP_SUMMARY $AP_LOGFILE $SPOOLDIR/* $AP_ARTIFACTS/* $AP_RESULTS/*
}
SHORTOPTS="hdNRS"
LONGOPTS="help,debug,new,norecord,noshutdown"

TEMP=$(getopt -o $SHORTOPTS --long $LONGOPTS -- "$@")
eval set -- "$TEMP"

while true ; do
    case "$1" in
    -h|--help)
        usage;;
    -d|--debug)
        set -x
        shift;;
    -N|--new)
        reset_test
        shift;;
    -R|--norecord)
        RMD_OPTS=""
        shift;;
    -S|--noshutdown)
        SHUTDOWN=0
        shift;;
    --) shift;
        break;;
    *) usage;;
    esac
done

setup_tests
if [ -f "/usr/lib/libeatmydata/libeatmydata.so" ]; then
    echo "I: Enabling eatmydata"
    export LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}/usr/lib/libeatmydata/libeatmydata.so"
fi
# Specific option for recordmydesktop for unity tests
# It is suspected to caused memory fragmentation and make the test crash
if [ -e "$AP_TESTSUITES" ]; then
    if grep -qw "unity" "$AP_TESTSUITES" 2>/dev/null; then
        RMD_OPTS="$RMD_OPTS --record-options=--fps=6,--no-wm-check"
    fi
fi

if which recordmydesktop >/dev/null 2>&1; then
    AP_OPTS="$AP_OPTS $RMD_OPTS"
fi

run_tests $SPOOLDIR

exit 0