Skip to content

Commit 5930190

Browse files
committed
PYCBC-1698: Improve Jenkins Integration Tests
Changes ======= * Update eventing mgmt tests to skip some failure tests that are no longer viable in server 8.0 * Update C++ core to include eventing mgmt logic changes from CXXCBC-716 * Update eventing mgmt to have a more robust clean-up after a test is complete * Fix `test_upsert_index_from_json` to only compare portions of the index `store` object as more key/value pairs have been added in server 8.0 * Remove `search_query_timeout` and `view_query_timeout` as the tests were not adding value and instead creating problems * Update transactions logic to handle raw `document_unretrievable` which helps to handle updated C++ core logic from CXXCBC-704. Change-Id: I7969a117584e59cc58300b5597d3422d1af94a12 Reviewed-on: https://review.couchbase.org/c/couchbase-python-client/+/232173 Tested-by: Build Bot <build@couchbase.com> Reviewed-by: Dimitris Christodoulou <dimitris.christodoulou@couchbase.com>
1 parent 11b8a21 commit 5930190

10 files changed

Lines changed: 274 additions & 296 deletions

File tree

acouchbase/tests/eventingmgmt_t.py

Lines changed: 182 additions & 119 deletions
Large diffs are not rendered by default.

acouchbase/tests/search_t.py

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@
2222
import pytest_asyncio
2323

