1 #include "mctest.h" 2 #include "mc/mcreq-flush-inl.h" 3 #include "mc/forward.h" 4 #include "pktmaker.h" 5 6 using namespace PacketMaker; 7 using std::vector; 8 using std::string; 9 10 struct Vars { 11 mc_PACKET *pkt; 12 mc_PIPELINE *pl; 13 nb_IOV iovs[10]; 14 mc_IOVINFO ioi; 15 vector<char> reqbuf; 16 17 Vars() { 18 pkt = NULL; 19 pl = NULL; 20 memset(&ioi, 0, sizeof(ioi)); 21 memset(&iovs, 0, sizeof(iovs)); 22 } 23 24 lcb_error_t requestPacket(mc_CMDQUEUE *cq) { 25 return mc_forward_packet(cq, &ioi, &pkt, &pl, 0); 26 } 27 28 void initInfo() { 29 mc_iovinfo_init(&ioi, iovs, 10); 30 } 31 }; 32 33 class McFwd : public ::testing::Test {}; 34 35 static void 36 setupRequestBuf(vector<char>& out, size_t nkey, size_t nval) 37 { 38 string k(nkey, 'K'); 39 string v(nval, 'V'); 40 StorageRequest sr(k, v); 41 out.clear(); 42 sr.serialize(out); 43 EXPECT_EQ(nkey + nval + 24, out.size()); 44 } 45 46 TEST_F(McFwd, testForwardSingle) 47 { 48 CQWrap cq; 49 StorageRequest sr(string("fookey"), string("foovalue")); 50 51 mc_IOVINFO iovinfo; 52 53 nb_IOV iovs[10]; 54 // Enqueue first packet inside entire body. 55 vector<char> reqbody; 56 sr.serialize(reqbody); 57 58 memset(iovs, 0, sizeof(iovs)); 59 memset(&iovinfo, 0, sizeof(iovinfo)); 60 mc_iovinfo_init(&iovinfo, iovs, 10); 61 ASSERT_EQ(10, iovinfo.c.niov); 62 ASSERT_EQ(&iovs[0], iovinfo.c.iov); 63 ASSERT_NE(0, reqbody.size()); 64 65 iovs->iov_base = &reqbody[0]; 66 iovs->iov_len = reqbody.size(); 67 iovinfo.total = reqbody.size(); 68 69 mc_PACKET *pkt = NULL; 70 mc_PIPELINE *pl = NULL; 71 lcb_error_t rc = mc_forward_packet(&cq, &iovinfo, &pkt, &pl, 0); 72 ASSERT_EQ(LCB_SUCCESS, rc); 73 ASSERT_EQ(0, iovinfo.wanted); 74 ASSERT_EQ(reqbody.size(), iovinfo.consumed); 75 ASSERT_EQ(9, iovinfo.c.niov); 76 ASSERT_EQ(0, iovinfo.c.offset); 77 mcreq_sched_fail(&cq); 78 } 79 80 TEST_F(McFwd, testFragmentedBasic) 81 { 82 CQWrap cq; 83 nb_IOV iovs[10]; 84 vector<char> reqbuf; 85 86 memset(iovs, 0, sizeof(iovs)); 87 setupRequestBuf(reqbuf, 10, 10); 88 89 iovs[0].iov_base = &reqbuf[0]; 90 iovs[0].iov_len = 34; 91 92 iovs[1].iov_base = &reqbuf[34]; 93 iovs[1].iov_len = 10; 94 95 mc_IOVINFO ioi; 96 memset(&ioi, 0, sizeof(ioi)); 97 mc_iovinfo_init(&ioi, iovs, 10); 98 lcb_error_t rc; 99 mc_PACKET *pkt; 100 mc_PIPELINE *pl; 101 102 rc = mc_forward_packet(&cq, &ioi, &pkt, &pl, 0); 103 ASSERT_EQ(LCB_SUCCESS, rc); 104 ASSERT_EQ(0, ioi.wanted); 105 ASSERT_EQ(44, ioi.consumed); 106 ASSERT_EQ(0, ioi.c.offset); 107 ASSERT_EQ(8, ioi.c.niov); 108 ASSERT_EQ(0, ioi.c.iov[0].iov_len); 109 mcreq_sched_fail(&cq); 110 } 111 112 TEST_F(McFwd, testFragmentedHeader) { 113 CQWrap cq; 114 Vars vars; 115 116 setupRequestBuf(vars.reqbuf, 100, 100); 117 vars.iovs[0].iov_base = &vars.reqbuf[0]; 118 vars.iovs[0].iov_len = 10; 119 120 vars.iovs[1].iov_base = &vars.reqbuf[10]; 121 vars.iovs[1].iov_len = 10; 122 123 vars.iovs[2].iov_base = &vars.reqbuf[20]; 124 vars.iovs[2].iov_len = vars.reqbuf.size() - 20; 125 vars.initInfo(); 126 ASSERT_EQ(vars.reqbuf.size(), vars.ioi.total); 127 128 lcb_error_t rc = vars.requestPacket(&cq); 129 ASSERT_EQ(LCB_SUCCESS, rc); 130 ASSERT_EQ(0, vars.pkt->flags & MCREQ_F_KEY_NOCOPY); 131 ASSERT_EQ(0, vars.ioi.total); 132 ASSERT_EQ(0, vars.ioi.c.offset); 133 ASSERT_EQ(vars.reqbuf.size(), vars.ioi.consumed); 134 ASSERT_EQ(0, vars.ioi.c.iov[0].iov_len); 135 ASSERT_EQ(7, vars.ioi.c.niov); 136 137 mcreq_sched_fail(&cq); 138 } 139 140 TEST_F(McFwd, testInsufficientHeader) 141 { 142 CQWrap cq; 143 Vars vars; 144 lcb_error_t rc; 145 146 setupRequestBuf(vars.reqbuf, 100, 100); 147 148 // Test with no data 149 vars.iovs[0].iov_base = NULL; 150 vars.iovs[0].iov_len = 0; 151 vars.initInfo(); 152 rc = vars.requestPacket(&cq); 153 ASSERT_EQ(LCB_INCOMPLETE_PACKET, rc); 154 ASSERT_EQ(24, vars.ioi.wanted); 155 156 // Test with partial (but incomplete header) 157 vars.iovs[0].iov_base = &vars.reqbuf[0]; 158 vars.iovs[0].iov_len = 20; 159 vars.initInfo(); 160 rc = vars.requestPacket(&cq); 161 ASSERT_EQ(LCB_INCOMPLETE_PACKET, rc); 162 ASSERT_EQ(24, vars.ioi.wanted); 163 164 // Test with full header but partial key 165 vars.iovs[0].iov_base = &vars.reqbuf[0]; 166 vars.iovs[0].iov_len = 30; 167 vars.initInfo(); 168 rc = vars.requestPacket(&cq); 169 ASSERT_EQ(rc, LCB_INCOMPLETE_PACKET); 170 ASSERT_EQ(vars.reqbuf.size(), vars.ioi.wanted); 171 } 172 173 TEST_F(McFwd, testMultiValue) 174 { 175 CQWrap cq; 176 Vars vars; 177 lcb_error_t rc; 178 setupRequestBuf(vars.reqbuf, 1, 810); 179 180 vars.iovs[0].iov_base = &vars.reqbuf[0]; 181 vars.iovs[0].iov_len = 25; 182 183 for (int ii = 1; ii < 10; ii++) { 184 vars.iovs[ii].iov_base = &vars.reqbuf[25 + (ii-1) * 90]; 185 vars.iovs[ii].iov_len = 90; 186 } 187 188 vars.initInfo(); 189 ASSERT_EQ(835, vars.reqbuf.size()); 190 ASSERT_EQ(835, vars.ioi.total); 191 192 rc = vars.requestPacket(&cq); 193 ASSERT_EQ(LCB_SUCCESS, rc); 194 ASSERT_NE(0, vars.pkt->flags & MCREQ_F_VALUE_IOV); 195 mcreq_sched_fail(&cq); 196 197 // Eh, let's check these other nifty things. Why not? 198 ASSERT_EQ(0, vars.ioi.wanted); 199 ASSERT_EQ(0, vars.ioi.c.niov); 200 } 201 202 TEST_F(McFwd, testNoMap) 203 { 204 CQWrap cq; 205 lcb_error_t err; 206 protocol_binary_request_header hdr; 207 memset(&hdr, 0, sizeof hdr); 208 hdr.request.magic = PROTOCOL_BINARY_REQ; 209 hdr.request.opcode = 0x50; 210 hdr.request.extlen = 8; 211 hdr.request.bodylen = htonl(8); 212 hdr.request.vbucket = 0; 213 char reqbuf[32] = { 0 }; 214 memcpy(reqbuf, hdr.bytes, sizeof hdr.bytes); 215 mc_IOVINFO ioi; 216 nb_IOV iov; 217 iov.iov_base = reqbuf; 218 iov.iov_len = sizeof reqbuf; 219 mc_iovinfo_init(&ioi, &iov, 1); 220 221 mc_PACKET *pkt_tmp; 222 mc_PIPELINE *pl_tmp = cq.pipelines[0]; 223 err = mc_forward_packet(&cq, &ioi, &pkt_tmp, &pl_tmp, MC_FWD_OPT_NOMAP); 224 225 ASSERT_EQ(LCB_SUCCESS, err); 226 ASSERT_NE(0, pkt_tmp->flags & MCREQ_F_UFWD); 227 228 // Get the key 229 const void *key; 230 lcb_SIZE nkey; 231 mcreq_get_key(pkt_tmp, &key, &nkey); 232 ASSERT_EQ(0, nkey); 233 234 // Ensure we have no vBucket stamping 235 protocol_binary_request_header hdr2; 236 mcreq_read_hdr(pkt_tmp, &hdr2); 237 ASSERT_EQ(0, hdr2.request.vbucket); 238 mcreq_sched_fail(&cq); 239 } 240