ticket47490_test.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. '''
  2. Created on Nov 7, 2013
  3. @author: tbordaz
  4. '''
  5. import os
  6. import sys
  7. import time
  8. import ldap
  9. import logging
  10. import socket
  11. import time
  12. import logging
  13. import pytest
  14. import re
  15. from lib389 import DirSrv, Entry, tools
  16. from lib389.tools import DirSrvTools
  17. from lib389._constants import *
  18. from constants import *
  19. logging.getLogger(__name__).setLevel(logging.DEBUG)
  20. log = logging.getLogger(__name__)
  21. installation_prefix = None
  22. TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
  23. ENTRY_DN = "cn=test_entry, %s" % SUFFIX
  24. MUST_OLD = "(postalAddress $ preferredLocale)"
  25. MUST_NEW = "(postalAddress $ preferredLocale $ telexNumber)"
  26. MAY_OLD = "(postalCode $ street)"
  27. MAY_NEW = "(postalCode $ street $ postOfficeBox)"
  28. def _ds_create_instance(args):
  29. # create the standalone instance
  30. return tools.DirSrvTools.createInstance(args, verbose=False)
  31. def _ds_rebind_instance(dirsrv):
  32. args_instance['prefix'] = dirsrv.prefix
  33. args_instance['backupdir'] = dirsrv.backupdir
  34. args_instance['newrootdn'] = dirsrv.binddn
  35. args_instance['newrootpw'] = dirsrv.bindpw
  36. args_instance['newhost'] = dirsrv.host
  37. args_instance['newport'] = dirsrv.port
  38. args_instance['newinstance'] = dirsrv.serverId
  39. args_instance['newsuffix'] = SUFFIX
  40. args_instance['no_admin'] = True
  41. return tools.DirSrvTools.createInstance(args_instance)
  42. class TopologyMasterConsumer(object):
  43. def __init__(self, master, consumer):
  44. self.master = master
  45. self.consumer = consumer
  46. def pattern_errorlog(file, log_pattern):
  47. try:
  48. pattern_errorlog.last_pos += 1
  49. except AttributeError:
  50. pattern_errorlog.last_pos = 0
  51. found = None
  52. log.debug("_pattern_errorlog: start at offset %d" % pattern_errorlog.last_pos)
  53. file.seek(pattern_errorlog.last_pos)
  54. # Use a while true iteration because 'for line in file: hit a
  55. # python bug that break file.tell()
  56. while True:
  57. line = file.readline()
  58. log.debug("_pattern_errorlog: [%d] %s" % (file.tell(), line))
  59. found = log_pattern.search(line)
  60. if ((line == '') or (found)):
  61. break
  62. log.debug("_pattern_errorlog: end at offset %d" % file.tell())
  63. pattern_errorlog.last_pos = file.tell()
  64. return found
  65. def _oc_definition(oid_ext, name, must=None, may=None):
  66. oid = "1.2.3.4.5.6.7.8.9.10.%d" % oid_ext
  67. desc = 'To test ticket 47490'
  68. sup = 'person'
  69. if not must:
  70. must = MUST_OLD
  71. if not may:
  72. may = MAY_OLD
  73. new_oc = "( %s NAME '%s' DESC '%s' SUP %s AUXILIARY MUST %s MAY %s )" % (oid, name, desc, sup, must, may)
  74. return new_oc
  75. def add_OC(instance, oid_ext, name):
  76. new_oc = _oc_definition(oid_ext, name)
  77. instance.addSchema('objectClasses', new_oc)
  78. def mod_OC(instance, oid_ext, name, old_must=None, old_may=None, new_must=None, new_may=None):
  79. old_oc = _oc_definition(oid_ext, name, old_must, old_may)
  80. new_oc = _oc_definition(oid_ext, name, new_must, new_may)
  81. instance.delSchema('objectClasses', old_oc)
  82. instance.addSchema('objectClasses', new_oc)
  83. def trigger_schema_push(topology):
  84. """
  85. It triggers an update on the supplier. This will start a replication
  86. session and a schema push
  87. """
  88. try:
  89. trigger_schema_push.value += 1
  90. except AttributeError:
  91. trigger_schema_push.value = 1
  92. replace = [(ldap.MOD_REPLACE, 'telephonenumber', str(trigger_schema_push.value))]
  93. topology.master.modify_s(ENTRY_DN, replace)
  94. # wait 10 seconds that the update is replicated
  95. loop = 0
  96. while loop <= 10:
  97. try:
  98. ent = topology.consumer.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)", ['telephonenumber'])
  99. val = ent.telephonenumber or "0"
  100. if int(val) == trigger_schema_push.value:
  101. return
  102. # the expected value is not yet replicated. try again
  103. time.sleep(1)
  104. loop += 1
  105. log.debug("trigger_schema_push: receive %s (expected %d)" % (val, trigger_schema_push.value))
  106. except ldap.NO_SUCH_OBJECT:
  107. time.sleep(1)
  108. loop += 1
  109. @pytest.fixture(scope="module")
  110. def topology(request):
  111. '''
  112. This fixture is used to create a replicated topology for the 'module'.
  113. The replicated topology is MASTER -> Consumer.
  114. At the beginning, It may exists a master instance and/or a consumer instance.
  115. It may also exists a backup for the master and/or the consumer.
  116. Principle:
  117. If master instance exists:
  118. restart it
  119. If consumer instance exists:
  120. restart it
  121. If backup of master AND backup of consumer exists:
  122. create or rebind to consumer
  123. create or rebind to master
  124. restore master from backup
  125. restore consumer from backup
  126. else:
  127. Cleanup everything
  128. remove instances
  129. remove backups
  130. Create instances
  131. Initialize replication
  132. Create backups
  133. '''
  134. global installation_prefix
  135. if installation_prefix:
  136. args_instance['prefix'] = installation_prefix
  137. # Args for the master instance
  138. args_instance['newhost'] = HOST_MASTER
  139. args_instance['newport'] = PORT_MASTER
  140. args_instance['newinstance'] = SERVERID_MASTER
  141. args_master = args_instance.copy()
  142. # Args for the consumer instance
  143. args_instance['newhost'] = HOST_CONSUMER
  144. args_instance['newport'] = PORT_CONSUMER
  145. args_instance['newinstance'] = SERVERID_CONSUMER
  146. args_consumer = args_instance.copy()
  147. # Get the status of the backups
  148. backup_master = DirSrvTools.existsBackup(args_master)
  149. backup_consumer = DirSrvTools.existsBackup(args_consumer)
  150. # Get the status of the instance and restart it if it exists
  151. instance_master = DirSrvTools.existsInstance(args_master)
  152. if instance_master:
  153. DirSrvTools.stop(instance_master, timeout=10)
  154. DirSrvTools.start(instance_master, timeout=10)
  155. instance_consumer = DirSrvTools.existsInstance(args_consumer)
  156. if instance_consumer:
  157. DirSrvTools.stop(instance_consumer, timeout=10)
  158. DirSrvTools.start(instance_consumer, timeout=10)
  159. if backup_master and backup_consumer:
  160. # The backups exist, assuming they are correct
  161. # we just re-init the instances with them
  162. master = _ds_create_instance(args_master)
  163. consumer = _ds_create_instance(args_consumer)
  164. # restore master from backup
  165. DirSrvTools.stop(master, timeout=10)
  166. DirSrvTools.instanceRestoreFS(master, backup_master)
  167. DirSrvTools.start(master, timeout=10)
  168. # restore consumer from backup
  169. DirSrvTools.stop(consumer, timeout=10)
  170. DirSrvTools.instanceRestoreFS(consumer, backup_consumer)
  171. DirSrvTools.start(consumer, timeout=10)
  172. else:
  173. # We should be here only in two conditions
  174. # - This is the first time a test involve master-consumer
  175. # so we need to create everything
  176. # - Something weird happened (instance/backup destroyed)
  177. # so we discard everything and recreate all
  178. # Remove all the backups. So even if we have a specific backup file
  179. # (e.g backup_master) we clear all backups that an instance my have created
  180. if backup_master:
  181. DirSrvTools.clearInstanceBackupFS(dirsrv=instance_master)
  182. if backup_consumer:
  183. DirSrvTools.clearInstanceBackupFS(dirsrv=instance_consumer)
  184. # Remove all the instances
  185. if instance_master:
  186. DirSrvTools.removeInstance(instance_master)
  187. if instance_consumer:
  188. DirSrvTools.removeInstance(instance_consumer)
  189. # Create the instance
  190. master = _ds_create_instance(args_master)
  191. consumer = _ds_create_instance(args_consumer)
  192. #
  193. # Now prepare the Master-Consumer topology
  194. #
  195. # First Enable replication
  196. master.enableReplication(suffix=SUFFIX, role="master", replicaId=REPLICAID_MASTER)
  197. consumer.enableReplication(suffix=SUFFIX, role="consumer")
  198. # Initialize the supplier->consumer
  199. repl_agreement = master.agreement.create(consumer, SUFFIX, binddn=defaultProperties[REPLICATION_BIND_DN], bindpw=defaultProperties[REPLICATION_BIND_PW])
  200. if not repl_agreement:
  201. log.fatal("Fail to create a replica agreement")
  202. sys.exit(1)
  203. log.debug("%s created" % repl_agreement)
  204. master.agreement.init(SUFFIX, HOST_CONSUMER, PORT_CONSUMER)
  205. master.waitForReplInit(repl_agreement)
  206. # Check replication is working fine
  207. master.add_s(Entry((TEST_REPL_DN, {
  208. 'objectclass': "top person".split(),
  209. 'sn': 'test_repl',
  210. 'cn': 'test_repl'})))
  211. loop = 0
  212. while loop <= 10:
  213. try:
  214. ent = consumer.getEntry(TEST_REPL_DN, ldap.SCOPE_BASE, "(objectclass=*)")
  215. break
  216. except ldap.NO_SUCH_OBJECT:
  217. time.sleep(1)
  218. loop += 1
  219. # Time to create the backups
  220. DirSrvTools.stop(master, timeout=10)
  221. master.backupfile = DirSrvTools.instanceBackupFS(master)
  222. DirSrvTools.start(master, timeout=10)
  223. DirSrvTools.stop(consumer, timeout=10)
  224. consumer.backupfile = DirSrvTools.instanceBackupFS(consumer)
  225. DirSrvTools.start(consumer, timeout=10)
  226. #
  227. # Here we have two instances master and consumer
  228. # with replication working. Either coming from a backup recovery
  229. # or from a fresh (re)init
  230. # Time to return the topology
  231. return TopologyMasterConsumer(master, consumer)
  232. def test_ticket47490_init(topology):
  233. """
  234. Initialize the test environment
  235. """
  236. log.debug("test_ticket47490_init topology %r (master %r, consumer %r" % (topology, topology.master, topology.consumer))
  237. # the test case will check if a warning message is logged in the
  238. # error log of the supplier
  239. topology.master.errorlog_file = open(topology.master.errlog, "r")
  240. # This entry will be used to trigger attempt of schema push
  241. topology.master.add_s(Entry((ENTRY_DN, {
  242. 'objectclass': "top person".split(),
  243. 'sn': 'test_entry',
  244. 'cn': 'test_entry'})))
  245. def test_ticket47490_one(topology):
  246. """
  247. Summary: Extra OC Schema is pushed - no error
  248. If supplier schema is a superset (one extra OC) of consumer schema, then
  249. schema is pushed and there is no message in the error log
  250. State at startup:
  251. - supplier default schema
  252. - consumer default schema
  253. Final state
  254. - supplier +masterNewOCA
  255. - consumer +masterNewOCA
  256. """
  257. log.debug("test_ticket47490_one topology %r (master %r, consumer %r" % (topology, topology.master, topology.consumer))
  258. # update the schema of the supplier so that it is a superset of
  259. # consumer. Schema should be pushed
  260. add_OC(topology.master, 2, 'masterNewOCA')
  261. trigger_schema_push(topology)
  262. master_schema_csn = topology.master.getSchemaCSN()
  263. consumer_schema_csn = topology.consumer.getSchemaCSN()
  264. # Check the schemaCSN was updated on the consumer
  265. log.debug("test_ticket47490_one master_schema_csn=%s", master_schema_csn)
  266. log.debug("ctest_ticket47490_one onsumer_schema_csn=%s", consumer_schema_csn)
  267. assert master_schema_csn == consumer_schema_csn
  268. # Check the error log of the supplier does not contain an error
  269. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  270. res = pattern_errorlog(topology.master.errorlog_file, regex)
  271. assert res == None
  272. def test_ticket47490_two(topology):
  273. """
  274. Summary: Extra OC Schema is NOT pushed - error
  275. If consumer schema is a superset (one extra OC) of supplier schema, then
  276. schema is not pushed and there is a message in the error log
  277. State at startup
  278. - supplier +masterNewOCA
  279. - consumer +masterNewOCA
  280. Final state
  281. - supplier +masterNewOCA +masterNewOCB
  282. - consumer +masterNewOCA +consumerNewOCA
  283. """
  284. # add this OC on consumer. Supplier will no push the schema
  285. add_OC(topology.consumer, 1, 'consumerNewOCA')
  286. # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  287. time.sleep(2)
  288. add_OC(topology.master, 3, 'masterNewOCB')
  289. # now push the scheam
  290. trigger_schema_push(topology)
  291. master_schema_csn = topology.master.getSchemaCSN()
  292. consumer_schema_csn = topology.consumer.getSchemaCSN()
  293. # Check the schemaCSN was NOT updated on the consumer
  294. log.debug("test_ticket47490_two master_schema_csn=%s", master_schema_csn)
  295. log.debug("test_ticket47490_two consumer_schema_csn=%s", consumer_schema_csn)
  296. assert master_schema_csn != consumer_schema_csn
  297. # Check the error log of the supplier does not contain an error
  298. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  299. res = pattern_errorlog(topology.master.errorlog_file, regex)
  300. assert res
  301. def test_ticket47490_three(topology):
  302. """
  303. Summary: Extra OC Schema is pushed - no error
  304. If supplier schema is again a superset (one extra OC), then
  305. schema is pushed and there is no message in the error log
  306. State at startup
  307. - supplier +masterNewOCA +masterNewOCB
  308. - consumer +masterNewOCA +consumerNewOCA
  309. Final state
  310. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  311. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  312. """
  313. # Do an upate to trigger the schema push attempt
  314. # add this OC on consumer. Supplier will no push the schema
  315. add_OC(topology.master, 1, 'consumerNewOCA')
  316. # now push the scheam
  317. trigger_schema_push(topology)
  318. master_schema_csn = topology.master.getSchemaCSN()
  319. consumer_schema_csn = topology.consumer.getSchemaCSN()
  320. # Check the schemaCSN was NOT updated on the consumer
  321. log.debug("test_ticket47490_three master_schema_csn=%s", master_schema_csn)
  322. log.debug("test_ticket47490_three consumer_schema_csn=%s", consumer_schema_csn)
  323. assert master_schema_csn == consumer_schema_csn
  324. # Check the error log of the supplier does not contain an error
  325. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  326. res = pattern_errorlog(topology.master.errorlog_file, regex)
  327. assert res == None
  328. def test_ticket47490_four(topology):
  329. """
  330. Summary: Same OC - extra MUST: Schema is pushed - no error
  331. If supplier schema is again a superset (OC with more MUST), then
  332. schema is pushed and there is no message in the error log
  333. State at startup
  334. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  335. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  336. Final state
  337. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  338. +must=telexnumber
  339. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  340. +must=telexnumber
  341. """
  342. mod_OC(topology.master, 2, 'masterNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  343. trigger_schema_push(topology)
  344. master_schema_csn = topology.master.getSchemaCSN()
  345. consumer_schema_csn = topology.consumer.getSchemaCSN()
  346. # Check the schemaCSN was updated on the consumer
  347. log.debug("test_ticket47490_four master_schema_csn=%s", master_schema_csn)
  348. log.debug("ctest_ticket47490_four onsumer_schema_csn=%s", consumer_schema_csn)
  349. assert master_schema_csn == consumer_schema_csn
  350. # Check the error log of the supplier does not contain an error
  351. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  352. res = pattern_errorlog(topology.master.errorlog_file, regex)
  353. assert res == None
  354. def test_ticket47490_five(topology):
  355. """
  356. Summary: Same OC - extra MUST: Schema is NOT pushed - error
  357. If consumer schema is a superset (OC with more MUST), then
  358. schema is not pushed and there is a message in the error log
  359. State at startup
  360. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  361. +must=telexnumber
  362. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  363. +must=telexnumber
  364. Final state
  365. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  366. +must=telexnumber
  367. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  368. +must=telexnumber +must=telexnumber
  369. Note: replication log is enabled to get more details
  370. """
  371. # get more detail why it fails
  372. topology.master.enableReplLogging()
  373. # add telenumber to 'consumerNewOCA' on the consumer
  374. mod_OC(topology.consumer, 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  375. # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  376. time.sleep(2)
  377. add_OC(topology.master, 4, 'masterNewOCC')
  378. trigger_schema_push(topology)
  379. master_schema_csn = topology.master.getSchemaCSN()
  380. consumer_schema_csn = topology.consumer.getSchemaCSN()
  381. # Check the schemaCSN was NOT updated on the consumer
  382. log.debug("test_ticket47490_five master_schema_csn=%s", master_schema_csn)
  383. log.debug("ctest_ticket47490_five onsumer_schema_csn=%s", consumer_schema_csn)
  384. assert master_schema_csn != consumer_schema_csn
  385. #Check that replication logging display additional message about 'telexNumber' not being
  386. # required in the master schema
  387. # This message appears before 'must not be overwritten' so it should be check first
  388. regex = re.compile("Attribute telexNumber is not required in 'consumerNewOCA' of the local supplier schema")
  389. res = pattern_errorlog(topology.master.errorlog_file, regex)
  390. assert res != None
  391. # Check the error log of the supplier does not contain an error
  392. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  393. res = pattern_errorlog(topology.master.errorlog_file, regex)
  394. assert res != None
  395. def test_ticket47490_six(topology):
  396. """
  397. Summary: Same OC - extra MUST: Schema is pushed - no error
  398. If supplier schema is again a superset (OC with more MUST), then
  399. schema is pushed and there is no message in the error log
  400. State at startup
  401. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  402. +must=telexnumber
  403. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  404. +must=telexnumber +must=telexnumber
  405. Final state
  406. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  407. +must=telexnumber +must=telexnumber
  408. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  409. +must=telexnumber +must=telexnumber
  410. Note: replication log is enabled to get more details
  411. """
  412. # add telenumber to 'consumerNewOCA' on the consumer
  413. mod_OC(topology.master, 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  414. trigger_schema_push(topology)
  415. master_schema_csn = topology.master.getSchemaCSN()
  416. consumer_schema_csn = topology.consumer.getSchemaCSN()
  417. # Check the schemaCSN was NOT updated on the consumer
  418. log.debug("test_ticket47490_six master_schema_csn=%s", master_schema_csn)
  419. log.debug("ctest_ticket47490_six onsumer_schema_csn=%s", consumer_schema_csn)
  420. assert master_schema_csn == consumer_schema_csn
  421. # Check the error log of the supplier does not contain an error
  422. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  423. res = pattern_errorlog(topology.master.errorlog_file, regex)
  424. assert res == None
  425. def test_ticket47490_seven(topology):
  426. """
  427. Summary: Same OC - extra MAY: Schema is pushed - no error
  428. If supplier schema is again a superset (OC with more MAY), then
  429. schema is pushed and there is no message in the error log
  430. State at startup
  431. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  432. +must=telexnumber +must=telexnumber
  433. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  434. +must=telexnumber +must=telexnumber
  435. Final stat
  436. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  437. +must=telexnumber +must=telexnumber
  438. +may=postOfficeBox
  439. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  440. +must=telexnumber +must=telexnumber
  441. +may=postOfficeBox
  442. """
  443. mod_OC(topology.master, 2, 'masterNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_NEW)
  444. trigger_schema_push(topology)
  445. master_schema_csn = topology.master.getSchemaCSN()
  446. consumer_schema_csn = topology.consumer.getSchemaCSN()
  447. # Check the schemaCSN was updated on the consumer
  448. log.debug("test_ticket47490_seven master_schema_csn=%s", master_schema_csn)
  449. log.debug("ctest_ticket47490_seven consumer_schema_csn=%s", consumer_schema_csn)
  450. assert master_schema_csn == consumer_schema_csn
  451. # Check the error log of the supplier does not contain an error
  452. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  453. res = pattern_errorlog(topology.master.errorlog_file, regex)
  454. assert res == None
  455. def test_ticket47490_eight(topology):
  456. """
  457. Summary: Same OC - extra MAY: Schema is NOT pushed - error
  458. If consumer schema is a superset (OC with more MAY), then
  459. schema is not pushed and there is message in the error log
  460. State at startup
  461. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  462. +must=telexnumber +must=telexnumber
  463. +may=postOfficeBox
  464. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  465. +must=telexnumber +must=telexnumber
  466. +may=postOfficeBox
  467. Final state
  468. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  469. +must=telexnumber +must=telexnumber
  470. +may=postOfficeBox +may=postOfficeBox
  471. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  472. +must=telexnumber +must=telexnumber
  473. +may=postOfficeBox +may=postOfficeBox
  474. """
  475. mod_OC(topology.consumer, 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_NEW)
  476. # modify OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  477. time.sleep(2)
  478. mod_OC(topology.master, 4, 'masterNewOCC', old_must=MUST_OLD, new_must=MUST_OLD, old_may=MAY_OLD, new_may=MAY_NEW)
  479. trigger_schema_push(topology)
  480. master_schema_csn = topology.master.getSchemaCSN()
  481. consumer_schema_csn = topology.consumer.getSchemaCSN()
  482. # Check the schemaCSN was not updated on the consumer
  483. log.debug("test_ticket47490_eight master_schema_csn=%s", master_schema_csn)
  484. log.debug("ctest_ticket47490_eight onsumer_schema_csn=%s", consumer_schema_csn)
  485. assert master_schema_csn != consumer_schema_csn
  486. #Check that replication logging display additional message about 'postOfficeBox' not being
  487. # allowed in the master schema
  488. # This message appears before 'must not be overwritten' so it should be check first
  489. regex = re.compile("Attribute postOfficeBox is not allowed in 'consumerNewOCA' of the local supplier schema")
  490. res = pattern_errorlog(topology.master.errorlog_file, regex)
  491. assert res != None
  492. # Check the error log of the supplier does not contain an error
  493. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  494. res = pattern_errorlog(topology.master.errorlog_file, regex)
  495. assert res != None
  496. def test_ticket47490_nine(topology):
  497. """
  498. Summary: Same OC - extra MAY: Schema is pushed - no error
  499. If consumer schema is a superset (OC with more MAY), then
  500. schema is not pushed and there is message in the error log
  501. State at startup
  502. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  503. +must=telexnumber +must=telexnumber
  504. +may=postOfficeBox +may=postOfficeBox
  505. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  506. +must=telexnumber +must=telexnumber
  507. +may=postOfficeBox +may=postOfficeBox
  508. Final state
  509. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  510. +must=telexnumber +must=telexnumber
  511. +may=postOfficeBox +may=postOfficeBox +may=postOfficeBox
  512. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  513. +must=telexnumber +must=telexnumber
  514. +may=postOfficeBox +may=postOfficeBox +may=postOfficeBox
  515. """
  516. mod_OC(topology.master, 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_NEW)
  517. trigger_schema_push(topology)
  518. master_schema_csn = topology.master.getSchemaCSN()
  519. consumer_schema_csn = topology.consumer.getSchemaCSN()
  520. # Check the schemaCSN was updated on the consumer
  521. log.debug("test_ticket47490_nine master_schema_csn=%s", master_schema_csn)
  522. log.debug("ctest_ticket47490_nine onsumer_schema_csn=%s", consumer_schema_csn)
  523. assert master_schema_csn == consumer_schema_csn
  524. # Check the error log of the supplier does not contain an error
  525. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  526. res = pattern_errorlog(topology.master.errorlog_file, regex)
  527. assert res == None
  528. def run_isolated():
  529. '''
  530. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  531. To run isolated without py.test, you need to
  532. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  533. - set the installation prefix
  534. - run this program
  535. '''
  536. global installation_prefix
  537. installation_prefix = None
  538. topo = topology(True)
  539. test_ticket47490_init(topo)
  540. test_ticket47490_one(topo)
  541. test_ticket47490_two(topo)
  542. test_ticket47490_three(topo)
  543. test_ticket47490_four(topo)
  544. test_ticket47490_five(topo)
  545. test_ticket47490_six(topo)
  546. test_ticket47490_seven(topo)
  547. test_ticket47490_eight(topo)
  548. test_ticket47490_nine(topo)
  549. if __name__ == '__main__':
  550. run_isolated()