ticket47490_test.py 27 KB

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