~ubuntu-branches/ubuntu/utopic/mir/utopic-proposed

« back to all changes in this revision

Viewing changes to tests/unit-tests/client/test_client_buffer_depository.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Daniel van Vugt
  • Date: 2014-07-17 07:58:53 UTC
  • mfrom: (1.1.67)
  • Revision ID: package-import@ubuntu.com-20140717075853-s4i71ob3iq4ns49z
Tags: 0.5.0+14.10.20140717-0ubuntu1
[ Daniel van Vugt ]
* New upstream release 0.5.0 (https://launchpad.net/mir/+milestone/0.5.0)
  - mirclient ABI unchanged at 8. Clients do not need rebuilding.
  - mirserver ABI bumped to 23. Servers need rebuilding, but probably don't
    need modification:
    . DefaultServerConfiguration/Cursor API: Cursor interfaces changed, most
      notably CursorImages moved from ::mir::graphics to ::mir::input.
    . DefaultServerConfiguration: New "prompt" API.
    . DefaultServerConfiguration: "clock" member is now static.
    . SessionAuthorizer: New functions.
    . ServerConfiguration: New function added: the_prompt_connector().
  - Enhancements:
    . Add AddressSanitizer cmake build type.
    . frontend, client API, tests: add support for prompt session
      permissions and for client detecting errors.
    . server: Ensure our emergency cleanup handling infrastructure is
      signal-safe.
    . Implement and enable an xcursor based image loader for cursors.
    . Fix warnings raised by the new g++-4.9.
    . shared, scene: Introduce a generic listener collection.
    . MirMotionEvent: Define a struct typedef to allow for
      pointer_coordinates to be used individually.
  - Bugs fixed:
    . Nexus 10 leaks during overlay operations (LP: #1331769)
    . MultiThreadedCompositor deadlocks (LP: #1335311)
    . Intermittent test failure in ClientSurfaceEvents can client query 
      orientation (LP: #1335741)
    . Intermittent test failure in ClientSurfaceEvents/OrientationEvents
      (LP: #1335752)
    . Intermittent memory error in ClientSurfaceEvents on
      orientation query (LP: #1335819)
    . mir_unit_tests.EventDistributorTest.* SEGFAULT (LP: #1338902)
    . [regression] Device locks randomly on welcome screen (LP: #1339700)
    . Intermittent deadlock when switching to session with custom display
      config & closing other session (LP: #1340669)
    . Mir cursor has no hotspot setting, assumes (0, 0) (LP: #1189775)
    . clang built mir_unit_tests.ProtobufSocketCommunicatorFD crashes
      intermittently (LP: #1300653)
    . g++-4.9 binary incompatibilities with libraries built with g++-4.8
      (LP: #1329089)
    . [test regression] SurfaceLoop fails sporadically on deleting surfaces
      for a disconnecting client (LP: #1335747)
    . Intermittent test failure ServerShutdown when clients are blocked
      (LP: #1335873)
    . [regression] mir_demo_client_multiwin is displayed with obviously
      wrong colours (LP: #1339471)
    . Partially onscreen surfaces not occluded when covered by another
      surface (LP: #1340078)
    . SurfaceConfigurator::attribute_set always say "unfocused" for focus
      property changes (LP: #1336548)

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include "src/client/aging_buffer.h"
23
23
#include "mir_toolkit/common.h"
24
24
#include "mir/geometry/size.h"
 
25
#include "mir_test/fake_shared.h"
25
26
 
26
27
#include <gtest/gtest.h>
27
28
#include <gmock/gmock.h>
36
37
        using namespace testing;
37
38
        ON_CALL(*this, mark_as_submitted())
38
39
            .WillByDefault(Invoke([this](){this->AgingBuffer::mark_as_submitted();}));
39
 
 
40
 
        // By default we expect all buffers to be destroyed.
41
 
        EXPECT_CALL(*this, Destroy()).Times(1);
42
 
    }
43
 
 
44
 
    MOCK_METHOD0(Destroy, void());
45
 
    virtual ~MockBuffer() noexcept
46
 
    {
47
 
        Destroy();
48
40
    }
49
41
 
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&));
56
49
};
57
50
 
58
51
struct MockClientBufferFactory : public mcl::ClientBufferFactory
59
52
{
60
 
    MockClientBufferFactory()
 
53
    MockClientBufferFactory() :
 
54
        alloc_count(0),
 
55
        free_count(0)
61
56
    {
62
57
        using namespace testing;
63
 
 
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]()
 
60
            {
 
61
                alloc_count++;
 
62
                auto buffer = std::shared_ptr<mcl::ClientBuffer>(
 
63
                    new NiceMock<MockBuffer>(),
 
64
                    [this](mcl::ClientBuffer* buffer)
 
65
                    {
 
66
                        free_count++;
 
67
                        delete buffer;
 
68
                    });
 
69
                if (alloc_count == 1)
 
70
                    first_allocated_buffer = buffer;
 
71
                return buffer;
 
72
            }));
 
73
    }
 
74
 
 
75
    ~MockClientBufferFactory()
 
76
    {
 
77
        EXPECT_THAT(alloc_count, testing::Eq(free_count));
69
78
    }
70
79
 
71
80
    MOCK_METHOD3(create_buffer,
72
81
                 std::shared_ptr<mcl::ClientBuffer>(std::shared_ptr<MirBufferPackage> const&,
73
82
                                                    geom::Size, MirPixelFormat));
74
83
 
75
 
    std::shared_ptr<mcl::ClientBuffer> buffer;
 
84
    bool first_buffer_allocated_and_then_freed()
 
85
    {
 
86
        if ((alloc_count >= 1) && (first_allocated_buffer.lock() == nullptr))
 
87
            return true;
 
88
        return false;
 
89
    }
 
90
 
 
91
    int alloc_count;
 
92
    int free_count;
 
93
    std::weak_ptr<mcl::ClientBuffer> first_allocated_buffer;
76
94
};
77
95
 
78
96
struct MirBufferDepositoryTest : public testing::Test
265
283
    std::shared_ptr<MirBufferPackage> packages[num_packages];
266
284
 
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;}));
273
 
 
274
 
 
275
286
    depository.deposit_package(packages[1], 2, size, pf);
276
287
    depository.deposit_package(packages[2], 3, size, pf);
277
288
 
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);
281
 
 
 
291
    EXPECT_THAT(mock_factory->free_count, Eq(0));
282
292
    depository.deposit_package(packages[3], 4, size, pf);
283
 
 
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());
287
295
}
288
296
 
289
297
TEST_F(MirBufferDepositoryTest, depositing_packages_implicitly_submits_current_buffer)
301
309
    depository.deposit_package(package2, 2, size, pf);
302
310
}
303
311
 
304
 
TEST_F(MirBufferDepositoryTest, depository_respects_max_buffer_parameter)
 
312
TEST_F(MirBufferDepositoryTest, depository_frees_buffers_after_reaching_capacity)
305
313
{
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];
310
317
 
311
318
    for (int num_buffers = 2; num_buffers < 10; ++num_buffers)
312
319
    {
313
320
        depository = std::make_shared<mcl::ClientBufferDepository>(mock_factory, num_buffers);
314
 
 
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;
318
323
 
319
324
        int i;
320
325
        for (i = 0; i < num_buffers ; ++i)
321
 
        {
322
 
            MockBuffer *buffer;
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;}));
326
 
        }
327
327
 
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]);
332
 
 
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());
336
333
    }
337
334
}
338
335
 
344
341
 
345
342
    auto package1 = std::make_shared<MirBufferPackage>();
346
343
    auto package2 = std::make_shared<MirBufferPackage>();
347
 
 
348
 
    EXPECT_CALL(*mock_factory, create_buffer(_,_,_))
349
 
        .Times(1);
350
 
 
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;
 
346
    Sequence seq;
 
347
    EXPECT_CALL(*mock_factory, create_buffer(Ref(package1),_,_))
 
348
        .InSequence(seq)
 
349
        .WillOnce(Return(mir::test::fake_shared(mock_buffer)));
 
350
    EXPECT_CALL(mock_buffer, update_from(Ref(*package2)))
 
351
        .InSequence(seq);
 
352
    EXPECT_CALL(mock_buffer, update_from(Ref(*package3)))
 
353
        .InSequence(seq);
 
354
 
 
355
    depository.deposit_package(package1, 8, size, pf);
 
356
    depository.deposit_package(package2, 8, size, pf);
 
357
    depository.deposit_package(package3, 8, size, pf);
354
358
}
355
359
 
356
360
TEST_F(MirBufferDepositoryTest, depository_creates_new_buffer_for_different_id)