I have been trying to write a test to prevent regressions of #293612: user_authenticate() should work when $_COOKIE is empty. However, I've not been able to using the existing simpletest API.
The reason for this is that to reproduce the bug, cookies need to be cleared right before the POSTing of username and password, and at present, drupalPost() calls drupalGet(), which sets the CURLOPT_COOKIEJAR option of the curl handle. Even if this drupalGet() were not called, the curlExec() calls curlConnect() which sets the CURLOPT_COOKIEJAR variable.
To fix this within the framework of the API, I've introduced a $clear_cookies option to drupalPost(), curlExec() and curlConnect(). If $clear_cookies is FALSE (the default) everything works as normal.
If $clear_cookies is TRUE, the behaviour of the curlExec() called from drupalPost() is altered: curlExec() calls curlConnect() with this option, and curlConnect() then calls curlClose() to get rid of any existing cookies, and does not set CURLOPT_COOKIEJAR. curlConnect() calls curlExec() without the $clear_cookies argument, and on *this* invocation, curlExec() does not set the COOKIEJAR. However, once this curlConnect() has returned, curlExec() does set the CURLOPT_COOKIEJAR just before it invokes curl_exec().
This does seem a bit messy, but it was the only way I could see of fixing things without writing large chunks of new code. I am new to php curl, so perhaps there is a neater way of doing things. However, I couldn't see any way of unseting options, apart from curl_close().
The patch also includes an example of the use of the extra argument, in user.test. This test will throw up a failure on an unpatched drupal tree, but will pass if the patch at #293612: user_authenticate() should work when $_COOKIE is empty is applied. The existing tests in user.test all pass.
I hope this is the right queue to submit things too. Please let me know if the two parts of the patch should be separated -- I did consider doing this, but on balance it seemed better to have it all together.
| Comment | File | Size | Author |
|---|---|---|---|
| #20 | simpletest-302075-20.patch | 6.29 KB | egfrith |
| #17 | 20081016_drupalpost_cookie_2.patch | 6.18 KB | egfrith |
| #16 | 20081016_drupalpost_cookie.patch | 6.13 KB | egfrith |
| #12 | simpletest-clearcookies_1.patch | 6.58 KB | egfrith |
| #4 | simpletest-clearcookies.patch | 4.57 KB | boombatower |
Comments
Comment #1
dries commentedMight be better to change:
$options = array(), $clear_cookies = FALSEto$url_optionsand more generic$curl_options?Comment #2
egfrith commentedHmm.... I see the point, but the I'm wondering if putting $clear_cookies into $curl_options would cause confusion.
The reason for this is that at present, whenever $curl_options is mentioned in the code, it means "an array of options for curl_setopt_array()".
The $clear_cookies flag does not correspond to this usage of $curl_options. Rather, it tells curlExec() only to set CURLOPT_COOKIEJAR just before the final curl_exec().
If a $curl_options argument were provided to drupalPost(), would it be merged with the options already sent to curlExec() in drupalPost()?
Comment #3
chx commentedThe original patch is good and we should not add non CURLOPT_ thing to curl_options indeed. Logging in with an empty cookies array is a problem indeed.
Comment #4
boombatower commentedI noticed this patch no longer applied.
Re-rolled, talking with chx about documentation and while we were talking he suggested changing the variable to $curl_restart as that is more correct.
User.test no longer passes with this applied.
Comment #5
boombatower commentedAlso shouldn't this change
drupalLogin() ?? which contains.
Comment #6
egfrith commentedI agree, $curl_restart is a better name for the option than $clear_cookies.
I don't think the default behaviour of drupalLogin() should change, since this simulates the browser behaviour that occurs most of the time. However, it might make sense to have a $curl_restart option to drupalLogin(), which would then get passed to the drupalPost() in drupalLogin().
This would allow the new code in user.test to be shortened to something like:
This thought did cross my mind when writing the original patch, but I dismissed it because as far as I can see, logging in without cookies only needs to be tested once. However, the number of lines of code with the argument to drupalLogin() (plus the doc string) will probably be less than or equal to the current number of lines of code, and perhaps there are some use cases which are as yet unclear... On balance, I would be minded to give drupalLogin() the new argument, but it's only a marginal preference.
Let me know if you'd like me to roll this into a patch.
Comment #7
boombatower commentedSeems like a good idea, never know if someone may want it later and seems cleaner than making the exception in the user.test.
Comment #8
egfrith commentedHmm... I've looked at user.test, and noticed that the original code at line 87 (on which I modelled the new code) is:
So the drupalLogin() function isn't used there. Before changing this, I'd like to know that there isn't a good reason that it's this way. And as I'd rather have both login snippets consistent, I'll hold off patching for now.
Comment #9
boombatower commentedThe test is old and most likely hasn't been updated. As I helped add things like the login method.
Comment #10
egfrith commentedOK, if it's felt that updating user.test along those lines doesn't count as scope creep, I'll try to update the patch later on today.
Comment #11
boombatower commentedYour implementing the new feature your adding. I don't see that as scope creep.
Comment #12
egfrith commentedHere's the latest version of the patch. Changes from the previous version
* drupalLogin() now has a $curl_restart parameter, documented in the same way as the other functions with the parameter
* user.test now uses drupalLogin() for the test of logging in with the new password and the test of logging in without cookies. This requires setting $user->pass_raw explicitly
I've tested hat the new test causes User.test to fail when it's applied.
Comment #13
boombatower commentedTest doesn't pass and there is a single line of extra white-space in user.test.
Comment #14
egfrith commentedJust to be clear, when you test the patch, does is cause a test to be failed when the patch at #293612: user_authenticate() should work when $_COOKIE is empty is applied? With this patch applied, the latest patch in this thread passed all its tests, as it should. The patch in this thread is designed to cause a failure in the current version of HEAD.
I've not access to my testing rig at the moment, so I can't tell which of the blank lines in the patch is the wrong one. Will try to look at that this evening.
Comment #15
boombatower commentedDue to no failing test policy this will need to be postponed until that patch makes it in. The spacing issue is no big deal. I would have re-rolled myself, but I thought this needed to be fixed in addition.
Comment #16
egfrith commentedThe issue that this test should prevent regressions to (#293612: user_authenticate() should work when $_COOKIE is empty) is now fixed, so I have rerolled the patch against HEAD and checked that all of the user tests pass.
Comment #17
egfrith commentedJust realised I hadn't rolled the patch correctly due to running cvs diff in a subdir. Corrected patch attached.
Comment #18
cwgordon7 commentedThe issue in question has been marked fixed.
Comment #20
egfrith commentedHere's a new version of the patch. Apart from reworking the code, I think I've addressed the concerns of comment #13, apart from possibly the white space in user.test. There is extra white space in user.test, but I think this matches the pattern of whitespace already in user.test.
Comment #22
grendzy commentedI tend to agree with #1 that more generic access to curl options would be beneficial. I'm also trying to find a way to access and manipulate cookies with cURL, see #457804: Enable simpletest to manipulate cookies.
Comment #23
boombatower commentedBelieve this is now supported, reopen for 8.x if not.
Comment #24
JeremyFrench commentedI can't see anything which directly corresponds to this here http://api.drupal.org/api/drupal/core--modules--simpletest--drupal_web_t... or in D7 so I don't believe that this issue is fixed. If there as a way to do this with all of the new options it doesn't seem to be documented.
Comment #25
sunPotentially related: #1671200: Simpletest broken: CURLOPT_COOKIEJAR cannot be NULL
Comment #32
dawehnerMink or pure guzzle HTTP calls both enable this usecase now.