mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 19:06:26 +00:00
Add LND mock up classes
This commit is contained in:
parent
09215be8a9
commit
4270f2d0a2
3
.github/workflows/django-test.yml
vendored
3
.github/workflows/django-test.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
strategy:
|
||||
max-parallel: 4
|
||||
matrix:
|
||||
python-version: ["3.11.6"] # , "3.12"]
|
||||
python-version: ["3.11.6", "3.12"]
|
||||
|
||||
services:
|
||||
db:
|
||||
@ -63,6 +63,7 @@ jobs:
|
||||
- name: 'Create .env File'
|
||||
run: |
|
||||
mv .env-sample .env
|
||||
sed -i "s/USE_TOR='True'/USE_TOR='False'/" .env
|
||||
|
||||
- name: 'Wait for PostgreSQL to become ready'
|
||||
run: |
|
||||
|
@ -71,8 +71,6 @@ class LNDNode:
|
||||
5: "Insufficient local balance.",
|
||||
}
|
||||
|
||||
is_testnet = lightningstub.GetInfo(lnrpc.GetInfoRequest()).testnet
|
||||
|
||||
@classmethod
|
||||
def get_version(cls):
|
||||
try:
|
||||
@ -93,8 +91,8 @@ class LNDNode:
|
||||
@classmethod
|
||||
def estimate_fee(cls, amount_sats, target_conf=2, min_confs=1):
|
||||
"""Returns estimated fee for onchain payouts"""
|
||||
|
||||
if cls.is_testnet:
|
||||
is_testnet = lightningstub.GetInfo(lnrpc.GetInfoRequest()).testnet
|
||||
if is_testnet:
|
||||
dummy_address = "tb1qehyqhruxwl2p5pt52k6nxj4v8wwc3f3pg7377x"
|
||||
else:
|
||||
dummy_address = "bc1qgxwaqe4m9mypd7ltww53yv3lyxhcfnhzzvy5j3"
|
||||
|
0
tests/mocks/__init__.py
Normal file
0
tests/mocks/__init__.py
Normal file
32
tests/mocks/lnd.py
Normal file
32
tests/mocks/lnd.py
Normal 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
|
@ -0,0 +1 @@
|
||||
oKrH73YD4ISQ0wzLNyPBeGp2OK7JTKghDfJe
|
@ -1,6 +1,7 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from unittest.mock import patch
|
||||
|
||||
from decouple import config
|
||||
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.tasks import cache_market
|
||||
from tests.mocks.lnd import (
|
||||
MockInvoicesStub,
|
||||
MockLightningStub,
|
||||
MockRouterStub,
|
||||
MockSignerStub,
|
||||
MockVersionerStub,
|
||||
)
|
||||
|
||||
|
||||
class TradeTest(TestCase):
|
||||
@ -22,6 +30,9 @@ class TradeTest(TestCase):
|
||||
User.objects.create_superuser(self.su_name, "super@user.com", self.su_pass)
|
||||
|
||||
def test_login_superuser(self):
|
||||
"""
|
||||
Test logging in as a superuser.
|
||||
"""
|
||||
path = "/coordinator/login/"
|
||||
data = {"username": self.su_name, "password": self.su_pass}
|
||||
response = self.client.post(path, data)
|
||||
@ -29,8 +40,8 @@ class TradeTest(TestCase):
|
||||
|
||||
def get_robot_auth(self, robot_index):
|
||||
"""
|
||||
Crates an AUTH header that embeds token, pub_key and enc_priv_key into a single string
|
||||
just as requested by the robosats token middleware.
|
||||
Create an AUTH header that embeds token, pub_key, and enc_priv_key into a single string
|
||||
as requested by the robosats token middleware.
|
||||
"""
|
||||
with open(f"tests/robots/{robot_index}/b91_token", "r") as file:
|
||||
b91_token = file.read()
|
||||
@ -44,24 +55,14 @@ class TradeTest(TestCase):
|
||||
}
|
||||
return headers, pub_key, enc_priv_key
|
||||
|
||||
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)
|
||||
def assert_robot(self, response, pub_key, enc_priv_key, expected_nickname):
|
||||
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(
|
||||
data["nickname"],
|
||||
expected_nickname,
|
||||
f"Robot {robot_index} created nickname is not MyopicRacket333",
|
||||
"Robot created nickname is not MyopicRacket333",
|
||||
)
|
||||
self.assertEqual(
|
||||
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")
|
||||
|
||||
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):
|
||||
"""
|
||||
Creates two robots to be used in the trade tests
|
||||
@ -97,13 +112,16 @@ class TradeTest(TestCase):
|
||||
cache_market()
|
||||
|
||||
usd = Currency.objects.get(id=1)
|
||||
self.assertTrue(
|
||||
isinstance(usd.exchange_rate, Decimal), "Exchange rate is not decimal"
|
||||
self.assertIsInstance(
|
||||
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.assertTrue(
|
||||
isinstance(usd.timestamp, datetime),
|
||||
"Externa price timestamp is not datetime",
|
||||
self.assertGreater(
|
||||
usd.exchange_rate, 0, "Exchange rate is not higher than zero"
|
||||
)
|
||||
self.assertIsInstance(
|
||||
usd.timestamp, datetime, "External price timestamp is not a datetime"
|
||||
)
|
||||
|
||||
def test_create_order(
|
||||
@ -147,18 +165,20 @@ class TradeTest(TestCase):
|
||||
data = json.loads(response.content.decode())
|
||||
|
||||
# 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(
|
||||
data["status"],
|
||||
Order.Status.WFB,
|
||||
"Newly created order status is not 'Waiting for maker bond'",
|
||||
)
|
||||
self.assertTrue(
|
||||
isinstance(datetime.fromisoformat(data["created_at"]), datetime),
|
||||
self.assertIsInstance(
|
||||
datetime.fromisoformat(data["created_at"]),
|
||||
datetime,
|
||||
"Order creation timestamp is not datetime",
|
||||
)
|
||||
self.assertTrue(
|
||||
isinstance(datetime.fromisoformat(data["expires_at"]), datetime),
|
||||
self.assertIsInstance(
|
||||
datetime.fromisoformat(data["expires_at"]),
|
||||
datetime,
|
||||
"Order expiry time is not datetime",
|
||||
)
|
||||
self.assertEqual(
|
||||
@ -166,13 +186,13 @@ class TradeTest(TestCase):
|
||||
)
|
||||
self.assertEqual(data["currency"], 1, "Order for USD is not of currency USD")
|
||||
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.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
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"
|
||||
)
|
||||
self.assertEqual(
|
||||
@ -185,31 +205,41 @@ class TradeTest(TestCase):
|
||||
escrow_duration,
|
||||
"Order escrow duration does not match",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
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"
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
float(data["longitude"]), longitude, "Order longitude does not match"
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
float(data["premium"]), premium, "Order premium does not match"
|
||||
)
|
||||
self.assertFalse(
|
||||
data["is_explicit"], "Relative pricing order has True is_explicit"
|
||||
)
|
||||
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")
|
||||
|
||||
with open(f"tests/robots/{robot_index}/nickname", "r") as file:
|
||||
maker_nickname = file.read()
|
||||
maker_id = User.objects.get(username=maker_nickname).id
|
||||
self.assertEqual(
|
||||
data["maker"],
|
||||
maker_id,
|
||||
"Maker user ID is not that of robot index {robot_index}",
|
||||
@patch("api.lightning.lightning_pb2_grpc.LightningStub", MockLightningStub)
|
||||
@patch("api.lightning.invoices_pb2_grpc.InvoicesStub", MockInvoicesStub)
|
||||
@patch("api.lightning.router_pb2_grpc.RouterStub", MockRouterStub)
|
||||
@patch("api.lightning.signer_pb2_grpc.SignerStub", MockSignerStub)
|
||||
@patch("api.lightning.verrpc_pb2_grpc.VersionerStub", MockVersionerStub)
|
||||
def test_maker_bond_locked(self):
|
||||
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,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user