1

I have some PHPT tests that are being run in PHPUnit. These tests include a --CLEAN-- section that handles the deletion of files created during the test. Running the PHPT tests at the command line using pear run-tests works fine, but when they are run though PHPUnit I get the following error:

BORKED --CLEAN-- section! output:
X-Powered-By: PHP/5.3.10-1ubuntu3.2
Content-type: text/html

This obviously looks like an HTTP header, but there is no further text, and the actions in the clean section still work as planned. Removing the CLEAN section removes the problem, but I would rather not have the test cleanup done outside of the PHPT file. Any ideas on what these are caused by, and how to get rid of them? They're not breaking the tests, but they look untidy in the output.

A PHPT test (the POST file data is truncated to protect my employment):

--TEST--
Test file upload
--POST_RAW-- 
Content-Type: multipart/form-data; boundary=---------------------------168481652011378167832091260413
Content-Length: 3510

-----------------------------168481652011378167832091260413
Content-Disposition: form-data; name="code"

te
-----------------------------168481652011378167832091260413
Content-Disposition: form-data; name="name"

test
-----------------------------168481652011378167832091260413
Content-Disposition: form-data; name="file"; filename="test.xml"
Content-Type: text/xml

<?xml  version="1.0" encoding="utf-8"?>
<testElement>
    <innerElement />
</testElement>

-----------------------------168481652011378167832091260413--
--FILE--
<?php
// Zend/PHPUnit bootstrap
require_once __DIR__ . '/../../../bootstrap.php';

$upload = new My_File_Upload();
var_dump($upload->handleFile(
    'file', 
    APPLICATION_PATH . '/../datafiles/request/',
    'application/xml',
    'testname'
));
var_dump(file_exists(APPLICATION_PATH . '/../datafiles/request/testname.xml'))
?>
--CLEAN--
<?php
    $file = dirname(__FILE__) . '/../../../../datafiles/request/testname.xml';
    if(file_exists($file)) unlink($file);
?>
--EXPECT--
string(12) "testname.xml"
bool(true)

A Zend/PHPUnit test wrapper:

<?php
require_once 'PHPUnit/Extensions/PhptTestCase.php';
/**
 * UploadFileHandleTest
 * 
 * PHPUnit wrapper for the phpt test file UploadFileHandleTest.phpt
 *
 */
class My_File_UploadFileHandle extends PHPUnit_Extensions_PhptTestCase
{
    /**
     * Test file uploads
     * 
     * Test the file uploads using associated .phpt test files. These test have to 
     * be abstracted to the php-cgi environment to permit accurate manipulation of 
     * the $_FILES superglobal. 
     * 
     * @see http://qafoo.com/blog/013_testing_file_uploads_with_php.html
     * 
     * @covers My_File_Upload::handleFile
     * 
     * @return void
     */
    public function __construct() 
    { 
        parent::__construct(__DIR__ . '/UploadFileHandleTest.phpt'); 
    }

    /**
     * Implement missing hasOutput method for PHPUnit
     * 
     * @return boolean 
     */
    public function hasOutput()
    {
        return false;
    }
}

The test suite to trigger the wrappers:

<?php

require_once 'UploadFileExists.php';
require_once 'UploadFileHandle.php';
require_once 'UploadFileHandleNoName.php';
require_once 'UploadFileHandleExceptions.php';

class My_File_UploadTestSuite extends PHPUnit_Framework_TestSuite
{
    public static function suite()
    {
        $suite = new My_File_UploadTestSuite('My_File_UploadFileTests');

        $suite->addTest(new My_File_UploadFileExists());
        $suite->addTest(new My_File_UploadFileHandle());
        $suite->addTest(new My_File_UploadFileHandleNoName());
        $suite->addTest(new My_File_UploadFileHandleExceptions());

        return $suite;
    }
}
shanethehat
  • 15,460
  • 11
  • 57
  • 87
  • There should be a double CRLF (i.e. add an extra empty line) between `Content-Length: 3510` and the request body. Don't know is this will fix it, but that is definitely *a* problem. Also verify that `3510` is the correct byte length for the message body - which it doesn't look like it is based on the data you posted. – DaveRandom Jul 18 '12 at 14:14
  • Thanks for the answer, I'll give it a go. The POSTed file data has been truncated in this example to protect IP so the length should be correct. It was harvested from a genuine header in Firefox. – shanethehat Jul 19 '12 at 07:10
  • Adding an extra line after the content length has not made a difference. The tests do run correctly, it just seems to spit out this message as an afterthought. – shanethehat Jul 19 '12 at 07:26
  • I'm thinking it's got something to do with all those `/..`s in the path in the --CLEAN-- section then. Does `testname.xml` actually get deleted during the cleanup? – DaveRandom Jul 19 '12 at 08:28
  • Yes, the actual clean operations execute fine. – shanethehat Jul 19 '12 at 08:29
  • I know this may sound like a long shot, but try removing the line break and any other white-space between `?>` and `--EXPECT--` – DaveRandom Jul 19 '12 at 08:31
  • By which I mean the *extra* line break, so it goes `"...?>\n--CLEAN--..."` instead of `"...?>\n\n--CLEAN--..."` – DaveRandom Jul 19 '12 at 08:33
  • That doesn't seem to have made any difference either. I've tightened up the whitespace as much as I think I can, so there's no blank lines before any of the section headers – shanethehat Jul 19 '12 at 08:38

1 Answers1

3

This is caused by using the PHP CGI executable to run your tests instead of the CLI version. The CGI binary will append the two headers in front of the response, and the PEAR module used for testing will scream bork bork and bloody murder if there's output provided from the code run in the --CLEAN-- section. Point the tests to the correct PHP binary and the issue should go away.

:~$ echo "" | php5-cgi
X-Powered-By: PHP/5.3.10-1ubuntu3.2
Content-type: text/html

Update: This is caused by an error in PEAR_RunTest where it doesn't reset which interpreter to use when running the --CLEAN-- section. I've patched PEAR_RunTest to fix the issue and submitted a PR for the issue.

MatsLindh
  • 49,529
  • 4
  • 53
  • 84
  • I was thinking exactly this when I suggested removing the whitespace after the `?>` tag in the `--CLEAN--` section. The problem, I suspect, will be that when you use a `--POST_RAW--` section, it will automatically use the CGI binary ([source](http://qa.php.net/phpt_details.php#post_raw_section)) - I don't know if this also applies to the code in the `--CLEAN--` section, but if it does there may be nothing one can do to stop this (in which case I would call this a bug). But definitely +1 - this answer identifies the problem, but whether there is a solution I don't know... – DaveRandom Jul 19 '12 at 09:11
  • I was under the impression that you have to run under CGI when using `--POST_RAW--` or the header is not applied, but I'll happily give it a try. How can I force PHPUnit to run the test as CLI instead? – shanethehat Jul 19 '12 at 09:36
  • It's a bug in PEAR_RunTest. I've updated my answer with a link to my pull request for the bug fix in PEAR. You might be able to provide a 'cgi' value in the $options array if you don't need the headers when running the test (-q to php-cgi suppresses the headers). – MatsLindh Jul 19 '12 at 12:45