#31130 closed defect (bug) (fixed)
WP_INSTALLING causes leakage between unit tests
Reported by: | boonebgorges | Owned by: | boonebgorges |
---|---|---|---|
Milestone: | 4.4 | Priority: | normal |
Severity: | normal | Version: | |
Component: | Build/Test Tools | Keywords: | has-patch dev-feedback |
Focuses: | Cc: |
Description (last modified by )
A number of multisite unit tests invoke WP_UnitTest_Factory_for_Blog::create()
, which uses wpmu_create_blog()
to create a blog. Whenever this happens, the WP_INSTALLING
constant is defined as true
for all later tests. This has a number of ramifications, especially in the Options API, which skips the cache when WP_INSTALLING
. See [28965], [31280], #28706.
I see four strategies for working around the problem:
- For any test that breaks when
WP_INSTALLING
, mark it skipped on multisite. This is what we're currently doing, and is lame. - Create wrapper functions for
WP_INSTALLING
so that it can be toggled on and off (unlike a constant). Eitherapply_filters()
, or a global toggle likewp_suspend_cache_invalidation()
. Then, inWP_UnitTest_Factory_For_Blog::create()
, toggle it off afterwpmu_create_blog()
has turned it on. The main downside here is thatWP_INSTALLING
is not really the kind of thing we want to be toggleable by devs, so we'd have to document it accordingly. - Run all blog-creating tests in separate processes that don't preserve the global state. That way, the constant would be set in the other process, but not when returning to run the rest of the tests. I played with this a little, and it looks like it's not going to be trivial to make it work - we may need to bootstrap WordPress for every test or something like that.
- Make sure that all tests that create a blog are run at the very end of the suite.
Option (2) seems like the most natural fix, but it's also the only one that touches src/
. Any additional thoughts are welcome.
Attachments (5)
Change History (36)
This ticket was mentioned in Slack in #core-multisite by jeremyfelt. View the logs.
10 years ago
#5
@
10 years ago
And more good conversation in #22251, with an IRC discussion to match.
#6
@
10 years ago
- Keywords has-patch dev-feedback added
31130.diff is an initial attempt at solving this.
- Introduce
$wp_config
inwp-settings.php
to hold any configuration data normally stored in constants. - Introduce
wp_define()
indefault-constants.php
for core to use as a way to define constants or to set the property in$wp_config
if tests are running. - Introduce
wp_defined()
indefault-constants.php
for core to use for retrieval of constants or$wp_config
data if tests are running. - Change all instances of
define()
anddefined()
used forWP_INSTALLING
towp_define()
andwp_defined()
. Some are not changed due to load order in places such aswp-activate.php
orinstall.php
, but may be possible with further exploration. These are not requirements for unit testing right now. - Reset the global
$wp_config
when tearing down tests. - Un-skip multisite tests that were previously skipped for
WP_INSTALLING
reasons. These appear to all pass. - Use
wp_schedule_update_network_counts()
when testing the same function, something we could not do before withWP_INSTALLING
defined.
Caveats...
I did get one random failed test out of several attempts for test_orderby_meta()
, but it never appeared again.
1) Tests_Comment_Query::test_orderby_meta Failed asserting that '322' matches expected 320. /srv/www/wordpress-develop/tests/phpunit/tests/comment/query.php:616
And the test of current_user_can_for_blog()
on a non-existing site now generates a missing table error since the test actually runs now that WP_INSTALLING
is not available.
Overall, the results are good.
- Before patching, all tests passed with 14 skipped.
- After patching, but without resetting the
$wp_config
global to clearWP_INSTALLING
, 5 tests failed and 9 skipped. - After resetting the
$wp_config
global, all tests passed with 9 skipped.
This patch/discussion could also belong on #22251. Outside of a specific solution for WP_INSTALLING
, there are other things to consider—is this a good approach, does this belong in $wp
rather than $wp_config
, new function naming, etc...
#7
@
10 years ago
This patch/discussion could also belong on #22251. Outside of a specific solution for WP_INSTALLING, there are other things to consider—is this a good approach, does this belong in $wp rather than $wp_config, new function naming, etc...
I think we should really invest some time on #22251 and come up with a proper generic approach that isn't unit-test specific, 31130.diff certainly proves it's usefulness though.
This ticket was mentioned in Slack in #core by boone. View the logs.
10 years ago
This ticket was mentioned in Slack in #core by boone. View the logs.
9 years ago
This ticket was mentioned in Slack in #core by boone. View the logs.
9 years ago
#18
@
9 years ago
- Milestone changed from Future Release to 4.4
This is driving me bonkers.
Thinking about jeremyfelt's suggestions: We who are familiar with the codebase think of the various constants as being related to each other, by virtue of being constants. But to a newcomer, they have nothing to do with each other. So wrapping them in a wp_defined()
function doesn't make a lot of sense.
For the purposes of this ticket, I'd like to suggest a more focused wp_installing()
function. See 31130.2.diff. It works just like force_ssl_admin()
and its ilk: store the current setting in a static variable; wp_installing()
with no args will return the setting; wp_installing( $bool )
will set the value to $bool
and return the previous value. The one fancy bit is that we must continue to support the WP_INSTALLING
constant, since WP defines it in various places before the bootstrap (and thus before wp_installing()
is loaded). So, wp_installing()
will default to true
if defined( 'WP_INSTALLING' ) && WP_INSTALLING
.
Then, in WP_UnitTest_Factory_For_Blog
, call wp_installing( false )
just after creating the blog. This solves the problem raised in the current ticket.
Again, I'm not opposed to a more general approach to the use of constants, but WP_INSTALLING
is more of an internal tool which is a constant by technical necessity, than it is a "config" setting. A standalone solution seems prudent.
#20
@
9 years ago
Replying to boonebgorges:
Again, I'm not opposed to a more general approach to the use of constants, but
WP_INSTALLING
is more of an internal tool which is a constant by technical necessity, than it is a "config" setting. A standalone solution seems prudent.
Agree completely.
31130.3.diff is a refresh of 31330.2.diff. Some recent churn confused things a bit. I also had to add DB error suppression in test_current_user_can_for_blog()
for the one check against a non-existent site. I'm not entirely sure why this was causing DB error output after patch and not before, but that's one of the reasons we're in this ticket... :)
With this patch:
- All standard, multisite, and ajax tests pass locally.
- I was able to install WordPress from scratch.
- I was able to create a network.
- I was able to add a new site to the network.
I like it.
#22
@
9 years ago
Thanks, jeremyfelt. Let's see what breaks after [34828].
I'm thinking that a make/core post is probably appropriate for this change. I just spent some time looking through the plugin repo to see what people were doing with WP_INSTALLING
. Most of them fall into one of a few camps: (a) those that check the constant to make sure we're not literally installing WordPress, (b) those that define the constant because they're doing things like cloning a site, (c) those that define the constant because they're bootstrapping WordPress again (?), and (d) caching plugins that point wp_cache_get()
to delete()
rather than get()
when WP_INSTALLING
. From what I can see, those in camp (a) will be unaffected in any meaningful way, and those who are doing (c) have already voided their warranty. (b) and (d) are a little less clear to me. For the vast majority of cases (ie, during a normal installation/upgrade), they won't be affected, since WP_INSTALLING
is defined as part of the bootstrap. The question is whether not having the constant available during site creation will do anything funny with cache implementations. I don't *think* it will, since the cache for a newly created site will be empty anyway, but there could turn out to be cache invalidation problems for global cache groups. Anyone have thoughts about this?
#23
@
9 years ago
I'm seeing a fatal in load.php after [34828] if I have a .maintenance
file in my wp root. This is because functions.php hasn't loaded yet when wp_maintenance
is called, and PHP dies when wp_installing
is undefined.
Not certain what to do. Patch incoming that reverts this line change so no more fatals, yea! maybe better would be to define the function where wp_maintenance
would have access to it, perhaps in load.php itself?
#24
@
9 years ago
In 31130.4.diff:
- Use Global instead of
wp_installing
function in load.php as functions.php hasn't loaded yet and wp_installing is undefined
#25
@
9 years ago
I think I like this better as it doesn't undo this ticket :)
In 31130.5.diff:
- Moves new
wp_installing
function to load.php, ensuring its available for use there
Fixes a PHP fatal when .maintenance file present.
#26
follow-up:
↓ 28
@
9 years ago
Moves new wp_installing function to load.php, ensuring its available for use there
Ding ding ding! We have a winner. Seems appropriate that it'd be in the same place as wp_maintenance()
anyway.
#28
in reply to:
↑ 26
@
9 years ago
Replying to boonebgorges:
Ding ding ding! We have a winner. Seems appropriate that it'd be in the same place as
wp_maintenance()
anyway.
:)
#29
@
9 years ago
- Resolution set to fixed
- Status changed from assigned to closed
The sky hasn't fallen, so let's close.
I think some flavor of option 2 is the sane way forward. I did some exploration of this with
DOMAIN_CURRENT_SITE
andPATH_CURRENT_SITE
during the 4.0 cycle in 27884.diff, but backed off quite a bit. There are a handful of constants that would be nice to flip on and off or back and forth without having to fire up an entirely new process.WP_INSTALLING
is a pretty brutal one, so we'll need to take care.Option 3 would be the next best bet if it worked. Trying to get the multisite tests to actually run in a separate process was not an enjoyable time as the separate processes would use the default config and the multisite tables would not be available. I'm sure there is a way to do this, I just couldn't find it.
Option 4 would work, but would always be a source of possible error when committing new tests.
Related #27884, #30256