Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / operation / test_mock_Request.cc
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/librbd/mock/MockJournal.h"
8 #include "librbd/AsyncRequest.h"
9 #include "librbd/operation/Request.h"
10
11 namespace librbd {
12 namespace {
13
14 struct MockTestImageCtx : public MockImageCtx {
15   MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
16   }
17 };
18
19 } // anonymous namespace
20
21 template <>
22 struct AsyncRequest<librbd::MockTestImageCtx> {
23   librbd::MockTestImageCtx &m_image_ctx;
24   Context *m_on_finish;
25
26   AsyncRequest(librbd::MockTestImageCtx &image_ctx, Context *on_finish)
27     : m_image_ctx(image_ctx), m_on_finish(on_finish) {
28   }
29   virtual ~AsyncRequest() {
30   }
31
32   virtual void finish(int r) {
33     m_on_finish->complete(r);
34   }
35   virtual void finish_and_destroy(int r) {
36     finish(r);
37     delete this;
38   }
39 };
40
41 } // namespace librbd
42
43 #include "librbd/operation/Request.cc"
44
45 namespace librbd {
46 namespace journal {
47
48 std::ostream& operator<<(std::ostream& os, const Event&) {
49   return os;
50 }
51
52 } // namespace journal
53
54 namespace operation {
55
56 using ::testing::InSequence;
57 using ::testing::Invoke;
58 using ::testing::Return;
59
60 struct MockRequest : public Request<librbd::MockTestImageCtx> {
61   MockRequest(librbd::MockTestImageCtx &image_ctx, Context *on_finish,
62               uint64_t journal_op_tid)
63     : Request<librbd::MockTestImageCtx>(image_ctx, on_finish, journal_op_tid) {
64   }
65
66   void complete(int r) {
67     finish_and_destroy(r);
68   }
69
70   void send_op_impl(int r) {
71     bool appending = append_op_event<
72       MockRequest, &MockRequest::handle_send>(this);
73     if (!appending) {
74       complete(r);
75     }
76   }
77   MOCK_METHOD1(should_complete, bool(int));
78   MOCK_METHOD0(send_op, void());
79   MOCK_METHOD1(handle_send, Context*(int*));
80   MOCK_CONST_METHOD0(can_affect_io, bool());
81   MOCK_CONST_METHOD1(create_event, journal::Event(uint64_t));
82 };
83
84 struct TestMockOperationRequest : public TestMockFixture {
85   void expect_can_affect_io(MockRequest &mock_request, bool can_affect) {
86     EXPECT_CALL(mock_request, can_affect_io())
87       .WillOnce(Return(can_affect));
88   }
89
90   void expect_is_journal_replaying(MockJournal &mock_journal, bool replaying) {
91     EXPECT_CALL(mock_journal, is_journal_replaying())
92       .WillOnce(Return(replaying));
93   }
94
95   void expect_is_journal_appending(MockJournal &mock_journal, bool appending) {
96     EXPECT_CALL(mock_journal, is_journal_appending())
97       .WillOnce(Return(appending));
98   }
99
100   void expect_send_op(MockRequest &mock_request, int r) {
101     EXPECT_CALL(mock_request, send_op())
102       .WillOnce(Invoke([&mock_request, r]() {
103                   mock_request.complete(r);
104                 }));
105   }
106
107   void expect_send_op_affects_io(MockImageCtx &mock_image_ctx,
108                                  MockRequest &mock_request, int r) {
109     EXPECT_CALL(mock_request, send_op())
110       .WillOnce(Invoke([&mock_image_ctx, &mock_request, r]() {
111                   mock_image_ctx.image_ctx->op_work_queue->queue(
112                     new FunctionContext([&mock_request, r](int _) {
113                       mock_request.send_op_impl(r);
114                     }), 0);
115                 }));
116   }
117
118 };
119
120 TEST_F(TestMockOperationRequest, SendJournalDisabled) {
121   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
122
123   librbd::ImageCtx *ictx;
124   ASSERT_EQ(0, open_image(m_image_name, &ictx));
125
126   MockTestImageCtx mock_image_ctx(*ictx);
127   MockJournal mock_journal;
128   mock_image_ctx.journal = &mock_journal;
129
130   C_SaferCond ctx;
131   MockRequest *mock_request = new MockRequest(mock_image_ctx, &ctx, 0);
132
133   InSequence seq;
134   expect_can_affect_io(*mock_request, false);
135   expect_is_journal_appending(mock_journal, false);
136   expect_send_op(*mock_request, 0);
137
138   {
139     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
140     mock_request->send();
141   }
142
143   ASSERT_EQ(0, ctx.wait());
144 }
145
146 TEST_F(TestMockOperationRequest, SendAffectsIOJournalDisabled) {
147   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
148
149   librbd::ImageCtx *ictx;
150   ASSERT_EQ(0, open_image(m_image_name, &ictx));
151
152   MockTestImageCtx mock_image_ctx(*ictx);
153   MockJournal mock_journal;
154   mock_image_ctx.journal = &mock_journal;
155
156   C_SaferCond ctx;
157   MockRequest *mock_request = new MockRequest(mock_image_ctx, &ctx, 0);
158
159   InSequence seq;
160   expect_can_affect_io(*mock_request, true);
161   expect_send_op_affects_io(mock_image_ctx, *mock_request, 0);
162   expect_can_affect_io(*mock_request, true);
163   expect_is_journal_replaying(mock_journal, false);
164   expect_is_journal_appending(mock_journal, false);
165
166   {
167     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
168     mock_request->send();
169   }
170
171   ASSERT_EQ(0, ctx.wait());
172 }
173
174 } // namespace operation
175 } // namespace librbd