Skip to content

Commit

Permalink
Some minor re-structuring, improving tests. Still very worried that r…
Browse files Browse the repository at this point in the history
…unning the tests might wipe the Storage, need to figure out a solution :(
  • Loading branch information
kipe committed Mar 3, 2016
1 parent e437e93 commit eb8b83c
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 6 deletions.
50 changes: 47 additions & 3 deletions enocean/communicators/communicator.py
@@ -1,14 +1,15 @@
# -*- encoding: utf-8 -*-
from __future__ import print_function, unicode_literals, division, absolute_import
import logging

import os
import threading
try:
import queue
except ImportError:
import Queue as queue
from enocean.protocol.packet import Packet, UTETeachIn
from enocean.protocol.packet import Packet, RadioPacket, UTETeachIn
from enocean.protocol.constants import PACKET, PARSE_RESULT, RETURN_CODE
from enocean.storage import Storage, Device


class Communicator(threading.Thread):
Expand All @@ -18,7 +19,8 @@ class Communicator(threading.Thread):
'''
logger = logging.getLogger('enocean.communicators.Communicator')

def __init__(self, callback=None, teach_in=True):
# TODO: Stupid, ugly hack to disable storage during testing.
def __init__(self, callback=None, teach_in=True, use_storage=True if os.environ.get('ENOCEAN_TESTING', None) else False, storage_location=None):
super(Communicator, self).__init__()
# Create an event to stop the thread
self._stop_flag = threading.Event()
Expand All @@ -35,6 +37,12 @@ def __init__(self, callback=None, teach_in=True):
# TODO: Not sure if we should use CO_WR_LEARNMODE??
self.teach_in = teach_in

# Initialize Storage
# TODO: Should really initialize with Storage-object, but not accept any new devices...
self.storage = None
if use_storage:
self.storage = Storage(storage_location)

def _get_from_send_queue(self):
''' Get message from send queue, if one exists '''
try:
Expand Down Expand Up @@ -114,12 +122,48 @@ def parse(self):
self.send(packet.create_response_packet(self.base_id), priority=0)
packet.response_sent = True

self.store_device(packet)

# TODO: Prioritize packages, once receive is changed to PriorityQueue
if self.__callback is None:
self.receive.put(packet)
else:
self.__callback(packet)
self.logger.debug(packet)

def store_device(self, packet):
''' Save device to storage, if all conditions are met. '''
if self.storage is None:
return
if self.teach_in is False:
return
if not isinstance(packet, RadioPacket):
return
if not packet.learn:
return

try:
device = self.storage.load_device(device_id=packet.sender)
# If device is found, update the data we're likely to get from the teach_in.
device.update({
'eep_rorg': packet.rorg,
'eep_func': packet.rorg_func,
'eep_type': packet.rorg_type,
'manufacturer_id': packet.rorg_manufacturer,
})
self.storage.save_device(device)
except KeyError:
# If device is not found, create a new device.
self.storage.save_device(
Device(
id=packet.sender,
eep_rorg=packet.rorg,
eep_func=packet.rorg_func,
eep_type=packet.rorg_type,
manufacturer_id=packet.rorg_manufacturer
)
)

@property
def base_id(self):
''' Fetches Base ID from the transmitter, if required. Otherwise returns the currently set Base ID. '''
Expand Down
31 changes: 31 additions & 0 deletions enocean/communicators/tests/test_communicator.py
Expand Up @@ -141,3 +141,34 @@ def test_thread():
com.start()
com.base_id
com.stop()


def test_storage():
data = bytearray([
0x55,
0x00, 0x0A, 0x07, 0x01,
0xEB,
0xA5, 0x08, 0x28, 0x46, 0x80, 0x01, 0x8A, 0x7B, 0x30, 0x00,
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x49, 0x00,
0x26
])

com = Communicator(use_storage=False)
assert com.storage is None
com._buffer.extend(data)
com.parse()
assert com.storage is None

com = Communicator(use_storage=True, storage_location='/tmp/enocean-tests.json')
assert len(com.storage.devices.keys()) == 0
com._buffer.extend(data)
com.parse()
assert len(com.storage.devices.keys()) == 1

com = Communicator()
com._buffer.extend(data)
com.parse()
packet = com.get_packet()
assert packet.learn

com.storage.wipe()
44 changes: 43 additions & 1 deletion enocean/storage/tests/test_storage.py
@@ -1,8 +1,9 @@
# -*- encoding: utf-8 -*-
from __future__ import print_function, unicode_literals, division, absolute_import
import os
import errno
from enocean.storage import Storage, Device
from enocean.decorators import timing
from enocean.tests.decorators import timing

PATH = '/tmp/enocean-tests.json'
# Remove the file to be sure...
Expand Down Expand Up @@ -103,6 +104,12 @@ def test_devices_add_remove():
assert s.next_offset == 0
assert s.used_offsets == [1]

try:
s.used_offsets = 'ASD'
assert False
except ValueError:
assert True

# Reload Storage, just to make sure save was successful.
s.load()

Expand All @@ -123,9 +130,20 @@ def test_devices_add_remove():
pass

s.remove_device('DE:AD:BE:EF')
del s.data['devices']
s.save_device(device)
# Reload Storage, just to make sure save was successful.
s.load()

s.remove_device('DE:AD:BE:EF')
s.save_device(device)
# Reload Storage, just to make sure save was successful.
s.load()

s.save_device(device)
# Reload Storage, just to make sure save was successful.
s.load()
s.remove_device([0xDE, 0xAD, 0xBE, 0xEF])
assert s.devices == {}

try:
Expand All @@ -135,3 +153,27 @@ def test_devices_add_remove():
assert True

s.wipe()


def test_random():
# FFS, if this kind of tests fail, and cause issues, shoot @kipe.
# @kipe wrote:
# to be honest, I have no idea on how to do these kinds of tests, except in a very, very
# very, very, safe environoment :S
# and furthermore, if these kind of tests run in your environment, you're fucked anyways...

# Try a directory, we are absolutely not allowed to write.
s = Storage('/usr/var/lib/local/bin/asd')
try:
s.save()
except OSError as exception:
if exception == errno.EEXIST:
raise
pass

s.location = '/bin/sh'
try:
s.wipe()
except OSError as exception:
if exception == errno.EPERM:
pass
2 changes: 0 additions & 2 deletions run_tests_with_timing.sh

This file was deleted.

2 changes: 2 additions & 0 deletions test.sh
@@ -0,0 +1,2 @@
#!/bin/sh
ENOCEAN_TESTING=1 nosetests -s -q --with-coverage --cover-package=enocean
2 changes: 2 additions & 0 deletions test_with_timing.sh
@@ -0,0 +1,2 @@
#!/bin/sh
WITH_TIMINGS=1 test.sh

0 comments on commit eb8b83c

Please sign in to comment.