summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWayne Witzel III <wwitzel@redhat.com>2016-01-27 19:42:58 +0100
committerWayne Witzel III <wwitzel@redhat.com>2016-02-02 00:37:56 +0100
commit3d4580611eedec18fa9928732dea44f77e1d6d57 (patch)
treead470126309ff45baca11b9f37234a2f01f2577f
parentreorganzing tests folder (diff)
downloadawx-3d4580611eedec18fa9928732dea44f77e1d6d57.tar.xz
awx-3d4580611eedec18fa9928732dea44f77e1d6d57.zip
added pytest to requirements_dev
reworking test strucutre reworked pytest.ini, removed functional imports, updated req_dev remove unneeded __init__ files add testing checker to local_settings examples adding testing packages to system Python for docker
-rw-r--r--Makefile6
-rw-r--r--awx/main/models/credential.py3
-rw-r--r--awx/main/tests/__init__.py0
-rw-r--r--awx/main/tests/functional/__init__.py24
-rw-r--r--awx/main/tests/functional/commands/__init__.py13
-rw-r--r--awx/main/tests/functional/fact/__init__.py6
-rw-r--r--awx/main/tests/functional/jobs/__init__.py11
-rw-r--r--awx/main/tests/unit/utils/__init__.py0
-rw-r--r--awx/main/utils.py122
-rw-r--r--awx/settings/local_settings.py.docker_compose9
-rw-r--r--awx/settings/local_settings.py.example9
-rw-r--r--pytest.ini5
-rw-r--r--requirements/requirements_dev.txt4
-rw-r--r--tools/docker-compose/Dockerfile4
14 files changed, 35 insertions, 181 deletions
diff --git a/Makefile b/Makefile
index abb16932c6..3d406b106b 100644
--- a/Makefile
+++ b/Makefile
@@ -357,17 +357,17 @@ pylint: reports
@(set -o pipefail && $@ | reports/$@.report)
check: flake8 pep8 # pyflakes pylint
-
+
# Run all API unit tests.
test:
- $(PYTHON) manage.py test -v2 awx.main.tests
+ $(PYTHON) -m py.test awx/main/tests
test_unit:
$(PYTHON) -m py.test awx/main/tests/unit
# Run all API unit tests with coverage enabled.
test_coverage:
- coverage run manage.py test -v2 awx.main.tests
+ $(PYTHON) -m py.test --cov=awx awx/main/tests
# Output test coverage as HTML (into htmlcov directory).
coverage_html:
diff --git a/awx/main/models/credential.py b/awx/main/models/credential.py
index e0d75dc182..c72c67b715 100644
--- a/awx/main/models/credential.py
+++ b/awx/main/models/credential.py
@@ -1,6 +1,9 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.
+import base64
+import re
+
# Django
from django.db import models
from django.utils.translation import ugettext_lazy as _
diff --git a/awx/main/tests/__init__.py b/awx/main/tests/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/awx/main/tests/__init__.py
+++ /dev/null
diff --git a/awx/main/tests/functional/__init__.py b/awx/main/tests/functional/__init__.py
deleted file mode 100644
index 37a6f1e643..0000000000
--- a/awx/main/tests/functional/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2015 Ansible, Inc.
-# All Rights Reserved.
-import logging
-logging.disable(logging.CRITICAL)
-
-from .organizations import * # noqa
-from .users import * # noqa
-from .inventory import * # noqa
-from .projects import ProjectsTest, ProjectUpdatesTest # noqa
-from .commands import * # noqa
-from .scripts import * # noqa
-from .tasks import RunJobTest # noqa
-from .ad_hoc import * # noqa
-from .licenses import LicenseTests # noqa
-from .jobs import * # noqa
-from .activity_stream import * # noqa
-from .schedules import * # noqa
-from .redact import * # noqa
-from .views import * # noqa
-from .commands import * # noqa
-from .fact import * # noqa
-from .unified_jobs import * # noqa
-from .ha import * # noqa
-from .settings import * # noqa
diff --git a/awx/main/tests/functional/commands/__init__.py b/awx/main/tests/functional/commands/__init__.py
deleted file mode 100644
index 84212dd2fb..0000000000
--- a/awx/main/tests/functional/commands/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015 Ansible, Inc.
-# All Rights Reserved
-
-from __future__ import absolute_import
-
-from .run_fact_cache_receiver import * # noqa
-from .commands_monolithic import * # noqa
-from .cleanup_facts import * # noqa
-from .age_deleted import * # noqa
-from .remove_instance import * # noqa
-from .run_socketio_service import * # noqa
-from .update_password import * # noqa
-
diff --git a/awx/main/tests/functional/fact/__init__.py b/awx/main/tests/functional/fact/__init__.py
deleted file mode 100644
index 234499d6e9..0000000000
--- a/awx/main/tests/functional/fact/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# Copyright (c) 2015 Ansible, Inc.
-# All Rights Reserved
-
-from __future__ import absolute_import
-
-from .fact_api import * # noqa
diff --git a/awx/main/tests/functional/jobs/__init__.py b/awx/main/tests/functional/jobs/__init__.py
deleted file mode 100644
index 092826ccf0..0000000000
--- a/awx/main/tests/functional/jobs/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015 Ansible, Inc.
-# All Rights Reserved
-
-from __future__ import absolute_import
-
-from .jobs_monolithic import * # noqa
-from .job_launch import * # noqa
-from .job_relaunch import * # noqa
-from .survey_password import * # noqa
-from .start_cancel import * # noqa
-from .base import * # noqa
diff --git a/awx/main/tests/unit/utils/__init__.py b/awx/main/tests/unit/utils/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/awx/main/tests/unit/utils/__init__.py
+++ /dev/null
diff --git a/awx/main/utils.py b/awx/main/utils.py
index 96df62b379..5b9b7a1f46 100644
--- a/awx/main/utils.py
+++ b/awx/main/utils.py
@@ -523,125 +523,3 @@ def timedelta_total_seconds(timedelta):
timedelta.microseconds + 0.0 +
(timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6
-def validate_ssh_private_key(data):
- """Validate that the given SSH private key or certificate is,
- in fact, valid.
- """
- # Map the X in BEGIN X PRIVATE KEY to the key type (ssh-keygen -t).
- # Tower jobs using OPENSSH format private keys may still fail if the
- # system SSH implementation lacks support for this format.
- key_types = {
- 'RSA': 'rsa',
- 'DSA': 'dsa',
- 'EC': 'ecdsa',
- 'OPENSSH': 'ed25519',
- '': 'rsa1',
- }
- # Key properties to return if valid.
- key_data = {
- 'key_type': None, # Key type (from above mapping).
- 'key_seg': '', # Key segment (all text including begin/end).
- 'key_b64': '', # Key data as base64.
- 'key_bin': '', # Key data as binary.
- 'key_enc': None, # Boolean, whether key is encrypted.
- 'cert_seg': '', # Cert segment (all text including begin/end).
- 'cert_b64': '', # Cert data as base64.
- 'cert_bin': '', # Cert data as binary.
- }
- data = data.strip()
- validation_error = ValidationError('Invalid private key')
-
- # Sanity check: We may potentially receive a full PEM certificate,
- # and we want to accept these.
- cert_begin_re = r'(-{4,})\s*BEGIN\s+CERTIFICATE\s*(-{4,})'
- cert_end_re = r'(-{4,})\s*END\s+CERTIFICATE\s*(-{4,})'
- cert_begin_match = re.search(cert_begin_re, data)
- cert_end_match = re.search(cert_end_re, data)
- if cert_begin_match and not cert_end_match:
- raise validation_error
- elif not cert_begin_match and cert_end_match:
- raise validation_error
- elif cert_begin_match and cert_end_match:
- cert_dashes = set([cert_begin_match.groups()[0], cert_begin_match.groups()[1],
- cert_end_match.groups()[0], cert_end_match.groups()[1]])
- if len(cert_dashes) != 1:
- raise validation_error
- key_data['cert_seg'] = data[cert_begin_match.start():cert_end_match.end()]
-
- # Find the private key, and also ensure that it internally matches
- # itself.
- # Set up the valid private key header and footer.
- begin_re = r'(-{4,})\s*BEGIN\s+([A-Z0-9]+)?\s*PRIVATE\sKEY\s*(-{4,})'
- end_re = r'(-{4,})\s*END\s+([A-Z0-9]+)?\s*PRIVATE\sKEY\s*(-{4,})'
- begin_match = re.search(begin_re, data)
- end_match = re.search(end_re, data)
- if not begin_match or not end_match:
- raise validation_error
-
- # Ensure that everything, such as dash counts and key type, lines up,
- # and raise an error if it does not.
- dashes = set([begin_match.groups()[0], begin_match.groups()[2],
- end_match.groups()[0], end_match.groups()[2]])
- if len(dashes) != 1:
- raise validation_error
- if begin_match.groups()[1] != end_match.groups()[1]:
- raise validation_error
- key_type = begin_match.groups()[1] or ''
- try:
- key_data['key_type'] = key_types[key_type]
- except KeyError:
- raise ValidationError('Invalid private key: unsupported type %s' % key_type)
-
- # The private key data begins and ends with the private key.
- key_data['key_seg'] = data[begin_match.start():end_match.end()]
-
- # Establish that we are able to base64 decode the private key;
- # if we can't, then it's not a valid key.
- #
- # If we got a certificate, validate that also, in the same way.
- header_re = re.compile(r'^(.+?):\s*?(.+?)(\\??)$')
- for segment_name in ('cert', 'key'):
- segment_to_validate = key_data['%s_seg' % segment_name]
- # If we have nothing; skip this one.
- # We've already validated that we have a private key above,
- # so we don't need to do it again.
- if not segment_to_validate:
- continue
-
- # Ensure that this segment is valid base64 data.
- base64_data = ''
- line_continues = False
- lines = segment_to_validate.splitlines()
- for line in lines[1:-1]:
- line = line.strip()
- if not line:
- continue
- if line_continues:
- line_continues = line.endswith('\\')
- continue
- line_match = header_re.match(line)
- if line_match:
- line_continues = line.endswith('\\')
- continue
- base64_data += line
- try:
- decoded_data = base64.b64decode(base64_data)
- if not decoded_data:
- raise validation_error
- key_data['%s_b64' % segment_name] = base64_data
- key_data['%s_bin' % segment_name] = decoded_data
- except TypeError:
- raise validation_error
-
- # Determine if key is encrypted.
- if key_data['key_type'] == 'ed25519':
- # See https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L3218
- # Decoded key data starts with magic string (null-terminated), four byte
- # length field, followed by the ciphername -- if ciphername is anything
- # other than 'none' the key is encrypted.
- key_data['key_enc'] = not bool(key_data['key_bin'].startswith('openssh-key-v1\x00\x00\x00\x00\x04none'))
- else:
- key_data['key_enc'] = bool('ENCRYPTED' in key_data['key_seg'])
-
- return key_data
-
diff --git a/awx/settings/local_settings.py.docker_compose b/awx/settings/local_settings.py.docker_compose
index 905e26857f..794d3ce073 100644
--- a/awx/settings/local_settings.py.docker_compose
+++ b/awx/settings/local_settings.py.docker_compose
@@ -30,10 +30,17 @@ DATABASES = {
}
}
+def is_testing(argv):
+ if "py.test" in argv[0] or "py/test.py" in argv[0]:
+ return True
+ elif argv[1] == "test":
+ return True
+ return False
+
# Use SQLite for unit tests instead of PostgreSQL. If the lines below are
# commented out, Django will create the test_awx-dev database in PostgreSQL to
# run unit tests.
-if len(sys.argv) >= 2 and sys.argv[1] == 'test':
+if len(sys.argv) >= 2 and is_testing(sys.argv):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
diff --git a/awx/settings/local_settings.py.example b/awx/settings/local_settings.py.example
index 2fb0c745fc..52648798fe 100644
--- a/awx/settings/local_settings.py.example
+++ b/awx/settings/local_settings.py.example
@@ -30,10 +30,17 @@ DATABASES = {
}
}
+def is_testing(argv):
+ if "py.test" in argv[0] or "py/test.py" in argv[0]:
+ return True
+ elif argv[1] == "test":
+ return True
+ return False
+
# Use SQLite for unit tests instead of PostgreSQL. If the lines below are
# commented out, Django will create the test_awx-dev database in PostgreSQL to
# run unit tests.
-if len(sys.argv) >= 2 and sys.argv[1] == 'test':
+if len(sys.argv) >= 2 and is_testing(sys.argv):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000000..751ebbb85f
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,5 @@
+[pytest]
+DJANGO_SETTINGS_MODULE = awx.settings.development
+python_paths = awx/lib/site-packages
+python_files = *.py
+addopts = --create-db
diff --git a/requirements/requirements_dev.txt b/requirements/requirements_dev.txt
index a2ff6cf11a..bd7d5f54c8 100644
--- a/requirements/requirements_dev.txt
+++ b/requirements/requirements_dev.txt
@@ -4,3 +4,7 @@ django-debug-toolbar==1.3.2
unittest2
pep8
flake8
+pytest
+pytest-cov
+pytest-django
+pytest-pythonpath
diff --git a/tools/docker-compose/Dockerfile b/tools/docker-compose/Dockerfile
index 32be28ca01..e2e57fd4a1 100644
--- a/tools/docker-compose/Dockerfile
+++ b/tools/docker-compose/Dockerfile
@@ -12,6 +12,10 @@ RUN echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-or
RUN apt-get update
RUN apt-get install -y openssh-server ansible mg vim tmux git mercurial subversion python-dev python-psycopg2 make postgresql-client libpq-dev nodejs python-psutil libxml2-dev libxslt-dev lib32z1-dev libsasl2-dev libldap2-dev libffi-dev libzmq-dev proot python-pip libxmlsec1-dev swig redis-server && rm -rf /var/lib/apt/lists/*
RUN pip install flake8
+RUN pip install pytest
+RUN pip install pytest-pythonpath
+RUN pip install pytest-django
+RUN pip install pytest-cov
RUN /usr/bin/ssh-keygen -q -t rsa -N "" -f /root/.ssh/id_rsa
RUN mkdir -p /etc/tower
RUN mkdir -p /data/db