ticket47490_test.py 26 KB

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