class TestDbUowAssociationOneToMany(TestCase):
    connection = Connection()

    def setUp(self):
        self.session = Session(0, self.connection['test_tori_db_session'])

        for collection in self.session.collections:
            collection._api.remove() # Reset the database

        self.__inject_data_with_one_to_many_association()

    def test_fetching(self):
        c = self.session.collection(Developer)

        boss = c.filter_one({'name': 'boss'})

        self.assertIsInstance(boss.delegates, list)

        self.assertIsInstance(boss.delegates[0], ProxyObject)
        self.assertEqual(boss.delegates[0].name, 'a')
        self.assertIsInstance(boss.delegates[1], ProxyObject)
        self.assertEqual(boss.delegates[1].name, 'b')

    def test_cascading_on_persist(self):
        c = self.session.collection(Developer)

        boss = c.filter_one({'name': 'boss'})
        boss.delegates[0].name = 'assistant'

        self.session.persist(boss)
        self.session.flush()

        data = c._api.find_one({'_id': boss.delegates[0].id})

        self.assertEqual(boss.delegates[0].name, data['name'])

    def test_update_association(self):
        c = self.session.collection(Developer)

        boss = c.filter_one({'name': 'boss'})
        boss.delegates[0].name = 'assistant'

        boss.delegates.append(Developer('c'))

        self.session.persist(boss)
        self.session.flush()

        data = c._api.find_one({'name': 'c'})

        self.assertIsNotNone(data)
        self.assertEqual(boss.delegates[2].id, data['_id'])

        data = c._api.find_one({'name': 'boss'})

        self.assertEqual(3, len(data['delegates']))

        for delegate in boss.delegates:
            self.assertIn(delegate.id, data['delegates'])

    def test_cascading_on_delete_with_some_deps(self):
        c = self.session.collection(Developer)

        boss = c.filter_one({'name': 'boss'})
        boss.delegates[0].name = 'assistant'

        boss.delegates.append(Developer('c'))

        self.session.persist(boss)

        architect = Developer('architect', delegates=[boss.delegates[0]])

        self.session.persist(architect)
        self.session.flush()

        self.assertEqual(5, len(c.filter()))

        self.session.delete(architect)
        self.session.flush()

        self.assertEqual(4, len(c.filter()), 'should have some dependencies left (but no orphan node)')

    def test_cascading_on_delete_with_no_deps(self):
        c = self.session.collection(Developer)

        boss = c.filter_one({'name': 'boss'})

        print('point a')

        for d in c._api.find():
            print(d)

        boss.delegates[0].name = 'assistant'

        boss.delegates.append(Developer('c'))

        self.session.persist(boss)

        print('point b')

        for d in c._api.find():
            print(d)

        architect = Developer('architect', delegates=[boss.delegates[0]])

        self.session.persist(architect)
        self.session.flush()

        print('point c')

        for d in c._api.find():
            print(d)

        self.session.delete(architect)
        self.session.delete(boss)
        self.session.flush()

        count = len(c.filter())

        print('point d')

        for d in c._api.find():
            print(d)

        self.assertEqual(0, count, 'There should not exist dependencies left (orphan removal). (remaining: {})'.format(count))

    def __inject_data_with_one_to_many_association(self):
        api = self.session.collection(Developer)._api

        api.remove()

        a_id = api.insert({'name': 'a'})
        b_id = api.insert({'name': 'b'})

        api.insert({'name': 'boss', 'delegates': [a_id, b_id]})
