async def test_foxx_development_toggle(db, cluster): if cluster: pytest.skip('Not tested in a cluster setup') service_mount = generate_service_mount() missing_mount = generate_service_mount() # Prep the test service await db.foxx.create_service( mount=service_mount, source=service_file, development=False, ) # Test enable development mode service = await db.foxx.enable_development(service_mount) assert service['mount'] == service_mount assert service['name'] == 'test' assert service['development'] is True # Test enable development mode for missing service with assert_raises(FoxxDevModeEnableError) as err: await db.foxx.enable_development(missing_mount) assert err.value.error_code == 3009 # Test disable development mode service = await db.foxx.disable_development(service_mount) assert service['mount'] == service_mount assert service['name'] == 'test' assert service['development'] is False # Test disable development mode for missing service with assert_raises(FoxxDevModeDisableError) as err: await db.foxx.disable_development(missing_mount) assert err.value.error_code == 3009
async def test_user_change_password(client, sys_db, cluster): if cluster: pytest.skip('Not tested in a cluster setup') username = generate_username() password1 = generate_string() password2 = generate_string() await sys_db.create_user(username, password1) await sys_db.update_permission(username, 'rw', sys_db.name) db1 = await client.db(sys_db.name, username, password1) db2 = await client.db(sys_db.name, username, password2) # Check authentication assert isinstance(await db1.properties(), dict) with assert_raises(DatabasePropertiesError) as err: await db2.properties() assert err.value.http_code == 401 # Update the user password and check again await sys_db.update_user(username, password2) assert isinstance(await db2.properties(), dict) with assert_raises(DatabasePropertiesError) as err: await db1.properties() assert err.value.http_code == 401 # Replace the user password back and check again await sys_db.update_user(username, password1) assert isinstance(await db1.properties(), dict) with assert_raises(DatabasePropertiesError) as err: await db2.properties() assert err.value.http_code == 401
async def test_delete_index(icol, bad_col): old_indexes = set(await extract('id', await icol.indexes())) icol.add_hash_index(['attr3', 'attr4'], unique=True) icol.add_skiplist_index(['attr3', 'attr4'], unique=True) icol.add_fulltext_index(fields=['attr3'], min_length=10) new_indexes = set(await extract('id', await icol.indexes())) assert new_indexes.issuperset(old_indexes) indexes_to_delete = new_indexes - old_indexes for index_id in indexes_to_delete: assert await icol.delete_index(index_id) is True new_indexes = set(await extract('id', await icol.indexes())) assert new_indexes == old_indexes # Test delete missing indexes for index_id in indexes_to_delete: assert await icol.delete_index(index_id, ignore_missing=True) is False for index_id in indexes_to_delete: with assert_raises(IndexDeleteError) as err: await icol.delete_index(index_id, ignore_missing=False) assert err.value.error_code == 1212 # Test delete indexes with bad collection for index_id in indexes_to_delete: with assert_raises(IndexDeleteError) as err: await bad_col.delete_index(index_id, ignore_missing=False) assert err.value.error_code in {11, 1228}
async def test_wal_misc_methods(sys_db, bad_db): try: await sys_db.wal.properties() except WALPropertiesError as err: if err.http_code == 501: pytest.skip('WAL not implemented') # Test get properties properties = await sys_db.wal.properties() assert 'oversized_ops' in properties assert 'log_size' in properties assert 'historic_logs' in properties assert 'reserve_logs' in properties assert 'throttle_wait' in properties assert 'throttle_limit' in properties # Test get properties with bad database with assert_raises(WALPropertiesError) as err: await bad_db.wal.properties() assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND} # Test configure properties await sys_db.wal.configure(historic_logs=15, oversized_ops=False, log_size=30000000, reserve_logs=5, throttle_limit=0, throttle_wait=16000) properties = await sys_db.wal.properties() assert properties['historic_logs'] == 15 assert properties['oversized_ops'] is False assert properties['log_size'] == 30000000 assert properties['reserve_logs'] == 5 assert properties['throttle_limit'] == 0 assert properties['throttle_wait'] == 16000 # Test configure properties with bad database with assert_raises(WALConfigureError) as err: await bad_db.wal.configure(log_size=2000000) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND} # Test get transactions result = await sys_db.wal.transactions() assert 'count' in result assert 'last_collected' in result # Test get transactions with bad database with assert_raises(WALTransactionListError) as err: await bad_db.wal.transactions() assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND} # Test flush result = await sys_db.wal.flush(garbage_collect=False, sync=False) assert isinstance(result, bool) # Test flush with bad database with assert_raises(WALFlushError) as err: await bad_db.wal.flush(garbage_collect=False, sync=False) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_vertex_collection_management(db, graph, bad_graph): # Test create valid "from" vertex collection fvcol_name = generate_col_name() assert not await graph.has_vertex_collection(fvcol_name) assert not await db.has_collection(fvcol_name) fvcol = await graph.create_vertex_collection(fvcol_name) assert await graph.has_vertex_collection(fvcol_name) assert await db.has_collection(fvcol_name) assert fvcol.name == fvcol_name assert fvcol.graph == graph.name assert fvcol_name in repr(fvcol) assert fvcol_name in await graph.vertex_collections() assert fvcol_name in await extract('name', await db.collections()) # Test create duplicate vertex collection with assert_raises(VertexCollectionCreateError) as err: await graph.create_vertex_collection(fvcol_name) assert err.value.error_code == 1938 assert fvcol_name in await graph.vertex_collections() assert fvcol_name in await extract('name', await db.collections()) # Test create valid "to" vertex collection tvcol_name = generate_col_name() assert not await graph.has_vertex_collection(tvcol_name) assert not await db.has_collection(tvcol_name) tvcol = await graph.create_vertex_collection(tvcol_name) assert await graph.has_vertex_collection(tvcol_name) assert await db.has_collection(tvcol_name) assert tvcol_name == tvcol_name assert tvcol.graph == graph.name assert tvcol_name in repr(tvcol) assert tvcol_name in await graph.vertex_collections() assert tvcol_name in await extract('name', await db.collections()) # Test list vertex collection via bad database with assert_raises(VertexCollectionListError) as err: await bad_graph.vertex_collections() assert err.value.error_code in {11, 1228} # Test delete missing vertex collection with assert_raises(VertexCollectionDeleteError) as err: await graph.delete_vertex_collection(generate_col_name()) assert err.value.error_code in {1926, 1928} # Test delete "to" vertex collection with purge option assert await graph.delete_vertex_collection(tvcol_name, purge=True) is True assert tvcol_name not in await graph.vertex_collections() assert fvcol_name in await extract('name', await db.collections()) assert tvcol_name not in await extract('name', await db.collections()) assert not await graph.has_vertex_collection(tvcol_name) # Test delete "from" vertex collection without purge option assert await graph.delete_vertex_collection(fvcol_name, purge=False) is True assert fvcol_name not in await graph.vertex_collections() assert fvcol_name in await extract('name', await db.collections()) assert not await graph.has_vertex_collection(fvcol_name)
async def test_aql_cache_management(db, bad_db): # Test get AQL cache properties properties = await db.aql.cache.properties() assert 'mode' in properties assert 'max_results' in properties assert 'max_results_size' in properties assert 'max_entry_size' in properties assert 'include_system' in properties # Test get AQL cache properties with bad database with assert_raises(AQLCachePropertiesError): await bad_db.aql.cache.properties() # Test get AQL cache configure properties properties = await db.aql.cache.configure( mode='on', max_results=100, max_results_size=10000, max_entry_size=10000, include_system=True ) assert properties['mode'] == 'on' assert properties['max_results'] == 100 assert properties['max_results_size'] == 10000 assert properties['max_entry_size'] == 10000 assert properties['include_system'] is True properties = await db.aql.cache.properties() assert properties['mode'] == 'on' assert properties['max_results'] == 100 assert properties['max_results_size'] == 10000 assert properties['max_entry_size'] == 10000 assert properties['include_system'] is True # Test get AQL cache configure properties with bad database with assert_raises(AQLCacheConfigureError): await bad_db.aql.cache.configure(mode='on') # Test get AQL cache entries result = await db.aql.cache.entries() assert isinstance(result, list) # Test get AQL cache entries with bad database with assert_raises(AQLCacheEntriesError) as err: await bad_db.aql.cache.entries() assert err.value.error_code in {11, 1228} # Test get AQL cache clear result = await db.aql.cache.clear() assert isinstance(result, bool) # Test get AQL cache clear with bad database with assert_raises(AQLCacheClearError) as err: await bad_db.aql.cache.clear() assert err.value.error_code in {11, 1228}
async def test_analyzer_management(db, bad_db, cluster): analyzer_name = generate_analyzer_name() full_analyzer_name = db.name + '::' + analyzer_name bad_analyzer_name = generate_analyzer_name() # Test create analyzer result = await db.create_analyzer(analyzer_name, 'identity', {}) assert result['name'] == full_analyzer_name assert result['type'] == 'identity' assert result['properties'] == {} assert result['features'] == [] # Test create duplicate with bad database with assert_raises(AnalyzerCreateError) as err: await bad_db.create_analyzer(analyzer_name, 'identity', {}, []) assert err.value.error_code in {11, 1228} # Test get analyzer result = await db.analyzer(analyzer_name) assert result['name'] == full_analyzer_name assert result['type'] == 'identity' assert result['properties'] == {} assert result['features'] == [] # Test get missing analyzer with assert_raises(AnalyzerGetError) as err: await db.analyzer(bad_analyzer_name) assert err.value.error_code in {1202} # Test list analyzers result = await db.analyzers() assert full_analyzer_name in [a['name'] for a in result] # Test list analyzers with bad database with assert_raises(AnalyzerListError) as err: await bad_db.analyzers() assert err.value.error_code in {11, 1228} # Test delete analyzer assert await db.delete_analyzer(analyzer_name, force=True) is True assert full_analyzer_name not in [a['name'] for a in await db.analyzers()] # Test delete missing analyzer with assert_raises(AnalyzerDeleteError) as err: await db.delete_analyzer(analyzer_name) assert err.value.error_code in {1202} # Test delete missing analyzer with ignore_missing set to True assert await db.delete_analyzer(analyzer_name, ignore_missing=True) is False
async def test_add_fulltext_index(icol): # Test add fulltext index with one attributes result = await icol.add_fulltext_index(fields=['attr1'], min_length=10, name='fulltext_index', in_background=True) expected_index = { 'sparse': True, 'type': 'fulltext', 'fields': ['attr1'], 'min_length': 10, 'unique': False, 'name': 'fulltext_index' } for key, value in expected_index.items(): assert result[key] == value assert result['id'] in await extract('id', await icol.indexes()) # Test add fulltext index with two attributes (should fail) with assert_raises(IndexCreateError) as err: await icol.add_fulltext_index(fields=['attr1', 'attr2']) assert err.value.error_code == 10 # Clean up the index await icol.delete_index(result['id'])
async def test_replication_make_slave(sys_db, bad_db, url, replication): if not replication: pytest.skip('Only tested for replication') await sys_db.replication.stop_applier() result = await sys_db.replication.make_slave( endpoint='tcp://192.168.1.65:8500', database='test', username='******', password='******', restrict_type='include', restrict_collections=['test'], include_system=False, max_connect_retries=5, connect_timeout=500, request_timeout=500, chunk_size=0, adaptive_polling=False, auto_resync=False, auto_resync_retries=0, initial_sync_max_wait_time=0, connection_retry_wait_time=0, idle_min_wait_time=0, idle_max_wait_time=0, require_from_present=False, verbose=True ) assert 'endpoint' in result assert 'database' in result with assert_raises(ReplicationMakeSlaveError) as err: await bad_db.replication.make_slave(endpoint=url) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_replication_inventory(sys_db, bad_db, cluster): if cluster: pytest.skip('Not tested in a cluster setup') dump_batch = await sys_db.replication.create_dump_batch(ttl=1000) dump_batch_id = dump_batch['id'] result = await sys_db.replication.inventory( batch_id=dump_batch_id, include_system=True, all_databases=True ) assert isinstance(result, dict) assert 'collections' not in result assert 'databases' in result assert 'state' in result assert 'tick' in result result = await sys_db.replication.inventory( batch_id=dump_batch_id, include_system=True, all_databases=False ) assert isinstance(result, dict) assert 'databases' not in result assert 'collections' in result assert 'state' in result assert 'tick' in result with assert_raises(ReplicationInventoryError) as err: await bad_db.replication.inventory(dump_batch_id) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND} await sys_db.replication.delete_dump_batch(dump_batch_id)
async def test_replication_server_id(sys_db, bad_db): result = await sys_db.replication.server_id() assert isinstance(result, string_types) with assert_raises(ReplicationServerIDError) as err: await bad_db.replication.server_id() assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_auth_superuser_token(client, sys_db, db_name, root_password, secret): token = generate_jwt(secret) db = await client.db('_system', superuser_token=token) bad_db = await client.db('_system', superuser_token='bad_token') assert isinstance(db.conn, JWTSuperuserConnection) assert isinstance(await db.version(), string_types) assert isinstance(await db.properties(), dict) # # Test get JWT secrets # secrets = db.jwt_secrets() # assert 'active' in secrets # assert 'passive' in secrets # # # Test get JWT secrets with bad database # with assert_raises(JWTSecretListError) as err: # bad_db.jwt_secrets() # assert err.value.error_code == FORBIDDEN # # # Test reload JWT secrets # secrets = db.reload_jwt_secrets() # assert 'active' in secrets # assert 'passive' in secrets # # # Test reload JWT secrets with bad database # with assert_raises(JWTSecretReloadError) as err: # bad_db.reload_jwt_secrets() # assert err.value.error_code == FORBIDDEN # Test get TLS data result = await db.tls() assert isinstance(result, dict) # Test get TLS data with bad database with assert_raises(ServerTLSError) as err: await bad_db.tls() assert err.value.error_code == FORBIDDEN # Test reload TLS result = await db.reload_tls() assert isinstance(result, dict) # Test reload TLS with bad database with assert_raises(ServerTLSReloadError) as err: await bad_db.reload_tls() assert err.value.error_code == FORBIDDEN
async def test_load_indexes(icol, bad_col): # Test load indexes assert await icol.load_indexes() is True # Test load indexes with bad collection with assert_raises(IndexLoadError) as err: await bad_col.load_indexes() assert err.value.error_code in {11, 1228}
async def test_replication_cluster_inventory(sys_db, bad_db, cluster): if cluster: result = await sys_db.replication.cluster_inventory(include_system=True) assert isinstance(result, dict) with assert_raises(ReplicationClusterInventoryError) as err: await bad_db.replication.cluster_inventory(include_system=True) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_auth_invalid_method(client, sys_db, db_name, username, password): with assert_raises(ValueError) as err: await client.db(name=db_name, username=username, password=password, verify=True, auth_method='bad_method') assert 'invalid auth_method' in str(err.value)
async def test_replication_first_tick(sys_db, bad_db, cluster): if cluster: pytest.skip('Not tested in a cluster setup') result = await sys_db.replication.logger_first_tick() assert isinstance(result, string_types) with assert_raises(ReplicationLoggerFirstTickError) as err: await bad_db.replication.logger_first_tick() assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_cluster_server_role(sys_db, bad_db, cluster): if not cluster: pytest.skip('Only tested in a cluster setup') result = await sys_db.cluster.server_role() assert isinstance(result, str) with assert_raises(ClusterServerRoleError) as err: await bad_db.cluster.server_role() assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_pregel_management(db, graph, cluster): if cluster: pytest.skip('Not tested in a cluster setup') # Test create pregel job job_id = await db.pregel.create_job( graph.name, 'pagerank', store=False, max_gss=100, thread_count=1, async_mode=False, result_field='result', algorithm_params={'threshold': 0.000001} ) assert isinstance(job_id, int) # Test create pregel job with unsupported algorithm with assert_raises(PregelJobCreateError) as err: await db.pregel.create_job(graph.name, 'invalid') assert err.value.error_code in {4, 10, 1600} # Test get existing pregel job job = await db.pregel.job(job_id) assert isinstance(job['state'], string_types) assert isinstance(job['aggregators'], dict) assert isinstance(job['gss'], int) assert isinstance(job['received_count'], int) assert isinstance(job['send_count'], int) assert 'total_runtime' in job # Test delete existing pregel job assert await db.pregel.delete_job(job_id) is True await asyncio.sleep(0.2) with assert_raises(PregelJobGetError) as err: await db.pregel.job(job_id) assert err.value.error_code in {4, 10, 1600} # Test delete missing pregel job with assert_raises(PregelJobDeleteError) as err: await db.pregel.delete_job(generate_string()) assert err.value.error_code in {4, 10, 1600}
async def test_replication_dump_methods(db, bad_db, col, docs, cluster): if cluster: pytest.skip('Not tested in a cluster setup') result = await db.replication.create_dump_batch(ttl=1000) assert 'id' in result and 'last_tick' in result batch_id = result['id'] with assert_raises(ReplicationDumpBatchCreateError) as err: await bad_db.replication.create_dump_batch(ttl=1000) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND} result = await db.replication.dump( collection=col.name, batch_id=batch_id, lower=0, upper=1000000, chunk_size=0, include_system=True, ticks=0, flush=True, deserialize=True ) assert 'content' in result assert 'check_more' in result with assert_raises(ReplicationDumpError) as err: await bad_db.replication.dump( collection=col.name, batch_id=batch_id ) assert err.value.error_code == HTTP_UNAUTHORIZED assert await db.replication.extend_dump_batch(batch_id, ttl=1000) is True with assert_raises(ReplicationDumpBatchExtendError) as err: await bad_db.replication.extend_dump_batch(batch_id, ttl=1000) assert err.value.error_code == HTTP_UNAUTHORIZED assert await db.replication.delete_dump_batch(batch_id) is True with assert_raises(ReplicationDumpBatchDeleteError) as err: await db.replication.delete_dump_batch(batch_id) assert err.value.error_code in {HTTP_NOT_FOUND, CURSOR_NOT_FOUND}
async def test_replication_logger_state(sys_db, bad_db, cluster): if cluster: pytest.skip('Not tested in a cluster setup') result = await sys_db.replication.logger_state() assert 'state' in result assert 'server' in result with assert_raises(ReplicationLoggerStateError) as err: await bad_db.replication.logger_state() assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_cluster_endpoints(db, bad_db, cluster): if not cluster: pytest.skip('Only tested in a cluster setup') # Test get server endpoints assert len(await db.cluster.endpoints()) > 0 # Test get server endpoints with bad database with assert_raises(ClusterEndpointsError) as err: await bad_db.cluster.endpoints() assert err.value.error_code in {11, 1228}
async def test_cluster_health(sys_db, bad_db, cluster): if not cluster: pytest.skip('Only tested in a cluster setup') result = await sys_db.cluster.health() assert 'Health' in result assert 'ClusterId' in result with assert_raises(ClusterHealthError) as err: await bad_db.cluster.health() assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_database_management(db, sys_db, bad_db): # Test list databases result = await sys_db.databases() assert '_system' in result # Test list databases with bad database with assert_raises(DatabaseListError): await bad_db.databases() # Test create database db_name = generate_db_name() assert await sys_db.has_database(db_name) is False assert await sys_db.create_database( name=db_name, replication_factor=1, write_concern=1, sharding="single") is True assert await sys_db.has_database(db_name) is True # Test create duplicate database with assert_raises(DatabaseCreateError) as err: await sys_db.create_database(db_name) assert err.value.error_code == 1207 # Test create database without permissions with assert_raises(DatabaseCreateError) as err: await db.create_database(db_name) assert err.value.error_code == 1230 # Test delete database without permissions with assert_raises(DatabaseDeleteError) as err: await db.delete_database(db_name) assert err.value.error_code == 1230 # Test delete database assert await sys_db.delete_database(db_name) is True assert db_name not in await sys_db.databases() # Test delete missing database with assert_raises(DatabaseDeleteError) as err: await sys_db.delete_database(db_name) assert err.value.error_code in {11, 1228} assert await sys_db.delete_database(db_name, ignore_missing=True) is False
async def test_cluster_server_version(sys_db, bad_db, cluster): if not cluster: pytest.skip('Only tested in a cluster setup') server_id = await sys_db.cluster.server_id() result = await sys_db.cluster.server_version(server_id) assert 'server' in result assert 'version' in result with assert_raises(ClusterServerVersionError) as err: await bad_db.cluster.server_version(server_id) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_cluster_server_engine(sys_db, bad_db, cluster): if not cluster: pytest.skip('Only tested in a cluster setup') server_id = await sys_db.cluster.server_id() result = await sys_db.cluster.server_engine(server_id) assert 'name' in result assert 'supports' in result with assert_raises(ClusterServerEngineError) as err: bad_db.cluster.server_engine(server_id) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_wal_last_tick(sys_db, bad_db, cluster): if cluster: pytest.skip('Not tested in a cluster setup') result = await sys_db.wal.last_tick() assert 'time' in result assert 'tick' in result assert 'server' in result # Test last_tick with bad database with assert_raises(WALLastTickError) as err: await bad_db.wal.last_tick() assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_cluster_server_statistics(sys_db, bad_db, cluster): if not cluster: pytest.skip('Only tested in a cluster setup') server_id = await sys_db.cluster.server_id() result = await sys_db.cluster.server_statistics(server_id) assert 'time' in result assert 'system' in result assert 'enabled' in result with assert_raises(ClusterServerStatisticsError) as err: await bad_db.cluster.server_statistics(server_id) assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
async def test_auth_jwt_expiry(client, sys_db, db_name, root_password, secret): # Test automatic token refresh on expired token. db = await client.db('_system', 'root', root_password, auth_method='jwt') expired_token = generate_jwt(secret, exp=0) db.conn._token = expired_token db.conn._auth_header = 'bearer {}'.format(expired_token) assert isinstance(await db.version(), string_types) # Test correct error on token expiry. db = await client.db('_system', superuser_token=expired_token) with assert_raises(ServerVersionError) as err: await db.version() assert err.value.error_code == FORBIDDEN
async def test_foxx_dependency_management(db, cluster): if cluster: pytest.skip('Not tested in a cluster setup') service_mount = generate_service_mount() missing_mount = generate_service_mount() # Prep the test service await db.foxx.create_service(mount=service_mount, source=service_file, dependencies={}) # Test get service dependencies assert await db.foxx.dependencies(service_mount) == {} # Test get missing service dependencies with assert_raises(FoxxDependencyGetError) as err: await db.foxx.dependencies(missing_mount) assert err.value.error_code == 3009 # Test update service dependencies assert await db.foxx.update_dependencies(service_mount, {}) == { 'values': {} } # Test update missing service dependencies with assert_raises(FoxxDependencyUpdateError) as err: await db.foxx.update_dependencies(missing_mount, {}) assert err.value.error_code == 3009 # Test replace service dependencies assert await db.foxx.replace_dependencies(service_mount, {}) == { 'values': {} } # Test replace missing service dependencies with assert_raises(FoxxDependencyReplaceError) as err: await db.foxx.replace_dependencies(missing_mount, {}) assert err.value.error_code == 3009
async def test_list_indexes(icol, bad_col): indexes = await icol.indexes() assert isinstance(indexes, list) assert len(indexes) > 0 assert 'id' in indexes[0] assert 'type' in indexes[0] assert 'fields' in indexes[0] assert 'selectivity' in indexes[0] assert 'sparse' in indexes[0] assert 'unique' in indexes[0] with assert_raises(IndexListError) as err: await bad_col.indexes() assert err.value.error_code in {11, 1228}