Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ coverage.xml
*.py,cover
.hypothesis/
.pytest_cache/
python/adelphi/tox.ini

# Translations
*.mo
Expand Down
86 changes: 86 additions & 0 deletions python/adelphi/bin/test-adelphi
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!python

# Run test suite for some set of Cassandra versions.
#
# We implement this as a front-end script because the tox/pytest/unittest chain
# isn't great about iterating over a suite of test fixtures and re-running the
# collected tests for each of them. Rather than fight with the frameworks we
# manage the fixture iteration manually in this script. This also has the
# nice side effect of moving a lot of C* checking/session code out of the test
# suite, which in turn should allow us to write simpler tests.
import configparser
import os

from tests.util.cassandra_util import connectToLocalCassandra

import click
import docker
from tenacity import retry, stop_after_attempt, wait_fixed
import tox


# Default C* versions to include in all integration tests
DEFAULT_CASSANDRA_VERSIONS = ["2.1.22", "2.2.19", "3.0.23", "3.11.10", "4.0-rc1"]

TOX_DEPENDENCIES = """pytest
subprocess32 ~= 3.5
tenacity ~= 7.0"""
TOX_CONFIG = "tox.ini"


@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def runCassandraContainer(client, version):
return client.containers.run(name="adelphi", remove=True, detach=True, ports={9042: 9042}, image="cassandra:{}".format(version))


def writeToxIni(version):
config = configparser.ConfigParser()
config["tox"] = { "envlist": "py2, py3" }
envs = {"CASSANDRA_VERSION": version}
config["testenv"] = {"deps": TOX_DEPENDENCIES, \
"commands": "pytest {posargs}", \
"setenv": "CASSANDRA_VERSION = {}".format(version)}
with open(TOX_CONFIG, 'w') as configfile:
config.write(configfile)

@click.command()
@click.option('--cassandra', '-c', multiple=True, type=str)
@click.option('--python', '-p', multiple=True, type=click.Choice(["py2","py3"], case_sensitive = False))
@click.option("--pytest", "-t", type=str, help="Arguments to be passed to pytest")
def runtests(cassandra, python, pytest):
client = docker.from_env()
tox_args = ["-e {}".format(py) for py in python] if python else []
if pytest:
tox_args.append("--")
tox_args.append(pytest)
print("Full tox args: {}".format(tox_args))

cassandra_versions = cassandra or DEFAULT_CASSANDRA_VERSIONS
print("Cassandra versions to test: {}".format(','.join(cassandra_versions)))
for version in cassandra_versions:

print("Running test suite for Cassandra version {}".format(version))
container = runCassandraContainer(client, version)

print("Validating connection to local Cassandra")
connectToLocalCassandra()

try:
if os.path.exists(TOX_CONFIG):
os.remove(TOX_CONFIG)
writeToxIni(version)

# cmdline() will raise SystemExit when it's done so trap that here to avoid
# exiting all the things
try:
tox.cmdline(tox_args)
except SystemExit:
pass
except Exception as exc:
print("Exception running tests for Cassandra version {}".format(version), exc)
finally:
container.stop()


if __name__ == '__main__':
runtests(obj={})
5 changes: 5 additions & 0 deletions python/adelphi/test-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
click ~= 7.1
cassandra-driver ~= 3.24
docker ~= 4.4
tenacity ~= 7.0
tox ~= 3.22
138 changes: 42 additions & 96 deletions python/adelphi/tests/integration/__init__.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
import logging
import os
import shutil
import sys
import tempfile
import time

from collections import namedtuple

from cassandra.cluster import Cluster
try:
import unittest2 as unittest
except ImportError:
import unittest

import docker
from tenacity import retry, stop_after_attempt, wait_fixed
from collections import namedtuple

# Default C* versions to include in all integration tests
CASSANDRA_VERSIONS = ["2.1.22", "2.2.19", "3.0.23", "3.11.9", "4.0-beta4"]
from tests.util.cassandra_util import callWithCassandra, createSchema

logging.basicConfig(filename="adelphi.log", level=logging.INFO)
log = logging.getLogger('adelphi')

TempDirs = namedtuple('TempDirs', 'basePath, outputDirPath')

class SchemaTestMixin:

def __keyspacesForCluster(cluster):
return set(cluster.metadata.keyspaces.keys())


def setupSchema(schemaPath):
return callWithCassandra(lambda _,s: createSchema(s, schemaPath))


def getAllKeyspaces():
return callWithCassandra(lambda c,s: __keyspacesForCluster(c))


