ticket47490_test.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  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. #
  233. # Here we have two instances master and consumer
  234. # with replication working. Either coming from a backup recovery
  235. # or from a fresh (re)init
  236. # Time to return the topology
  237. return TopologyMasterConsumer(master, consumer)
  238. def test_ticket47490_init(topology):
  239. """
  240. Initialize the test environment
  241. """
  242. log.debug("test_ticket47490_init topology %r (master %r, consumer %r" % (topology, topology.master, topology.consumer))
  243. # the test case will check if a warning message is logged in the
  244. # error log of the supplier
  245. topology.master.errorlog_file = open(topology.master.errlog, "r")
  246. # This entry will be used to trigger attempt of schema push
  247. topology.master.add_s(Entry((ENTRY_DN, {
  248. 'objectclass': "top person".split(),
  249. 'sn': 'test_entry',
  250. 'cn': 'test_entry'})))
  251. def test_ticket47490_one(topology):
  252. """
  253. Summary: Extra OC Schema is pushed - no error
  254. If supplier schema is a superset (one extra OC) of consumer schema, then
  255. schema is pushed and there is no message in the error log
  256. State at startup:
  257. - supplier default schema
  258. - consumer default schema
  259. Final state
  260. - supplier +masterNewOCA
  261. - consumer +masterNewOCA
  262. """
  263. log.debug("test_ticket47490_one topology %r (master %r, consumer %r" % (topology, topology.master, topology.consumer))
  264. # update the schema of the supplier so that it is a superset of
  265. # consumer. Schema should be pushed
  266. add_OC(topology.master, 2, 'masterNewOCA')
  267. trigger_schema_push(topology)
  268. master_schema_csn = topology.master.schema.get_schema_csn()
  269. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  270. # Check the schemaCSN was updated on the consumer
  271. log.debug("test_ticket47490_one master_schema_csn=%s", master_schema_csn)
  272. log.debug("ctest_ticket47490_one onsumer_schema_csn=%s", consumer_schema_csn)
  273. assert master_schema_csn == consumer_schema_csn
  274. # Check the error log of the supplier does not contain an error
  275. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  276. res = pattern_errorlog(topology.master.errorlog_file, regex)
  277. assert res == None
  278. def test_ticket47490_two(topology):
  279. """
  280. Summary: Extra OC Schema is pushed - (ticket 47721 allows to learn missing def)
  281. If consumer schema is a superset (one extra OC) of supplier schema, then
  282. schema is pushed and there is a message in the error log
  283. State at startup
  284. - supplier +masterNewOCA
  285. - consumer +masterNewOCA
  286. Final state
  287. - supplier +masterNewOCA +masterNewOCB
  288. - consumer +masterNewOCA +consumerNewOCA
  289. """
  290. # add this OC on consumer. Supplier will no push the schema
  291. add_OC(topology.consumer, 1, 'consumerNewOCA')
  292. # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  293. time.sleep(2)
  294. add_OC(topology.master, 3, 'masterNewOCB')
  295. # now push the scheam
  296. trigger_schema_push(topology)
  297. master_schema_csn = topology.master.schema.get_schema_csn()
  298. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  299. # Check the schemaCSN was NOT updated on the consumer
  300. # with 47721, supplier learns the missing definition
  301. log.debug("test_ticket47490_two master_schema_csn=%s", master_schema_csn)
  302. log.debug("test_ticket47490_two consumer_schema_csn=%s", consumer_schema_csn)
  303. assert master_schema_csn != consumer_schema_csn
  304. # Check the error log of the supplier does not contain an error
  305. # This message may happen during the learning phase
  306. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  307. res = pattern_errorlog(topology.master.errorlog_file, regex)
  308. def test_ticket47490_three(topology):
  309. """
  310. Summary: Extra OC Schema is pushed - no error
  311. If supplier schema is again a superset (one extra OC), then
  312. schema is pushed and there is no message in the error log
  313. State at startup
  314. - supplier +masterNewOCA +masterNewOCB
  315. - consumer +masterNewOCA +consumerNewOCA
  316. Final state
  317. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  318. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  319. """
  320. # Do an upate to trigger the schema push attempt
  321. # add this OC on consumer. Supplier will no push the schema
  322. add_OC(topology.master, 1, 'consumerNewOCA')
  323. # now push the scheam
  324. trigger_schema_push(topology)
  325. master_schema_csn = topology.master.schema.get_schema_csn()
  326. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  327. # Check the schemaCSN was NOT updated on the consumer
  328. log.debug("test_ticket47490_three master_schema_csn=%s", master_schema_csn)
  329. log.debug("test_ticket47490_three consumer_schema_csn=%s", consumer_schema_csn)
  330. assert master_schema_csn == consumer_schema_csn
  331. # Check the error log of the supplier does not contain an error
  332. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  333. res = pattern_errorlog(topology.master.errorlog_file, regex)
  334. assert res == None
  335. def test_ticket47490_four(topology):
  336. """
  337. Summary: Same OC - extra MUST: Schema is pushed - no error
  338. If supplier schema is again a superset (OC with more MUST), then
  339. schema is pushed and there is no message in the error log
  340. State at startup
  341. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  342. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  343. Final state
  344. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  345. +must=telexnumber
  346. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  347. +must=telexnumber
  348. """
  349. mod_OC(topology.master, 2, 'masterNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  350. trigger_schema_push(topology)
  351. master_schema_csn = topology.master.schema.get_schema_csn()
  352. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  353. # Check the schemaCSN was updated on the consumer
  354. log.debug("test_ticket47490_four master_schema_csn=%s", master_schema_csn)
  355. log.debug("ctest_ticket47490_four onsumer_schema_csn=%s", consumer_schema_csn)
  356. assert master_schema_csn == consumer_schema_csn
  357. # Check the error log of the supplier does not contain an error
  358. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  359. res = pattern_errorlog(topology.master.errorlog_file, regex)
  360. assert res == None
  361. def test_ticket47490_five(topology):
  362. """
  363. Summary: Same OC - extra MUST: Schema is pushed - (fix for 47721)
  364. If consumer schema is a superset (OC with more MUST), then
  365. schema is pushed (fix for 47721) and there is a message in the error log
  366. State at startup
  367. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  368. +must=telexnumber
  369. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  370. +must=telexnumber
  371. Final state
  372. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  373. +must=telexnumber
  374. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  375. +must=telexnumber +must=telexnumber
  376. Note: replication log is enabled to get more details
  377. """
  378. # get more detail why it fails
  379. topology.master.enableReplLogging()
  380. # add telenumber to 'consumerNewOCA' on the consumer
  381. mod_OC(topology.consumer, 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  382. # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  383. time.sleep(2)
  384. add_OC(topology.master, 4, 'masterNewOCC')
  385. trigger_schema_push(topology)
  386. master_schema_csn = topology.master.schema.get_schema_csn()
  387. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  388. # Check the schemaCSN was NOT updated on the consumer
  389. # with 47721, supplier learns the missing definition
  390. log.debug("test_ticket47490_five master_schema_csn=%s", master_schema_csn)
  391. log.debug("ctest_ticket47490_five onsumer_schema_csn=%s", consumer_schema_csn)
  392. assert master_schema_csn != consumer_schema_csn
  393. # Check the error log of the supplier does not contain an error
  394. # This message may happen during the learning phase
  395. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  396. res = pattern_errorlog(topology.master.errorlog_file, regex)
  397. def test_ticket47490_six(topology):
  398. """
  399. Summary: Same OC - extra MUST: Schema is pushed - no error
  400. If supplier schema is again a superset (OC with more MUST), then
  401. schema is pushed and there is no message in the error log
  402. State at startup
  403. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  404. +must=telexnumber
  405. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  406. +must=telexnumber +must=telexnumber
  407. Final state
  408. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  409. +must=telexnumber +must=telexnumber
  410. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  411. +must=telexnumber +must=telexnumber
  412. Note: replication log is enabled to get more details
  413. """
  414. # add telenumber to 'consumerNewOCA' on the consumer
  415. mod_OC(topology.master, 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  416. trigger_schema_push(topology)
  417. master_schema_csn = topology.master.schema.get_schema_csn()
  418. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  419. # Check the schemaCSN was NOT updated on the consumer
  420. log.debug("test_ticket47490_six master_schema_csn=%s", master_schema_csn)
  421. log.debug("ctest_ticket47490_six onsumer_schema_csn=%s", consumer_schema_csn)
  422. assert master_schema_csn == consumer_schema_csn
  423. # Check the error log of the supplier does not contain an error
  424. # This message may happen during the learning phase
  425. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  426. res = pattern_errorlog(topology.master.errorlog_file, regex)
  427. assert res == None
  428. def test_ticket47490_seven(topology):
  429. """
  430. Summary: Same OC - extra MAY: Schema is pushed - no error
  431. If supplier schema is again a superset (OC with more MAY), then
  432. schema is pushed and there is no message in the error log
  433. State at startup
  434. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  435. +must=telexnumber +must=telexnumber
  436. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  437. +must=telexnumber +must=telexnumber
  438. Final stat
  439. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  440. +must=telexnumber +must=telexnumber
  441. +may=postOfficeBox
  442. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  443. +must=telexnumber +must=telexnumber
  444. +may=postOfficeBox
  445. """
  446. mod_OC(topology.master, 2, 'masterNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_NEW)
  447. trigger_schema_push(topology)
  448. master_schema_csn = topology.master.schema.get_schema_csn()
  449. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  450. # Check the schemaCSN was updated on the consumer
  451. log.debug("test_ticket47490_seven master_schema_csn=%s", master_schema_csn)
  452. log.debug("ctest_ticket47490_seven consumer_schema_csn=%s", consumer_schema_csn)
  453. assert master_schema_csn == consumer_schema_csn
  454. # Check the error log of the supplier does not contain an error
  455. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  456. res = pattern_errorlog(topology.master.errorlog_file, regex)
  457. assert res == None
  458. def test_ticket47490_eight(topology):
  459. """
  460. Summary: Same OC - extra MAY: Schema is pushed (fix for 47721)
  461. If consumer schema is a superset (OC with more MAY), then
  462. schema is pushed (fix for 47721) and there is message in the error log
  463. State at startup
  464. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  465. +must=telexnumber +must=telexnumber
  466. +may=postOfficeBox
  467. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  468. +must=telexnumber +must=telexnumber
  469. +may=postOfficeBox
  470. Final state
  471. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  472. +must=telexnumber +must=telexnumber
  473. +may=postOfficeBox +may=postOfficeBox
  474. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  475. +must=telexnumber +must=telexnumber
  476. +may=postOfficeBox +may=postOfficeBox
  477. """
  478. mod_OC(topology.consumer, 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_NEW)
  479. # modify OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  480. time.sleep(2)
  481. mod_OC(topology.master, 4, 'masterNewOCC', old_must=MUST_OLD, new_must=MUST_OLD, old_may=MAY_OLD, new_may=MAY_NEW)
  482. trigger_schema_push(topology)
  483. master_schema_csn = topology.master.schema.get_schema_csn()
  484. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  485. # Check the schemaCSN was not updated on the consumer
  486. # with 47721, supplier learns the missing definition
  487. log.debug("test_ticket47490_eight master_schema_csn=%s", master_schema_csn)
  488. log.debug("ctest_ticket47490_eight onsumer_schema_csn=%s", consumer_schema_csn)
  489. assert master_schema_csn != consumer_schema_csn
  490. # Check the error log of the supplier does not contain an error
  491. # This message may happen during the learning phase
  492. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  493. res = pattern_errorlog(topology.master.errorlog_file, regex)
  494. def test_ticket47490_nine(topology):
  495. """
  496. Summary: Same OC - extra MAY: Schema is pushed - no error
  497. If consumer schema is a superset (OC with more MAY), then
  498. schema is not pushed and there is message in the error log
  499. State at startup
  500. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  501. +must=telexnumber +must=telexnumber
  502. +may=postOfficeBox +may=postOfficeBox
  503. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  504. +must=telexnumber +must=telexnumber
  505. +may=postOfficeBox +may=postOfficeBox
  506. Final state
  507. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  508. +must=telexnumber +must=telexnumber
  509. +may=postOfficeBox +may=postOfficeBox +may=postOfficeBox
  510. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  511. +must=telexnumber +must=telexnumber
  512. +may=postOfficeBox +may=postOfficeBox +may=postOfficeBox
  513. """
  514. mod_OC(topology.master, 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_NEW)
  515. trigger_schema_push(topology)
  516. master_schema_csn = topology.master.schema.get_schema_csn()
  517. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  518. # Check the schemaCSN was updated on the consumer
  519. log.debug("test_ticket47490_nine master_schema_csn=%s", master_schema_csn)
  520. log.debug("ctest_ticket47490_nine onsumer_schema_csn=%s", consumer_schema_csn)
  521. assert master_schema_csn == consumer_schema_csn
  522. # Check the error log of the supplier does not contain an error
  523. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  524. res = pattern_errorlog(topology.master.errorlog_file, regex)
  525. assert res == None
  526. def test_ticket47490_final(topology):
  527. topology.master.stop(timeout=10)
  528. topology.consumer.stop(timeout=10)
  529. def run_isolated():
  530. '''
  531. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  532. To run isolated without py.test, you need to
  533. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  534. - set the installation prefix
  535. - run this program
  536. '''
  537. global installation_prefix
  538. installation_prefix = None
  539. topo = topology(True)
  540. test_ticket47490_init(topo)
  541. test_ticket47490_one(topo)
  542. test_ticket47490_two(topo)
  543. test_ticket47490_three(topo)
  544. test_ticket47490_four(topo)
  545. test_ticket47490_five(topo)
  546. test_ticket47490_six(topo)
  547. test_ticket47490_seven(topo)
  548. test_ticket47490_eight(topo)
  549. test_ticket47490_nine(topo)
  550. test_ticket47490_final(topo)
  551. if __name__ == '__main__':
  552. run_isolated()