def test_longpoll_changes_termination_heartbeat(setup_client_syncgateway_test): """https://github.com/couchbase/couchbase-lite-java-core/issues/1296 Create 30 longpoll _changes in a loop (with heartbeat parameter = 5s) Cancel the request after 2s Wait 5.1s Create another request GET /db/ on listener and make sure the listener responds """ log_info("Running 'longpoll_changes_termination' ...") ls_db = "ls_db" cluster_config = setup_client_syncgateway_test["cluster_config"] sg_url = setup_client_syncgateway_test["sg_url"] ls_url = setup_client_syncgateway_test["ls_url"] log_info("Running 'test_longpoll_changes_termination' ...") log_info("ls_url: {}".format(ls_url)) log_info("sg_url: {}".format(sg_url)) sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_url, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) client = MobileRestClient() if client.get_server_platform(ls_url) == Platform.macosx: pytest.skip("https://github.com/couchbase/couchbase-lite-ios/issues/1236") client.create_database(ls_url, ls_db) ct = ChangesTracker(ls_url, ls_db) with ThreadPoolExecutor(max_workers=35) as executor: futures = [executor.submit( ct.start, timeout=5000, heartbeat=5000, request_timeout=2000 ) for _ in range(30)] for futures in as_completed(futures): log_info("Future _changes loop complete") log_info("Futures exited") # make sure client can still take connections dbs = client.get_databases(url=ls_url) log_info(dbs) database = client.get_database(url=ls_url, db_name=ls_db) log_info(database)
def test_auto_prune_with_pull(setup_client_syncgateway_test): """Sanity test for autopruning with replication 1. Create a database on LiteServ (ls_db) 2. Add doc to sync gateway 3. Update doc 50 times on sync_gateway 4. Set up pull replication from sync_gateway db to LiteServ db 5. Verify number of revisions on client is default (20) """ cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_url = setup_client_syncgateway_test["sg_url"] sg_admin_url = setup_client_syncgateway_test["sg_admin_url"] client = MobileRestClient() sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_url, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_auto_prune_listener_sanity' ...") log_info("ls_url: {}".format(ls_url)) log_info("sg_url: {}".format(sg_url)) log_info("sg_admin_url: {}".format(sg_admin_url)) num_docs = 1 num_revs = 50 sg_user_channels = ["NBC"] sg_db = "db" sg_user_name = "sg_user" client.create_user(url=sg_admin_url, db=sg_db, name=sg_user_name, password="******", channels=sg_user_channels) sg_session = client.create_session(url=sg_admin_url, db=sg_db, name=sg_user_name) ls_db = client.create_database(url=ls_url, name="ls_db") sg_db_docs = client.add_docs( url=sg_url, db=sg_db, number=num_docs, id_prefix=sg_db, channels=sg_user_channels, auth=sg_session ) assert len(sg_db_docs) == num_docs sg_docs_update = client.update_docs(url=sg_url, db=sg_db, docs=sg_db_docs, number_updates=num_revs, auth=sg_session) # Start continuous replication ls_db <- sg_db repl_one = client.start_replication(url=ls_url, continuous=True, from_url=sg_admin_url, from_db=sg_db, to_db=ls_db) client.wait_for_replication_status_idle(url=ls_url, replication_id=repl_one) client.verify_docs_present(url=ls_url, db=ls_db, expected_docs=sg_docs_update) client.verify_revs_num_for_docs(url=ls_url, db=ls_db, docs=sg_docs_update, expected_revs_per_doc=20)
def test_verify_open_revs_with_revs_limit_push_conflict(setup_client_syncgateway_test): """Test replication from multiple client dbs to one sync_gateway db https://github.com/couchbase/couchbase-lite-ios/issues/1277 """ cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_url = setup_client_syncgateway_test["sg_url"] sg_admin_url = setup_client_syncgateway_test["sg_admin_url"] num_docs = 100 num_revs = 20 sg_db = "db" sg_user_name = "sg_user" sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_url, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_verify_open_revs_with_revs_limit_push_conflict'") log_info("ls_url: {}".format(ls_url)) log_info("sg_admin_url: {}".format(sg_admin_url)) log_info("sg_url: {}".format(sg_url)) log_info("num_docs: {}".format(num_docs)) log_info("num_revs: {}".format(num_revs)) client = MobileRestClient() # Test the endpoint, listener does not support users but should have a default response client.get_session(url=ls_url) sg_user_channels = ["NBC"] client.create_user(url=sg_admin_url, db=sg_db, name=sg_user_name, password="******", channels=sg_user_channels) sg_session = client.create_session(url=sg_admin_url, db=sg_db, name=sg_user_name) ls_db = client.create_database(url=ls_url, name="ls_db") ls_db_docs = client.add_docs(url=ls_url, db=ls_db, number=num_docs, id_prefix="ls_db", channels=sg_user_channels) assert len(ls_db_docs) == num_docs # Start replication ls_db -> sg_db repl_one = client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_admin_url, to_db=sg_db ) client.verify_docs_present(url=sg_admin_url, db=sg_db, expected_docs=ls_db_docs) client.update_docs(url=sg_url, db=sg_db, docs=ls_db_docs, number_updates=num_revs, auth=sg_session) sg_current_doc = client.get_doc(url=sg_url, db=sg_db, doc_id="ls_db_2", auth=sg_session) client.update_docs(url=ls_url, db=ls_db, docs=ls_db_docs, number_updates=num_revs) ls_current_doc = client.get_doc(url=ls_url, db=ls_db, doc_id="ls_db_2") client.wait_for_replication_status_idle(url=ls_url, replication_id=repl_one) client.verify_doc_rev_generation(url=ls_url, db=ls_db, doc_id=ls_current_doc["_id"], expected_generation=21) client.verify_doc_rev_generation(url=sg_url, db=sg_db, doc_id=sg_current_doc["_id"], expected_generation=21, auth=sg_session) expected_ls_revs = [ls_current_doc["_rev"]] client.verify_open_revs(url=ls_url, db=ls_db, doc_id=ls_current_doc["_id"], expected_open_revs=expected_ls_revs) expected_sg_revs = [ls_current_doc["_rev"], sg_current_doc["_rev"]] client.verify_open_revs(url=sg_admin_url, db=sg_db, doc_id=sg_current_doc["_id"], expected_open_revs=expected_sg_revs)
def test_replication_with_multiple_client_dbs_and_single_sync_gateway_db(setup_client_syncgateway_test): """Test replication from multiple client dbs to one sync_gateway db""" cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_url = setup_client_syncgateway_test["sg_url"] sg_admin_url = setup_client_syncgateway_test["sg_admin_url"] num_docs = 1000 sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_url, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_replication_with_multiple_client_dbs_and_single_sync_gateway_db'") log_info("ls_url: {}".format(ls_url)) log_info("sg_admin_url: {}".format(sg_admin_url)) log_info("sg_url: {}".format(sg_url)) client = MobileRestClient() ls_db1 = client.create_database(url=ls_url, name="ls_db1") ls_db2 = client.create_database(url=ls_url, name="ls_db2") sg_db = client.create_database(url=sg_admin_url, name="sg_db", server="walrus:") # Setup continuous push / pull replication from ls_db1 to sg_db client.start_replication( url=ls_url, continuous=True, from_db=ls_db1, to_url=sg_admin_url, to_db=sg_db ) client.start_replication( url=ls_url, continuous=True, from_url=sg_admin_url, from_db=sg_db, to_db=ls_db1 ) # Setup continuous push / pull replication from ls_db2 to sg_db client.start_replication( url=ls_url, continuous=True, from_db=ls_db2, to_url=sg_admin_url, to_db=sg_db ) client.start_replication( url=ls_url, continuous=True, from_url=sg_admin_url, from_db=sg_db, to_db=ls_db2 ) ls_db_one_docs = client.add_docs(url=ls_url, db=ls_db1, number=num_docs, id_prefix=ls_db1) assert len(ls_db_one_docs) == 1000 ls_db_two_docs = client.add_docs(url=ls_url, db=ls_db2, number=num_docs, id_prefix=ls_db2) assert len(ls_db_two_docs) == 1000 ls_db1_db2_docs = ls_db_one_docs + ls_db_two_docs client.verify_docs_present(url=ls_url, db=ls_db1, expected_docs=ls_db1_db2_docs) client.verify_docs_present(url=ls_url, db=ls_db2, expected_docs=ls_db1_db2_docs) client.verify_docs_present(url=sg_admin_url, db=sg_db, expected_docs=ls_db1_db2_docs) client.verify_docs_in_changes(url=sg_admin_url, db=sg_db, expected_docs=ls_db1_db2_docs) client.verify_docs_in_changes(url=ls_url, db=ls_db1, expected_docs=ls_db1_db2_docs) client.verify_docs_in_changes(url=ls_url, db=ls_db2, expected_docs=ls_db1_db2_docs)
def test_client_to_sync_gateway_complex_replication_with_revs_limit(setup_client_syncgateway_test): """ Ported from sync_gateway tests repo ... 1. Clear server buckets ... 2. Restart liteserv with _session ... 3. Restart sync_gateway wil that config ... 4. Create db on LiteServ ... 5. Add numDocs to LiteServ db ... 6. Setup push replication from LiteServ db to sync_gateway ... 7. Verify doc present on sync_gateway (number of docs) ... 8. Update sg docs numRevs * 4 = 480 ... 9. Update docs on LiteServ db numRevs * 4 = 480 ... 10. Setup pull replication from sg -> liteserv db ... 11. Verify all docs are replicated ... 12. compact LiteServ db (POST _compact) ... 13. Verify number of revs in LiteServ db (?revs_info=true) check rev status == available fail if revs available > revs limit ... 14. Delete LiteServ db conflicts (?conflicts=true) DELETE _conflicts ... 15. Create numDoc number of docs in LiteServ db ... 16. Update LiteServ db docs numRevs * 5 (600) ... 17. Verify LiteServ db revs is < 602 ... 18. Verify LiteServ db docs revs prefix (9 * numRevs + 3) ... 19. Compact LiteServ db ... 20. Verify number of revs <= 10 ... 21. Delete LiteServ docs ... 22. Delete Server bucket ... 23. Delete LiteServ db """ ls_db_name = "ls_db" sg_db = "db" sg_user_name = "sg_user" num_docs = 10 num_revs = 100 cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_url = setup_client_syncgateway_test["sg_url"] sg_admin_url = setup_client_syncgateway_test["sg_admin_url"] sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_url, config="{}/walrus-revs-limit.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_client_to_sync_gateway_complex_replication_with_revs_limit'") log_info("ls_url: {}".format(ls_url)) log_info("sg_admin_url: {}".format(sg_admin_url)) log_info("sg_url: {}".format(sg_url)) client = MobileRestClient() # Test the endpoint, listener does not support users but should have a default response client.get_session(url=ls_url) sg_user_channels = ["NBC"] client.create_user(url=sg_admin_url, db=sg_db, name=sg_user_name, password="******", channels=sg_user_channels) sg_session = client.create_session(url=sg_admin_url, db=sg_db, name=sg_user_name) ls_db = client.create_database(url=ls_url, name=ls_db_name) ls_db_docs = client.add_docs(url=ls_url, db=ls_db, number=num_docs, id_prefix=ls_db, channels=sg_user_channels) assert len(ls_db_docs) == num_docs # Start replication ls_db -> sg_db repl_one = client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_admin_url, to_db=sg_db ) client.verify_docs_present(url=sg_admin_url, db=sg_db, expected_docs=ls_db_docs) # Delay is to the updates here due to couchbase/couchbase-lite-ios#1277. # Basically, if your revs depth is small and someone is updating a doc past the revs depth before a push replication, # the push replication will have no common ancestor with sync_gateway causing conflicts to be created. # Adding a delay between updates helps this situation. There is an alternative for CBL mac and CBL NET to change the default revs client depth # but that is not configurable for Android. # Currently adding a delay will allow the replication to act as expected for all platforms now. client.update_docs(url=sg_url, db=sg_db, docs=ls_db_docs, number_updates=num_revs, delay=0.1, auth=sg_session) client.update_docs(url=ls_url, db=ls_db, docs=ls_db_docs, number_updates=num_revs, delay=0.1) # Start replication ls_db <- sg_db repl_two = client.start_replication( url=ls_url, continuous=True, from_url=sg_admin_url, from_db=sg_db, to_db=ls_db ) client.wait_for_replication_status_idle(url=ls_url, replication_id=repl_one) client.wait_for_replication_status_idle(url=ls_url, replication_id=repl_two) client.compact_database(url=ls_url, db=ls_db) # LiteServ should only have 20 revisions due to built in client revs limit client.verify_revs_num_for_docs(url=ls_url, db=ls_db, docs=ls_db_docs, expected_revs_per_doc=20) # Sync Gateway should have 100 revisions due to the specified revs_limit in the sg config and possible conflict winners from the liteserv db client.verify_max_revs_num_for_docs(url=sg_url, db=sg_db, docs=ls_db_docs, expected_max_number_revs_per_doc=100, auth=sg_session) client.delete_conflicts(url=ls_url, db=ls_db, docs=ls_db_docs) expected_generation = num_revs + 1 client.verify_docs_rev_generations(url=ls_url, db=ls_db, docs=ls_db_docs, expected_generation=expected_generation) client.verify_docs_rev_generations(url=sg_url, db=sg_db, docs=ls_db_docs, expected_generation=expected_generation, auth=sg_session) client.delete_docs(url=ls_url, db=ls_db, docs=ls_db_docs) client.verify_docs_deleted(url=ls_url, db=ls_db, docs=ls_db_docs) client.verify_docs_deleted(url=sg_admin_url, db=sg_db, docs=ls_db_docs) ls_db_docs = client.add_docs(url=ls_url, db=ls_db, number=num_docs, id_prefix=ls_db, channels=sg_user_channels) assert len(ls_db_docs) == 10 expected_revs = num_revs + 20 + 2 client.update_docs(url=ls_url, db=ls_db, docs=ls_db_docs, delay=0.1, number_updates=num_revs) client.verify_max_revs_num_for_docs(url=ls_url, db=ls_db, docs=ls_db_docs, expected_max_number_revs_per_doc=expected_revs) expected_generation = (num_revs * 2) + 3 client.verify_docs_rev_generations(url=ls_url, db=ls_db, docs=ls_db_docs, expected_generation=expected_generation) client.compact_database(url=ls_url, db=ls_db) client.verify_revs_num_for_docs(url=ls_url, db=ls_db, docs=ls_db_docs, expected_revs_per_doc=20) client.stop_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_admin_url, to_db=sg_db ) client.stop_replication( url=ls_url, continuous=True, from_url=sg_admin_url, from_db=sg_db, to_db=ls_db ) client.wait_for_no_replications(url=ls_url) client.delete_conflicts(url=ls_url, db=ls_db, docs=ls_db_docs) client.delete_conflicts(url=sg_url, db=sg_db, docs=ls_db_docs, auth=sg_session) client.delete_docs(url=ls_url, db=ls_db, docs=ls_db_docs) # Start push pull and verify that all docs are deleted # Start replication ls_db -> sg_db repl_one = client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_admin_url, to_db=sg_db ) # Start replication ls_db <- sg_db repl_two = client.start_replication( url=ls_url, continuous=True, from_url=sg_admin_url, from_db=sg_db, to_db=ls_db ) client.verify_docs_deleted(url=ls_url, db=ls_db, docs=ls_db_docs) client.verify_docs_deleted(url=sg_admin_url, db=sg_db, docs=ls_db_docs)
def test_replication_with_session_cookie(setup_client_syncgateway_test): """Regression test for https://github.com/couchbase/couchbase-lite-android/issues/817 1. SyncGateway Config with guest disabled = true and One user added (e.g. user1 / 1234) 2. Create a new session on SGW for the user1 by using POST /_session. Capture the SyncGatewaySession cookie from the set-cookie in the response header. 3. Start continuous push and pull replicator on the LiteServ with SyncGatewaySession cookie. Make sure that both replicators start correctly 4. Delete the session from SGW by sending DELETE /_sessions/ to SGW 5. Cancel both push and pull replicator on the LiteServ 6. Repeat step 1 and 2 """ ls_db = "ls_db" sg_db = "db" cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_url = setup_client_syncgateway_test["sg_url"] sg_admin_url = setup_client_syncgateway_test["sg_admin_url"] sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_url, config="{}/walrus-user.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_replication_with_session_cookie'") log_info("ls_url: {}".format(ls_url)) log_info("sg_admin_url: {}".format(sg_admin_url)) log_info("sg_url: {}".format(sg_url)) client = MobileRestClient() client.create_database(url=ls_url, name=ls_db) # Get session header for user_1 session_header = client.create_session_header(url=sg_url, db=sg_db, name="user_1", password="******") # Get session id from header session_parts = re.split("=|;", session_header) session_id = session_parts[1] log_info("{}: {}".format(session_parts[0], session_id)) session = (session_parts[0], session_id) # Start authenticated push replication repl_one = client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_url, to_db=sg_db, to_auth=session_header ) # Start authenticated pull replication repl_two = client.start_replication( url=ls_url, continuous=True, from_url=sg_url, from_db=sg_db, from_auth=session_header, to_db=ls_db, ) # Wait for 2 replications to be 'Idle', On .NET they may not be immediately available via _active_tasks client.wait_for_replication_status_idle(ls_url, repl_one) client.wait_for_replication_status_idle(ls_url, repl_two) replications = client.get_replications(ls_url) assert len(replications) == 2, "2 replications (push / pull should be running)" num_docs_pushed = 100 # Sanity test docs ls_docs = client.add_docs(url=ls_url, db=ls_db, number=num_docs_pushed, id_prefix="ls_doc", channels=["ABC"]) assert len(ls_docs) == num_docs_pushed sg_docs = client.add_docs(url=sg_url, db=sg_db, number=num_docs_pushed, id_prefix="sg_doc", auth=session, channels=["ABC"]) assert len(sg_docs) == num_docs_pushed all_docs = client.merge(ls_docs, sg_docs) log_info(all_docs) client.verify_docs_present(url=sg_admin_url, db=sg_db, expected_docs=all_docs) client.verify_docs_present(url=ls_url, db=ls_db, expected_docs=all_docs) # GET from session endpoint /{db}/_session/{session-id} session = client.get_session(url=sg_admin_url, db=sg_db, session_id=session_id) assert len(session["userCtx"]["channels"]) == 2, "There should be only 2 channels for the user" assert "ABC" in session["userCtx"]["channels"], "The channel info should contain 'ABC'" assert session["userCtx"]["name"] == "user_1", "The user should have the name 'user_1'" assert len(session["authentication_handlers"]) == 2, "There should be 2 authentication_handlers" assert "default" in session["authentication_handlers"], "Did not find 'default' in authentication_headers" assert "cookie" in session["authentication_handlers"], "Did not find 'cookie' in authentication_headers" log_info("SESSIONs: {}".format(session)) # Delete session via sg admin port and _user rest endpoint client.delete_session(url=sg_admin_url, db=sg_db, user_name="user_1", session_id=session_id) # Make sure session is deleted try: session = client.get_session(url=sg_admin_url, db=sg_db, session_id=session_id) except HTTPError as he: expected_error_code = he.response.status_code log_info(expected_error_code) assert expected_error_code == 404, "Expected 404 status, actual {}".format(expected_error_code) # Cancel the replications # Stop repl_one client.stop_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_url, to_db=sg_db, to_auth=session_header ) # Stop repl_two client.stop_replication( url=ls_url, continuous=True, from_url=sg_url, from_db=sg_db, from_auth=session_header, to_db=ls_db, ) client.wait_for_no_replications(ls_url) replications = client.get_replications(ls_url) assert len(replications) == 0, "All replications should be stopped" # Create new session and new push / pull replications session_header = client.create_session_header(url=sg_url, db=sg_db, name="user_1", password="******") # Get session id from header session_parts = re.split("=|;", session_header) session_id = session_parts[1] log_info("{}: {}".format(session_parts[0], session_id)) # Start authenticated push replication repl_one = client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_url, to_db=sg_db, to_auth=session_header ) # Start authenticated pull replication repl_two = client.start_replication( url=ls_url, continuous=True, from_url=sg_url, from_db=sg_db, from_auth=session_header, to_db=ls_db, ) replications = client.get_replications(ls_url) assert len(replications) == 2, "2 replications (push / pull should be running), found: {}".format(2) session = client.get_session(url=sg_admin_url, db=sg_db, session_id=session_id) assert len(session["userCtx"]["channels"]) == 2, "There should be only 2 channels for the user" assert "ABC" in session["userCtx"]["channels"], "The channel info should contain 'ABC'" assert session["userCtx"]["name"] == "user_1", "The user should have the name 'user_1'" assert len(session["authentication_handlers"]) == 2, "There should be 2 authentication_handlers" assert "default" in session["authentication_handlers"], "Did not find 'default' in authentication_headers" assert "cookie" in session["authentication_handlers"], "Did not find 'cookie' in authentication_headers" log_info("SESSIONs: {}".format(session)) # Delete session via sg admin port and db rest endpoint client.delete_session(url=sg_admin_url, db=sg_db, session_id=session_id) # Make sure session is deleted try: session = client.get_session(url=sg_admin_url, db=sg_db, session_id=session_id) except HTTPError as he: expected_error_code = he.response.status_code log_info(expected_error_code) assert expected_error_code == 404, "Expected 404 status, actual {}".format(expected_error_code)
def test_multiple_replications_created_with_unique_properties(setup_client_syncgateway_test): """Regression test for couchbase/couchbase-lite-java-core#1386 1. Setup SGW with a remote database name db for an example 2. Create a local database such as ls_db 3. Send POST /_replicate with source = ls_db, target = http://localhost:4985/db, continuous = true 4. Send POST /_replicate with source = ls_db, target = http://localhost:4985/db, continuous = true, doc_ids=["doc1", "doc2"] 5. Send POST /_replicate with source = ls_db, target = http://localhost:4985/db, continuous = true, filter="filter1" 6. Make sure that the session_id from each POST /_replicate are different. 7. Send GET /_active_tasks to make sure that there are 3 tasks created. 8. Send 3 POST /_replicate withe the same parameter as Step 3=5 plus cancel=true to stop those replicators 9. Repeat Step 3 - 8 with source = and target = db for testing the pull replicator. """ sg_db = "db" ls_db = "ls_db" cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_one_admin = setup_client_syncgateway_test["sg_admin_url"] sg_one_public = setup_client_syncgateway_test["sg_url"] sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_one_public, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_multiple_replications_created_with_unique_properties'") log_info("ls_url: {}".format(ls_url)) log_info("sg_one_admin: {}".format(sg_one_admin)) log_info("sg_one_public: {}".format(sg_one_public)) client = MobileRestClient() client.create_database(url=ls_url, name=ls_db) ######## # PUSH # ######## # Start 3 unique push replication requests repl_one = client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db ) client.wait_for_replication_status_idle(ls_url, repl_one) repl_two = client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db, doc_ids=["doc_1", "doc_2"] ) client.wait_for_replication_status_idle(ls_url, repl_two) # Create doc filter and add to the design doc filters = { "language": "javascript", "filters": { "sample_filter": "function(doc, req) { if (doc.type && doc.type === \"skip\") { return false; } return true; }" } } client.add_design_doc(url=ls_url, db=ls_db, name="by_type", doc=json.dumps(filters)) repl_three = client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db, repl_filter="by_type/sample_filter" ) client.wait_for_replication_status_idle(ls_url, repl_three) # Verify 3 replicaitons are running replications = client.get_replications(ls_url) log_info(replications) assert len(replications) == 3, "Number of replications, Expected: {} Actual: {}".format( 3, len(replications) ) # Stop repl001 client.stop_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db ) # Stop repl002 client.stop_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db, doc_ids=["doc_1", "doc_2"] ) # Stop repl003 client.stop_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db, repl_filter="by_type/sample_filter" ) # Verify no replications are running client.wait_for_no_replications(ls_url) replications = client.get_replications(ls_url) log_info(replications) assert len(replications) == 0, "Number of replications, Expected: {} Actual: {}".format( 0, len(replications) ) ######## # PULL # ######## # Start 3 unique push replication requests repl_four = client.start_replication( url=ls_url, continuous=True, from_url=sg_one_admin, from_db=sg_db, to_db=ls_db ) client.wait_for_replication_status_idle(ls_url, repl_four) # Start filtered pull from sync gateway to LiteServ repl_five = client.start_replication( url=ls_url, continuous=True, from_url=sg_one_admin, from_db=sg_db, to_db=ls_db, channels_filter=["ABC", "CBS"] ) client.wait_for_replication_status_idle(ls_url, repl_five) # Verify 3 replicaitons are running replications = client.get_replications(ls_url) log_info(replications) assert len(replications) == 2, "Number of replications, Expected: {} Actual: {}".format( 2, len(replications) ) # Stop repl_four client.stop_replication( url=ls_url, continuous=True, from_url=sg_one_admin, from_db=sg_db, to_db=ls_db ) # Stop repl_five client.stop_replication( url=ls_url, continuous=True, from_url=sg_one_admin, from_db=sg_db, to_db=ls_db, channels_filter=["ABC", "CBS"] ) # Verify no replications are running client.wait_for_no_replications(ls_url) replications = client.get_replications(ls_url) log_info(replications) assert len(replications) == 0, "Number of replications, Expected: {} Actual: {}".format( 0, len(replications) )
def test_initial_pull_replication(setup_client_syncgateway_test, continuous): """ 1. Prepare sync-gateway to have 10000 documents. 2. Create a single shot / continuous pull replicator and to pull the docs into a database. 3. Verify if all of the docs get pulled. Referenced issue: couchbase/couchbase-lite-android#955. """ sg_db = "db" ls_db = "ls_db" num_docs = 10000 cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_one_admin = setup_client_syncgateway_test["sg_admin_url"] sg_one_public = setup_client_syncgateway_test["sg_url"] sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_one_public, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_initial_pull_replication', continuous: {}".format(continuous)) log_info("ls_url: {}".format(ls_url)) log_info("sg_one_admin: {}".format(sg_one_admin)) log_info("sg_one_public: {}".format(sg_one_public)) client = MobileRestClient() client.create_user(sg_one_admin, sg_db, "seth", password="******", channels=["ABC", "NBC"]) session = client.create_session(sg_one_admin, sg_db, "seth") # Create 'num_docs' docs on sync_gateway docs = client.add_docs( url=sg_one_public, db=sg_db, number=num_docs, id_prefix="seeded_doc", generator="four_k", auth=session ) assert len(docs) == num_docs client.create_database(url=ls_url, name=ls_db) # Start oneshot pull replication repl_id = client.start_replication( url=ls_url, continuous=continuous, from_url=sg_one_admin, from_db=sg_db, to_db=ls_db ) start = time.time() if continuous: log_info("Waiting for replication status 'Idle' for: {}".format(repl_id)) # Android will report IDLE status, and drop into the 'verify_docs_present' below # due to https://github.com/couchbase/couchbase-lite-java-core/issues/1409 client.wait_for_replication_status_idle(ls_url, repl_id) else: log_info("Waiting for no replications: {}".format(repl_id)) client.wait_for_no_replications(ls_url) # Verify docs replicated to client client.verify_docs_present(url=ls_url, db=ls_db, expected_docs=docs, timeout=240) all_docs_replicated_time = time.time() - start log_info("Replication took: {}s".format(all_docs_replicated_time)) # Verify docs show up in client's changes feed client.verify_docs_in_changes(url=ls_url, db=ls_db, expected_docs=docs) replications = client.get_replications(url=ls_url) if continuous: assert len(replications) == 1, "There should only be one replication running" assert replications[0]["status"] == "Idle", "Replication Status should be 'Idle'" assert replications[0]["continuous"], "Running replication should be continuous" # Only .NET has an 'error' property if "error" in replications[0]: assert len(replications[0]["error"]) == 0 else: assert len(replications) == 0, "No replications should be running"
def test_multiple_replications_not_created_with_same_properties(setup_client_syncgateway_test): """Regression test for https://github.com/couchbase/couchbase-lite-android/issues/939 1. Create LiteServ database and launch sync_gateway with database 2. Start 5 continuous push replicators with the same source and target 3. Make sure the sample replication id is returned 4. Check that 1 one replication exists in 'active_tasks' 5. Stop the replication with POST /_replicate cancel=true 6. Start 5 continuous pull replicators with the same source and target 7. Make sure the sample replication id is returned 8. Check that 1 one replication exists in 'active_tasks' 9. Stop the replication with POST /_replicate cancel=true """ sg_db = "db" ls_db = "ls_db" cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_one_admin = setup_client_syncgateway_test["sg_admin_url"] sg_one_public = setup_client_syncgateway_test["sg_url"] sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_one_public, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_multiple_replications_not_created_with_same_properties'") log_info("ls_url: {}".format(ls_url)) log_info("sg_one_admin: {}".format(sg_one_admin)) log_info("sg_one_public: {}".format(sg_one_public)) client = MobileRestClient() client.create_database(url=ls_url, name=ls_db) repl_id_num = 0 response_one_id_num = 0 response_two_id_num = 0 # launch 50 concurrent push replication requests with the same source / target with ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit( client.start_replication, url=ls_url, continuous=True, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db ) for _ in range(50)] for future in as_completed(futures): response_one_id = future.result() # Convert session_id from string "repl001" -> int 1 response_one_id_num = int(response_one_id.replace("repl", "")) log_info(response_one_id_num) # Assert that concurrent replications have a greater session id than 0 assert response_one_id_num > repl_id_num, "'response_one_id_num': {} should be greater than 'repl_id_num': {}".format( response_one_id_num, repl_id_num ) # Check there is only one replication running replications = client.get_replications(ls_url) assert len(replications) == 1, "Number of replications, Expected: {} Actual {}".format( 1, len(replications) ) # Stop replication client.stop_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db ) # Check that no replications are running client.wait_for_no_replications(ls_url) replications = client.get_replications(ls_url) assert len(replications) == 0, "Number of replications, Expected: {} Actual {}".format( 0, len(replications) ) # launch 50 concurrent pull replication requests with the same source / target with ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit( client.start_replication, url=ls_url, continuous=True, from_db=sg_db, from_url=sg_one_admin, to_db=ls_db ) for _ in range(50)] for future in as_completed(futures): response_two_id = future.result() # Convert session_id from string "repl001" -> int 1 response_two_id_num = int(response_two_id.replace("repl", "")) log_info(response_two_id_num) # Assert that the second set of concurrent replication requests has a higher id than the first assert response_two_id_num > response_one_id_num, "'response_two_id_num': {} should be greater than 'response_one_id_num': {}".format( response_two_id_num, response_one_id_num ) # Check there is only one replication running replications = client.get_replications(ls_url) assert len(replications) == 1, "Number of replications, Expected: {} Actual {}".format( 1, len(replications) ) # Stop replication client.stop_replication( url=ls_url, continuous=True, from_db=sg_db, from_url=sg_one_admin, to_db=ls_db ) # Check that no replications are running client.wait_for_no_replications(ls_url) replications = client.get_replications(ls_url) assert len(replications) == 0, "Number of replications, Expected: {} Actual {}".format( 0, len(replications) )
def test_initial_push_replication(setup_client_syncgateway_test, continuous): """ 1. Prepare LiteServ to have 10000 documents. 2. Create a single shot push / continuous replicator and to push the docs into a sync_gateway database. 3. Verify if all of the docs get pushed. """ sg_db = "db" ls_db = "ls_db" seth_channels = ["ABC", "NBC"] num_docs = 10000 cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_one_admin = setup_client_syncgateway_test["sg_admin_url"] sg_one_public = setup_client_syncgateway_test["sg_url"] sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_one_public, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_initial_push_replication', continuous: {}".format(continuous)) log_info("ls_url: {}".format(ls_url)) log_info("sg_one_admin: {}".format(sg_one_admin)) log_info("sg_one_public: {}".format(sg_one_public)) client = MobileRestClient() client.create_user(sg_one_admin, sg_db, "seth", password="******", channels=seth_channels) session = client.create_session(sg_one_admin, sg_db, "seth") client.create_database(url=ls_url, name=ls_db) # Create 'num_docs' docs on LiteServ docs = client.add_docs( url=ls_url, db=ls_db, number=num_docs, id_prefix="seeded_doc", generator="four_k", channels=seth_channels ) assert len(docs) == num_docs # Start push replication repl_id = client.start_replication( url=ls_url, continuous=continuous, from_db=ls_db, to_url=sg_one_admin, to_db=sg_db ) if continuous: log_info("Waiting for replication status 'Idle' for: {}".format(repl_id)) client.wait_for_replication_status_idle(ls_url, repl_id) else: log_info("Waiting for no replications: {}".format(repl_id)) client.wait_for_no_replications(ls_url) # Verify docs replicated to sync_gateway client.verify_docs_present(url=sg_one_public, db=sg_db, expected_docs=docs, auth=session) # Verify docs show up in sync_gateway's changes feed client.verify_docs_in_changes(url=sg_one_public, db=sg_db, expected_docs=docs, auth=session) replications = client.get_replications(url=ls_url) if continuous: assert len(replications) == 1, "There should only be one replication running" assert replications[0]["status"] == "Idle", "Replication Status should be 'Idle'" assert replications[0]["continuous"], "Running replication should be continuous" # Only .NET has an 'error' property if "error" in replications[0]: assert len(replications[0]["error"]) == 0 else: assert len(replications) == 0, "No replications should be running"
def test_auto_prune_listener_keeps_conflicts_sanity(setup_client_syncgateway_test): """" 1. Create db on LiteServ and add docs 2. Create db on sync_gateway and add docs with the same id 3. Create one shot push / pull replication 4. Update LiteServ 50 times 5. Assert that pruned conflict is still present 6. Delete the current revision and check that a GET returns the old conflict as the current rev """ cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_url = setup_client_syncgateway_test["sg_url"] sg_admin_url = setup_client_syncgateway_test["sg_admin_url"] client = MobileRestClient() sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_url, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_auto_prune_listener_keeps_conflicts_sanity' ...") log_info("ls_url: {}".format(ls_url)) log_info("sg_url: {}".format(sg_url)) log_info("sg_admin_url: {}".format(sg_admin_url)) num_docs = 1 num_revs = 100 sg_db = "db" ls_db = "ls_db" sg_user_name = "sg_user" sg_user_channels = ["NBC"] client.create_user(url=sg_admin_url, db=sg_db, name=sg_user_name, password="******", channels=sg_user_channels) sg_session = client.create_session(url=sg_admin_url, db=sg_db, name=sg_user_name) ls_db = client.create_database(url=ls_url, name=ls_db) # Create docs with same prefix to create conflicts when the dbs complete 1 shot replication ls_db_docs = client.add_docs(url=ls_url, db=ls_db, number=num_docs, id_prefix="doc", channels=sg_user_channels) assert len(ls_db_docs) == num_docs sg_db_docs = client.add_docs( url=sg_url, db=sg_db, number=num_docs, id_prefix="doc", channels=sg_user_channels, auth=sg_session ) assert len(sg_db_docs) == num_docs # Setup one shot pull replication and wait for idle. client.start_replication(url=ls_url, continuous=False, from_url=sg_admin_url, from_db=sg_db, to_db=ls_db) client.wait_for_no_replications(url=ls_url) # There should now be a conflict on the client conflicting_revs = client.get_conflict_revs(url=ls_url, db=ls_db, doc=ls_db_docs[0]) # Get the doc with conflict rev client.get_doc(url=ls_url, db=ls_db, doc_id=ls_db_docs[0]["id"], rev=conflicting_revs[0]) # Update doc past revs limit and make sure conflict is still available updated_doc = client.update_doc(url=ls_url, db=ls_db, doc_id=ls_db_docs[0]["id"], number_updates=num_revs) client.get_doc(url=ls_url, db=ls_db, doc_id=ls_db_docs[0]["id"], rev=conflicting_revs[0]) # Delete doc and ensure that the conflict is now the current rev client.delete_doc(url=ls_url, db=ls_db, doc_id=ls_db_docs[0]["id"], rev=updated_doc["rev"]) current_doc = client.get_doc(url=ls_url, db=ls_db, doc_id=ls_db_docs[0]["id"]) assert current_doc["_rev"] == conflicting_revs[0]
def test_attachment_revpos_when_ancestor_unavailable(params_from_base_test_setup, sg_conf_name): """ Creates a document with an attachment, then updates that document so that the body of the revision that originally pushed the document is no longer available. Add a new revision that's not a child of the active revision, and validate that it's uploaded successfully. Example: 1. Document is created with attachment at rev-1 2. Document is updated (strip digests and length, only put revpos & stub) multiple times on the server, goes to rev-4 3. Client attempts to add a new (conflicting) revision 2, with parent rev-1. 4. If the body of rev-1 is no longer available on the server (temporary backup of revision has expired, and is no longer stored in the in-memory rev cache), we were throwing an error to client because we couldn't verify based on the _attachments property in rev-1. 5. In this scenario, before returning error, we are now checking if the active revision has a common ancestor with the incoming revision. If so, we can validate any revpos values equal to or earlier than the common ancestor against the active revision """ cluster_config = params_from_base_test_setup["cluster_config"] mode = params_from_base_test_setup["mode"] sg_conf = sync_gateway_config_path_for_mode(sg_conf_name, mode) cluster_helper = ClusterKeywords() cluster_helper.reset_cluster(cluster_config, sg_conf) topology = cluster_helper.get_cluster_topology(cluster_config) cbs_url = topology["couchbase_servers"][0] sg_url = topology["sync_gateways"][0]["public"] sg_url_admin = topology["sync_gateways"][0]["admin"] sg_db = "db" bucket = "data-bucket" log_info("Running 'test_attachment_revpos_when_ancestor_unavailable'") log_info("Using cbs_url: {}".format(cbs_url)) log_info("Using sg_url: {}".format(sg_url)) log_info("Using sg_url_admin: {}".format(sg_url_admin)) log_info("Using sg_db: {}".format(sg_db)) log_info("Using bucket: {}".format(bucket)) channels_list = ["ABC"] client = MobileRestClient() sg_util = SyncGateway() cb_server = CouchbaseServer(cbs_url) user1 = client.create_user(url=sg_url_admin, db=sg_db, name="user1", password="******", channels=channels_list) doc_with_att = document.create_doc(doc_id="att_doc", content={"sample_key": "sample_val"}, attachment_name="sample_text.txt", channels=channels_list) doc_gen_1 = client.add_doc(url=sg_url, db=sg_db, doc=doc_with_att, auth=user1) client.update_doc(url=sg_url, db=sg_db, doc_id=doc_gen_1["id"], number_updates=10, auth=user1) # Clear cached rev doc bodys from server and cycle sync_gateway sg_util.stop_sync_gateway(cluster_config=cluster_config, url=sg_url) cb_server.delete_couchbase_server_cached_rev_bodies(bucket=bucket) sg_util.start_sync_gateway(cluster_config=cluster_config, url=sg_url, config=sg_conf) client.add_conflict( url=sg_url, db=sg_db, doc_id=doc_gen_1["id"], parent_revisions=doc_gen_1["rev"], new_revision="2-foo", auth=user1 )
def test_stale_revision_should_not_be_in_the_index(setup_client_syncgateway_test): """original ticket: https://github.com/couchbase/couchbase-lite-android/issues/855 scenario: 1. Running sync_gateway 2. Create database and starts both push and pull replicators through client REST API 3. Create two or more views through client REST API 4. Add doc, and verify doc is index with current revision through client REST API 5. Make sure document is pushed to sync gateway through sync gateway REST API 6. Update doc with sync gateway (not client side) through sync gateway REST API 7. Make sure updated document is pull replicated to client through client REST API 8. Make sure updated document is indexed through client REST API 9. Make sure stale revision is deleted from index. through client REST API 10. Pass criteria """ cluster_config = setup_client_syncgateway_test["cluster_config"] ls_url = setup_client_syncgateway_test["ls_url"] sg_url = setup_client_syncgateway_test["sg_url"] sg_admin_url = setup_client_syncgateway_test["sg_admin_url"] num_docs = 10 num_revs = 100 d_doc_name = "dd" sg_db = "db" sg_user_name = "sg_user" sg_helper = SyncGateway() sg_helper.start_sync_gateway( cluster_config=cluster_config, url=sg_url, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS) ) log_info("Running 'test_stale_revision_should_not_be_in_the_index'") log_info("ls_url: {}".format(ls_url)) log_info("sg_admin_url: {}".format(sg_admin_url)) log_info("sg_url: {}".format(sg_url)) log_info("num_docs: {}".format(num_docs)) log_info("num_revs: {}".format(num_revs)) client = MobileRestClient() sg_user_channels = ["NBC"] client.create_user(url=sg_admin_url, db=sg_db, name=sg_user_name, password="******", channels=sg_user_channels) sg_session = client.create_session(url=sg_admin_url, db=sg_db, name=sg_user_name) view = """{ "language" : "javascript", "views" : { "content_view" : { "map" : "function(doc, meta) { if (doc.content) { emit(doc._id, doc._rev); } }" }, "update_view" : { "map" : "function(doc, meta) { emit(doc.updates, null); }" } } }""" ls_db = client.create_database(url=ls_url, name="ls_db") # Setup continuous push / pull replication from ls_db1 to sg_db client.start_replication( url=ls_url, continuous=True, from_db=ls_db, to_url=sg_admin_url, to_db=sg_db ) client.start_replication( url=ls_url, continuous=True, from_url=sg_admin_url, from_db=sg_db, to_db=ls_db ) design_doc_id = client.add_design_doc(url=ls_url, db=ls_db, name=d_doc_name, doc=view) client.get_doc(url=ls_url, db=ls_db, doc_id=design_doc_id) doc_body = document.create_doc(doc_id="doc_1", content={"hi": "I should be in the view"}, channels=sg_user_channels) log_info(doc_body) doc_body_2 = document.create_doc(doc_id="doc_2", channels=sg_user_channels) doc = client.add_doc(url=ls_url, db=ls_db, doc=doc_body) doc_2 = client.add_doc(url=ls_url, db=ls_db, doc=doc_body_2) content_view_rows = client.get_view(url=ls_url, db=ls_db, design_doc_id=design_doc_id, view_name="content_view") client.verify_view_row_num(view_response=content_view_rows, expected_num_rows=1) update_view_rows = client.get_view(url=ls_url, db=ls_db, design_doc_id=design_doc_id, view_name="update_view") client.verify_view_row_num(view_response=update_view_rows, expected_num_rows=2) expected_docs_list = [doc, doc_2] client.verify_docs_present(url=sg_url, db=sg_db, expected_docs=expected_docs_list, auth=sg_session) updated_doc = client.update_doc(url=sg_url, db=sg_db, doc_id=doc["id"], number_updates=10, auth=sg_session) client.verify_docs_present(url=ls_url, db=ls_db, expected_docs=updated_doc) content_view_rows_2 = client.get_view(url=ls_url, db=ls_db, design_doc_id=design_doc_id, view_name="content_view") client.verify_view_row_num(view_response=content_view_rows_2, expected_num_rows=1) client.verify_view_contains_keys(view_response=content_view_rows_2, keys=doc["id"]) client.verify_view_contains_values(view_response=content_view_rows_2, values=updated_doc["rev"])
def test_listener_two_sync_gateways(setup_client_2sgs_test): """ Port of https://github.com/couchbaselabs/sync-gateway-tests/blob/master/tests/cbl-replication-mismatch-2-gateways.js Scenario: 1. Start 2 sync_gateways 2. Create sg_db_one db on sync_gateway one 3. Create sg_db_two db on sync_gateway two 4. Create ls_db_one and ls_db_two on Liteserv 5. Setup continuous push / pull replication from ls_db_one <-> sg_db_one 6. Setup continuous push / pull replication from ls_db_two <-> sg_db_two 7. Setup continuous push / pull replication from sg_db_one <-> ls_db_two 8. Setup continuous push / pull replication from sg_db_two <-> ls_db_one 9. Add num_docs / 2 to each liteserv database 10. Verify each database has num_docs docs 11. Verify all_docs in all dbs 12. Verify changes feed for sg_db_one and sg_db_two 13. Verify chnages feed for ls_db_one and ls_db_two """ num_docs = 500 ls_url = setup_client_2sgs_test["ls_url"] cluster_config = setup_client_2sgs_test["cluster_config"] sg_one_admin_url = setup_client_2sgs_test["sg_one_admin_url"] sg_two_admin_url = setup_client_2sgs_test["sg_two_admin_url"] sg_util = SyncGateway() sg_util.start_sync_gateway(cluster_config=cluster_config, url=sg_one_admin_url, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS)) sg_util.start_sync_gateway(cluster_config=cluster_config, url=sg_two_admin_url, config="{}/walrus.json".format(SYNC_GATEWAY_CONFIGS)) ls_db_one = "ls_db1" ls_db_two = "ls_db2" sg_db_one = "sg_db1" sg_db_two = "sg_db2" log_info("ls_url: {}".format(ls_url)) log_info("sg_one_admin_url: {}".format(sg_one_admin_url)) log_info("sg_two_admin_url: {}".format(sg_two_admin_url)) log_info("num_docs: {}".format(num_docs)) log_info("Running 'test_listener_two_sync_gateways' ...") client = MobileRestClient() # Create dbs on sync_gateway client.create_database(sg_one_admin_url, sg_db_one, "walrus:") client.create_database(sg_two_admin_url, sg_db_two, "walrus:") # Create dbs on LiteServ client.create_database(ls_url, ls_db_one) client.create_database(ls_url, ls_db_two) # Start continuous push pull replication ls_db_one <-> sg_db_one client.start_replication( url=ls_url, continuous=True, from_db=ls_db_one, to_url=sg_one_admin_url, to_db=sg_db_one ) client.start_replication( url=ls_url, continuous=True, from_url=sg_one_admin_url, from_db=sg_db_one, to_db=ls_db_one ) # Start continuous push pull replication ls_db_two <-> sg_db_two client.start_replication( url=ls_url, continuous=True, from_db=ls_db_two, to_url=sg_two_admin_url, to_db=sg_db_two ) client.start_replication( url=ls_url, continuous=True, from_url=sg_two_admin_url, from_db=sg_db_two, to_db=ls_db_two ) # Start continuous push pull replication sg_db_one <-> ls_db_two client.start_replication( url=ls_url, continuous=True, from_url=sg_one_admin_url, from_db=sg_db_one, to_db=ls_db_two ) client.start_replication( url=ls_url, continuous=True, from_db=ls_db_two, to_url=sg_one_admin_url, to_db=sg_db_one ) # Start continuous push pull replication sg_db_two <-> ls_db_one client.start_replication( url=ls_url, continuous=True, from_url=sg_two_admin_url, from_db=sg_db_two, to_db=ls_db_one ) client.start_replication( url=ls_url, continuous=True, from_db=ls_db_one, to_url=sg_two_admin_url, to_db=sg_db_two ) ls_db_one_docs = client.add_docs(url=ls_url, db=ls_db_one, number=num_docs / 2, id_prefix="ls_db_one_doc") assert len(ls_db_one_docs) == num_docs / 2 ls_db_two_docs = client.add_docs(url=ls_url, db=ls_db_two, number=num_docs / 2, id_prefix="ls_db_two_doc") assert len(ls_db_two_docs) == num_docs / 2 all_docs = client.merge(ls_db_one_docs, ls_db_two_docs) assert len(all_docs) == 500 # Verify docs replicate to each db client.verify_docs_present(url=ls_url, db=ls_db_one, expected_docs=all_docs) client.verify_docs_present(url=ls_url, db=ls_db_two, expected_docs=all_docs) client.verify_docs_present(url=sg_one_admin_url, db=sg_db_one, expected_docs=all_docs) client.verify_docs_present(url=sg_two_admin_url, db=sg_db_two, expected_docs=all_docs) # Verify changes feeds for each db client.verify_docs_in_changes(url=ls_url, db=ls_db_one, expected_docs=all_docs) client.verify_docs_in_changes(url=ls_url, db=ls_db_two, expected_docs=all_docs) client.verify_docs_in_changes(url=sg_one_admin_url, db=sg_db_one, expected_docs=all_docs) client.verify_docs_in_changes(url=sg_two_admin_url, db=sg_db_two, expected_docs=all_docs)