Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ab8de36
JS Server: Implemented snapshot & verify
snej Oct 24, 2025
4466ba3
JS Server: Implemented blobs for /updateDatabase
snej Oct 24, 2025
9d8028f
JS Server: Normalize collection names everywhere
snej Oct 24, 2025
31fd741
JS Server: Actually save doc after updating it
snej Oct 24, 2025
cfd7ad7
Disable more JS tests and a few more test server fixes
borrrden Oct 25, 2025
27dde81
Fix API spec for conflict resolvers and run query test
borrrden Oct 27, 2025
d987f5e
JS Server: Added auth support for replicator
snej Oct 27, 2025
e0101d2
JS Server: Implemented conflict resolvers
snej Oct 27, 2025
21b9083
JS Server: Throw error when updating keypath fails
snej Oct 27, 2025
6e2c5a8
JS Server: Implemented push/pull filters
snej Oct 28, 2025
362d68e
JS Server: Resolve relative blob URLs
snej Oct 28, 2025
6898f84
JS Server: support updatedBlobs in /verifyDocuments
snej Oct 28, 2025
ec004cc
JS Server: Just prettified tdkSchema.ts
snej Oct 28, 2025
002b971
JS Server: Fixed transaction error in /updateDatabase
snej Oct 28, 2025
df8eed5
A few small fixes
borrrden Oct 28, 2025
4b92322
Correct snapshot tests and behavior
borrrden Oct 28, 2025
259a313
Further correct Snapshot
snej Oct 28, 2025
017a520
Correct and error code and prettify message
borrrden Oct 28, 2025
58b9fc5
Update travel JS dataset
borrrden Oct 29, 2025
273f1b2
Switch SGW certificate strategy
borrrden Oct 29, 2025
2d6a5ba
Emit "transport: ws" for Javascript topology setups
borrrden Oct 29, 2025
85803be
Need to separate push and pull filter
borrrden Oct 29, 2025
2b7e18e
Relax smoke test requirements for error on connection failure
borrrden Oct 29, 2025
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
14 changes: 7 additions & 7 deletions client/smoke_tests/test_listener.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import aiohttp
import pytest
from cbltest import CBLPyTest
from cbltest.api.cbltestclass import CBLTestClass
from cbltest.api.listener import Listener
from cbltest.globals import CBLPyTestGlobal
from cbltest.responses import ServerVariant


class TestListener:
def setup_method(self, method):
# If writing a new test do not forget this step or the test server
# will not be informed about the currently running test
CBLPyTestGlobal.running_test_name = method.__name__

class TestListener(CBLTestClass):
@pytest.mark.asyncio(loop_scope="session")
async def test_start_stop_listener(self, cblpytest: CBLPyTest) -> None:
await self.skip_if_not_platform(
cblpytest.test_servers[0], ServerVariant.ALL & ~ServerVariant.JS
)

dbs = await cblpytest.test_servers[0].create_and_reset_db(["db1"])
db = dbs[0]
listener = Listener(db, ["_default._default"], 59840)
Expand Down
13 changes: 6 additions & 7 deletions client/smoke_tests/test_log_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
import pytest
import requests
from cbltest import CBLPyTest
from cbltest.globals import CBLPyTestGlobal
from cbltest.api.cbltestclass import CBLTestClass
from cbltest.logging import LogSlurpHandler, _cbl_log
from cbltest.responses import ServerVariant


class TestLogEndpoint:
def setup_method(self, method):
# If writing a new test do not forget this step or the test server
# will not be informed about the currently running test
CBLPyTestGlobal.running_test_name = method.__name__

