django-nose icon indicating copy to clipboard operation
django-nose copied to clipboard

REUSE_DB for tests fails when using django-guardian's ANONYMOUS_USER_ID as -1

Open anthonyfinch opened this issue 11 years ago • 10 comments

Was unsure whether this one really belonged here or with django-guardian, so apologies in advance if this is inappropriate.

Briefly, when using django-guardian (https://github.com/lukaszb/django-guardian) with the ANONYMOUS_USER_ID set to -1, tests work perfectly the first time round. However, when using REUSE_DB, on a second pass, django_nose cannot reset the database successfully.

Using the ANONYMOUS_USER_ID of -1 as suggested in the documentation for django-guardian (http://django-guardian.readthedocs.org/en/latest/configuration.html), reusing the database to run tests fails when resetting the database to it's 'clean' state. The error given is as follows:

django.db.utils.DatabaseError: setval: value -1 is out of bounds for sequence "auth_user_id_seq" (1..9223372036854775807)

Examining the reset statements, the one causing the error is: SELECT setval(pg_get_serial_sequence('"auth_user"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "auth_user";

The User object with id of -1 is created automatically by a signal hooked to post_syncdb in django_guardian's management/init.py.

Using: Django 1.4.3, django-guardian 1.0.4, postgres 9.1 with postgis 1.5. Django engine: django.contrib.gis.db.backends.postgis

The full stack trace:

Traceback (most recent call last):
  File "./manage.py", line 9, in <module>
    execute_from_command_line(sys.argv)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 49, in run_from_argv
    super(Command, self).run_from_argv(argv)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django/core/management/base.py", line 196, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/south/management/commands/test.py", line 8, in handle
    super(Command, self).handle(*args, **kwargs)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 72, in handle
    failures = test_runner.run_tests(test_labels)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django_nose/runner.py", line 155, in run_tests
    result = self.run_suite(nose_argv)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django_nose/runner.py", line 117, in run_suite
    addplugins=plugins_to_add)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/nose/core.py", line 118, in __init__
    **extra_args)
  File "/usr/lib/python2.7/unittest/main.py", line 95, in __init__
    self.runTests()
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/nose/core.py", line 197, in runTests
    result = self.testRunner.run(self.test)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/nose/core.py", line 50, in run
    wrapper = self.config.plugins.prepareTest(test)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/nose/plugins/manager.py", line 99, in __call__
    return self.call(*arg, **kw)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/nose/plugins/manager.py", line 167, in simple
    result = meth(*arg, **kw)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django_nose/plugin.py", line 78, in prepareTest
    self.old_names = self.runner.setup_databases()
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django_nose/runner.py", line 308, in setup_databases
    cursor.execute(reset_statement)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django/db/backends/util.py", line 40, in execute
    return self.cursor.execute(sql, params)
  File "/home/tony/.virtualenvs/trialreach/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 52, in execute
    return self.cursor.execute(query, args)
django.db.utils.DatabaseError: setval: value -1 is out of bounds for sequence "auth_user_id_seq" (1..9223372036854775807)

anthonyfinch avatar Apr 30 '13 11:04 anthonyfinch

I tried to reproduce this but I literally ran out of HD space installing the required PG / GIS stuff. If you have spatialite installed, could you try it, to see if it fixes the bug?

This is what you get when you partition a 90G hard drive in two.

fabiosantoscode avatar May 02 '13 18:05 fabiosantoscode

I have exactly the same error using postgres. What about spatialite? What should we try?

Natim avatar May 31 '13 08:05 Natim

Same thing here! Any idea on how to tackle this?

andrefsp avatar Jun 05 '13 21:06 andrefsp

I came across the same problem. Is there a solution for this yet?

Mactory avatar Jun 12 '15 07:06 Mactory

I remember we found a workaround at the time but I don't remember how. Quite a long time ago already.

Natim avatar Jun 12 '15 08:06 Natim

I actually did find a workaround by simply defining ANONYMOUS_USER_ID = 2147483647 in the settings for my tests

Mactory avatar Jun 12 '15 09:06 Mactory

Oh yes I remember we did ANONYMOUS_USER_ID = 0 rather than -1

Natim avatar Jun 12 '15 09:06 Natim

I tried that, but i got the same error since the sequence seems to start at 1, so I simply selected max_int.

Mactory avatar Jun 12 '15 09:06 Mactory

ok, it gets weird: If i set ANONYMOUS_USER_ID = 2147483647 as I said before, everything works fine as long as I don't actually generate any users. I just wrote the first test where I need a user, so I create one. If I delete the database and start off fresh, the new user gets ID 1 as expected. If it is the second time, the new user gets ID 2147483648 which is out of range and throws an error. I therefor now switched to using ANONYMOUS_USER_ID = 1073741824 since it gives me the most amount of users for the first and all following runs.

~~Interestingly enough, for ALL subsequent runs, the first ID that is assigned to a user is always 1073741825, so it seems to get reseted on every run.~~ Never mind this part. This only happened since my test did not run through.

Mactory avatar Jun 12 '15 11:06 Mactory

In case this helps anyone else struggling with this: For me, ANONYMOUS_USER_ID = 2147483647 failed with an out-of-range error that I didn't investigate. Setting it to 99999 did the trick though. After that, I got another error from runner.py: "TypeError: method expected 2 arguments, got 3", but that was because I had an old version of django_nose, fixed by upgrading to 1.4.1. Then I was scared of the reports that this connects to the real (not test) database for (perhaps) the first test in every test run, which I think I defused by manually applying this change to the django_nose in my virtualenv: https://github.com/django-nose/django-nose/pull/137/files. REUSE_DB now works for me, am very happy.

tartley avatar Jul 02 '15 14:07 tartley