2016-03-03 19:46:47 +03:00
|
|
|
import copy
|
2016-03-09 23:07:13 +03:00
|
|
|
import datetime
|
2015-08-10 01:02:37 +03:00
|
|
|
import json
|
2013-03-12 00:01:17 +04:00
|
|
|
import os
|
2014-07-03 17:56:45 +04:00
|
|
|
|
2015-02-14 12:27:13 +03:00
|
|
|
import kombu
|
2013-03-19 23:03:26 +04:00
|
|
|
import pytest
|
2015-08-10 01:02:37 +03:00
|
|
|
import responses
|
2017-06-09 20:28:30 +03:00
|
|
|
from _pytest.monkeypatch import MonkeyPatch
|
2015-09-15 19:13:08 +03:00
|
|
|
from django.conf import settings
|
2015-07-15 19:16:59 +03:00
|
|
|
from requests import Request
|
2015-09-30 14:01:38 +03:00
|
|
|
from requests_hawk import HawkAuth
|
2018-04-12 20:06:53 +03:00
|
|
|
from rest_framework.test import APIClient
|
2014-07-03 17:56:45 +04:00
|
|
|
|
2018-06-05 15:57:16 +03:00
|
|
|
from treeherder.autoclassify.autoclassify import mark_best_classification
|
2017-03-20 15:40:37 +03:00
|
|
|
from treeherder.client.thclient import TreeherderClient
|
2017-01-06 01:55:33 +03:00
|
|
|
from treeherder.etl.jobs import store_job_data
|
2017-08-04 19:38:57 +03:00
|
|
|
from treeherder.etl.push import store_push_data
|
2018-01-05 16:50:12 +03:00
|
|
|
from treeherder.model.models import (Commit,
|
|
|
|
JobNote,
|
2017-02-28 17:26:50 +03:00
|
|
|
Push,
|
|
|
|
TextLogErrorMetadata)
|
2014-07-03 17:56:45 +04:00
|
|
|
|
2013-03-12 00:01:17 +04:00
|
|
|
|
2013-04-26 22:18:18 +04:00
|
|
|
def pytest_addoption(parser):
|
|
|
|
parser.addoption(
|
|
|
|
"--runslow",
|
|
|
|
action="store_true",
|
|
|
|
help="run slow tests",
|
|
|
|
)
|
|
|
|
|
2013-03-20 17:59:48 +04:00
|
|
|
|
2013-03-12 00:01:17 +04:00
|
|
|
def pytest_runtest_setup(item):
|
|
|
|
"""
|
2013-04-16 22:00:34 +04:00
|
|
|
Per-test setup.
|
2013-05-01 14:50:55 +04:00
|
|
|
- Add an option to run those tests marked as 'slow'
|
2017-08-25 17:31:02 +03:00
|
|
|
- Clear the django cache between runs
|
2013-04-16 22:00:34 +04:00
|
|
|
"""
|
2013-03-12 00:01:17 +04:00
|
|
|
|
2013-05-01 14:50:55 +04:00
|
|
|
if 'slow' in item.keywords and not item.config.getoption("--runslow"):
|
|
|
|
pytest.skip("need --runslow option to run")
|
2013-03-12 00:01:17 +04:00
|
|
|
|
2013-03-28 04:40:42 +04:00
|
|
|
from django.core.cache import cache
|
2017-08-25 17:31:02 +03:00
|
|
|
cache.clear()
|
2013-04-19 03:23:58 +04:00
|
|
|
|
2013-05-01 14:50:55 +04:00
|
|
|
|
2017-06-09 20:28:30 +03:00
|
|
|
@pytest.fixture(scope="session", autouse=True)
|
|
|
|
def block_unmocked_requests():
|
|
|
|
"""
|
|
|
|
Prevents requests from being made unless they are mocked.
|
|
|
|
|
|
|
|
Helps avoid inadvertent dependencies on external resources during the test run.
|
|
|
|
"""
|
|
|
|
def mocked_send(*args, **kwargs):
|
|
|
|
raise RuntimeError('Tests must mock all HTTP requests!')
|
|
|
|
|
|
|
|
# The standard monkeypatch fixture cannot be used with session scope:
|
|
|
|
# https://github.com/pytest-dev/pytest/issues/363
|
|
|
|
monkeypatch = MonkeyPatch()
|
|
|
|
# Monkeypatching here since any higher level would break responses:
|
|
|
|
# https://github.com/getsentry/responses/blob/0.5.1/responses.py#L295
|
|
|
|
monkeypatch.setattr('requests.adapters.HTTPAdapter.send', mocked_send)
|
|
|
|
yield monkeypatch
|
|
|
|
monkeypatch.undo()
|
|
|
|
|
|
|
|
|
2016-06-29 13:25:38 +03:00
|
|
|
@pytest.fixture
|
|
|
|
def elasticsearch(request):
|
2018-04-19 14:46:50 +03:00
|
|
|
from treeherder.services.elasticsearch import reinit_index, refresh_index
|
2016-06-29 13:25:38 +03:00
|
|
|
|
2018-04-19 14:46:50 +03:00
|
|
|
if not settings.ELASTICSEARCH_URL:
|
|
|
|
return
|
|
|
|
|
|
|
|
reinit_index()
|
|
|
|
refresh_index()
|
2016-06-29 13:25:38 +03:00
|
|
|
|
|
|
|
|
2017-01-21 00:08:04 +03:00
|
|
|
@pytest.fixture
|
2013-04-19 03:23:58 +04:00
|
|
|
def sample_data():
|
|
|
|
"""Returns a SampleData() object"""
|
2016-01-18 19:13:42 +03:00
|
|
|
from .sampledata import SampleData
|
2013-04-19 03:23:58 +04:00
|
|
|
return SampleData()
|
2013-09-04 18:38:59 +04:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='session')
|
|
|
|
def test_base_dir():
|
|
|
|
return os.path.dirname(__file__)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2017-08-04 19:38:57 +03:00
|
|
|
def sample_push(sample_data):
|
|
|
|
return copy.deepcopy(sample_data.push_data)
|
2013-09-16 17:58:03 +04:00
|
|
|
|
|
|
|
|
2018-04-06 18:49:17 +03:00
|
|
|
@pytest.fixture(name='create_push')
|
|
|
|
def fixture_create_push():
|
|
|
|
"""Return a function to create a push"""
|
|
|
|
def create(repository,
|
|
|
|
revision='4c45a777949168d16c03a4cba167678b7ab65f76',
|
|
|
|
author='foo@bar.com'):
|
|
|
|
return Push.objects.create(
|
|
|
|
repository=repository,
|
|
|
|
revision=revision,
|
|
|
|
author=author,
|
|
|
|
time=datetime.datetime.now())
|
|
|
|
return create
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(name='create_commit')
|
|
|
|
def fixture_create_commit():
|
|
|
|
"""Return a function to create a commit"""
|
|
|
|
def create(push, comments='Bug 12345 - This is a message'):
|
|
|
|
return Commit.objects.create(
|
|
|
|
push=push,
|
|
|
|
revision=push.revision,
|
|
|
|
author=push.author,
|
|
|
|
comments=comments)
|
|
|
|
return create
|
|
|
|
|
|
|
|
|
2013-09-16 17:58:03 +04:00
|
|
|
@pytest.fixture
|
2016-03-15 03:22:48 +03:00
|
|
|
def test_repository(transactional_db):
|
2014-08-27 01:05:17 +04:00
|
|
|
from treeherder.model.models import Repository, RepositoryGroup
|
|
|
|
|
|
|
|
RepositoryGroup.objects.create(
|
2015-02-15 17:52:31 +03:00
|
|
|
name="development",
|
|
|
|
description=""
|
2014-08-27 01:05:17 +04:00
|
|
|
)
|
2013-09-16 17:58:03 +04:00
|
|
|
|
2016-03-15 03:22:48 +03:00
|
|
|
r = Repository.objects.create(
|
2015-02-15 17:52:31 +03:00
|
|
|
dvcs_type="hg",
|
2017-01-06 22:32:06 +03:00
|
|
|
name=settings.TREEHERDER_TEST_REPOSITORY_NAME,
|
2015-02-15 17:52:31 +03:00
|
|
|
url="https://hg.mozilla.org/mozilla-central",
|
|
|
|
active_status="active",
|
|
|
|
codebase="gecko",
|
|
|
|
repository_group_id=1,
|
2016-04-12 20:01:03 +03:00
|
|
|
description="",
|
2017-03-10 23:35:25 +03:00
|
|
|
performance_alerts_enabled=True,
|
|
|
|
expire_performance_data=False
|
2013-09-16 17:58:03 +04:00
|
|
|
)
|
2016-03-15 03:22:48 +03:00
|
|
|
return r
|
2013-09-16 17:58:03 +04:00
|
|
|
|
|
|
|
|
2018-05-23 18:13:51 +03:00
|
|
|
@pytest.fixture
|
|
|
|
def test_issue_tracker(transactional_db):
|
|
|
|
from treeherder.perf.models import IssueTracker
|
|
|
|
|
|
|
|
return IssueTracker.objects.create(
|
|
|
|
name="Bugzilla",
|
|
|
|
task_base_url="https://bugzilla.mozilla.org/show_bug.cgi?id="
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2016-12-29 22:34:04 +03:00
|
|
|
@pytest.fixture
|
|
|
|
def test_repository_2(test_repository):
|
|
|
|
from treeherder.model.models import Repository
|
|
|
|
|
|
|
|
return Repository.objects.create(
|
|
|
|
repository_group=test_repository.repository_group,
|
|
|
|
name=test_repository.name + '_2',
|
|
|
|
dvcs_type=test_repository.dvcs_type,
|
|
|
|
url=test_repository.url + '_2',
|
|
|
|
codebase=test_repository.codebase)
|
|
|
|
|
|
|
|
|
2018-01-05 16:50:12 +03:00
|
|
|
@pytest.fixture
|
2018-04-06 18:49:17 +03:00
|
|
|
def test_push(create_push, test_repository):
|
|
|
|
return create_push(test_repository)
|
2018-01-05 16:50:12 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2018-04-06 18:49:17 +03:00
|
|
|
def test_commit(create_commit, test_push):
|
|
|
|
return create_commit(test_push)
|
2018-01-05 16:50:12 +03:00
|
|
|
|
|
|
|
|
2018-04-06 20:26:01 +03:00
|
|
|
@pytest.fixture(name='create_jobs')
|
|
|
|
def fixture_create_jobs(test_repository, failure_classifications):
|
|
|
|
"""Return a function to create jobs"""
|
2016-09-23 21:51:57 +03:00
|
|
|
from treeherder.model.models import Job
|
|
|
|
|
2018-04-06 20:26:01 +03:00
|
|
|
def create(jobs):
|
|
|
|
store_job_data(test_repository, jobs)
|
|
|
|
return [Job.objects.get(id=i) for i in range(1, len(jobs) + 1)]
|
|
|
|
return create
|
2016-09-23 21:51:57 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2018-04-06 20:26:01 +03:00
|
|
|
def test_job(eleven_job_blobs, create_jobs):
|
|
|
|
return create_jobs(eleven_job_blobs[0:1])[0]
|
2016-09-23 21:51:57 +03:00
|
|
|
|
|
|
|
|
2018-04-06 20:26:01 +03:00
|
|
|
@pytest.fixture
|
|
|
|
def test_job_2(eleven_job_blobs, create_jobs):
|
|
|
|
return create_jobs(eleven_job_blobs[0:2])[1]
|
2016-09-23 21:51:57 +03:00
|
|
|
|
|
|
|
|
2013-09-16 17:58:03 +04:00
|
|
|
@pytest.fixture
|
|
|
|
def mock_log_parser(monkeypatch):
|
|
|
|
from celery import task
|
|
|
|
from treeherder.log_parser import tasks
|
|
|
|
|
|
|
|
@task
|
|
|
|
def task_mock(*args, **kwargs):
|
|
|
|
pass
|
|
|
|
|
2017-06-07 12:41:07 +03:00
|
|
|
monkeypatch.setattr(tasks, 'parse_logs', task_mock)
|
2013-09-16 17:58:03 +04:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2017-08-04 19:38:57 +03:00
|
|
|
def push_stored(test_repository, sample_push):
|
|
|
|
store_push_data(test_repository, sample_push)
|
2013-11-05 21:09:26 +04:00
|
|
|
|
2017-08-04 19:38:57 +03:00
|
|
|
return sample_push
|
2013-09-16 17:58:03 +04:00
|
|
|
|
|
|
|
|
2014-03-13 18:17:34 +04:00
|
|
|
@pytest.fixture
|
|
|
|
def mock_message_broker(monkeypatch):
|
2017-02-01 19:28:55 +03:00
|
|
|
monkeypatch.setattr(settings, 'BROKER_URL', 'memory://')
|
2014-06-03 20:46:20 +04:00
|
|
|
|
Bug 1059814 - Non-whitespace pep8 fixes using autopep8 aggressive mode
Generated using:
autopep8 --in-place --recursive --aggressive --aggressive
--max-line-length 999 --exclude='.git,__pycache__,.vagrant,build,vendor,
0001_initial.py,models.py,test_note_api.py,test_bug_job_map_api.py' .
autopep8's aggressive mode, unlike standard mode, makes non-whitespace
changes. It also uses lib2to3 to correct deprecated code (W690), some of
which aren't pep8 failures. Some of these changes are more dubious, but
rather than disable W690 completely, I've just excluded the files where
the unwanted changes would have been made, so we can benefit from the
rest.
2015-02-26 18:16:02 +03:00
|
|
|
|
2015-02-14 12:27:13 +03:00
|
|
|
@pytest.fixture
|
2017-08-04 19:38:57 +03:00
|
|
|
def push_with_three_jobs(sample_data, sample_push, test_repository):
|
2015-02-14 12:27:13 +03:00
|
|
|
"""
|
2017-08-04 19:38:57 +03:00
|
|
|
Stores a number of jobs in the same push.
|
2015-02-14 12:27:13 +03:00
|
|
|
"""
|
|
|
|
num_jobs = 3
|
2017-08-04 19:38:57 +03:00
|
|
|
push = sample_push[0]
|
2016-11-09 21:51:00 +03:00
|
|
|
jobs = copy.deepcopy(sample_data.job_data[0:num_jobs])
|
2015-02-14 12:27:13 +03:00
|
|
|
|
2017-08-04 19:38:57 +03:00
|
|
|
# Only store data for the first push....
|
|
|
|
store_push_data(test_repository, [push])
|
2015-02-14 12:27:13 +03:00
|
|
|
|
|
|
|
blobs = []
|
2018-04-07 00:43:26 +03:00
|
|
|
for blob in jobs:
|
2017-08-04 19:38:57 +03:00
|
|
|
# Modify job structure to sync with the push sample data
|
2015-02-14 12:27:13 +03:00
|
|
|
if 'sources' in blob:
|
|
|
|
del blob['sources']
|
|
|
|
|
|
|
|
# Skip log references since they do not work correctly in pending state.
|
|
|
|
if 'log_references' in blob['job']:
|
|
|
|
del blob['job']['log_references']
|
|
|
|
|
2017-08-04 19:38:57 +03:00
|
|
|
blob['revision'] = push['revision']
|
2015-02-14 12:27:13 +03:00
|
|
|
blob['job']['state'] = 'pending'
|
|
|
|
blobs.append(blob)
|
|
|
|
|
|
|
|
# Store and process the jobs so they are present in the tables.
|
2017-01-06 01:55:33 +03:00
|
|
|
store_job_data(test_repository, blobs)
|
2016-11-09 21:51:00 +03:00
|
|
|
return Push.objects.get(repository=test_repository,
|
2017-08-04 19:38:57 +03:00
|
|
|
revision=push['revision'])
|
2015-02-14 12:27:13 +03:00
|
|
|
|
|
|
|
|
2014-06-03 20:46:20 +04:00
|
|
|
@pytest.fixture
|
2017-08-04 19:38:57 +03:00
|
|
|
def eleven_job_blobs(sample_data, sample_push, test_repository, mock_log_parser):
|
|
|
|
store_push_data(test_repository, sample_push)
|
2014-06-03 20:46:20 +04:00
|
|
|
|
|
|
|
num_jobs = 11
|
|
|
|
jobs = sample_data.job_data[0:num_jobs]
|
|
|
|
|
2017-08-04 19:38:57 +03:00
|
|
|
max_index = len(sample_push) - 1
|
|
|
|
push_index = 0
|
2014-06-03 20:46:20 +04:00
|
|
|
|
|
|
|
blobs = []
|
2018-04-07 00:43:26 +03:00
|
|
|
for blob in jobs:
|
2014-06-03 20:46:20 +04:00
|
|
|
|
2017-08-04 19:38:57 +03:00
|
|
|
if push_index > max_index:
|
|
|
|
push_index = 0
|
2014-06-03 20:46:20 +04:00
|
|
|
|
2017-08-04 19:38:57 +03:00
|
|
|
# Modify job structure to sync with the push sample data
|
2014-06-03 20:46:20 +04:00
|
|
|
if 'sources' in blob:
|
|
|
|
del blob['sources']
|
|
|
|
|
2017-08-04 19:38:57 +03:00
|
|
|
blob['revision'] = sample_push[push_index]['revision']
|
2014-06-03 20:46:20 +04:00
|
|
|
|
|
|
|
blobs.append(blob)
|
|
|
|
|
2017-08-04 19:38:57 +03:00
|
|
|
push_index += 1
|
2016-07-06 00:15:52 +03:00
|
|
|
return blobs
|
2014-06-03 20:46:20 +04:00
|
|
|
|
2016-07-06 00:15:52 +03:00
|
|
|
|
|
|
|
@pytest.fixture
|
2017-01-06 01:55:33 +03:00
|
|
|
def eleven_jobs_stored(test_repository, failure_classifications, eleven_job_blobs):
|
2016-07-06 00:15:52 +03:00
|
|
|
"""stores a list of 11 job samples"""
|
2017-01-06 01:55:33 +03:00
|
|
|
store_job_data(test_repository, eleven_job_blobs)
|
2014-06-03 20:46:20 +04:00
|
|
|
|
|
|
|
|
2017-01-06 20:37:27 +03:00
|
|
|
@pytest.fixture
|
|
|
|
def taskcluster_jobs_stored(test_repository, sample_data):
|
|
|
|
"""stores a list of TaskCluster job samples"""
|
|
|
|
store_job_data(test_repository, sample_data.transformed_pulse_jobs)
|
|
|
|
|
|
|
|
|
2016-12-02 18:49:06 +03:00
|
|
|
@pytest.fixture
|
2016-12-23 20:31:45 +03:00
|
|
|
def test_job_with_notes(test_job, test_user):
|
|
|
|
"""test job with job notes."""
|
|
|
|
|
2016-10-03 19:56:51 +03:00
|
|
|
for failure_classification_id in [2, 3]:
|
2016-12-23 20:31:45 +03:00
|
|
|
JobNote.objects.create(job=test_job,
|
2016-10-03 19:56:51 +03:00
|
|
|
failure_classification_id=failure_classification_id,
|
2016-12-23 20:31:45 +03:00
|
|
|
user=test_user,
|
|
|
|
text="you look like a man-o-lantern")
|
|
|
|
|
|
|
|
test_job.refresh_from_db()
|
|
|
|
|
|
|
|
return test_job
|
2016-12-02 18:49:06 +03:00
|
|
|
|
|
|
|
|
2014-10-14 19:25:37 +04:00
|
|
|
@pytest.fixture
|
2018-04-12 20:06:53 +03:00
|
|
|
def mock_post_json(monkeypatch, client_credentials, client):
|
2016-06-21 14:07:44 +03:00
|
|
|
def _post_json(th_client, project, endpoint, data):
|
2016-06-13 16:40:40 +03:00
|
|
|
auth = th_client.session.auth
|
2015-09-30 14:01:38 +03:00
|
|
|
if not auth:
|
2015-11-13 04:11:35 +03:00
|
|
|
auth = HawkAuth(id=client_credentials.client_id,
|
|
|
|
key=str(client_credentials.secret))
|
2016-06-21 15:13:54 +03:00
|
|
|
url = th_client._get_endpoint_url(endpoint, project=project)
|
|
|
|
req = Request('POST', url, json=data, auth=auth)
|
2015-07-15 19:16:59 +03:00
|
|
|
prepped_request = req.prepare()
|
2018-04-12 20:06:53 +03:00
|
|
|
response = client.post(
|
2015-07-15 19:16:59 +03:00
|
|
|
prepped_request.url,
|
2018-04-12 20:06:53 +03:00
|
|
|
data=json.dumps(data),
|
2015-09-30 14:01:38 +03:00
|
|
|
content_type='application/json',
|
2018-04-12 20:06:53 +03:00
|
|
|
HTTP_AUTHORIZATION=str(prepped_request.headers['Authorization'])
|
2014-07-03 17:56:45 +04:00
|
|
|
)
|
2018-04-12 20:06:53 +03:00
|
|
|
# Replacement for the `raise_for_status()` in the original `_post_json()`
|
|
|
|
assert response.status_code == 200
|
|
|
|
return response
|
2014-07-03 17:56:45 +04:00
|
|
|
|
2015-07-15 19:16:59 +03:00
|
|
|
monkeypatch.setattr(TreeherderClient, '_post_json', _post_json)
|
2014-07-16 20:39:31 +04:00
|
|
|
|
2014-07-16 20:56:13 +04:00
|
|
|
|
2014-09-26 20:08:28 +04:00
|
|
|
@pytest.fixture
|
|
|
|
def activate_responses(request):
|
|
|
|
|
|
|
|
responses.start()
|
|
|
|
|
|
|
|
def fin():
|
2014-10-08 21:54:36 +04:00
|
|
|
responses.reset()
|
2014-09-26 20:08:28 +04:00
|
|
|
responses.stop()
|
|
|
|
|
|
|
|
request.addfinalizer(fin)
|
2015-02-14 12:27:13 +03:00
|
|
|
|
Bug 1059814 - Non-whitespace pep8 fixes using autopep8 aggressive mode
Generated using:
autopep8 --in-place --recursive --aggressive --aggressive
--max-line-length 999 --exclude='.git,__pycache__,.vagrant,build,vendor,
0001_initial.py,models.py,test_note_api.py,test_bug_job_map_api.py' .
autopep8's aggressive mode, unlike standard mode, makes non-whitespace
changes. It also uses lib2to3 to correct deprecated code (W690), some of
which aren't pep8 failures. Some of these changes are more dubious, but
rather than disable W690 completely, I've just excluded the files where
the unwanted changes would have been made, so we can benefit from the
rest.
2015-02-26 18:16:02 +03:00
|
|
|
|
2015-02-14 12:27:13 +03:00
|
|
|
def pulse_consumer(exchange, request):
|
|
|
|
exchange_name = 'exchange/{}/v1/{}'.format(
|
|
|
|
settings.PULSE_EXCHANGE_NAMESPACE,
|
|
|
|
exchange
|
|
|
|
)
|
|
|
|
|
2018-08-01 18:33:02 +03:00
|
|
|
connection = kombu.Connection(settings.PULSE_URL)
|
2015-02-14 12:27:13 +03:00
|
|
|
|
|
|
|
exchange = kombu.Exchange(
|
2018-04-06 19:35:14 +03:00
|
|
|
name=exchange_name,
|
|
|
|
type='topic'
|
|
|
|
)
|
2015-02-14 12:27:13 +03:00
|
|
|
|
|
|
|
queue = kombu.Queue(
|
2018-04-06 19:35:14 +03:00
|
|
|
no_ack=True,
|
|
|
|
exchange=exchange, # Exchange name
|
|
|
|
routing_key='#', # Bind to all messages
|
|
|
|
auto_delete=True, # Delete after each test
|
|
|
|
exclusive=False) # Disallow multiple consumers
|
2015-02-14 12:27:13 +03:00
|
|
|
|
|
|
|
simpleQueue = connection.SimpleQueue(
|
2018-04-06 19:35:14 +03:00
|
|
|
name=queue,
|
|
|
|
channel=connection,
|
|
|
|
no_ack=True)
|
2015-02-14 12:27:13 +03:00
|
|
|
|
|
|
|
def fin():
|
|
|
|
connection.release()
|
|
|
|
|
|
|
|
request.addfinalizer(fin)
|
|
|
|
return simpleQueue
|
|
|
|
|
Bug 1059814 - Non-whitespace pep8 fixes using autopep8 aggressive mode
Generated using:
autopep8 --in-place --recursive --aggressive --aggressive
--max-line-length 999 --exclude='.git,__pycache__,.vagrant,build,vendor,
0001_initial.py,models.py,test_note_api.py,test_bug_job_map_api.py' .
autopep8's aggressive mode, unlike standard mode, makes non-whitespace
changes. It also uses lib2to3 to correct deprecated code (W690), some of
which aren't pep8 failures. Some of these changes are more dubious, but
rather than disable W690 completely, I've just excluded the files where
the unwanted changes would have been made, so we can benefit from the
rest.
2015-02-26 18:16:02 +03:00
|
|
|
|
2015-02-14 12:27:13 +03:00
|
|
|
@pytest.fixture
|
|
|
|
def pulse_action_consumer(request):
|
|
|
|
return pulse_consumer('job-actions', request)
|
2015-05-22 00:29:05 +03:00
|
|
|
|
|
|
|
|
2015-08-17 20:01:39 +03:00
|
|
|
@pytest.fixture
|
2016-09-23 21:51:57 +03:00
|
|
|
def failure_lines(test_job, elasticsearch):
|
2015-08-17 20:01:39 +03:00
|
|
|
from tests.autoclassify.utils import test_line, create_failure_lines
|
|
|
|
|
2016-09-23 21:51:57 +03:00
|
|
|
return create_failure_lines(test_job,
|
2015-08-17 20:01:39 +03:00
|
|
|
[(test_line, {}),
|
|
|
|
(test_line, {"subtest": "subtest2"})])
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2016-11-24 20:56:50 +03:00
|
|
|
def failure_classifications(transactional_db):
|
2016-01-07 19:30:43 +03:00
|
|
|
from treeherder.model.models import FailureClassification
|
|
|
|
for name in ["not classified", "fixed by commit", "expected fail",
|
|
|
|
"intermittent", "infra", "intermittent needs filing",
|
|
|
|
"autoclassified intermittent"]:
|
|
|
|
FailureClassification(name=name).save()
|
|
|
|
|
|
|
|
|
2017-02-28 17:26:50 +03:00
|
|
|
@pytest.fixture
|
|
|
|
def text_log_errors_failure_lines(test_job, failure_lines):
|
|
|
|
from tests.autoclassify.utils import test_line, create_text_log_errors
|
|
|
|
|
|
|
|
lines = [(test_line, {}),
|
|
|
|
(test_line, {"subtest": "subtest2"})]
|
|
|
|
|
|
|
|
text_log_errors = create_text_log_errors(test_job, lines)
|
|
|
|
|
|
|
|
for error_line, failure_line in zip(text_log_errors, failure_lines):
|
|
|
|
TextLogErrorMetadata.objects.create(text_log_error=error_line,
|
|
|
|
failure_line=failure_line)
|
|
|
|
|
|
|
|
return text_log_errors, failure_lines
|
|
|
|
|
|
|
|
|
2016-01-07 19:30:43 +03:00
|
|
|
@pytest.fixture
|
2016-04-29 16:53:50 +03:00
|
|
|
def test_matcher(request):
|
2018-05-18 16:14:21 +03:00
|
|
|
return "TreeherderUnitTestDetector"
|
2016-04-29 16:53:50 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2017-02-28 17:26:50 +03:00
|
|
|
def classified_failures(test_job, text_log_errors_failure_lines, test_matcher,
|
2016-09-23 21:51:57 +03:00
|
|
|
failure_classifications):
|
2016-05-03 17:21:20 +03:00
|
|
|
from treeherder.model.models import ClassifiedFailure
|
2018-04-19 14:46:50 +03:00
|
|
|
from treeherder.services.elasticsearch import refresh_index
|
2016-05-03 18:02:02 +03:00
|
|
|
|
2017-02-28 17:26:50 +03:00
|
|
|
_, failure_lines = text_log_errors_failure_lines
|
|
|
|
|
2015-08-17 20:01:39 +03:00
|
|
|
classified_failures = []
|
|
|
|
|
|
|
|
for failure_line in failure_lines:
|
2016-09-23 21:51:57 +03:00
|
|
|
if failure_line.job_guid == test_job.guid:
|
2018-06-05 15:57:16 +03:00
|
|
|
classified_failure = ClassifiedFailure.objects.create()
|
2018-06-01 14:19:27 +03:00
|
|
|
|
2018-06-05 18:39:21 +03:00
|
|
|
failure_line.error.create_match(test_matcher, classified_failure)
|
2018-06-05 15:57:16 +03:00
|
|
|
mark_best_classification(failure_line.error, classified_failure)
|
2018-06-01 14:19:27 +03:00
|
|
|
|
2015-08-17 20:01:39 +03:00
|
|
|
classified_failures.append(classified_failure)
|
|
|
|
|
2018-04-19 14:46:50 +03:00
|
|
|
if settings.ELASTICSEARCH_URL:
|
|
|
|
refresh_index()
|
|
|
|
|
2015-08-17 20:01:39 +03:00
|
|
|
return classified_failures
|
|
|
|
|
|
|
|
|
2015-09-30 14:01:38 +03:00
|
|
|
@pytest.fixture
|
2016-05-02 21:21:45 +03:00
|
|
|
def test_user(request, transactional_db):
|
|
|
|
# a user *without* sheriff/staff permissions
|
2015-09-30 14:01:38 +03:00
|
|
|
from django.contrib.auth.models import User
|
2016-05-02 21:21:45 +03:00
|
|
|
user = User.objects.create(username="testuser1",
|
|
|
|
email='user@foo.com',
|
|
|
|
is_staff=False)
|
2015-09-30 14:01:38 +03:00
|
|
|
|
|
|
|
def fin():
|
|
|
|
user.delete()
|
|
|
|
request.addfinalizer(fin)
|
|
|
|
|
|
|
|
return user
|
|
|
|
|
|
|
|
|
2017-08-18 23:22:56 +03:00
|
|
|
@pytest.fixture
|
|
|
|
def test_ldap_user(request, transactional_db):
|
|
|
|
# a user *without* sheriff/staff permissions
|
|
|
|
from django.contrib.auth.models import User
|
|
|
|
user = User.objects.create(username="mozilla-ldap/user@foo.com",
|
|
|
|
email='user@foo.com',
|
|
|
|
is_staff=False)
|
|
|
|
|
|
|
|
def fin():
|
|
|
|
user.delete()
|
|
|
|
request.addfinalizer(fin)
|
|
|
|
|
|
|
|
return user
|
|
|
|
|
|
|
|
|
2015-09-30 14:01:38 +03:00
|
|
|
@pytest.fixture
|
2016-05-02 21:21:45 +03:00
|
|
|
def test_sheriff(request, transactional_db):
|
|
|
|
# a user *with* sheriff/staff permissions
|
|
|
|
from django.contrib.auth.models import User
|
|
|
|
|
|
|
|
user = User.objects.create(username="testsheriff1",
|
|
|
|
email='sheriff@foo.com',
|
|
|
|
is_staff=True)
|
|
|
|
|
|
|
|
def fin():
|
|
|
|
user.delete()
|
|
|
|
request.addfinalizer(fin)
|
|
|
|
|
|
|
|
return user
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2016-07-06 17:26:58 +03:00
|
|
|
def client_credentials(request, transactional_db):
|
2015-09-30 14:01:38 +03:00
|
|
|
from treeherder.credentials.models import Credentials
|
|
|
|
|
2016-07-06 17:26:58 +03:00
|
|
|
client_credentials = Credentials.objects.create(
|
|
|
|
client_id='test_client',
|
|
|
|
authorized=True
|
2015-09-30 14:01:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
def fin():
|
|
|
|
client_credentials.delete()
|
|
|
|
request.addfinalizer(fin)
|
|
|
|
|
|
|
|
return client_credentials
|
2015-12-04 00:59:21 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2016-06-09 19:50:54 +03:00
|
|
|
def test_perf_framework(transactional_db):
|
2016-06-01 02:54:49 +03:00
|
|
|
from treeherder.perf.models import PerformanceFramework
|
|
|
|
return PerformanceFramework.objects.create(
|
2016-07-04 18:08:07 +03:00
|
|
|
name='test_talos', enabled=True)
|
2016-06-01 02:54:49 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def test_perf_signature(test_repository, test_perf_framework):
|
2015-12-04 00:59:21 +03:00
|
|
|
from treeherder.model.models import (MachinePlatform,
|
|
|
|
Option,
|
|
|
|
OptionCollection)
|
2016-06-01 02:54:49 +03:00
|
|
|
from treeherder.perf.models import PerformanceSignature
|
2015-12-04 00:59:21 +03:00
|
|
|
|
|
|
|
option = Option.objects.create(name='opt')
|
|
|
|
option_collection = OptionCollection.objects.create(
|
|
|
|
option_collection_hash='my_option_hash',
|
|
|
|
option=option)
|
|
|
|
platform = MachinePlatform.objects.create(
|
|
|
|
os_name='win',
|
|
|
|
platform='win7',
|
2016-08-26 20:45:55 +03:00
|
|
|
architecture='x86')
|
2015-12-04 00:59:21 +03:00
|
|
|
|
|
|
|
signature = PerformanceSignature.objects.create(
|
|
|
|
repository=test_repository,
|
|
|
|
signature_hash=(40*'t'),
|
2016-06-01 02:54:49 +03:00
|
|
|
framework=test_perf_framework,
|
2015-12-04 00:59:21 +03:00
|
|
|
platform=platform,
|
|
|
|
option_collection=option_collection,
|
|
|
|
suite='mysuite',
|
2016-03-09 23:07:13 +03:00
|
|
|
test='mytest',
|
2016-03-28 23:32:42 +03:00
|
|
|
has_subtests=False,
|
2017-02-06 17:20:12 +03:00
|
|
|
extra_options='e10s opt',
|
2016-03-09 23:07:13 +03:00
|
|
|
last_updated=datetime.datetime.now()
|
2015-12-04 00:59:21 +03:00
|
|
|
)
|
|
|
|
return signature
|
2016-01-07 19:30:43 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2015-12-07 20:49:08 +03:00
|
|
|
def mock_bugzilla_api_request(monkeypatch):
|
|
|
|
"""Mock fetch_json() used by Bugzilla ETL to return a local sample file."""
|
|
|
|
import treeherder.etl.bugzilla
|
2016-01-07 19:30:43 +03:00
|
|
|
|
2015-12-07 20:49:08 +03:00
|
|
|
def _fetch_json(url, params=None):
|
2016-01-07 19:30:43 +03:00
|
|
|
tests_folder = os.path.dirname(__file__)
|
|
|
|
bug_list_path = os.path.join(
|
|
|
|
tests_folder,
|
|
|
|
"sample_data",
|
|
|
|
"bug_list.json"
|
|
|
|
)
|
|
|
|
with open(bug_list_path) as f:
|
2016-05-27 18:19:59 +03:00
|
|
|
return json.load(f)
|
2016-01-07 19:30:43 +03:00
|
|
|
|
2015-12-07 20:49:08 +03:00
|
|
|
monkeypatch.setattr(treeherder.etl.bugzilla,
|
|
|
|
'fetch_json',
|
|
|
|
_fetch_json)
|
2016-01-07 19:30:43 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2015-12-07 20:49:08 +03:00
|
|
|
def bugs(mock_bugzilla_api_request):
|
2016-01-07 19:30:43 +03:00
|
|
|
from treeherder.etl.bugzilla import BzApiBugProcess
|
|
|
|
from treeherder.model.models import Bugscache
|
|
|
|
|
|
|
|
process = BzApiBugProcess()
|
|
|
|
process.run()
|
|
|
|
|
|
|
|
return Bugscache.objects.all()
|
2016-02-05 13:44:58 +03:00
|
|
|
|
|
|
|
|
2018-02-07 20:59:30 +03:00
|
|
|
@pytest.fixture
|
2018-04-12 20:06:53 +03:00
|
|
|
def client():
|
2018-02-07 20:59:30 +03:00
|
|
|
"""
|
2018-04-12 20:06:53 +03:00
|
|
|
A django-rest-framework APIClient instance:
|
|
|
|
http://www.django-rest-framework.org/api-guide/testing/#apiclient
|
2018-02-07 20:59:30 +03:00
|
|
|
"""
|
2018-04-12 20:06:53 +03:00
|
|
|
return APIClient()
|
2018-02-07 20:59:30 +03:00
|
|
|
|
|
|
|
|
2016-02-05 13:44:58 +03:00
|
|
|
@pytest.fixture
|
2016-10-18 18:32:52 +03:00
|
|
|
def text_log_error_lines(test_job, failure_lines):
|
2018-03-21 17:55:05 +03:00
|
|
|
from tests.autoclassify.utils import create_text_log_errors
|
2016-02-05 13:44:58 +03:00
|
|
|
from treeherder.model.models import FailureLine
|
|
|
|
|
2016-09-23 21:51:57 +03:00
|
|
|
lines = [(item, {}) for item in FailureLine.objects.filter(job_guid=test_job.guid).values()]
|
2016-02-05 13:44:58 +03:00
|
|
|
|
2016-09-23 21:51:57 +03:00
|
|
|
errors = create_text_log_errors(test_job, lines)
|
2016-02-05 13:44:58 +03:00
|
|
|
|
2016-10-18 18:32:52 +03:00
|
|
|
return errors
|
2016-02-05 13:44:58 +03:00
|
|
|
|
|
|
|
|
2016-04-23 00:13:29 +03:00
|
|
|
@pytest.fixture
|
2018-05-23 18:13:51 +03:00
|
|
|
def test_perf_alert_summary(test_repository, push_stored, test_perf_framework, test_issue_tracker):
|
2016-04-23 00:13:29 +03:00
|
|
|
from treeherder.perf.models import PerformanceAlertSummary
|
|
|
|
return PerformanceAlertSummary.objects.create(
|
|
|
|
repository=test_repository,
|
2016-06-01 02:54:49 +03:00
|
|
|
framework=test_perf_framework,
|
2016-11-09 21:51:00 +03:00
|
|
|
prev_push_id=1,
|
|
|
|
push_id=2,
|
2016-06-01 02:54:49 +03:00
|
|
|
manually_created=False,
|
2016-04-23 00:13:29 +03:00
|
|
|
last_updated=datetime.datetime.now())
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def test_perf_alert(test_perf_signature, test_perf_alert_summary):
|
|
|
|
from treeherder.perf.models import PerformanceAlert
|
|
|
|
return PerformanceAlert.objects.create(
|
|
|
|
summary=test_perf_alert_summary,
|
|
|
|
series_signature=test_perf_signature,
|
|
|
|
is_regression=True,
|
|
|
|
amount_pct=0.5,
|
|
|
|
amount_abs=50.0,
|
|
|
|
prev_value=100.0,
|
|
|
|
new_value=150.0,
|
|
|
|
t_value=20.0)
|
2016-11-24 22:07:32 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def generic_reference_data(test_repository):
|
|
|
|
'''
|
|
|
|
Generic reference data (if you want to create a bunch of mock jobs)
|
|
|
|
'''
|
|
|
|
from treeherder.model.models import (BuildPlatform,
|
|
|
|
JobGroup,
|
|
|
|
JobType,
|
|
|
|
Machine,
|
|
|
|
MachinePlatform,
|
|
|
|
Option,
|
|
|
|
OptionCollection,
|
|
|
|
Product,
|
|
|
|
ReferenceDataSignatures)
|
|
|
|
|
|
|
|
class RefdataHolder(object):
|
|
|
|
pass
|
|
|
|
r = RefdataHolder()
|
|
|
|
|
|
|
|
r.option = Option.objects.create(name='my_option')
|
|
|
|
r.option_collection = OptionCollection.objects.create(
|
|
|
|
option_collection_hash='my_option_hash',
|
|
|
|
option=r.option)
|
|
|
|
r.option_collection_hash = r.option_collection.option_collection_hash
|
|
|
|
r.machine_platform = MachinePlatform.objects.create(
|
|
|
|
os_name="my_os",
|
|
|
|
platform="my_platform",
|
|
|
|
architecture="x86")
|
|
|
|
r.build_platform = BuildPlatform.objects.create(
|
|
|
|
os_name="my_os",
|
|
|
|
platform="my_platform",
|
|
|
|
architecture="x86")
|
|
|
|
r.machine = Machine.objects.create(name='mymachine')
|
|
|
|
r.job_group = JobGroup.objects.create(symbol='S', name='myjobgroup')
|
2017-08-28 21:25:38 +03:00
|
|
|
r.job_type = JobType.objects.create(symbol='j', name='myjob')
|
2016-11-24 22:07:32 +03:00
|
|
|
r.product = Product.objects.create(name='myproduct')
|
|
|
|
r.signature = ReferenceDataSignatures.objects.create(
|
|
|
|
name='myreferencedatasignaeture',
|
|
|
|
signature='1234',
|
|
|
|
build_os_name=r.build_platform.os_name,
|
|
|
|
build_platform=r.build_platform.platform,
|
|
|
|
build_architecture=r.build_platform.architecture,
|
|
|
|
machine_os_name=r.machine_platform.os_name,
|
|
|
|
machine_platform=r.machine_platform.platform,
|
|
|
|
machine_architecture=r.machine_platform.architecture,
|
|
|
|
job_group_name=r.job_group.name,
|
|
|
|
job_group_symbol=r.job_group.symbol,
|
|
|
|
job_type_name=r.job_type.name,
|
|
|
|
job_type_symbol=r.job_type.symbol,
|
|
|
|
option_collection_hash=r.option_collection_hash,
|
|
|
|
build_system_type='buildbot',
|
|
|
|
repository=test_repository.name,
|
|
|
|
first_submission_timestamp=0)
|
|
|
|
|
|
|
|
return r
|
2018-05-14 12:58:26 +03:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def bug_data(eleven_jobs_stored, test_repository, test_push, bugs):
|
|
|
|
from treeherder.model.models import (Job,
|
|
|
|
BugJobMap,
|
|
|
|
Option)
|
|
|
|
jobs = Job.objects.all()
|
|
|
|
bug_id = bugs[0].id
|
|
|
|
BugJobMap.objects.create(job=jobs[0], bug_id=bug_id)
|
|
|
|
query_string = '?startday=2012-05-09&endday=2018-05-10&tree={}'.format(
|
|
|
|
test_repository.name)
|
|
|
|
|
|
|
|
return {
|
|
|
|
'tree': test_repository.name,
|
|
|
|
'option': Option.objects.all()[0],
|
|
|
|
'bug_id': bug_id,
|
|
|
|
'job': jobs[0],
|
|
|
|
'jobs': jobs,
|
|
|
|
'query_string': query_string
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def test_run_data(bug_data):
|
|
|
|
pushes = Push.objects.all()
|
|
|
|
time = pushes[0].time.strftime('%Y-%m-%d')
|
|
|
|
test_runs = 0
|
|
|
|
for push in list(pushes):
|
|
|
|
if push.time.strftime('%Y-%m-%d') == time:
|
|
|
|
test_runs += 1
|
|
|
|
|
|
|
|
return {
|
|
|
|
'test_runs': test_runs,
|
|
|
|
'push_time': time
|
|
|
|
}
|