2424
import couchbase.search as search
25-
from couchbase.exceptions import (AmbiguousTimeoutException,
26-
InvalidArgumentException,
27-
QueryIndexNotFoundException)
25+
from couchbase.exceptions import InvalidArgumentException, QueryIndexNotFoundException
2826
from couchbase.mutation_state import MutationState
2927
from couchbase.options import SearchOptions
3028
from couchbase.search import (HighlightStyle,
@@ -739,33 +737,6 @@ async def test_search_raw_query(self, cb_env):
739737
res = cb_env.cluster.search_query(cb_env.TEST_INDEX_NAME, q, limit=10)
740738
await cb_env.assert_rows(res, 1)
741739

742-
# creating a new connection, allow retries
743-
@pytest.mark.flaky(reruns=5, reruns_delay=1)
744-
@pytest.mark.asyncio
745-
async def test_search_timeout(self, cb_env):
746-
from acouchbase.cluster import Cluster
747-
from couchbase.auth import PasswordAuthenticator
748-
from couchbase.options import ClusterOptions, ClusterTimeoutOptions
749-
conn_string = cb_env.config.get_connection_string()
750-
username, pw = cb_env.config.get_username_and_pw()
751-
auth = PasswordAuthenticator(username, pw)
752-
# Prior to PYCBC-1521, this test would fail as each request would override the cluster level search_timeout.
753-
# If a timeout was not provided in the request, the default 75s timeout would be used. PYCBC-1521 corrects
754-
# this behavior so this test will pass as we are essentially forcing an AmbiguousTimeoutException because
755-
# we are setting the cluster level search_timeout such a small value.
756-
timeout_opts = ClusterTimeoutOptions(search_timeout=timedelta(milliseconds=1))
757-
cluster = await Cluster.connect(f'{conn_string}', ClusterOptions(auth, timeout_options=timeout_opts))
758-
# don't need to do this except for older server versions
759-
_ = cluster.bucket(f'{cb_env.bucket.name}')
760-
q = search.TermQuery('auto')
761-
with pytest.raises(AmbiguousTimeoutException):
762-
res = cluster.search_query(cb_env.TEST_INDEX_NAME, q, SearchOptions(limit=10))
763-
[r async for r in res.rows()]
764-
# if we override the timeout w/in the request the query should succeed.
765-
res = cluster.search_query(cb_env.TEST_INDEX_NAME, q, SearchOptions(limit=10, timeout=timedelta(seconds=10)))
766-
rows = [r async for r in res.rows()]
767-
assert len(rows) > 0
768-
769740

770741
class ClassicSearchCollectionTests(SearchCollectionTestSuite):
771742
@pytest.fixture(scope='class')

acouchbase/tests/views_t.py

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,11 @@
1414
# limitations under the License.
1515

1616
import json
17-
from datetime import timedelta
1817

1918
import pytest
2019
import pytest_asyncio
2120

22-
from couchbase.exceptions import (AmbiguousTimeoutException,
23-
DesignDocumentNotFoundException,
24-
InvalidArgumentException)
21+
from couchbase.exceptions import DesignDocumentNotFoundException, InvalidArgumentException
2522
from couchbase.management.views import DesignDocumentNamespace
2623
from couchbase.options import ViewOptions
2724
from couchbase.views import (ViewMetaData,
@@ -267,39 +264,6 @@ async def test_view_query_startkey_docid(self, cb_env):
267264
assert isinstance(metadata, ViewMetaData)
268265
assert metadata.total_rows() >= expected_count
269266

270-
# creating a new connection, allow retries
271-
@pytest.mark.flaky(reruns=5, reruns_delay=1)
272-
@pytest.mark.asyncio
273-
async def test_view_query_timeout(self, cb_env):
274-
from acouchbase.cluster import Cluster
275-
from couchbase.auth import PasswordAuthenticator
276-
from couchbase.options import ClusterOptions, ClusterTimeoutOptions
277-
conn_string = cb_env.config.get_connection_string()
278-
username, pw = cb_env.config.get_username_and_pw()
279-
auth = PasswordAuthenticator(username, pw)
280-
# Prior to PYCBC-1521, this test would fail as each request would override the cluster level views_timeout.
281-
# If a timeout was not provided in the request, the default 75s timeout would be used. PYCBC-1521 corrects
282-
# this behavior so this test will pass as we are essentially forcing an AmbiguousTimeoutException because
283-
# we are setting the cluster level views_timeout such a small value.
284-
timeout_opts = ClusterTimeoutOptions(views_timeout=timedelta(milliseconds=1))
285-
cluster = await Cluster.connect(f'{conn_string}', ClusterOptions(auth, timeout_options=timeout_opts))
286-
# don't need to do this except for older server versions
287-
bucket = cluster.bucket(f'{cb_env.bucket.name}')
288-
with pytest.raises(AmbiguousTimeoutException):
289-
res = bucket.view_query(cb_env.DOCNAME,
290-
cb_env.TEST_VIEW_NAME,
291-
limit=10,
292-
namespace=DesignDocumentNamespace.DEVELOPMENT)
293-
[r async for r in res.rows()]
294-
# if we override the timeout w/in the request the query should succeed.
295-
res = bucket.view_query(cb_env.DOCNAME,
296-
cb_env.TEST_VIEW_NAME,
297-
limit=10,
298-
namespace=DesignDocumentNamespace.DEVELOPMENT,
299-
timeout=timedelta(seconds=10))
300-
rows = [r async for r in res.rows()]
301-
assert len(rows) > 0
302-
303267

304268
class ClassicViewsTests(ViewsTestSuite):
305269
@pytest.fixture(scope='class')

couchbase/tests/eventingmgmt_t.py

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
EventingFunctionNotBootstrappedException,
2424
EventingFunctionNotDeployedException,
2525
EventingFunctionNotFoundException,
26-
EventingFunctionNotUnDeployedException)
26+
EventingFunctionNotUnDeployedException,
27+
InternalServerFailureException)
2728
from couchbase.management.collections import CollectionSpec
2829
from couchbase.management.eventing import (EventingFunction,
2930
EventingFunctionBucketAccess,
@@ -33,7 +34,6 @@
3334
EventingFunctionDeploymentStatus,
3435
EventingFunctionKeyspace,
3536
EventingFunctionLanguageCompatibility,
36-
EventingFunctionProcessingStatus,
3737
EventingFunctionSettings,
3838
EventingFunctionsStatus,
3939
EventingFunctionState,
@@ -89,14 +89,16 @@ def create_eventing_function(self, cb_env):
8989
cb_env.efm.upsert_function(cb_env.BASIC_FUNC)
9090

9191
@pytest.fixture()
92-
def drop_eventing_function(self, cb_env):
92+
def drop_eventing_functions(self, cb_env):
9393
yield
94-
cb_env.efm.drop_function(cb_env.TEST_EVT_NAME)
95-
TestEnvironment.try_n_times_till_exception(10,
96-
1,
97-
cb_env.efm.get_function,
98-
cb_env.BASIC_FUNC.name,
99-
EventingFunctionNotFoundException)
94+
for fn_name in cb_env.function_names:
95+
cb_env.efm.drop_function(fn_name)
96+
TestEnvironment.try_n_times_till_exception(10,
97+
1,
98+
cb_env.efm.get_function,
99+
fn_name,
100+
EventingFunctionNotFoundException)
101+
cb_env.function_names = []
100102

101103
@pytest.fixture()
102104
def undeploy_and_drop_eventing_function(self, cb_env):
@@ -110,11 +112,12 @@ def undeploy_and_drop_eventing_function(self, cb_env):
110112
cb_env.BASIC_FUNC.name,
111113
EventingFunctionNotFoundException)
112114

