Added jenkins testing infrastructure.
[akaros.git] / tools / jenkins / launcher.sh
1 #!/bin/bash
2 # This script should be called from Jenkins when a new commit has been pushed 
3 # to the repo. 
4 # It analyzes what parts of the codebase have been modified, compiles everything
5 # that is needed, and reports on the results. 
6
7 set -e
8
9 readonly TMP_DIR=tmp
10 readonly DIFF_FILE=$TMP_DIR/changes.txt
11 readonly AKAROS_OUTPUT_FILE=$TMP_DIR/akaros_out.txt
12 readonly TEST_OUTPUT_DIR=output-tests
13 readonly TEST_DIR=tools/jenkins
14 readonly SCR_DIR=tools/jenkins/utils
15 readonly DOWNLOADS_DIR=dl
16
17 # Config files
18 readonly CONF_DIR=tools/jenkins/config
19 readonly CONF_COMP_COMPONENTS_FILE=$CONF_DIR/compilation_components.json
20
21 # Utility scripts
22 readonly SCR_WAIT_UNTIL=$SCR_DIR/wait_until.py
23 readonly SCR_GIT_CHANGES=$SCR_DIR/changes.py
24 readonly SCR_GEN_TEST_REPORTS=$SCR_DIR/test_reporter.py
25
26 # Busybox settings
27 readonly BUSYBOX_VERSION=1.17.3
28 readonly BUSYBOX_DL_URL=http://www.busybox.net/downloads/busybox-1.17.3.tar.bz2
29 readonly BUSYBOX_CONF_FILE=tools/patches/busybox/busybox-1.17.3-config
30
31 ################################################################################
32 ###############                   INITIAL SETUP                  ###############
33 ################################################################################
34
35 if [ "$INITIAL_SETUP" == true ]; then
36         echo -e "\n[INITIAL_SETUP]: Begin"
37         # Create directory for tests and other temp files.
38         mkdir -p $TMP_DIR
39         mkdir -p $TEST_OUTPUT_DIR
40         mkdir -p $DOWNLOADS_DIR
41
42         # Compile QEMU launcher
43         mkdir -p $WORKSPACE/install/qemu_launcher/
44         gcc $SCR_DIR/qemu_launcher.c -o install/qemu_launcher/qemu_launcher
45
46         echo "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
47         echo "Set up finished succesfully."
48         echo "Please run sudo chown root:root install/qemu_launcher/qemu_launcher"
49         echo "Please run sudo chmod 4755 install/qemu_launcher/qemu_launcher"
50         echo "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
51         echo ""
52         echo -e "[INITIAL_SETUP]: End\n"
53         exit 0
54 fi
55
56
57
58 ################################################################################
59 ###############                 PRE BUILD SETUP                  ###############
60 ################################################################################
61
62 function add_cross_compiler_to_path() {
63         export PATH=$WORKSPACE/install/riscv-ros-gcc/bin:$PATH
64         export PATH=$WORKSPACE/install/i686-ros-gcc/bin:$PATH
65         export PATH=$WORKSPACE/install/x86_64-ros-gcc/bin:$PATH
66 }
67
68 # Clean these two directories
69 rm $TMP_DIR/* $TEST_OUTPUT_DIR/* -f
70 add_cross_compiler_to_path
71
72
73 ################################################################################
74 ###############                    COMPILATION                   ###############
75 ################################################################################
76
77 function build_config() {
78         echo -e "\n[SET_MAKE_CONFIG]: Begin"
79
80         # Begin with default configuration.
81         case "$COMPILATION_ARCH" in
82         RISCV)  make ARCH=riscv defconfig
83             ;;
84         I686)  make ARCH=x86 defconfig
85                    sed -i -e 's/CONFIG_64BIT=y/# CONFIG_64BIT is not set/' \
86                           -e 's/# CONFIG_X86_32 is not set/CONFIG_X86_32=y/' \
87                           -e 's/CONFIG_X86_64=y/# CONFIG_X86_64 is not set/' \
88                           .config
89             ;;
90         X86_64)  make ARCH=x86 defconfig
91             ;;
92         esac
93
94         # Enable postboot kernel tests to run.
95         # These don't take much to execute so we can run them always and just parse
96         # results if needed.
97         echo "CONFIG_POSTBOOT_KERNEL_TESTING=y" >> .config
98
99         echo -e "[SET_MAKE_CONFIG]: End\n"
100 }
101
102 function build_cross_compiler() {
103         declare -A ARCH_SUBDIRS=( ["RISCV"]="riscv-ros-gcc" \
104                                   ["I686"]="i686-ros-gcc" \
105                                   ["X86_64"]="x86_64-ros-gcc" )
106
107         echo -e "\n[BUILD_CROSS_COMPILER]: Begin"
108
109         cd tools/compilers/gcc-glibc
110
111         # Clean everything up
112         # TODO: Possibly down the line try to optimize this to only clean the 
113         # architecture that we need to rebuild.
114         make clean
115
116         # Define cross compiler Makelocal.
117         echo "# Number of make jobs to spawn.  
118 MAKE_JOBS := 3
119 RISCV_INSTDIR         := $WORKSPACE/install/${ARCH_SUBDIRS["RISCV"]}/
120 I686_INSTDIR          := $WORKSPACE/install/${ARCH_SUBDIRS["I686"]}/
121 X86_64_INSTDIR        := $WORKSPACE/install/${ARCH_SUBDIRS["X86_64"]}/
122 " > Makelocal
123
124         # Create / clean directory where the cross compiler will be installed.
125         CROSS_COMP_DIR=$WORKSPACE/install/${ARCH_SUBDIRS["$COMPILATION_ARCH"]}/
126         mkdir -p CROSS_COMP_DIR
127         rm -rf CROSS_COMP_DIR*
128
129         # Compile cross compiler.
130         case "$COMPILATION_ARCH" in
131         RISCV)  make riscv
132             ;;
133         I686)  make i686
134             ;;
135         X86_64)  make x86_64
136             ;;
137         esac
138
139         # Go back to root directory.
140         cd ../../..
141         echo -e "[BUILD_CROSS_COMPILER]: End\n"
142 }
143
144 function build_kernel() {
145         echo -e "\n[BUILD_KERNEL]: Begin"
146         make clean
147         make
148         echo -e "[BUILD_KERNEL]: End\n"
149 }
150
151 function build_userspace() {
152         echo -e "\n[BUILD_USERSPACE]: Begin"
153         # This is needed because of a bug that won't let tests to be compiled
154         # unless the following files are present.
155         cd kern/kfs/bin
156         touch busybox
157         touch chmod
158         cd -
159
160         # Build and install user libs.
161         make userclean
162         make install-libs
163
164         # Compile tests.
165         make testclean
166         make tests
167
168         # Fill memory with tests.
169         make fill-kfs
170
171         # Recompile kernel.
172         make
173         echo -e "[BUILD_USERSPACE]: End\n"
174 }
175
176 function build_busybox() {
177         echo -e "\n[BUILD_BUSYBOX]: Begin"
178         
179         BUSYBOX_DIR=busybox-$BUSYBOX_VERSION
180         
181         cd $DOWNLOADS_DIR
182         
183         # Download busybox if we do not have it yet.
184         if [[ ! -d "$BUSYBOX_DIR" ]]; then
185                 echo "Trying to download from $BUSYBOX_DL_URL ..."
186                 
187                 wget $BUSYBOX_DL_URL -O busybox-$BUSYBOX_VERSION.tar.bz2
188                 tar -jxvf busybox-$BUSYBOX_VERSION.tar.bz2
189                 rm busybox-$BUSYBOX_VERSION.tar.bz2
190                 cp ../$BUSYBOX_CONF_FILE $BUSYBOX_DIR/.config
191         fi
192
193         # Build busybox and copy it into kfs
194         cd $BUSYBOX_DIR
195         make
196         cp busybox_unstripped ../../kern/kfs/bin/busybox
197         cd ../../
198
199         # Recompile kernel to include busybox
200         make
201
202         echo -e "[BUILD_BUSYBOX]: End\n"
203 }
204
205 # TODO: This won't work for RISCV, it must be changed to whatever is used.
206 function run_qemu() {
207         echo -e "\n[RUN_AKAROS_IN_QEMU]: Begin"
208
209         echo "-include $CONF_DIR/Makelocal_qemu" > Makelocal
210         export PATH=$WORKSPACE/install/qemu_launcher/:$PATH
211         make qemu > $AKAROS_OUTPUT_FILE &
212         MAKE_PID=$!
213
214         # TODO: Rather than finishing after Kernel PB Tests, put a generic 
215         #       "C'est fini" statement somewhere and look for it
216         WAIT_RESULT=`$SCR_WAIT_UNTIL $AKAROS_OUTPUT_FILE END_KERNEL_POSTBOOT_TESTS \
217             ${MAX_RUN_TIME:-100}`
218
219         # Extract Qemu_launcher PID
220         QEMU_PID=`ps --ppid $MAKE_PID | grep qemu_launcher | sed -e 's/^\s*//' | \
221                   cut -d' ' -f1`
222
223         # To kill qemu we need to send a USR1 signal to Qemu_launcher.
224         kill -10 $QEMU_PID
225
226         wait $MAKE_PID
227
228         echo -e "[RUN_AKAROS_IN_QEMU]: End\n"
229
230         # If the run was terminated via a timeout, then we finish with an error.
231         if [[ "$WAIT_RESULT" == TIMEOUT ]]; then
232                 echo "AKAROS was terminated after running for $MAX_RUN_TIME seconds."
233                 exit 1
234         fi
235 }
236
237
238
239 if [ "$COMPILE_ALL" == true ]; then
240         echo "Building all AKAROS"
241         build_config
242         
243         build_cross_compiler
244         build_kernel
245         build_userspace
246         build_busybox
247
248         run_qemu
249
250         AFFECTED_COMPONENTS="cross-compiler kernel userspace busybox"
251 else
252         # Save changed files between last tested commit and current one.
253         git diff --stat $GIT_PREVIOUS_COMMIT $GIT_COMMIT > $DIFF_FILE
254
255         # Extract build targets by parsing diff file.
256         AFFECTED_COMPONENTS=`$SCR_GIT_CHANGES $DIFF_FILE $CONF_COMP_COMPONENTS_FILE`
257         # Can contain {cross-compiler, kernel, userspace, busybox}
258
259         if [[ -n $AFFECTED_COMPONENTS ]]; 
260         then
261                 echo "Detected changes in "$AFFECTED_COMPONENTS
262                 build_config
263
264                 if [[ $AFFECTED_COMPONENTS == *cross-compiler* ]]
265                 then
266                         build_cross_compiler
267                         build_kernel
268                         build_userspace
269                         build_busybox
270                 else 
271                         if [[ $AFFECTED_COMPONENTS == *kernel* ]]
272                         then
273                                 build_kernel
274                         fi
275
276                         if [[ $AFFECTED_COMPONENTS == *userspace* ]]
277                         then
278                                 build_userspace
279                         fi
280
281                         if [[ $AFFECTED_COMPONENTS == *busybox* ]]
282                         then
283                                 build_busybox
284                         fi
285                 fi
286         else
287                 echo "Skipping build. No changes detected."
288         fi
289
290         run_qemu
291 fi
292
293
294 ################################################################################
295 ###############                  TEST REPORTING                  ###############
296 ################################################################################
297
298 echo -e "\n[TEST_REPORTING]: Begin"
299
300 TESTS_TO_RUN="KERNEL_POSTBOOT" # TODO(alfongj): Remove this when not needed.
301 # for COMPONENT in "${AFFECTED_COMPONENTS_ARRAY[@]}"; 
302 # do
303 #       # TODO(alfongj): Add to tests to run the name of the test suites to be ran.
304 #       # TESTS_TO_RUN="$TESTS_TO_RUN SOMETHING"
305 # done
306
307 # Generate test report
308 $SCR_GEN_TEST_REPORTS $AKAROS_OUTPUT_FILE $TEST_OUTPUT_DIR $TESTS_TO_RUN
309 echo "Tests generated in $TEST_OUTPUT_DIR"
310
311 echo -e "[TEST_REPORTING]: End\n"