From 2d4e1cb0f4e2eeb7078c3ed3f69f68e4519b3087 Mon Sep 17 00:00:00 2001 From: Vladislav Chugunov Date: Fri, 21 Jun 2019 21:26:52 +0300 Subject: [PATCH 1/2] Fix infinity loop when max_size is zero Max_size should be non_neg_integer Explicitly handle max_size=0 and do nothing but return same struct --- lib/deque.ex | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/deque.ex b/lib/deque.ex index 446f51c..d136aa7 100644 --- a/lib/deque.ex +++ b/lib/deque.ex @@ -13,12 +13,15 @@ defmodule Deque do defstruct size: 0, max_size: nil, list1: [], list2: [] - @spec new(integer) :: t + @spec new(non_neg_integer) :: t def new(max_size \\ 100) do %Deque{max_size: max_size} end @spec append(t, value) :: t + def append(%Deque{max_size: 0}=deque, _value) do + deque + end def append(%Deque{size: size, max_size: max_size, list1: [], list2: list2}=deque, value) when size < max_size do %{deque | size: size + 1, list2: [value|list2]} end @@ -33,6 +36,9 @@ defmodule Deque do end @spec appendleft(t, value) :: t + def appendleft(%Deque{max_size: 0}=deque, _value) do + deque + end def appendleft(%Deque{size: size, max_size: max_size, list1: list1, list2: []}=deque, value) when size < max_size do %{deque | size: size + 1, list1: [value|list1]} end From 80a672624545a0ac66257c0542f91e4d9f50c26f Mon Sep 17 00:00:00 2001 From: Vladislav Chugunov Date: Mon, 24 Jun 2019 12:57:40 +0300 Subject: [PATCH 2/2] Add test with max_size zero --- test/deque_test.exs | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/test/deque_test.exs b/test/deque_test.exs index 1ab02d6..2c33c8c 100644 --- a/test/deque_test.exs +++ b/test/deque_test.exs @@ -2,9 +2,12 @@ defmodule DequeTest do use ExUnit.Case test "new" do - deque = Deque.new(5) - assert deque.size == 0 - assert deque.max_size == 5 + 0..10 + |> Enum.each(fn max_size -> + deque = Deque.new(max_size) + assert deque.size == 0 + assert deque.max_size == max_size + end) end test "append/appendleft/pop/popleft" do @@ -35,14 +38,40 @@ defmodule DequeTest do assert deque.list2 == [] end + test "append/appendleft/pop/popleft max_size=0" do + deque = Enum.reduce(1..6, Deque.new(0), &Deque.append(&2, &1)) + assert deque.list1 == [] + assert deque.list2 == [] + + deque = Enum.reduce(1..3, deque, &Deque.appendleft(&2, &1)) + assert deque.list1 == [] + assert deque.list2 == [] + + {value, deque} = Deque.pop(deque) + assert value == nil + assert deque.list1 == [] + assert deque.list2 == [] + + {value, deque} = Deque.popleft(deque) + assert value == nil + assert deque.list1 == [] + assert deque.list2 == [] + end + test "enumerable" do deque = Enum.reduce(1..6, Deque.new(5), &Deque.append(&2, &1)) assert Enum.to_list(deque) == [2, 3, 4, 5, 6] + + deque = Enum.reduce(1..6, Deque.new(0), &Deque.append(&2, &1)) + assert Enum.to_list(deque) == [] end test "collectable/inspect" do deque = Enum.into(1..6, Deque.new(5)) assert inspect(deque) == "#Deque<[2, 3, 4, 5, 6]>" + + deque = Enum.into(1..6, Deque.new(0)) + assert inspect(deque) == "#Deque<[]>" end test "take_while" do @@ -51,6 +80,9 @@ defmodule DequeTest do deque = gen_take_while(400..500, 10, 492) assert Enum.to_list(deque) == [493, 494, 495, 496, 497, 498, 499, 500] + + deque = gen_take_while(400..500, 0, 492) + assert Enum.to_list(deque) == [] end defp gen_take_while(range, max_size, max_value) do