Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[2.1] TestSessionListener is setting an id to the session #3741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
diegoholiveira opened this issue Mar 31, 2012 · 32 comments
Closed

[2.1] TestSessionListener is setting an id to the session #3741

diegoholiveira opened this issue Mar 31, 2012 · 32 comments
Milestone

Comments

@diegoholiveira
Copy link

I'm trying to run my tests with sf2.1 and i'm getting an exception weird:

Cannot set session ID after the session has started.
500 Internal Server Error - LogicException

This error occour only when I run my tests, on the browser it's fine.

So I decide to track the error, then i found this lines on the class Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListener

    $session = $this->container->get('session');
    $cookies = $event->getRequest()->cookies;
    if ($cookies->has($session->getName())) {
        $session->setId($cookies->get($session->getName()));
    } else {
        $session->setId('');
    }

After remove this lines, everything works fine.

I don't know if this is a bug with the code or if something missing on my configuration.

refs FriendsOfSymfony/FOSFacebookBundle#79

@diegoholiveira
Copy link
Author

@Drak: can you help-me with this issue?

@ghost
Copy link

ghost commented Apr 2, 2012

Can you show me the tests?

@diegoholiveira
Copy link
Author

https://gist.github.com/2279935

As you can see, it's a simple test, and phpunit configuration file it's the sf default. Note that i'm using the most recent version on the master branch.

Thanks

@ghost
Copy link

ghost commented Apr 2, 2012

Note to others, we are discussing and investigating together on this.

@ghost
Copy link

ghost commented Apr 6, 2012

What I do't quite understand is why the tests pass in FrameworkBundle/Tests/Functional as these also use sessions. I haven't been able to see what the difference is between the tests, except for the invokation of the client. Does anyone have some idea?

@benji07
Copy link
Contributor

benji07 commented Apr 10, 2012

any news ?

@yethee
Copy link
Contributor

yethee commented Apr 10, 2012

@Drak, here simple test which is not passed.

@jakzal
Copy link
Contributor

jakzal commented Apr 11, 2012

@yethee in your test you modify the session but your first request is made without a cookie which holds the session id (so the session cannot be restored). I'd say it should work if you save the session and send a proper cookie (but it doesn't).

Exception is thrown in MockArraySessionStorage::setId(). I'm not sure if it's a bug. For some (probably good) reason it's forbidden to re-set the session id.

If you made a request before altering the session it'd properly set the cookie and your test would pass.

public function testPredefinedSession()
{
    $client = $this->createClient(array('test_case' => 'Session', 'root_config' => 'config.yml'));
    $client->request('GET', '/session');

    $session = static::$kernel->getContainer()->get('session');
    $session->set('name', 'foo');
    $session->save();

    $crawler = $client->request('GET', '/session');
    $this->assertContains('Welcome back foo, nice to meet you.', $crawler->text());
}

Notice you also need to save the session before making a request.

Anyone else has thoughts on this?

ping @Drak

@ghost
Copy link

ghost commented Apr 13, 2012

@fabpot - I'm temporarily stumped on this, have you some idea? The tests work in FrameworkBundle/Tests/Functional, yet other people's tests don't work. I don't get it.

@ghost
Copy link

ghost commented Apr 13, 2012

From what I can see, the listener order is correct, ie the test listeners fire before the session is started by the other listener, at least, in code it looks ok.

@jakzal
Copy link
Contributor

jakzal commented Apr 13, 2012

@Drak look at the @yethee's test. He accesses the session before first request is made (and therefore it's already started).

@ghost
Copy link

ghost commented Apr 14, 2012

@jakzal - in @yethee's case yes, but the tests shown by @diegoholiveira don't appear to be down to user implementation. The problem is, removing the exceptions is OK, but they were added explicitly to trap this kind of thing, so clearly something deeper is going on.

@benji07
Copy link
Contributor

benji07 commented Apr 14, 2012

Without the exception the problem is the same. The session doesn't work with behat (i can't test a simple login page)

@ghost
Copy link

ghost commented Apr 14, 2012

@benji07 are you using FrameworkBundle or not, because FrameworkBundle has a listener which saves sessions (when in test mode).

@benji07
Copy link
Contributor

benji07 commented Apr 14, 2012

I use the standard edition on master branch, i add mink, and try to test the login page

@benji07
Copy link
Contributor

benji07 commented Apr 14, 2012

it's work with symfony session, not with zombie.js

