Skip to content

Commit 4e65521

Browse files
authored
Merge pull request #1687 from peternewman/0.10-clang-latest
Fix the Python RPC tests on Big Endian architectures
2 parents 72af9f9 + 5290edd commit 4e65521

11 files changed

Lines changed: 201 additions & 31 deletions

File tree

.travis.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,12 +479,21 @@ before_install:
479479
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew uninstall --ignore-dependencies gnupg; fi
480480
#Fix a broken homebrew python upgrade - see https://github.com/Homebrew/homebrew-core/issues/26358
481481
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade python || true; fi
482-
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then if [ ! -d /usr/local/sbin ]; then sudo mkdir -p /usr/local/sbin && sudo chown -R $(whoami) /usr/local/sbin; fi; fi
483-
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then PATH=/usr/local/opt/ccache/libexec:$PATH; fi # Use ccache on Mac too
482+
#Uninstall some homebrew packages which aren't required so we don't end up updating and rebuilding them. Force so it doesn't reinstall
483+
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew uninstall --ignore-dependencies --force cgal liblwgeom libspatialite mercurial postgis postgres sfcgal; fi
484+
#Having fixed everything up, update to the bleeding edge
485+
#Skip updating for now as it seems to be breaking the build, also now done via the addon
486+
# - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
484487
# This is no longer allowed, so build all Mac builds as protobuf latest
485488
#- if [ "$TRAVIS_OS_NAME" == "osx" -a "$PROTOBUF" != "latest" ]; then brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/024ca9a4730a1f26ceede43485fbf62ef6f41179%5E/Formula/protobuf@3.1.rb; fi # install protobuf 3.1 as that's the latest we support everywhere
486489
#- if [ "$TRAVIS_OS_NAME" == "osx" -a "$PROTOBUF" != "latest" ]; then brew link -f https://raw.githubusercontent.com/Homebrew/homebrew-core/024ca9a4730a1f26ceede43485fbf62ef6f41179%5E/Formula/protobuf@3.1.rb; export PKG_CONFIG_PATH=/usr/local/opt/protobuf@3.1/lib/pkgconfig; brew install --build-from-source --ignore-dependencies --env=std protobuf-c; fi # While protobuf is not on the latest release
490+
- if [ "$TRAVIS_OS_NAME" == "osx" -a "$PROTOBUF" != "latest" ]; then brew install protobuf@3.6; fi
491+
- if [ "$TRAVIS_OS_NAME" == "osx" -a "$PROTOBUF" != "latest" ]; then brew link -f protobuf@3.6; export PKG_CONFIG_PATH=/usr/local/opt/protobuf@3.6/lib/pkgconfig; brew install --build-from-source --ignore-dependencies --env=std protobuf-c; fi # When protobuf is not on the latest release
487492
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir -p ${HOME}/Library/Python/2.7/lib/python/site-packages; echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >> ${HOME}/Library/Python/2.7/lib/python/site-packages/homebrew.pth; fi
493+
- if [ "$TRAVIS_OS_NAME" == "osx" -a "$CPPUNIT" != "1.14" ]; then brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/e6e43cf6a3%5E/Formula/cppunit.rb; fi # install a slightly older cppunit, as latest needs C++11 support
494+
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then PATH=/usr/local/opt/ccache/libexec:$PATH; fi # Use ccache on Mac too
495+
#Put back the old pip numpy we need to work
496+
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pip install --upgrade --no-deps --force-reinstall --user numpy; fi
488497
#Coverity doesn't work with g++ 5 or 6, so only upgrade to g++ 4.9 for that
489498
- if [ "$TRAVIS_OS_NAME" == "linux" -a \( "$TASK" = "compile" -o "$TASK" = "coverage" -o "$TASK" = "doxygen" \) -a "$CXX" = "g++" ]; then export CXX="ccache g++-10" CC="ccache gcc-10"; fi
490499
- if [ "$TASK" = "coverity" -a "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi

NEWS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ x/y/2020 ola-0.10.9
99
*
1010

1111
Bugs:
12-
*
12+
* Renamed EndpointNoticationEvent(sic) to EndpointNotificationEvent in the
13+
E1.33 EndpointManager code
1314

1415
Internal:
1516
*

python/examples/Makefile.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ dist_noinst_SCRIPTS += \
33
python/examples/ola_artnet_params.py \
44
python/examples/ola_candidate_ports.py \
55
python/examples/ola_devices.py \
6+
python/examples/ola_fetch_dmx.py \
67
python/examples/ola_patch_unpatch.py \
78
python/examples/ola_plugin_info.py \
89
python/examples/ola_rdm_discover.py \

python/examples/ola_fetch_dmx.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env python
2+
# This program is free software; you can redistribute it and/or modify
3+
# it under the terms of the GNU General Public License as published by
4+
# the Free Software Foundation; either version 2 of the License, or
5+
# (at your option) any later version.
6+
#
7+
# This program is distributed in the hope that it will be useful,
8+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
# GNU Library General Public License for more details.
11+
#
12+
# You should have received a copy of the GNU General Public License
13+
# along with this program; if not, write to the Free Software
14+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15+
#
16+
# ola_fetch_dmx.py
17+
# Copyright (C) 2020 Peter Newman
18+
19+
"""Gets a current frame of DMX for a universe."""
20+
21+
from __future__ import print_function
22+
from ola.ClientWrapper import ClientWrapper
23+
import getopt
24+
import textwrap
25+
import sys
26+
27+
__author__ = 'nomis52@gmail.com (Simon Newton)'
28+
29+
wrapper = None
30+
31+
32+
def DMXData(status, universe, data):
33+
if status.Succeeded():
34+
print(data)
35+
36+
else:
37+
print('Error: %s' % status.message, file=sys.stderr)
38+
39+
global wrapper
40+
if wrapper:
41+
wrapper.Stop()
42+
43+
44+
def Usage():
45+
print(textwrap.dedent("""
46+
Usage: ola_fetch_dmx.py --universe <universe>
47+
48+
Fetch the current DXM512 data for the universe and exit.
49+
50+
-h, --help Display this help message and exit.
51+
-u, --universe <universe> Universe number."""))
52+
53+
54+
def main():
55+
try:
56+
opts, args = getopt.getopt(sys.argv[1:], "hu:", ["help", "universe="])
57+
except getopt.GetoptError as err:
58+
print(str(err))
59+
Usage()
60+
sys.exit(2)
61+
62+
universe = 1
63+
for o, a in opts:
64+
if o in ("-h", "--help"):
65+
Usage()
66+
sys.exit()
67+
elif o in ("-u", "--universe"):
68+
universe = int(a)
69+
70+
global wrapper
71+
wrapper = ClientWrapper()
72+
client = wrapper.Client()
73+
client.FetchDmx(universe, DMXData)
74+
wrapper.Run()
75+
76+
77+
if __name__ == '__main__':
78+
main()

python/ola/ClientWrapperTest.py

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import unittest
2525
from ola.ClientWrapper import ClientWrapper
2626
from ola.ClientWrapper import _Event
27+
from ola.TestUtils import handleRPCByteOrder
2728

2829

2930
"""Test cases for the Event and Event loop of ClientWrapper class."""
@@ -192,22 +193,22 @@ def d():
192193
# Called immediately
193194
a_diff = results.a_called - self.start
194195
self.assertAlmostEqual(a_diff, datetime.timedelta(milliseconds=0),
195-
delta=datetime.timedelta(microseconds=500))
196+
delta=datetime.timedelta(microseconds=750))
196197

