Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6af38c8
Add tests for a subset of all the policies that support the key optio…
juliannguyen4 Jul 15, 2026
5fde297
Add first draft of apply/batch_apply send key test cases.
juliannguyen4 Jul 15, 2026
dc1ae8d
Also document batch_apply and apply policies' key option properly use…
juliannguyen4 Jul 15, 2026
b3ab0d2
Cleanup test code.
juliannguyen4 Jul 15, 2026
b8d3541
Improve fixture naming.
juliannguyen4 Jul 15, 2026
76e51a7
Document union precedence for policies in which the key option was te…
juliannguyen4 Jul 15, 2026
350a6d7
Add tests for dynamic config send key taking precedence for operate, …
juliannguyen4 Jul 15, 2026
4d42c30
Address apply/batch apply test failures. Reuse more code from conftest
juliannguyen4 Jul 16, 2026
a2a96cd
Fix inaccurate comment..
juliannguyen4 Jul 16, 2026
0d7b6bf
Address incorrect tests because command level policy will automatical…
juliannguyen4 Jul 16, 2026
ea24ccf
Update C client to fix bug where the union of send key options is not…
juliannguyen4 Jul 17, 2026
35a41f7
Pull C client again to address test regressions
juliannguyen4 Jul 17, 2026
a083de8
Have expect_records_to_have_user_key_stored only expect presence of u…
juliannguyen4 Jul 17, 2026
5785fec
Add ability to make each test case in new_tests/test_send_key_union_p…
juliannguyen4 Jul 17, 2026
e433aba
Address test syntax errors.
juliannguyen4 Jul 17, 2026
811c8e3
Try passing parameters indirectly to insert_records fixture to addres…
juliannguyen4 Jul 17, 2026
ae7099b
Document why make_set_unique is a fixture param. Add missing indirect…
juliannguyen4 Jul 20, 2026
9516daf
Clarify what make_set_unique is for.
juliannguyen4 Jul 20, 2026
6a193f2
Clear up confusing comment..
juliannguyen4 Jul 20, 2026
ddd5079
Make var naming less confusing
juliannguyen4 Jul 20, 2026
ba0e46d
Fix test bug that only runs query against demo instead of the unique …
juliannguyen4 Jul 20, 2026
84a20c4
Only test policies supported by dynamic config. This removes policies…
juliannguyen4 Jul 20, 2026
4312ed9
use time.time_ns() to generate set name instead because time.time() u…
juliannguyen4 Jul 20, 2026
9b5f72f
Only clean up test side effects if make_set_unique is false. This way…
juliannguyen4 Jul 20, 2026
bed12e5
Forgot to remove operate.send_key from dyn_config.yml, which is also …
juliannguyen4 Jul 20, 2026
5698cea
Pull Brian's fix to address the remaining batch_write and batch_apply…
juliannguyen4 Jul 20, 2026
87f3193
Point C client back to stage with Brian's fix now merged into there
juliannguyen4 Jul 20, 2026
0ade5c6
Reduce use of hardcoded strings
juliannguyen4 Jul 20, 2026
0cb7324
Merge remote-tracking branch 'origin/dev' into CLIENT-5055-document-s…
juliannguyen4 Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 5 additions & 20 deletions doc/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2141,10 +2141,7 @@ Write Policies
.. hlist::
:columns: 1

* **key**
| One of the :ref:`POLICY_KEY` values such as :data:`aerospike.POLICY_KEY_DIGEST`
|
| Default: :data:`aerospike.POLICY_KEY_DIGEST`
* .. include:: ./key_option_with_union_precedence.rst
* **exists**
| One of the :ref:`POLICY_EXISTS` values such as :data:`aerospike.POLICY_EXISTS_CREATE`
|
Expand Down Expand Up @@ -2256,10 +2253,7 @@ Operate Policies
.. hlist::
:columns: 1

* **key**
| One of the :ref:`POLICY_KEY` values such as :data:`aerospike.POLICY_KEY_DIGEST`
|
| Default: :data:`aerospike.POLICY_KEY_DIGEST`
* .. include:: ./key_option_with_union_precedence.rst
* **gen**
| One of the :ref:`POLICY_GEN` values such as :data:`aerospike.POLICY_GEN_IGNORE`
|
Expand Down Expand Up @@ -2343,10 +2337,7 @@ Apply Policies
.. hlist::
:columns: 1

* **key**
| One of the :ref:`POLICY_KEY` values such as :data:`aerospike.POLICY_KEY_DIGEST`
|
| Default: :data:`aerospike.POLICY_KEY_DIGEST`
* .. include:: ./key_option_with_union_precedence.rst
* **replica**
| One of the :ref:`POLICY_REPLICA` values such as :data:`aerospike.POLICY_REPLICA_MASTER`
|
Expand Down Expand Up @@ -2509,10 +2500,7 @@ Batch Write Policies
.. hlist::
:columns: 1

