Merge 'test.py: fix bugs, add support for flaky tests' from Konstantin Osipov

Marking a test as flaky allows to keep running it in CI rather than disable it when it's discovered that a test is flaky.
Flaky tests, if they fail, show up as flaky in the output, but don't fail the CI.
```
kostja@hulk:~/work/scylla/scylla$ ./test.py cdc_with --repeat=30 --verbose
Found 30 tests.
================================================================================
[N/TOTAL]   SUITE    MODE   RESULT   TEST
------------------------------------------------------------------------------
[1/30]       cql     debug  [ FLKY ] cdc_with_lwt_test.2 9.36s
[2/30]       cql     debug  [ FLKY ] cdc_with_lwt_test.1 9.53s
[3/30]       cql     debug  [ PASS ] cdc_with_lwt_test.7 9.37s
[4/30]       cql     debug  [ PASS ] cdc_with_lwt_test.8 9.41s
[5/30]       cql     debug  [ PASS ] cdc_with_lwt_test.10 9.76s
[6/30]       cql     debug  [ FLKY ] cdc_with_lwt_test.9 9.71s
```

Closes #10721

* github.com:scylladb/scylla:
  test.py: add support for flaky tests
  test.py: make Test hierarchy resettable
  test.py: proper suite name in the log
  test.py: shutdown cassandra-python connection before exit
This commit is contained in:
Kamil Braun
2022-06-10 19:00:36 +02:00
3 changed files with 79 additions and 9 deletions

View File

@@ -47,7 +47,7 @@ class ArtifactRegistry:
the suite. Executing exit artifacts right away is a good idea
because it kills running processes and frees their resources
early."""
logging.info("Cleaning up after suite %s...", suite)
logging.info("Cleaning up after suite %s...", suite.suite_key)
# Only drop suite artifacts if the suite executed successfully.
if not failed and suite in self.suite_artifacts:
await asyncio.gather(*self.suite_artifacts[suite])
@@ -55,7 +55,7 @@ class ArtifactRegistry:
if suite in self.exit_artifacts:
await asyncio.gather(*self.exit_artifacts[suite])
del self.exit_artifacts[suite]
logging.info("Done cleaning up after suite %s...", suite)
logging.info("Done cleaning up after suite %s...", suite.suite_key)
def add_suite_artifact(self, suite: Suite, artifact: Callable[[], Artifact]) -> None:
self.suite_artifacts.setdefault(suite, []).append(artifact())

View File

@@ -15,6 +15,7 @@ from typing import Optional, List, Callable
from cassandra import InvalidRequest # type: ignore
from cassandra.auth import PlainTextAuthProvider # type: ignore
from cassandra.cluster import Cluster, NoHostAvailable # type: ignore
from cassandra.cluster import Session # type: ignore
from cassandra.cluster import ExecutionProfile, EXEC_PROFILE_DEFAULT # type: ignore
from cassandra.policies import RoundRobinPolicy # type: ignore
@@ -108,6 +109,8 @@ class ScyllaServer:
self.seeds = seed
self.cmd: Optional[asyncio.subprocess.Process] = None
self.log_savepoint = 0
self.control_cluster: Optional[Cluster] = None
self.control_connection: Optional[Session] = None
async def stop_server() -> None:
if self.is_running:
@@ -227,8 +230,9 @@ class ScyllaServer:
session.execute("CREATE KEYSPACE k WITH REPLICATION = {" +
"'class' : 'SimpleStrategy', 'replication_factor' : 1 }")
session.execute("DROP KEYSPACE k")
self.control_connection = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile},
contact_points=[self.hostname], auth_provider=auth).connect()
self.control_cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile},
contact_points=[self.hostname], auth_provider=auth)
self.control_connection = self.control_cluster.connect()
return True
except (NoHostAvailable, InvalidRequest):
return False
@@ -316,6 +320,11 @@ Check the log files:
return
try:
if self.control_connection is not None:
self.control_connection.shutdown()
if self.control_cluster is not None:
self.control_cluster.shutdown()
self.cmd.kill()
except ProcessLookupError:
pass
@@ -326,6 +335,7 @@ Check the log files:
logging.info("stopped server at host %s", hostname)
self.cmd = None
self.control_connection = None
self.control_cluster = None
async def uninstall(self) -> None:
"""Clear all files left from a stopped server, including the