summaryrefslogtreecommitdiffstats
path: root/pyagl/conftest.py
blob: dd4dc31891c35f3ed61c44ee8a6b57aa242df806 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# Copyright (C) 2020 Konsulko Group
# Author: Edi Feschiyan
#
# 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 os
import re
import asyncio
import pytest
import argparse
import time
import asyncssh
import subprocess


class LavaAction(argparse.Action):
    def __init__(self, option_strings, dest, nargs=0, **kwargs):
        if nargs !=  0:
            raise ValueError("nargs not allowed")
        super(LavaAction, self).__init__(option_strings, dest, nargs=nargs, **kwargs)
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, True)
        setattr(namespace, 'color', 'no')


def pytest_addoption(parser):
    parser.addoption('-L', '--lava', action=LavaAction, help='enable LAVA signals')


def pytest_configure(config):
    # Force normal progress and verbose output off when doing LAVA output
    terminal = config.pluginmanager.getplugin('terminal')
    class QuietReporter(terminal.TerminalReporter):
        def _determine_show_progress_info(self):
            return False

        @property
        def verbosity(self):
            return 0

        @property
        def showlongtestinfo(self):
            return False

        @property
        def showfspath(self):
            return False

    if config.getoption('lava'):
        terminal.TerminalReporter = QuietReporter


def lava_result_convert(pytest_outcome):
    """ Convert the pytest outcome to the string expected by LAVA."""
    if pytest_outcome == 'passed':
        return 'pass'
    elif pytest_outcome == 'skipped':
        return 'skip'
    elif pytest_outcome == 'xfailed':
        return 'pass'
    else:
        return 'fail'


def pytest_report_teststatus(config, report):
    """ Insert strings that LAVA expects to capture test results."""
    done = False
    if config.getoption('lava'):
        # Convert pytest test file and name into a LAVA test name
        test_file = report.location[0].split('/')[-1]
        test_file = test_file.replace('test_', '', 1)
        if test_file.endswith('.py'):
            test_file = test_file[:-3]
        test_name = test_file + '_' + report.location[2][5:]
        # Strip any fixture parameters
        test_name = re.sub('\[.*\]$', '', test_name)
        test_result = lava_result_convert(report.outcome)

        # Generate expected LAVA testcase output
        if report.when == 'setup':
            if report.outcome == 'skipped':
                done = True
        elif report.when == 'call':
            done = True
            if report.outcome == 'failed':
                print(f'<LAVA_SIGNAL_STARTTC {test_name}>')
                print('ERROR:\n')
                print(report.longrepr)
                print(f'<LAVA_SIGNAL_ENDTC {test_name}>')
        if done:
            print(f'<LAVA_SIGNAL_TESTCASE TEST_CASE_ID={test_name} RESULT={test_result}>\n')
            # Delay to slow down serial output for LAVA
            time.sleep(0.25)

        # Quiet short result output
        category, short, verbose = '', '', ''
        if hasattr(report, 'wasxfail'):
            if report.skipped:
                category = 'xfailed'
            elif report.passed:
                category = 'xpassed'
            return (category, short, verbose)
        elif report.when in ('setup', 'teardown'):
            if report.failed:
                category = 'error'
            elif report.skipped:
                category = 'skipped'
            return (category, short, verbose)
        category = report.outcome
        return (category, short, verbose)


async def ssh_helper(address, cmd):
    ssh = await asyncssh.connect(address, username='root', known_hosts=None)
    return await ssh.run(cmd)


def pytest_collection_modifyitems(config, items):
    # Check for J1939 support, mark those tests as skip if not present
    have_j1939 = False
    cmd = [ 'grep', '-q', '^CAN_J1939', '/proc/net/protocols' ]
    address = os.environ.get('AGL_TGT_IP', 'localhost')
    if address != 'localhost':
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        result = loop.run_until_complete(ssh_helper(address, ' '.join(cmd)))
        have_j1939 = result.exit_status == 0
    else:
        result = subprocess.run(cmd)
        have_j1939 = result.returncode == 0

    if not have_j1939:
        skip_j1939 = pytest.mark.skip(reason="J1939 protocol support not available")
        for item in items:
            if "can_j1939" in item.keywords:
                item.add_marker(skip_j1939)