2 * Copyright (C) 2013 Google Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "platform/LifecycleNotifier.h"
30 #include "platform/LifecycleObserver.h"
31 #include "platform/heap/Handle.h"
32 #include <gtest/gtest.h>
36 class TestingObserver
;
38 class DummyContext final
: public NoBaseWillBeGarbageCollectedFinalized
<DummyContext
>, public LifecycleNotifier
<DummyContext
, TestingObserver
> {
39 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DummyContext
);
41 static PassOwnPtrWillBeRawPtr
<DummyContext
> create()
43 return adoptPtrWillBeNoop(new DummyContext());
48 LifecycleNotifier
<DummyContext
, TestingObserver
>::trace(visitor
);
52 class TestingObserver final
: public NoBaseWillBeGarbageCollectedFinalized
<TestingObserver
>, public LifecycleObserver
<DummyContext
, TestingObserver
, DummyContext
> {
53 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TestingObserver
);
55 static PassOwnPtrWillBeRawPtr
<TestingObserver
> create(DummyContext
* context
)
57 return adoptPtrWillBeNoop(new TestingObserver(context
));
60 void contextDestroyed() override
62 LifecycleObserver::contextDestroyed();
63 if (m_observerToRemoveOnDestruct
) {
64 lifecycleContext()->removeObserver(m_observerToRemoveOnDestruct
.get());
65 m_observerToRemoveOnDestruct
.clear();
67 m_contextDestroyedCalled
= true;
72 visitor
->trace(m_observerToRemoveOnDestruct
);
73 LifecycleObserver::trace(visitor
);
76 void unobserve() { setContext(nullptr); }
78 void setObserverToRemoveAndDestroy(PassOwnPtrWillBeRawPtr
<TestingObserver
> observerToRemoveOnDestruct
)
80 ASSERT(!m_observerToRemoveOnDestruct
);
81 m_observerToRemoveOnDestruct
= observerToRemoveOnDestruct
;
84 TestingObserver
* innerObserver() const { return m_observerToRemoveOnDestruct
.get(); }
85 bool contextDestroyedCalled() const { return m_contextDestroyedCalled
; }
88 explicit TestingObserver(DummyContext
* context
)
89 : LifecycleObserver(context
)
90 , m_contextDestroyedCalled(false)
94 OwnPtrWillBeMember
<TestingObserver
> m_observerToRemoveOnDestruct
;
95 bool m_contextDestroyedCalled
;
98 TEST(LifecycleContextTest
, shouldObserveContextDestroyed
)
100 OwnPtrWillBeRawPtr
<DummyContext
> context
= DummyContext::create();
101 OwnPtrWillBePersistent
<TestingObserver
> observer
= TestingObserver::create(context
.get());
103 EXPECT_EQ(observer
->lifecycleContext(), context
.get());
104 EXPECT_FALSE(observer
->contextDestroyedCalled());
105 context
->notifyContextDestroyed();
107 Heap::collectAllGarbage();
108 EXPECT_EQ(observer
->lifecycleContext(), static_cast<DummyContext
*>(0));
109 EXPECT_TRUE(observer
->contextDestroyedCalled());
112 TEST(LifecycleContextTest
, shouldNotObserveContextDestroyedIfUnobserve
)
114 OwnPtrWillBeRawPtr
<DummyContext
> context
= DummyContext::create();
115 OwnPtrWillBePersistent
<TestingObserver
> observer
= TestingObserver::create(context
.get());
116 observer
->unobserve();
117 context
->notifyContextDestroyed();
119 Heap::collectAllGarbage();
120 EXPECT_EQ(observer
->lifecycleContext(), static_cast<DummyContext
*>(0));
121 EXPECT_FALSE(observer
->contextDestroyedCalled());
124 TEST(LifecycleContextTest
, observerRemovedDuringNotifyDestroyed
)
126 // FIXME: Oilpan: this test can be removed when the LifecycleNotifier<T>::m_observers
127 // hash set is on the heap and membership is handled implicitly by the garbage collector.
128 OwnPtrWillBeRawPtr
<DummyContext
> context
= DummyContext::create();
129 OwnPtrWillBePersistent
<TestingObserver
> observer
= TestingObserver::create(context
.get());
130 OwnPtrWillBeRawPtr
<TestingObserver
> innerObserver
= TestingObserver::create(context
.get());
131 // Attach the observer to the other. When 'observer' is notified
132 // of destruction, it will remove & destroy 'innerObserver'.
133 observer
->setObserverToRemoveAndDestroy(innerObserver
.release());
135 EXPECT_EQ(observer
->lifecycleContext(), context
.get());
136 EXPECT_EQ(observer
->innerObserver()->lifecycleContext(), context
.get());
137 EXPECT_FALSE(observer
->contextDestroyedCalled());
138 EXPECT_FALSE(observer
->innerObserver()->contextDestroyedCalled());
140 context
->notifyContextDestroyed();
141 EXPECT_EQ(observer
->innerObserver(), nullptr);
143 Heap::collectAllGarbage();
144 EXPECT_EQ(observer
->lifecycleContext(), static_cast<DummyContext
*>(0));
145 EXPECT_TRUE(observer
->contextDestroyedCalled());