iPXE
profile_test.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 /** @file
00027  *
00028  * Profiling self-tests
00029  *
00030  */
00031 
00032 /* Forcibly enable assertions */
00033 #undef NDEBUG
00034 
00035 #include <string.h>
00036 #include <assert.h>
00037 #include <ipxe/test.h>
00038 #include <ipxe/profile.h>
00039 
00040 /** A profiling test */
00041 struct profile_test {
00042         /** Sample values */
00043         const unsigned long *samples;
00044         /** Number of samples */
00045         unsigned int count;
00046         /** Expected mean sample value */
00047         unsigned long mean;
00048         /** Expected standard deviation */
00049         unsigned long stddev;
00050 };
00051 
00052 /** Define inline data */
00053 #define DATA(...) { __VA_ARGS__ }
00054 
00055 /** Define a profiling test */
00056 #define PROFILE_TEST( name, MEAN, STDDEV, SAMPLES )                     \
00057         static const unsigned long name ## _samples[] = SAMPLES;        \
00058         static struct profile_test name = {                             \
00059                 .samples = name ## _samples,                            \
00060                 .count = ( sizeof ( name ## _samples ) /                \
00061                            sizeof ( name ## _samples [0] ) ),           \
00062                 .mean = MEAN,                                           \
00063                 .stddev = STDDEV,                                       \
00064         }
00065 
00066 /** Empty data set */
00067 PROFILE_TEST ( empty, 0, 0, DATA() );
00068 
00069 /** Single-element data set (zero) */
00070 PROFILE_TEST ( zero, 0, 0, DATA ( 0 ) );
00071 
00072 /** Single-element data set (non-zero) */
00073 PROFILE_TEST ( single, 42, 0, DATA ( 42 ) );
00074 
00075 /** Multiple identical element data set */
00076 PROFILE_TEST ( identical, 69, 0, DATA ( 69, 69, 69, 69, 69, 69, 69 ) );
00077 
00078 /** Small element data set */
00079 PROFILE_TEST ( small, 5, 2, DATA ( 3, 5, 9, 4, 3, 2, 5, 7 ) );
00080 
00081 /** Random data set */
00082 PROFILE_TEST ( random, 70198, 394,
00083                DATA ( 69772, 70068, 70769, 69653, 70663, 71078, 70101, 70341,
00084                       70215, 69600, 70020, 70456, 70421, 69972, 70267, 69999,
00085                       69972 ) );
00086 
00087 /** Large-valued random data set */
00088 PROFILE_TEST ( large, 93533894UL, 25538UL,
00089                DATA ( 93510333UL, 93561169UL, 93492361UL, 93528647UL,
00090                       93557566UL, 93503465UL, 93540126UL, 93549020UL,
00091                       93502307UL, 93527320UL, 93537152UL, 93540125UL,
00092                       93550773UL, 93586731UL, 93521312UL ) );
00093 
00094 /**
00095  * Report a profiling test result
00096  *
00097  * @v test              Profiling test
00098  * @v file              Test code file
00099  * @v line              Test code line
00100  */
00101 static void profile_okx ( struct profile_test *test, const char *file,
00102                           unsigned int line ) {
00103         struct profiler profiler;
00104         unsigned long mean;
00105         unsigned long stddev;
00106         unsigned int i;
00107 
00108         /* Initialise profiler */
00109         memset ( &profiler, 0, sizeof ( profiler ) );
00110 
00111         /* Record sample values */
00112         for ( i = 0 ; i < test->count ; i++ )
00113                 profile_update ( &profiler, test->samples[i] );
00114 
00115         /* Check resulting statistics */
00116         mean = profile_mean ( &profiler );
00117         stddev = profile_stddev ( &profiler );
00118         DBGC ( test, "PROFILE calculated mean %ld stddev %ld\n", mean, stddev );
00119         okx ( mean == test->mean, file, line );
00120         okx ( stddev == test->stddev, file, line );
00121 }
00122 #define profile_ok( test ) profile_okx ( test, __FILE__, __LINE__ )
00123 
00124 /**
00125  * Perform profiling self-tests
00126  *
00127  */
00128 static void profile_test_exec ( void ) {
00129 
00130         /* Perform profiling tests */
00131         profile_ok ( &empty );
00132         profile_ok ( &zero );
00133         profile_ok ( &single );
00134         profile_ok ( &identical );
00135         profile_ok ( &small );
00136         profile_ok ( &random );
00137         profile_ok ( &large );
00138 }
00139 
00140 /** Profiling self-test */
00141 struct self_test profile_test __self_test = {
00142         .name = "profile",
00143         .exec = profile_test_exec,
00144 };