class TestLogEndpoint(CBLTestClass):
@pytest.mark.asyncio(loop_scope="session")
async def test_log_message(self, cblpytest: CBLPyTest) -> None:
await self.skip_if_not_platform(
cblpytest.test_servers[0], ServerVariant.ALL & ~ServerVariant.JS
)
if cblpytest.config.logslurp_url is None:
pytest.skip(
"No LogSlurp server configured (required to check functionality)"
Expand Down
15 changes: 8 additions & 7 deletions client/smoke_tests/test_multipeer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@

import pytest
from cbltest import CBLPyTest
from cbltest.api.cbltestclass import CBLTestClass
from cbltest.api.multipeer_replicator import MultipeerReplicator
from cbltest.api.replicator_types import ReplicatorCollectionEntry
from cbltest.globals import CBLPyTestGlobal
from cbltest.responses import ServerVariant


class TestMultipeerReplicator:
def setup_method(self, method):
# If writing a new test do not forget this step or the test server
# will not be informed about the currently running test
CBLPyTestGlobal.running_test_name = method.__name__

class TestMultipeerReplicator(CBLTestClass):
@pytest.mark.asyncio(loop_scope="session")
async def test_start_stop_multipeer(self, cblpytest: CBLPyTest) -> None:
await self.skip_if_not_platform(
cblpytest.test_servers[0], ServerVariant.ALL & ~ServerVariant.JS
)
await self.skip_if_cbl_not(cblpytest.test_servers[0], ">= 3.3.0")

dbs = await cblpytest.test_servers[0].create_and_reset_db(["db1"])
db = dbs[0]
multipeer = MultipeerReplicator(
Expand Down
9 changes: 8 additions & 1 deletion client/smoke_tests/test_perform_maintenance.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import pytest
from cbltest import CBLPyTest
from cbltest.api.cbltestclass import CBLTestClass
from cbltest.api.database_types import MaintenanceType
from cbltest.responses import ServerVariant


class TestPerformMaintenance:
class TestPerformMaintenance(CBLTestClass):
@pytest.mark.asyncio(loop_scope="session")
@pytest.mark.parametrize(
"maintenance_type",
Expand All @@ -17,6 +19,11 @@ class TestPerformMaintenance:
async def test_perform_maintenance_endpoint(
self, cblpytest: CBLPyTest, maintenance_type: MaintenanceType
) -> None:
if maintenance_type != MaintenanceType.COMPACT:
await self.skip_if_not_platform(
cblpytest.test_servers[0], ServerVariant.ALL & ~ServerVariant.JS
)

dbs = await cblpytest.test_servers[0].create_and_reset_db(
["db1"], dataset="names"
)
Expand Down
10 changes: 6 additions & 4 deletions client/smoke_tests/test_run_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ async def test_run_query(self, cblpytest: CBLPyTest):
db = await cblpytest.test_servers[0].create_and_reset_db(
["db1"], dataset="names"
)
results = await db[0].run_query("select meta().id from _ LIMIT 5")
results = await db[0].run_query(
"select meta().id from _ ORDER BY meta().id LIMIT 5"
)
assert results is not None, "The query should return a result"
assert len(results) == 5, "The query should return five results"
i = 1
for r in results:
expected = ["name_1", "name_10", "name_100", "name_11", "name_12"]
for i, r in enumerate(results):
assert "id" in r, "The result should have an ID column"
assert r["id"] == f"name_{i}", f"The result ID should be name_{i}"
i += 1
assert r["id"] == expected[i], f"The result ID should be {expected[i]}"
7 changes: 1 addition & 6 deletions client/smoke_tests/test_start_replicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from cbltest import CBLPyTest
from cbltest.api.database import Database
from cbltest.api.error import CblTestServerBadResponseError
from cbltest.api.error_types import ErrorDomain
from cbltest.api.replicator import Replicator
from cbltest.api.replicator_types import (
ReplicatorActivityLevel,
Expand Down Expand Up @@ -35,11 +34,7 @@ async def test_bad_endpoint(self, cblpytest: CBLPyTest) -> None:
repl.add_default_collection()
await repl.start()
status = await repl.wait_for(ReplicatorActivityLevel.STOPPED)
assert (
status.error is not None
and ErrorDomain.equal(status.error.domain, ErrorDomain.CBL)
and status.error.code == 5002
)
assert status.error is not None

@pytest.mark.asyncio(loop_scope="session")
@pytest.mark.parametrize(
Expand Down
8 changes: 6 additions & 2 deletions client/src/cbltest/api/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ def response(self) -> TestServerResponse:
"""Gets the body of the response that had the bad status"""
return self.__response

def __init__(self, code: int, response: TestServerResponse, *args):
def __init__(self, code: int, response: TestServerResponse, message: str):
self.__code = code
self.__response = response
super().__init__(args)
self.__message = message
super().__init__(message)

def __str__(self) -> str:
return self.__message


class CblTimeoutError(Exception):
Expand Down
37 changes: 36 additions & 1 deletion client/src/cbltest/api/syncgateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,41 @@
from cbltest.utils import assert_not_null
from cbltest.version import VERSION

# This is copied from environment/aws/sgw_setup/cert/ca_cert.pem
# So if that file ever changes, change this too.
_SGW_CA_CERT: str = """-----BEGIN CERTIFICATE-----
MIIFWTCCA0GgAwIBAgIUBdrc0OhquX8RnXtZ6AiOY+57C18wDQYJKoZIhvcNAQEL
BQAwPDEZMBcGA1UEAwwQSW50ZXJuYWwgVGVzdCBDQTESMBAGA1UECgwJQ291Y2hi
YXNlMQswCQYDVQQGEwJVUzAeFw0yNTEwMjkwMTAzMDBaFw0yNzEwMjkwMTAzMDBa
MDwxGTAXBgNVBAMMEEludGVybmFsIFRlc3QgQ0ExEjAQBgNVBAoMCUNvdWNoYmFz
ZTELMAkGA1UEBhMCVVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCl
vMLIQDFfEcttEUSzBKkzoRSSLJ3Z/73xmJxBenCtZ9HasLhF3iJxwyQK09nD7sLv
RRwLeRfY8QObr/F/qJAa1cQtVA/5UxIiKsjDk+TrUibg4p6NFSgKUEg+08D0tRHG
CF3CF/3qcM/10A+Pg2K1COaAtPrYjslOv8DoDBzwOBxibaheDZmtBdPEeHghDXZr
DWYDe2770XGzKYqINCEDxNdyDUBdiNSzuX2h/YeZi6vGTtpAt3Iti2SIerRrCiah
UOlykQoqiDVh4JPXts79Xhszw0oDK6YWHEBBfXmYDUdYAyF97XC6hZc+6HxiCVTB
887mkyLCuKMGfB3dabyCqJ31fXm7gmufOs8voCfi/sKjLgcdZQUY4Gw345oYI3Yw
O41ig/uR04KW2xASba38vXt0fEl9/50+AO3xAy9oaY36nLSnBwTV72VbvTlvevGf
zSHbVIbtzcuovpudghYizmIqMEFguc8VsGgmwZb8mkypzB80SOoED3nJRziIK1ym
e+NuO0DIG6xMPUhputNhwqaeYXuSmcUH5YcmLN//ewMIjzxoH33H1cwcADHFioR/
YfIraSgVZCUhrN9aJlXdDOzDuhbVpXYJMbh5PfAiNLHPCXmo685Utf3ID+nFW1wd
WOIyuE3aJ5KVtG8hjlgKARV7eEqtxHjIl41QtsxalwIDAQABo1MwUTAdBgNVHQ4E
FgQUs2WdMu1wh9pJ5dPN80yN1NPAkSswHwYDVR0jBBgwFoAUs2WdMu1wh9pJ5dPN
80yN1NPAkSswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAhiYP
a9dvAv/33u9vBKzUo045RRrfEpv80DSZQb4ttyulrIfbaLFHxaDcf2+S+mywAgoW
tf9SAwWO41qU7sfIBnFdCh982nP1dD707GDAZIe8ZNpl/Vu3hWY3TRQAp9ufA51w
wxn0m2tOS18UXpv5BNX1kVaLlAiOzRzmP1ghx08v9yd8eBgnjJ89D2m1U+qFS1Xk
egiyw66HHc3bG+eo523/l4RDqTx6KkhYnD3Bz89IxMaeK7CuynCY3VyVWPeIUfBr
clkDBqZa4o7fD3xV6Wiu/NHZsWJx3wog1wwelvlsyOVM+mfd4IOsPGVCCdDGtpoq
sT+f9mPDXXHKuDER8a7HiCgGK8rAQtCm/P5UFp2HUEIru/psWCXc3vh9HYVX9W79
TwS+AVAlkeVogs1ugqAXOuGmstnevj6XzA8PszCKDSIV+t1PJSSOtypUyN4gbGGx
sk1s9bwqy7bw2cMh3tt7HromGOoLnPxnsbQCs5HsqNdiEsPABWnI6m7epm0tFjCe
gHDyw1LdmZlZ3R7DT+CwfyhxL6hktfs8h7goR1vkmS2q0Alxmw9faKVVpDyWnsZC
qv6PMC0fI7jhvrr2Uf2Hhw9SQlBFwZ7LjjLqjuuJkclM4VooDElsLbPjSUbA+c5h
WCKJ0c94mrl9GwwBmcSIKJBvd6u7uAta2fREJeE=
-----END CERTIFICATE-----
"""


class _CollectionMap(JSONSerializable):
@property
Expand Down Expand Up @@ -344,7 +379,7 @@ def _create_session(
self, secure: bool, scheme: str, url: str, port: int, auth: BasicAuth | None
) -> ClientSession:
if secure:
ssl_context = ssl.create_default_context(cadata=self.tls_cert())
ssl_context = ssl.create_default_context(cadata=_SGW_CA_CERT)
# Disable hostname check so that the pre-generated SG can be used on any machines.
ssl_context.check_hostname = False
return ClientSession(
Expand Down
4 changes: 2 additions & 2 deletions client/src/cbltest/requests_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ async def send(
cbl_trace(f"Received {ret_val} from {self.__url}")
if not resp.ok:
raise CblTestServerBadResponseError(
resp.status, ret_val, f"{self} returned {resp.status}"
resp.status, ret_val, f"returned {resp.status}"
)

return ret_val
Expand Down Expand Up @@ -167,7 +167,7 @@ async def send(
cbl_trace(f"Received {ret_val} from {self.__url}")
if ret_val.status_code != 200:
raise CblTestServerBadResponseError(
ret_val.status_code, ret_val, f"{self} returned {ret_val.status_code}"
ret_val.status_code, ret_val, f"returned {ret_val.status_code}"
)

return ret_val
Expand Down
2 changes: 2 additions & 0 deletions dataset/server/dbs/js/travel/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"name": "travel",
"collections": [
"travel.airlines",
"travel.airports",
"travel.hotels",
"travel.landmarks",
"travel.routes"
]
}
Empty file.
Empty file.
23 changes: 0 additions & 23 deletions environment/aws/common/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,29 +54,6 @@ def check_aws_key_checking() -> None:
)


def get_ec2_hostname(hostname: str) -> str:
"""
Convert an IP address to an EC2 hostname.

Args:
hostname (str): The IP address.

Returns:
str: The EC2 hostname.

Raises:
ValueError: If the hostname is not an IP address.
"""
if hostname.startswith("ec2-"):
return hostname

components = hostname.split(".")
if len(components) != 4:
raise ValueError(f"Invalid hostname {hostname}")

return f"ec2-{hostname.replace('.', '-')}.compute-1.amazonaws.com"


def start_container(
name: str,
context_name: str,
Expand Down
23 changes: 23 additions & 0 deletions environment/aws/common/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,29 @@ def untar_directory(input: Path, output: Path) -> None:
click.echo("Done")


def get_ec2_hostname(hostname: str) -> str:
"""
Convert an IP address to an EC2 hostname.

Args:
hostname (str): The IP address.

Returns:
str: The EC2 hostname.

Raises:
ValueError: If the hostname is not an IP address.
"""
if hostname.startswith("ec2-"):
return hostname

components = hostname.split(".")
if len(components) != 4:
raise ValueError(f"Invalid hostname {hostname}")

return f"ec2-{hostname.replace('.', '-')}.compute-1.amazonaws.com"


@contextmanager
def pushd(new_dir: Path):
prev_dir = Path.cwd()
Expand Down
3 changes: 1 addition & 2 deletions environment/aws/lb_setup/setup_load_balancers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@

from environment.aws.common.docker import (
check_aws_key_checking,
get_ec2_hostname,
start_container,
)
from environment.aws.common.io import LIGHT_GRAY, sftp_progress_bar
from environment.aws.common.io import LIGHT_GRAY, get_ec2_hostname, sftp_progress_bar
from environment.aws.common.output import header
from environment.aws.topology_setup.setup_topology import TopologyConfig

Expand Down
3 changes: 1 addition & 2 deletions environment/aws/logslurp_setup/setup_logslurp.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@

from environment.aws.common.docker import (
check_aws_key_checking,
get_ec2_hostname,
start_container,
)
from environment.aws.common.io import LIGHT_GRAY, sftp_progress_bar
from environment.aws.common.io import LIGHT_GRAY, get_ec2_hostname, sftp_progress_bar
from environment.aws.common.output import header
from environment.aws.topology_setup.setup_topology import TopologyConfig

Expand Down
31 changes: 31 additions & 0 deletions environment/aws/sgw_setup/cert/ca_cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFWTCCA0GgAwIBAgIUBdrc0OhquX8RnXtZ6AiOY+57C18wDQYJKoZIhvcNAQEL
BQAwPDEZMBcGA1UEAwwQSW50ZXJuYWwgVGVzdCBDQTESMBAGA1UECgwJQ291Y2hi
YXNlMQswCQYDVQQGEwJVUzAeFw0yNTEwMjkwMTAzMDBaFw0yNzEwMjkwMTAzMDBa
MDwxGTAXBgNVBAMMEEludGVybmFsIFRlc3QgQ0ExEjAQBgNVBAoMCUNvdWNoYmFz
ZTELMAkGA1UEBhMCVVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCl
vMLIQDFfEcttEUSzBKkzoRSSLJ3Z/73xmJxBenCtZ9HasLhF3iJxwyQK09nD7sLv
RRwLeRfY8QObr/F/qJAa1cQtVA/5UxIiKsjDk+TrUibg4p6NFSgKUEg+08D0tRHG
CF3CF/3qcM/10A+Pg2K1COaAtPrYjslOv8DoDBzwOBxibaheDZmtBdPEeHghDXZr
DWYDe2770XGzKYqINCEDxNdyDUBdiNSzuX2h/YeZi6vGTtpAt3Iti2SIerRrCiah
UOlykQoqiDVh4JPXts79Xhszw0oDK6YWHEBBfXmYDUdYAyF97XC6hZc+6HxiCVTB
887mkyLCuKMGfB3dabyCqJ31fXm7gmufOs8voCfi/sKjLgcdZQUY4Gw345oYI3Yw
O41ig/uR04KW2xASba38vXt0fEl9/50+AO3xAy9oaY36nLSnBwTV72VbvTlvevGf
zSHbVIbtzcuovpudghYizmIqMEFguc8VsGgmwZb8mkypzB80SOoED3nJRziIK1ym
e+NuO0DIG6xMPUhputNhwqaeYXuSmcUH5YcmLN//ewMIjzxoH33H1cwcADHFioR/
YfIraSgVZCUhrN9aJlXdDOzDuhbVpXYJMbh5PfAiNLHPCXmo685Utf3ID+nFW1wd
WOIyuE3aJ5KVtG8hjlgKARV7eEqtxHjIl41QtsxalwIDAQABo1MwUTAdBgNVHQ4E
FgQUs2WdMu1wh9pJ5dPN80yN1NPAkSswHwYDVR0jBBgwFoAUs2WdMu1wh9pJ5dPN
80yN1NPAkSswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAhiYP
a9dvAv/33u9vBKzUo045RRrfEpv80DSZQb4ttyulrIfbaLFHxaDcf2+S+mywAgoW
tf9SAwWO41qU7sfIBnFdCh982nP1dD707GDAZIe8ZNpl/Vu3hWY3TRQAp9ufA51w
wxn0m2tOS18UXpv5BNX1kVaLlAiOzRzmP1ghx08v9yd8eBgnjJ89D2m1U+qFS1Xk
egiyw66HHc3bG+eo523/l4RDqTx6KkhYnD3Bz89IxMaeK7CuynCY3VyVWPeIUfBr
clkDBqZa4o7fD3xV6Wiu/NHZsWJx3wog1wwelvlsyOVM+mfd4IOsPGVCCdDGtpoq
sT+f9mPDXXHKuDER8a7HiCgGK8rAQtCm/P5UFp2HUEIru/psWCXc3vh9HYVX9W79
TwS+AVAlkeVogs1ugqAXOuGmstnevj6XzA8PszCKDSIV+t1PJSSOtypUyN4gbGGx
sk1s9bwqy7bw2cMh3tt7HromGOoLnPxnsbQCs5HsqNdiEsPABWnI6m7epm0tFjCe
gHDyw1LdmZlZ3R7DT+CwfyhxL6hktfs8h7goR1vkmS2q0Alxmw9faKVVpDyWnsZC
qv6PMC0fI7jhvrr2Uf2Hhw9SQlBFwZ7LjjLqjuuJkclM4VooDElsLbPjSUbA+c5h
WCKJ0c94mrl9GwwBmcSIKJBvd6u7uAta2fREJeE=
-----END CERTIFICATE-----
Loading
Loading