Problem/Motivation

Kernel tests have a datetime.time service but that does not have the request_stack as is the case during regular operations.

This makes it impossible to simulate different request times by modifying the (fake) current request in the request stack.

Steps to reproduce

Run something like

$requestStack = $this->container->get('request_stack');
$time = $this->container->get('datetime.time');

$request = $requestStack->getCurrentRequest();

$request->server->set('REQUEST_TIME', 123123123);
$this->assertEquals(123123123, $time->getRequestTime());

$request->server->set('REQUEST_TIME', 456456456);
$this->assertEquals(456456456, $time->getRequestTime());

in a kernel test and notice that the test fails.

Proposed resolution

Add the request_stack as an argument to the datetime.time service definition in kernel tests.

Remaining tasks

User interface changes

-

Introduced terminology

-

API changes

-

Data model changes

-

Release notes snippet

Issue fork drupal-3578597

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

tstoeckler created an issue. See original summary.

tstoeckler’s picture

Did some archeology and this was actually removed in https://git.drupalcode.org/project/drupal/-/commit/8a034cda9b0508913e8ee... during development in #3113971: Replace REQUEST_TIME in services but I can't find any actual discussion.

Note that if people are turned off by the modifying of the request object in the example code in the issue summary, note that we currently do not have a generic, mutable version of the time service that could be used in tests, so this seems to be the most straightforward way to achieve that as far as I can tell.

tstoeckler’s picture

Issue summary: View changes

tstoeckler’s picture

Status: Active » Needs review

Added a quick MR. Verified that this fixed a test as described in the issue summary. Didn't add an explicit test as that seems somewhat esoteric to me, but could be easily added in KernelTestBaseTest::testRegister() if deemed appropriate.

smustgrave’s picture

Status: Needs review » Needs work

Seems to have broke some kernel tests?

tstoeckler’s picture

Yeah, haven't looked into it yet. Will try to fix them and then we can evaluate if this is actually a problematic change or if the tests that are now failing are just problematic.

tstoeckler’s picture

So I figured out what was going wrong in ResourceObjectNormalizerCacherTest. The incrementing of the request time was not done correctly as it is inherently additive, i.e. what the code did was:

$requestTime = getRequestTime();
$requestTime += 500;
$requestTime += 800; // This is now 1300 more than originally!
$requestTime += 801; // This is now 2101 more than originally!

But the assertions and code comments were doing:

// Test with initial request time
// Test with initial request time + 500
// Test with initial request time + 800
// Test with initial request time + 801

The fact that the test passed nevertheless was due to the very bug being fixed here. The "current time" in the memory backend never actually got updated so the MemoryBackend::prepareItem() never actually marked the items as invalid. And then the supposed "+800" test (which is actually a "+1300" test) accidentally tests the same code path that the supposed "+801 test" test should be testing. That one doesn't really make sense, though, anyway. When a cache item is expired it should not be returned, so the max age should not continuously be 0, instead it should be back to 800 because a new cache item was generated.

tstoeckler’s picture

Status: Needs work » Needs review

I think that the fact that the only test that failed was actually failing precisely due to this bug (and some flawed assumptions) is a pretty good case that this is in fact a valid bug fix.

smustgrave’s picture

but the new line adding the request_stack is removed?

tstoeckler’s picture

Oh right, forgot to point that out. I realized that whatever happens in KernelTestBase::register() only acts as overrides of stuff in core.services.yml and with the added argument the definitions are the same so we might as well drop the entire override.

As pointed out in the issue summary, the Git history is not very informative about why in particular this was added in the first place, so since tests pass without it, I think the most reasonable way forward is to just delete it.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Bug Smash Initiative

Based on the explanation believe the change makes sense, pipeline is green

longwave’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Fixed

Yep nice find, there is no need to override this here and it's found a genuine bug in a test.

Committed and pushed d2a88302e6b to main and e531888084f to 11.x. Thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • longwave committed e5318880 on 11.x
    test: #3578597 datetime.time service is missing the request stack in...

  • longwave committed d2a88302 on main
    test: #3578597 datetime.time service is missing the request stack in...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.