115+
@pytest.mark.usefixtures('drop_eventing_functions')
113116
def test_constant_bindings(self, cb_env):
114-
# TODO: look into why timeout occurs when providing > 1 constant
115-
# binding
117+
# TODO: look into why timeout occurs when providing > 1 constant binding
118+
cb_env.function_names = ['test-evt-const-func']
116119
local_func = EventingFunction(
117-
'test-evt-const-func',
120+
cb_env.function_names[0],
118121
cb_env.SIMPLE_EVT_CODE,
119122
cb_env.evt_version,
120123
metadata_keyspace=EventingFunctionKeyspace('default'),
@@ -165,8 +168,13 @@ def test_deploy_function_fail(self, cb_env):
165168
cb_env.wait_until_status(10, 1, EventingFunctionState.Undeployed, cb_env.BASIC_FUNC.name)
166169
cb_env.efm.deploy_function(cb_env.BASIC_FUNC.name)
167170
cb_env.wait_until_status(20, 3, EventingFunctionState.Deployed, cb_env.BASIC_FUNC.name)
168-
with pytest.raises(EventingFunctionAlreadyDeployedException):
171+
if cb_env.server_version_short >= 8.0:
172+
# no longer a failure in 8.0+
169173
cb_env.efm.deploy_function(cb_env.BASIC_FUNC.name)
174+
cb_env.wait_until_status(20, 3, EventingFunctionState.Deployed, cb_env.BASIC_FUNC.name)
175+
else:
176+
with pytest.raises(EventingFunctionAlreadyDeployedException):
177+
cb_env.efm.deploy_function(cb_env.BASIC_FUNC.name)
170178

171179
@pytest.mark.usefixtures('create_eventing_function')
172180
def test_drop_function(self, cb_env):
@@ -195,10 +203,15 @@ def test_drop_function_fail(self, cb_env):
195203
with pytest.raises(EventingFunctionNotUnDeployedException):
196204
cb_env.efm.drop_function(cb_env.BASIC_FUNC.name)
197205

206+
@pytest.mark.usefixtures('drop_eventing_functions')
198207
def test_functions_status(self, cb_env):
208+
cb_env.function_names = [
209+
'test-evt-func-1',
210+
'test-evt-func-2',
211+
]
199212
new_funcs = [
200213
EventingFunction(
201-
'test-evt-func-1',
214+
cb_env.function_names[0],
202215
cb_env.SIMPLE_EVT_CODE,
203216
cb_env.evt_version,
204217
metadata_keyspace=EventingFunctionKeyspace('default'),
@@ -215,7 +228,7 @@ def test_functions_status(self, cb_env):
215228
]
216229
),
217230
EventingFunction(
218-
'test-evt-func-2',
231+
cb_env.function_names[1],
219232
cb_env.SIMPLE_EVT_CODE,
220233
cb_env.evt_version,
221234
metadata_keyspace=EventingFunctionKeyspace('default'),
@@ -241,10 +254,15 @@ def test_functions_status(self, cb_env):
241254
for func in funcs.functions:
242255
assert isinstance(func, EventingFunctionStatus)
243256

257+
@pytest.mark.usefixtures('drop_eventing_functions')
244258
def test_get_all_functions(self, cb_env):
259+
cb_env.function_names = [
260+
'test-evt-func-1',
261+
'test-evt-func-2',
262+
]
245263
new_funcs = [
246264
EventingFunction(
247-
'test-evt-func-1',
265+
cb_env.function_names[0],
248266
cb_env.SIMPLE_EVT_CODE,
249267
cb_env.evt_version,
250268
metadata_keyspace=EventingFunctionKeyspace('default'),
@@ -261,7 +279,7 @@ def test_get_all_functions(self, cb_env):
261279
]
262280
),
263281
EventingFunction(
264-
'test-evt-func-2',
282+
cb_env.function_names[1],
265283
cb_env.SIMPLE_EVT_CODE,
266284
cb_env.evt_version,
267285
metadata_keyspace=EventingFunctionKeyspace('default'),
@@ -295,9 +313,11 @@ def test_get_function_fail(self, cb_env):
295313
with pytest.raises(EventingFunctionNotFoundException):
296314
cb_env.efm.get_function('not-a-function')
297315

316+
@pytest.mark.usefixtures('drop_eventing_functions')
298317
def test_options_simple(self, cb_env):
318+
cb_env.function_names = ['test-evt-func-1']
299319
local_func = EventingFunction(
300-
'test-evt-func-1',
320+
cb_env.function_names[0],
301321
cb_env.SIMPLE_EVT_CODE,
302322
cb_env.evt_version,
303323
metadata_keyspace=EventingFunctionKeyspace('default'),
@@ -328,8 +348,12 @@ def test_pause_function_fail(self, cb_env):
328348
with pytest.raises(EventingFunctionNotFoundException):
329349
cb_env.efm.pause_function('not-a-function')
330350

331-
with pytest.raises(EventingFunctionNotBootstrappedException):
332-
cb_env.efm.pause_function(cb_env.BASIC_FUNC.name)
351+
if cb_env.server_version_short >= 8.0:
352+
with pytest.raises(InternalServerFailureException):
353+
cb_env.efm.pause_function(cb_env.BASIC_FUNC.name)
354+
else:
355+
with pytest.raises(EventingFunctionNotBootstrappedException):
356+
cb_env.efm.pause_function(cb_env.BASIC_FUNC.name)
333357

334358
@pytest.mark.usefixtures('create_eventing_function')
335359
@pytest.mark.usefixtures('undeploy_and_drop_eventing_function')
@@ -342,15 +366,11 @@ def test_pause_and_resume_function(self, cb_env):
342366
cb_env.efm.pause_function(cb_env.BASIC_FUNC.name)
343367
func = TestEnvironment.try_n_times(5, 1, cb_env.efm.get_function, cb_env.BASIC_FUNC.name)
344368
cb_env.validate_eventing_function(func, shallow=True)
345-
# verify function processing status
346-
assert func.settings.processing_status == EventingFunctionProcessingStatus.Paused
347369
cb_env.wait_until_status(15, 2, EventingFunctionState.Paused, cb_env.BASIC_FUNC.name)
348370
# resume function
349371
cb_env.efm.resume_function(cb_env.BASIC_FUNC.name)
350372
func = TestEnvironment.try_n_times(5, 1, cb_env.efm.get_function, cb_env.BASIC_FUNC.name)
351373
cb_env.validate_eventing_function(func, shallow=True)
352-
# verify function processing status
353-
assert func.settings.processing_status == EventingFunctionProcessingStatus.Running
354374
# verify function state
355375
cb_env.wait_until_status(20, 3, EventingFunctionState.Deployed, cb_env.BASIC_FUNC.name)
356376

@@ -361,8 +381,12 @@ def test_resume_function_fail(self, cb_env):
361381
with pytest.raises(EventingFunctionNotFoundException):
362382
cb_env.efm.pause_function('not-a-function')
363383

364-
with pytest.raises(EventingFunctionNotBootstrappedException):
365-
cb_env.efm.pause_function(cb_env.BASIC_FUNC.name)
384+
if cb_env.server_version_short >= 8.0:
385+
with pytest.raises(InternalServerFailureException):
386+
cb_env.efm.pause_function(cb_env.BASIC_FUNC.name)
387+
else:
388+
with pytest.raises(EventingFunctionNotBootstrappedException):
389+
cb_env.efm.pause_function(cb_env.BASIC_FUNC.name)
366390

367391
@pytest.mark.usefixtures('create_and_drop_eventing_function')
368392
def test_undeploy_function(self, cb_env):
@@ -389,9 +413,11 @@ def test_undeploy_function_fail(self, cb_env):
389413
):
390414
cb_env.efm.undeploy_function('not-a-function')
391415

416+
@pytest.mark.usefixtures('drop_eventing_functions')
392417
def test_upsert_function(self, cb_env):
418+
cb_env.function_names = ['test-evt-func-1']
393419
local_func = EventingFunction(
394-
'test-evt-func-1',
420+
cb_env.function_names[0],
395421
cb_env.SIMPLE_EVT_CODE,
396422
cb_env.evt_version,
397423
metadata_keyspace=EventingFunctionKeyspace('default'),
@@ -431,20 +457,22 @@ def test_upsert_function_fail(self, cb_env):
431457
]
432458
)
433459

434-
# @TODO: couchbase++ seg faults on this...
435-
# with pytest.raises(EventingFunctionCompilationFailureException):
436-
# cb_env.efm.upsert_function(local_func)
437-
438460
local_func.code = cb_env.SIMPLE_EVT_CODE
439461
local_func.source_keyspace = EventingFunctionKeyspace(
440462
'beer-sample', "test-scope", "test-collection"
441463
)
442-
with pytest.raises(EventingFunctionCollectionNotFoundException):
443-
cb_env.efm.upsert_function(local_func)
444-
464+
if cb_env.server_version_short >= 8.0:
465+
with pytest.raises(InternalServerFailureException):
466+
cb_env.efm.upsert_function(local_func)
467+
else:
468+
with pytest.raises(EventingFunctionCollectionNotFoundException):
469+
cb_env.efm.upsert_function(local_func)
470+
471+
@pytest.mark.usefixtures('drop_eventing_functions')
445472
def test_url_bindings(self, cb_env):
473+
cb_env.function_names = ['test-evt-url-func']
446474
local_func = EventingFunction(
447-
"test-evt-url-func",
475+
cb_env.function_names[0],
448476
cb_env.SIMPLE_EVT_CODE,
449477
cb_env.evt_version,
450478
metadata_keyspace=EventingFunctionKeyspace('default'),
@@ -499,6 +527,7 @@ def test_url_bindings(self, cb_env):
499527
func = TestEnvironment.try_n_times(5, 3, cb_env.efm.get_function, local_func.name)
500528
cb_env.validate_eventing_function(func)
501529

530+
@pytest.mark.usefixtures('drop_eventing_functions')
502531
def test_with_scope_and_collection(self, cb_env):
503532
EnvironmentFeatures.check_if_feature_supported('collections',
504533
cb_env.server_version_short,
@@ -514,8 +543,9 @@ def test_with_scope_and_collection(self, cb_env):
514543
collection_spec,
515544
expected_exceptions=(CollectionAlreadyExistsException,))
516545

546+
cb_env.function_names = ['test-evt-func-coll']
517547
local_func = EventingFunction(
518-
'test-evt-func-coll',
548+
cb_env.function_names[0],
519549
cb_env.SIMPLE_EVT_CODE,
520550
cb_env.evt_version,
521551
metadata_keyspace=EventingFunctionKeyspace(
@@ -545,8 +575,6 @@ def test_with_scope_and_collection(self, cb_env):
545575
func = TestEnvironment.try_n_times(5, 3, cb_env.efm.get_function, local_func.name)
546576
cb_env.validate_eventing_function(func)
547577

548-
cb_env.efm.drop_function(local_func.name)
549-
550578

551579
@pytest.mark.flaky(reruns=5, reruns_delay=1)
552580
class ClassicEventingManagementTests(EventingManagementTestSuite):
@@ -571,7 +599,7 @@ def couchbase_test_environment(self, cb_base_env, test_manifest_validated):
571599
cb_env.teardown()
572600

573601

574-
@pytest.mark.flaky(reruns=5, reruns_delay=1)
602+
@pytest.mark.flaky(reruns=2, reruns_delay=1)
575603
class ClassicScopeEventingManagementTests(EventingManagementTestSuite):
576604

577605
@pytest.fixture(scope='class')

0 commit comments

Comments
 (0)