diff --git a/caf b/caf index 571c4d19..4f580d89 160000 --- a/caf +++ b/caf @@ -1 +1 @@ -Subproject commit 571c4d19ba6b72328e04e0452da9618cd0c9d3f3 +Subproject commit 4f580d89f35ae4d475505101623c8b022c0c6aa6 diff --git a/tests/btest/Baseline/web-socket.gh-357-regression/recv.recv.out b/tests/btest/Baseline/web-socket.gh-357-regression/recv.recv.out new file mode 100644 index 00000000..89cadd83 --- /dev/null +++ b/tests/btest/Baseline/web-socket.gh-357-regression/recv.recv.out @@ -0,0 +1,808 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +{ + "type": "data-message", + "topic": "/test", + "@data-type": "vector", + "data": [ + { + "@data-type": "count", + "data": 0 + }, + { + "@data-type": "count", + "data": 1 + }, + { + "@data-type": "count", + "data": 2 + }, + { + "@data-type": "count", + "data": 3 + }, + { + "@data-type": "count", + "data": 4 + }, + { + "@data-type": "count", + "data": 5 + }, + { + "@data-type": "count", + "data": 6 + }, + { + "@data-type": "count", + "data": 7 + }, + { + "@data-type": "count", + "data": 8 + }, + { + "@data-type": "count", + "data": 9 + }, + { + "@data-type": "count", + "data": 10 + }, + { + "@data-type": "count", + "data": 11 + }, + { + "@data-type": "count", + "data": 12 + }, + { + "@data-type": "count", + "data": 13 + }, + { + "@data-type": "count", + "data": 14 + }, + { + "@data-type": "count", + "data": 15 + }, + { + "@data-type": "count", + "data": 16 + }, + { + "@data-type": "count", + "data": 17 + }, + { + "@data-type": "count", + "data": 18 + }, + { + "@data-type": "count", + "data": 19 + }, + { + "@data-type": "count", + "data": 20 + }, + { + "@data-type": "count", + "data": 21 + }, + { + "@data-type": "count", + "data": 22 + }, + { + "@data-type": "count", + "data": 23 + }, + { + "@data-type": "count", + "data": 24 + }, + { + "@data-type": "count", + "data": 25 + }, + { + "@data-type": "count", + "data": 26 + }, + { + "@data-type": "count", + "data": 27 + }, + { + "@data-type": "count", + "data": 28 + }, + { + "@data-type": "count", + "data": 29 + }, + { + "@data-type": "count", + "data": 30 + }, + { + "@data-type": "count", + "data": 31 + }, + { + "@data-type": "count", + "data": 32 + }, + { + "@data-type": "count", + "data": 33 + }, + { + "@data-type": "count", + "data": 34 + }, + { + "@data-type": "count", + "data": 35 + }, + { + "@data-type": "count", + "data": 36 + }, + { + "@data-type": "count", + "data": 37 + }, + { + "@data-type": "count", + "data": 38 + }, + { + "@data-type": "count", + "data": 39 + }, + { + "@data-type": "count", + "data": 40 + }, + { + "@data-type": "count", + "data": 41 + }, + { + "@data-type": "count", + "data": 42 + }, + { + "@data-type": "count", + "data": 43 + }, + { + "@data-type": "count", + "data": 44 + }, + { + "@data-type": "count", + "data": 45 + }, + { + "@data-type": "count", + "data": 46 + }, + { + "@data-type": "count", + "data": 47 + }, + { + "@data-type": "count", + "data": 48 + }, + { + "@data-type": "count", + "data": 49 + }, + { + "@data-type": "count", + "data": 50 + }, + { + "@data-type": "count", + "data": 51 + }, + { + "@data-type": "count", + "data": 52 + }, + { + "@data-type": "count", + "data": 53 + }, + { + "@data-type": "count", + "data": 54 + }, + { + "@data-type": "count", + "data": 55 + }, + { + "@data-type": "count", + "data": 56 + }, + { + "@data-type": "count", + "data": 57 + }, + { + "@data-type": "count", + "data": 58 + }, + { + "@data-type": "count", + "data": 59 + }, + { + "@data-type": "count", + "data": 60 + }, + { + "@data-type": "count", + "data": 61 + }, + { + "@data-type": "count", + "data": 62 + }, + { + "@data-type": "count", + "data": 63 + }, + { + "@data-type": "count", + "data": 64 + }, + { + "@data-type": "count", + "data": 65 + }, + { + "@data-type": "count", + "data": 66 + }, + { + "@data-type": "count", + "data": 67 + }, + { + "@data-type": "count", + "data": 68 + }, + { + "@data-type": "count", + "data": 69 + }, + { + "@data-type": "count", + "data": 70 + }, + { + "@data-type": "count", + "data": 71 + }, + { + "@data-type": "count", + "data": 72 + }, + { + "@data-type": "count", + "data": 73 + }, + { + "@data-type": "count", + "data": 74 + }, + { + "@data-type": "count", + "data": 75 + }, + { + "@data-type": "count", + "data": 76 + }, + { + "@data-type": "count", + "data": 77 + }, + { + "@data-type": "count", + "data": 78 + }, + { + "@data-type": "count", + "data": 79 + }, + { + "@data-type": "count", + "data": 80 + }, + { + "@data-type": "count", + "data": 81 + }, + { + "@data-type": "count", + "data": 82 + }, + { + "@data-type": "count", + "data": 83 + }, + { + "@data-type": "count", + "data": 84 + }, + { + "@data-type": "count", + "data": 85 + }, + { + "@data-type": "count", + "data": 86 + }, + { + "@data-type": "count", + "data": 87 + }, + { + "@data-type": "count", + "data": 88 + }, + { + "@data-type": "count", + "data": 89 + }, + { + "@data-type": "count", + "data": 90 + }, + { + "@data-type": "count", + "data": 91 + }, + { + "@data-type": "count", + "data": 92 + }, + { + "@data-type": "count", + "data": 93 + }, + { + "@data-type": "count", + "data": 94 + }, + { + "@data-type": "count", + "data": 95 + }, + { + "@data-type": "count", + "data": 96 + }, + { + "@data-type": "count", + "data": 97 + }, + { + "@data-type": "count", + "data": 98 + }, + { + "@data-type": "count", + "data": 99 + }, + { + "@data-type": "count", + "data": 100 + }, + { + "@data-type": "count", + "data": 101 + }, + { + "@data-type": "count", + "data": 102 + }, + { + "@data-type": "count", + "data": 103 + }, + { + "@data-type": "count", + "data": 104 + }, + { + "@data-type": "count", + "data": 105 + }, + { + "@data-type": "count", + "data": 106 + }, + { + "@data-type": "count", + "data": 107 + }, + { + "@data-type": "count", + "data": 108 + }, + { + "@data-type": "count", + "data": 109 + }, + { + "@data-type": "count", + "data": 110 + }, + { + "@data-type": "count", + "data": 111 + }, + { + "@data-type": "count", + "data": 112 + }, + { + "@data-type": "count", + "data": 113 + }, + { + "@data-type": "count", + "data": 114 + }, + { + "@data-type": "count", + "data": 115 + }, + { + "@data-type": "count", + "data": 116 + }, + { + "@data-type": "count", + "data": 117 + }, + { + "@data-type": "count", + "data": 118 + }, + { + "@data-type": "count", + "data": 119 + }, + { + "@data-type": "count", + "data": 120 + }, + { + "@data-type": "count", + "data": 121 + }, + { + "@data-type": "count", + "data": 122 + }, + { + "@data-type": "count", + "data": 123 + }, + { + "@data-type": "count", + "data": 124 + }, + { + "@data-type": "count", + "data": 125 + }, + { + "@data-type": "count", + "data": 126 + }, + { + "@data-type": "count", + "data": 127 + }, + { + "@data-type": "count", + "data": 128 + }, + { + "@data-type": "count", + "data": 129 + }, + { + "@data-type": "count", + "data": 130 + }, + { + "@data-type": "count", + "data": 131 + }, + { + "@data-type": "count", + "data": 132 + }, + { + "@data-type": "count", + "data": 133 + }, + { + "@data-type": "count", + "data": 134 + }, + { + "@data-type": "count", + "data": 135 + }, + { + "@data-type": "count", + "data": 136 + }, + { + "@data-type": "count", + "data": 137 + }, + { + "@data-type": "count", + "data": 138 + }, + { + "@data-type": "count", + "data": 139 + }, + { + "@data-type": "count", + "data": 140 + }, + { + "@data-type": "count", + "data": 141 + }, + { + "@data-type": "count", + "data": 142 + }, + { + "@data-type": "count", + "data": 143 + }, + { + "@data-type": "count", + "data": 144 + }, + { + "@data-type": "count", + "data": 145 + }, + { + "@data-type": "count", + "data": 146 + }, + { + "@data-type": "count", + "data": 147 + }, + { + "@data-type": "count", + "data": 148 + }, + { + "@data-type": "count", + "data": 149 + }, + { + "@data-type": "count", + "data": 150 + }, + { + "@data-type": "count", + "data": 151 + }, + { + "@data-type": "count", + "data": 152 + }, + { + "@data-type": "count", + "data": 153 + }, + { + "@data-type": "count", + "data": 154 + }, + { + "@data-type": "count", + "data": 155 + }, + { + "@data-type": "count", + "data": 156 + }, + { + "@data-type": "count", + "data": 157 + }, + { + "@data-type": "count", + "data": 158 + }, + { + "@data-type": "count", + "data": 159 + }, + { + "@data-type": "count", + "data": 160 + }, + { + "@data-type": "count", + "data": 161 + }, + { + "@data-type": "count", + "data": 162 + }, + { + "@data-type": "count", + "data": 163 + }, + { + "@data-type": "count", + "data": 164 + }, + { + "@data-type": "count", + "data": 165 + }, + { + "@data-type": "count", + "data": 166 + }, + { + "@data-type": "count", + "data": 167 + }, + { + "@data-type": "count", + "data": 168 + }, + { + "@data-type": "count", + "data": 169 + }, + { + "@data-type": "count", + "data": 170 + }, + { + "@data-type": "count", + "data": 171 + }, + { + "@data-type": "count", + "data": 172 + }, + { + "@data-type": "count", + "data": 173 + }, + { + "@data-type": "count", + "data": 174 + }, + { + "@data-type": "count", + "data": 175 + }, + { + "@data-type": "count", + "data": 176 + }, + { + "@data-type": "count", + "data": 177 + }, + { + "@data-type": "count", + "data": 178 + }, + { + "@data-type": "count", + "data": 179 + }, + { + "@data-type": "count", + "data": 180 + }, + { + "@data-type": "count", + "data": 181 + }, + { + "@data-type": "count", + "data": 182 + }, + { + "@data-type": "count", + "data": 183 + }, + { + "@data-type": "count", + "data": 184 + }, + { + "@data-type": "count", + "data": 185 + }, + { + "@data-type": "count", + "data": 186 + }, + { + "@data-type": "count", + "data": 187 + }, + { + "@data-type": "count", + "data": 188 + }, + { + "@data-type": "count", + "data": 189 + }, + { + "@data-type": "count", + "data": 190 + }, + { + "@data-type": "count", + "data": 191 + }, + { + "@data-type": "count", + "data": 192 + }, + { + "@data-type": "count", + "data": 193 + }, + { + "@data-type": "count", + "data": 194 + }, + { + "@data-type": "count", + "data": 195 + }, + { + "@data-type": "count", + "data": 196 + }, + { + "@data-type": "count", + "data": 197 + }, + { + "@data-type": "count", + "data": 198 + }, + { + "@data-type": "count", + "data": 199 + } + ] +} diff --git a/tests/btest/web-socket/gh-357-regression.py b/tests/btest/web-socket/gh-357-regression.py new file mode 100644 index 00000000..10a9fc4a --- /dev/null +++ b/tests/btest/web-socket/gh-357-regression.py @@ -0,0 +1,123 @@ +# @TEST-GROUP: web-socket +# +# @TEST-PORT: BROKER_WEB_SOCKET_PORT +# +# @TEST-EXEC: btest-bg-run node "broker-node --config-file=../node.cfg" +# @TEST-EXEC: btest-bg-run recv "python3 ../recv.py >recv.out" +# @TEST-EXEC: $SCRIPTS/wait-for-file recv/ready 15 || (btest-bg-wait -k 1 && false) +# +# @TEST-EXEC: btest-bg-run send "python3 ../send.py" +# +# @TEST-EXEC: $SCRIPTS/wait-for-file recv/done 30 || (btest-bg-wait -k 1 && false) +# @TEST-EXEC: btest-diff recv/recv.out +# +# @TEST-EXEC: btest-bg-wait -k 1 + +@TEST-START-FILE node.cfg + +caf { + logger { + file { + path = 'broker.log' + verbosity = 'debug' + excluded-components = [] + } + } +} +broker { + disable-ssl = true +} +topics = ["/test"] +verbose = true + +@TEST-END-FILE + +@TEST-START-FILE recv.py + +import asyncio, websockets, os, time, json, sys + +ws_port = os.environ['BROKER_WEB_SOCKET_PORT'].split('/')[0] + +ws_url = f'ws://localhost:{ws_port}/v1/messages/json' + +async def do_run(): + # Try up to 30 times. + connected = False + for i in range(30): + try: + ws = await websockets.connect(ws_url) + connected = True + # send filter and wait for ack + await ws.send('["/test"]') + ack_json = await ws.recv() + ack = json.loads(ack_json) + if not 'type' in ack or ack['type'] != 'ack': + print('*** unexpected ACK from server:') + print(ack_json) + sys.exit() + # tell btest to start the sender now + with open('ready', 'w') as f: + f.write('ready') + # the message must be valid JSON + msg_json = await ws.recv() + msg = json.loads(msg_json) + # pretty-print to stdout (redirected to recv.out) + print(json.dumps(msg, indent=2)) + # tell btest we're done + with open('done', 'w') as f: + f.write('done') + await ws.close() + sys.exit() + except: + if not connected: + print(f'failed to connect to {ws_url}, try again', file=sys.stderr) + time.sleep(1) + else: + sys.exit() +loop = asyncio.get_event_loop() +loop.run_until_complete(do_run()) + +@TEST-END-FILE + +@TEST-START-FILE send.py + +import asyncio, websockets, os, json, sys + +ws_port = os.environ['BROKER_WEB_SOCKET_PORT'].split('/')[0] + +ws_url = f'ws://localhost:{ws_port}/v1/messages/json' + +msg_data = [] + +for i in range(200): + msg_data.append({ + '@data-type': 'count', + 'data': i + }) + +# Message with timestamps using the local time zone. +msg = { + 'type': 'data-message', + 'topic': '/test', + '@data-type': "vector", + 'data': msg_data +} + +async def do_run(): + async with websockets.connect(ws_url) as ws: + await ws.send('[]') + await ws.recv() # wait for ACK + msg_str = json.dumps(msg, indent=2) + if len(msg_str) < 4096: + raise RuntimeError('message is too short') + # split the message into chunks of 4096 bytes + chunks = [msg_str[i:i+4096] for i in range(0, len(msg_str), 4096)] + await ws.send(chunks) # send as fragmented message + resp = await ws.recv() + print(resp) + await ws.close() + +loop = asyncio.get_event_loop() +loop.run_until_complete(do_run()) + +@TEST-END-FILE