]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "test/librbd/test_mock_fixture.h" | |
5 | #include "test/librbd/test_support.h" | |
6 | #include "test/librbd/mock/MockImageCtx.h" | |
7 | #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" | |
8 | #include "librbd/ImageState.h" | |
9 | #include "librbd/mirror/snapshot/ImageMeta.h" | |
10 | #include "librbd/mirror/snapshot/Utils.h" | |
11 | ||
12 | namespace librbd { | |
13 | namespace { | |
14 | ||
15 | struct MockTestImageCtx : public MockImageCtx { | |
16 | MockTestImageCtx(librbd::ImageCtx& image_ctx) : MockImageCtx(image_ctx) { | |
17 | } | |
18 | }; | |
19 | ||
20 | } // anonymous namespace | |
21 | } // namespace librbd | |
22 | ||
23 | #include "librbd/mirror/snapshot/ImageMeta.cc" | |
24 | ||
25 | namespace librbd { | |
26 | namespace mirror { | |
27 | namespace snapshot { | |
28 | ||
29 | using ::testing::_; | |
30 | using ::testing::DoAll; | |
31 | using ::testing::InSequence; | |
32 | using ::testing::Invoke; | |
33 | using ::testing::Return; | |
34 | using ::testing::StrEq; | |
35 | using ::testing::WithArg; | |
36 | ||
37 | class TestMockMirrorSnapshotImageMeta : public TestMockFixture { | |
38 | public: | |
39 | typedef ImageMeta<MockTestImageCtx> MockImageMeta; | |
40 | ||
41 | void expect_metadata_get(MockTestImageCtx& mock_image_ctx, | |
42 | const std::string& mirror_uuid, | |
43 | const std::string& value, int r) { | |
44 | bufferlist in_bl; | |
45 | ceph::encode(util::get_image_meta_key(mirror_uuid), in_bl); | |
46 | ||
47 | bufferlist out_bl; | |
48 | ceph::encode(value, out_bl); | |
49 | ||
50 | EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), | |
51 | exec(mock_image_ctx.header_oid, _, StrEq("rbd"), | |
f67539c2 | 52 | StrEq("metadata_get"), ContentsEqual(in_bl), _, _, _)) |
9f95a23c TL |
53 | .WillOnce(DoAll(WithArg<5>(CopyInBufferlist(out_bl)), |
54 | Return(r))); | |
55 | } | |
56 | ||
57 | void expect_metadata_set(MockTestImageCtx& mock_image_ctx, | |
58 | const std::string& mirror_uuid, | |
59 | const std::string& value, int r) { | |
60 | bufferlist value_bl; | |
61 | value_bl.append(value); | |
62 | ||
63 | bufferlist in_bl; | |
64 | ceph::encode( | |
65 | std::map<std::string, bufferlist>{ | |
66 | {util::get_image_meta_key(mirror_uuid), value_bl}}, | |
67 | in_bl); | |
68 | ||
69 | EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), | |
70 | exec(mock_image_ctx.header_oid, _, StrEq("rbd"), | |
f67539c2 | 71 | StrEq("metadata_set"), ContentsEqual(in_bl), _, _, _)) |
9f95a23c TL |
72 | .WillOnce(Return(r)); |
73 | } | |
74 | }; | |
75 | ||
76 | TEST_F(TestMockMirrorSnapshotImageMeta, Load) { | |
77 | librbd::ImageCtx* image_ctx; | |
78 | ASSERT_EQ(0, open_image(m_image_name, &image_ctx)); | |
79 | MockTestImageCtx mock_image_ctx(*image_ctx); | |
80 | ||
81 | InSequence seq; | |
82 | expect_metadata_get(mock_image_ctx, "mirror uuid", | |
83 | "{\"resync_requested\": true}", 0); | |
84 | ||
85 | MockImageMeta mock_image_meta(&mock_image_ctx, "mirror uuid"); | |
86 | C_SaferCond ctx; | |
87 | mock_image_meta.load(&ctx); | |
88 | ASSERT_EQ(0, ctx.wait()); | |
89 | } | |
90 | ||
91 | TEST_F(TestMockMirrorSnapshotImageMeta, LoadError) { | |
92 | librbd::ImageCtx* image_ctx; | |
93 | ASSERT_EQ(0, open_image(m_image_name, &image_ctx)); | |
94 | MockTestImageCtx mock_image_ctx(*image_ctx); | |
95 | ||
96 | InSequence seq; | |
97 | expect_metadata_get(mock_image_ctx, "mirror uuid", | |
98 | "{\"resync_requested\": true}", -EINVAL); | |
99 | ||
100 | MockImageMeta mock_image_meta(&mock_image_ctx, "mirror uuid"); | |
101 | C_SaferCond ctx; | |
102 | mock_image_meta.load(&ctx); | |
103 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
104 | } | |
105 | ||
106 | TEST_F(TestMockMirrorSnapshotImageMeta, LoadCorrupt) { | |
107 | librbd::ImageCtx* image_ctx; | |
108 | ASSERT_EQ(0, open_image(m_image_name, &image_ctx)); | |
109 | MockTestImageCtx mock_image_ctx(*image_ctx); | |
110 | ||
111 | InSequence seq; | |
112 | expect_metadata_get(mock_image_ctx, "mirror uuid", | |
113 | "\"resync_requested\": true}", 0); | |
114 | ||
115 | MockImageMeta mock_image_meta(&mock_image_ctx, "mirror uuid"); | |
116 | C_SaferCond ctx; | |
117 | mock_image_meta.load(&ctx); | |
118 | ASSERT_EQ(-EBADMSG, ctx.wait()); | |
119 | } | |
120 | ||
121 | TEST_F(TestMockMirrorSnapshotImageMeta, Save) { | |
122 | librbd::ImageCtx* image_ctx; | |
123 | ASSERT_EQ(0, open_image(m_image_name, &image_ctx)); | |
124 | MockTestImageCtx mock_image_ctx(*image_ctx); | |
125 | ||
126 | InSequence seq; | |
127 | expect_metadata_set(mock_image_ctx, "mirror uuid", | |
128 | "{\"resync_requested\": true}", 0); | |
129 | ||
130 | MockImageMeta mock_image_meta(&mock_image_ctx, "mirror uuid"); | |
131 | mock_image_meta.resync_requested = true; | |
132 | ||
133 | C_SaferCond ctx; | |
134 | mock_image_meta.save(&ctx); | |
135 | ASSERT_EQ(0, ctx.wait()); | |
136 | ||
137 | // should have sent image-update notification | |
138 | ASSERT_TRUE(image_ctx->state->is_refresh_required()); | |
139 | } | |
140 | ||
141 | TEST_F(TestMockMirrorSnapshotImageMeta, SaveError) { | |
142 | librbd::ImageCtx* image_ctx; | |
143 | ASSERT_EQ(0, open_image(m_image_name, &image_ctx)); | |
144 | MockTestImageCtx mock_image_ctx(*image_ctx); | |
145 | ||
146 | InSequence seq; | |
147 | expect_metadata_set(mock_image_ctx, "mirror uuid", | |
148 | "{\"resync_requested\": false}", -EINVAL); | |
149 | ||
150 | MockImageMeta mock_image_meta(&mock_image_ctx, "mirror uuid"); | |
151 | ||
152 | C_SaferCond ctx; | |
153 | mock_image_meta.save(&ctx); | |
154 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
155 | } | |
156 | ||
157 | } // namespace snapshot | |
158 | } // namespace mirror | |
159 | } // namespace librbd |