Add LND mock up classes

This commit is contained in:
Reckless_Satoshi
2023-11-06 23:13:23 +00:00
committed by Reckless_Satoshi
parent 09215be8a9
commit 4270f2d0a2
6 changed files with 107 additions and 45 deletions

View File

@ -22,7 +22,7 @@ jobs:
strategy: strategy:
max-parallel: 4 max-parallel: 4
matrix: matrix:
python-version: ["3.11.6"] # , "3.12"] python-version: ["3.11.6", "3.12"]
services: services:
db: db:
@ -63,6 +63,7 @@ jobs:
- name: 'Create .env File' - name: 'Create .env File'
run: | run: |
mv .env-sample .env mv .env-sample .env
sed -i "s/USE_TOR='True'/USE_TOR='False'/" .env
- name: 'Wait for PostgreSQL to become ready' - name: 'Wait for PostgreSQL to become ready'
run: | run: |

View File

@ -71,8 +71,6 @@ class LNDNode:
5: "Insufficient local balance.", 5: "Insufficient local balance.",
} }
is_testnet = lightningstub.GetInfo(lnrpc.GetInfoRequest()).testnet
@classmethod @classmethod
def get_version(cls): def get_version(cls):
try: try:
@ -93,8 +91,8 @@ class LNDNode:
@classmethod @classmethod
def estimate_fee(cls, amount_sats, target_conf=2, min_confs=1): def estimate_fee(cls, amount_sats, target_conf=2, min_confs=1):
"""Returns estimated fee for onchain payouts""" """Returns estimated fee for onchain payouts"""
is_testnet = lightningstub.GetInfo(lnrpc.GetInfoRequest()).testnet
if cls.is_testnet: if is_testnet:
dummy_address = "tb1qehyqhruxwl2p5pt52k6nxj4v8wwc3f3pg7377x" dummy_address = "tb1qehyqhruxwl2p5pt52k6nxj4v8wwc3f3pg7377x"
else: else:
dummy_address = "bc1qgxwaqe4m9mypd7ltww53yv3lyxhcfnhzzvy5j3" dummy_address = "bc1qgxwaqe4m9mypd7ltww53yv3lyxhcfnhzzvy5j3"

0
tests/mocks/__init__.py Normal file
View File

32
tests/mocks/lnd.py Normal file
View File

@ -0,0 +1,32 @@
from unittest.mock import MagicMock
# Mock up of LND gRPC responses
class MockLightningStub:
def GetInfo(self, request):
response = MagicMock()
# Set the testnet attribute to True for testing purposes
response.testnet = True
return response
def EstimateFee(self, request):
response = MagicMock()
response.fee_sat = 1500
response.sat_per_vbyte = 13
return response
class MockInvoicesStub:
pass
class MockRouterStub:
pass
class MockSignerStub:
pass
class MockVersionerStub:
pass

View File

@ -0,0 +1 @@
oKrH73YD4ISQ0wzLNyPBeGp2OK7JTKghDfJe

View File

