From 2b9c82c4f6bf208a3d6648d7cc13b1f6c1b73616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20K=C3=A4chele?= Date: Sun, 29 Oct 2023 00:01:31 +0200 Subject: [PATCH] Add stack overflow based test case for matcher implementation --- lib/rex/matcher.rb | 2 ++ spec/factories/orders.rb | 1 + spec/matcher_spec.rb | 48 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/lib/rex/matcher.rb b/lib/rex/matcher.rb index 9fe34f2..bbd6d60 100644 --- a/lib/rex/matcher.rb +++ b/lib/rex/matcher.rb @@ -28,6 +28,8 @@ module Rex return trades if highest_buy_order.nil? || lowest_sell_order.nil? end + + trades end private diff --git a/spec/factories/orders.rb b/spec/factories/orders.rb index f61c2a0..85fc021 100644 --- a/spec/factories/orders.rb +++ b/spec/factories/orders.rb @@ -7,5 +7,6 @@ FactoryBot.define do sequence(:is_buy) { |i| (i % 2).zero? } sequence(:price) { 100 } sequence(:amount) { 20 } + remaining_amount { amount } end end diff --git a/spec/matcher_spec.rb b/spec/matcher_spec.rb index c75c8b9..3f504eb 100644 --- a/spec/matcher_spec.rb +++ b/spec/matcher_spec.rb @@ -48,5 +48,53 @@ RSpec.describe Rex::Matcher do expect(instance.match(Rex::OrderBook.new)).to eq([]) end end + + # https://stackoverflow.com/a/18524231/3200224 + # Testing a common example with a proven to be correct solution + context "stack overflow scenario" do + let(:order_1) { build(:order, price: 2030, is_buy: false, amount: 100) } + let(:order_2) { build(:order, price: 2025, is_buy: false, amount: 100) } + let(:order_3) { build(:order, price: 2030, is_buy: false, amount: 200) } + let(:order_4) { build(:order, price: 2015, is_buy: true, amount: 100) } + let(:order_5) { build(:order, price: 2020, is_buy: true, amount: 200) } + let(:order_6) { build(:order, price: 2015, is_buy: true, amount: 200) } + + let(:crossing_order) { build(:order, is_buy: true, amount: 250, price: 2035) } + + before do + order_book.add_order(order_1) + order_book.add_order(order_2) + order_book.add_order(order_3) + order_book.add_order(order_4) + order_book.add_order(order_5) + order_book.add_order(order_6) + + order_book.add_order(crossing_order) + end + + it "matches the orders accordingly" do + trades = instance.match(order_book) + + expect(trades.length).to eq(3) + + expect(trades[0].id).to eq(1) + expect(trades[0].price).to eq(2025) + expect(trades[0].amount).to eq(100) + expect(trades[0].buy_order).to eq(crossing_order) + expect(trades[0].sell_order).to eq(order_2) + + expect(trades[1].id).to eq(2) + expect(trades[1].price).to eq(2030) + expect(trades[1].amount).to eq(100) + expect(trades[1].buy_order).to eq(crossing_order) + expect(trades[1].sell_order).to eq(order_1) + + expect(trades[2].id).to eq(3) + expect(trades[2].price).to eq(2030) + expect(trades[2].amount).to eq(50) + expect(trades[2].buy_order).to eq(crossing_order) + expect(trades[2].sell_order).to eq(order_3) + end + end end end