Upgrade to Pro — share decks privately, control downloads, hide ads and more …

test || die

test || die

Presented by Zoe Slattery at PHP London Conference 2008

As PHP becomes ever more successful the requirement for stability increases and the freedom to make changes in the core code is correspondingly restricted.

Is the test coverage sufficient? Especially given the wide range and depth of change required to implement Unicode support.

Based on experience of contributing PHP tests, I'll talk about tests, coverage and what needs to happen!

PHP Community

February 29, 2008
Tweet

More Decks by PHP Community

Other Decks in Programming

Transcript

  1. test||die
    Testing the PHP implementation
    Zoë Slattery
    PHP London , February 29th 2008

    View full-size slide

  2. PHP Interpreter
    Extensions ( C )
    PHP code
    Why is the initialisation of
    class values
    unpredictable?
    Enough! – I’m going to
    spend my free time at
    parties…no more PHP
    Another BOGUS bug!
    I want to check­in this
    elegant bug fix but I
    have no clue what else
    it might break…
    Why is ­2^31 a float
    sometimes and an int
    other times?
    WHY?

    View full-size slide

  3. var_dump(PHP_INT_MAX);
    $min = ­PHP_INT_MAX ­ 1;
    var_dump($min);
    $min2 = ­2147483648;
    var_dump($min2);
    ?>
    int(2147483647)
    int(­2147483648)
    float(­2147483648)
    EXAMPLE 1

    View full-size slide

  4. B
    A K
    class C {
    const A = K;
    const B = K;
    }
    class C {
    public static $a = K;
    public static $b = K;
    }
    $b
    $a K
    C::A; K
    B
    A K
    K
    K
    C::$a;
    $b
    $a K
    echo “C::A = “.C::A.”\n”;
    echo “C::B = “.C::B.”\n”;
    6 6
    K
    B
    A K
    K K 6
    echo “C::$a = “.C::$a.”\n”;
    echo “C::$b = “.C::$b.”\n”;
    $b
    $a K
    define(‘K’, 6); K 6
    B
    A K
    define(‘K’, 6); K
    K 6
    $b
    $a K
    Class constants Static variables
    EXAMPLE 2

    View full-size slide

  5. Changes in source/ext, source/Zend, source/tests
    This looks like a lot …but actually – it’s a drop in the ocean ….
    What are we doing?
    2005 2006 2007 2008
    0
    500
    1000
    1500
    2000
    2500
    C and PHPT files changed in PHP 5
    C files added
    C files modified
    PHPT files added
    PHPT files modified
    Year
    Number of files

    View full-size slide

  6. A simple PHPTest
    ­­TEST­­
    strtr() function ­ basic test for strtr()
    ­­FILE­­
    $trans = array("hello"=>"hi",
    "hi"=>"hello",
    "a"=>"A", "world"=>"planet");
    var_dump(strtr("# hi all, I said hello world! #", $trans));
    ?>
    ­­EXPECT­­
    string(32) "# hello All, I sAid hi planet! #"

    View full-size slide

  7. test.phpt
    test.out
    test.exp
    test.diff
    run­tests.php
    Summary
    Summary + files
    Running PHPT tests
    php run­tests.php test.phpt
    Pass
    Fail

    View full-size slide

  8. PHP needs TESTS!
    PHP doesn't have enough test cases
    If you can write PHP you can write tests
    Writing tests can help improve your PHP coding
    Marcus BÖrger's slides on writing tests
    http://talks.somabo.de/

    View full-size slide

  9. Get involved!

    View full-size slide

  10. PHP Worldwide
    http://wiki.pooteeweet.org/TestFest
    LONDON! Second week in May – watch this Wiki!

    View full-size slide

  11. EXAMPLE 3
    Functions which expect integer input cast floating point values to int.
    #define DVAL_TO_LVAL(d, l) \
    if ((d) > LONG_MAX) { \
    (l) = (unsigned long) (d); \
    } else { \
    (l) = (long) (d); \
    }
    Linux, Windows 32 => lowest 32 bits of the representation as an integer.
    Mac=> lowest 32 bit UNLESS the integer overflows THEN ­1.
    Functions which are passed doubles by mistake will give unpredictable results on all platforms
    unless the function code makes an explicit check.

    View full-size slide

  12. This went into PHP4:
    #define DVAL_TO_LVAL(d, l) \
    if ((d) > LONG_MAX) { \
    (l) = LONG_MAX; \
    } else if ((d) < LONG_MIN) {/
    (l) = LONG_MIN; \
    } else { \
    (l) = (long) (d); \
    }
    Didn't work – Bug 30695
    Will convert 0x80000000 to INT_MAX (0x7FFFFFFF).
    What now?
    special case 0x8000000 to 0xFFFFFFFF (what side effects would there be?)
    every extension does it’s own checking (time consuming!)
    EXAMPLE 3 ­ Fix#1

    View full-size slide

  13. Integer repr'n in
    decimal on Mac
    Integer rep'n in
    decimal on
    Linux/Win
    Integer represented
    in hex on Lin/Win
    Cast to integer
    Floating point
    representation of
    4 bits
    O’flow
    ­1
    1
    0x1
    0001
    0001
    INT_MAX * 2 + 3 (17)
    ­1
    0
    0x0
    0000
    0001
    INT_MAX *2 + 2 (16)
    ­1
    ­1
    0xF
    1111
    INT_MAX *2 + 1 (15)
    ­2
    ­2
    0xE
    1110
    INT_MAX *2 (14)
    ­3
    ­3
    0xD
    1101
    INT_Max * 2 – 1 (13)
    ­7
    ­7
    0x9
    1001
    INT_MAX + 2 (9)
    ­8
    ­8
    0x8
    1000
    INT_MAX + 1 (8)
    7
    7
    0x7
    0111
    INT_MAX (7)
    EXAMPLE 3 ­ details

    View full-size slide

  14. EXAMPLE 3 ­ Fix#2
    # define DVAL_TO_LVAL(d, l) \
    if ((d) > LONG_MAX) { \
    if ((d) >
    MAX_UNSIGNED_INT) { \
    (l) = LONG_MAX;
    \
    } else { \
    (l) = (unsigned
    long) (d); \
    } \
    } else { \
    if((d) < LONG_MIN)
    { \
    (l) = LONG_MIN;
    \
    } else { \
    (l) = (long)
    (d); \
    } \
    }

    View full-size slide