Skip to content

Commit 1051f1e

Browse files
authored
Added proof-of-concept testing of SocketCAN on Travis CI & Smaller changes (hardbyte#275)
* added many tests in listsner_test * added platform checks and very basic SocketCanTest * added subprocess dependency for testing * testing CI builds * test CI builds * add correct version specifiers to setup.py * call setup.py correctly * better error messages in test/config.py * fix stupid error in test/config.py * fix test_timestamp unittest * removed a bazillion log messages when testing * make tests more forgiving & faster * test socketcan on Travis CI * added demo test for socketcan on Travis CI * try to fix travis builds * try to fix travis builds number 2 * fix bytes/bytearray bug in Python 2 * skip failing test and leave a note where to find the issue * added missing '@' * fix copy&paste mistake * removed setUpClass() in test case * add missing 'raise'
1 parent 1a34e01 commit 1051f1e

14 files changed

Lines changed: 146 additions & 42 deletions

‎.appveyor.yml‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,13 @@ environment:
1717
- PYTHON: "C:\\Python36-x64"
1818

1919
install:
20-
# We need our usual libraries
21-
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
2220
# We need to install the python-can library itself
23-
- "%PYTHON%\\python.exe -m pip install ."
21+
- "%PYTHON%\\python.exe -m pip install .[test]"
2422

2523
build: off
2624

2725
test_script:
2826
# Note that you must use the environment variable %PYTHON% to refer to
2927
# the interpreter you're using - Appveyor does not do anything special
3028
# to put the Python version you want to use on PATH.
31-
- "%PYTHON%\\python.exe setup.py test"
29+
- "%PYTHON%\\python.exe setup.py test -v"

‎.travis.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ matrix:
4343
- python: "nightly"
4444

4545
install:
46-
- travis_retry pip install .
47-
- travis_retry pip install -r requirements.txt
46+
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo bash test/open_vcan.sh ; fi
47+
- travis_retry pip install .[test]
4848

4949
script:
5050
- py.test -v

‎can/interfaces/virtual.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def recv(self, timeout=None):
4646
except queue.Empty:
4747
return None
4848

49-
logger.log(9, 'Received message:\n%s', msg)
49+
#logger.log(9, 'Received message:\n%s', msg)
5050
return msg
5151

5252
def send(self, msg, timeout=None):
@@ -55,7 +55,7 @@ def send(self, msg, timeout=None):
5555
for bus_queue in self.channel:
5656
if bus_queue is not self.queue or self.receive_own_messages:
5757
bus_queue.put(msg)
58-
logger.log(9, 'Transmitted message:\n%s', msg)
58+
#logger.log(9, 'Transmitted message:\n%s', msg)
5959

6060
def shutdown(self):
6161
self.channel.remove(self.queue)

‎can/io/logger.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
See the :class:`Logger` class.
66
"""
77

8+
import logging
9+
810
from .asc import ASCWriter
911
from .blf import BLFWriter
1012
from .csv import CSVWriter
1113
from .log import CanutilsLogWriter
1214
from .sqlite import SqliteWriter
1315
from .stdout import Printer
1416

17+
log = logging.getLogger("can.io.logger")
18+
1519

1620
class Logger(object):
1721
"""
@@ -22,6 +26,7 @@ class Logger(object):
2226
* .blf :class:`can.BLFWriter`
2327
* .csv: :class:`can.CSVWriter`
2428
* .db: :class:`can.SqliteWriter`
29+
* .log :class:`can.CanutilsLogWriter`
2530
* other: :class:`can.Printer`
2631
2732
Note this class itself is just a dispatcher,
@@ -35,13 +40,14 @@ def __new__(cls, other, filename):
3540
return Printer()
3641
elif filename.endswith(".asc"):
3742
return ASCWriter(filename)
38-
elif filename.endswith(".log"):
39-
return CanutilsLogWriter(filename)
4043
elif filename.endswith(".blf"):
4144
return BLFWriter(filename)
4245
elif filename.endswith(".csv"):
4346
return CSVWriter(filename)
4447
elif filename.endswith(".db"):
4548
return SqliteWriter(filename)
49+
elif filename.endswith(".log"):
50+
return CanutilsLogWriter(filename)
4651
else:
52+
log.info('unknown file type "%s", falling pack to can.Printer', filename)
4753
return Printer(filename)

‎can/io/player.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ class LogReader(object):
4444

4545
@classmethod
4646
def __new__(cls, other, filename):
47-
if filename.endswith(".asc"):
47+
if not filename:
48+
raise TypeError("a filename must be given")
49+
elif filename.endswith(".asc"):
4850
return ASCReader(filename)
4951
elif filename.endswith(".blf"):
5052
return BLFReader(filename)

‎requirements.txt‎

Lines changed: 0 additions & 2 deletions
This file was deleted.

‎setup.py‎

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,29 @@
55
python-can requires the setuptools package to be installed.
66
"""
77

8+
from sys import version_info
89
import re
910
import logging
1011
from setuptools import setup, find_packages
1112

13+
logging.basicConfig(level=logging.WARNING)
14+
1215
with open('can/__init__.py', 'r') as fd:
1316
version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]',
1417
fd.read(), re.MULTILINE).group(1)
1518

1619
with open('README.rst', 'r') as f:
1720
long_description = f.read()
1821

19-
logging.basicConfig(level=logging.WARNING)
22+
tests_require = [
23+
'mock',
24+
'nose',
25+
'pyserial >= 3.0',
26+
]
27+
if version_info.major < 3:
28+
tests_require += ['subprocess32 >= 3.2']
2029

2130
setup(
22-
2331
# Description
2432
name="python-can",
2533
url="https://github.com/hardbyte/python-can",
@@ -29,7 +37,9 @@
2937
# Code
3038
version=version,
3139
packages=find_packages(),
32-
40+
# see https://www.python.org/dev/peps/pep-0345/#version-specifiers
41+
python_requires='>=2.7,!=3.0,!=3.1,!=3.2',
42+
3343
# Author
3444
author="Brian Thorne",
3545
author_email="brian@thorne.link",
@@ -45,18 +55,16 @@
4555

4656
# Installation
4757
install_requires=[
58+
'setuptools',
4859
#'Deprecated >= 1.1.0',
4960
],
5061
extras_require={
5162
'serial': ['pyserial >= 3.0'],
52-
'neovi': ['python-ics'],
63+
'neovi': ['python-ics >= 2.8'],
64+
'test': tests_require
5365
},
5466

5567
# Testing
5668
test_suite="nose.collector",
57-
tests_require=[
58-
'mock',
59-
'nose',
60-
'pyserial >= 3.0'
61-
],
69+
tests_require=tests_require,
6270
)

‎test/back2back_test.py‎

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
This module tests two virtual busses attached to each other.
66
"""
77

8-
from __future__ import absolute_import
8+
from __future__ import absolute_import, print_function
99

10+
import sys
1011
import unittest
11-
import time
12+
from time import sleep
1213

1314
import can
1415

1516
from .config import *
17+
from .data.example_data import generate_message
1618

1719
BITRATE = 500000
1820
TIMEOUT = 0.1
@@ -80,12 +82,12 @@ def test_no_message(self):
8082
def test_timestamp(self):
8183
self.bus2.send(can.Message())
8284
recv_msg1 = self.bus1.recv(TIMEOUT)
83-
time.sleep(5)
85+
sleep(2.0)
8486
self.bus2.send(can.Message())
8587
recv_msg2 = self.bus1.recv(TIMEOUT)
8688
delta_time = recv_msg2.timestamp - recv_msg1.timestamp
87-
self.assertTrue(4.8 < delta_time < 5.2,
88-
'Time difference should have been 5s +/- 200ms.'
89+
self.assertTrue(1.75 <= delta_time <= 2.25,
90+
'Time difference should have been 2s +/- 250ms.'
8991
'But measured {}'.format(delta_time))
9092

9193
def test_standard_message(self):
@@ -130,6 +132,39 @@ def test_fd_message_with_brs(self):
130132
data=[0xff] * 48)
131133
self._send_and_receive(msg)
132134

135+
# FIXME
136+
@unittest.skip("skip until CAN FD support is fixed, see issue #274")
137+
#@unittest.skipUnless(TEST_INTERFACE_SOCKETCAN, "skip testing of socketcan")
138+
class BasicTestSocketCan(unittest.TestCase):
139+
140+
def setUp(self):
141+
socketcan_version = can.util.choose_socketcan_implementation()
142+
print("testing python-can's socketcan version:",
143+
socketcan_version)
144+
145+
self.bus1 = can.interface.Bus(channel="vcan0",
146+
bustype=socketcan_version,
147+
bitrate=250000,
148+
fd=TEST_CAN_FD)
149+
self.bus2 = can.interface.Bus(channel="vcan0",
150+
bustype=socketcan_version,
151+
bitrate=250000,
152+
fd=TEST_CAN_FD)
153+
154+
def tearDown(self):
155+
self.bus1.shutdown()
156+
self.bus2.shutdown()
157+
158+
def test_basics(self):
159+
reader = can.BufferedReader()
160+
notifier = can.Notifier(self.bus2, [reader])
161+
162+
message = can.Message(arbitration_id=0x4321, data=[1, 2, 3], extended_id=True)
163+
self.bus1.send(message)
164+
165+
self.assertEqual(message, reader.get_message(timeout=2.0))
166+
notifier.stop()
167+
133168

134169
if __name__ == '__main__':
135170
unittest.main()

‎test/config.py‎

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
# coding: utf-8
33

44
"""
5-
This module contains some configuration for the tests.
5+
This module contains various configuration for the tests.
66
77
Some tests are skipped when run on a CI server because they are not
88
reproducible, see #243 (https://github.com/hardbyte/python-can/issues/243).
99
"""
1010

11+
import platform
1112
from os import environ as environment
1213

14+
15+
# ############################## Continuos integration
16+
1317
# see here for the environment variables that are set on the CI servers:
1418
# - https://docs.travis-ci.com/user/environment-variables/
1519
# - https://www.appveyor.com/docs/environment-variables/
@@ -21,4 +25,27 @@
2125
environment.get('CI', '').lower() == 'true' or \
2226
environment.get('CONTINUOUS_INTEGRATION', '').lower() == 'true'
2327

28+
if IS_APPVEYOR and IS_TRAVIS:
29+
raise EnvironmentError("IS_APPVEYOR and IS_TRAVIS cannot be both True at the same time")
30+
31+
# ############################## Platforms
32+
33+
_sys = platform.system().lower()
34+
IS_WINDOWS = "windows" in _sys or ("win" in _sys and "darwin" not in _sys)
35+
IS_LINUX = "linux" in _sys
36+
IS_OSX = "darwin" in _sys
37+
38+
if (IS_WINDOWS and IS_LINUX) or (IS_LINUX and IS_OSX) or (IS_WINDOWS and IS_OSX):
39+
raise EnvironmentError(
40+
"only one of IS_WINDOWS ({}), IS_LINUX ({}) and IS_OSX ({}) ".format(IS_WINDOWS, IS_LINUX, IS_OSX) +
41+
"can be True at the same time " +
42+
'(platform.system() == "{}")'.format(platform.system())
43+
)
44+
elif not IS_WINDOWS and not IS_LINUX and not IS_OSX:
45+
raise EnvironmentError("one of IS_WINDOWS, IS_LINUX, IS_OSX has to be True")
46+
47+
# ############################## What tests to run
48+
2449
TEST_CAN_FD = True
50+
51+
TEST_INTERFACE_SOCKETCAN = IS_CI and IS_LINUX

‎test/data/example_data.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,5 @@ def generate_message(arbitration_id):
124124
Generates a new message with the given ID, some random data
125125
and a non-extended ID.
126126
"""
127-
data = bytes([random.randrange(0, 2 ** 8 - 1) for _ in range(8)])
127+
data = bytearray([random.randrange(0, 2 ** 8 - 1) for _ in range(8)])
128128
return Message(arbitration_id=arbitration_id, data=data, extended_id=False)

0 commit comments

Comments
 (0)