rex/spec/server/matching_engine_spec.rb

224 lines
6.0 KiB
Ruby
Raw Normal View History

2024-02-18 20:13:58 +01:00
# require "eventmachine"
RSpec.describe Rex::Server::MatchingEngine do
let(:inbox) { MockQueue.new }
let(:outbox) { MockQueue.new }
subject(:instance) { described_class.new(inbox, outbox) }
around do |example|
instance.start
example.run
instance.stop
end
before do
messages.each do |message|
inbox.push(message)
end
end
describe "order creation message" do
let(:messages) do
[
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 1,
price: 10,
quantity: 20,
side: :buy
)
]
end
it "sends order created event followed by order book update event" do
expect(outbox.messages).to eq([
Rex::Server::Messages::OrderCreatedEvent.new(1, 1, :buy, 20, 20, 10),
Rex::Server::Messages::OrderBookUpdateEvent.new(:buy, 10, 20)
])
end
context "when my order matches an order" do
let(:messages) do
[
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 1,
price: 10,
quantity: 20,
side: :buy
),
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 2,
price: 9,
quantity: 22,
side: :sell
)
]
end
it "returns order book updates, order fill updates and trades" do
expect(outbox.messages).to eq([
Rex::Server::Messages::OrderCreatedEvent.new(id: 1, user_id: 1, side: :buy, quantity: 20, remaining_quantity: 20, price: 10),
Rex::Server::Messages::OrderBookUpdateEvent.new(side: :buy, price: 10, quantity: 20),
Rex::Server::Messages::OrderCreatedEvent.new(id: 2, user_id: 2, side: :sell, quantity: 22, remaining_quantity: 22, price: 9),
Rex::Server::Messages::OrderBookUpdateEvent.new(side: :sell, price: 9, quantity: 22),
Rex::Server::Messages::TradeEvent.new(id: 1, price: 9, quantity: 20),
Rex::Server::Messages::OrderFillEvent.new(id: 1, user_id: 1, price: 10, side: :buy, remaining_quantity: 0),
Rex::Server::Messages::OrderFillEvent.new(id: 2, user_id: 2, price: 9, side: :sell, remaining_quantity: 2),
Rex::Server::Messages::OrderBookUpdateEvent.new(side: :buy, price: 10, quantity: 0),
Rex::Server::Messages::OrderBookUpdateEvent.new(side: :sell, price: 9, quantity: 2)
])
end
end
end
describe "cancel order request" do
context "when order is not existent" do
let(:messages) do
[
Rex::Server::Messages::CancelOrderRequest.new(1, 1)
]
end
it "returns nothing" do
expect(outbox.messages).to be_empty
end
end
context "when order exists" do
let(:messages) do
[
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 1,
price: 10,
quantity: 20,
side: :buy
),
Rex::Server::Messages::CancelOrderRequest.new(1, 1)
]
end
it "returns a cancelled order event and updates the order book" do
expect(outbox.messages.last(2)).to eq([
Rex::Server::Messages::OrderCancelledEvent.new(id: 1, user_id: 1, side: :buy, remaining_quantity: 20, price: 10),
Rex::Server::Messages::OrderBookUpdateEvent.new(side: :buy, price: 10, quantity: 0)
])
end
end
end
describe "fetch order book request" do
let(:messages) do
[
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 1,
price: 10,
quantity: 20,
side: :buy
),
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 2,
price: 11,
quantity: 22,
side: :sell
),
Rex::Server::Messages::FetchOrderBookRequest.new(3)
]
end
it "returns a list limit order book updates" do
expect(outbox.messages.last(2)).to eq([
Rex::Server::Messages::OrderBookFetchEvent.new(
3,
:buy,
10,
20
),
Rex::Server::Messages::OrderBookFetchEvent.new(
3,
:sell,
11,
22
)
])
end
end
describe "fetch trades request" do
context "when no trades exist" do
let(:messages) do
[
Rex::Server::Messages::FetchTradesRequest.new(1)
]
end
it "returns nothing" do
expect(outbox.messages).to be_empty
end
end
context "when trades exist" do
let(:messages) do
[
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 1,
price: 10,
quantity: 15,
side: :buy
),
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 2,
price: 10,
quantity: 15,
side: :sell
),
Rex::Server::Messages::FetchTradesRequest.new(1)
]
end
it "returns trade fetch events" do
expect(outbox.messages.last(1)).to eq([
Rex::Server::Messages::TradeFetchEvent.new(
id: 1,
user_id: 1,
price: 10,
quantity: 15
)
])
end
end
end
describe "fetch orders request" do
context "when user does not have any orders" do
let(:messages) do
[
Rex::Server::Messages::FetchOrdersRequest.new(1)
]
end
it "returns nothing" do
expect(outbox.messages).to be_empty
end
end
context "when user has orders" do
let(:messages) do
[
Rex::Server::Messages::CreateOrderRequest.new(
user_id: 1,
price: 10,
quantity: 15,
side: :sell
),
Rex::Server::Messages::FetchOrdersRequest.new(1)
]
end
it "returns the orders" do
expect(outbox.messages.last).to eq(
Rex::Server::Messages::OrderFetchEvent.new(id: 1, user_id: 1, side: :sell, quantity: 15, remaining_quantity: 15, price: 10)
)
end
end
end
end