JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
delete string_array.php (buggy, stupid)
[wfpl.git] / unit_tests.php
1 <?php
2
3 #  Copyright (C) 2009 Jason Woofenden
4 #
5 #  This program is free software: you can redistribute it and/or modify
6 #  it under the terms of the GNU General Public License as published by
7 #  the Free Software Foundation, either version 3 of the License, or
8 #  (at your option) any later version.
9 #  
10 #  This program is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #  GNU General Public License for more details.
14 #  
15 #  You should have received a copy of the GNU General Public License
16 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
19 # This file is for running unit tests. Either on wfpl or your own code.
20
21 require_once(__DIR__.'/'.'template.php');
22 require_once(__DIR__.'/'.'messages.php');
23
24 # call this to declare that a unit test has passed
25 function unit_test_passed($msg) {
26         $GLOBALS['unit_tests_passed_msgs'][] = $msg;
27         $GLOBALS['unit_tests_passed'] += 1;
28 }
29
30 # call this to declare that a unit test has failed
31 function unit_test_failed($msg) {
32         $GLOBALS['unit_tests_failed_msgs'][] = $msg;
33         $GLOBALS['unit_tests_failed'] += 1;
34 }
35
36 function backslashinate($str) {
37         return '"' . addcslashes($str, "\0..\37\"\\\177..\377") . '"';
38 }
39
40 function backslashinate_each($a) {
41         foreach($a as &$v) {
42                 $v = backslashinate($v);
43         }
44
45         return $a;
46 }
47         
48
49 # use this function to unit-test a function
50 # real prototype: ($name, $args..., $correct)
51 function unit_test_func() {
52         $args = func_get_args();
53         $function = array_shift($args);
54         $correct = array_pop($args);
55         $result = call_user_func_array($function, $args);
56         $message = "$function(" . join(', ', backslashinate_each($args)) . ") returned " . backslashinate($result);
57         if($result === $correct) {
58                 unit_test_passed($message);
59         } else {
60                 unit_test_failed($message . " instead of " . backslashinate($correct));
61         }
62 }
63
64
65 function file_run_unit_tests($filename) {
66         require_once($filename);
67         $func = basename($filename, '.php') . '_unit_tests_main';
68
69         if(function_exists($func)) {
70                 return $func();
71         }
72 }
73
74 # Run many unit tests. Pass a directory containing php files with tests in
75 # them, and a space-separated list of their basenames. Each of those files is
76 # expected to define a function <basename>_unit_tests_main which will run all
77 # tests in that file. It should print a message() about each test that failed,
78 # and return the number of tests that failed.
79 function run_unit_tests($directory, $basenames) {
80         $files = array();
81         $GLOBALS['unit_tests_passed'] = 0;
82         $GLOBALS['unit_tests_failed'] = 0;
83         $basenames = explode(' ', $basenames);
84         foreach($basenames as $basename) {
85                 $GLOBALS['unit_tests_passed_msgs'] = array();
86                 $GLOBALS['unit_tests_failed_msgs'] = array();
87                 $already_passed = $GLOBALS['unit_tests_passed'];
88                 $already_failed = $GLOBALS['unit_tests_failed'];
89                 $filename = "$directory/$basename.php";
90                 file_run_unit_tests($filename);
91                 $files[] = array(
92                         'file' => $filename,
93                         'fails' => columnize($GLOBALS['unit_tests_failed_msgs']),
94                         'passes' => columnize($GLOBALS['unit_tests_passed_msgs']),
95                         'count_passed' => $GLOBALS['unit_tests_passed'] - $already_passed,
96                         'count_failed' => $GLOBALS['unit_tests_failed'] - $already_failed
97                 );
98         }
99         $passed = $GLOBALS['unit_tests_passed'];
100         $failed = $GLOBALS['unit_tests_failed'];
101         tem_set('unit_tests', array(
102                 'files' => $files,
103                 'total_passed' => $passed,
104                 'total_failed' => $failed
105         ));
106 }
107
108 # Call this to unit test wfpl. By default it tests everything, or you can pass
109 # a space-separated list of the basenames of the files in wfpl/unit_tests/
110 # that you'd like to run.
111 function unit_test_wfpl($basenames = 'format db misc encode') {
112         tem_load(__DIR__.'/'.'unit_tests/template.html');
113         run_unit_tests(__DIR__.'/'.'unit_tests', $basenames);
114         display_messages();
115         tem_output();
116         exit();
117 }