def dropNewKeyspaces(origKeyspaces):
def dropFn(cluster, session):
currentKeyspaces = __keyspacesForCluster(cluster)
droppingKeyspaces = currentKeyspaces - origKeyspaces
log.info("Dropping the following keyspaes created by this test: {}".format(",".join(droppingKeyspaces)))
for keyspace in droppingKeyspaces:
session.execute("drop keyspace {}".format(keyspace))
return callWithCassandra(dropFn)


class SchemaTestCase(unittest.TestCase):

def basePath(self, name):
return os.path.join(self.dirs.basePath, name)
Expand All @@ -45,96 +64,23 @@ def makeTempDirs(self):
self.dirs = TempDirs(base, outputDir)


def connectToLocalCassandra(self):
session = None
while not session:
try:
cluster = Cluster(["127.0.0.1"],port=9042)
session = cluster.connect()

# Confirm that the session is actually functioning before calling things good
rs = session.execute("select * from system.local")
log.info("Connected to Cassandra cluster, first row of system.local: {}".format(rs.one()))
log.info("Cassandra cluster ready")
return (cluster,session)
except:
log.info("Couldn't quite connect yet, will retry")
time.sleep(1)


def createSchema(self, session=None):
schemaPath = self.getBaseSchemaPath()
log.info("Creating schema on Cassandra cluster from file {}".format(schemaPath))
with open(schemaPath) as schema:
buff = ""
for line in schema:
realLine = line.strip()
if len(realLine) == 0:
log.debug("Skipping empty statement")
continue
if realLine.startswith("//"):
log.debug("Skipping commented statement {}".format(stmt))
continue
buff += (" " if len(buff) > 0 else "")
buff += realLine
if realLine.endswith(';'):
log.debug("Executing statement {}".format(buff))
try:
session.execute(buff)
except:
log.error("Exception executing statement: {}".format(buff), exc_info=sys.exc_info()[0])
self.fail("Exception executing statement: {}, check log for details".format(buff))
buff = ""


@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def getContainer(self, client, version):
return client.containers.run(name="adelphi", remove=True, detach=True, ports={9042:9042}, image="cassandra:{}".format(version))


def runTestForVersion(self, version=None):
log.info("Testing Cassandra version {}".format(version))

client = docker.from_env()
container = self.getContainer(client, version)

self.makeTempDirs()

(cluster,session) = (None,None)
try:
(cluster,session) = self.connectToLocalCassandra()
self.createSchema(session)
log.info("Running Adelphi")
self.runAdelphi(version)
log.info("Adelphi run completed, evaluating Adelphi output(s)")
self.evalAdelphiOutput(version)
except:
log.error("Exception running test for version {}".format(version), exc_info=sys.exc_info()[0])
self.fail("Exception running test for version {}, check log for details".format(version))
finally:
if cluster:
cluster.shutdown()
def setUp(self):
# Invoking for completeness; for unittest base setUp/tearDown impls are no-ops
super(SchemaTestCase, self).setUp()

if "KEEP_CONTAINER" in os.environ:
log.info("KEEP_CONTAINER env var set, preserving Cassandra container 'adelphi'")
else:
container.stop()
# This should be set in the tox config
self.version = os.environ["CASSANDRA_VERSION"]
log.info("Testing Cassandra version {}".format(self.version))

self.cleanUpVersion(version)


def testVersions(self):
versions = CASSANDRA_VERSIONS
if "CASSANDRA_VERSIONS" in os.environ:
versions = [s.strip() for s in os.environ["CASSANDRA_VERSIONS"].split(',')]

log.info("Testing the following Cassandra versions: {}".format(versions))
self.makeTempDirs()

for version in versions:
self.runTestForVersion(version)

def tearDown(self):
super(SchemaTestCase, self).tearDown()

def cleanUpVersion(self, version):
# TODO: Note that there's no easy way to access this from test-adelphi unless we modify the
# ini generation code... and I'm not completely sure that's worth it. Might want to think
# about just deleting this outright... or making it a CLI option that can be easily accessed.
if "KEEP_LOGS" in os.environ:
log.info("KEEP_LOGS env var set, preserving logs/output at {}".format(self.dirs.basePath))
else:
Expand Down
46 changes: 0 additions & 46 deletions python/adelphi/tests/integration/cql/__init__.py

This file was deleted.

53 changes: 0 additions & 53 deletions python/adelphi/tests/integration/cql/test_cql_export_outputdir.py

This file was deleted.

Loading