Skip to content

Commit ce1053a

Browse files
authored
Merge branch 'main' into replication_url_for_testserver
2 parents 4d32048 + dc7e836 commit ce1053a

147 files changed

Lines changed: 749 additions & 1055 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.pre-commit-config.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v5.0.0
4+
hooks:
5+
- id: check-executables-have-shebangs
6+
- id: check-shebang-scripts-are-executable
7+
- repo: https://github.com/astral-sh/ruff-pre-commit
8+
rev: v0.11.7
9+
hooks:
10+
- id: ruff
11+
- id: ruff-format
12+
- repo: https://github.com/asottile/pyupgrade
13+
rev: v3.19.1
14+
hooks:
15+
- id: pyupgrade
16+
args: [--py310-plus]

README.md

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ The system consists of 4 components:
1717
* README.md - this file
1818
* client - A python framework that configures the environment, runs tests and reports their results
1919
* dataset - A collection datasets used in tests. Each dataset appears in two formats, as a cblite2 db, and as raw JSON
20-
* environment - The docker compose script that creates and runs the environment
20+
* environment - Scripts and such for setting up and tearing down a backend environment
2121
* jenkins - The jenkins pipelines and the docker compose for running the Jenkins server.
2222
* servers - A test server for each CBL platform. Servers run on their platform and accept instructions from the client to run tests
2323
* spec - Documentation: The specification for this system.
@@ -28,7 +28,7 @@ The system consists of 4 components:
2828
### Requirements
2929

