# -*- encoding: utf-8 -*-
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import os
import shutil
import socket

import fixtures

import psutil

import requests

import testtools

from pifpaf import drivers
from pifpaf.drivers import aodh
from pifpaf.drivers import artemis
from pifpaf.drivers import ceph
from pifpaf.drivers import consul
from pifpaf.drivers import couchdb
from pifpaf.drivers import elasticsearch
from pifpaf.drivers import etcd
from pifpaf.drivers import fakes3
from pifpaf.drivers import gnocchi
from pifpaf.drivers import httpbin
from pifpaf.drivers import influxdb
from pifpaf.drivers import kafka
from pifpaf.drivers import keystone
from pifpaf.drivers import memcached
from pifpaf.drivers import mongodb
from pifpaf.drivers import mysql
from pifpaf.drivers import postgresql
from pifpaf.drivers import qdrouterd
from pifpaf.drivers import rabbitmq
from pifpaf.drivers import redis
from pifpaf.drivers import s3rver
from pifpaf.drivers import swift
from pifpaf.drivers import valkey
from pifpaf.drivers import vault
from pifpaf.drivers import zookeeper

# FIXME(jd) These are path grabbed from the various modules imported above, do
# that in a better way
os.environ["PATH"] = ":".join((
    os.getenv("PATH", ""),
    "/opt/influxdb",
    "/usr/share/elasticsearch/bin",
    "/usr/local/sbin",
    "/opt/kafka/bin",
))

unkillable = os.path.join(
    os.path.dirname(os.path.realpath(__file__)),
    "unkillable.py")


# NOTE(tobias-urdin): The rados python bindings is only installed
# for the python version that the distro ships.
def _has_rados():
    try:
        import rados  # noqa
        return True
    except ImportError:
        return False