197198
# Called in 5 milliseconds
198199
b_diff = results.b_called - self.start
199200
self.assertAlmostEqual(b_diff, datetime.timedelta(milliseconds=5),
200-
delta=datetime.timedelta(microseconds=500))
201+
delta=datetime.timedelta(microseconds=750))
201202

202203
# Called in 10 milliseconds
203204
c_diff = results.c_called - self.start
204205
self.assertAlmostEqual(c_diff, datetime.timedelta(milliseconds=10),
205-
delta=datetime.timedelta(microseconds=500))
206+
delta=datetime.timedelta(microseconds=750))
206207

207208
# Called in 15 milliseconds
208209
d_diff = results.d_called - self.start
209210
self.assertAlmostEqual(d_diff, datetime.timedelta(milliseconds=15),
210-
delta=datetime.timedelta(microseconds=500))
211+
delta=datetime.timedelta(microseconds=750))
211212

212213
sockets[0].close()
213214
sockets[1].close()
@@ -223,12 +224,12 @@ class results:
223224

224225
def DataCallback(self):
225226
data = sockets[1].recv(4096)
226-
expected = binascii.unhexlify(
227+
expected = handleRPCByteOrder(binascii.unhexlify(
227228
"7d000010080110001a0d557064617465446d784461746122680801126400000"
228229
"000000000000000000000000000000000000000000000000000000000000000"
229230
"000000000000000000000000000000000000000000000000000000000000000"
230231
"000000000000000000000000000000000000000000000000000000000000000"
231-
"000000")
232+
"000000"))
232233
self.assertEqual(data, expected,
233234
msg="Regression check failed. If protocol change "
234235
"was intended set expected to: " +
@@ -242,11 +243,78 @@ def DataCallback(self):
242243

243244
wrapper.Run()
244245

246+
sockets[0].close()
247+
sockets[1].close()
248+
245249
self.assertTrue(results.gotdata)
246250

251+
# @timeout_decorator.timeout(2)
252+
def testFetchDmx(self):
253+
"""uses client to send a FetchDMX with mocked olad.
254+
Regression test that confirms sent message is correct and
255+
sends fixed response message."""
256+
sockets = socket.socketpair()
257+
wrapper = ClientWrapper(sockets[0])
258+
client = wrapper.Client()
259+
260+
class results:
261+
got_request = False
262+
got_response = False
263+
264+
def DataCallback(self):
265+
# request and response for
266+
# ola_fetch_dmx.py -u 0
267+
# enable logging in rpc/StreamRpcChannel.py
268+
data = sockets[1].recv(4096)
269+
expected = handleRPCByteOrder(binascii.unhexlify(
270+
"10000010080110001a06476574446d7822020800"))
271+
self.assertEqual(data, expected,
272+
msg="Regression check failed. If protocol change "
273+
"was intended set expected to: " +
274+
str(binascii.hexlify(data)))
275+
results.got_request = True
276+
response = handleRPCByteOrder(binascii.unhexlify(
277+
"0c020010080210002285040800128004"
278+
"00000000000000000000000000000000000000000000000000000000000000"
279+
"00000000000000000000000000000000000000000000000000000000000000"
280+
"00000000000000000000000000000000000000000000000000000000000000"
281+
"00000000000000000000000000000000000000000000000000000000000000"
282+
"00000000000000000000000000000000000000000000000000000000000000"
283+
"00000000000000000000000000000000000000000000000000000000000000"
284+
"00000000000000000000000000000000000000000000000000000000000000"
285+
"00000000000000000000000000000000000000000000000000000000000000"
286+
"00000000000000000000000000000000000000000000000000000000000000"
287+
"00000000000000000000000000000000000000000000000000000000000000"
288+
"00000000000000000000000000000000000000000000000000000000000000"
289+
"00000000000000000000000000000000000000000000000000000000000000"
290+
"00000000000000000000000000000000000000000000000000000000000000"
291+
"00000000000000000000000000000000000000000000000000000000000000"
292+
"00000000000000000000000000000000000000000000000000000000000000"
293+
"00000000000000000000000000000000000000000000000000000000000000"
294+
"00000000000000000000000000000000"))
295+
sent_bytes = sockets[1].send(response)
296+
self.assertEqual(sent_bytes, len(response))
297+
298+
def ResponseCallback(self, status, universe, data):
299+
results.got_response = True
300+
self.assertTrue(status.Succeeded())
301+
self.assertEqual(universe, 0)
302+
self.assertEqual(len(data), 512)
303+
self.assertEqual(data, array.array('B', [0] * 512))
304+
wrapper.AddEvent(0, wrapper.Stop)
305+
306+
wrapper._ss.AddReadDescriptor(sockets[1], lambda: DataCallback(self))
307+
308+
client.FetchDmx(0, lambda x, y, z: ResponseCallback(self, x, y, z))
309+
310+
wrapper.Run()
311+
247312
sockets[0].close()
248313
sockets[1].close()
249314

315+
self.assertTrue(results.got_request)
316+
self.assertTrue(results.got_response)
317+
250318

251319
if __name__ == '__main__':
252320
unittest.main()

python/ola/RDMTest.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from ola.OlaClient import RDMNack
2727
from ola.RDMAPI import RDMAPI
2828
from ola.UID import UID
29+
from ola.TestUtils import handleRPCByteOrder
2930

3031

3132
"""Test cases for RDM device commands."""
@@ -57,18 +58,18 @@ def DataCallback(self):
5758
# against olad dummy plugin
5859
# enable logging in rpc/StreamRpcChannel.py
5960
data = sockets[1].recv(4096)
60-
expected = binascii.unhexlify(
61+
expected = handleRPCByteOrder(binascii.unhexlify(
6162
"29000010080110001a0a52444d436f6d6d616e6422170801120908f0f4011500"
62-
"ffffff180020602a0030003800")
63+
"ffffff180020602a0030003800"))
6364
self.assertEqual(data, expected,
6465
msg="Regression check failed. If protocol change "
6566
"was intended set expected to: " +
6667
str(binascii.hexlify(data)))
6768
results.got_request = True
68-
response = binascii.unhexlify(
69+
response = handleRPCByteOrder(binascii.unhexlify(
6970
"3f0000100802100022390800100018002213010000017fff0000000300050204"
7071
"00010000032860300038004a0908f0f4011500ffffff520908f0f40115ac1100"
71-
"02580a")
72+
"02580a"))
7273
sent_bytes = sockets[1].send(response)
7374
self.assertEqual(sent_bytes, len(response))
7475

@@ -124,18 +125,18 @@ def DataCallback(self):
124125
# against olad dummy plugin
125126
# enable logging in rpc/StreamRpcChannel.py
126127
data = sockets[1].recv(4096)
127-
expected = binascii.unhexlify(
128+
expected = handleRPCByteOrder(binascii.unhexlify(
128129
"2b000010080110001a0a52444d436f6d6d616e6422190801120908f0f4011500"
129-
"ffffff180020e1012a010230003800")
130+
"ffffff180020e1012a010230003800"))
130131
self.assertEqual(data, expected,
131132
msg="Regression check failed. If protocol change "
132133
"was intended set expected to: " +
133134
str(binascii.hexlify(data)))
134135
results.got_request = True
135-
response = binascii.unhexlify(
136+
response = handleRPCByteOrder(binascii.unhexlify(
136137
"3d0000100802100022370800100018002210020005506572736f6e616c697479"
137138
"203228e101300038004a0908f0f4011500ffffff520908f0f40115ac107de058"
138-
"29")
139+
"29"))
139140
sent_bytes = sockets[1].send(response)
140141
self.assertEqual(sent_bytes, len(response))
141142

@@ -184,17 +185,17 @@ def DataCallback(self):
184185
# against olad dummy plugin
185186
# enable logging in rpc/StreamRpcChannel.py
186187
data = sockets[1].recv(4096)
187-
expected = binascii.unhexlify(
188+
expected = handleRPCByteOrder(binascii.unhexlify(
188189
"2b000010080110001a0a52444d436f6d6d616e6422190801120908f0f401150"
189-
"0ffffff180020e0012a010a30013800")
190+
"0ffffff180020e0012a010a30013800"))
190191
self.assertEqual(data, expected,
191192
msg="Regression check failed. If protocol change "
192193
"was intended set expected to: " +
193194
str(binascii.hexlify(data)))
194195
results.got_request = True
195-
response = binascii.unhexlify(
196+
response = handleRPCByteOrder(binascii.unhexlify(
196197
"2f0000100802100022290800100218002202000628e001300138004a0908f0f"
197-
"4011500ffffff520908f0f40115ac107de05831")
198+
"4011500ffffff520908f0f40115ac107de05831"))
198199
sent_bytes = sockets[1].send(response)
199200
self.assertEqual(sent_bytes, len(response))
200201

python/ola/TestUtils.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
# Copyright (C) 2020 Bruce Lowekamp
1818

1919
import itertools
20+
import struct
21+
import sys
2022

2123
"""Common utils for ola python tests"""
2224

@@ -32,3 +34,13 @@ def allHashNotEqual(testCase, t):
3234
h = map(hash, t)
3335
for pair in itertools.combinations(h, 2):
3436
testCase.assertNotEqual(pair[0], pair[1])
37+
38+
39+
def handleRPCByteOrder(expected):
40+
# The RPC header (version and size) is encoded in native format, so flip that
41+
# part of the expected data where necessary (as our expected is from a
42+
# little endian source)
43+
if sys.byteorder == 'big':
44+
expected = (struct.pack('=L', struct.unpack_from('<L', expected)[0]) +
45+
expected[4:])
46+
return expected

tools/e133/EndpointManager.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void EndpointManager::EndpointIDs(vector<uint16_t> *id_list) const {
8282
* @param callback the Callback to run. Ownership is not transferred.
8383
*/
8484
void EndpointManager::RegisterNotification(
85-
EndpointNoticationEvent event_type,
85+
EndpointNotificationEvent event_type,
8686
EndpointNotificationCallback *callback) {
8787
// if this callback already exists update it
8888
vector<EndpointNotification>::iterator iter = m_callbacks.begin();
@@ -121,7 +121,7 @@ bool EndpointManager::UnRegisterNotification(
121121
* @param event_type the type of notifications to trigger.
122122
*/
123123
void EndpointManager::RunNotifications(uint16_t endpoint_id,
124-
EndpointNoticationEvent event_type) {
124+
EndpointNotificationEvent event_type) {
125125
vector<EndpointNotification>::iterator iter = m_callbacks.begin();
126126
for (; iter != m_callbacks.end(); ++iter) {
127127
if (iter->event_type == event_type || event_type == BOTH)

tools/e133/EndpointManager.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
class EndpointManager {
4242
public:
4343
typedef ola::Callback1<void, uint16_t> EndpointNotificationCallback;
44-
typedef enum { ADD, REMOVE, BOTH } EndpointNoticationEvent;
44+
typedef enum { ADD, REMOVE, BOTH } EndpointNotificationEvent;
4545

4646
EndpointManager()
4747
: m_list_change_number(0) {
@@ -60,7 +60,7 @@ class EndpointManager {
6060
void EndpointIDs(std::vector<uint16_t> *id_list) const;
6161

6262
// control notifications
63-
void RegisterNotification(EndpointNoticationEvent event_type,
63+
void RegisterNotification(EndpointNotificationEvent event_type,
6464
EndpointNotificationCallback *callback);
6565
bool UnRegisterNotification(EndpointNotificationCallback *callback);
6666

@@ -73,12 +73,12 @@ class EndpointManager {
7373

7474
// list of callbacks to run
7575
typedef struct {
76-
EndpointNoticationEvent event_type;
76+
EndpointNotificationEvent event_type;
7777
EndpointNotificationCallback *callback;
7878
} EndpointNotification;
7979
std::vector<EndpointNotification> m_callbacks;
8080

8181
void RunNotifications(uint16_t endpoint_id,
82-
EndpointNoticationEvent event_type);
82+
EndpointNotificationEvent event_type);
8383
};
8484
#endif // TOOLS_E133_ENDPOINTMANAGER_H_

0 commit comments

Comments
 (0)