Exemple #1
0
class RouterReadTestCase(TestCase):

    def setUp(self):
        from django.contrib.auth import get_user_model
        self.sut = ShardedRouter()
        self.user = get_user_model().objects.create_user(username='******', password='******', email='*****@*****.**')

    def test_sharded_instance_uses_a_routing_read_strategies(self):
        item = TestModel.objects.using('app_shard_002').create(random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        with patch.object(self.sut, 'get_read_db_routing_strategy') as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=TestModel, **hints), 'testing')

    def test_sharded_instance(self):
        item = TestModel.objects.using('app_shard_002').create(random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        self.assertEqual(self.sut.db_for_read(model=TestModel, **hints), 'app_shard_002')

    def test_sharded_model(self):
        self.assertEqual(self.sut.db_for_read(model=TestModel), None)

    def test_specific_database(self):
        self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs), 'app_shard_001')

    def test_specific_database_does_not_use_the_routing_read_strategy(self):
        with patch.object(self.sut, 'get_read_db_routing_strategy') as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs), 'app_shard_001')

    def test_other(self):
        from django.contrib.auth import get_user_model
        self.assertEqual(self.sut.db_for_read(model=get_user_model()), None)
Exemple #2
0
class RouterReadTestCase(TransactionTestCase):
    databases = '__all__'

    def setUp(self):
        self.sut = ShardedRouter()
        self.user = get_user_model().objects.create_user(
            username='******',
            password='******',
            email='*****@*****.**')

    def test_sharded_instance_uses_a_routing_read_strategies(self):
        item = TestModel.objects.using('app_shard_002').create(
            random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        with patch.object(self.sut, 'get_read_db_routing_strategy'
                          ) as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(
                settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=TestModel, **hints),
                             'testing')

    def test_sharded_instance(self):
        item = TestModel.objects.using('app_shard_002').create(
            random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        self.assertEqual(self.sut.db_for_read(model=TestModel, **hints),
                         'app_shard_002')

    def test_sharded_model(self):
        self.assertEqual(self.sut.db_for_read(model=TestModel), None)

    def test_specific_database(self):
        self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs),
                         'app_shard_001')

    def test_specific_database_does_not_use_the_routing_read_strategy(self):
        with patch.object(self.sut, 'get_read_db_routing_strategy'
                          ) as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(
                settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs),
                             'app_shard_001')

    def test_other(self):
        self.assertEqual(self.sut.db_for_read(model=get_user_model()),
                         "default")
