Mercurial > code > home > repos > light9
comparison light9/collector/collector_test.py @ 1506:37cbb245d93c
fix tests. add logging, some mypy types.
Ignore-this: 61371f65438a4e77f70d21cc5d5193bf
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Tue, 28 Mar 2017 07:48:10 +0000 |
parents | f427801da9f6 |
children | c1bf296b0a74 |
comparison
equal
deleted
inserted
replaced
1505:e917fb4eea3a | 1506:37cbb245d93c |
---|---|
1 import unittest | 1 import unittest |
2 import datetime | 2 import datetime, time |
3 from freezegun import freeze_time | 3 from freezegun import freeze_time |
4 from rdflib import Namespace | 4 from rdflib import Namespace, URIRef |
5 | 5 |
6 from light9.namespaces import L9, DEV | 6 from light9.namespaces import L9, DEV |
7 from light9.collector.collector import Collector, outputMap | 7 from light9.collector.collector import Collector, outputMap |
8 from light9.rdfdb.mock_syncedgraph import MockSyncedGraph | 8 from light9.rdfdb.mock_syncedgraph import MockSyncedGraph |
9 | 9 |
15 @prefix dev: <http://light9.bigasterisk.com/device/> . | 15 @prefix dev: <http://light9.bigasterisk.com/device/> . |
16 @prefix udmx: <http://light9.bigasterisk.com/output/udmx/> . | 16 @prefix udmx: <http://light9.bigasterisk.com/output/udmx/> . |
17 @prefix dmx0: <http://light9.bigasterisk.com/output/dmx0/> . | 17 @prefix dmx0: <http://light9.bigasterisk.com/output/dmx0/> . |
18 ''' | 18 ''' |
19 | 19 |
20 THEATER = ''' | |
21 :brightness a :DeviceAttr; :dataType :scalar . | |
22 | |
23 :SimpleDimmer a :DeviceClass; | |
24 :deviceAttr :brightness; | |
25 :attr | |
26 [ :outputAttr :level; :dmxOffset 0 ] . | |
27 | |
28 :ChauvetColorStrip a :DeviceClass; | |
29 :deviceAttr :color; | |
30 :attr | |
31 [ :outputAttr :mode; :dmxOffset 0 ], | |
32 [ :outputAttr :red; :dmxOffset 1 ], | |
33 [ :outputAttr :green; :dmxOffset 2 ], | |
34 [ :outputAttr :blue; :dmxOffset 3 ] . | |
35 | |
36 ''' | |
37 | |
38 t0 = 0 # time | |
39 | |
20 class MockOutput(object): | 40 class MockOutput(object): |
21 def __init__(self, connections): | 41 def __init__(self, uri, connections): |
22 self.connections = connections | 42 self.connections = connections |
23 self.updates = [] | 43 self.updates = [] |
44 self.uri = uri | |
45 self.numChannels = 4 | |
24 | 46 |
25 def allConnections(self): | 47 def allConnections(self): |
26 return self.connections | 48 return self.connections |
27 | 49 |
28 def update(self, values): | 50 def update(self, values): |
29 self.updates.append(values) | 51 self.updates.append(values) |
30 | 52 |
31 def flush(self): | 53 def flush(self): |
32 self.updates.append('flush') | 54 self.updates.append('flush') |
33 | 55 |
56 @unittest.skip("outputMap got rewritten and mostly doesn't raise on these cases") | |
34 class TestOutputMap(unittest.TestCase): | 57 class TestOutputMap(unittest.TestCase): |
35 def testWorking(self): | 58 def testWorking(self): |
36 out0 = MockOutput([(0, DMX0['c1'])]) | 59 out0 = MockOutput(UDMX, [(0, DMX0['c1'])]) |
37 m = outputMap(MockSyncedGraph(PREFIX + ''' | 60 m = outputMap(MockSyncedGraph(PREFIX + ''' |
38 dmx0:c1 :connectedTo dev:inst1Brightness . | 61 dmx0:c1 :connectedTo dev:inst1Brightness . |
39 dev:inst1 a :Device; :brightness dev:inst1Brightness . | 62 dev:inst1 a :Device; :brightness dev:inst1Brightness . |
40 '''), [out0]) | 63 '''), [out0]) |
41 self.assertEqual({(DEV['inst1'], L9['brightness']): (out0, 0)}, m) | 64 self.assertEqual({(DEV['inst1'], L9['brightness']): (out0, 0)}, m) |
65 | |
42 def testMissingOutput(self): | 66 def testMissingOutput(self): |
43 out0 = MockOutput([(0, DMX0['c1'])]) | 67 out0 = MockOutput(UDMX, [(0, DMX0['c1'])]) |
44 self.assertRaises(KeyError, outputMap, MockSyncedGraph(PREFIX + ''' | 68 self.assertRaises(KeyError, outputMap, MockSyncedGraph(PREFIX + ''' |
45 dmx0:c2 :connectedTo dev:inst1Brightness . | |
46 dev:inst1 a :Device; :brightness dev:inst1Brightness . | 69 dev:inst1 a :Device; :brightness dev:inst1Brightness . |
47 '''), [out0]) | 70 '''), [out0]) |
48 | 71 |
49 def testMissingOutputConnection(self): | 72 def testMissingOutputConnection(self): |
50 out0 = MockOutput([(0, DMX0['c1'])]) | 73 out0 = MockOutput(UDMX, [(0, DMX0['c1'])]) |
51 self.assertRaises(ValueError, outputMap, MockSyncedGraph(PREFIX + ''' | 74 self.assertRaises(ValueError, outputMap, MockSyncedGraph(PREFIX + ''' |
52 dev:inst1 a :Device; :brightness dev:inst1Brightness . | 75 dev:inst1 a :Device; :brightness dev:inst1Brightness . |
53 '''), [out0]) | 76 '''), [out0]) |
54 | 77 |
55 def testMultipleOutputConnections(self): | 78 def testMultipleOutputConnections(self): |
56 out0 = MockOutput([(0, DMX0['c1'])]) | 79 out0 = MockOutput(UDMX, [(0, DMX0['c1'])]) |
57 self.assertRaises(ValueError, outputMap, MockSyncedGraph(PREFIX + ''' | 80 self.assertRaises(ValueError, outputMap, MockSyncedGraph(PREFIX + ''' |
58 dmx0:c1 :connectedTo dev:inst1Brightness . | 81 dmx0:c1 :connectedTo dev:inst1Brightness . |
59 dmx0:c2 :connectedTo dev:inst1Brightness . | 82 dmx0:c2 :connectedTo dev:inst1Brightness . |
60 dev:inst1 a :Device; :brightness dev:inst1Brightness . | 83 dev:inst1 a :Device; :brightness dev:inst1Brightness . |
61 '''), [out0]) | 84 '''), [out0]) |
62 | 85 |
63 | 86 |
64 | 87 |
65 class TestCollector(unittest.TestCase): | 88 class TestCollector(unittest.TestCase): |
66 def setUp(self): | 89 def setUp(self): |
67 self.config = MockSyncedGraph(PREFIX + ''' | 90 self.config = MockSyncedGraph(PREFIX + THEATER + ''' |
68 | |
69 udmx:c1 :connectedTo dev:colorStripRed . | |
70 udmx:c2 :connectedTo dev:colorStripGreen . | |
71 udmx:c3 :connectedTo dev:colorStripBlue . | |
72 udmx:c4 :connectedTo dev:colorStripMode . | |
73 | 91 |
74 dev:colorStrip a :Device, :ChauvetColorStrip; | 92 dev:colorStrip a :Device, :ChauvetColorStrip; |
93 :dmxUniverse udmx:; :dmxBase 1; | |
75 :red dev:colorStripRed; | 94 :red dev:colorStripRed; |
76 :green dev:colorStripGreen; | 95 :green dev:colorStripGreen; |
77 :blue dev:colorStripBlue; | 96 :blue dev:colorStripBlue; |
78 :mode dev:colorStripMode . | 97 :mode dev:colorStripMode . |
79 | 98 |
80 dmx0:c1 :connectedTo dev:inst1Brightness . | 99 dev:inst1 a :Device, :SimpleDimmer; |
81 dev:inst1 a :Device, :Dimmer; | 100 :dmxUniverse dmx0:; :dmxBase 1; |
82 :brightness dev:inst1Brightness . | 101 :level dev:inst1Brightness . |
83 ''') | 102 ''') |
84 | 103 |
85 self.dmx0 = MockOutput([(0, DMX0['c1'])]) | 104 self.dmx0 = MockOutput(DMX0[None], [(0, DMX0['c1'])]) |
86 self.udmx = MockOutput([(0, UDMX['c1']), | 105 self.udmx = MockOutput(UDMX[None], [(0, UDMX['c1']), |
87 (1, UDMX['c2']), | 106 (1, UDMX['c2']), |
88 (2, UDMX['c3']), | 107 (2, UDMX['c3']), |
89 (3, UDMX['c4'])]) | 108 (3, UDMX['c4'])]) |
90 | 109 |
91 def testRoutesColorOutput(self): | 110 def testRoutesColorOutput(self): |
92 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) | 111 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) |
93 | 112 |
94 c.setAttrs('client', 'sess1', | 113 c.setAttrs('client', 'sess1', |
95 [(DEV['colorStrip'], L9['color'], '#00ff00')]) | 114 [(DEV['colorStrip'], L9['color'], '#00ff00')], t0) |
96 | 115 |
97 self.assertEqual([[0, 255, 0, 215], 'flush'], self.udmx.updates) | 116 self.assertEqual([[215, 0, 255, 0], 'flush'], self.udmx.updates) |
98 self.assertEqual([], self.dmx0.updates) | 117 self.assertEqual([[0, 0, 0, 0], 'flush'], self.dmx0.updates) |
99 | 118 |
100 def testOutputMaxOfTwoClients(self): | 119 def testOutputMaxOfTwoClients(self): |
101 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) | 120 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) |
102 | 121 |
103 c.setAttrs('client1', 'sess1', | 122 c.setAttrs('client1', 'sess1', |
104 [(DEV['colorStrip'], L9['color'], '#ff0000')]) | 123 [(DEV['colorStrip'], L9['color'], '#ff0000')], t0) |
105 c.setAttrs('client2', 'sess1', | 124 c.setAttrs('client2', 'sess1', |
106 [(DEV['colorStrip'], L9['color'], '#333333')]) | 125 [(DEV['colorStrip'], L9['color'], '#333333')], t0) |
107 | 126 |
108 self.assertEqual([[255, 0, 0, 215], 'flush', | 127 self.assertEqual([[215, 255, 0, 0], 'flush', |
109 [255, 51, 51, 215], 'flush'], | 128 [215, 255, 51, 51], 'flush'], |
110 self.udmx.updates) | 129 self.udmx.updates) |
111 self.assertEqual([], self.dmx0.updates) | 130 self.assertEqual([[0, 0, 0, 0], 'flush', [0, 0, 0, 0], 'flush'], |
131 self.dmx0.updates) | |
112 | 132 |
113 def testClientOnSameOutputIsRememberedOverCalls(self): | 133 def testClientOnSameOutputIsRememberedOverCalls(self): |
114 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) | 134 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) |
115 | 135 |
116 c.setAttrs('client1', 'sess1', | 136 c.setAttrs('client1', 'sess1', |
117 [(DEV['colorStrip'], L9['color'], '#080000')]) | 137 [(DEV['colorStrip'], L9['color'], '#080000')], t0) |
118 c.setAttrs('client2', 'sess1', | 138 c.setAttrs('client2', 'sess1', |
119 [(DEV['colorStrip'], L9['color'], '#060000')]) | 139 [(DEV['colorStrip'], L9['color'], '#060000')], t0) |
120 c.setAttrs('client1', 'sess1', | 140 c.setAttrs('client1', 'sess1', |
121 [(DEV['colorStrip'], L9['color'], '#050000')]) | 141 [(DEV['colorStrip'], L9['color'], '#050000')], t0) |
122 | 142 |
123 self.assertEqual([[8, 0, 0, 215], 'flush', | 143 self.assertEqual([[215, 8, 0, 0], 'flush', |
124 [8, 0, 0, 215], 'flush', | 144 [215, 8, 0, 0], 'flush', |
125 [6, 0, 0, 215], 'flush'], | 145 [215, 6, 0, 0], 'flush'], |
126 self.udmx.updates) | 146 self.udmx.updates) |
127 self.assertEqual([], self.dmx0.updates) | 147 self.assertEqual([[0, 0, 0, 0], 'flush', |
148 [0, 0, 0, 0], 'flush', | |
149 [0, 0, 0, 0], 'flush'], | |
150 self.dmx0.updates) | |
128 | 151 |
129 def testClientsOnDifferentOutputs(self): | 152 def testClientsOnDifferentOutputs(self): |
130 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) | 153 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) |
131 | 154 |
132 c.setAttrs('client1', 'sess1', [(DEV['colorStrip'], L9['color'], '#aa0000')]) | 155 c.setAttrs('client1', 'sess1', [(DEV['colorStrip'], L9['color'], '#aa0000')], t0) |
133 c.setAttrs('client2', 'sess1', [(DEV['inst1'], L9['brightness'], .5)]) | 156 c.setAttrs('client2', 'sess1', [(DEV['inst1'], L9['brightness'], .5)], t0) |
134 | 157 |
135 # ok that udmx is flushed twice- it can screen out its own duplicates | 158 # ok that udmx is flushed twice- it can screen out its own duplicates |
136 self.assertEqual([[170, 0, 0, 215], 'flush', | 159 self.assertEqual([[215, 170, 0, 0], 'flush', |
137 [170, 0, 0, 215], 'flush'], self.udmx.updates) | 160 [215, 170, 0, 0], 'flush'], self.udmx.updates) |
138 self.assertEqual([[127], 'flush'], self.dmx0.updates) | 161 self.assertEqual([[0, 0, 0, 0], 'flush', |
162 [127, 0, 0, 0], 'flush'], self.dmx0.updates) | |
139 | 163 |
140 def testNewSessionReplacesPreviousOutput(self): | 164 def testNewSessionReplacesPreviousOutput(self): |
141 # ..as opposed to getting max'd with it | 165 # ..as opposed to getting max'd with it |
142 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) | 166 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) |
143 | 167 |
144 c.setAttrs('client1', 'sess1', [(DEV['inst1'], L9['brightness'], .8)]) | 168 c.setAttrs('client1', 'sess1', [(DEV['inst1'], L9['brightness'], .8)], t0) |
145 c.setAttrs('client1', 'sess2', [(DEV['inst1'], L9['brightness'], .5)]) | 169 c.setAttrs('client1', 'sess2', [(DEV['inst1'], L9['brightness'], .5)], t0) |
146 | 170 |
147 self.assertEqual([[204], 'flush', [127], 'flush'], self.dmx0.updates) | 171 self.assertEqual([[204, 0, 0, 0], 'flush', |
172 [127, 0, 0, 0], 'flush'], self.dmx0.updates) | |
148 | 173 |
149 def testNewSessionDropsPreviousSettingsOfOtherAttrs(self): | 174 def testNewSessionDropsPreviousSettingsOfOtherAttrs(self): |
150 | 175 c = Collector(MockSyncedGraph(PREFIX + THEATER + ''' |
151 c = Collector(MockSyncedGraph(PREFIX + ''' | |
152 | |
153 udmx:c1 :connectedTo dev:colorStripRed . | |
154 udmx:c2 :connectedTo dev:colorStripGreen . | |
155 udmx:c3 :connectedTo dev:colorStripBlue . | |
156 udmx:c4 :connectedTo dev:colorStripMode . | |
157 | 176 |
158 dev:colorStrip a :Device, :ChauvetColorStrip; | 177 dev:colorStrip a :Device, :ChauvetColorStrip; |
178 :dmxUniverse udmx:; :dmxBase 1; | |
159 :red dev:colorStripRed; | 179 :red dev:colorStripRed; |
160 :green dev:colorStripGreen; | 180 :green dev:colorStripGreen; |
161 :blue dev:colorStripBlue; | 181 :blue dev:colorStripBlue; |
162 :mode dev:colorStripMode . | 182 :mode dev:colorStripMode . |
163 | 183 |
164 dmx0:c1 :connectedTo dev:inst1Brightness . | 184 dev:inst1 a :Device, :SimpleDimmer; |
165 dev:inst1 a :Device, :Dimmer; | 185 :dmxUniverse dmx0:; :dmxBase 0; |
166 :brightness dev:inst1Brightness . | 186 :level dev:inst1Brightness . |
167 '''), outputs=[self.dmx0, self.udmx]) | 187 '''), outputs=[self.dmx0, self.udmx]) |
168 | 188 |
169 c.setAttrs('client1', 'sess1', | 189 c.setAttrs('client1', 'sess1', |
170 [(DEV['colorStrip'], L9['color'], '#ff0000')]) | 190 [(DEV['colorStrip'], L9['color'], '#ff0000')], t0) |
171 c.setAttrs('client1', 'sess2', | 191 c.setAttrs('client1', 'sess2', |
172 [(DEV['colorStrip'], L9['color'], '#00ff00')]) | 192 [(DEV['colorStrip'], L9['color'], '#00ff00')], t0) |
173 | 193 |
174 self.assertEqual([[255, 0, 0, 215], 'flush', | 194 self.assertEqual([[215, 255, 0, 0], 'flush', |
175 [0, 255, 0, 215], 'flush'], self.udmx.updates) | 195 [215, 0, 255, 0], 'flush'], self.udmx.updates) |
176 | 196 |
177 def testClientIsForgottenAfterAWhile(self): | 197 def testClientIsForgottenAfterAWhile(self): |
178 with freeze_time(datetime.datetime.now()) as ft: | 198 with freeze_time(datetime.datetime.now()) as ft: |
179 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) | 199 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) |
180 c.setAttrs('cli1', 'sess1', [(DEV['inst1'], L9['brightness'], .5)]) | 200 c.setAttrs('cli1', 'sess1', [(DEV['inst1'], L9['brightness'], .5)], |
201 time.time()) | |
181 ft.tick(delta=datetime.timedelta(seconds=1)) | 202 ft.tick(delta=datetime.timedelta(seconds=1)) |
182 c.setAttrs('cli2', 'sess1', [(DEV['inst1'], L9['brightness'], .2)]) | 203 # this max's with cli1's value so we still see .5 |
204 c.setAttrs('cli2', 'sess1', [(DEV['inst1'], L9['brightness'], .2)], | |
205 time.time()) | |
183 ft.tick(delta=datetime.timedelta(seconds=9.1)) | 206 ft.tick(delta=datetime.timedelta(seconds=9.1)) |
184 c.setAttrs('cli2', 'sess1', [(DEV['inst1'], L9['brightness'], .4)]) | 207 # now cli1 is forgotten, so our value appears |
185 self.assertEqual([[127], 'flush', [127], 'flush', [102], 'flush'], | 208 c.setAttrs('cli2', 'sess1', [(DEV['inst1'], L9['brightness'], .4)], |
209 time.time()) | |
210 self.assertEqual([[127, 0, 0, 0], 'flush', | |
211 [127, 0, 0, 0], 'flush', | |
212 [102, 0, 0, 0], 'flush'], | |
186 self.dmx0.updates) | 213 self.dmx0.updates) |
187 | 214 |
188 def testClientUpdatesAreCollected(self): | 215 def testClientUpdatesAreNotMerged(self): |
189 # second call to setAttrs doesn't forget the first | 216 # second call to setAttrs forgets the first |
190 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) | 217 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) |
191 | 218 t0 = time.time() |
192 c.setAttrs('client1', 'sess1', [(DEV['inst1'], L9['brightness'], .5)]) | 219 c.setAttrs('client1', 'sess1', [(DEV['inst1'], L9['brightness'], .5)], t0) |
193 c.setAttrs('client1', 'sess1', [(DEV['inst1'], L9['brightness'], 1)]) | 220 c.setAttrs('client1', 'sess1', [(DEV['inst1'], L9['brightness'], 1)], t0) |
194 c.setAttrs('client1', 'sess1', [(DEV['colorStrip'], L9['color'], '#00ff00')]) | 221 c.setAttrs('client1', 'sess1', [(DEV['colorStrip'], L9['color'], '#00ff00')], t0) |
195 | 222 |
196 self.assertEqual([[0, 255, 0, 215], 'flush'], self.udmx.updates) | 223 self.assertEqual([[0, 0, 0, 0], 'flush', |
197 self.assertEqual([[127], 'flush', [255], 'flush', [255], 'flush'], self.dmx0.updates) | 224 [0, 0, 0, 0], 'flush', |
225 [215, 0, 255, 0], 'flush'], | |
226 self.udmx.updates) | |
227 self.assertEqual([[127, 0, 0, 0], 'flush', | |
228 [255, 0, 0, 0], 'flush', | |
229 [0, 0, 0, 0], 'flush'], | |
230 self.dmx0.updates) | |
198 | 231 |
199 def testRepeatedAttributesInOneRequestGetResolved(self): | 232 def testRepeatedAttributesInOneRequestGetResolved(self): |
200 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) | 233 c = Collector(self.config, outputs=[self.dmx0, self.udmx]) |
201 | 234 |
202 c.setAttrs('client1', 'sess1', [ | 235 c.setAttrs('client1', 'sess1', [ |
203 (DEV['inst1'], L9['brightness'], .5), | 236 (DEV['inst1'], L9['brightness'], .5), |
204 (DEV['inst1'], L9['brightness'], .3), | 237 (DEV['inst1'], L9['brightness'], .3), |
205 ]) | 238 ], t0) |
206 self.assertEqual([[127], 'flush'], self.dmx0.updates) | 239 self.assertEqual([[127, 0, 0, 0], 'flush'], self.dmx0.updates) |
207 | 240 |
208 c.setAttrs('client1', 'sess1', [ | 241 c.setAttrs('client1', 'sess1', [ |
209 (DEV['inst1'], L9['brightness'], .3), | 242 (DEV['inst1'], L9['brightness'], .3), |
210 (DEV['inst1'], L9['brightness'], .5), | 243 (DEV['inst1'], L9['brightness'], .5), |
211 ]) | 244 ], t0) |
212 self.assertEqual([[127], 'flush', [127], 'flush'], self.dmx0.updates) | 245 self.assertEqual([[127, 0, 0, 0], 'flush', |
213 | 246 [127, 0, 0, 0], 'flush'], self.dmx0.updates) |
247 |