~budgester/irm/trunk

« back to all changes in this revision

Viewing changes to testing/simpletest/dumper.php

  • Committer: budgester at budgester
  • Date: 2008-03-05 23:14:13 UTC
  • Revision ID: budgester@budgester.com-20080305231413-k5vqfuckfo09ju42
Initial import of IRM codebase

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
    /**
 
3
     *  base include file for SimpleTest
 
4
     *  @package        SimpleTest
 
5
     *  @subpackage     UnitTester
 
6
     *  @version        $Id: dumper.php,v 1.28 2006/01/03 01:17:07 lastcraft Exp $
 
7
     */
 
8
    /**
 
9
     * does type matter
 
10
     */
 
11
    if (! defined('TYPE_MATTERS')) {
 
12
        define('TYPE_MATTERS', true);
 
13
    }
 
14
    
 
15
    /**
 
16
     *    Displays variables as text and does diffs.
 
17
         *        @package      SimpleTest
 
18
         *        @subpackage   UnitTester
 
19
     */
 
20
    class SimpleDumper {
 
21
        
 
22
        /**
 
23
         *    Renders a variable in a shorter form than print_r().
 
24
         *    @param mixed $value      Variable to render as a string.
 
25
         *    @return string           Human readable string form.
 
26
         *    @access public
 
27
         */
 
28
        function describeValue($value) {
 
29
            $type = $this->getType($value);
 
30
            switch($type) {
 
31
                case "Null":
 
32
                    return "NULL";
 
33
                case "Boolean":
 
34
                    return "Boolean: " . ($value ? "true" : "false");
 
35
                case "Array":
 
36
                    return "Array: " . count($value) . " items";
 
37
                case "Object":
 
38
                    return "Object: of " . get_class($value);
 
39
                case "String":
 
40
                    return "String: " . $this->clipString($value, 200);
 
41
                default:
 
42
                    return "$type: $value";
 
43
            }
 
44
            return "Unknown";
 
45
        }
 
46
        
 
47
        /**
 
48
         *    Gets the string representation of a type.
 
49
         *    @param mixed $value    Variable to check against.
 
50
         *    @return string         Type.
 
51
         *    @access public
 
52
         */
 
53
        function getType($value) {
 
54
            if (! isset($value)) {
 
55
                return "Null";
 
56
            } elseif (is_bool($value)) {
 
57
                return "Boolean";
 
58
            } elseif (is_string($value)) {
 
59
                return "String";
 
60
            } elseif (is_integer($value)) {
 
61
                return "Integer";
 
62
            } elseif (is_float($value)) {
 
63
                return "Float";
 
64
            } elseif (is_array($value)) {
 
65
                return "Array";
 
66
            } elseif (is_resource($value)) {
 
67
                return "Resource";
 
68
            } elseif (is_object($value)) {
 
69
                return "Object";
 
70
            }
 
71
            return "Unknown";
 
72
        }
 
73
 
 
74
        /**
 
75
         *    Creates a human readable description of the
 
76
         *    difference between two variables. Uses a
 
77
         *    dynamic call.
 
78
         *    @param mixed $first        First variable.
 
79
         *    @param mixed $second       Value to compare with.
 
80
         *    @param boolean $identical  If true then type anomolies count.
 
81
         *    @return string             Description of difference.
 
82
         *    @access public
 
83
         */
 
84
        function describeDifference($first, $second, $identical = false) {
 
85
            if ($identical) {
 
86
                if (! $this->_isTypeMatch($first, $second)) {
 
87
                    return "with type mismatch as [" . $this->describeValue($first) .
 
88
                        "] does not match [" . $this->describeValue($second) . "]";
 
89
                }
 
90
            }
 
91
            $type = $this->getType($first);
 
92
            if ($type == "Unknown") {
 
93
                return "with unknown type";
 
94
            }
 
95
            $method = '_describe' . $type . 'Difference';
 
96
            return $this->$method($first, $second, $identical);
 
97
        }
 
98
        
 
99
        /**
 
100
         *    Tests to see if types match.
 
101
         *    @param mixed $first        First variable.
 
102
         *    @param mixed $second       Value to compare with.
 
103
         *    @return boolean            True if matches.
 
104
         *    @access private
 
105
         */
 
106
        function _isTypeMatch($first, $second) {
 
107
            return ($this->getType($first) == $this->getType($second));
 
108
        }
 
109
 
 
110
        /**
 
111
         *    Clips a string to a maximum length.
 
112
         *    @param string $value         String to truncate.
 
113
         *    @param integer $size         Minimum string size to show.
 
114
         *    @param integer $position     Centre of string section.
 
115
         *    @return string               Shortened version.
 
116
         *    @access public
 
117
         */
 
118
        function clipString($value, $size, $position = 0) {
 
119
            $length = strlen($value);
 
120
            if ($length <= $size) {
 
121
                return $value;
 
122
            }
 
123
            $position = min($position, $length);
 
124
            $start = ($size/2 > $position ? 0 : $position - $size/2);
 
125
            if ($start + $size > $length) {
 
126
                $start = $length - $size;
 
127
            }
 
128
            $value = substr($value, $start, $size);
 
129
            return ($start > 0 ? "..." : "") . $value . ($start + $size < $length ? "..." : "");
 
130
        }
 
131
        
 
132
        /**
 
133
         *    Creates a human readable description of the
 
134
         *    difference between two variables. The minimal
 
135
         *    version.
 
136
         *    @param null $first          First value.
 
137
         *    @param mixed $second        Value to compare with.
 
138
         *    @return string              Human readable description.
 
139
         *    @access private
 
140
         */
 
141
        function _describeGenericDifference($first, $second) {
 
142
            return "as [" . $this->describeValue($first) .
 
143
                    "] does not match [" .
 
144
                    $this->describeValue($second) . "]";
 
145
        }
 
146
        
 
147
        /**
 
148
         *    Creates a human readable description of the
 
149
         *    difference between a null and another variable.
 
150
         *    @param null $first          First null.
 
151
         *    @param mixed $second        Null to compare with.
 
152
         *    @param boolean $identical   If true then type anomolies count.
 
153
         *    @return string              Human readable description.
 
154
         *    @access private
 
155
         */
 
156
        function _describeNullDifference($first, $second, $identical) {
 
157
            return $this->_describeGenericDifference($first, $second);
 
158
        }
 
159
        
 
160
        /**
 
161
         *    Creates a human readable description of the
 
162
         *    difference between a boolean and another variable.
 
163
         *    @param boolean $first       First boolean.
 
164
         *    @param mixed $second        Boolean to compare with.
 
165
         *    @param boolean $identical   If true then type anomolies count.
 
166
         *    @return string              Human readable description.
 
167
         *    @access private
 
168
         */
 
169
        function _describeBooleanDifference($first, $second, $identical) {
 
170
            return $this->_describeGenericDifference($first, $second);
 
171
        }
 
172
        
 
173
        /**
 
174
         *    Creates a human readable description of the
 
175
         *    difference between a string and another variable.
 
176
         *    @param string $first        First string.
 
177
         *    @param mixed $second        String to compare with.
 
178
         *    @param boolean $identical   If true then type anomolies count.
 
179
         *    @return string              Human readable description.
 
180
         *    @access private
 
181
         */
 
182
        function _describeStringDifference($first, $second, $identical) {
 
183
            if (is_object($second) || is_array($second)) {
 
184
                return $this->_describeGenericDifference($first, $second);
 
185
            }
 
186
            $position = $this->_stringDiffersAt($first, $second);
 
187
            $message = "at character $position";
 
188
            $message .= " with [" .
 
189
                    $this->clipString($first, 200, $position) . "] and [" .
 
190
                    $this->clipString($second, 200, $position) . "]";
 
191
            return $message;
 
192
        }
 
193
        
 
194
        /**
 
195
         *    Creates a human readable description of the
 
196
         *    difference between an integer and another variable.
 
197
         *    @param integer $first       First number.
 
198
         *    @param mixed $second        Number to compare with.
 
199
         *    @param boolean $identical   If true then type anomolies count.
 
200
         *    @return string              Human readable description.
 
201
         *    @access private
 
202
         */
 
203
        function _describeIntegerDifference($first, $second, $identical) {
 
204
            if (is_object($second) || is_array($second)) {
 
205
                return $this->_describeGenericDifference($first, $second);
 
206
            }
 
207
            return "because [" . $this->describeValue($first) .
 
208
                    "] differs from [" .
 
209
                    $this->describeValue($second) . "] by " .
 
210
                    abs($first - $second);
 
211
        }
 
212
        
 
213
        /**
 
214
         *    Creates a human readable description of the
 
215
         *    difference between two floating point numbers.
 
216
         *    @param float $first         First float.
 
217
         *    @param mixed $second        Float to compare with.
 
218
         *    @param boolean $identical   If true then type anomolies count.
 
219
         *    @return string              Human readable description.
 
220
         *    @access private
 
221
         */
 
222
        function _describeFloatDifference($first, $second, $identical) {
 
223
            if (is_object($second) || is_array($second)) {
 
224
                return $this->_describeGenericDifference($first, $second);
 
225
            }
 
226
            return "because [" . $this->describeValue($first) .
 
227
                    "] differs from [" .
 
228
                    $this->describeValue($second) . "] by " .
 
229
                    abs($first - $second);
 
230
        }
 
231
        
 
232
        /**
 
233
         *    Creates a human readable description of the
 
234
         *    difference between two arrays.
 
235
         *    @param array $first         First array.
 
236
         *    @param mixed $second        Array to compare with.
 
237
         *    @param boolean $identical   If true then type anomolies count.
 
238
         *    @return string              Human readable description.
 
239
         *    @access private
 
240
         */
 
241
        function _describeArrayDifference($first, $second, $identical) {
 
242
            if (! is_array($second)) {
 
243
                return $this->_describeGenericDifference($first, $second);
 
244
            }
 
245
            if (! $this->_isMatchingKeys($first, $second, $identical)) {
 
246
                return "as key list [" .
 
247
                        implode(", ", array_keys($first)) . "] does not match key list [" .
 
248
                        implode(", ", array_keys($second)) . "]";
 
249
            }
 
250
            foreach (array_keys($first) as $key) {
 
251
                if ($identical && ($first[$key] === $second[$key])) {
 
252
                    continue;
 
253
                }
 
254
                if (! $identical && ($first[$key] == $second[$key])) {
 
255
                    continue;
 
256
                }
 
257
                return "with member [$key] " . $this->describeDifference(
 
258
                        $first[$key],
 
259
                        $second[$key],
 
260
                        $identical);
 
261
            }
 
262
            return "";
 
263
        }
 
264
        
 
265
        /**
 
266
         *    Compares two arrays to see if their key lists match.
 
267
         *    For an identical match, the ordering and types of the keys
 
268
         *    is significant.
 
269
         *    @param array $first         First array.
 
270
         *    @param array $second        Array to compare with.
 
271
         *    @param boolean $identical   If true then type anomolies count.
 
272
         *    @return boolean             True if matching.
 
273
         *    @access private
 
274
         */
 
275
        function _isMatchingKeys($first, $second, $identical) {
 
276
            $first_keys = array_keys($first);
 
277
            $second_keys = array_keys($second);
 
278
            if ($identical) {
 
279
                return ($first_keys === $second_keys);
 
280
            }
 
281
            sort($first_keys);
 
282
            sort($second_keys);
 
283
            return ($first_keys == $second_keys);
 
284
        }
 
285
        
 
286
        /**
 
287
         *    Creates a human readable description of the
 
288
         *    difference between a resource and another variable.
 
289
         *    @param resource $first       First resource.
 
290
         *    @param mixed $second         Resource to compare with.
 
291
         *    @param boolean $identical    If true then type anomolies count.
 
292
         *    @return string              Human readable description.
 
293
         *    @access private
 
294
         */
 
295
        function _describeResourceDifference($first, $second, $identical) {
 
296
            return $this->_describeGenericDifference($first, $second);
 
297
        }
 
298
        
 
299
        /**
 
300
         *    Creates a human readable description of the
 
301
         *    difference between two objects.
 
302
         *    @param object $first        First object.
 
303
         *    @param mixed $second        Object to compare with.
 
304
         *    @param boolean $identical   If true then type anomolies count.
 
305
         *    @return string              Human readable description.
 
306
         *    @access private
 
307
         */
 
308
        function _describeObjectDifference($first, $second, $identical) {
 
309
            if (! is_object($second)) {
 
310
                return $this->_describeGenericDifference($first, $second);
 
311
            }
 
312
            return $this->_describeArrayDifference(
 
313
                    get_object_vars($first),
 
314
                    get_object_vars($second),
 
315
                    $identical);
 
316
        }
 
317
        
 
318
        /**
 
319
         *    Find the first character position that differs
 
320
         *    in two strings by binary chop.
 
321
         *    @param string $first        First string.
 
322
         *    @param string $second       String to compare with.
 
323
         *    @return integer             Position of first differing
 
324
         *                                character.
 
325
         *    @access private
 
326
         */
 
327
        function _stringDiffersAt($first, $second) {
 
328
            if (! $first || ! $second) {
 
329
                return 0;
 
330
            }
 
331
            if (strlen($first) < strlen($second)) {
 
332
                list($first, $second) = array($second, $first);
 
333
            }
 
334
            $position = 0;
 
335
            $step = strlen($first);
 
336
            while ($step > 1) {
 
337
                $step = (integer)(($step + 1) / 2);
 
338
                if (strncmp($first, $second, $position + $step) == 0) {
 
339
                    $position += $step;
 
340
                }
 
341
            }
 
342
            return $position;
 
343
        }
 
344
        
 
345
        /**
 
346
         *    Sends a formatted dump of a variable to a string.
 
347
         *    @param mixed $variable    Variable to display.
 
348
         *    @return string            Output from print_r().
 
349
         *    @access public
 
350
         *    @static
 
351
         */
 
352
        function dump($variable) {
 
353
            ob_start();
 
354
            print_r($variable);
 
355
            $formatted = ob_get_contents();
 
356
            ob_end_clean();
 
357
            return $formatted;
 
358
        }
 
359
 
 
360
        /**
 
361
         *    Extracts the last assertion that was not within
 
362
         *    Simpletest itself. The name must start with "assert".
 
363
         *    @param array $stack      List of stack frames.
 
364
         *    @access public
 
365
         *    @static
 
366
         */
 
367
        function getFormattedAssertionLine($stack) {
 
368
            foreach ($stack as $frame) {
 
369
                if (isset($frame['file'])) {
 
370
                    if (strpos($frame['file'], SIMPLE_TEST) !== false) {
 
371
                        if (dirname($frame['file']) . '/' == SIMPLE_TEST) {
 
372
                            continue;
 
373
                        }
 
374
                    }
 
375
                }
 
376
                if (SimpleDumper::_stackFrameIsAnAssertion($frame)) {
 
377
                    return ' at [' . $frame['file'] . ' line ' . $frame['line'] . ']';
 
378
                }
 
379
            }
 
380
            return '';
 
381
        }
 
382
        
 
383
        /**
 
384
         *    Tries to determine if the method call is an assertion.
 
385
         *    @param array $frame     PHP stack frame.
 
386
         *    @access private
 
387
         *    @static
 
388
         */
 
389
        function _stackFrameIsAnAssertion($frame) {
 
390
            if (($frame['function'] == 'fail') || ($frame['function'] == 'pass')) {
 
391
                return true;
 
392
            }
 
393
            if (strncmp($frame['function'], 'assert', 6) == 0) {
 
394
                return true;
 
395
            }
 
396
            if (strncmp($frame['function'], 'expect', 6) == 0) {
 
397
                return true;
 
398
            }
 
399
            return false;
 
400
        }
 
401
    }
 
402
?>
 
 
b'\\ No newline at end of file'