# HG changeset patch # User Sylvain Thénault # Date 1281109760 -7200 # Node ID 62011f82c386e3b41988db718048bb4d4c04a671 # Parent d7cef08aad2757664291bd7ddad877f69c8541a9# Parent aa7402e998a1af52dd142d5da6923a3493d4e7b0 backport stable diff -r d7cef08aad27 -r 62011f82c386 doc/book/en/devrepo/testing.rst --- a/doc/book/en/devrepo/testing.rst Wed Aug 04 11:16:40 2010 +0200 +++ b/doc/book/en/devrepo/testing.rst Fri Aug 06 17:49:20 2010 +0200 @@ -145,7 +145,7 @@ connection from another ! Email notifications tests -------------------------- +````````````````````````` When running tests potentially generated e-mails are not really sent but is found in the list `MAILBOX` of module @@ -212,6 +212,21 @@ auto_populate cannot guess by itself; these must yield resultsets against which views may be selected. +Testing with other cubes +------------------------ + +Sometimes a small component cannot be tested all by itself, so one +needs to specify other cubes to be used as part of the the unit test +suite. This is handled by the ``bootstrap_cubes`` file located under +``mycube\test\data``. One example from the `preview` cube:: + + card, file, preview + +The format is: + +* possibly several empy lines or lines starting with ``#`` (comment lines) +* one line containing a coma separated list of cube names. + Test APIS --------- diff -r d7cef08aad27 -r 62011f82c386 hooks/syncschema.py --- a/hooks/syncschema.py Wed Aug 04 11:16:40 2010 +0200 +++ b/hooks/syncschema.py Fri Aug 06 17:49:20 2010 +0200 @@ -104,6 +104,28 @@ session.info('added index on %s(%s)', table, column) +def insert_rdef_on_subclasses(session, eschema, rschema, rdefdef, props): + # XXX 'infered': True/False, not clear actually + props.update({'constraints': rdefdef.constraints, + 'description': rdefdef.description, + 'cardinality': rdefdef.cardinality, + 'permissions': rdefdef.get_permissions(), + 'order': rdefdef.order, + 'infered': False, 'eid': None + }) + cstrtypemap = ss.cstrtype_mapping(session) + groupmap = group_mapping(session) + object = rschema.schema.eschema(rdefdef.object) + for specialization in eschema.specialized_by(False): + if (specialization, rdefdef.object) in rschema.rdefs: + continue + print 'adding infered', specialization, rschema.type, object + sperdef = RelationDefinitionSchema(specialization, rschema, + object, props) + ss.execschemarql(session.execute, sperdef, + ss.rdef2rql(sperdef, cstrtypemap, groupmap)) + + def check_valid_changes(session, entity, ro_attrs=('name', 'final')): errors = {} # don't use getattr(entity, attr), we would get the modified value if any @@ -454,25 +476,7 @@ # if relation type has been inserted in the same transaction, its final # attribute is still set to False, so we've to ensure it's False rschema.final = True - # XXX 'infered': True/False, not clear actually - props.update({'constraints': rdefdef.constraints, - 'description': rdefdef.description, - 'cardinality': rdefdef.cardinality, - 'constraints': rdefdef.constraints, - 'permissions': rdefdef.get_permissions(), - 'order': rdefdef.order, - 'infered': False, 'eid': None - }) - cstrtypemap = ss.cstrtype_mapping(session) - groupmap = group_mapping(session) - object = schema.eschema(rdefdef.object) - for specialization in eschema.specialized_by(False): - if (specialization, rdefdef.object) in rschema.rdefs: - continue - sperdef = RelationDefinitionSchema(specialization, rschema, - object, props) - ss.execschemarql(session.execute, sperdef, - ss.rdef2rql(sperdef, cstrtypemap, groupmap)) + insert_rdef_on_subclasses(session, eschema, rschema, rdefdef, props) # set default value, using sql for performance and to avoid # modification_date update if default: @@ -514,6 +518,9 @@ # first occurence of "Subject relation Something" whatever Something if len(rschema.objects(rdefdef.subject)) == 1: add_inline_relation_column(session, rdefdef.subject, rtype) + eschema = schema[rdefdef.subject] + insert_rdef_on_subclasses(session, eschema, rschema, rdefdef, + {'composite': entity.composite}) else: # need to create the relation if no relation definition in the # schema and if it has not been added during other event of the same diff -r d7cef08aad27 -r 62011f82c386 server/migractions.py --- a/server/migractions.py Wed Aug 04 11:16:40 2010 +0200 +++ b/server/migractions.py Fri Aug 06 17:49:20 2010 +0200 @@ -378,9 +378,13 @@ for gname in newgroups: if not confirm or self.confirm('Grant %s permission of %s to %s?' % (action, erschema, gname)): - self.rqlexec('SET T %s G WHERE G eid %%(x)s, T eid %s' - % (perm, teid), - {'x': gm[gname]}, ask_confirm=False) + try: + self.rqlexec('SET T %s G WHERE G eid %%(x)s, T eid %s' + % (perm, teid), + {'x': gm[gname]}, ask_confirm=False) + except KeyError: + self.error('can grant %s perm to unexistant group %s', + action, gname) # handle rql expressions newexprs = dict((expr.expression, expr) for expr in erschema.get_rqlexprs(action)) for expreid, expression in self.rqlexec('Any E, EX WHERE T %s E, E expression EX, ' @@ -876,7 +880,15 @@ self.sqlexec('UPDATE %s_relation SET eid_to=%s WHERE eid_to=%s' % (rtype, new.eid, oldeid), ask_confirm=False) # delete relations using SQL to avoid relations content removal - # triggered by schema synchronization hooks + # triggered by schema synchronization hooks. Should add deleted eids + # into pending eids else we may get some validation error on commit + # since integrity hooks may think some required relation is + # missing... + pending = self.session.transaction_data.setdefault('pendingeids', set()) + for eid, in self.sqlexec('SELECT cw_eid FROM cw_CWRelation ' + 'WHERE cw_from_entity=%(eid)s OR cw_to_entity=%(eid)s', + {'eid': oldeid}, ask_confirm=False): + pending.add(eid) self.sqlexec('DELETE FROM cw_CWRelation ' 'WHERE cw_from_entity=%(eid)s OR cw_to_entity=%(eid)s', {'eid': oldeid}, ask_confirm=False) @@ -911,10 +923,15 @@ self.commit() gmap = self.group_mapping() cmap = self.cstrtype_mapping() + done = set() for rdef in rschema.rdefs.itervalues(): if not (reposchema.has_entity(rdef.subject) and reposchema.has_entity(rdef.object)): continue + # symmetric relations appears twice + if (rdef.subject, rdef.object) in done: + continue + done.add( (rdef.subject, rdef.object) ) self._set_rdef_eid(rdef) ss.execschemarql(execute, rdef, ss.rdef2rql(rdef, cmap, gmap)) diff -r d7cef08aad27 -r 62011f82c386 server/serverctl.py --- a/server/serverctl.py Wed Aug 04 11:16:40 2010 +0200 +++ b/server/serverctl.py Fri Aug 06 17:49:20 2010 +0200 @@ -71,13 +71,13 @@ 'on the database:') print special_privs print - default_user = source.get('db-user', os.environ.get('USER', '')) - user = raw_input('Connect as user ? [%r]: ' % default_user) - user = user or default_user - if user == source.get('db-user') and source.get('db-password'): - password = source['db-password'] - else: - password = getpass('password: ') + default_user = source.get('db-user', os.environ.get('USER', '')) + user = raw_input('Connect as user ? [%r]: ' % default_user) + user = user or default_user + if user == source.get('db-user') and source.get('db-password'): + password = source['db-password'] + else: + password = getpass('password: ') else: user = password = None extra_args = source.get('db-extra-arguments') diff -r d7cef08aad27 -r 62011f82c386 server/session.py --- a/server/session.py Wed Aug 04 11:16:40 2010 +0200 +++ b/server/session.py Fri Aug 06 17:49:20 2010 +0200 @@ -1025,7 +1025,7 @@ def __init__(self, repo, cnxprops=None): super(InternalSession, self).__init__(InternalManager(), repo, cnxprops, _id='internal') - self.user.req = self # XXX remove when "vreg = user.req.vreg" hack in entity.py is gone + self.user._cw = self # XXX remove when "vreg = user._cw.vreg" hack in entity.py is gone self.cnxtype = 'inmemory' self.disable_hook_categories('integrity') diff -r d7cef08aad27 -r 62011f82c386 web/views/primary.py --- a/web/views/primary.py Wed Aug 04 11:16:40 2010 +0200 +++ b/web/views/primary.py Fri Aug 06 17:49:20 2010 +0200 @@ -130,7 +130,7 @@ display_attributes = [] for rschema, _, role, dispctrl in self._section_def(entity, 'attributes'): vid = dispctrl.get('vid', 'reledit') - if rschema.final or vid == 'reledit': + if rschema.final or vid == 'reledit' or dispctrl.get('rtypevid'): value = entity.view(vid, rtype=rschema.type, role=role) else: rset = self._relation_rset(entity, rschema, role, dispctrl)