test_PyModel.py :  » Database » Modeling-Framework » Modeling-0.9 » Modeling » tests » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Database » Modeling Framework 
Modeling Framework » Modeling 0.9 » Modeling » tests » test_PyModel.py
#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-
#-----------------------------------------------------------------------------
# Modeling Framework: an Object-Relational Bridge for python
#
# Copyright (c) 2001-2004 Sbastien Bigaret <sbigaret@users.sourceforge.net>
# All rights reserved.
#
# This file is part of the Modeling Framework.
#
# This code is distributed under a "3-clause BSD"-style license;
# see the LICENSE file for details.
#-----------------------------------------------------------------------------

"""
Tests for PyModel

"""

import unittest
if __name__ == "__main__":
  import utils, sys
  utils.fixpath()
from Modeling.PyModel import *

class TestPyModel(unittest.TestCase):
  """
  Tests for PyModel
  """
  def checkEntitiesProperties(self, entities):
    """
    For each entity in 'entities', check that its attributes and
    relationships entity() points to it. Also check that the relationships'
    destination entity is not None.
    See in particular the comment in updateComponent() for an explanation
    """
    for e in entities:
      for a in e.attributes():
        self.assertEqual(a.entity(), e)
      for r in e.relationships():
        self.assertEqual(r.entity(), e)
        self.failUnless(r.destinationEntity(),'%s.%s.destinationEntity() is None'%(e.name(),r.name()))
        
  
  def check_model(self, model):
    """
    This method tests that:

      - checkEntitiesProperties() succeeds,

      - SalesClerk has 2 relationships,

      - for Employee and SalesClerk, relationships 'toStore' and 'toMarks'
        have the correct multiplicity, that their source and destination
        attributes are correct, and that their destination entities are correct
        
    """
    emp=model.component.entityNamed('Employee')
    sc=model.component.entityNamed('SalesClerk')
    store=model.component.entityNamed('Store')
    mark=model.component.entityNamed('Mark')

    self.checkEntitiesProperties((emp,sc,store,mark))

    self.assertEqual(len(sc.relationships()), 2)
    
    def check(self, toStore, toMarks, store, mark):
      self.failUnless(toStore.isToOne())
      self.failUnless(toMarks.isToMany())
      self.assertEqual(toStore.destinationEntity(), store)
      self.assertEqual(toMarks.destinationEntity(), mark)

    # Check toStore and toMarks for Employee
    toStore=emp.propertyNamed('toStore')
    fkStore=emp.propertyNamed('fkStore')
    toMarks=emp.propertyNamed('toMarks')
    check(self, toStore, toMarks, store, mark)
    self.failIf(fkStore not in toStore.sourceAttributes())
    self.failIf(store.propertyNamed('id') not in toStore.destinationAttributes())
    self.failIf(emp.propertyNamed('id') not in toMarks.sourceAttributes())
    self.failIf(mark.propertyNamed('fkEmployee') not in toMarks.destinationAttributes())
    self.failIf(fkStore.isRequired()!=toStore.multiplicityLowerBound(), '%i != %i'%(fkStore.isRequired(),toStore.multiplicityLowerBound()))

    # Check toStore and toMarks for SalesClerk
    toStore=sc.propertyNamed('toStore')
    fkStore=sc.propertyNamed('fkStore')
    toMarks=sc.propertyNamed('toMarks')
    check(self, toStore, toMarks, store, mark)
    self.failIf(sc.propertyNamed('fkStore') not in toStore.sourceAttributes())
    self.failIf(store.propertyNamed('id') not in toStore.destinationAttributes())
    self.failIf(sc.propertyNamed('id') not in toMarks.sourceAttributes())
    self.failIf(mark.propertyNamed('fkEmployee') not in toMarks.destinationAttributes())
    self.failIf(fkStore.isRequired()!=toStore.multiplicityLowerBound())

  def check_inverse_rels(self, model):
    """
    This method checks that Employee.toStore (resp. Employee.toMarks) is the
    inverse relationship for Store.toEmployees (resp. Mark.toEmployee)
    """
    emp=model.component.entityNamed('Employee')
    sc=model.component.entityNamed('SalesClerk')
    store=model.component.entityNamed('Store')
    mark=model.component.entityNamed('Mark')

    self.failUnless(mark.relationshipNamed('toEmployee').inverseRelationship()==emp.propertyNamed('toMarks'))
    self.failUnless(store.relationshipNamed('toEmployees').inverseRelationship()==emp.propertyNamed('toStore'))

    toEmployee=mark.relationshipNamed('toEmployee')
    self.failIf(mark.propertyNamed('fkEmployee').isRequired()!=toEmployee.multiplicityLowerBound())

  ## BEGIN tests
  def setUp(self):
    self.model = Model('StoreEmployees',adaptorName='Postgresql')
    self.model.version='0.1'
    Entity.defaults['properties'] = [
      APrimaryKey('id', isClassProperty=0, isRequired=1, doc='Default PK')
      ]
    AString.defaults['width'] = 20

  def test_01_attr(self):
    "[PyModel] entity w/ attributes and default pk"
    model = self.model
    model.entities = [
      Entity('Employee',
             properties=[ AString('lastName', isRequired=1, usedForLocking=1), 
                          AString('firstName', isRequired=1, width=50,
                                  usedForLocking=1),
                          ] ),
      ]
    model.build()
    emp=model.component.entityNamed('Employee')
    self.checkEntitiesProperties((emp,))
    self.assertEqual(emp.attributeNamed('lastName').width(), 20)
    self.assertEqual(emp.attributeNamed('firstName').width(), 50)
    self.assertEqual(emp.attributeNamed('firstName').isRequired(), 1)
    self.assertEqual(emp.primaryKeyAttributeNames(), ['id']) # default PK
    self.failIf(emp.primaryKeyAttributes()[0].isClassProperty())
    self.assertEqual(emp.primaryKeyAttributes()[0].defaultValue(), None)
   
  def test_01b_attr(self):
    "[PyModel] attributes' props can be reassigned before build()"
    # bug #842698
    model = self.model
    model.entities = [
      Entity('Employee', properties=[ AString('firstName', width=30) ] ),
      ]
    attr=model.entityNamed('Employee').attributeNamed('firstName')
    attr.width=50
    attr.isRequired=1
    attr.usedForLocking=1
    model.build()
    emp=model.component.entityNamed('Employee')
    self.checkEntitiesProperties((emp,))
    firstName=emp.attributeNamed('firstName')
    self.assertEqual(firstName.width(), 50)
    self.assertEqual(firstName.isRequired(), 1)
    self.failUnless(firstName in emp.attributesUsedForLocking())
    
  def test_02_pk(self):
    "[PyModel] entity w/ pk"
    model = self.model
    # we also use the same name 'id'
    model.entities = [
      Entity('Employee',
             properties=[ APrimaryKey('id', isClassProperty=1, isRequired=1,
                                      doc='SalesClerk PK') ] ), ]
    model.build()
    emp=model.component.entityNamed('Employee')
    self.checkEntitiesProperties((emp,))
    self.assertEqual(emp.primaryKeyAttributeNames(), ['id'])
    self.assertEqual(emp.primaryKeyAttributes()[0].comment(), 'SalesClerk PK')
    self.failUnless(emp.primaryKeyAttributes()[0].isClassProperty())
    self.assertEqual(emp.primaryKeyAttributes()[0].defaultValue(), 0)
        
  def test_03_attrs_and_inheritance(self):
    "[PyModel] attrs_and_inheritance"
    model = self.model
    model.entities = [
      Entity('Employee',
             properties=[ AString('lastName', isRequired=1, usedForLocking=1), 
                          AString('firstName', isRequired=1, width=50,
                                  usedForLocking=1),
                          ] ),
      Entity('SalesClerk', parent='Employee',
             properties=[ APrimaryKey('id', isClassProperty=1, isRequired=1,
                                      # NB: avec ID & Rels c'est une erreur!
                                      doc='SalesClerk PK'),
                          AString('firstName', isRequired=1, width=5,
                                  usedForLocking=1),
                          ] ),
      Entity('Executive', parent='Employee',
             properties=[ AString('officeLocation', width=5), ] ),
      ]
    model.build()
    emp=model.component.entityNamed('Employee')
    sc=model.component.entityNamed('SalesClerk')
    ex=model.component.entityNamed('Executive')

    self.checkEntitiesProperties((emp,sc,ex))

    self.assertEqual(emp.primaryKeyAttributeNames(), ['id'])
    self.assertEqual(emp.primaryKeyAttributeNames(), ['id']) # PK overriden
    self.assertEqual(emp.primaryKeyAttributeNames(), ['id'])
    self.failIf(emp.primaryKeyAttributes()[0].isClassProperty())
    self.failIf(ex.primaryKeyAttributes()[0].isClassProperty())
    self.failUnless(sc.primaryKeyAttributes()[0].isClassProperty())
    # Propagation of attributes
    self.failIf([a for a in emp.attributesNames()
                 if a not in sc.attributesNames()])
    self.failIf([a for a in emp.attributesNames()
                 if a not in ex.attributesNames()])
    self.assertEqual(len(sc.attributes()),3)
    self.assertEqual(len(ex.attributes()),4)
    #
    self.assertEqual(emp.attributeNamed('firstName').width(), 50)
    self.assertEqual(sc.attributeNamed('firstName').width(), 5)

    self.assertEqual(emp.attributeNamed('id').entity(), emp)
    self.assertEqual(sc.attributeNamed('id').entity(), sc)
    self.assertEqual(ex.attributeNamed('id').entity(), ex)

  def test_04_fully_qualified_relationships_no_inverse(self):
    "[PyModel] fully_qualified_relationships"
    model = self.model
    model.entities = [
      Entity('Employee',
             properties=[ AForeignKey('fkStore'),
                          RToOne('toStore', 'Store',src='fkStore',dst='id',
                                 delete='deny'),
                          RToMany('toMarks', 'Mark',src='id',dst='fkEmployee',
                                  delete='cascade'),
                          ] ),
      Entity('SalesClerk', parent='Employee'),
      Entity('Mark', properties=[ AForeignKey('fkEmployee') ]),
      Entity('Store'),
      ]
    model.build()
    self.check_model(model)
    self.failIf(model.component.entityNamed('Employee').propertyNamed('toStore').deleteRule()!='deny')
    self.failIf(model.component.entityNamed('Employee').propertyNamed('toMarks').deleteRule()!='cascade')
    
  def test_05_unqualified_relationships_no_inverse(self):
    "[PyModel] unqualified_relationships_no_inverse"
    model = self.model
    model.entities = [
      Entity('Employee',
             properties=[ 
                          RToMany('toMarks', 'Mark'),
                          RToOne('toStore', 'Store'),
                          ] ),
      Entity('SalesClerk', parent='Employee'),
      Entity('Mark'),
      Entity('Store'),
      ]
    model.build()
    self.check_model(model)

    emp=model.component.entityNamed('Employee')
    sc=model.component.entityNamed('SalesClerk')
    store=model.component.entityNamed('Store')
    mark=model.component.entityNamed('Mark')


    self.assertEqual(len(sc.relationships()), 2)

    # Check that each entity has the expected number of attributes
    self.assertEqual(len(emp.attributes()), 2)   # id + fk
    self.assertEqual(len(sc.attributes()), 2)    # id + fk
    self.assertEqual(len(store.attributes()), 1) # id
    self.assertEqual(len(mark.attributes()), 2)  # id + fk
    
    self.failUnless(emp.attributeNamed('fkStore'))
    self.failUnless(sc.attributeNamed('fkStore'))
    self.failUnless(mark.attributeNamed('fkEmployee'))
    
  # test_06 qualified & unqualified
  # model = self.model
  # model.entities = [
  #   Entity('Employee',
  #          properties=[ AForeignKey('fkStore'),
  #                       #RToOne('toStore', 'Store',src='fkStore',dst='id'),
  #                       RToMany('toMarks', 'Mark',src='id',dst='fkEmployee'),
  #                       ] ),
  #   Entity('SalesClerk', parent='Employee'),
  #   Entity('Mark',
  #         properties=[ AForeignKey('fkEmployee'),
  #                      #RToOne('toEmployee','Employee',inverse='toMarks')
  #                      ]
  #          ),
  #   Entity('Store',
  #         properties=[RToMany('toEmployees','Employee')#,src='id',dst='fkStore')
  #                     ]#,inverse='toStore')]
  #          ),
  #   # NB: quid si inverse='ghjgh'? --> TBD test!
  #   ]

  def test_07_relationships_with_inverse(self):
    "[PyModel] qualified_relationships_with_inverse"
    self.model.entities = [
      Entity('Employee',
             properties=[ AForeignKey('fkStore'),
                          RToOne('toStore', 'Store',src='fkStore',dst='id'),
                          RToMany('toMarks', 'Mark',src='id',dst='fkEmployee'),
                          ] ),
      Entity('SalesClerk', parent='Employee'),
      Entity('Mark',
            properties=[ AForeignKey('fkEmployee'),
                         RToOne('toEmployee','Employee',inverse='toMarks')
                         ]
             ),
      Entity('Store',
            properties=[RToMany('toEmployees','Employee',inverse='toStore',
                                )#src='id',dst='fkStore')
                        ]#,inverse='toStore')]
             ),
      # NB: quid si inverse='ghjgh'? --> TBD test!
      ]
    self.model.build()
    self.check_model(self.model)
    self.check_inverse_rels(self.model)
    #
    self.setUp()
    self.model.entities = [
      Entity('Employee',
             properties=[ RToOne('toStore', 'Store'),#,src='fkStore',dst='id'),
                          RToMany('toMarks', 'Mark'),#,src='id',dst='fkEmployee'),
                          ] ),
      Entity('SalesClerk', parent='Employee'),
      Entity('Mark',
            properties=[ RToOne('toEmployee','Employee',inverse='toMarks') ]
             ),
      Entity('Store',
            properties=[RToMany('toEmployees','Employee',inverse='toStore',)]
             ),
      ]
    self.model.build()
    self.check_model(self.model)
    self.check_inverse_rels(self.model)

    # Automatic creation of source + destination key
    # NOTE: this fails by now, because the feature is considered not desirable
    #       for now.
    self.setUp()
    self.model.entities = [
      Entity('Employee',
             properties=[ RToOne('toStore', 'Store',src='fkStore',dst='id'),
                          RToMany('toMarks', 'Mark',src='id',dst='fkEmployee'),
                          ] ),
      Entity('SalesClerk', parent='Employee'),
      Entity('Mark',
            properties=[ RToOne('toEmployee','Employee',inverse='toMarks') ]
             ),
      Entity('Store',
            properties=[RToMany('toEmployees','Employee',inverse='toStore',)]
             ),
      ]
    self.assertRaises(ValueError, self.model.build)
    #self.check_model(self.model)
    #self.check_inverse_rels(self.model)

  def test_08_qualified_relationships_with_inverse(self):
    "[PyModel] unqualified_relationships_with_inverse"
    # Simple declaration
    model = self.model
    model.entities = [
      Entity('Employee'),
      Entity('SalesClerk', parent='Employee'),
      Entity('Mark'),
      Entity('Store'),
      ]
    model.associations = [
      Association('Employee', 'Store'),
      Association('Mark', 'Employee'),
      ]
    model.build()
    self.check_model(self.model)
    self.check_inverse_rels(self.model)
    #
    self.setUp()
    model=self.model
    model.entities = [
      Entity('Employee'),
      Entity('SalesClerk', parent='Employee'),
      Entity('Mark'),
      Entity('Store'),
      ]
    model.associations = [
      Association('Employee', 'Store',
                  relations=['toStore', 'toEmployees'],
                  multiplicity=[ [1, 1], [0, None] ],
                  keys=['fkStore', 'id'],
                  delete=['nullify', 'deny'],
                  ),
      Association('Mark', 'Employee',
                  relations=['toEmployee', 'toMarks'],
                  multiplicity=[ [1, 1], [0, None] ],
                  keys=['fkEmployee', 'id'],
                  delete=['nullify', 'cascade']
                  ),
      ]
    model.build()
    self.check_model(model)
    self.check_inverse_rels(model)
    # check that delete rules were correctly set
    emp=model.component.entityNamed('Employee')
    mark=model.component.entityNamed('Mark')
    store=model.component.entityNamed('Store')

    # check that the fk are set as expected
    self.failUnless(emp.propertyNamed('fkStore'))
    self.failUnless(mark.propertyNamed('fkEmployee'))
    self.failIf(emp.propertyNamed('toStore').deleteRule()!='nullify')
    self.failUnless(emp.propertyNamed('toStore').isMandatory()) #841315
    self.failIf(emp.propertyNamed('toMarks').deleteRule()!='cascade')
    self.failIf(store.propertyNamed('toEmployees').deleteRule()!='deny')
    self.failIf(mark.propertyNamed('toEmployee').deleteRule()!='nullify')
    self.failUnless(mark.propertyNamed('toEmployee').isMandatory())

    # Check Association's defaults
    ass_def_delete=Association.defaults['delete']
    try:
      Association.defaults['delete']=['deny', 'cascade']
      self.setUp()
      model=self.model
      model.entities = [ Entity('Employee'), Entity('Mark'), Entity('Store'),
                         Entity('SalesClerk', parent='Employee'), ]
      model.associations = [
        Association('Employee', 'Store'), Association('Mark', 'Employee'), ]
      model.build()
      self.check_model(model)
      self.check_inverse_rels(model)
      emp=model.component.entityNamed('Employee')
      mark=model.component.entityNamed('Mark')
      store=model.component.entityNamed('Store')
      self.failIf(emp.propertyNamed('toStore').deleteRule()!='deny')
      self.failIf(emp.propertyNamed('toMarks').deleteRule()!='cascade')
      self.failIf(store.propertyNamed('toEmployees').deleteRule()!='cascade')
      self.failIf(mark.propertyNamed('toEmployee').deleteRule()!='deny')
    finally:
      Association.defaults['delete']=ass_def_delete # restore
    
    # Association's defaults are NOT related to RToOne/RToMany defaults
    toOne_def_delete=RToOne.defaults['delete']
    toMany_def_delete=RToMany.defaults['delete']
    RToOne.defaults['delete']=['deny']
    RToOne.defaults['delete']=['cascade']
    try:
      self.setUp()
      model=self.model
      model.entities = [ Entity('Employee'), Entity('Mark'), Entity('Store'),
                         Entity('SalesClerk', parent='Employee'), ]
      model.associations = [
        Association('Employee', 'Store'), Association('Mark', 'Employee'), ]
      model.build()
      self.check_model(model)
      self.check_inverse_rels(model)
      emp=model.component.entityNamed('Employee')
      mark=model.component.entityNamed('Mark')
      store=model.component.entityNamed('Store')
      self.failIf(emp.propertyNamed('toStore').deleteRule()=='deny')
      self.failIf(emp.propertyNamed('toMarks').deleteRule()=='cascade')
      self.failIf(store.propertyNamed('toEmployees').deleteRule()=='cascade')
      self.failIf(mark.propertyNamed('toEmployee').deleteRule()=='deny')
    finally:
      RToOne.defaults['delete']=toOne_def_delete
      RToOne.defaults['delete']=toMany_def_delete

  def test_09_cannot_rebuild(self):
    "[PyModel] build() should be called once, no more"
    model = self.model
    model.entities = [
      Entity('Employee',
             properties=[ AString('lastName'),
                          AString('firstName'),
                          ] ),
      ]
    model.build()
    self.failUnless(model.is_built)
    self.assertRaises(RuntimeError, model.build)

  def test_10_bound_relationships(self):
    "[PyModel] bug #1023234-relationships with an finite upper bound"
    model = self.model
    model.entities = [
      Entity('Employee'), Entity('Store'),
      ]
    model.associations = [ Association('Employee', 'Store',
                                       multiplicity = [ [0,1], [0,2] ] )
      ]
    model.build()
    
def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(TestPyModel, "test_"))
    return suite

if __name__ == "__main__":
  verbose='-V' in sys.argv and 'Y' or ('-v' in sys.argv and 1 or 0)
  errs = utils.run_suite(test_suite(), verbosity=verbose)
  sys.exit(errs and 1 or 0)

## TBD: test init/build sur elements, p.ex. RToOne + cardinality, etc.
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.