3030
1. [Docker](https://www.docker.com/get-started)
31-
2. [Python 3.9+](https://www.python.org/downloads)
31+
2. [Python 3.10+](https://www.python.org/downloads)
3232
3. [OpenSSL 1.1 for CBS Python SDK](https://docs.couchbase.com/python-sdk/current/hello-world/start-using-sdk.html)
3333
4. [Git LFS](https://git-lfs.com)
3434

@@ -40,43 +40,15 @@ The system consists of 4 components:
4040
```
4141
This repository uses Git LFS to store binary dataset files. Ensure that you have [Git LFS](https://git-lfs.com) installed, and run `git lfs install` once to setup the extension hook before cloning the repository.
4242

43-
2. Open a terminal window and start the environment by running the `./start_environment.py` script in the environment folder.
44-
The script will start CBS and SG in the docker container in the background and wait until SG is successfully started before exiting.
45-
```
46-
cd environment
47-
./start_environment.py
48-
```
49-
* To shutdown the environment, run `docker compose down`.
50-
51-
3. Build and run the test server of the platform that you want to test.
52-
* [C](https://github.com/couchbaselabs/couchbase-lite-tests/tree/main/servers/c)
53-
* Android
54-
* .Net
55-
* iOS
56-
57-
4. From the tests directory, set up a python virtual environment:
58-
```
59-
cd tests
60-
python3 -m venv venv
61-
. venv/bin/activate
62-
pip install -r requirements.txt
63-
```
64-
* You may need to use `python<version>` command e.g. `python3.10` if you already have `python3` for the other version.
65-
* You only need to create the python venv once. To reactivate run `. venv/bin/activate`, and to deactivate run `deactivate`.
66-
* When you update the repo or the Python TDK code, run `pip install ../client` to update the TDK.
43+
2. From the jenkins/pipelines directory of your choice, run the relevant script (such as run_test.ps1, test.sh, etc) with the various arguments regarding versions of things to use.
6744

68-
5. Edit the file `config.example.json` with the URL of your Test server started in the Step 2.
69-
```
70-
"test-servers": ["http://192.168.100.104:8080"]
71-
```
72-
6. Run the pytest tests as examples below.
73-
```
74-
# Run one test file:
75-
pytest --config config.example.json test_basic_replication.py
45+
### Contributing
7646

77-
# Run all tests:
78-
pytest --config config.example.json
47+
Notice that this repo has a .pre-commit-config.yaml file, which means it is ready to use with the [pre-commit](https://pre-commit.com/#intro) python tool. Essentially, after you clone this repo you should run
7948

80-
# Run all with detail and without deprecation warning:
81-
pytest -v --no-header -W ignore::DeprecationWarning --config config.example.json
82-
```
49+
```
50+
pip install pre-commit
51+
pre-commit install
52+
```
53+
54+
After that git pre-commit validation will check various things for you to ensure adherence to best practices and standards.

client/smoke_tests/test_snapshot_verify.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, List, Optional, Union
1+
from typing import Any
22

33
import pytest
44
from cbltest import CBLPyTest
@@ -16,12 +16,12 @@ def setup_method(self, method):
1616

1717
def upsert_multiple(
1818
self,
19-
instances: List[Union[SnapshotUpdater, DatabaseUpdater]],
19+
instances: list[SnapshotUpdater | DatabaseUpdater],
2020
collection: str,
2121
document: str,
22-
new_properties: Optional[List[Dict[str, Any]]] = None,
23-
removed_properties: Optional[List[str]] = None,
24-
new_blobs: Optional[Dict[str, str]] = None,
22+
new_properties: list[dict[str, Any]] | None = None,
23+
removed_properties: list[str] | None = None,
24+
new_blobs: dict[str, str] | None = None,
2525
) -> None:
2626
for instance in instances:
2727
instance.upsert_document(
@@ -30,7 +30,7 @@ def upsert_multiple(
3030

3131
def delete_multiple(
3232
self,
33-
instances: List[Union[SnapshotUpdater, DatabaseUpdater]],
33+
instances: list[SnapshotUpdater | DatabaseUpdater],
3434
collection: str,
3535
document: str,
3636
) -> None:
@@ -39,7 +39,7 @@ def delete_multiple(
3939

4040
def purge_multiple(
4141
self,
42-
instances: List[Union[SnapshotUpdater, DatabaseUpdater]],
42+
instances: list[SnapshotUpdater | DatabaseUpdater],
4343
collection: str,
4444
document: str,
4545
) -> None:

client/smoke_tests/test_start_replicator.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from typing import Optional
2-
31
import pytest
42
from cbltest import CBLPyTest
53
from cbltest.api.database import Database
@@ -53,7 +51,7 @@ async def test_bad_endpoint(self, cblpytest: CBLPyTest) -> None:
5351
],
5452
)
5553
async def test_known_conflict_resolvers(
56-
self, cblpytest: CBLPyTest, name: str, parameters: Optional[dict]
54+
self, cblpytest: CBLPyTest, name: str, parameters: dict | None
5755
):
5856
dbs = await cblpytest.test_servers[0].create_and_reset_db(["db1"])
5957
db = dbs[0]

client/smoke_tests/test_update_endpoint.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from typing import Optional
2-
31
import pytest
42
from cbltest import CBLPyTest
53
from cbltest.api.database import Database
@@ -13,7 +11,7 @@ def setup_method(self, method) -> None:
1311
# will not be informed about the currently running test
1412
CBLPyTestGlobal.running_test_name = method.__name__
1513

16-
self.db: Optional[Database] = None
14+
self.db: Database | None = None
1715

1816
@pytest.mark.asyncio(loop_scope="session")
1917
@pytest.mark.parametrize(

client/src/cbltest/__init__.py

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
from json import dumps
2-
from sys import version_info
3-
from typing import Dict, List, Optional
42

53
from .api.couchbaseserver import CouchbaseServer
64
from .api.syncgateway import SyncGateway
@@ -17,9 +15,6 @@
1715
from .logging import LogLevel, cbl_log_init, cbl_setLogLevel
1816
from .requests import RequestFactory
1917

20-
if version_info < (3, 9):
21-
raise RuntimeError("Python must be at least v3.9!")
22-
2318

2419
class CBLPyTest:
2520
"""
@@ -38,7 +33,7 @@ def log_level(self) -> LogLevel:
3833
return self.__log_level
3934

4035
@property
41-
def extra_props(self) -> Optional[Dict[str, str]]:
36+
def extra_props(self) -> dict[str, str] | None:
4237
"""Gets the extra properties provided as parsed from the provided JSON file path"""
4338
return self.__extra_props
4439

@@ -48,30 +43,30 @@ def request_factory(self) -> RequestFactory:
4843
return self.__request_factory
4944

5045
@property
51-
def test_servers(self) -> List[TestServer]:
46+
def test_servers(self) -> list[TestServer]:
5247
"""Gets the list of Test Servers available"""
5348
return self.__test_servers
5449

5550
@property
56-
def sync_gateways(self) -> List[SyncGateway]:
51+
def sync_gateways(self) -> list[SyncGateway]:
5752
"""Gets the list of Sync Gateways available"""
5853
return self.__sync_gateways
5954

6055
@property
61-
def couchbase_servers(self) -> List[CouchbaseServer]:
56+
def couchbase_servers(self) -> list[CouchbaseServer]:
6257
"""Gets the list of Couchbase Servers available"""
6358
return self.__couchbase_servers
6459

6560
@property
66-
def load_balancers(self) -> List[str]:
61+
def load_balancers(self) -> list[str]:
6762
"""Gets the list of Load Balancers available"""
6863
return self.__config.load_balancers
6964

7065
@staticmethod
7166
async def create(
7267
config_path: str,
7368
log_level: LogLevel = LogLevel.VERBOSE,
74-
extra_props_path: Optional[str] = None,
69+
extra_props_path: str | None = None,
7570
test_server_only: bool = False,
7671
):
7772
ret_val = CBLPyTest(config_path, log_level, extra_props_path, test_server_only)
@@ -93,7 +88,7 @@ def __init__(
9388
self,
9489
config_path: str,
9590
log_level: LogLevel = LogLevel.VERBOSE,
96-
extra_props_path: Optional[str] = None,
91+
extra_props_path: str | None = None,
9792
test_server_only: bool = False,
9893
):
9994
_assert_not_null(config_path, "config_path")
@@ -105,7 +100,7 @@ def __init__(
105100
self.__extra_props = _parse_extra_props(extra_props_path)
106101

107102
self.__request_factory = RequestFactory(self.__config)
108-
self.__test_servers: List[TestServer] = []
103+
self.__test_servers: list[TestServer] = []
109104
index = 0
110105
for ts in self.__config.test_servers:
111106
ts_info = TestServerInfo(ts)
@@ -114,7 +109,7 @@ def __init__(
114109
)
115110
index += 1
116111

117-
self.__sync_gateways: List[SyncGateway] = []
112+
self.__sync_gateways: list[SyncGateway] = []
118113
index = 0
119114
if not test_server_only:
120115
for sg in self.__config.sync_gateways:
@@ -131,7 +126,7 @@ def __init__(
131126
)
132127
index += 1
133128

134-
self.__couchbase_servers: List[CouchbaseServer] = []
129+
self.__couchbase_servers: list[CouchbaseServer] = []
135130
if not test_server_only:
136131
for cbs in self.__config.couchbase_servers:
137132
cbs_info = CouchbaseServerInfo(cbs)

client/src/cbltest/api/cloud.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from json import dumps, load
22
from pathlib import Path
3-
from typing import List, Optional, cast
3+
from typing import cast
44

55
from opentelemetry.trace import get_tracer
66

@@ -35,13 +35,13 @@ def _check_all_indexes_removed(self, bucket: str) -> None:
3535
raise ValueError(f"{count} indexes remain in '{bucket}' bucket")
3636

3737
def _wait_for_all_indexed_removed(self, bucket: str) -> None:
38-
_try_n_times(10, 2, True, self._check_all_indexes_removed, type(None), bucket)
38+
_try_n_times(10, 2, True, self._check_all_indexes_removed, bucket)
3939

4040
async def configure_dataset(
4141
self,
4242
dataset_path: Path,
4343
dataset_name: str,
44-
sg_config_options: Optional[List[str]] = None,
44+
sg_config_options: list[str] | None = None,
4545
) -> None:
4646
"""
4747
Creates a database, ensuring that it is in an empty state when finished

client/src/cbltest/api/couchbaseserver.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
from datetime import timedelta
22
from time import sleep
3-
from typing import Dict, List
43

54
from couchbase.auth import PasswordAuthenticator
6-
from couchbase.bucket import Bucket
75
from couchbase.cluster import Cluster
86
from couchbase.exceptions import (
97
BucketAlreadyExistsException,
@@ -41,7 +39,7 @@ def __init__(self, url: str, username: str, password: str):
4139
self.__cluster = Cluster(url, opts)
4240
self.__cluster.wait_until_ready(timedelta(seconds=10))
4341

44-
def create_collections(self, bucket: str, scope: str, names: List[str]) -> None:
42+
def create_collections(self, bucket: str, scope: str, names: list[str]) -> None:
4543
"""
4644
A function that will create a specified set of collections in the specified scope
4745
which resides in the specified bucket
@@ -55,9 +53,7 @@ def create_collections(self, bucket: str, scope: str, names: List[str]) -> None:
5553
"Create Scope",
5654
attributes={"cbl.scope.name": scope, "cbl.bucket.name": bucket},
5755
):
58-
bucket_obj = _try_n_times(
59-
10, 1, False, self.__cluster.bucket, Bucket, bucket
60-
)
56+
bucket_obj = _try_n_times(10, 1, False, self.__cluster.bucket, bucket)
6157
c = bucket_obj.collections()
6258
try:
6359
if scope != "_default":
@@ -150,7 +146,7 @@ def run_query(
150146
bucket: str,
151147
scope: str = "_default",
152148
collection: str = "_default",
153-
) -> List[Dict]:
149+
) -> list[dict]:
154150
"""
155151
Runs the specified query on the server. The query may be formatted in a special way.
156152

0 commit comments

Comments
 (0)