You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

123 lines
4.9 KiB

import os
import json
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, Deferred
from twisted.trial import unittest
from autobahn.twisted.websocket import WebSocketClientFactory, \
WebSocketClientProtocol, connectWS, listenWS
from jmbase import get_log, hextobin
from jmbase.support import get_free_tcp_ports
from jmclient import (JmwalletdWebSocketServerFactory,
JmwalletdWebSocketServerProtocol)
from jmclient.auth import JMTokenAuthority
from jmbitcoin import CTransaction
testdir = os.path.dirname(os.path.realpath(__file__))
jlog = get_log()
# example transaction for sending a notification with:
test_tx_hex_1 = "02000000000102578770b2732aed421ffe62d54fd695cf281ca336e4f686d2adbb2e8c3bedb2570000000000ffffffff4719a259786b4237f92460629181edcc3424419592529103143090f07d85ec330100000000ffffffff0324fd9b0100000000160014d38fa4a6ac8db7495e5e2b5d219dccd412dd9bae24fd9b0100000000160014564aead56de8f4d445fc5b74a61793b5c8a819667af6c208000000001600146ec55c2e1d1a7a868b5ec91822bf40bba842bac502473044022078f8106a5645cc4afeef36d4addec391a5b058cc51053b42c89fcedf92f4db1002200cdf1b66a922863fba8dc1b1b1a0dce043d952fa14dcbe86c427fda25e930a53012102f1f750bfb73dbe4c7faec2c9c301ad0e02176cd47bcc909ff0a117e95b2aad7b02483045022100b9a6c2295a1b0f7605381d416f6ed8da763bd7c20f2402dd36b62dd9dd07375002207d40eaff4fc6ee219a7498abfab6bdc54b7ce006ac4b978b64bff960fbf5f31e012103c2a7d6e44acdbd503c578ec7d1741a44864780be0186e555e853eee86e06f11f00000000"
test_tx_hex_txid = "ca606efc5ba8f6669ba15e9262e5d38e745345ea96106d5a919688d1ff0da0cc"
# Shared JWT token authority for test:
token_authority = JMTokenAuthority()
class ServerTProtocol(JmwalletdWebSocketServerProtocol):
def onMessage(self, payload, isBinary):
super().onMessage(payload, isBinary)
self.factory.on_message_deferred.callback(None)
class ClientTProtocol(WebSocketClientProtocol):
"""
Simple client that connects to a WebSocket server, send a HELLO
message every 2 seconds and print everything it receives.
"""
ACCESS_TOKEN = token_authority.issue()["token"].encode("utf8")
def sendAuth(self):
"""Our server will not broadcast to us unless we authenticate."""
self.sendMessage(self.ACCESS_TOKEN)
def onOpen(self):
# auth on startup
self.sendAuth()
# for test, monitor how many times we
# were notified.
self.factory.notifs = 0
def onMessage(self, payload, isBinary):
if not isBinary:
payload = payload.decode("utf-8")
jlog.info("Text message received: {}".format(payload))
self.factory.notifs += 1
self.factory.on_message_deferred.callback(None)
# ensure we got the transaction message expected:
deser_notif = json.loads(payload)
assert deser_notif["txid"] == test_tx_hex_txid
assert deser_notif["txdetails"]["txid"] == test_tx_hex_txid
class WebsocketTestBase(object):
""" This tests that a websocket client can connect to our
websocket subscription service
"""
# the port for the ws (auto)
wss_port = None
def setUp(self):
if self.wss_port is None:
free_ports = get_free_tcp_ports(1)
self.wss_port = free_ports[0]
self.wss_url = "ws://127.0.0.1:" + str(self.wss_port)
self.wss_factory = JmwalletdWebSocketServerFactory(self.wss_url, token_authority)
self.wss_factory.protocol = ServerTProtocol
self.wss_factory.on_message_deferred = Deferred()
self.listeningport = listenWS(self.wss_factory, contextFactory=None)
self.test_tx = CTransaction.deserialize(hextobin(test_tx_hex_1))
def stopListening(self):
return self.listeningport.stopListening()
@inlineCallbacks
def do_test(self):
self.client_factory = WebSocketClientFactory("ws://127.0.0.1:"+str(self.wss_port))
self.client_factory.on_message_deferred = Deferred()
self.client_factory.protocol = ClientTProtocol
# keep track of the connector object so we can close it manually:
self.client_connector = connectWS(self.client_factory)
# wait on server to receive message
yield self.wss_factory.on_message_deferred
yield self.fire_tx_notif()
# wait on client to receive message
yield self.client_factory.on_message_deferred
assert self.client_factory.notifs == 1
@inlineCallbacks
def fire_tx_notif(self):
yield self.wss_factory.sendTxNotification(
self.test_tx, test_tx_hex_txid)
def tearDown(self):
reactor.disconnectAll()
for dc in reactor.getDelayedCalls():
if not dc.cancelled:
dc.cancel()
self.client_connector.disconnect()
return self.stopListening()
class TrialTestWS(WebsocketTestBase, unittest.TestCase):
@inlineCallbacks
def test_basic_notification(self):
yield self.do_test()