Marking as major because this means testing is broken for any project using composer (with or without composer_manager). No builds passing.
1) core/vendor/bin/phpunit includes the nearest autoloader, which is core/vendor/autoload.php
2) core/tests/bootstrap.php then blindly includes the root autoload.php
By default, the root autoload.php also points to core/vendor, and no crash occurs.
However, once you start using the root composer.json and have a root vendor directory, you overwrite autoload.php to point to root/vendor, and phpunit is now including a different autoloader. These two autoloaders conflict, and a crash occurs.
I've spoken to Fabianx about this and we agreed that there's no way to avoid the hack that is drupal_phpunit_get_extension_namespaces().
Instead, we should just use the phpunit that's in the root vendor directory ('./vendor/bin/phpunit -c core').
However, simpletest also invokes phpunit, and it hardcodes the one in core/vendor:
function simpletest_phpunit_command() {
// Don't use the committed version in composer's bin dir if running on
// windows.
if (substr(PHP_OS, 0, 3) == 'WIN') {
$php_executable_finder = new PhpExecutableFinder();
$php = $php_executable_finder->find();
$phpunit_bin = escapeshellarg($php) . " -f " . escapeshellarg(\Drupal::root() . "/core/vendor/phpunit/phpunit/composer/bin/phpunit") . " --";
}
else {
$phpunit_bin = \Drupal::root() . "/core/vendor/bin/phpunit";
}
return $phpunit_bin;
}
Should we just add an is_dir(\Drupal::root() . '/vendor') and switch based on that? Or introduce an environment variable override?
Fabian suggested having an option to turn off phpunit invocation completely, but I don't like having to enforce two different testing workflows based on whether composer is used or not.
Comment | File | Size | Author |
---|---|---|---|
#15 | 2554849-15.patch | 1.4 KB | bojanz |
#15 | interdiff-14-15.txt | 1.37 KB | bojanz |
#14 | 2554849-14.patch | 1.41 KB | hussainweb |
#14 | interdiff-9-14.txt | 1.46 KB | hussainweb |
Comments
Comment #2
bojanz CreditAttribution: bojanz commentedI should note that I've tried to have a different autoloader-prefix in the root composer.json, but that doesn't prevent the whole conflict because both autoloaders also try to unconditionally include core/lib/Drupal.php (cause it's in the "files" property in composer.json).
Comment #3
davidwbarratt CreditAttribution: davidwbarratt at Golf Channel commentedI put my vendor directory in
../vendor
so your proposed fix wouldn't help. I suggest we modify./core/phpunit.dist.xml
to exclude../vendor
or we have an examplephpunit.xml
in the root for people to use.Comment #4
bojanz CreditAttribution: bojanz commentedNo phpunit.xml will help you avoid this issue, cause the second autoloader inclusion is coming from core/tests/bootstrap.php
It's not config controlled at all.
EDIT: To clarify, the main problem here is that run_tests.sh (simpletest) insists on invoking phpunit from a hardcoded location.
You are free to run phpunit from the root directory yourself, pointing it at core's config file, that works. But simpletest still fails.
Comment #5
Mile23The first step is to avoid two vendor directories: #2380389: Use a single vendor directory in the root
Then we can just have phpunit.xml.dist at the root level.
Then it can find the right bootstrap file.
Then the bootstrapper can find the right autoload.
And all will be right with the world, and no one will have to waste time figuring out that they need to say
./vendor/bin/phpunit -c core
Example configurations which work around workarounds we can fix right now are a bad idea.
Comment #6
davidwbarratt CreditAttribution: davidwbarratt at Golf Channel commentedAre you talking about:
?
If so, the
autoload.php
file tells you to modify it:which should prevent the second inclusion, no?
Comment #7
bojanz CreditAttribution: bojanz commented@Mile23
Please stop repeating the same only slightly relevant story on each issue.
@davidwbarratt
No. I wrote in the issue summary clearly where the two inclusions happen:
core/vendor/bin/phpunit:
core/tests/bootstrap.php:
The autoload.php is the root file you are referring to, the one now pointing to the root vendor dir, therefore causing the crash.
Comment #8
davidwbarratt CreditAttribution: davidwbarratt at Golf Channel commentedAh! I understand now. sorry, I'm not sure why I was so confused.
I got around this by doing what you recommended:
I do that mostly because I just pretend that
./core/vendor
doesn't exist.However, I haven't run simpletest, but looking at what you posted, yes it would break. :/
But also, despite Mile23's enthusiasm, #2380389: Use a single vendor directory in the root doesn't not solve the problem if you are like me and your vendor directory is not
./vendor
but is instead../vendor
(or anywhere else for that matter).Comment #9
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedAFAIK we just have to remove the hardcoded path and retrieve the path from autoload.php.
Comment #10
Mile23This is precisely why I'm cynical about anyone finding a solution: No one will listen to the answer when its handed to them.
It's the same story because it's the same problem: If we put everything in *1* place, then we can modify run-tests.sh to look in the *1* place.
But what the hell do I know?
Wrong.
If we normalize on a single vendor directory, then changes to where that vendor directory is located become easier. If Drupal knows that there is only one vendor directory, then you can fake it out more easily.
If you solve this issue by making another workaround, you make it increasingly more impossible to solve the real problem.
BTW, before I realized I was not welcome to help solve this issue, I made a travis test. Go ahead and fork it if it doesn't actually reflect the behavior you're discussing. It passes right now because it's broken.
https://travis-ci.org/paul-m/d8-drupal-require-mod-autoload
Comment #11
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #12
bojanz CreditAttribution: bojanz at Centarro commented#9 works for me. I think it's as clean as we can get. Thank you, webflo.
+1 to RTBC.
EDIT: We could use a comment reminding the reader why we're using reflection. I can do that reroll.
Comment #13
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #14
hussainwebI added a comment to explain why we are using reflection. I also changed the variable name to be something hopefully more descriptive.
Comment #15
bojanz CreditAttribution: bojanz at Centarro commentedYou beat me to it :)
Converted it's to its, and double quotes to single quotes, since we're changing those lines anyway and this is more in line with what core usually does.
Comment #16
XanoI'd extend this comment with an explanation of how/why we can determine the dir, but that's a nitpick and isn't in the way of RTBC.
Comment #17
timmillwoodGood find!
RTBC +1
Comment #18
alexpottThis issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed f82e0a3 and pushed to 8.0.x. Thanks!