class TestDrivers(testtools.TestCase):
    def setUp(self):
        super(TestDrivers, self).setUp()
        self.logger = self.useFixture(
            fixtures.FakeLogger(
                format="%(levelname)8s [%(name)s] %(message)s",
                level=logging.DEBUG,
                nuke_handlers=True,
            )
        )

    def _run(self, cmd):
        self.assertEqual(0, os.system(cmd + " >/dev/null 2>&1"))

    def _do_test_stuck(self, cmd):
        d = drivers.Driver(debug=True)
        d.setUp()
        c, _ = d._exec(cmd, wait_for_line="started")
        parent = psutil.Process(c.pid)
        procs = parent.children(recursive=True)
        procs.append(parent)
        d._kill(c)
        gone, alive = psutil.wait_procs(procs, timeout=0)
        self.assertEqual([], alive)

    @testtools.skip("Skip for now leaves zombie process")
    def test_stuck_no_sigterm_with_children(self):
        self._do_test_stuck(["python", "-u", unkillable])

    @testtools.skip("Skip for now leaves zombie process")
    def test_stuck_no_sigterm_in_children_only(self):
        self._do_test_stuck(["python", "-u", unkillable, "--child-only"])

    @testtools.skip("Skip for now leaves zombie process")
    def test_stuck_no_sigterm_and_parent_exited(self):
        self._do_test_stuck(["python", "-u", unkillable, "--exited-parent"])

    @testtools.skip("Skip for now leaves zombie process")
    def test_stuck_simple(self):
        self._do_test_stuck(["bash", "-c",
                             "trap ':' TERM ; echo started; sleep 10000"])

    @testtools.skip("Driver need rework")
    @testtools.skipUnless(shutil.which("elasticsearch"),
                          "elasticsearch not found")
    def test_elasticsearch(self):
        port = 9201
        self.useFixture(elasticsearch.ElasticsearchDriver(port=port))
        self.assertEqual("es://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_ELASTICSEARCH_PORT"))
        r = requests.get("http://localhost:%d/" % port)
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(shutil.which("etcd"),
                          "etcd not found")
    @testtools.skipUnless(shutil.which("etcdctl"),
                          "etcdctl not found")
    def test_etcd(self):
        port = 4005
        peer_port = 4006
        self.useFixture(etcd.EtcdDriver(port=port, peer_port=peer_port))
        self.assertEqual("etcd://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_ETCD_PORT"))
        r = requests.get("http://localhost:%d/version" % port)
        self.assertEqual(200, r.status_code)
        self._run("etcdctl endpoint health")

    @testtools.skipUnless(shutil.which("etcd"),
                          "etcd not found")
    @testtools.skipUnless(shutil.which("etcdctl"),
                          "etcdctl not found")
    def test_etcd_cluster(self):
        port = 4007
        peer_port = 4008
        self.useFixture(etcd.EtcdDriver(port=port, peer_port=peer_port,
                                        cluster=True))
        self.assertEqual("etcd://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_ETCD_PORT"))
        r = requests.get("http://localhost:%d/version" % port)
        self.assertEqual(200, r.status_code)
        self._run("etcdctl endpoint health")

    @testtools.skipUnless(shutil.which("consul"),
                          "consul not found")
    def test_consul(self):
        port = 8601
        host = consul.ConsulDriver.DEFAULT_HOST
        self.useFixture(consul.ConsulDriver(port=port))
        self.assertEqual("consul://%s:%d" % (host, port),
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_CONSUL_PORT"))
        r = requests.get("http://%s:%d/v1/status/leader" % (host, port))
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(shutil.which("influxd"),
                          "influxd not found")
    def test_influxdb(self):
        port = 51236
        database = 'foobar'
        self.useFixture(influxdb.InfluxDBDriver(port=port, database='foobar'))
        self.assertEqual("influxdb://localhost:%d/%s" % (port, database),
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_INFLUXDB_PORT"))
        self.assertEqual(database, os.getenv("PIFPAF_INFLUXDB_DATABASE"))
        self._run("influx -port %d -execute 'SHOW DATABASES;'" % port)

    @testtools.skipUnless(shutil.which("memcached"),
                          "memcached not found")
    def test_memcached(self):
        port = 11213
        self.useFixture(memcached.MemcachedDriver(port=port))
        self.assertEqual("memcached://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_MEMCACHED_PORT"))

    @testtools.skipUnless(shutil.which("vault"),
                          "vault not found")
    def test_vault(self):
        listen_address = "localhost:5049"
        self.useFixture(vault.VaultDriver(listen_address=listen_address))
        self.assertEqual("http://%s" % listen_address,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual("http://%s" % listen_address,
                         os.getenv("PIFPAF_VAULT_ADDR"))
        self.assertTrue(len(os.getenv("PIFPAF_ROOT_TOKEN")) > 0)

    @testtools.skipUnless(shutil.which("fakes3"),
                          "fakes3 not found")
    def test_fakes3(self):
        port = 8990
        self.useFixture(fakes3.FakeS3Driver(port=port))
        self.assertEqual("s3://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_FAKES3_PORT"))

    @testtools.skipUnless(shutil.which("s3rver"),
                          "s3rver not found")
    def test_s3rver(self):
        port = 4569
        self.useFixture(s3rver.S3rverDriver(port=port))
        self.assertEqual("s3://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual("http://localhost:%d" % port,
                         os.getenv("PIFPAF_HTTP_URL"))

    @testtools.skipUnless(shutil.which("mongod"),
                          "mongod not found")
    def test_mongodb(self):
        port = 29002
        self.useFixture(mongodb.MongoDBDriver(port=port))
        self.assertEqual("mongodb://localhost:%d/test" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_MONGODB_PORT"))
        self._run(
            "mongo --norc --host localhost --port %d --eval 'quit()'" % port)

    @testtools.skipUnless(shutil.which("mysqld"),
                          "mysqld not found")
    def test_mysql(self):
        f = self.useFixture(mysql.MySQLDriver())
        self.assertEqual(
            "mysql://root@localhost/pifpaf?unix_socket=%s/mysql.socket"
            % f.tempdir,
            os.getenv("PIFPAF_URL"))
        self.assertEqual(
            "mysql://root@localhost/pifpaf?unix_socket=%s/mysql.socket"
            % f.tempdir,
            f.url)
        self._run(
            "mysql --no-defaults -S %s -e 'SHOW TABLES;' pifpaf" % f.socket)

    @testtools.skipUnless(shutil.which("pg_config"),
                          "pg_config not found")
    def test_postgresql(self):
        port = 9825
        f = self.useFixture(postgresql.PostgreSQLDriver(port=port))
        self.assertEqual(
            "postgresql://localhost/postgres?host=%s&port=%d"
            % (f.tempdir, port),
            os.getenv("PIFPAF_URL"))
        self._run("psql template1 -c 'CREATE TABLE FOOBAR();'")

    @testtools.skipUnless(shutil.which("pg_config"),
                          "pg_config not found")
    def test_postgresql_async(self):
        port = 9825
        f = self.useFixture(postgresql.PostgreSQLDriver(port=port, sync=False))
        self.assertEqual(
            "postgresql://localhost/postgres?host=%s&port=%d"
            % (f.tempdir, port),
            os.getenv("PIFPAF_URL"))
        self._run("psql template1 -c 'CREATE TABLE FOOBAR();'")

    @testtools.skipUnless(shutil.which("redis-server"),
                          "redis-server not found")
    def test_redis(self):
        port = 6384
        f = self.useFixture(redis.RedisDriver(port=port))
        self.assertEqual("redis://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_REDIS_PORT"))
        self._run("redis-cli -p %d llen pifpaf" % f.port)

    @testtools.skipUnless(shutil.which("redis-server"),
                          "redis-server not found")
    def test_redis_with_password(self):
        port = 6384
        f = self.useFixture(redis.RedisDriver(port=port, password='secrete'))
        self.assertEqual("redis://:secrete@localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_REDIS_PORT"))
        self._run("redis-cli -p %d -a secrete llen pifpaf" % f.port)

    @testtools.skipUnless(shutil.which("redis-sentinel"),
                          "redis-sentinel not found")
    def test_redis_sentinel(self):
        port = 6385
        f = self.useFixture(redis.RedisDriver(sentinel=True, port=port))
        self.assertEqual("redis://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_REDIS_PORT"))
        self.assertEqual("6380", os.getenv("PIFPAF_REDIS_SENTINEL_PORT"))
        self._run("redis-cli -p %d sentinel master pifpaf" % f.sentinel_port)
        self._run("redis-cli -p %d llen pifpaf" % f.port)

    @testtools.skipUnless(shutil.which("redis-sentinel"),
                          "redis-sentinel not found")
    def test_redis_sentinel_with_password(self):
        port = 6385
        f = self.useFixture(redis.RedisDriver(sentinel=True, port=port,
                                              password='secrete'))
        self.assertEqual("redis://:secrete@localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_REDIS_PORT"))
        self.assertEqual("6380", os.getenv("PIFPAF_REDIS_SENTINEL_PORT"))
        self._run("redis-cli -p %d -a secrete sentinel master pifpaf" %
                  f.sentinel_port)
        self._run("redis-cli -p %d -a secrete llen pifpaf" % f.port)

    @testtools.skipUnless(shutil.which("valkey-server"),
                          "valkey-server not found")
    def test_valkey(self):
        port = 6384
        f = self.useFixture(valkey.ValkeyDriver(port=port))
        self.assertEqual("valkey://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_VALKEY_PORT"))
        self._run("valkey-cli -p %d llen pifpaf" % f.port)

    @testtools.skipUnless(shutil.which("valkey-server"),
                          "valkey-server not found")
    def test_valkey_with_password(self):
        port = 6384
        f = self.useFixture(valkey.ValkeyDriver(port=port, password='secrete'))
        self.assertEqual("valkey://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_VALKEY_PORT"))
        self._run("valkey-cli -p %d -a secrete llen pifpaf" % f.port)

    @testtools.skipUnless(shutil.which("valkey-sentinel"),
                          "valkey-sentinel not found")
    def test_valkey_sentinel(self):
        port = 6385
        f = self.useFixture(valkey.ValkeyDriver(sentinel=True, port=port))
        self.assertEqual("valkey://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_VALKEY_PORT"))
        self.assertEqual("6380", os.getenv("PIFPAF_VALKEY_SENTINEL_PORT"))
        self._run("valkey-cli -p %d sentinel master pifpaf" % f.sentinel_port)
        self._run("valkey-cli -p %d llen pifpaf" % f.port)

    @testtools.skipUnless(shutil.which("valkey-sentinel"),
                          "valkey-sentinel not found")
    def test_valkey_sentinel_with_password(self):
        port = 6385
        f = self.useFixture(valkey.ValkeyDriver(sentinel=True, port=port,
                                                password='secrete'))
        self.assertEqual("valkey://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_VALKEY_PORT"))
        self.assertEqual("6380", os.getenv("PIFPAF_VALKEY_SENTINEL_PORT"))
        self._run("valkey-cli -p %d -a secrete sentinel master pifpaf" %
                  f.sentinel_port)
        self._run("valkey-cli -p %d -a secrete llen pifpaf" % f.port)

    @testtools.skipUnless(shutil.which(
        "zkServer.sh", path=":".join(zookeeper.ZooKeeperDriver.PATH)),
        "ZooKeeper not found")
    def test_zookeeper(self):
        port = 2182
        f = self.useFixture(zookeeper.ZooKeeperDriver(port=port))
        self.assertEqual("zookeeper://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(str(port), os.getenv("PIFPAF_ZOOKEEPER_PORT"))
        s = socket.create_connection(("localhost", f.port))
        s.send(b"ruok\n")
        reply = s.recv(1024)
        self.assertEqual(b"imok", reply)

    @testtools.skipUnless(shutil.which("gnocchi-api"),
                          "Gnocchi not found")
    def test_gnocchi(self):
        port = gnocchi.GnocchiDriver.DEFAULT_PORT
        self.useFixture(gnocchi.GnocchiDriver())
        self.assertEqual("gnocchi://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        r = requests.get("http://localhost:%d/" % port)
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(shutil.which("redis-server"),
                          "redis-server not found")
    @testtools.skipUnless(shutil.which("gnocchi-api"),
                          "Gnocchi not found")
    def test_gnocchi_with_redis_coordinator(self):
        self.useFixture(gnocchi.GnocchiDriver(coordination_driver="redis",
                                              port=8043))
        self.assertEqual("gnocchi://localhost:%d" % 8043,
                         os.getenv("PIFPAF_URL"))
        r = requests.get("http://localhost:%d/" % 8043)
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(shutil.which("gnocchi-api"),
                          "Gnocchi not found")
    def test_gnocchi_with_existing_indexer(self):
        port = gnocchi.GnocchiDriver.DEFAULT_PORT + 15
        pg = self.useFixture(postgresql.PostgreSQLDriver(port=9833))
        self.useFixture(gnocchi.GnocchiDriver(
            indexer_url=pg.url, port=port))
        self.assertEqual("gnocchi://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        r = requests.get("http://localhost:%d/" % port)
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(shutil.which("gnocchi-api"),
                          "Gnocchi not found")
    @testtools.skipUnless(shutil.which("swift-proxy-server"),
                          "Swift not found")
    def test_gnocchi_with_existing_swift(self):
        # This test produces a lot of logs and causes an error:
        #   `Length too long: 25727093`.
        # To reduce log size, temporary disable debug log.
        level = drivers.LOG.getEffectiveLevel()
        drivers.LOG.setLevel(logging.INFO)
        try:
            tmp_rootdir = self._get_tmpdir_for_xattr()
            self.useFixture(swift.SwiftDriver(tmp_rootdir=tmp_rootdir))
            self.useFixture(gnocchi.GnocchiDriver(
                storage_url=os.getenv("PIFPAF_URL")))
            self.assertEqual("gnocchi://localhost:8041",
                             os.getenv("PIFPAF_URL"))
            r = requests.get("http://localhost:8041/")
            self.assertEqual(200, r.status_code)
        finally:
            drivers.LOG.setLevel(level)

    @testtools.skipUnless(shutil.which("gnocchi-api"),
                          "Gnocchi not found")
    @testtools.skipUnless(shutil.which("s3rver"),
                          "s3rver not found")
    def test_gnocchi_with_existing_s3rver(self):
        s3 = self.useFixture(s3rver.S3rverDriver(port=4569))
        port = gnocchi.GnocchiDriver.DEFAULT_PORT + 12
        self.useFixture(gnocchi.GnocchiDriver(
            storage_url="s3://gnocchi:pass@localhost:%d" % s3.port,
            port=port))
        self.assertEqual("gnocchi://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        r = requests.get("http://localhost:%d/" % port)
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(_has_rados(), "Rados not found")
    @testtools.skipUnless(shutil.which("gnocchi-api"),
                          "Gnocchi not found")
    @testtools.skipUnless(shutil.which("ceph-mon"),
                          "Ceph Monitor not found")
    @testtools.skipUnless(shutil.which("ceph-osd"),
                          "Ceph OSD not found")
    @testtools.skipUnless(shutil.which("ceph"),
                          "Ceph client not found")
    def test_gnocchi_with_existing_ceph(self):
        port = gnocchi.GnocchiDriver.DEFAULT_PORT + 10
        tmp_rootdir = self._get_tmpdir_for_xattr()
        ceph_driver = ceph.CephDriver(tmp_rootdir=tmp_rootdir)
        self.useFixture(ceph_driver)

        ceph_driver._exec(["ceph", "-c", os.getenv("CEPH_CONF"), "osd",
                           "pool", "create", "gnocchi"]),

        self.useFixture(gnocchi.GnocchiDriver(
            storage_url="ceph://%s" % os.getenv("CEPH_CONF"),
            port=port))
        self.assertEqual("gnocchi://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        r = requests.get("http://localhost:%d/" % port)
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(shutil.which("pg_config"),
                          "pg_config not found")
    @testtools.skipUnless(shutil.which("gnocchi-api"),
                          "Gnocchi not found")
    @testtools.skipUnless(shutil.which("aodh-api"),
                          "Aodh not found")
    def test_aodh_with_existing_db(self):
        pg = self.useFixture(postgresql.PostgreSQLDriver(port=12345))
        a = self.useFixture(aodh.AodhDriver(database_url=pg.url))
        self.assertEqual("aodh://localhost:%d" % a.port,
                         os.getenv("PIFPAF_URL"))
        r = requests.get(os.getenv("PIFPAF_AODH_HTTP_URL"))
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(shutil.which("gnocchi-api"),
                          "Gnocchi not found")
    @testtools.skipUnless(shutil.which("aodh-api"),
                          "Aodh not found")
    def test_aodh(self):
        a = self.useFixture(aodh.AodhDriver())
        self.assertEqual("aodh://localhost:%d" % a.port,
                         os.getenv("PIFPAF_URL"))
        r = requests.get(os.getenv("PIFPAF_AODH_HTTP_URL"))
        self.assertEqual(200, r.status_code)

    @testtools.skipUnless(shutil.which("keystone-manage"),
                          "Keystone not found")
    def test_keystone(self):
        self.skipTest(
            "Keystone does not provide configuration files in venv")
        a = self.useFixture(keystone.KeystoneDriver())
        self.assertEqual("keystone://localhost:%d" % a.port,
                         os.getenv("PIFPAF_URL"))
        r = requests.get(os.getenv("PIFPAF_KEYSTONE_HTTP_URL"))
        self.assertEqual(300, r.status_code)

    @testtools.skipUnless(_has_rados(), "Rados not found")
    @testtools.skipUnless(shutil.which("ceph-mon"),
                          "Ceph Monitor not found")
    @testtools.skipUnless(shutil.which("ceph-osd"),
                          "Ceph OSD not found")
    @testtools.skipUnless(shutil.which("ceph"),
                          "Ceph client not found")
    def test_ceph(self):
        tmp_rootdir = self._get_tmpdir_for_xattr()
        a = self.useFixture(ceph.CephDriver(tmp_rootdir=tmp_rootdir))
        self.assertEqual("ceph://localhost:%d" % a.port,
                         os.getenv("PIFPAF_URL"))
        self.assertIn("ceph.conf", os.getenv("CEPH_CONF"))
        self.assertIn("ceph.conf", os.getenv("PIFPAF_CEPH_CONF"))

    @testtools.skipUnless(shutil.which("rabbitmq-server"),
                          "RabbitMQ not found")
    def test_rabbitmq(self):
        a = self.useFixture(rabbitmq.RabbitMQDriver())
        self.assertEqual("rabbit://%s:%s@localhost:%d//" % (a.username,
                                                            a.password,
                                                            a.port),
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(a.nodename + "@localhost",
                         os.getenv("PIFPAF_RABBITMQ_NODENAME"))
        self.assertEqual(str(a.port), os.getenv("PIFPAF_RABBITMQ_PORT"))

    @testtools.skipUnless(shutil.which("rabbitmq-server"),
                          "RabbitMQ not found")
    def test_rabbitmq_cluster(self):
        a = self.useFixture(rabbitmq.RabbitMQDriver(cluster=True, port=12345))
        self.assertEqual(
            "rabbit://%(user)s:%(pass)s@localhost:%(port1)d,"
            "%(user)s:%(pass)s@localhost:%(port2)d,"
            "%(user)s:%(pass)s@localhost:%(port3)d//" % {
                "user": a.username,
                "pass": a.password,
                "port1": a.port,
                "port2": a.port + 1,
                "port3": a.port + 2},
            os.getenv("PIFPAF_URL"))
        self.assertEqual(a.nodename + "-1@localhost",
                         os.getenv("PIFPAF_RABBITMQ_NODENAME"))
        self.assertEqual(a.nodename + "-1@localhost",
                         os.getenv("PIFPAF_RABBITMQ_NODENAME1"))
        self.assertEqual(a.nodename + "-2@localhost",
                         os.getenv("PIFPAF_RABBITMQ_NODENAME2"))
        self.assertEqual(a.nodename + "-3@localhost",
                         os.getenv("PIFPAF_RABBITMQ_NODENAME3"))
        self.assertEqual(str(a.port), os.getenv("PIFPAF_RABBITMQ_PORT"))

        a.kill_node(a.nodename + "-2@localhost")
        a.stop_node(a.nodename + "-3@localhost")
        a.start_node(a.nodename + "-3@localhost")
        a.start_node(a.nodename + "-2@localhost")

    @testtools.skipUnless(shutil.which("couchdb"),
                          "CouchDB not found")
    def test_couchdb(self):
        port = 6984
        self.useFixture(couchdb.CouchDBDriver(port=port))
        self.assertEqual("couchdb://localhost:%d" % port,
                         os.getenv("PIFPAF_URL"))
        r = requests.get("http://localhost:%d/" % port)
        self.assertEqual(r.json()["couchdb"], "Welcome")

    @testtools.skipUnless(shutil.which("artemis"),
                          "Artemis not found")
    def test_artemis(self):
        self.useFixture(artemis.ArtemisDriver(port=54321))
        self.assertEqual("amqp://localhost:54321",
                         os.getenv("PIFPAF_URL"))
        self.assertEqual("54321", os.getenv("PIFPAF_ARTEMIS_PORT"))
        self.assertEqual("amqp://localhost:54321",
                         os.getenv("PIFPAF_ARTEMIS_URL"))

    @testtools.skipUnless(shutil.which("qdrouterd"),
                          "Qdrouterd not found")
    def test_qdrouterd(self):
        a = self.useFixture(qdrouterd.QdrouterdDriver(port=54321))
        self.assertEqual("amqp://%s:%s@localhost:54321" % (a.username,
                                                           a.password),
                         os.getenv("PIFPAF_URL"))
        self.assertEqual("54321", os.getenv("PIFPAF_QDROUTERD_PORT"))
        self.assertEqual("amqp://localhost:54321",
                         os.getenv("PIFPAF_QDROUTERD_URL"))

    @testtools.skipUnless(shutil.which("kafka-server-start.sh"),
                          "Kafka not found")
    def test_kafka(self):
        a = self.useFixture(kafka.KafkaDriver(port=54321,
                                              zookeeper_port=12345))
        self.assertEqual("kafka://localhost:54321",
                         os.getenv("PIFPAF_URL"))
        self.assertEqual(12345, a.zookeeper_port)
        self.assertEqual("54321", os.getenv("PIFPAF_KAFKA_PORT"))
        self.assertEqual("PLAINTEXT", os.getenv("PIFPAF_KAFKA_PROTOCOL"))
        self.assertEqual("PLAINTEXT://localhost:54321",
                         os.getenv("PIFPAF_KAFKA_URL"))

    @testtools.skipUnless(shutil.which("swift-proxy-server"),
                          "Swift not found")
    def test_swift(self):
        tmp_rootdir = self._get_tmpdir_for_xattr()
        a = self.useFixture(swift.SwiftDriver(tmp_rootdir=tmp_rootdir))
        self.assertEqual("http://localhost:8080/auth/v1.0",
                         os.getenv("PIFPAF_SWIFT_AUTH_URL"))
        self.assertEqual(8080, a.port)
        self.assertEqual("8080", os.getenv("PIFPAF_SWIFT_PORT"))
        self.assertEqual("test:tester", os.getenv("PIFPAF_SWIFT_USERNAME"))
        self.assertEqual("testing", os.getenv("PIFPAF_SWIFT_PASSWORD"))
        self.assertEqual(
            "swift://test%3Atester:testing@localhost:8080/auth/v1.0",
            os.getenv("PIFPAF_SWIFT_URL"))
        self.assertEqual(
            "swift://test%3Atester:testing@localhost:8080/auth/v1.0",
            os.getenv("PIFPAF_URL"))

    @testtools.skipUnless(testtools.try_import('httpbin'),
                          "httpbin not found")
    def test_httpbin(self):
        port = 6666
        a = self.useFixture(httpbin.HttpBinDriver(port=port))
        self.assertEqual(port, a.port)
        r = requests.get("http://127.0.0.1:%d/ip" % port)
        self.assertEqual(r.status_code, 200)
        self.assertEqual(r.json()["origin"], "127.0.0.1")

    def _get_tmpdir_for_xattr(self):
        tmp_rootdir = os.getenv("TMPDIR_FOR_XATTR")
        # NOTE(sileht): Don't skip test if user have explicitly set a directory
        if not tmp_rootdir:
            try:
                d = drivers.Driver(tmp_rootdir=tmp_rootdir)
                self.useFixture(d)
                d._ensure_xattr_support()
            except RuntimeError as e:
                self.skipTest(str(e))
        return tmp_rootdir
