diff --git a/light9/collector/collector_test.py b/light9/collector/collector_test.py
--- a/light9/collector/collector_test.py
+++ b/light9/collector/collector_test.py
@@ -1,25 +1,21 @@
import unittest
import datetime
from freezegun import freeze_time
-from rdflib import Literal, Graph, Namespace
-from rdflib.parser import StringInputSource
+from rdflib import Namespace
from light9.namespaces import L9, DEV
from light9.collector.collector import Collector, outputMap
+from light9.rdfdb.mock_syncedgraph import MockSyncedGraph
UDMX = Namespace('http://light9.bigasterisk.com/output/udmx/')
DMX0 = Namespace('http://light9.bigasterisk.com/output/dmx0/')
-
-def fromN3(n3):
- out = Graph()
- out.parse(StringInputSource('''
- @prefix : .
+PREFIX = '''
+ @prefix : .
@prefix dev: .
@prefix udmx: .
@prefix dmx0: .
- ''' + n3), format='n3')
- return out
+'''
class MockOutput(object):
def __init__(self, connections):
@@ -38,27 +34,27 @@ class MockOutput(object):
class TestOutputMap(unittest.TestCase):
def testWorking(self):
out0 = MockOutput([(0, DMX0['c1'])])
- m = outputMap(fromN3('''
+ m = outputMap(MockSyncedGraph(PREFIX + '''
dmx0:c1 :connectedTo dev:inst1Brightness .
dev:inst1 a :Device; :brightness dev:inst1Brightness .
'''), [out0])
self.assertEqual({(DEV['inst1'], L9['brightness']): (out0, 0)}, m)
def testMissingOutput(self):
out0 = MockOutput([(0, DMX0['c1'])])
- self.assertRaises(KeyError, outputMap, fromN3('''
+ self.assertRaises(KeyError, outputMap, MockSyncedGraph(PREFIX + '''
dmx0:c2 :connectedTo dev:inst1Brightness .
dev:inst1 a :Device; :brightness dev:inst1Brightness .
'''), [out0])
def testMissingOutputConnection(self):
out0 = MockOutput([(0, DMX0['c1'])])
- self.assertRaises(ValueError, outputMap, fromN3('''
+ self.assertRaises(ValueError, outputMap, MockSyncedGraph(PREFIX + '''
dev:inst1 a :Device; :brightness dev:inst1Brightness .
'''), [out0])
def testMultipleOutputConnections(self):
out0 = MockOutput([(0, DMX0['c1'])])
- self.assertRaises(ValueError, outputMap, fromN3('''
+ self.assertRaises(ValueError, outputMap, MockSyncedGraph(PREFIX + '''
dmx0:c1 :connectedTo dev:inst1Brightness .
dmx0:c2 :connectedTo dev:inst1Brightness .
dev:inst1 a :Device; :brightness dev:inst1Brightness .
@@ -68,7 +64,7 @@ class TestOutputMap(unittest.TestCase):
class TestCollector(unittest.TestCase):
def setUp(self):
- self.config = fromN3('''
+ self.config = MockSyncedGraph(PREFIX + '''
udmx:c1 :connectedTo dev:colorStripRed .
udmx:c2 :connectedTo dev:colorStripGreen .
@@ -151,10 +147,29 @@ class TestCollector(unittest.TestCase):
self.assertEqual([[204], 'flush', [127], 'flush'], self.dmx0.updates)
def testNewSessionDropsPreviousSettingsOfOtherAttrs(self):
- c = Collector(self.config, outputs=[self.dmx0, self.udmx])
+
+ c = Collector(MockSyncedGraph(PREFIX + '''
+
+ udmx:c1 :connectedTo dev:colorStripRed .
+ udmx:c2 :connectedTo dev:colorStripGreen .
+ udmx:c3 :connectedTo dev:colorStripBlue .
+ udmx:c4 :connectedTo dev:colorStripMode .
- c.setAttrs('client1', 'sess1', [(DEV['colorStrip'], L9['red'], 1)])
- c.setAttrs('client1', 'sess2', [(DEV['colorStrip'], L9['green'], 1)])
+ dev:colorStrip a :Device, :ChauvetColorStrip;
+ :red dev:colorStripRed;
+ :green dev:colorStripGreen;
+ :blue dev:colorStripBlue;
+ :mode dev:colorStripMode .
+
+ dmx0:c1 :connectedTo dev:inst1Brightness .
+ dev:inst1 a :Device, :Dimmer;
+ :brightness dev:inst1Brightness .
+ '''), outputs=[self.dmx0, self.udmx])
+
+ c.setAttrs('client1', 'sess1',
+ [(DEV['colorStrip'], L9['color'], '#ff0000')])
+ c.setAttrs('client1', 'sess2',
+ [(DEV['colorStrip'], L9['color'], '#00ff00')])
self.assertEqual([[255, 0, 0, 215], 'flush',
[0, 255, 0, 215], 'flush'], self.udmx.updates)
diff --git a/light9/collector/device_test.py b/light9/collector/device_test.py
--- a/light9/collector/device_test.py
+++ b/light9/collector/device_test.py
@@ -48,5 +48,6 @@ class TestResolve(unittest.TestCase):
resolve(None, L9['color'], ['#ff0300', '#000400']))
def testMaxes3Colors(self):
self.assertEqual('#112233',
- resolve(None, L9['color'], ['#110000', '#002200', '#000033']))
+ resolve(None, L9['color'],
+ ['#110000', '#002200', '#000033']))
diff --git a/light9/rdfdb/mock_syncedgraph.py b/light9/rdfdb/mock_syncedgraph.py
new file mode 100644
--- /dev/null
+++ b/light9/rdfdb/mock_syncedgraph.py
@@ -0,0 +1,50 @@
+
+from rdflib import Graph, RDF, RDFS
+from rdflib.parser import StringInputSource
+
+class MockSyncedGraph(object):
+ """
+ Lets users of SyncedGraph mostly work. Doesn't yet help with any
+ testing of the rerun-upon-graph-change behavior.
+ """
+ def __init__(self, n3Content):
+ self._graph = Graph()
+ self._graph.parse(StringInputSource(n3Content), format='n3')
+
+ def addHandler(self, func):
+ func()
+
+ def value(self, subject=None, predicate=RDF.value, object=None,
+ default=None, any=True):
+ if object is not None:
+ raise NotImplementedError()
+ return self._graph.value(subject, predicate, object=object,
+ default=default, any=any)
+
+ def objects(self, subject=None, predicate=None):
+ return self._graph.objects(subject, predicate)
+
+ def label(self, uri):
+ return self.value(uri, RDFS.label)
+
+ def subjects(self, predicate=None, object=None):
+ return self._graph.subjects(predicate, object)
+
+ def predicate_objects(self, subject):
+ return self._graph.predicate_objects(subject)
+
+ def items(self, listUri):
+ """generator. Having a chain of watchers on the results is not
+ well-tested yet"""
+ chain = set([listUri])
+ while listUri:
+ item = self.value(listUri, RDF.first)
+ if item:
+ yield item
+ listUri = self.value(listUri, RDF.rest)
+ if listUri in chain:
+ raise ValueError("List contains a recursive rdf:rest reference")
+ chain.add(listUri)
+
+ def contains(self, triple):
+ return triple in self._graph