Files
n8n-openai-adapter/lib/elixir/test/elixir/enum_test.exs
T
José Valim e2720924da Add Enumerable.slice/1 and use it in Enum (#6958)
We have reimplemented Enum.at/3, Enum.fetch/2, Enum.fetch!/2,
Enum.random/1, Enum.slice/2, and Enum.slice/3 to be more
efficient by using the new protocol function.

This partially implements #6955. We have decided to not replace
`count/1` by an `aggregate/2` callback because it became clear
we cannot implement `min/1` for date ranges since `Enum.min/1`
does a structural comparison. Given ranges are still the only case
that requires custom aggregations, we have decided to inline those
in Enum until we have more evidence that such callback is necessary.
2017-10-21 16:17:04 +02:00

1712 lines
55 KiB
Elixir

Code.require_file("test_helper.exs", __DIR__)
defmodule EnumTest do
use ExUnit.Case, async: true
doctest Enum
defp assert_runs_enumeration_only_once(enum_fun) do
enumerator =
Stream.map([:element], fn element ->
send(self(), element)
element
end)
enum_fun.(enumerator)
assert_received :element
refute_received :element
end
test "all?/2" do
assert Enum.all?([2, 4, 6])
refute Enum.all?([2, nil, 4])
assert Enum.all?([])
assert Enum.all?([2, 4, 6], fn x -> rem(x, 2) == 0 end)
refute Enum.all?([2, 3, 4], fn x -> rem(x, 2) == 0 end)
end
test "any?/2" do
refute Enum.any?([2, 4, 6], fn x -> rem(x, 2) == 1 end)
assert Enum.any?([2, 3, 4], fn x -> rem(x, 2) == 1 end)
refute Enum.any?([false, false, false])
assert Enum.any?([false, true, false])
assert Enum.any?([:foo, false, false])
refute Enum.any?([false, nil, false])
refute Enum.any?([])
end
test "at/3" do
assert Enum.at([2, 4, 6], 0) == 2
assert Enum.at([2, 4, 6], 2) == 6
assert Enum.at([2, 4, 6], 4) == nil
assert Enum.at([2, 4, 6], 4, :none) == :none
assert Enum.at([2, 4, 6], -2) == 4
assert Enum.at([2, 4, 6], -4) == nil
end
test "chunk/2" do
assert Enum.chunk([1, 2, 3, 4, 5], 2) == [[1, 2], [3, 4]]
end
test "chunk/4" do
assert Enum.chunk([1, 2, 3, 4, 5], 2, 2, [6]) == [[1, 2], [3, 4], [5, 6]]
assert Enum.chunk([1, 2, 3, 4, 5, 6], 3, 2) == [[1, 2, 3], [3, 4, 5]]
assert Enum.chunk([1, 2, 3, 4, 5, 6], 2, 3) == [[1, 2], [4, 5]]
assert Enum.chunk([1, 2, 3, 4, 5, 6], 3, 2, []) == [[1, 2, 3], [3, 4, 5], [5, 6]]
assert Enum.chunk([1, 2, 3, 4, 5, 6], 3, 3, []) == [[1, 2, 3], [4, 5, 6]]
assert Enum.chunk([1, 2, 3, 4, 5], 4, 4, 6..10) == [[1, 2, 3, 4], [5, 6, 7, 8]]
end
test "chunk_every/2" do
assert Enum.chunk_every([1, 2, 3, 4, 5], 2) == [[1, 2], [3, 4], [5]]
end
test "chunk_every/4" do
assert Enum.chunk_every([1, 2, 3, 4, 5], 2, 2, [6]) == [[1, 2], [3, 4], [5, 6]]
assert Enum.chunk_every([1, 2, 3, 4, 5, 6], 3, 2, :discard) == [[1, 2, 3], [3, 4, 5]]
assert Enum.chunk_every([1, 2, 3, 4, 5, 6], 2, 3, :discard) == [[1, 2], [4, 5]]
assert Enum.chunk_every([1, 2, 3, 4, 5, 6], 3, 2, []) == [[1, 2, 3], [3, 4, 5], [5, 6]]
assert Enum.chunk_every([1, 2, 3, 4, 5, 6], 3, 3, []) == [[1, 2, 3], [4, 5, 6]]
assert Enum.chunk_every([1, 2, 3, 4, 5], 4, 4, 6..10) == [[1, 2, 3, 4], [5, 6, 7, 8]]
end
test "chunk_by/2" do
assert Enum.chunk_by([1, 2, 2, 3, 4, 4, 6, 7, 7], &(rem(&1, 2) == 1)) ==
[[1], [2, 2], [3], [4, 4, 6], [7, 7]]
assert Enum.chunk_by([1, 2, 3, 4], fn _ -> true end) == [[1, 2, 3, 4]]
assert Enum.chunk_by([], fn _ -> true end) == []
assert Enum.chunk_by([1], fn _ -> true end) == [[1]]
end
test "chunk_while/4" do
chunk_fun = fn i, acc ->
cond do
i > 10 ->
{:halt, acc}
rem(i, 2) == 0 ->
{:cont, Enum.reverse([i | acc]), []}
true ->
{:cont, [i | acc]}
end
end
after_fun = fn
[] -> {:cont, []}
acc -> {:cont, Enum.reverse(acc), []}
end
assert Enum.chunk_while([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [], chunk_fun, after_fun) ==
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
assert Enum.chunk_while(0..9, [], chunk_fun, after_fun) ==
[[0], [1, 2], [3, 4], [5, 6], [7, 8], [9]]
assert Enum.chunk_while(0..10, [], chunk_fun, after_fun) ==
[[0], [1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
assert Enum.chunk_while(0..11, [], chunk_fun, after_fun) ==
[[0], [1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
assert Enum.chunk_while([5, 7, 9, 11], [], chunk_fun, after_fun) == [[5, 7, 9]]
end
test "concat/1" do
assert Enum.concat([[1, [2], 3], [4], [5, 6]]) == [1, [2], 3, 4, 5, 6]
assert Enum.concat([[], []]) == []
assert Enum.concat([[]]) == []
assert Enum.concat([]) == []
end
test "concat/2" do
assert Enum.concat([], [1]) == [1]
assert Enum.concat([1, [2], 3], [4, 5]) == [1, [2], 3, 4, 5]
assert Enum.concat([1, 2], 3..5) == [1, 2, 3, 4, 5]
assert Enum.concat([], []) == []
assert Enum.concat([], 1..3) == [1, 2, 3]
assert Enum.concat(fn acc, _ -> acc end, [1]) == [1]
end
test "count/1" do
assert Enum.count([1, 2, 3]) == 3
assert Enum.count([]) == 0
assert Enum.count([1, true, false, nil]) == 4
end
test "count/2" do
assert Enum.count([1, 2, 3], fn x -> rem(x, 2) == 0 end) == 1
assert Enum.count([], fn x -> rem(x, 2) == 0 end) == 0
assert Enum.count([1, true, false, nil], & &1) == 2
end
test "dedup/1" do
assert Enum.dedup([1, 1, 2, 1, 1, 2, 1]) == [1, 2, 1, 2, 1]
assert Enum.dedup([2, 1, 1, 2, 1]) == [2, 1, 2, 1]
assert Enum.dedup([1, 2, 3, 4]) == [1, 2, 3, 4]
assert Enum.dedup([1, 1.0, 2.0, 2]) == [1, 1.0, 2.0, 2]
assert Enum.dedup([]) == []
assert Enum.dedup([nil, nil, true, {:value, true}]) == [nil, true, {:value, true}]
assert Enum.dedup([nil]) == [nil]
end
test "dedup_by/2" do
assert Enum.dedup_by([{1, :x}, {2, :y}, {2, :z}, {1, :x}], fn {x, _} -> x end) ==
[{1, :x}, {2, :y}, {1, :x}]
assert Enum.dedup_by([5, 1, 2, 3, 2, 1], fn x -> x > 2 end) == [5, 1, 3, 2]
end
test "drop/2" do
assert Enum.drop([1, 2, 3], 0) == [1, 2, 3]
assert Enum.drop([1, 2, 3], 1) == [2, 3]
assert Enum.drop([1, 2, 3], 2) == [3]
assert Enum.drop([1, 2, 3], 3) == []
assert Enum.drop([1, 2, 3], 4) == []
assert Enum.drop([1, 2, 3], -1) == [1, 2]
assert Enum.drop([1, 2, 3], -2) == [1]
assert Enum.drop([1, 2, 3], -4) == []
assert Enum.drop([], 3) == []
end
test "drop_every/2" do
assert Enum.drop_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2) == [2, 4, 6, 8, 10]
assert Enum.drop_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3) == [2, 3, 5, 6, 8, 9]
assert Enum.drop_every([], 2) == []
assert Enum.drop_every([1, 2], 2) == [2]
assert Enum.drop_every([1, 2, 3], 0) == [1, 2, 3]
assert_raise FunctionClauseError, fn ->
Enum.drop_every([1, 2, 3], -1)
end
end
test "drop_while/2" do
assert Enum.drop_while([1, 2, 3, 4, 3, 2, 1], fn x -> x <= 3 end) == [4, 3, 2, 1]
assert Enum.drop_while([1, 2, 3], fn _ -> false end) == [1, 2, 3]
assert Enum.drop_while([1, 2, 3], fn x -> x <= 3 end) == []
assert Enum.drop_while([], fn _ -> false end) == []
end
test "each/2" do
try do
assert Enum.each([], fn x -> x end) == :ok
assert Enum.each([1, 2, 3], fn x -> Process.put(:enum_test_each, x * 2) end) == :ok
assert Process.get(:enum_test_each) == 6
after
Process.delete(:enum_test_each)
end
end
test "empty?/1" do
assert Enum.empty?([])
refute Enum.empty?([1, 2, 3])
refute Enum.empty?(1..3)
end
test "fetch/2" do
assert Enum.fetch([66], 0) == {:ok, 66}
assert Enum.fetch([66], -1) == {:ok, 66}
assert Enum.fetch([66], 1) == :error
assert Enum.fetch([66], -2) == :error
assert Enum.fetch([2, 4, 6], 0) == {:ok, 2}
assert Enum.fetch([2, 4, 6], -1) == {:ok, 6}
assert Enum.fetch([2, 4, 6], 2) == {:ok, 6}
assert Enum.fetch([2, 4, 6], 4) == :error
assert Enum.fetch([2, 4, 6], -2) == {:ok, 4}
assert Enum.fetch([2, 4, 6], -4) == :error
assert Enum.fetch([], 0) == :error
assert Enum.fetch([], 1) == :error
end
test "fetch!/2" do
assert Enum.fetch!([2, 4, 6], 0) == 2
assert Enum.fetch!([2, 4, 6], 2) == 6
assert Enum.fetch!([2, 4, 6], -2) == 4
assert_raise Enum.OutOfBoundsError, fn ->
Enum.fetch!([2, 4, 6], 4)
end
assert_raise Enum.OutOfBoundsError, fn ->
Enum.fetch!([2, 4, 6], -4)
end
end
test "filter/2" do
assert Enum.filter([1, 2, 3], fn x -> rem(x, 2) == 0 end) == [2]
assert Enum.filter([2, 4, 6], fn x -> rem(x, 2) == 0 end) == [2, 4, 6]
assert Enum.filter([1, 2, false, 3, nil], & &1) == [1, 2, 3]
assert Enum.filter([1, 2, 3], &match?(1, &1)) == [1]
assert Enum.filter([1, 2, 3], &match?(x when x < 3, &1)) == [1, 2]
assert Enum.filter([1, 2, 3], fn _ -> true end) == [1, 2, 3]
end
test "find/3" do
assert Enum.find([2, 4, 6], fn x -> rem(x, 2) == 1 end) == nil
assert Enum.find([2, 4, 6], 0, fn x -> rem(x, 2) == 1 end) == 0
assert Enum.find([2, 3, 4], fn x -> rem(x, 2) == 1 end) == 3
end
test "find_index/2" do
assert Enum.find_index([2, 4, 6], fn x -> rem(x, 2) == 1 end) == nil
assert Enum.find_index([2, 3, 4], fn x -> rem(x, 2) == 1 end) == 1
assert Stream.take(1..3, 3) |> Enum.find_index(fn _ -> false end) == nil
assert Stream.take(1..6, 6) |> Enum.find_index(fn x -> x == 5 end) == 4
end
test "find_value/2" do
assert Enum.find_value([2, 4, 6], fn x -> rem(x, 2) == 1 end) == nil
assert Enum.find_value([2, 4, 6], 0, fn x -> rem(x, 2) == 1 end) == 0
assert Enum.find_value([2, 3, 4], fn x -> rem(x, 2) == 1 end)
end
test "flat_map/2" do
assert Enum.flat_map([], fn x -> [x, x] end) == []
assert Enum.flat_map([1, 2, 3], fn x -> [x, x] end) == [1, 1, 2, 2, 3, 3]
assert Enum.flat_map([1, 2, 3], fn x -> x..(x + 1) end) == [1, 2, 2, 3, 3, 4]
end
test "flat_map_reduce/3" do
assert Enum.flat_map_reduce([1, 2, 3], 0, &{[&1, &2], &1 + &2}) == {[1, 0, 2, 1, 3, 3], 6}
end
test "group_by/3" do
assert Enum.group_by([], fn _ -> raise "oops" end) == %{}
assert Enum.group_by([1, 2, 3], &rem(&1, 2)) == %{0 => [2], 1 => [1, 3]}
end
test "intersperse/2" do
assert Enum.intersperse([], true) == []
assert Enum.intersperse([1], true) == [1]
assert Enum.intersperse([1, 2, 3], true) == [1, true, 2, true, 3]
end
test "into/2" do
assert Enum.into([a: 1, b: 2], %{}) == %{a: 1, b: 2}
assert Enum.into([a: 1, b: 2], %{c: 3}) == %{a: 1, b: 2, c: 3}
assert Enum.into(%{a: 1, b: 2}, []) == [a: 1, b: 2]
assert Enum.into(1..3, []) == [1, 2, 3]
assert Enum.into(["H", "i"], "") == "Hi"
end
test "into/3" do
assert Enum.into([1, 2, 3], [], fn x -> x * 2 end) == [2, 4, 6]
assert Enum.into([1, 2, 3], "numbers: ", &to_string/1) == "numbers: 123"
assert_raise FunctionClauseError, fn ->
Enum.into([2, 3], %{a: 1}, & &1)
end
end
test "join/2" do
assert Enum.join([], " = ") == ""
assert Enum.join([1, 2, 3], " = ") == "1 = 2 = 3"
assert Enum.join([1, "2", 3], " = ") == "1 = 2 = 3"
assert Enum.join([1, 2, 3]) == "123"
assert Enum.join(["", "", 1, 2, "", 3, "", "\n"], ";") == ";;1;2;;3;;\n"
assert Enum.join([""]) == ""
assert Enum.join(fn acc, _ -> acc end, ".") == ""
end
test "map/2" do
assert Enum.map([], fn x -> x * 2 end) == []
assert Enum.map([1, 2, 3], fn x -> x * 2 end) == [2, 4, 6]
end
test "map_every/3" do
assert Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2, fn x -> x * 2 end) ==
[2, 2, 6, 4, 10, 6, 14, 8, 18, 10]
assert Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3, fn x -> x * 2 end) ==
[2, 2, 3, 8, 5, 6, 14, 8, 9, 20]
assert Enum.map_every([], 2, fn x -> x * 2 end) == []
assert Enum.map_every([1, 2], 2, fn x -> x * 2 end) == [2, 2]
assert Enum.map_every([1, 2, 3], 0, fn _x -> raise :i_should_have_never_been_invoked end) ==
[1, 2, 3]
assert Enum.map_every(1..3, 1, fn x -> x * 2 end) == [2, 4, 6]
assert_raise FunctionClauseError, fn ->
Enum.map_every([1, 2, 3], -1, fn x -> x * 2 end)
end
assert_raise FunctionClauseError, fn ->
Enum.map_every(1..10, 3.33, fn x -> x * 2 end)
end
assert Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 9, fn x -> x + 1000 end) ==
[1001, 2, 3, 4, 5, 6, 7, 8, 9, 1010]
assert Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10, fn x -> x + 1000 end) ==
[1001, 2, 3, 4, 5, 6, 7, 8, 9, 10]
assert Enum.map_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 100, fn x -> x + 1000 end) ==
[1001, 2, 3, 4, 5, 6, 7, 8, 9, 10]
end
test "map_join/3" do
assert Enum.map_join([], " = ", &(&1 * 2)) == ""
assert Enum.map_join([1, 2, 3], " = ", &(&1 * 2)) == "2 = 4 = 6"
assert Enum.map_join([1, 2, 3], &(&1 * 2)) == "246"
assert Enum.map_join(["", "", 1, 2, "", 3, "", "\n"], ";", & &1) == ";;1;2;;3;;\n"
assert Enum.map_join([""], "", & &1) == ""
assert Enum.map_join(fn acc, _ -> acc end, ".", &(&1 + 0)) == ""
end
test "map_reduce/3" do
assert Enum.map_reduce([], 1, fn x, acc -> {x * 2, x + acc} end) == {[], 1}
assert Enum.map_reduce([1, 2, 3], 1, fn x, acc -> {x * 2, x + acc} end) == {[2, 4, 6], 7}
end
test "max/1" do
assert Enum.max([1]) == 1
assert Enum.max([1, 2, 3]) == 3
assert Enum.max([1, [], :a, {}]) == []
assert_raise Enum.EmptyError, fn ->
Enum.max([])
end
end
test "max/2" do
assert Enum.max([1], fn -> nil end) == 1
assert Enum.max([1, 2, 3], fn -> nil end) == 3
assert Enum.max([1, [], :a, {}], fn -> nil end) == []
assert Enum.max([], fn -> :empty_value end) == :empty_value
assert Enum.max(%{}, fn -> :empty_value end) == :empty_value
assert_runs_enumeration_only_once(&Enum.max(&1, fn -> nil end))
end
test "max_by/2" do
assert Enum.max_by(["a", "aa", "aaa"], fn x -> String.length(x) end) == "aaa"
assert_raise Enum.EmptyError, fn ->
Enum.max_by([], fn x -> String.length(x) end)
end
assert_raise Enum.EmptyError, fn ->
Enum.max_by(%{}, & &1)
end
end
test "max_by/3" do
assert Enum.max_by(["a", "aa", "aaa"], fn x -> String.length(x) end, fn -> nil end) == "aaa"
assert Enum.max_by([], fn x -> String.length(x) end, fn -> :empty_value end) == :empty_value
assert Enum.max_by(%{}, & &1, fn -> :empty_value end) == :empty_value
assert Enum.max_by(%{}, & &1, fn -> {:a, :tuple} end) == {:a, :tuple}
assert_runs_enumeration_only_once(&Enum.max_by(&1, fn e -> e end, fn -> nil end))
end
test "member?/2" do
assert Enum.member?([1, 2, 3], 2)
refute Enum.member?([], 0)
refute Enum.member?([1, 2, 3], 0)
end
test "min/1" do
assert Enum.min([1]) == 1
assert Enum.min([1, 2, 3]) == 1
assert Enum.min([[], :a, {}]) == :a
assert_raise Enum.EmptyError, fn ->
Enum.min([])
end
end
test "min/2" do
assert Enum.min([1], fn -> nil end) == 1
assert Enum.min([1, 2, 3], fn -> nil end) == 1
assert Enum.min([[], :a, {}], fn -> nil end) == :a
assert Enum.min([], fn -> :empty_value end) == :empty_value
assert Enum.min(%{}, fn -> :empty_value end) == :empty_value
assert_runs_enumeration_only_once(&Enum.min(&1, fn -> nil end))
end
test "min_by/2" do
assert Enum.min_by(["a", "aa", "aaa"], fn x -> String.length(x) end) == "a"
assert_raise Enum.EmptyError, fn ->
Enum.min_by([], fn x -> String.length(x) end)
end
assert_raise Enum.EmptyError, fn ->
Enum.min_by(%{}, & &1)
end
end
test "min_by/3" do
assert Enum.min_by(["a", "aa", "aaa"], fn x -> String.length(x) end, fn -> nil end) == "a"
assert Enum.min_by([], fn x -> String.length(x) end, fn -> :empty_value end) == :empty_value
assert Enum.min_by(%{}, & &1, fn -> :empty_value end) == :empty_value
assert Enum.min_by(%{}, & &1, fn -> {:a, :tuple} end) == {:a, :tuple}
assert_runs_enumeration_only_once(&Enum.min_by(&1, fn e -> e end, fn -> nil end))
end
test "min_max/1" do
assert Enum.min_max([1]) == {1, 1}
assert Enum.min_max([2, 3, 1]) == {1, 3}
assert Enum.min_max([[], :a, {}]) == {:a, []}
assert_raise Enum.EmptyError, fn ->
Enum.min_max([])
end
end
test "min_max/2" do
assert Enum.min_max([1], fn -> nil end) == {1, 1}
assert Enum.min_max([2, 3, 1], fn -> nil end) == {1, 3}
assert Enum.min_max([[], :a, {}], fn -> nil end) == {:a, []}
assert Enum.min_max([], fn -> {:empty_min, :empty_max} end) == {:empty_min, :empty_max}
assert Enum.min_max(%{}, fn -> {:empty_min, :empty_max} end) == {:empty_min, :empty_max}
assert_runs_enumeration_only_once(&Enum.min_max(&1, fn -> nil end))
end
test "min_max_by/2" do
assert Enum.min_max_by(["aaa", "a", "aa"], fn x -> String.length(x) end) == {"a", "aaa"}
assert_raise Enum.EmptyError, fn ->
Enum.min_max_by([], fn x -> String.length(x) end)
end
end
test "min_max_by/3" do
assert Enum.min_max_by(["aaa", "a", "aa"], fn x -> String.length(x) end, fn -> nil end) ==
{"a", "aaa"}
assert Enum.min_max_by([], fn x -> String.length(x) end, fn -> {:no_min, :no_max} end) ==
{:no_min, :no_max}
assert Enum.min_max_by(%{}, fn x -> String.length(x) end, fn -> {:no_min, :no_max} end) ==
{:no_min, :no_max}
assert_runs_enumeration_only_once(&Enum.min_max_by(&1, fn x -> x end, fn -> nil end))
end
test "split_with/2" do
assert Enum.split_with([], fn x -> rem(x, 2) == 0 end) == {[], []}
assert Enum.split_with([1, 2, 3], fn x -> rem(x, 2) == 0 end) == {[2], [1, 3]}
assert Enum.split_with([2, 4, 6], fn x -> rem(x, 2) == 0 end) == {[2, 4, 6], []}
assert Enum.split_with(1..5, fn x -> rem(x, 2) == 0 end) == {[2, 4], [1, 3, 5]}
assert Enum.split_with(-3..0, fn x -> x > 0 end) == {[], [-3, -2, -1, 0]}
assert Enum.split_with(%{}, fn x -> rem(x, 2) == 0 end) == {[], []}
assert Enum.split_with(%{a: 1, b: 2, c: 3}, fn {_k, v} -> rem(v, 2) == 0 end) ==
{[b: 2], [a: 1, c: 3]}
assert Enum.split_with(%{b: 2, d: 4, f: 6}, fn {_k, v} -> rem(v, 2) == 0 end) ==
{[b: 2, d: 4, f: 6], []}
end
test "random/1" do
# corner cases, independent of the seed
assert_raise Enum.EmptyError, fn -> Enum.random([]) end
assert Enum.random([1]) == 1
# set a fixed seed so the test can be deterministic
# please note the order of following assertions is important
seed1 = {1406, 407_414, 139_258}
seed2 = {1306, 421_106, 567_597}
:rand.seed(:exsplus, seed1)
assert Enum.random([1, 2]) == 2
assert Enum.random([1, 2, 3]) == 1
assert Enum.random([1, 2, 3, 4]) == 1
assert Enum.random([1, 2, 3, 4, 5]) == 2
:rand.seed(:exsplus, seed2)
assert Enum.random([1, 2]) == 2
assert Enum.random([1, 2, 3]) == 3
assert Enum.random([1, 2, 3, 4]) == 2
assert Enum.random([1, 2, 3, 4, 5]) == 3
end
test "reduce/2" do
assert Enum.reduce([1, 2, 3], fn x, acc -> x + acc end) == 6
assert_raise Enum.EmptyError, fn ->
Enum.reduce([], fn x, acc -> x + acc end)
end
assert_raise Enum.EmptyError, fn ->
Enum.reduce(%{}, fn _, acc -> acc end)
end
end
test "reduce/3" do
assert Enum.reduce([], 1, fn x, acc -> x + acc end) == 1
assert Enum.reduce([1, 2, 3], 1, fn x, acc -> x + acc end) == 7
end
test "reduce_while/3" do
assert Enum.reduce_while([1, 2, 3], 1, fn i, acc -> {:cont, acc + i} end) == 7
assert Enum.reduce_while([1, 2, 3], 1, fn _i, acc -> {:halt, acc} end) == 1
assert Enum.reduce_while([], 0, fn _i, acc -> {:cont, acc} end) == 0
end
test "reject/2" do
assert Enum.reject([1, 2, 3], fn x -> rem(x, 2) == 0 end) == [1, 3]
assert Enum.reject([2, 4, 6], fn x -> rem(x, 2) == 0 end) == []
assert Enum.reject([1, true, nil, false, 2], & &1) == [nil, false]
end
test "reverse/1" do
assert Enum.reverse([]) == []
assert Enum.reverse([1, 2, 3]) == [3, 2, 1]
assert Enum.reverse([5..5]) == [5..5]
end
test "reverse/2" do
assert Enum.reverse([1, 2, 3], [4, 5, 6]) == [3, 2, 1, 4, 5, 6]
assert Enum.reverse([1, 2, 3], []) == [3, 2, 1]
assert Enum.reverse([5..5], [5]) == [5..5, 5]
end
test "reverse_slice/3" do
assert Enum.reverse_slice([], 1, 2) == []
assert Enum.reverse_slice([1, 2, 3], 0, 0) == [1, 2, 3]
assert Enum.reverse_slice([1, 2, 3], 0, 1) == [1, 2, 3]
assert Enum.reverse_slice([1, 2, 3], 0, 2) == [2, 1, 3]
assert Enum.reverse_slice([1, 2, 3], 0, 20_000_000) == [3, 2, 1]
assert Enum.reverse_slice([1, 2, 3], 100, 2) == [1, 2, 3]
assert Enum.reverse_slice([1, 2, 3], 10, 10) == [1, 2, 3]
end
test "scan/2" do
assert Enum.scan([1, 2, 3, 4, 5], &(&1 + &2)) == [1, 3, 6, 10, 15]
assert Enum.scan([], &(&1 + &2)) == []
end
test "scan/3" do
assert Enum.scan([1, 2, 3, 4, 5], 0, &(&1 + &2)) == [1, 3, 6, 10, 15]
assert Enum.scan([], 0, &(&1 + &2)) == []
end
test "shuffle/1" do
# set a fixed seed so the test can be deterministic
:rand.seed(:exsplus, {1374, 347_975, 449_264})
assert Enum.shuffle([1, 2, 3, 4, 5]) == [2, 1, 3, 5, 4]
end
test "slice/2" do
list = [1, 2, 3, 4, 5]
assert Enum.slice(list, 0..0) == [1]
assert Enum.slice(list, 0..1) == [1, 2]
assert Enum.slice(list, 0..2) == [1, 2, 3]
assert Enum.slice(list, 1, 2) == [2, 3]
assert Enum.slice(list, 1, 0) == []
assert Enum.slice(list, 2, 5) == [3, 4, 5]
assert Enum.slice(list, 2, 6) == [3, 4, 5]
assert Enum.slice(list, 5, 5) == []
assert Enum.slice(list, 6, 5) == []
assert Enum.slice(list, 6, 0) == []
assert Enum.slice(list, -6, 0) == []
assert Enum.slice(list, -6, 5) == []
assert Enum.slice(list, -2, 5) == [4, 5]
assert Enum.slice(list, -3, 1) == [3]
assert_raise FunctionClauseError, fn ->
Enum.slice(list, 0, -1)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(list, 0.99, 0)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(list, 0, 0.99)
end
end
test "slice/3" do
list = [1, 2, 3, 4, 5]
assert Enum.slice(list, 0, 0) == []
assert Enum.slice(list, 0, 1) == [1]
assert Enum.slice(list, 0, 2) == [1, 2]
assert Enum.slice(list, 1, 2) == [2, 3]
assert Enum.slice(list, 1, 0) == []
assert Enum.slice(list, 2, 5) == [3, 4, 5]
assert Enum.slice(list, 2, 6) == [3, 4, 5]
assert Enum.slice(list, 5, 5) == []
assert Enum.slice(list, 6, 5) == []
assert Enum.slice(list, 6, 0) == []
assert Enum.slice(list, -6, 0) == []
assert Enum.slice(list, -6, 5) == []
assert Enum.slice(list, -2, 5) == [4, 5]
assert Enum.slice(list, -3, 1) == [3]
assert_raise FunctionClauseError, fn ->
Enum.slice(list, 0, -1)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(list, 0.99, 0)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(list, 0, 0.99)
end
end
test "sort/1" do
assert Enum.sort([5, 3, 2, 4, 1]) == [1, 2, 3, 4, 5]
end
test "sort/2" do
assert Enum.sort([5, 3, 2, 4, 1], &(&1 > &2)) == [5, 4, 3, 2, 1]
end
test "sort_by/3" do
collection = [
[other_data: 1, sorted_data: 5],
[other_data: 3, sorted_data: 4],
[other_data: 4, sorted_data: 3],
[other_data: 2, sorted_data: 2],
[other_data: 5, sorted_data: 1]
]
assert Enum.sort_by(collection, & &1[:sorted_data]) == [
[other_data: 5, sorted_data: 1],
[other_data: 2, sorted_data: 2],
[other_data: 4, sorted_data: 3],
[other_data: 3, sorted_data: 4],
[other_data: 1, sorted_data: 5]
]
assert Enum.sort_by(collection, & &1[:sorted_data], &>=/2) == collection
end
test "split/2" do
assert Enum.split([1, 2, 3], 0) == {[], [1, 2, 3]}
assert Enum.split([1, 2, 3], 1) == {[1], [2, 3]}
assert Enum.split([1, 2, 3], 2) == {[1, 2], [3]}
assert Enum.split([1, 2, 3], 3) == {[1, 2, 3], []}
assert Enum.split([1, 2, 3], 4) == {[1, 2, 3], []}
assert Enum.split([], 3) == {[], []}
assert Enum.split([1, 2, 3], -1) == {[1, 2], [3]}
assert Enum.split([1, 2, 3], -2) == {[1], [2, 3]}
assert Enum.split([1, 2, 3], -3) == {[], [1, 2, 3]}
assert Enum.split([1, 2, 3], -10) == {[], [1, 2, 3]}
end
test "split_while/2" do
assert Enum.split_while([1, 2, 3], fn _ -> false end) == {[], [1, 2, 3]}
assert Enum.split_while([1, 2, 3], fn _ -> true end) == {[1, 2, 3], []}
assert Enum.split_while([1, 2, 3], fn x -> x > 2 end) == {[], [1, 2, 3]}
assert Enum.split_while([1, 2, 3], fn x -> x > 3 end) == {[], [1, 2, 3]}
assert Enum.split_while([1, 2, 3], fn x -> x < 3 end) == {[1, 2], [3]}
assert Enum.split_while([], fn _ -> true end) == {[], []}
end
test "sum/1" do
assert Enum.sum([]) == 0
assert Enum.sum([1]) == 1
assert Enum.sum([1, 2, 3]) == 6
assert Enum.sum([1.1, 2.2, 3.3]) == 6.6
assert Enum.sum([-3, -2, -1, 0, 1, 2, 3]) == 0
assert Enum.sum(42..42) == 42
assert Enum.sum(11..17) == 98
assert Enum.sum(17..11) == 98
assert Enum.sum(11..-17) == Enum.sum(-17..11)
assert_raise ArithmeticError, fn ->
Enum.sum([{}])
end
assert_raise ArithmeticError, fn ->
Enum.sum([1, {}])
end
end
test "take/2" do
assert Enum.take([1, 2, 3], 0) == []
assert Enum.take([1, 2, 3], 1) == [1]
assert Enum.take([1, 2, 3], 2) == [1, 2]
assert Enum.take([1, 2, 3], 3) == [1, 2, 3]
assert Enum.take([1, 2, 3], 4) == [1, 2, 3]
assert Enum.take([1, 2, 3], -1) == [3]
assert Enum.take([1, 2, 3], -2) == [2, 3]
assert Enum.take([1, 2, 3], -4) == [1, 2, 3]
assert Enum.take([], 3) == []
end
test "take_every/2" do
assert Enum.take_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2) == [1, 3, 5, 7, 9]
assert Enum.take_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3) == [1, 4, 7, 10]
assert Enum.take_every([], 2) == []
assert Enum.take_every([1, 2], 2) == [1]
assert Enum.take_every([1, 2, 3], 0) == []
assert Enum.take_every(1..3, 1) == [1, 2, 3]
assert_raise FunctionClauseError, fn ->
Enum.take_every([1, 2, 3], -1)
end
assert_raise FunctionClauseError, fn ->
Enum.take_every(1..10, 3.33)
end
end
test "take_random/2" do
assert Enum.take_random(-42..-42, 1) == [-42]
# corner cases, independent of the seed
assert_raise FunctionClauseError, fn -> Enum.take_random([1, 2], -1) end
assert Enum.take_random([], 0) == []
assert Enum.take_random([], 3) == []
assert Enum.take_random([1], 0) == []
assert Enum.take_random([1], 2) == [1]
assert Enum.take_random([1, 2], 0) == []
# set a fixed seed so the test can be deterministic
# please note the order of following assertions is important
seed1 = {1406, 407_414, 139_258}
seed2 = {1406, 421_106, 567_597}
:rand.seed(:exsplus, seed1)
assert Enum.take_random([1, 2, 3], 1) == [2]
assert Enum.take_random([1, 2, 3], 2) == [3, 1]
assert Enum.take_random([1, 2, 3], 3) == [1, 3, 2]
assert Enum.take_random([1, 2, 3], 4) == [2, 3, 1]
:rand.seed(:exsplus, seed2)
assert Enum.take_random([1, 2, 3], 1) == [3]
assert Enum.take_random([1, 2, 3], 2) == [1, 2]
assert Enum.take_random([1, 2, 3], 3) == [1, 2, 3]
assert Enum.take_random([1, 2, 3], 4) == [2, 1, 3]
assert Enum.take_random([1, 2, 3], 129) == [3, 2, 1]
# assert that every item in the sample comes from the input list
list = for _ <- 1..100, do: make_ref()
for x <- Enum.take_random(list, 50) do
assert x in list
end
assert_raise FunctionClauseError, fn ->
Enum.take_random(1..10, -1)
end
assert_raise FunctionClauseError, fn ->
Enum.take_random(1..10, 10.0)
end
assert_raise FunctionClauseError, fn ->
Enum.take_random(1..10, 128.1)
end
end
test "take_while/2" do
assert Enum.take_while([1, 2, 3], fn x -> x > 3 end) == []
assert Enum.take_while([1, 2, 3], fn x -> x <= 1 end) == [1]
assert Enum.take_while([1, 2, 3], fn x -> x <= 3 end) == [1, 2, 3]
assert Enum.take_while([], fn _ -> true end) == []
end
test "to_list/1" do
assert Enum.to_list([]) == []
end
test "uniq/1" do
assert Enum.uniq([5, 1, 2, 3, 2, 1]) == [5, 1, 2, 3]
end
test "uniq_by/2" do
assert Enum.uniq_by([1, 2, 3, 2, 1], fn x -> x end) == [1, 2, 3]
end
test "unzip/1" do
assert Enum.unzip([{:a, 1}, {:b, 2}, {:c, 3}]) == {[:a, :b, :c], [1, 2, 3]}
assert Enum.unzip([]) == {[], []}
assert Enum.unzip(%{a: 1, b: 2}) == {[:a, :b], [1, 2]}
assert Enum.unzip(foo: "a", bar: "b") == {[:foo, :bar], ["a", "b"]}
assert_raise FunctionClauseError, fn -> Enum.unzip([{:a, 1}, {:b, 2, "foo"}]) end
assert_raise FunctionClauseError, fn -> Enum.unzip([{1, 2, {3, {4, 5}}}]) end
assert_raise FunctionClauseError, fn -> Enum.unzip([1, 2, 3]) end
end
test "with_index/2" do
assert Enum.with_index([]) == []
assert Enum.with_index([1, 2, 3]) == [{1, 0}, {2, 1}, {3, 2}]
assert Enum.with_index([1, 2, 3], 10) == [{1, 10}, {2, 11}, {3, 12}]
end
test "zip/2" do
assert Enum.zip([:a, :b], [1, 2]) == [{:a, 1}, {:b, 2}]
assert Enum.zip([:a, :b], [1, 2, 3, 4]) == [{:a, 1}, {:b, 2}]
assert Enum.zip([:a, :b, :c, :d], [1, 2]) == [{:a, 1}, {:b, 2}]
assert Enum.zip([], [1]) == []
assert Enum.zip([1], []) == []
assert Enum.zip([], []) == []
end
test "zip/1" do
assert Enum.zip([[:a, :b], [1, 2], ["foo", "bar"]]) == [{:a, 1, "foo"}, {:b, 2, "bar"}]
assert Enum.zip([[:a, :b], [1, 2, 3, 4], ["foo", "bar", "baz", "qux"]]) ==
[{:a, 1, "foo"}, {:b, 2, "bar"}]
assert Enum.zip([[:a, :b, :c, :d], [1, 2], ["foo", "bar", "baz", "qux"]]) ==
[{:a, 1, "foo"}, {:b, 2, "bar"}]
assert Enum.zip([[:a, :b, :c, :d], [1, 2, 3, 4], ["foo", "bar"]]) ==
[{:a, 1, "foo"}, {:b, 2, "bar"}]
assert Enum.zip([1..10, ["foo", "bar"]]) == [{1, "foo"}, {2, "bar"}]
assert Enum.zip([]) == []
assert Enum.zip([[]]) == []
assert Enum.zip([[1]]) == [{1}]
assert Enum.zip([[], [], [], []]) == []
assert_raise FunctionClauseError, fn ->
Enum.zip(%{})
end
end
end
defmodule EnumTest.Range do
# Ranges use custom callbacks for protocols in many operations.
use ExUnit.Case, async: true
test "all?/2" do
assert Enum.all?(0..1)
assert Enum.all?(1..0)
refute Enum.all?(0..5, fn x -> rem(x, 2) == 0 end)
assert Enum.all?(0..1, fn x -> x < 2 end)
end
test "any?/2" do
assert Enum.any?(1..0)
refute Enum.any?(0..5, &(&1 > 10))
assert Enum.any?(0..5, &(&1 > 3))
end
test "at/3" do
assert Enum.at(2..6, 0) == 2
assert Enum.at(2..6, 4) == 6
assert Enum.at(2..6, 6) == nil
assert Enum.at(2..6, 6, :none) == :none
assert Enum.at(2..6, -2) == 5
assert Enum.at(2..6, -8) == nil
end
test "chunk/2" do
assert Enum.chunk(1..5, 2) == [[1, 2], [3, 4]]
end
test "chunk/4" do
assert Enum.chunk(1..5, 2, 2, [6]) == [[1, 2], [3, 4], [5, 6]]
assert Enum.chunk(1..6, 3, 2) == [[1, 2, 3], [3, 4, 5]]
assert Enum.chunk(1..6, 2, 3) == [[1, 2], [4, 5]]
assert Enum.chunk(1..6, 3, 2, []) == [[1, 2, 3], [3, 4, 5], [5, 6]]
assert Enum.chunk(1..5, 4, 4, 6..10) == [[1, 2, 3, 4], [5, 6, 7, 8]]
end
test "chunk_every/2" do
assert Enum.chunk_every(1..5, 2) == [[1, 2], [3, 4], [5]]
end
test "chunk_every/4" do
assert Enum.chunk_every(1..5, 2, 2) == [[1, 2], [3, 4], [5]]
assert Enum.chunk_every(1..6, 3, 2, :discard) == [[1, 2, 3], [3, 4, 5]]
assert Enum.chunk_every(1..6, 2, 3, :discard) == [[1, 2], [4, 5]]
assert Enum.chunk_every(1..6, 3, 2, []) == [[1, 2, 3], [3, 4, 5], [5, 6]]
assert Enum.chunk_every(1..5, 4, 4, 6..10) == [[1, 2, 3, 4], [5, 6, 7, 8]]
end
test "chunk_by/2" do
assert Enum.chunk_by(1..4, fn _ -> true end) == [[1, 2, 3, 4]]
assert Enum.chunk_by(1..4, &(rem(&1, 2) == 1)) == [[1], [2], [3], [4]]
end
test "concat/1" do
assert Enum.concat([1..2, 4..6]) == [1, 2, 4, 5, 6]
assert Enum.concat([1..5, fn acc, _ -> acc end, [1]]) == [1, 2, 3, 4, 5, 1]
end
test "concat/2" do
assert Enum.concat(1..3, 4..5) == [1, 2, 3, 4, 5]
assert Enum.concat(1..3, [4, 5]) == [1, 2, 3, 4, 5]
assert Enum.concat(1..3, []) == [1, 2, 3]
assert Enum.concat(1..3, 0..0) == [1, 2, 3, 0]
end
test "count/1" do
assert Enum.count(1..5) == 5
assert Enum.count(1..1) == 1
end
test "count/2" do
assert Enum.count(1..5, fn x -> rem(x, 2) == 0 end) == 2
assert Enum.count(1..1, fn x -> rem(x, 2) == 0 end) == 0
end
test "dedup/1" do
assert Enum.dedup(1..3) == [1, 2, 3]
end
test "dedup_by/2" do
assert Enum.dedup_by(1..3, fn _ -> 1 end) == [1]
end
test "drop/2" do
assert Enum.drop(1..3, 0) == [1, 2, 3]
assert Enum.drop(1..3, 1) == [2, 3]
assert Enum.drop(1..3, 2) == [3]
assert Enum.drop(1..3, 3) == []
assert Enum.drop(1..3, 4) == []
assert Enum.drop(1..3, -1) == [1, 2]
assert Enum.drop(1..3, -2) == [1]
assert Enum.drop(1..3, -4) == []
assert Enum.drop(1..0, 3) == []
end
test "drop_every/2" do
assert Enum.drop_every(1..10, 2) == [2, 4, 6, 8, 10]
assert Enum.drop_every(1..10, 3) == [2, 3, 5, 6, 8, 9]
assert Enum.drop_every(0..0, 2) == []
assert Enum.drop_every(1..2, 2) == [2]
assert Enum.drop_every(1..3, 0) == [1, 2, 3]
assert Enum.drop_every(1..3, 1) == []
assert_raise FunctionClauseError, fn ->
Enum.drop_every(1..10, 3.33)
end
end
test "drop_while/2" do
assert Enum.drop_while(0..6, fn x -> x <= 3 end) == [4, 5, 6]
assert Enum.drop_while(0..6, fn _ -> false end) == [0, 1, 2, 3, 4, 5, 6]
assert Enum.drop_while(0..3, fn x -> x <= 3 end) == []
assert Enum.drop_while(1..0, fn _ -> nil end) == [1, 0]
end
test "each/2" do
try do
assert Enum.each(1..0, fn x -> x end) == :ok
assert Enum.each(1..3, fn x -> Process.put(:enum_test_each, x * 2) end) == :ok
assert Process.get(:enum_test_each) == 6
after
Process.delete(:enum_test_each)
end
try do
assert Enum.each(-1..-3, fn x -> Process.put(:enum_test_each, x * 2) end) == :ok
assert Process.get(:enum_test_each) == -6
after
Process.delete(:enum_test_each)
end
end
test "empty?/1" do
refute Enum.empty?(1..0)
refute Enum.empty?(1..2)
end
test "fetch/2" do
# ascending order
assert Enum.fetch(-10..20, 4) == {:ok, -6}
assert Enum.fetch(-10..20, -4) == {:ok, 17}
# ascending order, first
assert Enum.fetch(-10..20, 0) == {:ok, -10}
assert Enum.fetch(-10..20, -31) == {:ok, -10}
# ascending order, last
assert Enum.fetch(-10..20, -1) == {:ok, 20}
assert Enum.fetch(-10..20, 30) == {:ok, 20}
# ascending order, out of bound
assert Enum.fetch(-10..20, 31) == :error
assert Enum.fetch(-10..20, -32) == :error
# descending order
assert Enum.fetch(20..-10, 4) == {:ok, 16}
assert Enum.fetch(20..-10, -4) == {:ok, -7}
# descending order, first
assert Enum.fetch(20..-10, 0) == {:ok, 20}
assert Enum.fetch(20..-10, -31) == {:ok, 20}
# descending order, last
assert Enum.fetch(20..-10, -1) == {:ok, -10}
assert Enum.fetch(20..-10, 30) == {:ok, -10}
# descending order, out of bound
assert Enum.fetch(20..-10, 31) == :error
assert Enum.fetch(20..-10, -32) == :error
# edge cases
assert Enum.fetch(42..42, 0) == {:ok, 42}
assert Enum.fetch(42..42, -1) == {:ok, 42}
assert Enum.fetch(42..42, 2) == :error
assert Enum.fetch(42..42, -2) == :error
end
test "fetch!/2" do
assert Enum.fetch!(2..6, 0) == 2
assert Enum.fetch!(2..6, 4) == 6
assert Enum.fetch!(2..6, -1) == 6
assert Enum.fetch!(2..6, -2) == 5
assert Enum.fetch!(-2..-6, 0) == -2
assert Enum.fetch!(-2..-6, 4) == -6
assert_raise Enum.OutOfBoundsError, fn ->
Enum.fetch!(2..6, 8)
end
assert_raise Enum.OutOfBoundsError, fn ->
Enum.fetch!(-2..-6, 8)
end
assert_raise Enum.OutOfBoundsError, fn ->
Enum.fetch!(2..6, -8)
end
end
test "filter/2" do
assert Enum.filter(1..3, fn x -> rem(x, 2) == 0 end) == [2]
assert Enum.filter(1..6, fn x -> rem(x, 2) == 0 end) == [2, 4, 6]
assert Enum.filter(1..3, &match?(1, &1)) == [1]
assert Enum.filter(1..3, &match?(x when x < 3, &1)) == [1, 2]
assert Enum.filter(1..3, fn _ -> true end) == [1, 2, 3]
end
test "find/3" do
assert Enum.find(2..6, fn x -> rem(x, 2) == 0 end) == 2
assert Enum.find(2..6, fn x -> rem(x, 2) == 1 end) == 3
assert Enum.find(2..6, fn _ -> false end) == nil
assert Enum.find(2..6, 0, fn _ -> false end) == 0
end
test "find_index/2" do
assert Enum.find_index(2..6, fn x -> rem(x, 2) == 1 end) == 1
end
test "find_value/3" do
assert Enum.find_value(2..6, fn x -> rem(x, 2) == 1 end)
end
test "flat_map/2" do
assert Enum.flat_map(1..3, fn x -> [x, x] end) == [1, 1, 2, 2, 3, 3]
end
test "flat_map_reduce/3" do
assert Enum.flat_map_reduce(1..100, 0, fn i, acc ->
if acc < 3, do: {[i], acc + 1}, else: {:halt, acc}
end) == {[1, 2, 3], 3}
end
test "group_by/3" do
assert Enum.group_by(1..6, &rem(&1, 3)) == %{0 => [3, 6], 1 => [1, 4], 2 => [2, 5]}
assert Enum.group_by(1..6, &rem(&1, 3), &(&1 * 2)) ==
%{0 => [6, 12], 1 => [2, 8], 2 => [4, 10]}
end
test "intersperse/2" do
assert Enum.intersperse(1..0, true) == [1, true, 0]
assert Enum.intersperse(1..3, false) == [1, false, 2, false, 3]
end
test "into/2" do
assert Enum.into(3..5, [1, 2]) == [1, 2, 3, 4, 5]
assert Enum.into(1..5, []) == [1, 2, 3, 4, 5]
end
test "into/3" do
assert Enum.into(1..5, [], fn x -> x * 2 end) == [2, 4, 6, 8, 10]
assert Enum.into(1..3, "numbers: ", &to_string/1) == "numbers: 123"
end
test "join/2" do
assert Enum.join(1..0, " = ") == "1 = 0"
assert Enum.join(1..3, " = ") == "1 = 2 = 3"
assert Enum.join(1..3) == "123"
end
test "map/2" do
assert Enum.map(1..3, fn x -> x * 2 end) == [2, 4, 6]
assert Enum.map(-1..-3, fn x -> x * 2 end) == [-2, -4, -6]
end
test "map_every/3" do
assert Enum.map_every(1..10, 2, fn x -> x * 2 end) == [2, 2, 6, 4, 10, 6, 14, 8, 18, 10]
assert Enum.map_every(-1..-10, 2, fn x -> x * 2 end) ==
[-2, -2, -6, -4, -10, -6, -14, -8, -18, -10]
assert Enum.map_every(1..2, 2, fn x -> x * 2 end) == [2, 2]
assert Enum.map_every(1..3, 0, fn x -> x * 2 end) == [1, 2, 3]
assert_raise FunctionClauseError, fn ->
Enum.map_every(1..3, -1, fn x -> x * 2 end)
end
end
test "map_join/3" do
assert Enum.map_join(1..0, " = ", &(&1 * 2)) == "2 = 0"
assert Enum.map_join(1..3, " = ", &(&1 * 2)) == "2 = 4 = 6"
assert Enum.map_join(1..3, &(&1 * 2)) == "246"
end
test "map_reduce/3" do
assert Enum.map_reduce(1..0, 1, fn x, acc -> {x * 2, x + acc} end) == {[2, 0], 2}
assert Enum.map_reduce(1..3, 1, fn x, acc -> {x * 2, x + acc} end) == {[2, 4, 6], 7}
end
test "max/1" do
assert Enum.max(1..1) == 1
assert Enum.max(1..3) == 3
assert Enum.max(3..1) == 3
end
test "max_by/2" do
assert Enum.max_by(1..1, fn x -> :math.pow(-2, x) end) == 1
assert Enum.max_by(1..3, fn x -> :math.pow(-2, x) end) == 2
end
test "member?/2" do
assert Enum.member?(1..3, 2)
refute Enum.member?(1..3, 0)
end
test "min/1" do
assert Enum.min(1..1) == 1
assert Enum.min(1..3) == 1
end
test "min_by/2" do
assert Enum.min_by(1..1, fn x -> :math.pow(-2, x) end) == 1
assert Enum.min_by(1..3, fn x -> :math.pow(-2, x) end) == 3
end
test "min_max/1" do
assert Enum.min_max(1..1) == {1, 1}
assert Enum.min_max(1..3) == {1, 3}
assert Enum.min_max(3..1) == {1, 3}
end
test "min_max_by/2" do
assert Enum.min_max_by(1..1, fn x -> x end) == {1, 1}
assert Enum.min_max_by(1..3, fn x -> x end) == {1, 3}
end
test "split_with/2" do
assert Enum.split_with(1..3, fn x -> rem(x, 2) == 0 end) == {[2], [1, 3]}
end
test "random/1" do
# corner cases, independent of the seed
assert Enum.random(1..1) == 1
# set a fixed seed so the test can be deterministic
# please note the order of following assertions is important
seed1 = {1406, 407_414, 139_258}
seed2 = {1306, 421_106, 567_597}
:rand.seed(:exsplus, seed1)
assert Enum.random(1..2) == 1
assert Enum.random(1..3) == 2
assert Enum.random(3..1) == 1
:rand.seed(:exsplus, seed2)
assert Enum.random(1..2) == 1
assert Enum.random(1..3) == 3
end
test "reduce/2" do
assert Enum.reduce(1..3, fn x, acc -> x + acc end) == 6
end
test "reduce/3" do
assert Enum.reduce(1..0, 1, fn x, acc -> x + acc end) == 2
assert Enum.reduce(1..3, 1, fn x, acc -> x + acc end) == 7
end
test "reduce_while/3" do
assert Enum.reduce_while(1..100, 0, fn i, acc ->
if i <= 3, do: {:cont, acc + i}, else: {:halt, acc}
end) == 6
end
test "reject/2" do
assert Enum.reject(1..3, fn x -> rem(x, 2) == 0 end) == [1, 3]
assert Enum.reject(1..6, fn x -> rem(x, 2) == 0 end) == [1, 3, 5]
end
test "reverse/1" do
assert Enum.reverse(0..0) == [0]
assert Enum.reverse(1..3) == [3, 2, 1]
assert Enum.reverse(-3..5) == [5, 4, 3, 2, 1, 0, -1, -2, -3]
assert Enum.reverse(5..5) == [5]
end
test "reverse/2" do
assert Enum.reverse(1..3, 4..6) == [3, 2, 1, 4, 5, 6]
assert Enum.reverse([1, 2, 3], 4..6) == [3, 2, 1, 4, 5, 6]
assert Enum.reverse(1..3, [4, 5, 6]) == [3, 2, 1, 4, 5, 6]
assert Enum.reverse(-3..5, MapSet.new([-3, -2])) == [5, 4, 3, 2, 1, 0, -1, -2, -3, -3, -2]
assert Enum.reverse(5..5, [5]) == [5, 5]
end
test "reverse_slice/3" do
assert Enum.reverse_slice(1..6, 2, 0) == [1, 2, 3, 4, 5, 6]
assert Enum.reverse_slice(1..6, 2, 2) == [1, 2, 4, 3, 5, 6]
assert Enum.reverse_slice(1..6, 2, 4) == [1, 2, 6, 5, 4, 3]
assert Enum.reverse_slice(1..6, 2, 10_000_000) == [1, 2, 6, 5, 4, 3]
assert Enum.reverse_slice(1..6, 10_000_000, 4) == [1, 2, 3, 4, 5, 6]
assert Enum.reverse_slice(1..6, 50, 50) == [1, 2, 3, 4, 5, 6]
end
test "scan/2" do
assert Enum.scan(1..5, &(&1 + &2)) == [1, 3, 6, 10, 15]
end
test "scan/3" do
assert Enum.scan(1..5, 0, &(&1 + &2)) == [1, 3, 6, 10, 15]
end
test "shuffle/1" do
# set a fixed seed so the test can be deterministic
:rand.seed(:exsplus, {1374, 347_975, 449_264})
assert Enum.shuffle(1..5) == [2, 1, 3, 5, 4]
end
test "slice/2" do
assert Enum.slice(1..5, 0..0) == [1]
assert Enum.slice(1..5, 0..1) == [1, 2]
assert Enum.slice(1..5, 0..2) == [1, 2, 3]
assert Enum.slice(1..5, 1..2) == [2, 3]
assert Enum.slice(1..5, 1..0) == []
assert Enum.slice(1..5, 2..5) == [3, 4, 5]
assert Enum.slice(1..5, 2..6) == [3, 4, 5]
assert Enum.slice(1..5, 4..4) == [5]
assert Enum.slice(1..5, 5..5) == []
assert Enum.slice(1..5, 6..5) == []
assert Enum.slice(1..5, 6..0) == []
assert Enum.slice(1..5, -6..0) == []
assert Enum.slice(1..5, -6..5) == []
assert Enum.slice(1..5, -5..-1) == [1, 2, 3, 4, 5]
assert Enum.slice(1..5, -5..-3) == [1, 2, 3]
assert Enum.slice(1..5, -6..-1) == []
assert_raise ArgumentError, fn ->
x = 1.1
Enum.slice(1..5, x..2)
end
assert_raise ArgumentError, fn ->
x = 1.9
Enum.slice(1..5, 1..x)
end
assert Enum.slice(5..1, 0..0) == [5]
assert Enum.slice(5..1, 0..1) == [5, 4]
assert Enum.slice(5..1, 0..2) == [5, 4, 3]
assert Enum.slice(5..1, 1..2) == [4, 3]
assert Enum.slice(5..1, 1..0) == []
assert Enum.slice(5..1, 2..5) == [3, 2, 1]
assert Enum.slice(5..1, 2..6) == [3, 2, 1]
assert Enum.slice(5..1, 4..4) == [1]
assert Enum.slice(5..1, 5..5) == []
assert Enum.slice(5..1, 6..5) == []
assert Enum.slice(5..1, 6..0) == []
assert Enum.slice(5..1, -6..0) == []
assert Enum.slice(5..1, -6..5) == []
assert Enum.slice(5..1, -5..-1) == [5, 4, 3, 2, 1]
assert Enum.slice(5..1, -5..-3) == [5, 4, 3]
assert Enum.slice(5..1, -6..-1) == []
end
test "slice/3" do
assert Enum.slice(1..5, 0, 0) == []
assert Enum.slice(1..5, 0, 1) == [1]
assert Enum.slice(1..5, 0, 2) == [1, 2]
assert Enum.slice(1..5, 1, 2) == [2, 3]
assert Enum.slice(1..5, 1, 0) == []
assert Enum.slice(1..5, 2, 3) == [3, 4, 5]
assert Enum.slice(1..5, 2, 6) == [3, 4, 5]
assert Enum.slice(1..5, 5, 5) == []
assert Enum.slice(1..5, 6, 5) == []
assert Enum.slice(1..5, 6, 0) == []
assert Enum.slice(1..5, -6, 0) == []
assert Enum.slice(1..5, -6, 5) == []
assert Enum.slice(1..5, -2, 5) == [4, 5]
assert Enum.slice(1..5, -3, 1) == [3]
assert_raise FunctionClauseError, fn ->
Enum.slice(1..5, 0, -1)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(1..5, 0.99, 0)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(1..5, 0, 0.99)
end
assert Enum.slice(5..1, 0, 0) == []
assert Enum.slice(5..1, 0, 1) == [5]
assert Enum.slice(5..1, 0, 2) == [5, 4]
assert Enum.slice(5..1, 1, 2) == [4, 3]
assert Enum.slice(5..1, 1, 0) == []
assert Enum.slice(5..1, 2, 3) == [3, 2, 1]
assert Enum.slice(5..1, 2, 6) == [3, 2, 1]
assert Enum.slice(5..1, 4, 4) == [1]
assert Enum.slice(5..1, 5, 5) == []
assert Enum.slice(5..1, 6, 5) == []
assert Enum.slice(5..1, 6, 0) == []
assert Enum.slice(5..1, -6, 0) == []
assert Enum.slice(5..1, -6, 5) == []
end
test "sort/1" do
assert Enum.sort(3..1) == [1, 2, 3]
assert Enum.sort(2..1) == [1, 2]
assert Enum.sort(1..1) == [1]
end
test "sort/2" do
assert Enum.sort(3..1, &(&1 > &2)) == [3, 2, 1]
assert Enum.sort(2..1, &(&1 > &2)) == [2, 1]
assert Enum.sort(1..1, &(&1 > &2)) == [1]
end
test "sort_by/2" do
assert Enum.sort_by(3..1, & &1) == [1, 2, 3]
end
test "split/2" do
assert Enum.split(1..3, 0) == {[], [1, 2, 3]}
assert Enum.split(1..3, 1) == {[1], [2, 3]}
assert Enum.split(1..3, 2) == {[1, 2], [3]}
assert Enum.split(1..3, 3) == {[1, 2, 3], []}
assert Enum.split(1..3, 4) == {[1, 2, 3], []}
assert Enum.split(1..3, -1) == {[1, 2], [3]}
assert Enum.split(1..3, -2) == {[1], [2, 3]}
assert Enum.split(1..3, -3) == {[], [1, 2, 3]}
assert Enum.split(1..3, -10) == {[], [1, 2, 3]}
assert Enum.split(1..0, 3) == {[1, 0], []}
end
test "split_while/2" do
assert Enum.split_while(1..3, fn _ -> false end) == {[], [1, 2, 3]}
assert Enum.split_while(1..3, fn _ -> nil end) == {[], [1, 2, 3]}
assert Enum.split_while(1..3, fn _ -> true end) == {[1, 2, 3], []}
assert Enum.split_while(1..3, fn x -> x > 2 end) == {[], [1, 2, 3]}
assert Enum.split_while(1..3, fn x -> x > 3 end) == {[], [1, 2, 3]}
assert Enum.split_while(1..3, fn x -> x < 3 end) == {[1, 2], [3]}
assert Enum.split_while(1..3, fn x -> x end) == {[1, 2, 3], []}
assert Enum.split_while(1..0, fn _ -> true end) == {[1, 0], []}
end
test "sum/1" do
assert Enum.sum(0..0) == 0
assert Enum.sum(1..1) == 1
assert Enum.sum(1..3) == 6
assert Enum.sum(0..100) == 5050
assert Enum.sum(10..100) == 5005
assert Enum.sum(100..10) == 5005
assert Enum.sum(-10..-20) == -165
assert Enum.sum(-10..2) == -52
end
test "take/2" do
assert Enum.take(1..3, 0) == []
assert Enum.take(1..3, 1) == [1]
assert Enum.take(1..3, 2) == [1, 2]
assert Enum.take(1..3, 3) == [1, 2, 3]
assert Enum.take(1..3, 4) == [1, 2, 3]
assert Enum.take(1..3, -1) == [3]
assert Enum.take(1..3, -2) == [2, 3]
assert Enum.take(1..3, -4) == [1, 2, 3]
assert Enum.take(1..0, 3) == [1, 0]
end
test "take_every/2" do
assert Enum.take_every(1..10, 2) == [1, 3, 5, 7, 9]
assert Enum.take_every(1..2, 2) == [1]
assert Enum.take_every(1..3, 0) == []
assert_raise FunctionClauseError, fn ->
Enum.take_every(1..3, -1)
end
end
test "take_random/2" do
# corner cases, independent of the seed
assert_raise FunctionClauseError, fn -> Enum.take_random(1..2, -1) end
assert Enum.take_random(1..1, 0) == []
assert Enum.take_random(1..1, 1) == [1]
assert Enum.take_random(1..1, 2) == [1]
assert Enum.take_random(1..2, 0) == []
# set a fixed seed so the test can be deterministic
# please note the order of following assertions is important
seed1 = {1406, 407_414, 139_258}
seed2 = {1406, 421_106, 567_597}
:rand.seed(:exsplus, seed1)
assert Enum.take_random(1..3, 1) == [2]
assert Enum.take_random(1..3, 2) == [3, 1]
assert Enum.take_random(1..3, 3) == [1, 3, 2]
assert Enum.take_random(1..3, 4) == [2, 3, 1]
assert Enum.take_random(3..1, 1) == [3]
:rand.seed(:exsplus, seed2)
assert Enum.take_random(1..3, 1) == [3]
assert Enum.take_random(1..3, 2) == [1, 2]
assert Enum.take_random(1..3, 3) == [1, 2, 3]
assert Enum.take_random(1..3, 4) == [2, 1, 3]
# make sure optimizations don't change fixed seeded tests
:rand.seed(:exsplus, {101, 102, 103})
one = Enum.take_random(1..100, 1)
:rand.seed(:exsplus, {101, 102, 103})
two = Enum.take_random(1..100, 2)
assert hd(one) == hd(two)
end
test "take_while/2" do
assert Enum.take_while(1..3, fn x -> x > 3 end) == []
assert Enum.take_while(1..3, fn x -> x <= 1 end) == [1]
assert Enum.take_while(1..3, fn x -> x <= 3 end) == [1, 2, 3]
assert Enum.take_while(1..3, fn x -> x end) == [1, 2, 3]
assert Enum.take_while(1..3, fn _ -> nil end) == []
end
test "to_list/1" do
assert Enum.to_list([1, 2, 3]) == [1, 2, 3]
assert Enum.to_list(MapSet.new(1..3)) == [1, 2, 3]
assert Enum.to_list(1..3) == [1, 2, 3]
end
test "uniq/1" do
assert Enum.uniq(1..3) == [1, 2, 3]
end
test "uniq_by/2" do
assert Enum.uniq_by(1..3, fn x -> x end) == [1, 2, 3]
end
test "unzip/1" do
assert_raise FunctionClauseError, fn -> Enum.unzip(1..3) end
end
test "with_index/2" do
assert Enum.with_index(1..3) == [{1, 0}, {2, 1}, {3, 2}]
assert Enum.with_index(1..3, 3) == [{1, 3}, {2, 4}, {3, 5}]
end
test "zip/2" do
assert Enum.zip([:a, :b], 1..2) == [{:a, 1}, {:b, 2}]
assert Enum.zip([:a, :b], 1..4) == [{:a, 1}, {:b, 2}]
assert Enum.zip([:a, :b, :c, :d], 1..2) == [{:a, 1}, {:b, 2}]
assert Enum.zip(1..2, [:a, :b]) == [{1, :a}, {2, :b}]
assert Enum.zip(1..4, [:a, :b]) == [{1, :a}, {2, :b}]
assert Enum.zip(1..2, [:a, :b, :c, :d]) == [{1, :a}, {2, :b}]
assert Enum.zip(1..2, 1..2) == [{1, 1}, {2, 2}]
assert Enum.zip(1..4, 1..2) == [{1, 1}, {2, 2}]
assert Enum.zip(1..2, 1..4) == [{1, 1}, {2, 2}]
end
end
defmodule EnumTest.Map do
# Maps use different protocols path than lists and ranges in the cases below.
use ExUnit.Case, async: true
test "random/1" do
map = %{a: 1, b: 2, c: 3}
seed1 = {1406, 407_414, 139_258}
seed2 = {1406, 421_106, 567_597}
:rand.seed(:exsplus, seed1)
assert Enum.random(map) == {:c, 3}
assert Enum.random(map) == {:b, 2}
assert Enum.random(map) == {:c, 3}
:rand.seed(:exsplus, seed2)
assert Enum.random(map) == {:a, 1}
assert Enum.random(map) == {:a, 1}
end
test "take_random/2" do
# corner cases, independent of the seed
assert_raise FunctionClauseError, fn -> Enum.take_random(1..2, -1) end
assert Enum.take_random(%{a: 1}, 0) == []
assert Enum.take_random(%{a: 1}, 2) == [a: 1]
assert Enum.take_random(%{a: 1, b: 2}, 0) == []
# set a fixed seed so the test can be deterministic
# please note the order of following assertions is important
map = %{a: 1, b: 2, c: 3}
seed1 = {1406, 407_414, 139_258}
seed2 = {1406, 421_106, 567_597}
:rand.seed(:exsplus, seed1)
assert Enum.take_random(map, 1) == [b: 2]
assert Enum.take_random(map, 2) == [c: 3, a: 1]
assert Enum.take_random(map, 3) == [a: 1, c: 3, b: 2]
assert Enum.take_random(map, 4) == [b: 2, c: 3, a: 1]
:rand.seed(:exsplus, seed2)
assert Enum.take_random(map, 1) == [c: 3]
assert Enum.take_random(map, 2) == [a: 1, b: 2]
assert Enum.take_random(map, 3) == [a: 1, b: 2, c: 3]
assert Enum.take_random(map, 4) == [b: 2, a: 1, c: 3]
end
test "reverse/1" do
assert Enum.reverse(%{}) == []
assert Enum.reverse(MapSet.new()) == []
assert Enum.reverse(%{a: 1, b: 2, c: 3}) == [c: 3, b: 2, a: 1]
end
test "reverse/2" do
assert Enum.reverse([a: 1, b: 2, c: 3, a: 1], %{x: 1, y: 2, z: 3}) ==
[a: 1, c: 3, b: 2, a: 1, x: 1, y: 2, z: 3]
assert Enum.reverse([], %{a: 1}) == [a: 1]
assert Enum.reverse([], %{}) == []
assert Enum.reverse(%{a: 1}, []) == [a: 1]
assert Enum.reverse(MapSet.new(), %{}) == []
end
test "fetch/2" do
map = %{a: 1, b: 2, c: 3, d: 4, e: 5}
assert Enum.fetch(map, 0) == {:ok, {:a, 1}}
assert Enum.fetch(map, -2) == {:ok, {:d, 4}}
assert Enum.fetch(map, -6) == :error
assert Enum.fetch(map, 5) == :error
assert Enum.fetch(%{}, 0) == :error
assert Stream.take(map, 3) |> Enum.fetch(3) == :error
assert Stream.take(map, 5) |> Enum.fetch(4) == {:ok, {:e, 5}}
end
test "slice/2" do
map = %{a: 1, b: 2, c: 3, d: 4, e: 5}
assert Enum.slice(map, 0..0) == [a: 1]
assert Enum.slice(map, 0..1) == [a: 1, b: 2]
assert Enum.slice(map, 0..2) == [a: 1, b: 2, c: 3]
end
test "slice/3" do
map = %{a: 1, b: 2, c: 3, d: 4, e: 5}
assert Enum.slice(map, 1, 2) == [b: 2, c: 3]
assert Enum.slice(map, 1, 0) == []
assert Enum.slice(map, 2, 5) == [c: 3, d: 4, e: 5]
assert Enum.slice(map, 2, 6) == [c: 3, d: 4, e: 5]
assert Enum.slice(map, 5, 5) == []
assert Enum.slice(map, 6, 5) == []
assert Enum.slice(map, 6, 0) == []
assert Enum.slice(map, -6, 0) == []
assert Enum.slice(map, -6, 5) == []
assert Enum.slice(map, -2, 5) == [d: 4, e: 5]
assert Enum.slice(map, -3, 1) == [c: 3]
assert_raise FunctionClauseError, fn ->
Enum.slice(map, 0, -1)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(map, 0.99, 0)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(map, 0, 0.99)
end
assert Enum.slice(map, 0, 0) == []
assert Enum.slice(map, 0, 1) == [a: 1]
assert Enum.slice(map, 0, 2) == [a: 1, b: 2]
assert Enum.slice(map, 1, 2) == [b: 2, c: 3]
assert Enum.slice(map, 1, 0) == []
assert Enum.slice(map, 2, 5) == [c: 3, d: 4, e: 5]
assert Enum.slice(map, 2, 6) == [c: 3, d: 4, e: 5]
assert Enum.slice(map, 5, 5) == []
assert Enum.slice(map, 6, 5) == []
assert Enum.slice(map, 6, 0) == []
assert Enum.slice(map, -6, 0) == []
assert Enum.slice(map, -6, 5) == []
assert Enum.slice(map, -2, 5) == [d: 4, e: 5]
assert Enum.slice(map, -3, 1) == [c: 3]
assert_raise FunctionClauseError, fn ->
Enum.slice(map, 0, -1)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(map, 0.99, 0)
end
assert_raise FunctionClauseError, fn ->
Enum.slice(map, 0, 0.99)
end
end
end
defmodule EnumTest.SideEffects do
use ExUnit.Case, async: true
import ExUnit.CaptureIO
import PathHelpers
test "take/2 with side effects" do
stream =
Stream.unfold(1, fn x ->
IO.puts(x)
{x, x + 1}
end)
assert capture_io(fn ->
Enum.take(stream, 1)
end) == "1\n"
end
test "take/2 does not consume next without a need" do
path = tmp_path("oneliner.txt")
File.mkdir(Path.dirname(path))
try do
File.write!(path, "ONE")
File.open!(path, [], fn file ->
iterator = IO.stream(file, :line)
assert Enum.take(iterator, 1) == ["ONE"]
assert Enum.take(iterator, 5) == []
end)
after
File.rm(path)
end
end
test "take/2 with no item works as no-op" do
iterator = File.stream!(fixture_path("unknown.txt"))
assert Enum.take(iterator, 0) == []
assert Enum.take(iterator, 0) == []
assert Enum.take(iterator, 0) == []
assert Enum.take(iterator, 0) == []
end
end
defmodule EnumTest.Function do
use ExUnit.Case, async: true
test "raises Protocol.UndefinedError for funs of wrong arity" do
assert_raise Protocol.UndefinedError, fn ->
Enum.to_list(fn -> nil end)
end
end
end