Problem/Motivation
Deprecate the functions: drupal_valid_test_ua() and drupal_generate_test_ua(). As we want to kill all includes.
Proposed resolution
Deprecate the functions: drupal_valid_test_ua() and drupal_generate_test_ua(). Move the functionality to the class Drupal\Core\Test\UserAgent.
Remaining tasks
TBD
User interface changes
None
API changes
None
Data model changes
None
Release notes snippet
TBD
| Comment | File | Size | Author |
|---|---|---|---|
| #160 | reroll_diff_153-160.txt | 20.99 KB | adityasingh |
| #160 | 3038513-160.patch | 43.23 KB | adityasingh |
| #153 | 3038513-153-do-not-commit.patch | 44.99 KB | andypost |
| #153 | interdiff.txt | 1.8 KB | andypost |
| #147 | 3038513-147.patch | 45.56 KB | andypost |
Issue fork drupal-3038513
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
Comment #2
jepster_First patch version.
Comment #3
jepster_Replaced another usage of drupal_valid_test_ua() for being able to generate test groups.
Comment #4
jepster_Merged in current 8.7.x branch.
Comment #5
jepster_Included the bootstrap file again, which has been previously removed for testing purpose.
Comment #6
jepster_Comment #7
jepster_Comment #8
jepster_Added deprecation message.
Comment #9
jepster_Replaced remaining usages of drupal_valid_test_ua(). Except in the files, where Drupal is not fully booted.
Comment #11
jepster_Comment #12
volegerAdded missed replacements in the code and comments.
Added trigger error.
Comment #13
volegerForgot to kill includes)
Comment #14
volegerMissed dependency, fixed CS.
Comment #15
volegerComment #16
jepster_I have updated the Drupal version in the deprecation message and changed the visibility of class method to private. Protected was unnecessary there. Should be protected, if it actually matters.
Comment #17
berdirLooks like this breaks basically every web test and as a result of that testbot isn't even capable of showing the results, try running some of those locally to debug what the problem is.
Comment #18
berdirSee https://dispatcher.drupalci.org/job/drupal_patches/88173/artifact/jenkin... for example, somehow the page seems to be basically dead in the test and it is unable to log in.
Comment #19
jepster_Edited this comment, because Drupal bootstrap actually is required. Wondering how the DRUPAL_ROOT constant could have anything to do with the changes from this branch.
Comment #20
jepster_@Berdir: What is the navigation path to that output? I'm curious which output other patches get within the Jenkins pipeline.
Comment #21
berdirYou can't just visit a path, it simply doesn't work yet as it should. Had a look, the problem is that we need to update drupal_generate_test_ua() at the same time, these two functions are a tandem and they need to be in the same file, as they rely on the filectime() and fileinode() of __FILE__ and currently that doesn't match anymore.
Comment #22
volegerAdded replacements for drupal_generate_test_ua()
Comment #23
berdirI've been wondering about a) moving this to a dedicated utility class. and b) expanding "ua" to UserAgent, possibly TestUserAgent::validate()/generate() or so.
Also would be nice if we could switch to a request object instead of using globals, not sure if that's always possible. Hope so :) Maybe it can remain static but we pass in the request object?
But first lets get some real test results, so far results look promising, just a few fails, mostly passes on the browser tests.
Comment #25
mile23Yay just found this issue. :-)
Since, generally, our test layer shouldn't be available at runtime, we should have a version of
CoreServiceProviderthat is added by the kernel if$env == 'test'. So if you saynew DrupalKernel('test')you get a kernel that usesCoreServiceProviderHotRoddedForTestsinstead ofCoreServiceProvider.CoreServiceProviderHotRoddedForTestswould then swap outsession_configurationservice withSessionConfigurationForTesting.SessionConfigurationForTestingthen knows how to deal with test UA and so forth.I'm not sure how far out of scope that would be here, but if there's any time to do it, it's when we're trying to get rid of include files.
Again, since these really shouldn't be reachable during non-test runtime, let's not put these on
DrupalKernel, because they don't really need what the kernel encapsulates.So these should be on a helper class in
Drupal\Core\Test, with a @todo to move it toDrupal\Testin #2750461: Remove Simpletest UI because we don't want to maintain a graphical test runner and/or the refactoring mentioned above.So +1 on #23.
Comment #26
berdir> I'm not sure how far out of scope that would be here
That's definitely out of scope IMHO, the whole point of these methods is to actually figure out if it is a test run or not, they can't be depending on that.
That, I also proposed in my comment above to move them into a utility and not DrupalKernel, with better names.
Comment #27
volegerAddressed #23 and #25
Comment #28
volegerLet's see can we kill more includes now.
Comment #30
berdirLooks like all update tests are broken?
Comment #31
volegerLet's return all removed includes and see will this help.
Comment #32
jepster_@voleger: Looks like the correct fix. Since the recent fails have reported issues with the DRUPAL_ROOT constant. That's what has been corrected.
Thanks for your good work!
Comment #33
volegerNo, test report shows failed tests.
https://dispatcher.drupalci.org/job/drupal_patches/90358/testReport/
Comment #34
volegerNo idea what is the reason for failed Functional and FunctionalJavascript tests.
Comment #35
berdirYeah, "PHP 7.1 & MySQL 5.7 Build Successful" actually means *very unsuccessful* unless a project has no tests.
I'm not convinced this makes sense. This is something that we need to run at regular runtime as I wrote above, it is *not* a test-only thing, we don't want to register \Drupal\Tests at runtime.
This stuff is called before we have a container, you can't use \Drupal:: here.
I went with $_SERVER['REQUEST_TIME'] for now, that then passes functional tests again.
Something we could try is require that a request object is passed to this and then read all the server/cookie stuff from that, that should always exist. But lets get it green first with minimal changes.
Quickstart is only half-passing with this, somehow error handling/display is still broken.
Comment #36
berdirComment #38
volegermissed replacement,
reverted include file removal from update.php
tried to include bootstrap inc in the UserAgent methods
Comment #39
volegerReroll for core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php
Comment #40
volegerLooks everything replaced correctly. Let's try to decrease includes.
Comment #41
volegerLooks like other bootstrap includes can't be replaced now, because of used DRUPAL_ROOT and REQUEST_TIME constants.
This one should be ready for review.
Comment #42
volegerNope, looks like #40 should be the patch for review.
Comment #43
berdir#40 looks nice to me, I think what we need is a @group legacy test that tests the deprecation and that the old functions still work?
Comment #45
volegerFilled CR https://www.drupal.org/node/3044173
Added initial legacy test
Comment #46
jepster_The test is failing, because no sites/simpletest/ENVIRONMENT_ID folder is being created. Can it be, that the test is fired too early?
Comment #47
volegerMaybe defining DRUPAL_TEST_IN_CHILD_SITE will help with this test?
Comment #48
jepster_Unfortunately I am getting still the same error with that setting.
Comment #49
mile23If you revert everything from this patch except this test, and then run it without including bootstrap.inc, it tells you that
DRUPAL_TEST_IN_CHILD_SITEis undefined.That's because kernel tests don't make requests, so that whole infrastructure shouldn't be expected to exist. There's no such thing as a kernel test that calls
drupal_generate_test_ua().Turn this test into a functional test, since that's what' we're testing.
The fact that this is ambiguous and brittle? ::points at #25.1:: There's a reason the symfony kernel has an
$envvariable on construction. I started on a patch to do this, but so many other things.Comment #50
volegerConverted test. Thanks @Mile23 for the explanation.
Comment #51
volegerComment #52
berdirThat kind of wrapping is almost always done for unit tests. I guess that's still necessary because it is a static call that does all kinds of things that would likely not work in a unit test.
However, changing from protected to private is kind of a break as well. *If* we do that, we could possibly also rename the method to reflect the new name. If we don't do that, we also shouldn't change it to private.
Either this should use the full name, then we don't need the @see or we can revert the rewrapping because UserAgent::validate() is actually shorter than the function name and we can keep the text as it was before.
this is correct as it uses the full namespace, I think prefer that above too and then drop the @see.
this reference wasn't updated yet for the new class name, I'd also suggest to use the namespace and drop the @see.
Comment #53
volegerRerolled.
Addressed #52
FIxed CS issues of deprecation messages.
Comment #54
berdirWe usually don't do Class X, that's literally repeating what it says below. We should just describe what it does: "Generates and validates test user agents"?
Also, as mentioned in #35, I still think this @todo makes no sense. This has nothing to do with the graphical UI runner, this is about identifying if it is a test request, it's not possible to only load this when running a test as we need it to decide that.
Maybe this is where the @todo above is from? It's not limited to "Simpletest", we should replace this with "test request" or "browser test request" or something like that.
And also as mentioned in #35, I would suggest we pass in the Request object here, so we can replace all those super-globals with $request.
also interesting. Are we far enough in the bootstrap process to do a throw an access denied exception?
This will conflict with #3053956: Deprecate \Drupal\Component\Utility\Crypt::hashEquals() in favour of PHP's builtin hash_equals(), we'll need to update it to use hash_equals(), if it happens to be updated before that gets committed, we could already update now, will be easier to reroll then.
same here.
I guess simple is also a reference to simpletest, but not sure if there are any implications to changing how the hash is built exactly.
Comment #55
omarlopesinoAdding new patch fixing 1 to 5.
I am not sure how, but in 6, adding 'simpletest' is necessary. It seems related to the table prefix created by simpletest, maybe someone can clarify?
Comment #56
omarlopesinoReroll.
Comment #57
omarlopesinoComment #58
mile23Re: #54.1:
I'm pretty sure this is about not wanting to be able to autoload this class if there's no Simpletest UI. The linked issue is #2750461: Remove Simpletest UI because we don't want to maintain a graphical test runner
It'd be best if
UserAgentweren't autoloadable out of a testing context. But since we need it for simpletest UI right now, and since it's a non-trivial refactor, it would have to happen when/if we remove that testing form. For instance, see this frominstall_begin_request()that shows us why we shouldn't be able to autoload it, and also why it's not easy to change:#54.6: If we want to have an initiative to remove the word 'simpletest' from core, then let's get on that. :-)
My main review:
So a couple things here...
1) We don't have any isolated tests of the
UserAgentclass. We just need a basic sanity check type test. It will have to be a kernel test so we have some of the dependencies such as a database.2) If we update the signature of
validate()to bevalidate($new_prefix = NULL, Symfony\Component\HttpFoundation\Request $request = NULL)then we can test the validation.Comment #59
berdir> I'm pretty sure this is about not wanting to be able to autoload this class if there's no Simpletest UI. The linked issue is #2750461: Remove Simpletest UI because we don't want to maintain a graphical test runner
Yes, but that's my point, this code has nothing to do with the simpletest UI? It's to detect and validate that a request belongs to a certain test environment. It has to be loaded and used *before* we know that we are executing a test, which means it is impossible to have it in a test-only namespace or anything like that. This @todo is bogus, which is why I suggested to remove it :)
> #54.6: If we want to have an initiative to remove the word 'simpletest' from core, then let's get on that. :-)
The above is why I suggested to change this, having simpletest in there leads to those wrong conclusions that it as anything to do with simpletest.module, which is no longer true, not for phpunit tests. But I'm happy to leave that to another issue.
+1 on at least optionally allowing to pass in $request and I think we should make it required. The main check for this is very much in the critical path and is before we have a container *but* we have a request object.
Comment #60
mile23Correct. It doesn't have anything directly to do with simpletest UI, but the UI allows you to run tests outside of a test-only context.
That's why
drupal_valid_test_ua()is in bootstrap.inc, and we keep calling it in order to check whether or not we're in a test context. Core has a lot of places where it tries to figure out whether it's running under test or not, in order to work around simpletest.We shouldn't be doing that, though. We should have an assumption that we're not running under tests. Over time we can remove complexity from core and from the testing system by decoupling them.
That's why we should eventually move
UserAgenttoDrupal\Tests\so that it can't be autoloaded unless we're running tests. There's a test isolation reason for this, and there's also a security reason for this, see #58.That's the explanation of my understanding of that @todo. It might make more sense to link to #2866082: [Plan] Roadmap for Simpletest instead. Or it might make more sense to just put
UserAgentunderDrupal\Tests\now, if it's not too disruptive to the patch as it is.Comment #61
berdirBut then how do you propose that we'd handle this instead?
We could change how in-test-requests are identified, but we will always need something like this to allow running tests without special hardcoded environments, being able to run tests in parallel and so on. It has nothing to do with simpletest, UI test runner or not. Not anymore.
I still believe that even if we would change this in the future, it has nothing to do with the removal of simpletest.module and there is no need for a @todo pointing to such an issue.
Comment #62
mile23The thing we're discussing *IS* the special hardcoded environment, and I'm proposing that we allow running tests without it. :-)
But, whatever. Just leave the todo out and then we'll eventually move it anyway.
So that leaves #58.1 and #58.2, and @Berdir at least agrees with 2.
Comment #63
kim.pepperComment #64
volegerAddressed 58.2
Comment #65
volegerThe first iteration of moving to Drupal\Tests namespace
Comment #66
volegerGet rid of \Drupal\Core\Test\UserAgent in favor of \Drupal\Tests\UserAgent
Comment #67
volegerAddressed #58.1 and #62
Comment #68
volegerAddressed #58.1 over the patch from #64
Comment #70
volegerFix constant definition check.
Comment #72
volegerRemoved
::generatemethod coverage. Not sure how to test it properly.Comment #73
berdirA bit confused about the last few patches, is this still work in progress?
As I wrote in the last chapter in #59, I think the request argument should be required and the caller should be responsible to provide it.
Comment #74
volegerI tried to move the UserAgent class into Drupal\Tests. Looks like there needs more work to do it. So the last patch reverts that movement. Let's left this for follow-up issue.
Here the patch addressing #73
Comment #76
berdirno need to change the areguments to the old function, just always use the fallback there.
Will need to review the other parts when I can look through the code, that looks much more complicated than what I was hoping for :)
Comment #77
volegerAddressed #76
Also rerolled after recent changes related to Drupal Scaffold.
Comment #78
volegerChange status
Comment #80
andypostHere's few fixes
- old implementation always using globals, so request should be taken not from
\Drupal::request()- fixed
REQUEST_TIMEshould be taken from request too- few docs improvements
Failed file upload tests indicates that more work needed to prevent using files when request is created from globals
Comment #82
volegerReroll (simpletest.install file was updated)
Missed argument pass in one of the
::validatemethod call.Also minor changes of the call replacements.
Comment #84
andypostLooks all remaining failures are consequence of file upload handling by created request object
Files are processed from globals twice that's why second created request object throws exception - can't move already moved file
To solve it clearly the request object should be by-passed (not created each time) so it makes me think about other way to detect test ID
Comment #85
berdirI'm not sure what you mean with different way? The test ID *is* in the request data. The only decision we can make is whether or not we use the request object. The problem with not adding the argument now is that we can then never refactor it later on.
To make this work, we need to avoid Request::createFromGlobals() at least during regular requests, not just to make it work but also for performance reasons. The main one is \Drupal\Core\DrupalKernel::bootEnvironment(), and for the calls to that that matter, the request is available in the caller, so I started to add an argument there, we'll have to figure out BC for that.
I've also added some checks to ExtensionDiscovery so that we can use the request when available. Got one test working with that, lets see about the others.
Comment #87
andypostRe-roll still getting issue with
Comment #89
volegerRerolled against 9.0.x
Comment #90
volegerAlso had fixed the last issue with the patch. So the patch is finally ready for the review
Comment #91
volegerComment #94
volegerAdded missed $defaultTheme in the legacy test.
Comment #95
volegerJust reroll against 9.1.x
Ready for the review.
Comment #97
volegerForgot to add update.php into the diff result.
Comment #98
meenakshig commentedComment #99
voleger#98 looks like a crosspost
#97 is the patch for the review. I can't find the patch in Files below, so just hiding unrelated files from IS.
Comment #100
volegerReupload #97 patch. Unable set testing for the #97 patch.
Comment #102
volegerUnrelated test fail
Comment #104
daffie commentedPatch looks good. Some remarks:
This line can be changed to:
[, $prefix, $time, $salt, $hmac] = $matches;What does this line? And can it be removed?
Comment #105
mohrerao commentedignore this patch please
Comment #106
mohrerao commentedComment #108
daffie commentedThe points from comment #104.1 and #104.3 are still open.
Comment #109
mohrerao commentedComment #110
mohrerao commentedFixed #104.1 and #104.3 .
Comment #111
mohrerao commentedOops, patch missed adding UserAgent.php file.
Fixed #104.1 and #104.3 .
Comment #113
volegerNeed to fix the last test fail. core/tests/Drupal/Tests/Core/Database/DatabaseTest.php setUp() method mocks container methods. So the argument 'request_stack' in 'has' method not expected.
Comment #114
mohrerao commentedWorking on the failed test.
Comment #115
mohrerao commentedRemoved mock container creation as this is now not needed.
Comment #116
mohrerao commentedComment #117
volegerThe last test fail fixed. +1 for rtbc
Comment #118
daffie commentedPatch looks good, needs some minor improvements:
Missing the added parameter in the docblock.
Can we put the whole request stuff on a separate line. For an improvement in readability.
Why add link to an unrelated issue?
Can we change "UA" to "user agent".
Outlining to the 80 character maximum can be improved.
Comment #119
deepak goyal commentedComment #120
naresh_bavaskar@daffie Addressed the #118
Please review
Comment #121
naresh_bavaskarSorry @Deepak Goyal, I did not check that is assigned to you.
Comment #122
deepak goyal commentedI have also created patch for the same please review.
Comment #123
deepak goyal commentedComment #124
daffie commentedReview of the patch from comment #120.
The change that I wanted was:
This change is not necessary. Out of scope for this issue.
The comment goes over the 80 character limit.
Comment #125
deepak goyal commentedComment #126
deepak goyal commentedHi @daffie
Updated patch please review.
Comment #127
deepak goyal commentedComment #129
hardik_patel_12 commentedSolving test case , kindly review a new patch.
Comment #131
longwave@Hardik_Patel_12: thanks for the patches here and elsewhere, but your interdiffs seem to be diffs-of-diffs which are quite hard to read - please see https://www.drupal.org/documentation/git/interdiff for a number of ways of creating a more useful interdiff which lets reviewers see the changes between patches more easily.
Comment #132
longwaveFixed the failing test in #126.
Comment #133
daffie commentedOnly #124.3 is still open.
Comment #134
daffie commentedSorry, wrong status. Needs to be "needs work", because #124.3 is still open.
Comment #135
raunak.singh commentedI am working on this as per #133 comment
Comment #136
raunak.singh commentedHi @daffie,
I have updated the patch and fix #124.3 issue. Please take a look.
Comment #137
daffie commented@Raunak.singh: I think your patch is missing some parts.
Comment #138
raunak.singh commentedYes @daffie
I am Working on it.
Comment #139
raunak.singh commentedDue to internet issue patch file not added
Comment #140
raunak.singh commentedResolve previous patch issue please take a look.
Comment #141
raunak.singh commentedComment #142
jungleclassyis not encouraged to use. even this is a test testing legacy code, but newly added. Changed tostark.Comment #143
daffie commentedAll my remarks are addressed.
All code changes look good to me.
All usages of drupal_valid_test_ua() and drupal_generate_test_ua() have been replaced.
Both functions are deprecated and have deprecation message testing.
Updated the CR and IS.
For me it is RTBC.
Comment #144
andypostBit more clean-up, while review I think we should split it more
- split validate() into set and get behaviors - validation and doing a lot with request are different functions
- while we changing update.php probably makes sense to move gc-* to
\Drupal\Core\DrupalKernel::bootEnvironment()because this place should be called only once and we can use request objectI think it should use
\Drupal::hasRequest()insteadas we change signature, better to remove
Comment #145
andypostFurther clean-up - generate method works independently from request object, except a case when we need to test it.
Then the
DRUPAL_TEST_IN_CHILD_SITEdefined and verify should just make sure that setup already donePatch also removes lots of new usages of the request
Comment #146
andypostExtension discovery already using global request to find site path, so validation should use the same object
Comment #147
andypostNo reason to make kernel environment request dependent (only globals should be used here)
Patch removes this dependency but maybe we can move this detection to
\Drupal\Core\DrupalKernel::initializeSettings()where request appears and site settings (testing ones are needs a cookie from request)This method already protected and "testing knowledge" could be hidden there
Comment #150
andypostTesting revert of interdiff from #146 (not clear why extension scan require
\Drupal::request()for this tests)Comment #151
alexpottOn the face of it this functions being functions is not really wrong. Moving them to a new class class only means more code to autoload on every request. This issue is alternatively fixed by #3151118: Include bootstrap.inc using composer with way less change.
This change is not necessary.
Comment #152
andypostNot all of this code is needed every request.
Generate and "resurrect from generated" are testing time "injections", which, in theory, should be bypassed for production, at least this ability nice to have.
Ideally it could be integrated into kernel (main one) and could use integration into update kernel (for GC instead of update.php)
Comment #153
andypostReroll after SA ceee045fa5f907f0e28d504f4a3e355a855c4e98
Also fixed #151.2 and added changes from SA to new class
Comment #154
hardik_patel_12 commentedComment #156
alexpott@andypost we're going to be loading the UserAgent class on every request I still think #3151118: Include bootstrap.inc using composer is the way to go and this change pushes unnecessary change and deprecations on contributed and custom code.
Moving this code away from where DRUPAL_ROOT is define doesn't improve the architecture. I'd argue it makes things a bit worse because at least DRUPAL_ROOT is defined in the same location as the methods currently are.
Comment #157
andypost@alexpott I'm totally agree with cost of autoload (which I see in top 10 of the most of profilers last years)
Looks we need new issue policy/no-patch about further clean-up
On one hand loading of boostrap.php is cheaper and will be, even with PHP preload
OTOH this file still needs cleaning
Comment #159
daffie commentedI am sure that the patch needs a reroll now that #3151118: Include bootstrap.inc using composer has landed.
Comment #160
adityasingh commentedReroll the patch for 9.2
Comment #162
daffie commentedThese 2 lines are old code. We are now using the method
$this->expectDeprecation().Comment #163
volegerRebased MR-12
Updated versions in the deprecation messages.
Comment #164
alexpottAs stated in #151 I don't think we should be moving
drupal_valid_test_ua()is worth it. Now that bootstrap.inc is autoloaded there's no compelling reason to make that change.drupal_generate_test_ua()should move to somewhere in the test system - maybe as a static method in\Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware.Comment #165
volegerReverted deprecation of drupal_valid_test_ua()
Comment #166
volegerUpdated CR [#3044173]
Comment #167
daffie commentedThe testbot is not happy with the latest MR. See https://dispatcher.drupalci.org/job/drupal_patches/71311/
Comment #171
alexpottGiven the security implications and how drupal_valid_test_ua() and drupal_generate_test_ua() are related I'd prefer to leave these two functions inside bootstrap.inc and next to each other. I think the supposed benefits of having one less method in bootstrap.inc are not as great as the benefit of having these methods next to each other.
I'm going to close this issue as works as designed.