FaradayRF / faradayio

FaradayRF TUN/TAP adapter
https://www.faradayrf.com
GNU General Public License v3.0
15 stars 6 forks source link

Test Driven Development #3

Closed kb1lqc closed 6 years ago

kb1lqc commented 6 years ago

This project will use the style of test driven development (TDD). This website explains it well.

kb1lqc commented 6 years ago

Ohh splinter helps automate website automated testing. Nice! Not terribly useful here unless we provide a statistics webpage with flask or something. Adding a note here.

https://splinter.readthedocs.io/en/latest/

kb1lqc commented 6 years ago

I noticed a few interesting things that must be done when developing in a virtual environment and using both python 2.7 and 3.5 on the same computer. These are:

@kb1lqd @hdkmike

kb1lqc commented 6 years ago

Also, when installing python-pytun on Ubuntu you will need to install the python3-dev package per: https://stackoverflow.com/a/21530768

kb1lqc commented 6 years ago

Alright. This might be easier to approach from the opposite direction and create a unittest.mock serial port which provides some test return_value. The issue I'm having is the same with the UDP end of defining these tests.. what data is being sent? I guess random UDP packets? Do I just generate them with dpkt or something? Any suggestions @reillyeon @hdkmike? I'll be around on Gitter Sunday if you want to try to catch me.

kb1lqc commented 6 years ago

:warning: Need to add user to dailup group for good/easy linux serial port use

kb1lqc commented 6 years ago

Well then. Looks like pyserial can be used for loopback tests with serial compliant objects pointing to a local loopback port... I'll be damned.... nifty.

https://pythonhosted.org/pyserial/pyserial_api.html#serial.serial_for_url

@kb1lqd @hdkmike @reillyeon

kb1lqc commented 6 years ago

Oh wow, right on the front page of the documentation you can call a function with serial and see the available serial ports. This is really useful @kb1lqd !

https://pythonhosted.org/pyserial/shortintro.html#listing-ports

https://pythonhosted.org/pyserial/url_handlers.html

kb1lqc commented 6 years ago

Progress! Ended up deleting a bunch of my code but I like this approach much better. I am now starting to use pyserial's url based serial connection and using the loopback device to make a test serial port which I can then treat as any other serial port! Literally using python serial library to interact.

@kb1lqd @el-iso @reillyeon @hdkmike

https://github.com/kb1lqc/faradayio/blob/initial/tests/serialtestclass.py

class SerialTestClass(object):
    """A mock serial port test class"""
    def __init__(self):
        """Creates a mock serial port which is a loopback object"""
        self._port = "loop://"
        self._timeout = 0
        self._baudrate = 115200
        self.serialPort = \
            serial.serial_for_url(  url=self._port,
                                    timeout=self._timeout,
baudrate=self._baudrate)

A SUPER simple test to make sure this works is shown below

https://github.com/kb1lqc/faradayio/blob/initial/tests/test_serial.py

This simply writes "Hello World!" to the serial port and then reads it's back using serial for both read/write. I then check with assert that the string received was in-fact Hello World!. Super simple but it's a good foundation. I can actually start making progress defining the tests. I do need to figure out how this fits in with asyncio and whether that means I can use pyserial-asyncio too.

image

kb1lqc commented 6 years ago

Synchronous serial port send and receive are working with unit testing! At least as much as I can figure that it's unit testing. Not currently testing all possible inputs or exceptions but it's a start. I'd like to move to asynchronous now that this is working.

It turns out sliplib is not terribly well documented and the sliplib.Driver.receive() function actually sends messages to sliplib.Driver.messages instead of returning messages. This tripped me up a bit but I figured it out. Therefore I decided to make the faraday.receive() function a generator which yields each message. Let me know if this is a bad idea! image

kb1lqc commented 6 years ago

@kb1lqd @reillyeon @hdkmike I sort of have a test working for asyncio based serial ports. I pretty much copied the pyserial-asyncio unit test and modified it for my own use.

https://github.com/kb1lqc/faradayio/blob/initial/tests/test_serial.py#L143

This uses the Input and Output classes in the faradayio module.

The problem I am having is that I can't seem to return a value from the test. I can only run the coroutine with run_until_complete(client). This test "Passes" but that's because it doesn't error. I am not asserting anything.

The pyserial-asyncio unit test checks that the receive list equals the bytes that were sent to it over the serial port (socket in this case). I can't do that since when the coroutine of aysncio completes, the list is destroyed. I am not sure how to go about and actually unit test a asyncio.Protocol.

@pyserial any help would be appreciated! @bufferoverflow @zsquareplusc

I really want to use asyncio as it appears to be everything I need but maybe I need to consider just doing something with synchronous pyserial... like we did before. https://stackoverflow.com/questions/17553543/pyserial-non-blocking-read-loop

kb1lqc commented 6 years ago

I removed the asyncio code for now and started building better unit tests for pyserial and sliplib implementations within faradayio. I need to test exceptions and stuff but this is a good step to making progress with serial and SLIP support with unit tests to back it up.

https://github.com/kb1lqc/faradayio/tree/initial

@kb1lqd @reillyeon @el-iso @hdkmike

kb1lqc commented 6 years ago

The documentation in CONTRIBUTIONS.md in our Athena Project needs to be updated to reflect a central location for this desired approach. Closing this ticket as I created https://github.com/FaradayRF/Athena/issues/2 to reflect this need on that repository.