1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/librbd/test_mock_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
7 #include "librbd/ImageState.h"
8 #include "librbd/internal.h"
9 #include "librbd/ObjectMap.h"
10 #include "librbd/object_map/SnapshotRollbackRequest.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
15 namespace object_map
{
18 using ::testing::DoDefault
;
19 using ::testing::Return
;
20 using ::testing::StrEq
;
22 class TestMockObjectMapSnapshotRollbackRequest
: public TestMockFixture
{
24 void expect_read_map(librbd::ImageCtx
*ictx
, uint64_t snap_id
, int r
) {
26 EXPECT_CALL(get_mock_io_ctx(ictx
->md_ctx
),
27 read(ObjectMap
<>::object_map_name(ictx
->id
, snap_id
),
28 0, 0, _
)).WillOnce(Return(r
));
30 EXPECT_CALL(get_mock_io_ctx(ictx
->md_ctx
),
31 read(ObjectMap
<>::object_map_name(ictx
->id
, snap_id
),
32 0, 0, _
)).WillOnce(DoDefault());
36 void expect_write_map(librbd::ImageCtx
*ictx
, int r
) {
37 EXPECT_CALL(get_mock_io_ctx(ictx
->md_ctx
),
38 exec(ObjectMap
<>::object_map_name(ictx
->id
, CEPH_NOSNAP
), _
,
39 StrEq("lock"), StrEq("assert_locked"), _
, _
, _
))
40 .WillOnce(DoDefault());
42 EXPECT_CALL(get_mock_io_ctx(ictx
->md_ctx
),
44 ObjectMap
<>::object_map_name(ictx
->id
, CEPH_NOSNAP
), _
, _
))
47 EXPECT_CALL(get_mock_io_ctx(ictx
->md_ctx
),
49 ObjectMap
<>::object_map_name(ictx
->id
, CEPH_NOSNAP
), _
, _
))
50 .WillOnce(DoDefault());
54 void expect_invalidate(librbd::ImageCtx
*ictx
, uint32_t times
) {
55 EXPECT_CALL(get_mock_io_ctx(ictx
->md_ctx
),
56 exec(ictx
->header_oid
, _
, StrEq("rbd"), StrEq("set_flags"), _
, _
, _
))
58 .WillRepeatedly(DoDefault());
62 TEST_F(TestMockObjectMapSnapshotRollbackRequest
, Success
) {
63 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
65 librbd::ImageCtx
*ictx
;
66 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
67 ASSERT_EQ(0, snap_create(*ictx
, "snap1"));
68 ASSERT_EQ(0, ictx
->state
->refresh_if_required());
70 uint64_t snap_id
= ictx
->snap_info
.rbegin()->first
;
71 expect_read_map(ictx
, snap_id
, 0);
72 expect_write_map(ictx
, 0);
75 AsyncRequest
<> *request
= new SnapshotRollbackRequest(
76 *ictx
, snap_id
, &cond_ctx
);
78 ASSERT_EQ(0, cond_ctx
.wait());
80 expect_unlock_exclusive_lock(*ictx
);
83 TEST_F(TestMockObjectMapSnapshotRollbackRequest
, ReadMapError
) {
84 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
86 librbd::ImageCtx
*ictx
;
87 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
88 ASSERT_EQ(0, snap_create(*ictx
, "snap1"));
89 ASSERT_EQ(0, ictx
->state
->refresh_if_required());
91 uint64_t snap_id
= ictx
->snap_info
.rbegin()->first
;
92 expect_read_map(ictx
, snap_id
, -ENOENT
);
93 expect_invalidate(ictx
, 2);
96 AsyncRequest
<> *request
= new SnapshotRollbackRequest(
97 *ictx
, snap_id
, &cond_ctx
);
99 ASSERT_EQ(0, cond_ctx
.wait());
102 RWLock::RLocker
snap_locker(ictx
->snap_lock
);
104 ASSERT_EQ(0, ictx
->get_flags(snap_id
, &flags
));
105 ASSERT_NE(0U, flags
& RBD_FLAG_OBJECT_MAP_INVALID
);
108 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
109 ASSERT_TRUE(flags_set
);
110 expect_unlock_exclusive_lock(*ictx
);
113 TEST_F(TestMockObjectMapSnapshotRollbackRequest
, WriteMapError
) {
114 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
116 librbd::ImageCtx
*ictx
;
117 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
118 ASSERT_EQ(0, snap_create(*ictx
, "snap1"));
119 ASSERT_EQ(0, ictx
->state
->refresh_if_required());
121 uint64_t snap_id
= ictx
->snap_info
.rbegin()->first
;
122 expect_read_map(ictx
, snap_id
, 0);
123 expect_write_map(ictx
, -EINVAL
);
124 expect_invalidate(ictx
, 1);
126 C_SaferCond cond_ctx
;
127 AsyncRequest
<> *request
= new SnapshotRollbackRequest(
128 *ictx
, snap_id
, &cond_ctx
);
130 ASSERT_EQ(0, cond_ctx
.wait());
133 RWLock::RLocker
snap_locker(ictx
->snap_lock
);
135 ASSERT_EQ(0, ictx
->get_flags(snap_id
, &flags
));
136 ASSERT_EQ(0U, flags
& RBD_FLAG_OBJECT_MAP_INVALID
);
139 ASSERT_EQ(0, ictx
->test_flags(RBD_FLAG_OBJECT_MAP_INVALID
, &flags_set
));
140 ASSERT_TRUE(flags_set
);
141 expect_unlock_exclusive_lock(*ictx
);
144 } // namespace object_map
145 } // namespace librbd