Add unit test for circular observed pointers.

No functional change.

We may encounter such a situation in the future (e.g. to handle
cleanup for XFA JavaScript bound objects under one design). Be
sure that it works today without any memory safety issues.

Change-Id: I2894a93da632657d573c813211d073b7fc37b091
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52830
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcrt/observable_unittest.cpp b/core/fxcrt/observable_unittest.cpp
index 5c55805..4f86aba 100644
--- a/core/fxcrt/observable_unittest.cpp
+++ b/core/fxcrt/observable_unittest.cpp
@@ -14,11 +14,15 @@
 
 class PseudoObservable final : public Observable<PseudoObservable> {
  public:
-  PseudoObservable() {}
   int SomeMethod() { return 42; }
   size_t ActiveObservedPtrs() const { return ActiveObserversForTesting(); }
 };
 
+class SelfObservable final : public Observable<SelfObservable> {
+ public:
+  ObservedPtr m_pOther;
+};
+
 }  // namespace
 
 TEST(ObservePtr, Null) {
@@ -185,4 +189,24 @@
   EXPECT_TRUE(obj1_bool);
 }
 
+TEST(ObservePtr, SelfObservable) {
+  SelfObservable thing;
+  thing.m_pOther.Reset(&thing);
+  EXPECT_EQ(&thing, thing.m_pOther.Get());
+  // Must be no ASAN violations upon cleanup here.
+}
+
+TEST(ObservePtr, PairwiseObservable) {
+  SelfObservable thing1;
+  {
+    SelfObservable thing2;
+    thing1.m_pOther.Reset(&thing2);
+    thing2.m_pOther.Reset(&thing1);
+    EXPECT_EQ(&thing2, thing1.m_pOther.Get());
+    EXPECT_EQ(&thing1, thing2.m_pOther.Get());
+  }
+  EXPECT_EQ(nullptr, thing1.m_pOther.Get());
+  // Must be no ASAN violations upon cleanup here.
+}
+
 }  // namespace fxcrt