From eb18291113c1925b83a2786ea0a700c9834311f9 Mon Sep 17 00:00:00 2001 From: Michael Lamers Date: Fri, 19 Aug 2022 04:34:18 +0200 Subject: [PATCH] fix: use SplayTreeSet to resolve inconsistent hashCodes (#142) --- lib/src/equatable_utils.dart | 7 +++++++ test/equatable_test.dart | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/src/equatable_utils.dart b/lib/src/equatable_utils.dart index 4a18c5b7..e0ae8dd2 100644 --- a/lib/src/equatable_utils.dart +++ b/lib/src/equatable_utils.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:collection/collection.dart'; import 'package:equatable/equatable.dart'; @@ -46,6 +48,11 @@ int _combine(int hash, dynamic object) { }); return hash; } + if (object is Set && object is! SplayTreeSet) { + // this is needed to have a consistent iteration order so that the produced + // hash is consistent independently of the Set insertion order + object = SplayTreeSet.from(object); + } if (object is Iterable) { for (final value in object) { hash = hash ^ _combine(hash, value); diff --git a/test/equatable_test.dart b/test/equatable_test.dart index 40b326b3..0bffe89c 100644 --- a/test/equatable_test.dart +++ b/test/equatable_test.dart @@ -968,6 +968,17 @@ void main() { expect(instanceA.hashCode == instanceB.hashCode, true); }); + test('should return when Set values are same but in different order', () { + final instanceA = SimpleEquatable>( + Set.from(['A', 'B']), + ); + final instanceB = SimpleEquatable>( + Set.from(['B', 'A']), + ); + expect(instanceA == instanceB, true); + expect(instanceA.hashCode == instanceB.hashCode, true); + }); + test('should return when values are different', () { final instanceA = SimpleEquatable>( Set.from(['A', 'B']),