36
37
using namespace testing;
37
38
ON_CALL(*this, mark_as_submitted())
38
39
.WillByDefault(Invoke([this](){this->AgingBuffer::mark_as_submitted();}));
40
// By default we expect all buffers to be destroyed.
41
EXPECT_CALL(*this, Destroy()).Times(1);
44
MOCK_METHOD0(Destroy, void());
45
virtual ~MockBuffer() noexcept
50
42
MOCK_METHOD0(mark_as_submitted, void());
53
45
MOCK_CONST_METHOD0(stride, geom::Stride());
54
46
MOCK_CONST_METHOD0(pixel_format, MirPixelFormat());
55
47
MOCK_CONST_METHOD0(native_buffer_handle, std::shared_ptr<mir::graphics::NativeBuffer>());
48
MOCK_METHOD1(update_from, void(MirBufferPackage const&));
58
51
struct MockClientBufferFactory : public mcl::ClientBufferFactory
60
MockClientBufferFactory()
53
MockClientBufferFactory() :
62
57
using namespace testing;
64
// Some tests, quite reasonably, rely on create_buffer returning a different buffer each time
65
// Handle this by first updating our "buffer" temporary, then returning-by-pointee.
66
58
ON_CALL(*this, create_buffer(_,_,_))
67
.WillByDefault(DoAll(InvokeWithoutArgs([this]() {this->buffer = std::make_shared<NiceMock<MockBuffer>>();}),
68
ReturnPointee(&buffer)));
59
.WillByDefault(InvokeWithoutArgs([this]()
62
auto buffer = std::shared_ptr<mcl::ClientBuffer>(
63
new NiceMock<MockBuffer>(),
64
[this](mcl::ClientBuffer* buffer)
70
first_allocated_buffer = buffer;
75
~MockClientBufferFactory()
77
EXPECT_THAT(alloc_count, testing::Eq(free_count));
71
80
MOCK_METHOD3(create_buffer,
72
81
std::shared_ptr<mcl::ClientBuffer>(std::shared_ptr<MirBufferPackage> const&,
73
82
geom::Size, MirPixelFormat));
75
std::shared_ptr<mcl::ClientBuffer> buffer;
84
bool first_buffer_allocated_and_then_freed()
86
if ((alloc_count >= 1) && (first_allocated_buffer.lock() == nullptr))
93
std::weak_ptr<mcl::ClientBuffer> first_allocated_buffer;
78
96
struct MirBufferDepositoryTest : public testing::Test
265
283
std::shared_ptr<MirBufferPackage> packages[num_packages];
267
285
depository.deposit_package(packages[0], 1, size, pf);
268
// Raw pointer so we don't influence the buffer's life-cycle
269
MockBuffer *first_buffer = static_cast<MockBuffer *>(depository.current_buffer().get());
270
// We expect this to not be destroyed before we deposit the fourth buffer.
271
bool buffer_destroyed = false;
272
ON_CALL(*first_buffer, Destroy()).WillByDefault(Invoke([&buffer_destroyed] () {buffer_destroyed = true;}));
275
286
depository.deposit_package(packages[1], 2, size, pf);
276
287
depository.deposit_package(packages[2], 3, size, pf);
278
289
// We've deposited three different buffers now; the fourth should trigger the destruction
279
290
// of the first buffer.
280
ASSERT_FALSE(buffer_destroyed);
291
EXPECT_THAT(mock_factory->free_count, Eq(0));
282
292
depository.deposit_package(packages[3], 4, size, pf);
284
// Explicitly verify that the buffer has been destroyed here, before the depository goes out of scope
285
// and its destructor cleans everything up.
286
EXPECT_TRUE(buffer_destroyed);
293
EXPECT_THAT(mock_factory->free_count, Eq(1));
294
EXPECT_TRUE(mock_factory->first_buffer_allocated_and_then_freed());
289
297
TEST_F(MirBufferDepositoryTest, depositing_packages_implicitly_submits_current_buffer)
301
309
depository.deposit_package(package2, 2, size, pf);
304
TEST_F(MirBufferDepositoryTest, depository_respects_max_buffer_parameter)
312
TEST_F(MirBufferDepositoryTest, depository_frees_buffers_after_reaching_capacity)
306
314
using namespace testing;
307
315
std::shared_ptr<mcl::ClientBufferDepository> depository;
308
316
std::shared_ptr<MirBufferPackage> packages[10];
309
bool buffer_destroyed[10];
311
318
for (int num_buffers = 2; num_buffers < 10; ++num_buffers)
313
320
depository = std::make_shared<mcl::ClientBufferDepository>(mock_factory, num_buffers);
315
// Reset destroyed tracking; resetting the depository will have destroyed all the buffers
316
for (bool& destroyed_flag : buffer_destroyed)
317
destroyed_flag = false;
321
mock_factory->free_count = 0;
322
mock_factory->alloc_count = 0;
320
325
for (i = 0; i < num_buffers ; ++i)
323
326
depository->deposit_package(packages[i], i + 1, size, pf);
324
buffer = static_cast<MockBuffer *>(depository->current_buffer().get());
325
ON_CALL(*buffer, Destroy()).WillByDefault(Invoke([&buffer_destroyed, i] () {buffer_destroyed[i] = true;}));
328
// Next deposit should destroy first buffer
329
ASSERT_FALSE(buffer_destroyed[0]);
328
// Next deposit should destroy a buffer
329
EXPECT_THAT(mock_factory->free_count, Eq(0));
330
330
depository->deposit_package(packages[i], i+1, size, pf);
331
EXPECT_TRUE(buffer_destroyed[0]);
333
// Verify none of the other buffers have been destroyed
334
for (i = 1; i < num_buffers; ++i)
335
EXPECT_FALSE(buffer_destroyed[i]);
331
EXPECT_THAT(mock_factory->free_count, Eq(1));
332
EXPECT_TRUE(mock_factory->first_buffer_allocated_and_then_freed());
345
342
auto package1 = std::make_shared<MirBufferPackage>();
346
343
auto package2 = std::make_shared<MirBufferPackage>();
348
EXPECT_CALL(*mock_factory, create_buffer(_,_,_))
351
depository.deposit_package(package1, 8, size, pf);
352
depository.deposit_package(package1, 8, size, pf);
353
depository.deposit_package(package1, 8, size, pf);
344
auto package3 = std::make_shared<MirBufferPackage>();
345
NiceMock<MockBuffer> mock_buffer;
347
EXPECT_CALL(*mock_factory, create_buffer(Ref(package1),_,_))
349
.WillOnce(Return(mir::test::fake_shared(mock_buffer)));
350
EXPECT_CALL(mock_buffer, update_from(Ref(*package2)))
352
EXPECT_CALL(mock_buffer, update_from(Ref(*package3)))
355
depository.deposit_package(package1, 8, size, pf);
356
depository.deposit_package(package2, 8, size, pf);
357
depository.deposit_package(package3, 8, size, pf);
356
360
TEST_F(MirBufferDepositoryTest, depository_creates_new_buffer_for_different_id)