* **key**
| One of the :ref:`POLICY_KEY` values such as :data:`aerospike.POLICY_KEY_DIGEST`
|
| Default: :data:`aerospike.POLICY_KEY_DIGEST`
* .. include:: ./key_option_with_union_precedence.rst
* **commit_level**
| One of the :ref:`POLICY_COMMIT_LEVEL` values such as :data:`aerospike.POLICY_COMMIT_LEVEL_ALL`
|
Expand Down Expand Up @@ -2564,10 +2552,7 @@ Batch Apply Policies
.. hlist::
:columns: 1

* **key**
| One of the :ref:`POLICY_KEY` values such as :data:`aerospike.POLICY_KEY_DIGEST`
|
| Default: :data:`aerospike.POLICY_KEY_DIGEST`
* .. include:: ./key_option_with_union_precedence.rst
* **commit_level**
| One of the :ref:`POLICY_COMMIT_LEVEL` values such as :data:`aerospike.POLICY_COMMIT_LEVEL_ALL`
|
Expand Down
9 changes: 9 additions & 0 deletions doc/key_option_with_union_precedence.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
**key**

One of the :ref:`POLICY_KEY` values such as :data:`aerospike.POLICY_KEY_DIGEST`

This option is unique from other options such that it uses union precedence;
if this is set to :data:`aerospike.POLICY_KEY_SEND` either in dynamic config, config-level, or command-level,
:data:`aerospike.POLICY_KEY_SEND` will always be applied.