Exemple #3
0
class RouterReadTestCase(TransactionTestCase):
    def setUp(self):
        from django.contrib.auth import get_user_model
        self.sut = ShardedRouter()
        self.user = get_user_model().objects.create_user(
            username='******',
            password='******',
            email='*****@*****.**')

    def test_sharded_instance_uses_a_routing_read_strategies(self):
        item = TestModel.objects.using('app_shard_002').create(
            random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        with patch.object(self.sut, 'get_read_db_routing_strategy'
                          ) as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(
                settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=TestModel, **hints),
                             'testing')

    def test_sharded_instance(self):
        item = TestModel.objects.using('app_shard_002').create(
            random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        self.assertEqual(self.sut.db_for_read(model=TestModel, **hints),
                         'app_shard_002')

    def test_sharded_model(self):
        self.assertEqual(self.sut.db_for_read(model=TestModel), None)

    def test_specific_database(self):
        self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs),
                         'app_shard_001')

    def test_specific_database_does_not_use_the_routing_read_strategy(self):
        with patch.object(self.sut, 'get_read_db_routing_strategy'
                          ) as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(
                settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs),
                             'app_shard_001')

    def test_other(self):
        from django.contrib.auth import get_user_model
        self.assertEqual(self.sut.db_for_read(model=get_user_model()),
                         "default")

    def test_router_hints_receives_get_kwargs(self):
        original_id = TestModel.objects.create(user_pk=self.user.pk).id

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_write',
                          wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_read',
                    wraps=self.sut.db_for_read) as read_route_function:
                result = TestModel.objects.get(user_pk=self.user.pk)

        self.assertEqual(result.id, original_id)
        self.assertEqual(
            [call(TestModel, **lookups_to_find),
             call(get_user_model())], read_route_function.mock_calls)
        self.assertEqual([], write_route_function.mock_calls)

    def test_router_hints_receives_get_kwargs_on_get_or_create__get(self):
        original_id = TestModel.objects.create(user_pk=self.user.pk).id

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_write',
                          wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_read',
                    wraps=self.sut.db_for_read) as read_route_function:
                result, created = TestModel.objects.get_or_create(
                    user_pk=self.user.pk)

        self.assertEqual(result.id, original_id)
        self.assertFalse(created)
        self.assertEqual([call(get_user_model())],
                         read_route_function.mock_calls)

        self.assertEqual([
            call(TestModel, **lookups_to_find),
        ], write_route_function.mock_calls)

    def test_router_hints_receives_get_kwargs_on_get_or_create__create(self):
        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_write',
                          wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_read',
                    wraps=self.sut.db_for_read) as read_route_function:

                _, created = TestModel.objects.get_or_create(
                    user_pk=self.user.pk)

        self.assertTrue(created)
        self.assertEqual([
            call(get_user_model()),
            call(get_user_model()),
            call(get_user_model())
        ], read_route_function.mock_calls)

        self.assertEqual(
            [
                call(TestModel, **lookups_to_find),
                call(TestModel, **lookups_to_find),
                call(
                    TestModel,
                    instance=write_route_function.mock_calls[2][2]["instance"],
                    **lookups_to_find
                ),  # no way to access that copy of the instance here, the one prior to saving.
                call(ShardedTestModelIDs),
            ],
            write_route_function.mock_calls)

    def test_router_hints_receives_get_kwargs_on_update_or_create__get(self):
        original_id = TestModel.objects.create(user_pk=self.user.pk).id

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_read',
                          wraps=self.sut.db_for_read) as read_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_write',
                    wraps=self.sut.db_for_write) as write_route_function:

                result, created = TestModel.objects.update_or_create(
                    user_pk=self.user.pk)

        self.assertEqual(result.id, original_id)
        self.assertFalse(created)

        import django
        if django.VERSION < (1, 10) or django.VERSION >= (1, 11):
            self.assertEqual([
                call(get_user_model()),
                call(get_user_model()),
                call(get_user_model())
            ], read_route_function.mock_calls)
            self.assertEqual([
                call(TestModel, **lookups_to_find),
                call(TestModel, **lookups_to_find),
                call(TestModel, **lookups_to_find)
            ], write_route_function.mock_calls)
        else:
            # Django 1.10 dropped a call for each here :)
            self.assertEqual([call(get_user_model()),
                              call(get_user_model())],
                             read_route_function.mock_calls)
            self.assertEqual([
                call(TestModel, **lookups_to_find),
                call(TestModel, **lookups_to_find)
            ], write_route_function.mock_calls)

    def test_router_hints_receives_get_kwargs_on_update_or_create__create(
            self):
        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_read',
                          wraps=self.sut.db_for_read) as read_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_write',
                    wraps=self.sut.db_for_write) as write_route_function:

                instance, created = TestModel.objects.update_or_create(
                    user_pk=self.user.pk)

        self.assertTrue(created)
        import django
        if (1, 11) > django.VERSION:
            self.assertEqual([
                call(get_user_model()),
                call(get_user_model()),
                call(get_user_model())
            ], read_route_function.mock_calls)
            self.assertEqual(
                [
                    call(TestModel, **lookups_to_find),
                    call(TestModel, **lookups_to_find),
                    # no way to access that copy of the instance here, the one prior to saving.
                    call(TestModel,
                         instance=write_route_function.mock_calls[2][2]
                         ["instance"],
                         **lookups_to_find),
                    call(ShardedTestModelIDs),
                ],
                write_route_function.mock_calls)
        else:
            self.assertEqual([
                call(get_user_model()),
                call(get_user_model()),
                call(get_user_model()),
                call(get_user_model())
            ], read_route_function.mock_calls)
            self.assertEqual([
                call(TestModel, **lookups_to_find),
                call(TestModel, **lookups_to_find),
                call(TestModel, **lookups_to_find),
                call(
                    TestModel,
                    instance=write_route_function.mock_calls[3][2]["instance"],
                    **lookups_to_find),
                call(ShardedTestModelIDs),
            ], write_route_function.mock_calls)

    def test_router_hints_receives_filter_kwargs_on_count(self):
        TestModel.objects.create(user_pk=self.user.pk)

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_write',
                          wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_read',
                    wraps=self.sut.db_for_read) as read_route_function:
                result = TestModel.objects.filter(user_pk=self.user.pk).count()

        self.assertEqual(result, 1)
        self.assertEqual(
            [call(TestModel, **lookups_to_find),
             call(get_user_model())], read_route_function.mock_calls)
        self.assertEqual([], write_route_function.mock_calls)

    def test_router_hints_receives_filter_kwargs_on_exists(self):
        TestModel.objects.create(user_pk=self.user.pk)

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_write',
                          wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_read',
                    wraps=self.sut.db_for_read) as read_route_function:
                result = TestModel.objects.filter(
                    user_pk=self.user.pk).exists()

        self.assertTrue(result)
        self.assertEqual(
            [call(TestModel, **lookups_to_find),
             call(get_user_model())], read_route_function.mock_calls)
        self.assertEqual([], write_route_function.mock_calls)

    def test_router_hints_receives_filter_kwargs(self):
        TestModel.objects.create(user_pk=self.user.pk)

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_write',
                          wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_read',
                    wraps=self.sut.db_for_read) as read_route_function:
                list(TestModel.objects.filter(user_pk=self.user.pk))

        self.assertEqual(
            [call(TestModel, **lookups_to_find),
             call(get_user_model())], read_route_function.mock_calls)
        self.assertEqual([], write_route_function.mock_calls)

    def test_router_gets_hints_correctly_with_positional_arguments_like_Q_in_filter(
            self):
        TestModel.objects.create(user_pk=self.user.pk, random_string="test")

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_write',
                          wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_read',
                    wraps=self.sut.db_for_read) as read_route_function:
                list(
                    TestModel.objects.filter(Q(random_string="test")
                                             | Q(random_string__isnull=True),
                                             user_pk=self.user.pk))

        self.assertEqual(
            [call(TestModel, **lookups_to_find),
             call(get_user_model())], read_route_function.mock_calls)
        self.assertEqual([], write_route_function.mock_calls)

    def test_router_gets_hints_correctly_with_positional_arguments_like_Q_in_get(
            self):
        TestModel.objects.create(user_pk=self.user.pk, random_string="test")

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter,
                          'db_for_write',
                          wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(
                    ShardedRouter, 'db_for_read',
                    wraps=self.sut.db_for_read) as read_route_function:
                TestModel.objects.get(Q(random_string="test")
                                      | Q(random_string__isnull=True),
                                      user_pk=self.user.pk)

        self.assertEqual(
            [call(TestModel, **lookups_to_find),
             call(get_user_model())], read_route_function.mock_calls)
        self.assertEqual([], write_route_function.mock_calls)

    def test_queryset_router_filter_returns_existing_objects(self):
        for i in range(1, 11):
            test_model_obj = TestModel.objects.create(user_pk=self.user.pk,
                                                      random_string="%s" % i)
            self.assertIn(test_model_obj._state.db,
                          ['app_shard_001', 'app_shard_002'])

        test_models = TestModel.objects.filter(user_pk=self.user.pk)
        self.assertEqual(len(test_models), 10)

        from django.contrib.auth import get_user_model
        new_user = get_user_model().objects.create_user(
            username='******',
            password='******',
            email='*****@*****.**')
        for i in range(1, 21):
            TestModel.objects.create(user_pk=new_user.pk,
                                     random_string="%s" % i)

        test_models = TestModel.objects.filter(user_pk=new_user.pk)
        self.assertEqual(len(test_models), 20)

    def test_queryset_router_filter_with_aggregates(self):
        for i in range(1, 11):
            TestModel.objects.create(user_pk=self.user.pk,
                                     random_string="%s" % i)
        num_models = TestModel.objects.filter(user_pk=self.user.pk).count()
        self.assertEqual(num_models, 10)

        sum_model_pk = TestModel.objects.filter(
            user_pk=self.user.pk).aggregate(user_pk_sum=Sum('user_pk'))
        self.assertEqual(sum_model_pk['user_pk_sum'], self.user.pk * 10)
