ticket47490_test.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2015 Red Hat, Inc.
  3. # All rights reserved.
  4. #
  5. # License: GPL (version 3 or any later version).
  6. # See LICENSE for details.
  7. # --- END COPYRIGHT BLOCK ---
  8. #
  9. '''
  10. Created on Nov 7, 2013
  11. @author: tbordaz
  12. '''
  13. import os
  14. import sys
  15. import ldap
  16. import time
  17. import logging
  18. import pytest
  19. import re
  20. from lib389 import DirSrv, Entry
  21. from lib389._constants import *
  22. from lib389.properties import *
  23. logging.getLogger(__name__).setLevel(logging.DEBUG)
  24. log = logging.getLogger(__name__)
  25. installation_prefix = None
  26. TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
  27. ENTRY_DN = "cn=test_entry, %s" % SUFFIX
  28. MUST_OLD = "(postalAddress $ preferredLocale)"
  29. MUST_NEW = "(postalAddress $ preferredLocale $ telexNumber)"
  30. MAY_OLD = "(postalCode $ street)"
  31. MAY_NEW = "(postalCode $ street $ postOfficeBox)"
  32. class TopologyMasterConsumer(object):
  33. def __init__(self, master, consumer):
  34. master.open()
  35. self.master = master
  36. consumer.open()
  37. self.consumer = consumer
  38. def _header(topology, label):
  39. topology.master.log.info("\n\n###############################################")
  40. topology.master.log.info("#######")
  41. topology.master.log.info("####### %s" % label)
  42. topology.master.log.info("#######")
  43. topology.master.log.info("###################################################")
  44. def pattern_errorlog(file, log_pattern):
  45. try:
  46. pattern_errorlog.last_pos += 1
  47. except AttributeError:
  48. pattern_errorlog.last_pos = 0
  49. found = None
  50. log.debug("_pattern_errorlog: start at offset %d" % pattern_errorlog.last_pos)
  51. file.seek(pattern_errorlog.last_pos)
  52. # Use a while true iteration because 'for line in file: hit a
  53. # python bug that break file.tell()
  54. while True:
  55. line = file.readline()
  56. log.debug("_pattern_errorlog: [%d] %s" % (file.tell(), line))
  57. found = log_pattern.search(line)
  58. if ((line == '') or (found)):
  59. break
  60. log.debug("_pattern_errorlog: end at offset %d" % file.tell())
  61. pattern_errorlog.last_pos = file.tell()
  62. return found
  63. def _oc_definition(oid_ext, name, must=None, may=None):
  64. oid = "1.2.3.4.5.6.7.8.9.10.%d" % oid_ext
  65. desc = 'To test ticket 47490'
  66. sup = 'person'
  67. if not must:
  68. must = MUST_OLD
  69. if not may:
  70. may = MAY_OLD
  71. new_oc = "( %s NAME '%s' DESC '%s' SUP %s AUXILIARY MUST %s MAY %s )" % (oid, name, desc, sup, must, may)
  72. return new_oc
  73. def add_OC(instance, oid_ext, name):
  74. new_oc = _oc_definition(oid_ext, name)
  75. instance.schema.add_schema('objectClasses', new_oc)
  76. def mod_OC(instance, oid_ext, name, old_must=None, old_may=None, new_must=None, new_may=None):
  77. old_oc = _oc_definition(oid_ext, name, old_must, old_may)
  78. new_oc = _oc_definition(oid_ext, name, new_must, new_may)
  79. instance.schema.del_schema('objectClasses', old_oc)
  80. instance.schema.add_schema('objectClasses', new_oc)
  81. def support_schema_learning(topology):
  82. """
  83. with https://fedorahosted.org/389/ticket/47721, the supplier and consumer can learn
  84. schema definitions when a replication occurs.
  85. Before that ticket: replication of the schema fails requiring administrative operation
  86. In the test the schemaCSN (master consumer) differs
  87. After that ticket: replication of the schema succeeds (after an initial phase of learning)
  88. In the test the schema CSN (master consumer) are in sync
  89. This function returns True if 47721 is fixed in the current release
  90. False else
  91. """
  92. ent = topology.consumer.getEntry(DN_CONFIG, ldap.SCOPE_BASE, "(cn=config)", ['nsslapd-versionstring'])
  93. if ent.hasAttr('nsslapd-versionstring'):
  94. val = ent.getValue('nsslapd-versionstring')
  95. version = val.split('/')[1].split('.') # something like ['1', '3', '1', '23', 'final_fix']
  96. major = int(version[0])
  97. minor = int(version[1])
  98. if major > 1:
  99. return True
  100. if minor > 3:
  101. # version is 1.4 or after
  102. return True
  103. if minor == 3:
  104. if version[2].isdigit():
  105. if int(version[2]) >= 3:
  106. return True
  107. return False
  108. def trigger_update(topology):
  109. """
  110. It triggers an update on the supplier. This will start a replication
  111. session and a schema push
  112. """
  113. try:
  114. trigger_update.value += 1
  115. except AttributeError:
  116. trigger_update.value = 1
  117. replace = [(ldap.MOD_REPLACE, 'telephonenumber', str(trigger_update.value))]
  118. topology.master.modify_s(ENTRY_DN, replace)
  119. # wait 10 seconds that the update is replicated
  120. loop = 0
  121. while loop <= 10:
  122. try:
  123. ent = topology.consumer.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)", ['telephonenumber'])
  124. val = ent.telephonenumber or "0"
  125. if int(val) == trigger_update.value:
  126. return
  127. # the expected value is not yet replicated. try again
  128. time.sleep(1)
  129. loop += 1
  130. log.debug("trigger_update: receive %s (expected %d)" % (val, trigger_update.value))
  131. except ldap.NO_SUCH_OBJECT:
  132. time.sleep(1)
  133. loop += 1
  134. def trigger_schema_push(topology):
  135. '''
  136. Trigger update to create a replication session.
  137. In case of 47721 is fixed and the replica needs to learn the missing definition, then
  138. the first replication session learn the definition and the second replication session
  139. push the schema (and the schemaCSN.
  140. This is why there is two updates and replica agreement is stopped/start (to create a second session)
  141. '''
  142. agreements = topology.master.agreement.list(suffix=SUFFIX, consumer_host=topology.consumer.host, consumer_port=topology.consumer.port)
  143. assert(len(agreements) == 1)
  144. ra = agreements[0]
  145. trigger_update(topology)
  146. topology.master.agreement.pause(ra.dn)
  147. topology.master.agreement.resume(ra.dn)
  148. trigger_update(topology)
  149. @pytest.fixture(scope="module")
  150. def topology(request):
  151. '''
  152. This fixture is used to create a replicated topology for the 'module'.
  153. The replicated topology is MASTER -> Consumer.
  154. '''
  155. global installation_prefix
  156. if installation_prefix:
  157. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  158. master = DirSrv(verbose=False)
  159. consumer = DirSrv(verbose=False)
  160. # Args for the master instance
  161. args_instance[SER_HOST] = HOST_MASTER_1
  162. args_instance[SER_PORT] = PORT_MASTER_1
  163. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  164. args_master = args_instance.copy()
  165. master.allocate(args_master)
  166. # Args for the consumer instance
  167. args_instance[SER_HOST] = HOST_CONSUMER_1
  168. args_instance[SER_PORT] = PORT_CONSUMER_1
  169. args_instance[SER_SERVERID_PROP] = SERVERID_CONSUMER_1
  170. args_consumer = args_instance.copy()
  171. consumer.allocate(args_consumer)
  172. # Get the status of the instance
  173. instance_master = master.exists()
  174. instance_consumer = consumer.exists()
  175. # Remove all the instances
  176. if instance_master:
  177. master.delete()
  178. if instance_consumer:
  179. consumer.delete()
  180. # Create the instances
  181. master.create()
  182. master.open()
  183. consumer.create()
  184. consumer.open()
  185. #
  186. # Now prepare the Master-Consumer topology
  187. #
  188. # First Enable replication
  189. master.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  190. consumer.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_CONSUMER)
  191. # Initialize the supplier->consumer
  192. properties = {RA_NAME: r'meTo_$host:$port',
  193. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  194. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  195. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  196. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  197. repl_agreement = master.agreement.create(suffix=SUFFIX, host=consumer.host, port=consumer.port, properties=properties)
  198. if not repl_agreement:
  199. log.fatal("Fail to create a replica agreement")
  200. sys.exit(1)
  201. log.debug("%s created" % repl_agreement)
  202. master.agreement.init(SUFFIX, HOST_CONSUMER_1, PORT_CONSUMER_1)
  203. master.waitForReplInit(repl_agreement)
  204. # Check replication is working fine
  205. if master.testReplication(DEFAULT_SUFFIX, consumer):
  206. log.info('Replication is working.')
  207. else:
  208. log.fatal('Replication is not working.')
  209. assert False
  210. def fin():
  211. master.delete()
  212. consumer.delete()
  213. request.addfinalizer(fin)
  214. #
  215. # Here we have two instances master and consumer
  216. # with replication working.
  217. return TopologyMasterConsumer(master, consumer)
  218. def test_ticket47490_init(topology):
  219. """
  220. Initialize the test environment
  221. """
  222. log.debug("test_ticket47490_init topology %r (master %r, consumer %r" % (topology, topology.master, topology.consumer))
  223. # the test case will check if a warning message is logged in the
  224. # error log of the supplier
  225. topology.master.errorlog_file = open(topology.master.errlog, "r")
  226. # This entry will be used to trigger attempt of schema push
  227. topology.master.add_s(Entry((ENTRY_DN, {
  228. 'objectclass': "top person".split(),
  229. 'sn': 'test_entry',
  230. 'cn': 'test_entry'})))
  231. def test_ticket47490_one(topology):
  232. """
  233. Summary: Extra OC Schema is pushed - no error
  234. If supplier schema is a superset (one extra OC) of consumer schema, then
  235. schema is pushed and there is no message in the error log
  236. State at startup:
  237. - supplier default schema
  238. - consumer default schema
  239. Final state
  240. - supplier +masterNewOCA
  241. - consumer +masterNewOCA
  242. """
  243. _header(topology, "Extra OC Schema is pushed - no error")
  244. log.debug("test_ticket47490_one topology %r (master %r, consumer %r" % (topology, topology.master, topology.consumer))
  245. # update the schema of the supplier so that it is a superset of
  246. # consumer. Schema should be pushed
  247. add_OC(topology.master, 2, 'masterNewOCA')
  248. trigger_schema_push(topology)
  249. master_schema_csn = topology.master.schema.get_schema_csn()
  250. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  251. # Check the schemaCSN was updated on the consumer
  252. log.debug("test_ticket47490_one master_schema_csn=%s", master_schema_csn)
  253. log.debug("ctest_ticket47490_one onsumer_schema_csn=%s", consumer_schema_csn)
  254. assert master_schema_csn == consumer_schema_csn
  255. # Check the error log of the supplier does not contain an error
  256. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  257. res = pattern_errorlog(topology.master.errorlog_file, regex)
  258. if res is not None:
  259. assert False
  260. def test_ticket47490_two(topology):
  261. """
  262. Summary: Extra OC Schema is pushed - (ticket 47721 allows to learn missing def)
  263. If consumer schema is a superset (one extra OC) of supplier schema, then
  264. schema is pushed and there is a message in the error log
  265. State at startup
  266. - supplier +masterNewOCA
  267. - consumer +masterNewOCA
  268. Final state
  269. - supplier +masterNewOCA +masterNewOCB
  270. - consumer +masterNewOCA +consumerNewOCA
  271. """
  272. _header(topology, "Extra OC Schema is pushed - (ticket 47721 allows to learn missing def)")
  273. # add this OC on consumer. Supplier will no push the schema
  274. add_OC(topology.consumer, 1, 'consumerNewOCA')
  275. # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  276. time.sleep(2)
  277. add_OC(topology.master, 3, 'masterNewOCB')
  278. # now push the scheam
  279. trigger_schema_push(topology)
  280. master_schema_csn = topology.master.schema.get_schema_csn()
  281. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  282. # Check the schemaCSN was NOT updated on the consumer
  283. # with 47721, supplier learns the missing definition
  284. log.debug("test_ticket47490_two master_schema_csn=%s", master_schema_csn)
  285. log.debug("test_ticket47490_two consumer_schema_csn=%s", consumer_schema_csn)
  286. if support_schema_learning(topology):
  287. assert master_schema_csn == consumer_schema_csn
  288. else:
  289. assert master_schema_csn != consumer_schema_csn
  290. # Check the error log of the supplier does not contain an error
  291. # This message may happen during the learning phase
  292. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  293. res = pattern_errorlog(topology.master.errorlog_file, regex)
  294. def test_ticket47490_three(topology):
  295. """
  296. Summary: Extra OC Schema is pushed - no error
  297. If supplier schema is again a superset (one extra OC), then
  298. schema is pushed and there is no message in the error log
  299. State at startup
  300. - supplier +masterNewOCA +masterNewOCB
  301. - consumer +masterNewOCA +consumerNewOCA
  302. Final state
  303. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  304. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  305. """
  306. _header(topology, "Extra OC Schema is pushed - no error")
  307. # Do an upate to trigger the schema push attempt
  308. # add this OC on consumer. Supplier will no push the schema
  309. add_OC(topology.master, 1, 'consumerNewOCA')
  310. # now push the scheam
  311. trigger_schema_push(topology)
  312. master_schema_csn = topology.master.schema.get_schema_csn()
  313. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  314. # Check the schemaCSN was NOT updated on the consumer
  315. log.debug("test_ticket47490_three master_schema_csn=%s", master_schema_csn)
  316. log.debug("test_ticket47490_three consumer_schema_csn=%s", consumer_schema_csn)
  317. assert master_schema_csn == consumer_schema_csn
  318. # Check the error log of the supplier does not contain an error
  319. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  320. res = pattern_errorlog(topology.master.errorlog_file, regex)
  321. if res is not None:
  322. assert False
  323. def test_ticket47490_four(topology):
  324. """
  325. Summary: Same OC - extra MUST: Schema is pushed - no error
  326. If supplier schema is again a superset (OC with more MUST), then
  327. schema is pushed and there is no message in the error log
  328. State at startup
  329. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  330. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  331. Final state
  332. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  333. +must=telexnumber
  334. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  335. +must=telexnumber
  336. """
  337. _header(topology, "Same OC - extra MUST: Schema is pushed - no error")
  338. mod_OC(topology.master, 2, 'masterNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  339. trigger_schema_push(topology)
  340. master_schema_csn = topology.master.schema.get_schema_csn()
  341. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  342. # Check the schemaCSN was updated on the consumer
  343. log.debug("test_ticket47490_four master_schema_csn=%s", master_schema_csn)
  344. log.debug("ctest_ticket47490_four onsumer_schema_csn=%s", consumer_schema_csn)
  345. assert master_schema_csn == consumer_schema_csn
  346. # Check the error log of the supplier does not contain an error
  347. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  348. res = pattern_errorlog(topology.master.errorlog_file, regex)
  349. if res is not None:
  350. assert False
  351. def test_ticket47490_five(topology):
  352. """
  353. Summary: Same OC - extra MUST: Schema is pushed - (fix for 47721)
  354. If consumer schema is a superset (OC with more MUST), then
  355. schema is pushed (fix for 47721) and there is a message in the error log
  356. State at startup
  357. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
  358. +must=telexnumber
  359. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  360. +must=telexnumber
  361. Final state
  362. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  363. +must=telexnumber
  364. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  365. +must=telexnumber +must=telexnumber
  366. Note: replication log is enabled to get more details
  367. """
  368. _header(topology, "Same OC - extra MUST: Schema is pushed - (fix for 47721)")
  369. # get more detail why it fails
  370. topology.master.enableReplLogging()
  371. # add telenumber to 'consumerNewOCA' on the consumer
  372. mod_OC(topology.consumer, 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  373. # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  374. time.sleep(2)
  375. add_OC(topology.master, 4, 'masterNewOCC')
  376. trigger_schema_push(topology)
  377. master_schema_csn = topology.master.schema.get_schema_csn()
  378. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  379. # Check the schemaCSN was NOT updated on the consumer
  380. # with 47721, supplier learns the missing definition
  381. log.debug("test_ticket47490_five master_schema_csn=%s", master_schema_csn)
  382. log.debug("ctest_ticket47490_five onsumer_schema_csn=%s", consumer_schema_csn)
  383. if support_schema_learning(topology):
  384. assert master_schema_csn == consumer_schema_csn
  385. else:
  386. assert master_schema_csn != consumer_schema_csn
  387. # Check the error log of the supplier does not contain an error
  388. # This message may happen during the learning phase
  389. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  390. res = pattern_errorlog(topology.master.errorlog_file, regex)
  391. def test_ticket47490_six(topology):
  392. """
  393. Summary: Same OC - extra MUST: Schema is pushed - no error
  394. If supplier schema is again a superset (OC with more MUST), then
  395. schema is pushed and there is no message in the error log
  396. State at startup
  397. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  398. +must=telexnumber
  399. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
  400. +must=telexnumber +must=telexnumber
  401. Final state
  402. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  403. +must=telexnumber +must=telexnumber
  404. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  405. +must=telexnumber +must=telexnumber
  406. Note: replication log is enabled to get more details
  407. """
  408. _header(topology, "Same OC - extra MUST: Schema is pushed - no error")
  409. # add telenumber to 'consumerNewOCA' on the consumer
  410. mod_OC(topology.master, 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_OLD)
  411. trigger_schema_push(topology)
  412. master_schema_csn = topology.master.schema.get_schema_csn()
  413. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  414. # Check the schemaCSN was NOT updated on the consumer
  415. log.debug("test_ticket47490_six master_schema_csn=%s", master_schema_csn)
  416. log.debug("ctest_ticket47490_six onsumer_schema_csn=%s", consumer_schema_csn)
  417. assert master_schema_csn == consumer_schema_csn
  418. # Check the error log of the supplier does not contain an error
  419. # This message may happen during the learning phase
  420. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  421. res = pattern_errorlog(topology.master.errorlog_file, regex)
  422. if res is not None:
  423. assert False
  424. def test_ticket47490_seven(topology):
  425. """
  426. Summary: Same OC - extra MAY: Schema is pushed - no error
  427. If supplier schema is again a superset (OC with more MAY), then
  428. schema is pushed and there is no message in the error log
  429. State at startup
  430. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  431. +must=telexnumber +must=telexnumber
  432. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  433. +must=telexnumber +must=telexnumber
  434. Final stat
  435. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  436. +must=telexnumber +must=telexnumber
  437. +may=postOfficeBox
  438. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  439. +must=telexnumber +must=telexnumber
  440. +may=postOfficeBox
  441. """
  442. _header(topology, "Same OC - extra MAY: Schema is pushed - no error")
  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.schema.get_schema_csn()
  446. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  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. if res is not None:
  455. assert False
  456. def test_ticket47490_eight(topology):
  457. """
  458. Summary: Same OC - extra MAY: Schema is pushed (fix for 47721)
  459. If consumer schema is a superset (OC with more MAY), then
  460. schema is pushed (fix for 47721) and there is message in the error log
  461. State at startup
  462. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  463. +must=telexnumber +must=telexnumber
  464. +may=postOfficeBox
  465. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  466. +must=telexnumber +must=telexnumber
  467. +may=postOfficeBox
  468. Final state
  469. - supplier +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  470. +must=telexnumber +must=telexnumber
  471. +may=postOfficeBox +may=postOfficeBox
  472. - consumer +masterNewOCA +masterNewOCB +consumerNewOCA +masterNewOCC
  473. +must=telexnumber +must=telexnumber
  474. +may=postOfficeBox +may=postOfficeBox
  475. """
  476. _header(topology, "Same OC - extra MAY: Schema is pushed (fix for 47721)")
  477. mod_OC(topology.consumer, 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_NEW)
  478. # modify OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
  479. time.sleep(2)
  480. mod_OC(topology.master, 4, 'masterNewOCC', old_must=MUST_OLD, new_must=MUST_OLD, old_may=MAY_OLD, new_may=MAY_NEW)
  481. trigger_schema_push(topology)
  482. master_schema_csn = topology.master.schema.get_schema_csn()
  483. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  484. # Check the schemaCSN was not updated on the consumer
  485. # with 47721, supplier learns the missing definition
  486. log.debug("test_ticket47490_eight master_schema_csn=%s", master_schema_csn)
  487. log.debug("ctest_ticket47490_eight onsumer_schema_csn=%s", consumer_schema_csn)
  488. if support_schema_learning(topology):
  489. assert master_schema_csn == consumer_schema_csn
  490. else:
  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. _header(topology, "Same OC - extra MAY: Schema is pushed - no error")
  517. mod_OC(topology.master, 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD, new_may=MAY_NEW)
  518. trigger_schema_push(topology)
  519. master_schema_csn = topology.master.schema.get_schema_csn()
  520. consumer_schema_csn = topology.consumer.schema.get_schema_csn()
  521. # Check the schemaCSN was updated on the consumer
  522. log.debug("test_ticket47490_nine master_schema_csn=%s", master_schema_csn)
  523. log.debug("ctest_ticket47490_nine onsumer_schema_csn=%s", consumer_schema_csn)
  524. assert master_schema_csn == consumer_schema_csn
  525. # Check the error log of the supplier does not contain an error
  526. regex = re.compile("must not be overwritten \(set replication log for additional info\)")
  527. res = pattern_errorlog(topology.master.errorlog_file, regex)
  528. if res is not None:
  529. assert False
  530. log.info('Testcase PASSED')
  531. if __name__ == '__main__':
  532. # Run isolated
  533. # -s for DEBUG mode
  534. CURRENT_FILE = os.path.realpath(__file__)
  535. pytest.main("-s %s" % CURRENT_FILE)