EDIT: it's work with sahi too (maybe there are a but with zombie.js)

@jakzal
Copy link
Contributor

jakzal commented Apr 14, 2012

@Drak would be helpful if someone linked to/pasted @diegoholiveira's tests.

@diegoholiveira
Copy link
Author

@jakzal sorry dude, i don't understand what you mean. Did you like to take a look into my tests?

@jakzal
Copy link
Contributor

jakzal commented Apr 14, 2012

@diegoholiveira sorry, i didn't notice your link....

@diegoholiveira
Copy link
Author

@jakzal no problems :)

If you need something, just ping me.

@maoueh
Copy link
Contributor

maoueh commented Apr 19, 2012

Hi,

I'm jumping in since I'm now facing this issue as well. Here a test case failing:

<?php

namespace Acme\UpartyBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class UserControllerTest extends WebTestCase
{
    public function testCreateUser()
    {
        $client = $this->createClient();
        $crawler = $client->request('GET', '/en/user/create');
    }
}

When I started to work today, tests were ok. Then, I added JMSDebuggingBundle and updated Symfony 2.1 dependencies then tests stopped working. Last time I updated, its when Form options were fixed, so it like 8 days ago from now.

The failing machine is on Mac OS X, I have another box at home, which is on Windows and with the project not updated yet. I will make some test tonight or tomorrow morning to see what caused the problem to arise now and not before. Maybe it could help with the debugging of the problem.

Regards,
Matt

@maoueh
Copy link
Contributor

maoueh commented Apr 22, 2012

Here a follow-up of my previous post.

Today, I tried to revert to a previous working state and tests were passing as expected with a preivous version of my project. Since the last thing I had done before it failed was adding JMSDebuggingBundle and updating Symfony, I tought I should try to remove the bundle to see if it was working. It did.

So, I went back to the HEAD of my branch to have my project fully up-to-date and tried to disable the bundle. This also made the tests passed.

So, my conclusion is that, in my case, the bundle was interacting badly with the session somehow which is triggering the errors in my tests. The current workaround I did is to disable the JMSDebuggingBundle when the environment is test. Here the code:

if (in_array($this->getEnvironment(), array('dev', 'test'))) {
    $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();

    if ($this->getEnvironment() === 'dev') {
        $bundles[] = new JMS\DebuggingBundle\JMSDebuggingBundle($this);
    }
}

I thought it could be the custom container class provided with the bundle that was breaking something, but it wasn't the case since commenting the code changing the container base class did not make the tests pass. Once again, I'm changing the container base class only in dev environment to workaround this issue.

Anyone in this thread having the error is using JMSDebuggingBundle? It could also a bad interaction with any other bundle. But one certitude, in my case, this was the offending bundle.

Hope it helps to resolve this issue.

Regards,
Matt

@diegoholiveira
Copy link
Author

I'm not using JMSDebuggingBundle. In fact, i'm just using the default bundles that come into symfony-standard.

:)

@maoueh
Copy link
Contributor

maoueh commented Apr 23, 2012

Hello again,

Since @diegoholiveira is using only default bundles, it is clearly not only JMSDebuggingBundle that triggers this error. So, I went ahead and searched a bit on what is going on. Here my findings.

I'm my project, I'm also using FOSFacebookBundle to authenticate users. Before adding JMSDebuggingBundle, every tests were passing. When I added it, it started to break. FOSFacebookBundle is working with the session at some point to retrieve some information from it. The main class that deals with session is FacebookSessionPersistence. If I comment everything related to the object session in it, my tests passed (well, no but they don't trigger the exception mentionned in this issue).

  1. My project with FOSFacebookBundle only => Ok
  2. My project with FOSFacebookBundle & JMSDebuggingBundle => Exception
  3. My project with FOSFacebookBundle & JMSDebuggingBundle but with session stuff in FacebookSessionPersistence commented out => Ok

A weird interaction is going on since activating JMSDebuggingBundle triggers the error on my project but it is not bundle's direct fault because it can work if some code in FOSFacebookBundle is commented out.

So, I decided to find a way for others to reproduce this error. What you can do is to checkout symfony-standard, add FOSFacebookBundle and JMSDebuggingBundle, configure them (FOSFacebookBundle can by configured with false app_id and app_secret), configure the security configuration to use FOSFacebookBundle. Magic, tests will fail with the LogicException about session already started.

To make it easy to reproduce, I cloned current symfony-standard and configured it with the stuff required to reproduce this problem. I pushed it on my own repo on Github. You can find this customized symfony-standard in my test_session_listener_problem branch.

If you clone my repo, checkout branch test_session_listener_problem, run php composer.phar install then go in folder app/ and run phpunit, you should see the exception.

If you then comment $bundles[] = new JMS\DebuggingBundle\JMSDebuggingBundle($this); in AppKernel.php, test will be ok and you will not see the exception.

I cannot conclude if this a Symfony bug or not. Only thing I can say, this is a bizarre issue and seems to be related to integration of code. Since @diegoholiveira use default bundles from symfony-standard, I guess his code must contain something that triggers this error.

Again, hope this helps to sort out this weird issue :)