@ -1,6 +1,7 @@
import json import json
from datetime import datetime from datetime import datetime
from decimal import Decimal from decimal import Decimal
from unittest.mock import patch
from decouple import config from decouple import config
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -8,6 +9,13 @@ from django.test import Client, TestCase
from api.models import Currency, Order from api.models import Currency, Order
from api.tasks import cache_market from api.tasks import cache_market
from tests.mocks.lnd import (
MockInvoicesStub,
MockLightningStub,
MockRouterStub,
MockSignerStub,
MockVersionerStub,
)
class TradeTest(TestCase): class TradeTest(TestCase):
@ -22,6 +30,9 @@ class TradeTest(TestCase):
User.objects.create_superuser(self.su_name, "super@user.com", self.su_pass) User.objects.create_superuser(self.su_name, "super@user.com", self.su_pass)
def test_login_superuser(self): def test_login_superuser(self):
"""
Test logging in as a superuser.
"""
path = "/coordinator/login/" path = "/coordinator/login/"
data = {"username": self.su_name, "password": self.su_pass} data = {"username": self.su_name, "password": self.su_pass}
response = self.client.post(path, data) response = self.client.post(path, data)
@ -29,8 +40,8 @@ class TradeTest(TestCase):
def get_robot_auth(self, robot_index): def get_robot_auth(self, robot_index):
""" """
Crates an AUTH header that embeds token, pub_key and enc_priv_key into a single string Create an AUTH header that embeds token, pub_key, and enc_priv_key into a single string
just as requested by the robosats token middleware. as requested by the robosats token middleware.
""" """
with open(f"tests/robots/{robot_index}/b91_token", "r") as file: with open(f"tests/robots/{robot_index}/b91_token", "r") as file:
b91_token = file.read() b91_token = file.read()
@ -44,24 +55,14 @@ class TradeTest(TestCase):
} }
return headers, pub_key, enc_priv_key return headers, pub_key, enc_priv_key
def create_robot(self, robot_index): def assert_robot(self, response, pub_key, enc_priv_key, expected_nickname):
"""
Creates the robots in /tests/robots/{robot_index}
"""
path = "/api/robot/"
headers, pub_key, enc_priv_key = self.get_robot_auth(robot_index)
response = self.client.get(path, **headers)
data = json.loads(response.content.decode()) data = json.loads(response.content.decode())
with open(f"tests/robots/{robot_index}/nickname", "r") as file:
expected_nickname = file.read()
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual( self.assertEqual(
data["nickname"], data["nickname"],
expected_nickname, expected_nickname,
f"Robot {robot_index} created nickname is not MyopicRacket333", "Robot created nickname is not MyopicRacket333",
) )
self.assertEqual( self.assertEqual(
data["public_key"], pub_key, "Returned public Kky does not match" data["public_key"], pub_key, "Returned public Kky does not match"
@ -86,6 +87,20 @@ class TradeTest(TestCase):
) )
self.assertEqual(data["earned_rewards"], 0, "The new robot's rewards are not 0") self.assertEqual(data["earned_rewards"], 0, "The new robot's rewards are not 0")
def create_robot(self, robot_index):
"""
Creates the robots in /tests/robots/{robot_index}
"""
path = "/api/robot/"
headers, pub_key, enc_priv_key = self.get_robot_auth(robot_index)
response = self.client.get(path, **headers)
with open(f"tests/robots/{robot_index}/nickname", "r") as file:
expected_nickname = file.read()
self.assert_robot(response, pub_key, enc_priv_key, expected_nickname)
def test_create_robots(self): def test_create_robots(self):
""" """
Creates two robots to be used in the trade tests Creates two robots to be used in the trade tests
@ -97,13 +112,16 @@ class TradeTest(TestCase):
cache_market() cache_market()
usd = Currency.objects.get(id=1) usd = Currency.objects.get(id=1)
self.assertTrue( self.assertIsInstance(
isinstance(usd.exchange_rate, Decimal), "Exchange rate is not decimal" usd.exchange_rate,
Decimal,
f"Exchange rate is not a Decimal. Got {type(usd.exchange_rate)}",
) )
self.assertLess(0, usd.exchange_rate, "Exchange rate is not higher than zero") self.assertGreater(
self.assertTrue( usd.exchange_rate, 0, "Exchange rate is not higher than zero"
isinstance(usd.timestamp, datetime), )
"Externa price timestamp is not datetime", self.assertIsInstance(
usd.timestamp, datetime, "External price timestamp is not a datetime"
) )
def test_create_order( def test_create_order(
@ -147,18 +165,20 @@ class TradeTest(TestCase):
data = json.loads(response.content.decode()) data = json.loads(response.content.decode())
# Checks # Checks
self.assertTrue(isinstance(data["id"], int), "Order ID is not an integer") self.assertIsInstance(data["id"], int, "Order ID is not an integer")
self.assertEqual( self.assertEqual(
data["status"], data["status"],
Order.Status.WFB, Order.Status.WFB,
"Newly created order status is not 'Waiting for maker bond'", "Newly created order status is not 'Waiting for maker bond'",
) )
self.assertTrue( self.assertIsInstance(
isinstance(datetime.fromisoformat(data["created_at"]), datetime), datetime.fromisoformat(data["created_at"]),
datetime,
"Order creation timestamp is not datetime", "Order creation timestamp is not datetime",
) )
self.assertTrue( self.assertIsInstance(
isinstance(datetime.fromisoformat(data["expires_at"]), datetime), datetime.fromisoformat(data["expires_at"]),
datetime,
"Order expiry time is not datetime", "Order expiry time is not datetime",
) )
self.assertEqual( self.assertEqual(
@ -166,13 +186,13 @@ class TradeTest(TestCase):
) )
self.assertEqual(data["currency"], 1, "Order for USD is not of currency USD") self.assertEqual(data["currency"], 1, "Order for USD is not of currency USD")
self.assertIsNone( self.assertIsNone(
data["amount"], "Order with range has a non null simple amount" data["amount"], "Order with range has a non-null simple amount"
) )
self.assertTrue(data["has_range"], "Order with range has a False has_range") self.assertTrue(data["has_range"], "Order with range has a False has_range")
self.assertEqual( self.assertAlmostEqual(
float(data["min_amount"]), min_amount, "Order min amount does not match" float(data["min_amount"]), min_amount, "Order min amount does not match"
) )
self.assertEqual( self.assertAlmostEqual(
float(data["max_amount"]), max_amount, "Order max amount does not match" float(data["max_amount"]), max_amount, "Order max amount does not match"
) )
self.assertEqual( self.assertEqual(
@ -185,31 +205,41 @@ class TradeTest(TestCase):
escrow_duration, escrow_duration,
"Order escrow duration does not match", "Order escrow duration does not match",
) )
self.assertEqual( self.assertAlmostEqual(
float(data["bond_size"]), bond_size, "Order bond size does not match" float(data["bond_size"]), bond_size, "Order bond size does not match"
) )
self.assertEqual( self.assertAlmostEqual(
float(data["latitude"]), latitude, "Order latitude does not match" float(data["latitude"]), latitude, "Order latitude does not match"
) )
self.assertEqual( self.assertAlmostEqual(
float(data["longitude"]), longitude, "Order longitude does not match" float(data["longitude"]), longitude, "Order longitude does not match"
) )
self.assertEqual( self.assertAlmostEqual(
float(data["premium"]), premium, "Order premium does not match" float(data["premium"]), premium, "Order premium does not match"
) )
self.assertFalse( self.assertFalse(
data["is_explicit"], "Relative pricing order has True is_explicit" data["is_explicit"], "Relative pricing order has True is_explicit"
) )
self.assertIsNone( self.assertIsNone(
data["satoshis"], "Relative pricing order has non null Satoshis" data["satoshis"], "Relative pricing order has non-null Satoshis"
) )
self.assertIsNone(data["taker"], "New order's taker is not null") self.assertIsNone(data["taker"], "New order's taker is not null")
with open(f"tests/robots/{robot_index}/nickname", "r") as file: @patch("api.lightning.lightning_pb2_grpc.LightningStub", MockLightningStub)
maker_nickname = file.read() @patch("api.lightning.invoices_pb2_grpc.InvoicesStub", MockInvoicesStub)
maker_id = User.objects.get(username=maker_nickname).id @patch("api.lightning.router_pb2_grpc.RouterStub", MockRouterStub)
self.assertEqual( @patch("api.lightning.signer_pb2_grpc.SignerStub", MockSignerStub)
data["maker"], @patch("api.lightning.verrpc_pb2_grpc.VersionerStub", MockVersionerStub)
maker_id, def test_maker_bond_locked(self):
"Maker user ID is not that of robot index {robot_index}", self.test_create_order(
robot_index=1,
payment_method="Cash F2F",
min_amount=80,
max_amount=500,
premium=5,
public_duration=86000,
escrow_duration=8000,
bond_size=2,
latitude=0,
longitude=0,
) )