raw
9987-embargoing         1 # https://stackoverflow.com/questions/1896918/running-unittest-with-typical-test-directory-structure
9978-bugfixes 2 import time
9987-embargoing 3 import unittest
9987-embargoing 4 import logging
9987-embargoing 5 from mock import Mock
9982-getdata 6 from lib.commands import DIRECT
9982-getdata 7 from lib.commands import GETDATA
9987-embargoing 8 from lib.station import Station
9982-getdata 9 from lib.state import State
9982-getdata 10 from lib.message import Message
9982-getdata 11 from lib.getdata import GetData
9982-getdata 12 from lib.order_buffer import OrderBuffer
9982-getdata 13 from lib.long_buffer import LongBuffer
9982-getdata 14 from collections import namedtuple
9982-getdata 15 import helper
9987-embargoing 16
9987-embargoing 17 class TestStation(unittest.TestCase):
9987-embargoing 18 def setUp(self):
9982-getdata 19 helper.setup()
9987-embargoing 20 logging.basicConfig(level=logging.DEBUG)
9982-getdata 21 self.station_socket = Mock()
9982-getdata 22 Options = namedtuple('Options', ['db_path',
9982-getdata 23 'address_table_path',
9982-getdata 24 'socket',
9982-getdata 25 'irc_ports',
9982-getdata 26 'udp_port',
9982-getdata 27 'channel_name',
9982-getdata 28 'password',
9982-getdata 29 'motd',
9982-getdata 30 'listen'])
9982-getdata 31 options = Options(
9982-getdata 32 None,
9982-getdata 33 None,
9982-getdata 34 self.station_socket,
9982-getdata 35 None,
9982-getdata 36 None,
9982-getdata 37 None,
9982-getdata 38 None,
9982-getdata 39 None,
9982-getdata 40 None
9982-getdata 41 )
9987-embargoing 42 self.station = Station(options)
9987-embargoing 43 self.station.deliver = Mock()
9987-embargoing 44 self.station.rebroadcast = Mock()
9987-embargoing 45 self.station.rebroadcast.return_value = "foobar"
9982-getdata 46 self.bob_state = State(Mock(), None)
9982-getdata 47 self.station.state.set_knob('nick', 'alice')
9982-getdata 48 self.bob_state.set_knob('nick', 'bob')
9982-getdata 49 self.setupBob()
9982-getdata 50 self.setupAlice()
9982-getdata 51
9982-getdata 52 def setupBob(self):
9982-getdata 53 self.station.state.add_peer('bob')
9982-getdata 54 self.station.state.add_key(
9982-getdata 55 'bob',
9982-getdata 56 '9h6wYndVjt8QpnIZOYb7KD2tYKCKw4rjlYg4LM1ODx1Qkr3qA0IuKNukkwKhQ4UP9ypMlhyPHa7AGD7NO7Ws5w=='
9982-getdata 57 )
9982-getdata 58 self.station.state.update_at({
9982-getdata 59 'handle': 'bob',
9982-getdata 60 'address': '127.0.0.1',
9982-getdata 61 'port': 8889
9982-getdata 62 })
9982-getdata 63
9982-getdata 64 def setupAlice(self):
9982-getdata 65 self.bob_state.add_peer('alice')
9982-getdata 66 self.bob_state.add_key(
9982-getdata 67 'alice',
9982-getdata 68 '9h6wYndVjt8QpnIZOYb7KD2tYKCKw4rjlYg4LM1ODx1Qkr3qA0IuKNukkwKhQ4UP9ypMlhyPHa7AGD7NO7Ws5w=='
9982-getdata 69 )
9982-getdata 70 self.bob_state.update_at({
9982-getdata 71 'handle': 'alice',
9982-getdata 72 'address': '127.0.0.1',
9982-getdata 73 'port': 8888
9982-getdata 74 })
9987-embargoing 75
9987-embargoing 76 def tearDown(self):
9987-embargoing 77 pass
9987-embargoing 78
9978-bugfixes 79 def test_clean_getdata_requests_clears_expired_hashes(self):
9978-bugfixes 80 self.station.getdata_requests["abc"] = time.time() - 15
9978-bugfixes 81 self.station.clean_getdata_requests()
9978-bugfixes 82 self.assertEqual(len(self.station.getdata_requests), 0)
9978-bugfixes 83
9978-bugfixes 84 def test_clean_getdata_requests_retains_valid_hashes(self):
9978-bugfixes 85 self.station.getdata_requests["abc"] = time.time()
9978-bugfixes 86 self.station.clean_getdata_requests()
9978-bugfixes 87 self.assertEqual(len(self.station.getdata_requests), 1)
9978-bugfixes 88
9987-embargoing 89 def test_embargo_bounce_ordering(self):
9982-getdata 90 self.skipTest("the tested code has been re-implemented")
9987-embargoing 91 peer1 = Mock()
9987-embargoing 92 peer1.handles = ["a", "b"]
9987-embargoing 93 peer2 = Mock()
9987-embargoing 94 peer2.handles = ["c", "d"]
9987-embargoing 95 low_bounce_message = Mock()
9987-embargoing 96 low_bounce_message.peer = peer1
9987-embargoing 97 low_bounce_message.bounces = 1
9987-embargoing 98 low_bounce_message.message_hash = "messagehash"
9987-embargoing 99 high_bounce_message = Mock()
9987-embargoing 100 high_bounce_message.peer = peer2
9987-embargoing 101 high_bounce_message.bounces = 2
9987-embargoing 102 high_bounce_message.message_hash = "messagehash"
9982-getdata 103 self.station.short_buffer = {
9987-embargoing 104 "messagehash": [
9987-embargoing 105 low_bounce_message,
9987-embargoing 106 high_bounce_message
9987-embargoing 107 ],
9987-embargoing 108 }
9987-embargoing 109 self.station.flush_hearsay_messages()
9987-embargoing 110 self.station.deliver.assert_called_once_with(low_bounce_message)
9987-embargoing 111 self.station.rebroadcast.assert_called_once_with(low_bounce_message)
9987-embargoing 112
9987-embargoing 113 def test_embargo_queue_cleared(self):
9982-getdata 114 self.skipTest("the embargo queue is now th short buffer")
9987-embargoing 115 peer = Mock()
9987-embargoing 116 peer.handles = ["a", "b"]
9987-embargoing 117 message = Mock()
9987-embargoing 118 message.speaker = "c"
9987-embargoing 119 message.peer = peer
9982-getdata 120 self.station.short_buffer = {
9987-embargoing 121 "messagehash": [
9987-embargoing 122 message
9987-embargoing 123 ],
9987-embargoing 124 }
9982-getdata 125 self.assertEqual(len(self.station.short_buffer), 1)
9987-embargoing 126 self.station.flush_hearsay_messages()
9982-getdata 127 self.assertEqual(len(self.station.short_buffer), 0)
9987-embargoing 128
9987-embargoing 129 def test_simple_hearsay_prefix(self):
9982-getdata 130 self.skipTest("this code has moved")
9987-embargoing 131 peer = Mock()
9987-embargoing 132 peer.handles = ["a", "b"]
9987-embargoing 133 message = Mock()
9987-embargoing 134 message.speaker = "c"
9987-embargoing 135 message.prefix = None
9987-embargoing 136 message.peer = peer
9982-getdata 137 self.station.short_buffer = {
9987-embargoing 138 "messagehash": [
9987-embargoing 139 message
9987-embargoing 140 ],
9987-embargoing 141 }
9987-embargoing 142 self.station.flush_hearsay_messages()
9987-embargoing 143 self.assertEqual(message.prefix, "c[a]")
9987-embargoing 144
9987-embargoing 145 def test_in_wot_hearsay_prefix_under_four(self):
9982-getdata 146 self.skipTest("the embargo queue is now th short buffer")
9987-embargoing 147 peer1 = Mock()
9987-embargoing 148 peer1.handles = ["a", "b"]
9987-embargoing 149 peer2 = Mock()
9987-embargoing 150 peer2.handles = ["d", "e"]
9987-embargoing 151 peer3 = Mock()
9987-embargoing 152 peer3.handles = ["f", "g"]
9987-embargoing 153 message_via_peer1 = Mock()
9987-embargoing 154 message_via_peer1.speaker = "c"
9987-embargoing 155 message_via_peer1.prefix = None
9987-embargoing 156 message_via_peer1.peer = peer1
9987-embargoing 157 message_via_peer1.bounces = 1
9987-embargoing 158 message_via_peer2 = Mock()
9987-embargoing 159 message_via_peer2.speaker = "c"
9987-embargoing 160 message_via_peer2.prefix = None
9987-embargoing 161 message_via_peer2.peer = peer2
9987-embargoing 162 message_via_peer2.bounces = 2
9987-embargoing 163 message_via_peer3 = Mock()
9987-embargoing 164 message_via_peer3.speaker = "c"
9987-embargoing 165 message_via_peer3.prefix = None
9987-embargoing 166 message_via_peer3.peer = peer3
9987-embargoing 167 message_via_peer3.bounces = 1
9982-getdata 168 self.station.short_buffer = {
9987-embargoing 169 "messagehash": [
9987-embargoing 170 message_via_peer1,
9987-embargoing 171 message_via_peer2,
9987-embargoing 172 message_via_peer3
9987-embargoing 173 ],
9987-embargoing 174 }
9987-embargoing 175 self.station.flush_hearsay_messages()
9987-embargoing 176 self.station.deliver.assert_called_once_with(message_via_peer1)
9987-embargoing 177 self.assertEqual(message_via_peer1.prefix, "c[a|d|f]")
9987-embargoing 178
9987-embargoing 179 def test_in_wot_hearsay_prefix_more_than_three(self):
9982-getdata 180 self.skipTest("the embargo queue is now th short buffer")
9987-embargoing 181 peer1 = Mock()
9987-embargoing 182 peer1.handles = ["a", "b"]
9987-embargoing 183 peer2 = Mock()
9987-embargoing 184 peer2.handles = ["d", "e"]
9987-embargoing 185 peer3 = Mock()
9987-embargoing 186 peer3.handles = ["f", "g"]
9987-embargoing 187 peer4 = Mock()
9987-embargoing 188 peer4.handles = ["f", "g"]
9987-embargoing 189 message_via_peer1 = Mock()
9987-embargoing 190 message_via_peer1.speaker = "c"
9987-embargoing 191 message_via_peer1.prefix = None
9987-embargoing 192 message_via_peer1.peer = peer1
9987-embargoing 193 message_via_peer1.bounces = 1
9987-embargoing 194 message_via_peer2 = Mock()
9987-embargoing 195 message_via_peer2.speaker = "c"
9987-embargoing 196 message_via_peer2.prefix = None
9987-embargoing 197 message_via_peer2.peer = peer2
9987-embargoing 198 message_via_peer2.bounces = 2
9987-embargoing 199 message_via_peer3 = Mock()
9987-embargoing 200 message_via_peer3.speaker = "c"
9987-embargoing 201 message_via_peer3.prefix = None
9987-embargoing 202 message_via_peer3.peer = peer3
9987-embargoing 203 message_via_peer3.bounces = 1
9987-embargoing 204 message_via_peer4 = Mock()
9987-embargoing 205 message_via_peer4.speaker = "c"
9987-embargoing 206 message_via_peer4.prefix = None
9987-embargoing 207 message_via_peer4.peer = peer4
9987-embargoing 208 message_via_peer4.bounces = 1
9982-getdata 209 self.station.short_buffer = {
9987-embargoing 210 "messagehash": [
9987-embargoing 211 message_via_peer1,
9987-embargoing 212 message_via_peer2,
9987-embargoing 213 message_via_peer3,
9987-embargoing 214 message_via_peer4
9987-embargoing 215 ],
9987-embargoing 216 }
9987-embargoing 217 self.station.flush_hearsay_messages()
9987-embargoing 218 self.station.deliver.assert_called_once_with(message_via_peer1)
9987-embargoing 219 self.assertEqual(message_via_peer1.prefix, "c[4]")
9982-getdata 220
9982-getdata 221 # this test occasionally fails
9982-getdata 222 def test_receive_getdata_request_for_existing_direct_message(self):
9982-getdata 223 self.skipTest("intermittent failure")
9982-getdata 224 # 'send' bob a couple of messages
9982-getdata 225 m1 = Message({
9982-getdata 226 'command': DIRECT,
9982-getdata 227 'handle': 'bob',
9982-getdata 228 'speaker': 'alice',
9982-getdata 229 'body': 'm1',
9982-getdata 230 'bounces': 0
9982-getdata 231 }, self.station.state)
9982-getdata 232
9982-getdata 233 m1.send()
9982-getdata 234
9982-getdata 235 m2 = Message({
9982-getdata 236 'command': DIRECT,
9982-getdata 237 'handle': 'bob',
9982-getdata 238 'speaker': 'alice',
9982-getdata 239 'body': 'm2',
9982-getdata 240 'bounces': 0,
9982-getdata 241 }, self.station.state)
9982-getdata 242
9982-getdata 243 m2.send()
9982-getdata 244
9982-getdata 245 # oops look's like bob didn't get the message
9982-getdata 246
9982-getdata 247 # build GETDATA black packet to retreive m1
9982-getdata 248 alice = self.bob_state.get_peer_by_handle('alice')
9982-getdata 249 bob = self.station.state.get_peer_by_handle('bob')
9982-getdata 250 gd_message = GetData(m2, self.bob_state)
9982-getdata 251 gd_message_bytes = gd_message.get_message_bytes(alice)
9982-getdata 252 gd_black_packet = Message.pack(bob, GETDATA, gd_message.bounces, gd_message_bytes)
9982-getdata 253
9982-getdata 254 # call handle_udp_data with GETDATA packet
9982-getdata 255 self.station.handle_udp_data([gd_black_packet, ['127.0.0.1', 8889]])
9982-getdata 256
9982-getdata 257 # build up the retry black packet to verify that it was sent
9982-getdata 258 retry_black_packet = Message.pack(bob, DIRECT, 0, m1.get_message_bytes(bob))
9982-getdata 259
9982-getdata 260 # assert retry is called and sends the correct message
9982-getdata 261 sent_message_black_packet = self.station_socket.sendto.call_args[0][0]
9982-getdata 262 sent_message = Message.unpack(bob, sent_message_black_packet, LongBuffer(), OrderBuffer(), self.station.state)
9982-getdata 263 self.assertEqual(sent_message.body, 'm1')