Skip to content

Commit 1b7e6ce

Browse files
committed
Add tests for simultaneous access crash
1 parent 925bc28 commit 1b7e6ce

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

Tests/SwiftyUserDefaultsTests/TestHelpers/DefaultsSerializableSpec.swift

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,43 @@ extension DefaultsSerializableSpec where Serializable.T: Equatable, Serializable
630630
expect(update?.newValue).toEventually(beNil())
631631
}
632632
#endif
633+
634+
then("reference itself in the update closure without crash") {
635+
let key = DefaultsKey<Serializable?>("test")
636+
637+
var update: DefaultsObserver<Serializable?>.Update?
638+
var newValueReferencedDirectly: Serializable?
639+
observer = defaults.observe(key) { receivedUpdate in
640+
update = receivedUpdate
641+
newValueReferencedDirectly = defaults[key: key]
642+
}
643+
defaults[key: key] = self.customValue
644+
645+
expect(update).toEventuallyNot(beNil())
646+
expect(update?.oldValue).toEventually(beNil())
647+
expect(update?.newValue).toEventually(equal(self.customValue))
648+
expect(update?.newValue).toEventually(equal(newValueReferencedDirectly))
649+
}
650+
651+
then("reference itself in the update closure on custom queue without crash") {
652+
let key = DefaultsKey<Serializable?>("test")
653+
654+
var update: DefaultsObserver<Serializable?>.Update?
655+
var newValueReferencedDirectly: Serializable?
656+
observer = defaults.observe(key) { receivedUpdate in
657+
update = receivedUpdate
658+
newValueReferencedDirectly = defaults[key: key]
659+
}
660+
661+
DispatchQueue.global(qos: .utility).async {
662+
defaults[key: key] = self.customValue
663+
}
664+
665+
expect(update).toEventuallyNot(beNil())
666+
expect(update?.oldValue).toEventually(beNil())
667+
expect(update?.newValue).toEventually(equal(self.customValue))
668+
expect(update?.newValue).toEventually(equal(newValueReferencedDirectly))
669+
}
633670

634671
then("remove observer on dispose") {
635672
let key = DefaultsKey<Serializable?>("test")
@@ -776,6 +813,41 @@ extension DefaultsSerializableSpec where Serializable.T: Equatable, Serializable
776813
expect(update?.newValue).toEventually(equal(self.defaultValue))
777814
}
778815
#endif
816+
817+
then("reference itself in the update closure without crash") {
818+
let key = DefaultsKey<Serializable?>("test", defaultValue: self.defaultValue)
819+
820+
var update: DefaultsObserver<Serializable?>.Update?
821+
var newValueReferencedDirectly: Serializable?
822+
observer = defaults.observe(key) { receivedUpdate in
823+
update = receivedUpdate
824+
newValueReferencedDirectly = defaults[key: key]
825+
}
826+
defaults[key: key] = self.customValue
827+
828+
expect(update).toEventuallyNot(beNil())
829+
expect(update?.newValue).toEventually(equal(self.customValue))
830+
expect(update?.newValue).toEventually(equal(newValueReferencedDirectly))
831+
}
832+
833+
then("reference itself in the update closure on custom queue without crash") {
834+
let key = DefaultsKey<Serializable?>("test", defaultValue: self.defaultValue)
835+
836+
var update: DefaultsObserver<Serializable?>.Update?
837+
var newValueReferencedDirectly: Serializable?
838+
observer = defaults.observe(key) { receivedUpdate in
839+
update = receivedUpdate
840+
newValueReferencedDirectly = defaults[key: key]
841+
}
842+
843+
DispatchQueue.global(qos: .utility).async {
844+
defaults[key: key] = self.customValue
845+
}
846+
847+
expect(update).toEventuallyNot(beNil())
848+
expect(update?.newValue).toEventually(equal(self.customValue))
849+
expect(update?.newValue).toEventually(equal(newValueReferencedDirectly))
850+
}
779851

780852
then("remove observer on dispose") {
781853
let key = DefaultsKey<Serializable?>("test", defaultValue: self.defaultValue)
@@ -890,6 +962,41 @@ extension DefaultsSerializableSpec where Serializable.T: Equatable, Serializable
890962
expect(update?.oldValue).toEventually(equal(self.defaultValue))
891963
expect(update?.newValue).toEventually(equal(self.customValue))
892964
}
965+
966+
then("reference itself in the update closure without crash") {
967+
let key = DefaultsKey<Serializable>("test", defaultValue: self.defaultValue)
968+
969+
var update: DefaultsObserver<Serializable>.Update?
970+
var newValueReferencedDirectly: Serializable?
971+
observer = defaults.observe(key) { receivedUpdate in
972+
update = receivedUpdate
973+
newValueReferencedDirectly = defaults[key: key]
974+
}
975+
defaults[key: key] = self.customValue
976+
977+
expect(update).toEventuallyNot(beNil())
978+
expect(update?.newValue).toEventually(equal(self.customValue))
979+
expect(update?.newValue).toEventually(equal(newValueReferencedDirectly))
980+
}
981+
982+
then("reference itself in the update closure on custom queue without crash") {
983+
let key = DefaultsKey<Serializable>("test", defaultValue: self.defaultValue)
984+
985+
var update: DefaultsObserver<Serializable>.Update?
986+
var newValueReferencedDirectly: Serializable?
987+
observer = defaults.observe(key) { receivedUpdate in
988+
update = receivedUpdate
989+
newValueReferencedDirectly = defaults[key: key]
990+
}
991+
992+
DispatchQueue.global(qos: .utility).async {
993+
defaults[key: key] = self.customValue
994+
}
995+
996+
expect(update).toEventuallyNot(beNil())
997+
expect(update?.newValue).toEventually(equal(self.customValue))
998+
expect(update?.newValue).toEventually(equal(newValueReferencedDirectly))
999+
}
8931000

8941001
then("remove observer on dispose") {
8951002
let key = DefaultsKey<Serializable>("test", defaultValue: self.defaultValue)

0 commit comments

Comments
 (0)