blob: 339996e9d9dfa7c6cdc737fb421dd0e8a1988a62 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <unordered_map>
#include <vector>
#include "base/containers/flat_set.h"
#include "base/test/test_mock_time_task_runner.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/test/compositor_frame_helpers.h"
#include "components/viz/test/surface_id_allocator_set.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::ElementsAre;
using testing::IsEmpty;
using testing::SizeIs;
using testing::UnorderedElementsAre;
namespace viz {
namespace {
constexpr FrameSinkId kFrameSink1(1, 0);
constexpr FrameSinkId kFrameSink2(2, 0);
constexpr FrameSinkId kFrameSink3(3, 0);
} // namespace
// Tests for reference tracking in CompositorFrameSinkSupport and
// SurfaceManager.
class SurfaceReferencesTest : public testing::Test {
public:
SurfaceReferencesTest()
: task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>()),
scoped_context_(task_runner_.get()) {}
SurfaceManager& GetSurfaceManager() { return *manager_->surface_manager(); }
// Creates a new Surface with the provided |frame_sink_id| and |local_id|.
// Will first create a Surfacesupport for |frame_sink_id| if necessary.
SurfaceId CreateSurface(const FrameSinkId& frame_sink_id,
uint32_t parent_id) {
SurfaceId surface_id =
allocator_set_.MakeSurfaceId(frame_sink_id, parent_id);
GetCompositorFrameSinkSupport(frame_sink_id)
.SubmitCompositorFrame(surface_id.local_surface_id(),
MakeDefaultCompositorFrame());
return surface_id;
}
// Destroy Surface with |surface_id|.
void DestroySurface(const SurfaceId& surface_id) {
GetCompositorFrameSinkSupport(surface_id.frame_sink_id())
.EvictSurface(surface_id.local_surface_id());
}
CompositorFrameSinkSupport& GetCompositorFrameSinkSupport(
const FrameSinkId& frame_sink_id) {
auto& support_ptr = supports_[frame_sink_id];
if (!support_ptr) {
manager_->RegisterFrameSinkId(frame_sink_id,
true /* report_activation */);
constexpr bool is_root = false;
support_ptr = std::make_unique<CompositorFrameSinkSupport>(
nullptr, manager_.get(), frame_sink_id, is_root);
}
return *support_ptr;
}
void DestroyCompositorFrameSinkSupport(const FrameSinkId& frame_sink_id) {
auto support_ptr = supports_.find(frame_sink_id);
ASSERT_NE(support_ptr, supports_.end());
supports_.erase(support_ptr);
manager_->InvalidateFrameSinkId(frame_sink_id, {});
}
void RemoveSurfaceReference(const SurfaceId& parent_id,
const SurfaceId& child_id) {
manager_->surface_manager()->RemoveSurfaceReferences(
{SurfaceReference(parent_id, child_id)});
}
void AddSurfaceReference(const SurfaceId& parent_id,
const SurfaceId& child_id) {
manager_->surface_manager()->AddSurfaceReferences(
{SurfaceReference(parent_id, child_id)});
}
// Returns all the references where |surface_id| is the parent.
const base::flat_set<SurfaceId>& GetReferencesFrom(
const SurfaceId& surface_id) {
return GetSurfaceManager().GetSurfacesReferencedByParent(surface_id);
}
// Returns all the references where |surface_id| is the child.
const base::flat_set<SurfaceId> GetReferencesFor(
const SurfaceId& surface_id) {
return GetSurfaceManager().GetSurfacesThatReferenceChildForTesting(
surface_id);
}
// Temporary references are stored as a map in SurfaceManager. This method
// converts the map to a vector.
std::vector<SurfaceId> GetAllTempReferences() {
std::vector<SurfaceId> temp_references;
for (auto& map_entry : GetSurfaceManager().temporary_references_)
temp_references.push_back(map_entry.first);
return temp_references;
}
bool IsTemporaryReferenceTimerRunning() const {
return manager_->surface_manager()->expire_timer_->IsRunning();
}
protected:
// testing::Test:
void SetUp() override {
// Start each test with a fresh SurfaceManager instance.
manager_ = std::make_unique<FrameSinkManagerImpl>(
FrameSinkManagerImpl::InitParams());
}
void TearDown() override {
supports_.clear();
manager_.reset();
}
// Use a TestMockTimeTaskRunner so we can test timer behaviour in |manager_|.
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
base::TestMockTimeTaskRunner::ScopedContext scoped_context_;
std::unique_ptr<FrameSinkManagerImpl> manager_;
std::unordered_map<FrameSinkId,
std::unique_ptr<CompositorFrameSinkSupport>,
FrameSinkIdHash>
supports_;
SurfaceIdAllocatorSet allocator_set_;
};
TEST_F(SurfaceReferencesTest, AddReference) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
EXPECT_THAT(GetReferencesFor(id1),
UnorderedElementsAre(GetSurfaceManager().GetRootSurfaceId()));
EXPECT_THAT(GetReferencesFrom(id1), IsEmpty());
}
TEST_F(SurfaceReferencesTest, AddRemoveReference) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
SurfaceId id2 = CreateSurface(kFrameSink2, 1);
AddSurfaceReference(id1, id2);
EXPECT_THAT(GetReferencesFor(id1),
UnorderedElementsAre(GetSurfaceManager().GetRootSurfaceId()));
EXPECT_THAT(GetReferencesFor(id2), UnorderedElementsAre(id1));
EXPECT_THAT(GetReferencesFrom(id1), UnorderedElementsAre(id2));
EXPECT_THAT(GetReferencesFrom(id2), IsEmpty());
RemoveSurfaceReference(id1, id2);
EXPECT_THAT(GetReferencesFor(id1), SizeIs(1));
EXPECT_THAT(GetReferencesFor(id2), IsEmpty());
EXPECT_THAT(GetReferencesFrom(id1), IsEmpty());
EXPECT_THAT(GetReferencesFrom(id2), IsEmpty());
}
TEST_F(SurfaceReferencesTest, NewSurfaceFromFrameSink) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
SurfaceId id2 = CreateSurface(kFrameSink2, 1);
SurfaceId id3 = CreateSurface(kFrameSink3, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
AddSurfaceReference(id1, id2);
AddSurfaceReference(id2, id3);
// |kFramesink2| received a CompositorFrame with a new size, so it destroys
// |id2| and creates |id2_next|. No reference have been removed yet.
SurfaceId id2_next = CreateSurface(kFrameSink2, 2);
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2_next));
// Add references to and from |id2_next|.
AddSurfaceReference(id1, id2_next);
AddSurfaceReference(id2_next, id3);
EXPECT_THAT(GetReferencesFor(id2), UnorderedElementsAre(id1));
EXPECT_THAT(GetReferencesFor(id2_next), UnorderedElementsAre(id1));
EXPECT_THAT(GetReferencesFor(id3), UnorderedElementsAre(id2, id2_next));
RemoveSurfaceReference(id1, id2);
GetSurfaceManager().GarbageCollectSurfaces();
EXPECT_THAT(GetReferencesFor(id2), IsEmpty());
EXPECT_THAT(GetReferencesFor(id2_next), UnorderedElementsAre(id1));
EXPECT_THAT(GetReferencesFor(id3), UnorderedElementsAre(id2_next));
// |id2| should be deleted during GC but other surfaces shouldn't.
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2_next));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3));
}
TEST_F(SurfaceReferencesTest, ReferenceCycleGetsDeleted) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
SurfaceId id2 = CreateSurface(kFrameSink2, 1);
SurfaceId id3 = CreateSurface(kFrameSink3, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
AddSurfaceReference(id1, id2);
AddSurfaceReference(id2, id3);
// This reference forms a cycle between id2 and id3.
AddSurfaceReference(id3, id2);
DestroySurface(id3);
DestroySurface(id2);
DestroySurface(id1);
RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
GetSurfaceManager().GarbageCollectSurfaces();
// Removing the reference from the root to id1 should allow all three surfaces
// to be deleted during GC even with a cycle between 2 and 3.
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1));
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id3));
}
TEST_F(SurfaceReferencesTest, SurfacesAreDeletedDuringGarbageCollection) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
SurfaceId id2 = CreateSurface(kFrameSink2, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
AddSurfaceReference(id1, id2);
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id1));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
// Destroying the surfaces shouldn't delete them yet, since there is still an
// active reference on all surfaces.
DestroySurface(id1);
DestroySurface(id2);
GetSurfaceManager().GarbageCollectSurfaces();
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id1));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
// Should delete |id2| when the only reference to it is removed.
RemoveSurfaceReference(id1, id2);
GetSurfaceManager().GarbageCollectSurfaces();
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
// Should delete |id1| when the only reference to it is removed.
RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
GetSurfaceManager().GarbageCollectSurfaces();
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1));
}
TEST_F(SurfaceReferencesTest, GarbageCollectionWorksRecursively) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
SurfaceId id2 = CreateSurface(kFrameSink2, 1);
SurfaceId id3 = CreateSurface(kFrameSink3, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
AddSurfaceReference(id1, id2);
AddSurfaceReference(id2, id3);
DestroySurface(id3);
DestroySurface(id2);
DestroySurface(id1);
GetSurfaceManager().GarbageCollectSurfaces();
// Destroying the surfaces shouldn't delete them yet, since there is still an
// active reference on all surfaces.
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id1));
RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
GetSurfaceManager().GarbageCollectSurfaces();
// Removing the reference from the root to id1 should allow all three surfaces
// to be deleted during GC.
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1));
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id3));
}
// Verify that surfaces marked as live are not garbage collected and any
// dependencies are also not garbage collected.
TEST_F(SurfaceReferencesTest, LiveSurfaceStillReachable) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
SurfaceId id2 = CreateSurface(kFrameSink2, 1);
SurfaceId id3 = CreateSurface(kFrameSink3, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
AddSurfaceReference(id1, id2);
AddSurfaceReference(id2, id3);
ASSERT_THAT(GetAllTempReferences(), IsEmpty());
// Marking |id3| for destruction shouldn't cause it be garbage collected
// because |id2| is still reachable from the root.
DestroySurface(id3);
GetSurfaceManager().GarbageCollectSurfaces();
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3));
// Removing the surface reference to |id2| makes it not reachable from the
// root, however it's not marked as destroyed and is still live. Make sure we
// also don't delete any dependencies, such as |id3|, as well.
RemoveSurfaceReference(id1, id2);
GetSurfaceManager().GarbageCollectSurfaces();
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id3));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
// |id2| is unreachable and destroyed. Garbage collection should delete both
// |id2| and |id3| now.
DestroySurface(id2);
GetSurfaceManager().GarbageCollectSurfaces();
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id3));
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
}
TEST_F(SurfaceReferencesTest, TryAddReferenceSameReferenceTwice) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
SurfaceId id2 = CreateSurface(kFrameSink2, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
AddSurfaceReference(id1, id2);
EXPECT_THAT(GetReferencesFor(id2), SizeIs(1));
EXPECT_THAT(GetReferencesFrom(id1), SizeIs(1));
// The second request should be ignored without crashing.
AddSurfaceReference(id1, id2);
EXPECT_THAT(GetReferencesFor(id2), SizeIs(1));
EXPECT_THAT(GetReferencesFrom(id1), SizeIs(1));
}
TEST_F(SurfaceReferencesTest, AddingSelfReferenceFails) {
SurfaceId id1 = CreateSurface(kFrameSink2, 1);
// A temporary reference must exist to |id1|.
EXPECT_THAT(GetAllTempReferences(), ElementsAre(id1));
EXPECT_THAT(GetReferencesFrom(id1), IsEmpty());
EXPECT_THAT(GetReferencesFor(id1), IsEmpty());
// Try to add a self reference. This should fail.
AddSurfaceReference(id1, id1);
// Adding a self reference should be ignored without crashing. The temporary
// reference to |id1| must still exist.
EXPECT_THAT(GetAllTempReferences(), ElementsAre(id1));
EXPECT_THAT(GetReferencesFrom(id1), IsEmpty());
EXPECT_THAT(GetReferencesFor(id1), IsEmpty());
}
TEST_F(SurfaceReferencesTest, RemovingNonexistantReferenceFails) {
SurfaceId id1 = CreateSurface(kFrameSink1, 1);
SurfaceId id2 = CreateSurface(kFrameSink2, 1);
// Removing non-existent reference should be ignored.
AddSurfaceReference(id1, id2);
RemoveSurfaceReference(id2, id1);
EXPECT_THAT(GetReferencesFrom(id1), SizeIs(1));
EXPECT_THAT(GetReferencesFor(id2), SizeIs(1));
}
TEST_F(SurfaceReferencesTest, AddSurfaceThenReference) {
// Create a new surface.
const SurfaceId surface_id = CreateSurface(kFrameSink2, 1);
// A temporary reference must be added to |surface_id|.
EXPECT_THAT(GetAllTempReferences(), ElementsAre(surface_id));
// Create |parent_id| and add a real reference from it to |surface_id|.
const SurfaceId parent_id = CreateSurface(kFrameSink1, 1);
AddSurfaceReference(parent_id, surface_id);
// The temporary reference to |surface_id| should be gone.
// The only temporary reference should be to |parent_id|.
// There must be a real reference from |parent_id| to |child_id|.
EXPECT_THAT(GetReferencesFrom(parent_id), ElementsAre(surface_id));
EXPECT_THAT(GetAllTempReferences(), ElementsAre(parent_id));
}
TEST_F(SurfaceReferencesTest, AddSurfaceThenRootReference) {
// Create a new surface.
const SurfaceId surface_id = CreateSurface(kFrameSink1, 1);
// Temporary reference should be added to |surface_id|.
EXPECT_THAT(GetAllTempReferences(), ElementsAre(surface_id));
// Add a surface reference from root to |surface_id|.
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), surface_id);
// The temporary reference should be gone and there should now be a surface
// reference from root to |surface_id|.
EXPECT_THAT(GetAllTempReferences(), IsEmpty());
EXPECT_THAT(GetReferencesFrom(GetSurfaceManager().GetRootSurfaceId()),
ElementsAre(surface_id));
}
TEST_F(SurfaceReferencesTest, AddTwoSurfacesThenOneReference) {
// Create two surfaces with different FrameSinkIds.
const SurfaceId surface_id1 = CreateSurface(kFrameSink2, 1);
const SurfaceId surface_id2 = CreateSurface(kFrameSink3, 1);
// Temporary reference should be added for both surfaces.
EXPECT_THAT(GetAllTempReferences(),
UnorderedElementsAre(surface_id1, surface_id2));
// Create |parent_id| and add a real reference from it to |surface_id1|.
const SurfaceId parent_id = CreateSurface(kFrameSink1, 1);
AddSurfaceReference(parent_id, surface_id1);
// Real reference must be added to |surface_id1| and the temporary reference
// to it must be gone.
// There should still be a temporary reference left to |surface_id2|.
// A temporary reference to |parent_id| must be created.
EXPECT_THAT(GetAllTempReferences(),
UnorderedElementsAre(parent_id, surface_id2));
EXPECT_THAT(GetReferencesFrom(parent_id), ElementsAre(surface_id1));
}
TEST_F(SurfaceReferencesTest, AddSurfacesSkipReference) {
// Add two surfaces that have the same FrameSinkId. This would happen
// when a client submits two CompositorFrames before parent submits a new
// CompositorFrame.
const SurfaceId surface_id1 = CreateSurface(kFrameSink2, 1);
const SurfaceId surface_id2 = CreateSurface(kFrameSink2, 2);
// Temporary references should be added for both surfaces and they should be
// stored in the order of creation.
EXPECT_THAT(GetAllTempReferences(),
UnorderedElementsAre(surface_id1, surface_id2));
// Create |parent_id| and add a reference from it to |surface_id2| which was
// created later.
const SurfaceId parent_id = CreateSurface(kFrameSink1, 1);
AddSurfaceReference(parent_id, surface_id2);
// The real reference should be added for |surface_id2| and the temporary
// references to both |surface_id1| and |surface_id2| should be gone.
// There should be a temporary reference to |parent_id|.
EXPECT_THAT(GetAllTempReferences(), ElementsAre(parent_id));
EXPECT_THAT(GetReferencesFrom(parent_id), ElementsAre(surface_id2));
}
TEST_F(SurfaceReferencesTest, RemoveFirstTempReferenceOnly) {
// Add two surfaces that have the same FrameSinkId. This would happen
// when a client submits two CFs before parent submits a new CF.
const SurfaceId surface_id1 = CreateSurface(kFrameSink2, 1);
const SurfaceId surface_id2 = CreateSurface(kFrameSink2, 2);
// Temporary references should be added for both surfaces and they should be
// stored in the order of creation.
EXPECT_THAT(GetAllTempReferences(),
UnorderedElementsAre(surface_id1, surface_id2));
// Create |parent_id| and add a reference from it to |surface_id1| which was
// created earlier.
const SurfaceId parent_id = CreateSurface(kFrameSink1, 1);
AddSurfaceReference(parent_id, surface_id1);
// The real reference should be added for |surface_id1| and its temporary
// reference should be removed. The temporary reference for |surface_id2|
// should remain. A temporary reference must be added for |parent_id|.
EXPECT_THAT(GetAllTempReferences(),
UnorderedElementsAre(parent_id, surface_id2));
EXPECT_THAT(GetReferencesFrom(parent_id), ElementsAre(surface_id1));
}
TEST_F(SurfaceReferencesTest, SurfaceWithTemporaryReferenceIsDeleted) {
const SurfaceId id1 = CreateSurface(kFrameSink1, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
// We create |id2| and never add a real reference to it. This leaves the
// temporary reference.
const SurfaceId id2 = CreateSurface(kFrameSink2, 1);
ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id2));
EXPECT_NE(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
// Destroy both surfaces so they can be garbage collected. We remove the
// surface reference to |id1| which will run GarbageCollectSurfaces().
DestroySurface(id1);
DestroySurface(id2);
RemoveSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), id1);
GetSurfaceManager().GarbageCollectSurfaces();
// |id1| is destroyed and has no references, so it's deleted.
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id1));
// |id2| is destroyed and the temporary reference is dropped, so it's deleted.
EXPECT_EQ(nullptr, GetSurfaceManager().GetSurfaceForId(id2));
}
// Checks that adding a surface reference clears the temporary reference.
TEST_F(SurfaceReferencesTest, InvalidateHasNoEffectOnSurfaceReferences) {
const SurfaceId parent_id = CreateSurface(kFrameSink1, 1);
AddSurfaceReference(GetSurfaceManager().GetRootSurfaceId(), parent_id);
const SurfaceId id1 = CreateSurface(kFrameSink2, 1);
ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id1));
// Adding a real surface reference will remove the temporary reference.
AddSurfaceReference(parent_id, id1);
ASSERT_THAT(GetAllTempReferences(), IsEmpty());
ASSERT_THAT(GetReferencesFor(id1), UnorderedElementsAre(parent_id));
}
// Check that old temporary references are deleted, but only for surfaces marked
// as destroyed.
TEST_F(SurfaceReferencesTest, MarkOldTemporaryReferences) {
constexpr base::TimeDelta kFastForwardTime = base::Seconds(30);
// There are no temporary references so the timer should be stopped.
EXPECT_FALSE(IsTemporaryReferenceTimerRunning());
// Creating the surface should create a temporary reference and start timer.
const SurfaceId id = CreateSurface(kFrameSink2, 1);
ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id));
EXPECT_TRUE(IsTemporaryReferenceTimerRunning());
// The temporary reference should not be marked as old and then deleted
// because the surface is still alive.
task_runner_->FastForwardBy(kFastForwardTime);
ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id));
EXPECT_TRUE(IsTemporaryReferenceTimerRunning());
// After the surface is marked as destroyed, the temporary reference should
// be marked as old then deleted. The timer should stop because there are no
// temporary references.
DestroySurface(id);
task_runner_->FastForwardBy(kFastForwardTime);
ASSERT_THAT(GetAllTempReferences(), IsEmpty());
EXPECT_FALSE(IsTemporaryReferenceTimerRunning());
}
} // namespace viz