Regards,
Matt

@diegoholiveira
Copy link
Author

Hi Matt,

Sorry dude, but I give you WRONG information about my project. I'm using FOSFacebookBundle too (I just remember that I'm using when I see you last response, it's easy to forgot about it because it's something that we not deal directly every day...)

@maoueh
Copy link
Contributor

maoueh commented Apr 23, 2012

@diegoholiveira No problem at all :), it may now be easier to debug the issue. This seems in some way related to FOSFacebookBundle. What I found odd is that without JMSDebuggingBundle, I don't have this issue at all. But with it enabled, the error is triggered. So weird.

It could potentially be related to this FOSFacebookBundle issue.

@maoueh
Copy link
Contributor

maoueh commented Apr 23, 2012

After reading more thoroughly issue #79 of FOSFacebookBundle, I think the issue we are seeing is directly caused by facebook bundle. I still have no clue why JMSDebuggingBundle triggers the problem on my project, but I'm 90% sure FOSFacebookBundle is the culprit of this issue.

Maybe @Drak could confirm my hypothesis.

@lsmith77
Copy link
Contributor

lsmith77 commented May 8, 2012

also seeing this issue when updating. i am not using FOSFacebookBundle, but a fairly hacked up version of Sensio's CasBundle

@lsmith77
Copy link
Contributor

lsmith77 commented May 9, 2012

Some more information about my use case. My provider class has a dependency on a service that in turn requires the container. I managed to fix the issue by instead injecting the container and then only fetching the session lazily .. but not instead the constructor.

@guilhermeblanco
Copy link
Contributor

@lsmith77 @maoueh @Drak @diegoholiveira I am experiencing the same problem right now.
I don't use ANY of the mentioned bundles, but for testing I use the LiipFunctionalTestBundle. Under this situation, I try to emulate a login of a user, which triggers the start of the Session and then it fails internally.

@guilhermeblanco
Copy link
Contributor

@Drak @stof By commenting the lines:

} else {
    $session->setId('');
}

The issue is now fixed in my environment.

fabpot added a commit that referenced this issue May 30, 2012
Commits
-------

3ad01c0 Update src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php

Discussion
----------

Fix broken web test cases with session already started

This PR fixes the issues highlighted in PR #4445 and #3741 by not overriding the session id if the session is already started.

---------------------------------------------------------------------------

by travisbot at 2012-05-29T19:06:33Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1468970) (merged 3ad01c0 into adf07f1).

---------------------------------------------------------------------------

by stloyd at 2012-05-29T19:07:54Z

Look at #2040. It's quite old, but there is at least some "reason" =)

---------------------------------------------------------------------------

by guilhermeblanco at 2012-05-29T20:57:27Z

@stloyd it seems to me that doing a session_id() (and now as $session->setId()) is still wrong.
The right should be a regeneration of the id then, which would still make my code pass. The problem is that setId method checks for a possible regeneration/double attribution, which prevents an already started session (from a WebTestCase) to live peacefully with the TestSessionListener, because it will always try to set an id.
So either we allow to regenerate ids or this code is not only useless for 2.1, but actually broken.

---------------------------------------------------------------------------

by drak at 2012-05-30T02:42:47Z

@guilhermeblanco - When I was doing the session refactoring I wanted to make exactly the patch this PR now but I didnt because I wast sure if there were reasons I was unaware of. @fabpot - I would merge this PR if it fixes the related tickets.
@fabpot fabpot closed this as completed May 30, 2012
@josecelano
Copy link

I had the same problem. In my case the problem was I had an event listener which had this code:

$this->session->start();

As it is described in this isuue FriendsOfSymfony/FOSFacebookBundle#79 the problem is to start the session too early.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants