Skip to content

Commit 8cb1361

Browse files
committed
Fix diffing for variable structs, closes #9958
1 parent 967f4b4 commit 8cb1361

File tree

2 files changed

+71
-14
lines changed

2 files changed

+71
-14
lines changed

lib/ex_unit/lib/ex_unit/diff.ex

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,12 @@ defmodule ExUnit.Diff do
8282
diff_tuple(Tuple.to_list(left), Tuple.to_list(right), env)
8383
end
8484

85-
defp diff_quoted({:%, _, [struct, {:%{}, _, kw}]}, %{} = right, env)
86-
when is_atom(struct) and is_list(kw) do
87-
diff_quoted_struct([__struct__: struct] ++ kw, struct, right, env)
85+
defp diff_quoted({:%, _, [struct, {:%{}, _, kw}]}, %{} = right, env) when is_list(kw) do
86+
diff_quoted_struct([__struct__: struct] ++ kw, right, env)
8887
end
8988

90-
defp diff_quoted({:%{}, _, items}, %{} = right, env) when is_list(items) do
91-
if struct = items[:__struct__] do
92-
diff_quoted_struct(items, struct, right, env)
93-
else
94-
diff_map(items, right, nil, maybe_struct(right), env)
95-
end
89+
defp diff_quoted({:%{}, _, kw}, %{} = right, env) when is_list(kw) do
90+
diff_quoted_struct(kw, right, env)
9691
end
9792

9893
defp diff_quoted({:<>, _, [literal, _]} = left, right, env)
@@ -628,8 +623,9 @@ defmodule ExUnit.Diff do
628623

629624
# Structs
630625

631-
defp diff_quoted_struct(kw, struct1, right, env) do
632-
left = load_struct(struct1)
626+
defp diff_quoted_struct(kw, right, env) do
627+
struct1 = kw[:__struct__]
628+
left = load_struct(kw[:__struct__])
633629

634630
if left && Enum.all?(kw, fn {k, _} -> Map.has_key?(left, k) end) do
635631
if Macro.quoted_literal?(kw) do
@@ -676,7 +672,8 @@ defmodule ExUnit.Diff do
676672
end
677673

678674
defp load_struct(struct) do
679-
if Code.ensure_loaded?(struct) and function_exported?(struct, :__struct__, 0) do
675+
if is_atom(struct) and struct != nil and
676+
Code.ensure_loaded?(struct) and function_exported?(struct, :__struct__, 0) do
680677
struct.__struct__
681678
end
682679
end

lib/ex_unit/test/ex_unit/diff_test.exs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ defmodule ExUnit.DiffTest do
627627
)
628628
end
629629

630-
test "structs with inspect difference" do
630+
test "structs with same inspect but different" do
631631
refute_diff(
632632
%Opaque{data: 1} = %Opaque{data: 2},
633633
"%ExUnit.DiffTest.Opaque{data: -1-}",
@@ -641,7 +641,7 @@ defmodule ExUnit.DiffTest do
641641
)
642642
end
643643

644-
test "structs without inspect difference outside match" do
644+
test "structs with same inspect but different outside match" do
645645
refute_diff(
646646
%Opaque{data: 1} == %Opaque{data: 2},
647647
"%ExUnit.DiffTest.Opaque{data: -1-}",
@@ -663,6 +663,66 @@ defmodule ExUnit.DiffTest do
663663
)
664664
end
665665

666+
test "structs with matched type" do
667+
pins = %{{:type, nil} => User, {:age, nil} => 33}
668+
669+
# pin on __struct__
670+
assert_diff(
671+
%{__struct__: ^type, age: ^age, name: "john"} = %User{name: "john", age: 33},
672+
[],
673+
pins
674+
)
675+
676+
refute_diff(
677+
%{__struct__: ^type, age: ^age, name: "john"} = %User{name: "jane", age: 33},
678+
"%{__struct__: ^type, age: ^age, name: \"j-oh-n\"}",
679+
"%ExUnit.DiffTest.User{age: 33, name: \"j+a+n+e+\"}",
680+
pins
681+
)
682+
683+
refute_diff(
684+
%{__struct__: ^type, age: ^age, name: "john"} = %User{name: "john", age: 35},
685+
"%{__struct__: ^type, age: -^age-, name: \"john\"}",
686+
"%ExUnit.DiffTest.User{age: 3+5+, name: \"john\"}",
687+
pins
688+
)
689+
690+
refute_diff(
691+
%{__struct__: ^type, age: ^age, name: "john"} = ~D[2020-01-01],
692+
"%{__struct__: -^type-, -age: ^age-, -name: \"john\"-}",
693+
"%+Date+{calendar: Calendar.ISO, day: 1, month: 1, year: 2020}",
694+
pins
695+
)
696+
697+
# pin on %
698+
assert_diff(
699+
%^type{age: ^age, name: "john"} = %User{name: "john", age: 33},
700+
[],
701+
pins
702+
)
703+
704+
refute_diff(
705+
%^type{age: ^age, name: "john"} = %User{name: "jane", age: 33},
706+
"%{__struct__: ^type, age: ^age, name: \"j-oh-n\"}",
707+
"%ExUnit.DiffTest.User{age: 33, name: \"j+a+n+e+\"}",
708+
pins
709+
)
710+
711+
refute_diff(
712+
%^type{age: ^age, name: "john"} = %User{name: "john", age: 35},
713+
"%{__struct__: ^type, age: -^age-, name: \"john\"}",
714+
"%ExUnit.DiffTest.User{age: 3+5+, name: \"john\"}",
715+
pins
716+
)
717+
718+
refute_diff(
719+
%^type{age: ^age, name: "john"} = ~D[2020-01-01],
720+
"%{__struct__: -^type-, -age: ^age-, -name: \"john\"-}",
721+
"%+Date+{calendar: Calendar.ISO, day: 1, month: 1, year: 2020}",
722+
pins
723+
)
724+
end
725+
666726
test "invalid structs" do
667727
refute_diff(
668728
%{__struct__: Unknown} = %{},

0 commit comments

Comments
 (0)