class RouterReadTestCase(TestCase):

    def setUp(self):
        from django.contrib.auth import get_user_model
        self.sut = ShardedRouter()
        self.user = get_user_model().objects.create_user(username='******', password='******', email='*****@*****.**')

    def test_sharded_instance_uses_a_routing_read_strategies(self):
        item = TestModel.objects.using('app_shard_002').create(random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        with patch.object(self.sut, 'get_read_db_routing_strategy') as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=TestModel, **hints), 'testing')

    def test_sharded_instance(self):
        item = TestModel.objects.using('app_shard_002').create(random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        self.assertEqual(self.sut.db_for_read(model=TestModel, **hints), 'app_shard_002')

    def test_sharded_model(self):
        self.assertEqual(self.sut.db_for_read(model=TestModel), None)

    def test_specific_database(self):
        self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs), 'app_shard_001')

    def test_specific_database_does_not_use_the_routing_read_strategy(self):
        with patch.object(self.sut, 'get_read_db_routing_strategy') as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs), 'app_shard_001')

    def test_other(self):
        from django.contrib.auth import get_user_model
        self.assertEqual(self.sut.db_for_read(model=get_user_model()), None)

    def test_router_hints_receives_filter_kwargs(self):
        TestModel.objects.create(user_pk=self.user.pk)

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_read') as read_route_function:
            read_route_function.return_value = 'app_shard_001'
            test_models = list(TestModel.objects.filter(user_pk=self.user.pk))
            self.assertIn(lookups_to_find, read_route_function.call_args)

    def test_queryset_router_filter_returns_existing_objects(self):
        for i in range(1, 11):
            test_model_obj = TestModel.objects.create(user_pk=self.user.pk, random_string="%s" % i)
            self.assertIn(test_model_obj._state.db, ['app_shard_001', 'app_shard_002'])

        test_models = TestModel.objects.filter(user_pk=self.user.pk)
        self.assertEqual(len(test_models), 10)

        from django.contrib.auth import get_user_model
        new_user = get_user_model().objects.create_user(username='******', password='******', email='*****@*****.**')
        for i in range(1, 21):
            TestModel.objects.create(user_pk=new_user.pk, random_string="%s" % i)

        test_models = TestModel.objects.filter(user_pk=new_user.pk)
        self.assertEqual(len(test_models), 20)

    def test_queryset_router_filter_with_aggregates(self):
        for i in range(1, 11):
            TestModel.objects.create(user_pk=self.user.pk, random_string="%s" % i)
        num_models = TestModel.objects.filter(user_pk=self.user.pk).count()
        self.assertEqual(num_models, 10)

        sum_model_pk = TestModel.objects.filter(user_pk=self.user.pk).aggregate(user_pk_sum=Sum('user_pk'))
        self.assertEqual(sum_model_pk['user_pk_sum'], self.user.pk * 10)
