Finish limit implementation
This commit is contained in:
parent
b3b31427db
commit
c16e705a4c
@ -1,5 +1,10 @@
|
|||||||
module Rex
|
module Rex
|
||||||
class Limit
|
class Limit
|
||||||
|
attr_reader(
|
||||||
|
:first_order,
|
||||||
|
:last_order,
|
||||||
|
:price
|
||||||
|
)
|
||||||
def initialize(price)
|
def initialize(price)
|
||||||
@price = price
|
@price = price
|
||||||
@first_order = nil
|
@first_order = nil
|
||||||
@ -11,13 +16,24 @@ module Rex
|
|||||||
@first_order
|
@first_order
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def count
|
||||||
|
@order_count
|
||||||
|
end
|
||||||
|
|
||||||
def pop_first_order
|
def pop_first_order
|
||||||
|
return nil if empty?
|
||||||
|
|
||||||
order = @first_order
|
order = @first_order
|
||||||
@first_order = @first_order.next_order
|
@first_order = @first_order.next_order
|
||||||
|
@first_order&.previous_order = nil
|
||||||
|
|
||||||
if @first_order.nil?
|
if @first_order.nil?
|
||||||
@last_order = nil
|
@last_order = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
order.next_order = nil
|
||||||
|
order.previous_order = nil
|
||||||
|
|
||||||
@order_count -= 1
|
@order_count -= 1
|
||||||
order
|
order
|
||||||
end
|
end
|
||||||
@ -27,11 +43,35 @@ module Rex
|
|||||||
@first_order = order
|
@first_order = order
|
||||||
else
|
else
|
||||||
@last_order.next_order = order
|
@last_order.next_order = order
|
||||||
|
order.previous_order = @last_order
|
||||||
end
|
end
|
||||||
@last_order = order
|
@last_order = order
|
||||||
@order_count += 1
|
@order_count += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Assumption when calling: the order is part of the limit
|
||||||
|
def remove_order(order)
|
||||||
|
if @first_order == order
|
||||||
|
@first_order = order.next_order
|
||||||
|
end
|
||||||
|
|
||||||
|
if @last_order == order
|
||||||
|
@last_order = order.previous_order
|
||||||
|
end
|
||||||
|
|
||||||
|
previous_order = order.previous_order
|
||||||
|
next_order = order.next_order
|
||||||
|
|
||||||
|
previous_order&.next_order = next_order
|
||||||
|
next_order&.previous_order = previous_order
|
||||||
|
|
||||||
|
order.previous_order = nil
|
||||||
|
order.next_order = nil
|
||||||
|
@order_count -= 1
|
||||||
|
|
||||||
|
order
|
||||||
|
end
|
||||||
|
|
||||||
def empty?
|
def empty?
|
||||||
@order_count == 0
|
@order_count == 0
|
||||||
end
|
end
|
||||||
|
9
spec/factories/limits.rb
Normal file
9
spec/factories/limits.rb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
FactoryBot.define do
|
||||||
|
factory :limit, class: Rex::Limit do
|
||||||
|
transient do
|
||||||
|
price { 100 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
277
spec/limit_spec.rb
Normal file
277
spec/limit_spec.rb
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Rex::Limit do
|
||||||
|
let(:instance) { described_class.new(100) }
|
||||||
|
let(:order_a) { build(:order) }
|
||||||
|
let(:order_b) { build(:order) }
|
||||||
|
let(:order_c) { build(:order) }
|
||||||
|
|
||||||
|
describe "#add_order" do
|
||||||
|
context "when limit has no orders yet" do
|
||||||
|
it "increases the count by one" do
|
||||||
|
expect do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
end.to change(instance, :count).by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets the first and last order correctly" do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
|
||||||
|
expect(instance.first_order).to eq(order_a)
|
||||||
|
expect(instance.last_order).to eq(order_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not change the previous/next order values" do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
|
||||||
|
expect(order_a.previous_order).to eq(nil)
|
||||||
|
expect(order_a.next_order).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when limit orders already in it" do
|
||||||
|
before do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "increases the count by one" do
|
||||||
|
expect do
|
||||||
|
instance.add_order(order_b)
|
||||||
|
end.to change(instance, :count).by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets the first and last order correctly" do
|
||||||
|
instance.add_order(order_b)
|
||||||
|
|
||||||
|
expect(instance.first_order).to eq(order_a)
|
||||||
|
expect(instance.last_order).to eq(order_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not change the previous/next order values" do
|
||||||
|
instance.add_order(order_b)
|
||||||
|
|
||||||
|
expect(order_a.previous_order).to eq(nil)
|
||||||
|
expect(order_a.next_order).to eq(order_b)
|
||||||
|
|
||||||
|
expect(order_b.previous_order).to eq(order_a)
|
||||||
|
expect(order_b.next_order).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#peek_first_order" do
|
||||||
|
subject { instance.peek_first_order }
|
||||||
|
|
||||||
|
context "when limit is empty" do
|
||||||
|
it { is_expected.to eq(nil) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when limit has one item" do
|
||||||
|
before do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the first first order" do
|
||||||
|
expect(subject).to eq(order_a)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when limit has two items" do
|
||||||
|
before do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
instance.add_order(order_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the first order" do
|
||||||
|
expect(subject).to eq(order_a)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#pop_first_order" do
|
||||||
|
context "when limit is empty" do
|
||||||
|
it "returns nil" do
|
||||||
|
expect(instance.pop_first_order).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not change the count" do
|
||||||
|
expect { instance.pop_first_order }.not_to change(instance, :count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when limit has two orders" do
|
||||||
|
before do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
instance.add_order(order_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "decrements the count by 1" do
|
||||||
|
expect { instance.pop_first_order }.to change(instance, :count).by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the first order" do
|
||||||
|
expect(instance.pop_first_order).to eq(order_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the first order" do
|
||||||
|
expect { instance.pop_first_order }.to change(instance, :first_order).from(order_a).to(order_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets the previous/next order accordingly" do
|
||||||
|
popped_order = instance.pop_first_order
|
||||||
|
|
||||||
|
expect(popped_order.next_order).to eq(nil)
|
||||||
|
expect(popped_order.previous_order).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "updates the previous/next order links of the new first order" do
|
||||||
|
instance.pop_first_order
|
||||||
|
new_first_order = instance.peek_first_order
|
||||||
|
|
||||||
|
expect(new_first_order.previous_order).to eq(nil)
|
||||||
|
expect(new_first_order.next_order).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when limit has only one order" do
|
||||||
|
before do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "decrements the count by 1" do
|
||||||
|
expect { instance.pop_first_order }.to change(instance, :count).to(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the first order" do
|
||||||
|
expect(instance.pop_first_order).to eq(order_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the first order" do
|
||||||
|
expect { instance.pop_first_order }.to change(instance, :first_order).from(order_a).to(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets the previous/next of the returned order to nil" do
|
||||||
|
popped_order = instance.pop_first_order
|
||||||
|
|
||||||
|
expect(popped_order.next_order).to eq(nil)
|
||||||
|
expect(popped_order.previous_order).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets the first/last order correctly" do
|
||||||
|
instance.pop_first_order
|
||||||
|
|
||||||
|
expect(instance.first_order).to eq(nil)
|
||||||
|
expect(instance.last_order).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#remove_order" do
|
||||||
|
context "when the order is the first order" do
|
||||||
|
before do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "decrements the count by 1" do
|
||||||
|
expect { instance.remove_order(order_a) }.to change(instance, :count).by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the removed order" do
|
||||||
|
expect(instance.remove_order(order_a)).to eq(order_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the previous/next order of the removed order" do
|
||||||
|
instance.remove_order(order_a)
|
||||||
|
|
||||||
|
expect(order_a.previous_order).to eq(nil)
|
||||||
|
expect(order_a.next_order).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the first/last order in the limit" do
|
||||||
|
instance.remove_order(order_a)
|
||||||
|
|
||||||
|
expect(instance.first_order).to eq(nil)
|
||||||
|
expect(instance.last_order).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the order is the last order" do
|
||||||
|
before do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
instance.add_order(order_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "decrements the count by 1" do
|
||||||
|
expect { instance.remove_order(order_b) }.to change(instance, :count).by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the removed order" do
|
||||||
|
expect(instance.remove_order(order_b)).to eq(order_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the previous/next order of the removed order" do
|
||||||
|
instance.remove_order(order_b)
|
||||||
|
|
||||||
|
expect(order_b.previous_order).to eq(nil)
|
||||||
|
expect(order_b.next_order).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the first/last order in the limit" do
|
||||||
|
instance.remove_order(order_b)
|
||||||
|
|
||||||
|
expect(instance.first_order).to eq(order_a)
|
||||||
|
expect(instance.last_order).to eq(order_a)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the order is the in the middle of the queue" do
|
||||||
|
before do
|
||||||
|
instance.add_order(order_a)
|
||||||
|
instance.add_order(order_b)
|
||||||
|
instance.add_order(order_c)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "decrements the count by 1" do
|
||||||
|
expect { instance.remove_order(order_b) }.to change(instance, :count).by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the removed order" do
|
||||||
|
expect(instance.remove_order(order_b)).to eq(order_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the previous/next order of the removed order" do
|
||||||
|
instance.remove_order(order_b)
|
||||||
|
|
||||||
|
expect(order_b.previous_order).to eq(nil)
|
||||||
|
expect(order_b.next_order).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not adjust the first/last order in the limit" do
|
||||||
|
instance.remove_order(order_b)
|
||||||
|
|
||||||
|
expect(instance.first_order).to eq(order_a)
|
||||||
|
expect(instance.last_order).to eq(order_c)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adjusts the previous/next order of the remaining orders" do
|
||||||
|
instance.remove_order(order_b)
|
||||||
|
|
||||||
|
expect(order_a.previous_order).to eq(nil)
|
||||||
|
expect(order_a.next_order).to eq(order_c)
|
||||||
|
|
||||||
|
expect(order_c.previous_order).to eq(order_a)
|
||||||
|
expect(order_c.next_order).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ends up in a valid state after deleting all the orders" do
|
||||||
|
[order_a, order_b, order_c].shuffle.each do |order|
|
||||||
|
instance.remove_order(order)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(instance.first_order).to eq(nil)
|
||||||
|
expect(instance.last_order).to eq(nil)
|
||||||
|
expect(instance.count).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user