Default: :data:`aerospike.POLICY_KEY_DIGEST`
4 changes: 4 additions & 0 deletions test/dyn_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ dynamic:
enable: true
write:
send_key: true
batch_write:
send_key: true
batch_udf:
send_key: true
static:
client:
config_interval: 1000
44 changes: 38 additions & 6 deletions test/new_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,26 +270,55 @@ def wait_for_job_completion(as_connection, job_id, job_module: int = aerospike.J
BIN_NAME = "number"
MAP_BIN_NAME = "map"

# TODO: scale down tests maybe
KEYS = [(TEST_NS, TEST_SET, i) for i in range(500)]
expected_number_bin_values = set()

# Add records around the test
@pytest.fixture(scope="function")
def clean_test_background(as_connection):
def insert_records(request, as_connection):

# - Some tests don't make use of unique sets,
# so we leave them alone for backwards compatibility
# - make_set_unique ensures that if a test case's cleanup stage fails to run
# e.g when the test case's setup fixture fails out,
# that test case's records does not interfere with future test cases that need to perform a query
num_keys, make_set_unique = request.param

if make_set_unique:
set_name = f"{TEST_SET}-{time.time_ns()}"
else:
set_name = TEST_SET

request.cls.set_name = set_name
keys = [(TEST_NS, set_name, i) for i in range(num_keys)]
request.cls.keys = keys

batch_records = []
brs = BatchRecords(batch_records=batch_records)
for i, key in enumerate(KEYS):

for i, key in enumerate(keys):
ops = [
operations.write(BIN_NAME, i),
operations.write(MAP_BIN_NAME, {"a": i})
]
br = Write(key, ops=ops)
batch_records.append(br)
expected_number_bin_values.add(i)

as_connection.batch_write(brs)

yield
as_connection.batch_remove(KEYS)

if make_set_unique is False:
as_connection.batch_remove(keys)

def expect_records_to_have_user_key_stored(client: aerospike.Client, set_name: str):
query = client.query(TEST_NS, set_name)
recs = query.results()

# Check that record key tuple has the user key
for record in recs:
pk = record[0]
assert pk[2] is not None

BASIC_READ_BIN_OPS = [
operations.read(BIN_NAME)
Expand All @@ -307,7 +336,7 @@ def clean_test_background(as_connection):
NON_EXISTENT_BIN_NAME = "asdf"

@pytest.fixture()
def query(request, clean_test_background, as_connection):
def query(request, insert_records, as_connection):
if not hasattr(request, "param"):
query = as_connection.query(TEST_NS, TEST_SET)
else:
Expand Down Expand Up @@ -413,3 +442,6 @@ def hydrate_partitions_1000_to_1003(request, as_connection):
yield

as_connection.batch_remove(keys)

AEROSPIKE_CLIENT_CONFIG_URL = "AEROSPIKE_CLIENT_CONFIG_URL"
DYN_CONFIG_PATH = "./dyn_config.yml"
3 changes: 0 additions & 3 deletions test/new_tests/string_helpers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
from .conftest import KEYS
import unicodedata
import pytest
from aerospike_helpers.string_helpers import StringPolicy


KEY = KEYS[0]

NON_STR_BIN_NAME = INT_BIN_NAME = "nonstr"
STR_BIN_NAME = "str"
DOUBLE_BIN_NAME = "double"
Expand Down
4 changes: 2 additions & 2 deletions test/new_tests/test_command_level_policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
from aerospike_helpers.batch import records as br
from .test_base_class import TestBaseClass
from aerospike_helpers.operations import operations
from .conftest import verify_record_ttl
from .conftest import verify_record_ttl, TEST_NS, TEST_SET

SKIP_MSG = "read_touch_ttl_percent only supported on server 7.1 or higher"
KEY = ("test", "demo", 1)
KEY = (TEST_NS, TEST_SET, 1)


@pytest.mark.usefixtures("as_connection")
Expand Down
16 changes: 4 additions & 12 deletions test/new_tests/test_dynamic_config.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import aerospike
from aerospike import exception as e
from .conftest import expect_records_to_have_user_key_stored, AEROSPIKE_CLIENT_CONFIG_URL, DYN_CONFIG_PATH
from .test_base_class import TestBaseClass
import pytest
import os
import glob

DYN_CONFIG_PATH = "./dyn_config.yml"
METRICS_LOG_FILES = "./metrics-*.log"


Expand Down Expand Up @@ -52,8 +52,6 @@ def cleanup_metrics_logs(self):
for item in metrics_log_filenames:
os.remove(item)

AEROSPIKE_CLIENT_CONFIG_URL = "AEROSPIKE_CLIENT_CONFIG_URL"

@pytest.fixture
def functional_test_setup(self, request, show_more_logs, cleanup_metrics_logs):
config = TestBaseClass.get_connection_config()
Expand All @@ -73,7 +71,7 @@ def functional_test_setup(self, request, show_more_logs, cleanup_metrics_logs):
setup_client.close()

if request.param is True:
del os.environ[self.AEROSPIKE_CLIENT_CONFIG_URL]
del os.environ[AEROSPIKE_CLIENT_CONFIG_URL]

# Decide whether env var should be used or not to read dynamic config file.
# If not using env var, use the config provider instead
Expand All @@ -82,7 +80,7 @@ def functional_test_setup(self, request, show_more_logs, cleanup_metrics_logs):
def test_dyn_config_file_works(self, functional_test_setup):
config = TestBaseClass.get_connection_config()
if functional_test_setup is True:
os.environ[self.AEROSPIKE_CLIENT_CONFIG_URL] = DYN_CONFIG_PATH
os.environ[AEROSPIKE_CLIENT_CONFIG_URL] = DYN_CONFIG_PATH
else:
provider = aerospike.ConfigProvider(DYN_CONFIG_PATH)
config["config_provider"] = provider
Expand All @@ -93,13 +91,7 @@ def test_dyn_config_file_works(self, functional_test_setup):

# "Send key" is enabled in dynamic config
# The key should be returned here
query = self.client.query("test", "demo")
recs = query.results()
assert len(recs) == 1
# Check that record key tuple has the primary key
first_record = recs[0]
first_record_key = first_record[0]
assert first_record_key[2] is self.key[2]
expect_records_to_have_user_key_stored(self.client, set_name="demo")

def test_enable_metrics_cannot_override_dyn_config(self, show_more_logs):
config = TestBaseClass.get_connection_config()
Expand Down
8 changes: 4 additions & 4 deletions test/new_tests/test_exception_subcode.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import pytest
from .conftest import KEYS, BIN_NAME
from .conftest import TEST_NS, TEST_SET, BIN_NAME
import aerospike
from aerospike import exception as e
from aerospike_helpers.operations import list_operations as list_ops
from .test_base_class import TestBaseClass
from . import as_errors


KEY = KEYS[0]
KEY = (TEST_NS, TEST_SET, 1)
OPS = [
list_ops.list_get_by_index(BIN_NAME, index=99, return_type=aerospike.LIST_RETURN_VALUE)
]
Expand Down Expand Up @@ -49,7 +49,7 @@ def test_error_verbosity_levels(self, policy_w_verbosity_setting: dict, set_in_c
if not set_in_client_config:
cmd_policy |= policy_w_verbosity_setting

self.as_connection.operate(KEYS[0], OPS, policy=cmd_policy)
self.as_connection.operate(KEY, OPS, policy=cmd_policy)

# Make sure there's no regression with the parent error code
assert excinfo.value.code == as_errors.AEROSPIKE_ERR_OP_NOT_APPLICABLE
Expand Down Expand Up @@ -83,4 +83,4 @@ def test_invalid_verbosity(self):
ERROR_DETAIL_VERBOSITY_SETTING: 3
}
with pytest.raises(e.ServerError):
self.as_connection.operate(KEYS[0], OPS, policy=policy)
self.as_connection.operate(KEY, OPS, policy=policy)
3 changes: 2 additions & 1 deletion test/new_tests/test_expressions_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

from .test_base_class import TestBaseClass
from .string_helpers import *
from .conftest import expect_server_version_earlier_than_8_1_3_to_fail
from .conftest import expect_server_version_earlier_than_8_1_3_to_fail, TEST_NS, TEST_SET
KEY = (TEST_NS, TEST_SET, 1)


class TestExpressions:
Expand Down
7 changes: 7 additions & 0 deletions test/new_tests/test_query_bin_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ class TestQueryBinProjection:
aerospike.Client.query
],
indirect=True
),
pytest.mark.parametrize(
"insert_records",
[
[500, False]
],
indirect=True
)
]

Expand Down
Loading
Loading