class RouterReadTestCase(TransactionTestCase):

    def setUp(self):
        from django.contrib.auth import get_user_model
        self.sut = ShardedRouter()
        self.user = get_user_model().objects.create_user(username='******', password='******', email='*****@*****.**')

    def test_sharded_instance_uses_a_routing_read_strategies(self):
        item = TestModel.objects.using('app_shard_002').create(random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        with patch.object(self.sut, 'get_read_db_routing_strategy') as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=TestModel, **hints), 'testing')

    def test_sharded_instance(self):
        item = TestModel.objects.using('app_shard_002').create(random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        self.assertEqual(self.sut.db_for_read(model=TestModel, **hints), 'app_shard_002')

    def test_sharded_model(self):
        self.assertEqual(self.sut.db_for_read(model=TestModel), None)

    def test_specific_database(self):
        self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs), 'app_shard_001')

    def test_specific_database_does_not_use_the_routing_read_strategy(self):
        with patch.object(self.sut, 'get_read_db_routing_strategy') as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs), 'app_shard_001')

    def test_other(self):
        from django.contrib.auth import get_user_model
        self.assertEqual(self.sut.db_for_read(model=get_user_model()), "default")

    def test_router_hints_receives_get_kwargs(self):
        original_id = TestModel.objects.create(user_pk=self.user.pk).id

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
                result = TestModel.objects.get(user_pk=self.user.pk)

        self.assertEqual(result.id, original_id)
        self.assertEqual(
            [call(TestModel, **lookups_to_find), call(get_user_model())],
            read_route_function.mock_calls
        )
        self.assertEqual(
            [],
            write_route_function.mock_calls
        )

    def test_router_hints_receives_get_kwargs_on_get_or_create__get(self):
        original_id = TestModel.objects.create(user_pk=self.user.pk).id

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
                result, created = TestModel.objects.get_or_create(user_pk=self.user.pk)

        self.assertEqual(result.id, original_id)
        self.assertFalse(created)
        self.assertEqual(
            [call(get_user_model())],
            read_route_function.mock_calls
        )

        self.assertEqual(
            [
                call(TestModel, **lookups_to_find),
            ],
            write_route_function.mock_calls
        )

    def test_router_hints_receives_get_kwargs_on_get_or_create__create(self):
        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:

                _, created = TestModel.objects.get_or_create(user_pk=self.user.pk)

        self.assertTrue(created)
        self.assertEqual(
            [call(get_user_model()), call(get_user_model()), call(get_user_model())],
            read_route_function.mock_calls
        )

        self.assertEqual(
            [
                call(TestModel, **lookups_to_find),
                call(TestModel, **lookups_to_find),
                call(TestModel, instance=write_route_function.mock_calls[2][2]["instance"], **lookups_to_find),  # no way to access that copy of the instance here, the one prior to saving.
                call(ShardedTestModelIDs),
            ],
            write_route_function.mock_calls
        )

    def test_router_hints_receives_get_kwargs_on_update_or_create__get(self):
        original_id = TestModel.objects.create(user_pk=self.user.pk).id

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
            with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:

                result, created = TestModel.objects.update_or_create(user_pk=self.user.pk)

        self.assertEqual(result.id, original_id)
        self.assertFalse(created)

        import django
        if django.VERSION < (1, 10) or django.VERSION >= (1, 11):
            self.assertEqual(
                [call(get_user_model()), call(get_user_model()), call(get_user_model())],
                read_route_function.mock_calls
            )
            self.assertEqual(
                [call(TestModel, **lookups_to_find), call(TestModel, **lookups_to_find), call(TestModel, **lookups_to_find)],
                write_route_function.mock_calls
            )
        else:
            # Django 1.10 dropped a call for each here :)
            self.assertEqual(
                [call(get_user_model()), call(get_user_model())],
                read_route_function.mock_calls
            )
            self.assertEqual(
                [call(TestModel, **lookups_to_find), call(TestModel, **lookups_to_find)],
                write_route_function.mock_calls
            )

    def test_router_hints_receives_get_kwargs_on_update_or_create__create(self):
        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
            with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:

                instance, created = TestModel.objects.update_or_create(user_pk=self.user.pk)

        self.assertTrue(created)
        import django
        if (1, 11) > django.VERSION:
            self.assertEqual(
                [call(get_user_model()), call(get_user_model()), call(get_user_model())],
                read_route_function.mock_calls
            )
            self.assertEqual(
                [
                    call(TestModel, **lookups_to_find),
                    call(TestModel, **lookups_to_find),
                    # no way to access that copy of the instance here, the one prior to saving.
                    call(TestModel, instance=write_route_function.mock_calls[2][2]["instance"], **lookups_to_find),
                    call(ShardedTestModelIDs),
                ],
                write_route_function.mock_calls
            )
        else:
            self.assertEqual(
                [call(get_user_model()), call(get_user_model()), call(get_user_model()), call(get_user_model())],
                read_route_function.mock_calls
            )
            self.assertEqual(
                [
                    call(TestModel, **lookups_to_find),
                    call(TestModel, **lookups_to_find),
                    call(TestModel, **lookups_to_find),
                    call(TestModel, instance=write_route_function.mock_calls[3][2]["instance"], **lookups_to_find),
                    call(ShardedTestModelIDs),
                ],
                write_route_function.mock_calls
            )

    def test_router_hints_receives_filter_kwargs_on_count(self):
        TestModel.objects.create(user_pk=self.user.pk)

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
                result = TestModel.objects.filter(user_pk=self.user.pk).count()

        self.assertEqual(result, 1)
        self.assertEqual(
            [call(TestModel, **lookups_to_find), call(get_user_model())],
            read_route_function.mock_calls
        )
        self.assertEqual(
            [],
            write_route_function.mock_calls
        )

    def test_router_hints_receives_filter_kwargs_on_exists(self):
        TestModel.objects.create(user_pk=self.user.pk)

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
                result = TestModel.objects.filter(user_pk=self.user.pk).exists()

        self.assertTrue(result)
        self.assertEqual(
            [call(TestModel, **lookups_to_find), call(get_user_model())],
            read_route_function.mock_calls
        )
        self.assertEqual(
            [],
            write_route_function.mock_calls
        )

    def test_router_hints_receives_filter_kwargs(self):
        TestModel.objects.create(user_pk=self.user.pk)

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
                list(TestModel.objects.filter(user_pk=self.user.pk))

        self.assertEqual(
            [call(TestModel, **lookups_to_find), call(get_user_model())],
            read_route_function.mock_calls
        )
        self.assertEqual(
            [],
            write_route_function.mock_calls
        )

    def test_router_gets_hints_correctly_with_positional_arguments_like_Q_in_filter(self):
        TestModel.objects.create(user_pk=self.user.pk, random_string="test")

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
                list(TestModel.objects.filter(Q(random_string="test") | Q(random_string__isnull=True), user_pk=self.user.pk))

        self.assertEqual(
            [call(TestModel, **lookups_to_find), call(get_user_model())],
            read_route_function.mock_calls
        )
        self.assertEqual(
            [],
            write_route_function.mock_calls
        )

    def test_router_gets_hints_correctly_with_positional_arguments_like_Q_in_get(self):
        TestModel.objects.create(user_pk=self.user.pk, random_string="test")

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_write', wraps=self.sut.db_for_write) as write_route_function:
            with patch.object(ShardedRouter, 'db_for_read', wraps=self.sut.db_for_read) as read_route_function:
                TestModel.objects.get(Q(random_string="test") | Q(random_string__isnull=True), user_pk=self.user.pk)

        self.assertEqual(
            [call(TestModel, **lookups_to_find), call(get_user_model())],
            read_route_function.mock_calls
        )
        self.assertEqual(
            [],
            write_route_function.mock_calls
        )

    def test_queryset_router_filter_returns_existing_objects(self):
        for i in range(1, 11):
            test_model_obj = TestModel.objects.create(user_pk=self.user.pk, random_string="%s" % i)
            self.assertIn(test_model_obj._state.db, ['app_shard_001', 'app_shard_002'])

        test_models = TestModel.objects.filter(user_pk=self.user.pk)
        self.assertEqual(len(test_models), 10)

        from django.contrib.auth import get_user_model
        new_user = get_user_model().objects.create_user(username='******', password='******', email='*****@*****.**')
        for i in range(1, 21):
            TestModel.objects.create(user_pk=new_user.pk, random_string="%s" % i)

        test_models = TestModel.objects.filter(user_pk=new_user.pk)
        self.assertEqual(len(test_models), 20)

    def test_queryset_router_filter_with_aggregates(self):
        for i in range(1, 11):
            TestModel.objects.create(user_pk=self.user.pk, random_string="%s" % i)
        num_models = TestModel.objects.filter(user_pk=self.user.pk).count()
        self.assertEqual(num_models, 10)

        sum_model_pk = TestModel.objects.filter(user_pk=self.user.pk).aggregate(user_pk_sum=Sum('user_pk'))
        self.assertEqual(sum_model_pk['user_pk_sum'], self.user.pk * 10)