Exemple #2
0
class TestDbSession(TestCase):
    connection       = Connection()
    registered_types = {
        'developer': Developer,
        'computer':  Computer,
        'testnode':  TestNode
    }

    def setUp(self):
        self.session = Session(0, self.connection['test_tori_db_session'], self.registered_types)

        for collection in self.session.collections:
            collection._api.remove() # Reset the database

    def test_commit_with_insert_with_cascading(self):
        reference_map = self.__inject_data_with_cascading()

        collection = self.session.collection(TestNode)
        doc        = collection.filter_one({'name': 'a'})

        self.assertEqual(len(reference_map), len(collection.filter()))
        self.assertEqual(reference_map['a'].id, doc.id)

    def test_commit_with_insert_without_cascading(self):
        reference_map = self.__mock_data_without_cascading()

        developer_collection = self.session.collection(Developer)
        computer_collection = self.session.collection(Computer)

        self.session.persist(reference_map['d1'])
        self.session.flush()

        self.assertEqual(1, len(developer_collection.filter()))
        self.assertEqual(0, len(computer_collection.filter()))

        developer = developer_collection.filter_one({'name': 'Shiroyuki'})

        self.assertIsNone(developer.computer.id)

        raw_data = developer_collection._api.find_one({'_id': developer.id})

        self.assertIsNone(raw_data['computer'])

    def test_commit_with_update(self):
        reference_map = self.__inject_data_with_cascading()

        doc = self.session.collection(TestNode).filter_one({'name': 'a'})
        doc.name = 'root'

        self.session.persist(doc)
        self.session.flush()

        docs = self.session.collection(TestNode).filter()

        self.assertEqual(len(reference_map), len(docs))
        self.assertEqual(reference_map['a'].id, doc.id)
        self.assertEqual(reference_map['a'].name, doc.name)

        doc = self.session.collection(TestNode).filter_one({'name': 'root'})

        self.assertEqual(reference_map['a'].id, doc.id)

    def test_commit_with_update_with_cascading(self):
        reference_map = self.__inject_data_with_cascading()

        doc = self.session.collection(TestNode).filter_one({'name': 'a'})
        doc.left.name = 'left'

        self.session.persist(doc)
        self.session.flush()

        docs = self.session.collection(TestNode).filter()

        self.assertEqual(len(reference_map), len(docs))
        self.assertEqual(reference_map['b'].id, doc.left.id)
        self.assertEqual(reference_map['b'].name, doc.left.name)

        doc = self.session.collection(TestNode).filter_one({'name': 'a'})

        self.assertEqual(reference_map['b'].id, doc.left.id)

    def test_commit_with_update_without_cascading(self):
        reference_map = self.__mock_data_without_cascading()

        developer_collection = self.session.collection(Developer)
        computer_collection = self.session.collection(Computer)

        self.session.persist(reference_map['d1'], reference_map['c1'])
        self.session.flush()

        self.assertEqual(1, len(developer_collection.filter()))
        self.assertEqual(1, len(computer_collection.filter()))

        developer = developer_collection.filter_one({'name': 'Shiroyuki'})
        developer.computer.name = 'MacBook Pro'

        self.session.persist(developer)
        self.session.flush()

        record = self.session._uow.retrieve_record(developer.computer)

        self.assertEqual(Record.STATUS_CLEAN, record.status)

        raw_data = computer_collection._api.find_one({'_id': reference_map['c1'].id})

        self.assertNotEqual(raw_data['name'], developer.computer.name)

    def test_commit_with_delete(self):
        reference_map = self.__inject_data_with_cascading()

        collection = self.session.collection(TestNode)
        doc_g      = collection.filter_one({'name': 'g'})

        self.session.delete(doc_g)
        self.session.flush()

        self.assertEqual(len(reference_map) - 1, len(collection.filter()))

    def test_commit_with_delete_with_cascading(self):
        reference_map = self.__inject_data_with_cascading()

        collection = self.session.collection(TestNode)
        doc_a      = collection.filter_one({'name': 'a'})

        self.session.delete(doc_a)
        self.session.flush()

        self.assertEqual(len(reference_map) - 4, len(collection.filter()))

    def test_commit_with_delete_with_cascading_with_some_dependency_left(self):
        reference_map     = self.__inject_data_with_cascading()
        expected_max_size = len(reference_map) + 1

        collection = self.session.collection(TestNode)

        # Added an extra node that relies on node "f" without using the collection.
        collection._api.insert({'left': None, 'right': reference_map['f'].id, 'name': 'extra'})

        doc_h = collection.filter_one({'name': 'h'})

        self.session.delete(doc_h)
        self.session.flush()

        self.assertEqual(
            expected_max_size - 1,
            len(collection.filter()),
            'Expected for %s nodes remaining' % expected_max_size
        )

    def test_commit_with_delete_with_cascading_with_some_unsupervised_dependency_left(self):
        reference_map     = self.__inject_data_with_cascading()
        expected_max_size = len(reference_map) + 1

        collection = self.session.collection(TestNode)

        # Added an extra node that relies on node "f" without using the collection.
        collection._api.insert({'left': None, 'right': reference_map['f'].id, 'name': 'extra'})

        self.session.delete(reference_map['e'], reference_map['h'])
        self.session.flush()

        self.assertEqual(expected_max_size - 2, len(collection.filter()))

    def test_commit_with_delete_with_cascading_with_no_dependency_left(self):
        reference_map = self.__inject_data_with_cascading()

        collection = self.session.collection(TestNode)

        self.session.delete(reference_map['e'], reference_map['h'])
        self.session.flush()

        self.assertEqual(len(reference_map) - 3, len(collection.filter()))

    def __inject_data_with_cascading(self):
        reference_map = {}

        reference_map['g'] = TestNode('g', None, None)
        reference_map['f'] = TestNode('f', None, None)
        reference_map['e'] = TestNode('e', None, reference_map['f'])
        reference_map['d'] = TestNode('d', None, None)
        reference_map['c'] = TestNode('c', reference_map['d'], None)
        reference_map['b'] = TestNode('b', None, reference_map['d'])
        reference_map['a'] = TestNode('a', reference_map['b'], reference_map['c'])
        reference_map['h'] = TestNode('h', reference_map['f'], None)

        self.session.persist(reference_map['a'], reference_map['e'], reference_map['g'], reference_map['h'])
        self.session.flush()

        return reference_map

    def __mock_data_without_cascading(self):
        reference_map = {}

        reference_map['c1'] = Computer('MacBook Air')
        reference_map['d1'] = Developer('Shiroyuki', reference_map['c1'])

        return reference_map