ticket47490_test.py 28 KB

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