class RouterReadTestCase(TestCase):
    def setUp(self):
        from django.contrib.auth import get_user_model
        self.sut = ShardedRouter()
        self.user = get_user_model().objects.create_user(
            username='******',
            password='******',
            email='*****@*****.**')

    def test_sharded_instance_uses_a_routing_read_strategies(self):
        item = TestModel.objects.using('app_shard_002').create(
            random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        with patch.object(self.sut, 'get_read_db_routing_strategy'
                          ) as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(
                settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=TestModel, **hints),
                             'testing')

    def test_sharded_instance(self):
        item = TestModel.objects.using('app_shard_002').create(
            random_string=2, user_pk=self.user.pk)
        hints = {'instance': item}
        self.assertEqual(self.sut.db_for_read(model=TestModel, **hints),
                         'app_shard_002')

    def test_sharded_model(self):
        self.assertEqual(self.sut.db_for_read(model=TestModel), None)

    def test_specific_database(self):
        self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs),
                         'app_shard_001')

    def test_specific_database_does_not_use_the_routing_read_strategy(self):
        with patch.object(self.sut, 'get_read_db_routing_strategy'
                          ) as mock_get_read_db_routing_strategy:
            mock_get_read_db_routing_strategy.return_value = FakeRoutingStrategy(
                settings.DATABASES)
            self.assertEqual(self.sut.db_for_read(model=ShardedTestModelIDs),
                             'app_shard_001')

    def test_other(self):
        from django.contrib.auth import get_user_model
        self.assertEqual(self.sut.db_for_read(model=get_user_model()), None)

    def test_router_hints_receives_filter_kwargs(self):
        TestModel.objects.create(user_pk=self.user.pk)

        lookups_to_find = {'exact_lookups': {'user_pk': self.user.pk}}

        with patch.object(ShardedRouter, 'db_for_read') as read_route_function:
            read_route_function.return_value = 'app_shard_001'
            test_models = list(TestModel.objects.filter(user_pk=self.user.pk))
            self.assertIn(lookups_to_find, read_route_function.call_args)

    def test_queryset_router_filter_returns_existing_objects(self):
        for i in range(1, 11):
            test_model_obj = TestModel.objects.create(user_pk=self.user.pk,
                                                      random_string="%s" % i)
            self.assertIn(test_model_obj._state.db,
                          ['app_shard_001', 'app_shard_002'])

        test_models = TestModel.objects.filter(user_pk=self.user.pk)
        self.assertEqual(len(test_models), 10)

        from django.contrib.auth import get_user_model
        new_user = get_user_model().objects.create_user(
            username='******',
            password='******',
            email='*****@*****.**')
        for i in range(1, 21):
            TestModel.objects.create(user_pk=new_user.pk,
                                     random_string="%s" % i)

        test_models = TestModel.objects.filter(user_pk=new_user.pk)
        self.assertEqual(len(test_models), 20)

    def test_queryset_router_filter_with_aggregates(self):
        for i in range(1, 11):
            TestModel.objects.create(user_pk=self.user.pk,
                                     random_string="%s" % i)
        num_models = TestModel.objects.filter(user_pk=self.user.pk).count()
        self.assertEqual(num_models, 10)

        sum_model_pk = TestModel.objects.filter(
            user_pk=self.user.pk).aggregate(user_pk_sum=Sum('user_pk'))
        self.assertEqual(sum_model_pk['user_pk_sum'], self.user.pk * 10)