How does the automatic complexity analysis of Codility work?
Probably only Codility knows for sure how they do it.  But here is how I bet they do it.

First, they devise a set of test cases of varying sizes.  They run your program on each test case and time how long it takes.  This gives them a set of observations $(n_i,t_i)$, where $n_i$ is the size of the $i$th test case and $t_i$ is the time your program takes given that input.  These can be viewed as a set of points in the 2D plane.

Second, they try to fit a curve to these points.  For instance, they check whether a line appears to fit the points, or a quadratic, or a cubic.  They probably have a library of a set of families of curves (e.g., $cn, $cn^2$, $c n \lg n$, $c \lg n$, and so on), and they check each to which ones are consistent with the observation.  Then they output that one as the running time of your algorithm.

I would imagine some adjustments might be necessary.  Rather than checking whether the points fit the curve, it might be necessary to check whether the points all fall below the curve.  For instance, rather than checking whether there exists a constant $c$ such that $t_i \approx c n_i^2$ for all $i$, they might check whether there is a constant $c$ such that $t_i \le c n_i^2$ for all $i$ (with some constraints on $c$, e.g., $c \le 1000$).  Out of all asymptotic running times that seem to be consistent with the observations, they select the asymptotically smallest one and output that one.

This approach has the advantage that it does not require analysis of source code.  All they need is the ability to run your program and time its running time.

At the same time, this heuristic is definitely not foolproof: it can give the wrong answers in some cases.  See How to fool the plot inspection heuristic?