-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8808ee8
commit 7e4ddf2
Showing
6 changed files
with
107 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
oKrH73YD4ISQ0wzLNyPBeGp2OK7JTKghDfJe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,21 @@ | ||
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 | ||
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,15 +30,18 @@ def setUp(self): | |
User.objects.create_superuser(self.su_name, "[email protected]", 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) | ||
self.assertEqual(response.status_code, 302) | ||
|
||
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 @@ def get_robot_auth(self, robot_index): | |
} | ||
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 @@ def create_robot(self, robot_index): | |
) | ||
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 @@ def test_cache_market(self): | |
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.assertGreater( | ||
usd.exchange_rate, 0, "Exchange rate is not higher than zero" | ||
) | ||
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.assertIsInstance( | ||
usd.timestamp, datetime, "External price timestamp is not a datetime" | ||
) | ||
|
||
def test_create_order( | ||
|
@@ -147,32 +165,34 @@ def test_create_order( | |
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( | ||
data["type"], Order.Types.BUY, "Buy order is not of type value BUY" | ||
) | ||
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 @@ def test_create_order( | |
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, | ||
) |