Motr  M0
service_ut.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Seagate Technology LLC and/or its Affiliates
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * For any questions about this software or licensing,
17  * please email opensource@seagate.com or cortx-questions@seagate.com.
18  *
19  */
20 
21 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_UT
22 #include "lib/trace.h"
23 #include "lib/misc.h"
24 #include "ut/misc.h"
25 #include "ut/ut.h"
26 #include "iscservice/isc.h"
27 #include "iscservice/isc_service.h"
28 #include "iscservice/ut/common.h" /* cc_block_init */
29 #include "lib/finject.h"
30 #include "rpc/rpclib.h" /* m0_rpc_server_start */
31 #include "rpc/ut/at/at_ut.h" /* atut__bufdata_alloc */
32 
33 #include <stdio.h>
34 
35 #define SERVER_ENDPOINT_ADDR "0@lo:12345:34:1"
36 #define SERVER_ENDPOINT M0_NET_XPRT_PREFIX_DEFAULT":"SERVER_ENDPOINT_ADDR
37 #define CLIENT_ENDPOINT_ADDR "0@lo:12345:34:2"
38 #define F_CONT 0x12345
39 #define BARRIER_CNT 2
40 
41 static struct m0_reqh_service *iscs;
45 static uint32_t cc_type;
46 static const char *SERVER_LOGFILE = "isc_ut.log";
47 char *isc_ut_server_args[] = { "m0d", "-T", "LINUX",
48  "-D", "sr_db", "-S", "sr_stob",
49  "-A", "linuxstob:sr_addb_stob",
50  "-f", M0_UT_CONF_PROCESS,
51  "-w", "10",
52  "-F",
53  "-G", SERVER_ENDPOINT,
54  "-e", SERVER_ENDPOINT,
55 // "-P", M0_UT_CONF_PROFILE,
56  "-c", M0_UT_PATH("conf.xc")};
59  struct m0_chan riv_chan;
61 
62 static void req_fop_prepare(struct m0_fop *req_fop,
63  uint32_t buf_type,
64  struct m0_fid *fid,
65  uint32_t f_type);
66 
67 static void isc_item_cb(struct m0_rpc_item *item)
68 {
69  struct m0_fop *req_fop;
70  struct m0_fop *repl_fop;
71 
72  req_fop = m0_rpc_item_to_fop(item);
73  repl_fop = m0_rpc_item_to_fop(item->ri_reply);
74  /*
75  * References guarantee that fops are not released
76  * before the reply is processed.
77  */
78  m0_fop_get(req_fop);
79  m0_fop_get(repl_fop);
81 }
82 
83 static const struct m0_rpc_item_ops isc_item_ops = {
85 };
86 
87 /*
88  * Classification of function types based on signature.
89  */
90 enum funct_type {
91  /* Neither receives i/p buffer nor returns anything. */
93  /* Receives no i/p buffer, returns error. */
95  /* Receives i/p buffer, returns nothing. */
97  /* Receives i/p buffer and returns o/p buffer. */
99 };
100 
101 /*
102  * A parameter that decides whether all threads use the same fid for
103  * registering a computation or a different fid.
104  */
108 };
109 
110 /* A parameter for the choice of m0_rpc_at buffer. */
111 enum buf_type {
114 };
115 
118  struct m0_chan ve_chan;
119  volatile uint32_t ve_count;
120  uint32_t ve_wait_count;
121 } vis_ent;
122 
123 static int ret_codes[] =
124  {-ENOENT, -EINVAL, -ENOMEM, -EPROTO, -EPERM, -ENOMSG, 0};
125 
126 struct comp_req_aux {
127  int (*cra_comp)(struct m0_buf *arg_in,
128  struct m0_buf *args_out,
129  struct m0_isc_comp_private *comp_data, int *rc);
130  char *cra_name;
131 } cra;
132 
133 char *fixed_str = "abcdefgh";
134 
135 static void fid_get(const char *f_name, struct m0_fid *fid)
136 {
137  uint32_t f_key = m0_full_name_hash((const unsigned char*)f_name,
138  strlen(f_name));
140 }
141 
143 {
144  int rc = 0;
145 
152 
154  M0_UT_ASSERT(rc == 0);
156  M0_UT_ASSERT(rc == 0);
158  NULL);
160  M0_UT_ASSERT(rc == 0);
161  return rc;
162 }
163 
164 static void isc_ut_server_stop(void)
165 {
170 }
171 
172 static void isc_ut_client_start(void)
173 {
174  int rc;
175 
178  M0_UT_ASSERT(rc == 0);
186 
188  M0_UT_ASSERT(rc == 0);
191 }
192 
193 static void isc_ut_client_stop()
194 {
195  int rc;
196 
198  M0_UT_ASSERT(rc == 0);
200 }
201 
202 static int null_computation(struct m0_buf *in, struct m0_buf *out,
203  struct m0_isc_comp_private *comp_data, int *rc)
204 {
205  *rc = 0;
206  return M0_FSO_AGAIN;
207 }
208 
209 static struct m0_rpc_machine *fom_rmach(const struct m0_fom *fom)
210 {
211  return fom->fo_fop->f_item.ri_session->s_conn->c_rpc_machine;
212 }
213 
214 /* Increments ASCII value of each character by one. */
215 static int string_update(struct m0_buf *in, struct m0_buf *out,
216  struct m0_isc_comp_private *comp_data, int *rc)
217 {
218  struct m0_rpc_machine *rmach;
219  uint32_t i;
220  uint64_t size;
221  char *instr;
222  char *outstr;
223 
224  if (M0_FI_ENABLED("comp_error")) {
225  *rc = -EPERM;
226  return M0_FSO_AGAIN;
227  }
228  if (M0_FI_ENABLED("at_mismatch")) {
229  rmach = fom_rmach(comp_data->icp_fom);
230  size = rmach->rm_bulk_cutoff * 2;
231  } else
232  size = in->b_nob;
233  *rc = m0_buf_alloc(out, size);
234  if (*rc != 0)
235  return M0_FSO_AGAIN;
236  instr = (char *)in->b_addr;
237  outstr = (char *)out->b_addr;
238  for (i = 0; i < in->b_nob; ++i) {
239  outstr[i] = (instr[i] + 1) % CHAR_MAX;
240  }
241  return M0_FSO_AGAIN;
242 }
243 
244 /* Compares input string with predefined string. */
245 static int strguess(struct m0_buf *in, struct m0_buf *out,
246  struct m0_isc_comp_private *comp_data, int *rc)
247 {
248  if (!m0_buf_streq(in, fixed_str))
249  *rc = M0_ERR(-EINVAL);
250  else
251  *rc = 0;
252 
253  return M0_FSO_AGAIN;
254 }
255 
256 static void comp_launch(void *args)
257 {
258  struct thr_args *thr_args = args;
259  struct m0_isc_comp_req *comp_req = thr_args->ta_data;
260  int rc;
261 
262  /* Wait till the last thread reaches here. */
264  rc = m0_isc_comp_req_exec_sync(comp_req);
265  M0_UT_ASSERT(rc == 0);
266  m0_isc_comp_req_fini(comp_req);
267 }
268 
269 static void vis_entry_init(uint32_t barrier_cnt)
270 {
273  vis_ent.ve_count = 0;
274  vis_ent.ve_wait_count = barrier_cnt;
275 }
276 
277 static void vis_entry_fini(void)
278 {
281  M0_SET0(&vis_ent);
282 }
283 
284 /*
285  * Puts calling fom on wait till predefined number of threads visit the
286  * function.
287  */
288 static int barrier(struct m0_buf *in, struct m0_buf *out,
289  struct m0_isc_comp_private *comp_data, int *rc)
290 {
291  int result;
292 
295  m0_fom_wait_on(comp_data->icp_fom, &vis_ent.ve_chan,
296  &comp_data->icp_fom->fo_cb);
297  result = M0_FSO_WAIT;
298  *rc = -EAGAIN;
299  ++vis_ent.ve_count;
300  } else {
302  result = M0_FSO_AGAIN;
303  *rc = 0;
305  ++vis_ent.ve_count;
306  }
308  return result;
309 }
310 
311 static void local_invocation(struct m0_isc_comp_req *comp_req,
312  struct m0_fid *fid, int exp_rc)
313 {
314  struct m0_buf comp_arg = M0_BUF_INIT0;
315  struct m0_reqh *reqh;
316  struct m0_cookie comp_cookie;
317  int rc;
318 
319  M0_SET0(&comp_cookie);
321  m0_isc_comp_req_init(comp_req, &comp_arg, fid, &comp_cookie,
323  rc = m0_isc_comp_req_exec_sync(comp_req);
324  M0_UT_ASSERT(rc == 0);
325  M0_UT_ASSERT(comp_req->icr_rc == exp_rc);
326  m0_isc_comp_req_fini(comp_req);
327 }
328 
329 static void comp_req_init(void *arg, int tid)
330 {
331  struct m0_isc_comp_req *comp_req = arg;
332  struct m0_fid fid;
333  struct m0_reqh *reqh;
334  struct m0_reqh_service *svc_isc;
335  struct m0_buf comp_arg = M0_BUF_INIT0;
336  int rc;
337  int exp_rc;
338 
341  M0_UT_ASSERT(svc_isc != NULL);
342  if (cc_type == CT_DIFF_FID) {
343  m0_fid_set(&fid, 0x1234, tid);
344  exp_rc = 0;
345  } else {
346  fid_get(cra.cra_name, &fid);
347  exp_rc = -EEXIST;
348  }
350  M0_UT_ASSERT(rc == exp_rc);
351  m0_isc_comp_req_init(comp_req, &comp_arg, &fid, &comp_req->icr_cookie,
353 }
354 
355 /*
356  * Tests the local invocation of a computation. Also tests the concurrent
357  * invocation.
358  */
359 static void test_comp_launch(void)
360 {
361  struct m0_reqh_service *svc_isc;
362  struct m0_reqh *reqh;
363  struct m0_fid fid;
364  struct m0_isc_comp_req comp_req;
365  struct cnc_cntrl_block cc_block;
366  int rc;
367 
368  M0_SET0(&comp_req);
369  M0_SET0(&fid);
370 
372  M0_UT_ASSERT(rc == 0);
375  M0_UT_ASSERT(svc_isc != NULL);
376  fid_get("null_computation", &fid);
377  /* Test a local invocation of computation. */
378  rc = m0_isc_comp_register(null_computation, "null_computation", &fid);
379  M0_UT_ASSERT(rc == 0);
380  local_invocation(&comp_req, &fid, 0);
382 
385 
386  /* Set the global parameters for comp_req_init(). */
387  cra.cra_name = m0_strdup("barrier");
388  cra.cra_comp = barrier;
389  /* Test concurrent invocation of different fids */
392  cc_block_init(&cc_block, sizeof comp_req, comp_req_init);
393  cc_block_launch(&cc_block, comp_launch);
395  vis_entry_fini();
396 
397  /* Test concurrent invocation of a same fid. */
399  fid_get("barrier", &fid);
400  rc = m0_isc_comp_register(barrier, "barrier", &fid);
401  M0_UT_ASSERT(rc == 0);
403  cc_block_init(&cc_block, sizeof comp_req, comp_req_init);
404  cc_block_launch(&cc_block, comp_launch);
406  vis_entry_fini();
407 
408  /* Test error in computation. */
409  fid_get("string_update", &fid);
410  rc = m0_isc_comp_register(string_update, "string_update", &fid);
411  M0_UT_ASSERT(rc == 0);
412  m0_fi_enable("string_update", "comp_error");
413  local_invocation(&comp_req, &fid, -EPERM);
414  m0_fi_disable("string_update", "comp_error");
415 
417 }
418 
419 static void test_local_err_path(void)
420 {
421  struct m0_reqh_service *svc_isc;
422  struct m0_reqh *reqh;
423  struct m0_fid fid;
424  struct m0_isc_comp_req comp_req;
425  int rc;
426 
427  M0_SET0(&comp_req);
428  M0_SET0(&fid);
429 
431  M0_UT_ASSERT(rc == 0);
433  svc_isc =
435  M0_UT_ASSERT(svc_isc != NULL);
436  fid_get("null_computation", &fid);
437 
438  /* Test a local invocation of computation. */
439  rc = m0_isc_comp_register(null_computation, "null_computation", &fid);
440  M0_UT_ASSERT(rc == 0);
441  local_invocation(&comp_req, &fid, 0);
443 
444  /* Test a computation that's absent. */
445  local_invocation(&comp_req, &fid, -ENOENT);
446 
447  /* Test error in computation. */
448  fid_get("string_update", &fid);
449  rc = m0_isc_comp_register(string_update, "string_update", &fid);
450  M0_UT_ASSERT(rc == 0);
451  m0_fi_enable("string_update", "comp_error");
452  local_invocation(&comp_req, &fid, -EPERM);
453  m0_fi_disable("string_update", "comp_error");
454 
455  /* Test error in buffer allocation. */
456  m0_fi_enable("isc_comp_launch", "oom");
457  local_invocation(&comp_req, &fid, -ENOMEM);
458  m0_fi_disable("isc_comp_launch", "oom");
459 
460 
462 }
463 
464 /*
465  * Tests probing of registration state of a computation when:
466  * -computation is registered.
467  * -computation is unregistered while its instance is running.
468  * -computation is not present with the isc service.
469  */
470 static void test_comp_state(void)
471 {
472  struct m0_reqh_service *svc_isc;
473  struct m0_reqh *reqh;
474  struct m0_fid fid;
475  struct m0_clink waiter;
476  struct m0_isc_comp_req comp_req;
477  int state;
478  int rc;
479 
480  M0_SET0(&comp_req);
482  M0_UT_ASSERT(rc == 0);
484  svc_isc =
486  M0_UT_ASSERT(svc_isc != NULL);
487 
489  fid_get("barrier", &fid);
490  /* Check state of a computation that's absent. */
491  state = m0_isc_comp_state_probe(&fid);
492  M0_UT_ASSERT(state == -ENOENT);
493  rc = m0_isc_comp_register(barrier, "barrier", &fid);
494  M0_UT_ASSERT(rc == 0);
496  /* Set the global parameters for comp_req_init(). */
497  cra.cra_name = m0_strdup("barrier");
498  cra.cra_comp = barrier;
499  comp_req_init(&comp_req, 0);
500  m0_clink_init(&waiter, NULL);
501  m0_clink_add_lock(&comp_req.icr_chan, &waiter);
502  waiter.cl_is_oneshot = true;
503 
504  rc = m0_isc_comp_req_exec(&comp_req);
505  M0_UT_ASSERT(rc == 0);
506  /* Spin till the computation is launched. */
507  while (vis_ent.ve_count == 0);
508  /* Check the state of a registered computation. */
509  state = m0_isc_comp_state_probe(&fid);
511 
512  /* Unregister while a computation is running. */
514  state = m0_isc_comp_state_probe(&fid);
516  /*
517  * Try registering a computation that's scheduled for
518  * unregister.
519  */
520  rc = m0_isc_comp_register(barrier, "barrier", &fid);
521  M0_UT_ASSERT(rc == -EEXIST);
522  /* Invoke the fom pending on channel. */
524  vis_ent.ve_count++;
527 
528  /* Wait for the computation to finish. */
529  m0_chan_wait(&waiter);
530  /* Computation shall now be unavailable. */
531  state = m0_isc_comp_state_probe(&fid);
532  M0_UT_ASSERT(state == -ENOENT);
533 
535  vis_entry_fini();
537 }
538 
544 };
545 
546 static uint32_t remote_invocation_async(struct m0_fid *fid,
547  int exp_rc, uint32_t buf_type,
548  uint32_t phase, struct m0_fop **arg_fop)
549 {
550  struct m0_fop *req_fop;
551  struct m0_fop *reply_fop;
552  struct m0_fop_isc_rep repl;
553  struct m0_fop_isc *req;
554  struct m0_buf recv_buf = M0_BUF_INIT0;
555  struct m0_isc_comp *comp;
556  int rc;
557 
558  switch (phase) {
559  case FPP_SEND:
560  req_fop = m0_alloc(sizeof *req_fop);
561  M0_UT_ASSERT(req_fop != NULL);
562  m0_fop_init(req_fop, &m0_fop_isc_fopt,
564  rc = m0_fop_data_alloc(req_fop);
565  M0_ASSERT(rc == 0);
567 
568  req_fop->f_item.ri_ops = &isc_item_ops;
570  rc = m0_rpc_post(&req_fop->f_item);
571  M0_UT_ASSERT(rc == 0);
572  *arg_fop = req_fop;
573  return FPP_REPLY_PROCESS;
574  case FPP_REPLY_PROCESS:
575  req_fop = *arg_fop;
577  repl = *(struct m0_fop_isc_rep *)m0_fop_data(reply_fop);
578  M0_UT_ASSERT(repl.fir_rc == exp_rc);
579  req = m0_fop_data(req_fop);
580  if (repl.fir_rc == 0) {
581  rc = m0_rpc_at_rep_get(&req->fi_ret,
582  &repl.fir_ret, &recv_buf);
583  M0_UT_ASSERT(rc == 0);
584  /* Ensure that a valid cookie is returned. */
585  comp = m0_cookie_of(&repl.fir_comp_cookie,
586  struct m0_isc_comp, ic_gen);
587  M0_UT_ASSERT(comp != NULL);
589  &req->fi_comp_id));
590  }
591  m0_fop_put0_lock(req_fop);
593  return FPP_COMPLETE;
594  }
595  return FPP_INVALID;
596 }
597 
598 static void req_fop_prepare(struct m0_fop *req_fop,
599  uint32_t buf_type,
600  struct m0_fid *fid,
601  uint32_t f_type)
602 {
603  struct m0_fop_isc *fop_isc;
604  struct m0_buf data = M0_BUF_INIT0;
605  struct m0_rpc_machine *rmach;
606  char *in_buf;
607  uint32_t size;
608  m0_bcount_t buflen;
609  int rc;
610 
611  fop_isc = m0_fop_data(req_fop);
612  size = 0;
613  rmach = &isc_ut_cctx.rcx_rpc_machine;
614  fop_isc->fi_comp_id = *fid;
615  m0_rpc_at_init(&fop_isc->fi_args);
617  m0_rpc_max_msg_size(rmach->rm_tm.ntm_dom, 0));
618  switch (f_type) {
619  case FT_NEITHER_IO:
620  case FT_NO_INPUT:
621  break;
622  case FT_NO_OUTPUT:
623  in_buf = m0_strdup(fixed_str);
624  M0_UT_ASSERT(in_buf != NULL);
625  m0_buf_init(&data, (void *)in_buf, strlen(fixed_str));
626  break;
627  case FT_BOTH_IO:
628  size = buf_type == BT_INLINE ? INLINE_LEN : buflen;
629  atut__bufdata_alloc(&data, size, rmach);
630  memset(data.b_addr, 'a', data.b_nob);
631  break;
632  default:
633  M0_UT_ASSERT(false);
634  }
635  rc = m0_rpc_at_add(&fop_isc->fi_args, &data,
637  M0_UT_ASSERT(rc == 0);
638  m0_rpc_at_init(&fop_isc->fi_ret);
639  if (M0_FI_ENABLED("at_mismatch")) {
640  rc = m0_rpc_at_recv(&fop_isc->fi_ret,
642  M0_RPC_AT_UNKNOWN_LEN, false);
643  } else {
644  rc = m0_rpc_at_recv(&fop_isc->fi_ret,
646  size, false);
647  M0_UT_ASSERT(ergo(size == buflen,
648  (fop_isc->fi_ret.ab_type == M0_RPC_AT_BULK_RECV)));
649  }
650  M0_UT_ASSERT(rc == 0);
651 }
652 
653 /* Sets the conditions required to invoke the particular error path. */
654 static void ret_codes_precond(int exp_rc, uint32_t buf_type, struct m0_fid *fid)
655 {
656  int rc;
657 
658  switch (exp_rc) {
659  case -EINVAL:
660  m0_fi_enable("comp_ref_get", "unregister");
661  break;
662  case -ENOENT:
664  break;
665  case -ENOMEM:
666  m0_fi_enable("isc_comp_launch", "oom");
667  break;
668  case -EPROTO:
670  break;
671  case -EPERM:
672  m0_fi_enable("string_update", "comp_error");
673  break;
674  case -ENOMSG:
675  m0_fi_enable("req_fop_prepare", "at_mismatch");
676  m0_fi_enable("string_update", "at_mismatch");
677  break;
678  case 0:
679  rc = m0_isc_comp_register(string_update, "string_update", fid);
680  M0_UT_ASSERT(M0_IN(rc, (0, -EEXIST)));
681  break;
682  default:
683  break;
684  }
685 }
686 
687 /* Undoes the conditions set during ret_codes_precond(). */
688 static void ret_codes_postcond(int exp_rc, void *arg)
689 {
690  struct m0_fid *fid;
691  int rc;
692 
693  switch (exp_rc) {
694  case -EINVAL:
695  m0_fi_disable("comp_ref_get", "unregister");
696  break;
697  case -ENOENT:
698  fid = (struct m0_fid *)arg;
699  rc = m0_isc_comp_register(string_update, "string_update", fid);
700  M0_UT_ASSERT(rc == 0);
701  break;
702  case -ENOMEM:
703  fid = (struct m0_fid *)arg;
704  m0_fi_disable("isc_comp_launch", "oom");
705  break;
706  case -EPERM:
707  m0_fi_disable("string_update", "comp_error");
708  break;
709  case -ENOMSG:
710  m0_fi_disable("req_fop_prepare", "at_mismatch");
711  m0_fi_disable("string_update", "at_mismatch");
712  break;
713  default:
714  break;
715  }
716 }
717 
718 static void remote_invocation(struct m0_fid *fid, int exp_rc, uint32_t f_type, uint32_t buf_type)
719 {
720  struct m0_fop *req_fop;
721  struct m0_fop *reply_fop;
722  struct m0_fop_isc_rep *repl;
723  struct m0_fop_isc *req;
724  struct m0_buf recv_buf = M0_BUF_INIT0;
725  struct m0_isc_comp *comp;
726  int ret_rc;
727  int rc;
728  int i;
729 
730  M0_ALLOC_PTR(req_fop);
731  M0_ASSERT(req_fop != NULL);
732 
734  rc = m0_fop_data_alloc(req_fop);
735  M0_ASSERT(rc == 0);
736 
737  if (M0_IN(exp_rc, (-EINVAL, -ENOMEM, -EPERM, -ENOMSG, 0))) {
738  req_fop_prepare(req_fop, buf_type, fid, f_type);
739  } else {
740  struct m0_fop_isc *fop_isc = m0_fop_data(req_fop);
741  fop_isc->fi_comp_id = *fid;
742  }
743 
746  M0_UT_ASSERT(rc == 0);
747 
749  repl = (struct m0_fop_isc_rep *)m0_fop_data(reply_fop);
750  M0_UT_ASSERT(repl->fir_rc == exp_rc);
751  req = m0_fop_data(req_fop);
752  ret_rc = m0_rpc_at_rep_get(&req->fi_ret, &repl->fir_ret, &recv_buf);
753  /* Ensure that a valid cookie is returned. */
754  comp = m0_cookie_of(&repl->fir_comp_cookie, struct m0_isc_comp, ic_gen);
755  if (!M0_IN(repl->fir_rc, (-ENOENT, -EINVAL))) {
756  M0_UT_ASSERT(comp != NULL);
757  M0_UT_ASSERT(m0_fid_eq(&comp->ic_fid, &req->fi_comp_id));
758  } else if (f_type != FT_NO_INPUT)
759  M0_UT_ASSERT(comp == NULL);
760  switch (f_type) {
761  case FT_NEITHER_IO:
762  case FT_NO_OUTPUT:
763  M0_UT_ASSERT(ret_rc == 0);
764  break;
765  case FT_NO_INPUT:
766  M0_UT_ASSERT(ret_rc == 0);
767  break;
768  case FT_BOTH_IO:
769  for (i = 0; i < recv_buf.b_nob; ++i) {
770  M0_UT_ASSERT(((uint8_t *)recv_buf.b_addr)[i] ==
771  'b');
772  }
773  break;
774  }
775  m0_rpc_at_fini(&req->fi_args);
776  m0_rpc_at_fini(&req->fi_ret);
777  m0_rpc_at_fini(&repl->fir_ret);
778  m0_fop_put_lock(req_fop);
779 }
780 
781 static uint32_t expected_output(uint32_t f_type)
782 {
783  switch (f_type) {
784  case FT_NEITHER_IO:
785  case FT_NO_OUTPUT:
786  case FT_BOTH_IO:
787  return 0;
788  case FT_NO_INPUT:
789  return -EINVAL;
790  default:
791  M0_UT_ASSERT(false);
792  }
793  return 0;
794 }
795 
796 static void comp_remote_invoke(struct comp_req_aux *cra, uint32_t f_type)
797 {
798  struct m0_fid fid;
799  int rc;
800  int exp_rc;
801 
802  exp_rc = expected_output(f_type);
803  fid_get(cra->cra_name, &fid);
805  M0_UT_ASSERT(rc == 0);
808 }
809 
810 /*
811  * Tests four possible signatures of a computation. See @funct_type.
812  */
813 static void test_comp_signature(void)
814 {
815  struct m0_reqh *reqh;
816  struct m0_reqh_service *svc_isc;
817  int rc;
818 
820  M0_UT_ASSERT(rc == 0);
823  M0_UT_ASSERT(svc_isc != NULL);
825  /* no-i/p and no-o/p. */
826  cra.cra_name = m0_strdup("null_computation");
829 
830  /* i/p and no-o/p */
831  cra.cra_name = m0_strdup("strguess");
834 
835  /* no-i/p and o/p err */
836  cra.cra_name = m0_strdup("strguess");
839 
840  /* Both i/p and o/p. */
841  cra.cra_name = m0_strdup("string_update");
844 
847 }
848 
849 /* Tests the case when isc-fom is made to wait by computation. */
850 static void test_remote_waiting(void)
851 {
852  struct m0_reqh *reqh;
853  struct m0_reqh_service *svc_isc;
854  struct m0_isc_comp_req comp_req;
855  struct m0_fid fid;
856  struct m0_fop *arg_fop;
857  struct m0_clink waiter;
858  uint32_t phase;
859  int rc;
860 
862  M0_UT_ASSERT(rc == 0);
865  M0_UT_ASSERT(svc_isc != NULL);
866  fid_get("barrier", &fid);
867  cra.cra_name = m0_strdup("barrier");
868  cra.cra_comp = barrier;
869  rc = m0_isc_comp_register(barrier, "barrier", &fid);
870  M0_UT_ASSERT(rc == 0);
873  /* Prepare to wait for reply fop. */
876  m0_clink_init(&waiter, NULL);
878  waiter.cl_is_oneshot = true;
880  &arg_fop);
881  /* Spin till the fom is executed. */
882  while (vis_ent.ve_count == 0);
884 
885  /* Launch a local computation to release the waiting fom. */
886  comp_req_init(&comp_req, 0);
887  rc = m0_isc_comp_req_exec_sync(&comp_req);
888  M0_UT_ASSERT(rc == 0);
890 
891  /* Wait for reply fop. */
892  m0_chan_wait(&waiter);
893  phase = remote_invocation_async(&fid, 0, BT_INLINE, phase, &arg_fop);
894  m0_fop_put0_lock(arg_fop);
895  M0_UT_ASSERT(phase == FPP_COMPLETE);
898 }
899 
900 /*
901  * Tests error path associated with the remote invocation of a
902  * computation. Following error-paths are exercised during the test:
903  * -when computation is not registered (-ENOENT)
904  * -when computation is scheduled to unregister (-EINVAL)
905  * -insufficient memory (-ENOMEM)
906  * -when m0_rpc_at buffer is not initialised properly (-EPROTO)
907  * -when a computation returns an error (-EPERM)
908  * -when caller does not anticipate response via bulk-io.(-ENOMSG)
909  * -when all parameters are sane (0)
910  */
911 static void test_remote_err_path(void)
912 {
913  struct m0_reqh *reqh;
914  struct m0_reqh_service *svc_isc;
915  struct m0_fid fid;
916  int rc;
917  int i;
918  int j;
919 
921  M0_UT_ASSERT(rc == 0);
924  M0_UT_ASSERT(svc_isc != NULL);
925  fid_get("string_update", &fid);
926  rc = m0_isc_comp_register(string_update, "string_update", &fid);
927  M0_UT_ASSERT(rc == 0);
929  for (j = BT_INLINE; j < BT_INBULK + 1; ++j) {
930  for (i = 0; i < ARRAY_SIZE(ret_codes); ++i) {
934  }
935  }
938 }
939 
941  .ts_name = "isc-service-ut",
942  .ts_init = NULL,
943  .ts_fini = NULL,
944  .ts_tests = {
945  {"comp-launch", test_comp_launch, "Nachiket"},
946  {"local-error-path", test_local_err_path, "Nachiket"},
947  {"comp-state", test_comp_state, "Nachiket"},
948  {"remote-comp-signature", test_comp_signature, "Nachiket"},
949  {"remote-waiting", test_remote_waiting, "Nachiket"},
950  {"remote-error-path", test_remote_err_path, "Nachiket"},
951  {NULL, NULL}
952  }
953 };
fop_processing_phase
Definition: service_ut.c:539
M0_INTERNAL m0_bcount_t m0_net_domain_get_max_buffer_segment_size(struct m0_net_domain *dom)
M0_INTERNAL int m0_rpc_post(struct m0_rpc_item *item)
Definition: rpc.c:63
M0_INTERNAL void cc_block_launch(struct cnc_cntrl_block *cc_block, void(*t_op)(void *))
Definition: common.c:47
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
static struct m0_rpc_client_ctx isc_ut_cctx
Definition: service_ut.c:43
M0_INTERNAL int m0_reqh_service_start(struct m0_reqh_service *service)
Definition: reqh_service.c:343
static void remote_invocation(struct m0_fid *fid, int exp_rc, uint32_t f_type, uint32_t buf_type)
Definition: service_ut.c:718
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
struct m0_mutex ve_mutex
Definition: service_ut.c:117
void m0_net_domain_fini(struct m0_net_domain *dom)
Definition: domain.c:71
#define m0_strdup(s)
Definition: string.h:43
struct m0_reqh * m0_cs_reqh_get(struct m0_motr *cctx)
Definition: setup.c:1762
M0_INTERNAL void m0_reqh_service_stop(struct m0_reqh_service *service)
Definition: reqh_service.c:402
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
buf_type
Definition: service_ut.c:111
#define ergo(a, b)
Definition: misc.h:293
void * b_addr
Definition: buf.h:39
#define F_CONT
Definition: service_ut.c:38
char * cra_name
Definition: service_ut.c:130
static struct io_request req
Definition: file.c:100
M0_INTERNAL bool m0_buf_streq(const struct m0_buf *buf, const char *str)
Definition: buf.c:132
M0_INTERNAL void m0_fop_init(struct m0_fop *fop, struct m0_fop_type *fopt, void *data, void(*fop_release)(struct m0_ref *))
Definition: fop.c:79
char ** rsx_argv
Definition: rpclib.h:77
M0_INTERNAL void m0_rpc_at_init(struct m0_rpc_at_buf *ab)
Definition: at.c:433
M0_INTERNAL void m0_reqh_service_prepare_to_stop(struct m0_reqh_service *service)
Definition: reqh_service.c:375
int32_t fir_rc
Definition: isc_fops.h:75
struct m0_rpc_at_buf fir_ret
Definition: isc_fops.h:79
int m0_rpc_server_start(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:50
struct m0_chan icr_chan
Definition: isc.h:189
M0_INTERNAL void atut__bufdata_alloc(struct m0_buf *buf, size_t size, struct m0_rpc_machine *rmach)
Definition: at_ut.c:143
#define SERVER_ENDPOINT_ADDR
Definition: service_ut.c:35
static int null_computation(struct m0_buf *in, struct m0_buf *out, struct m0_isc_comp_private *comp_data, int *rc)
Definition: service_ut.c:202
M0_INTERNAL void m0_buf_init(struct m0_buf *buf, void *data, uint32_t nob)
Definition: buf.c:37
struct m0_bufvec data
Definition: di.c:40
M0_INTERNAL int m0_isc_comp_req_exec_sync(struct m0_isc_comp_req *comp_req)
Definition: isc.c:517
static void test_remote_waiting(void)
Definition: service_ut.c:850
struct m0_net_domain * ntm_dom
Definition: net.h:853
void * m0_fop_data(const struct m0_fop *fop)
Definition: fop.c:220
struct comp_req_aux cra
M0_INTERNAL int m0_rpc_at_add(struct m0_rpc_at_buf *ab, const struct m0_buf *buf, const struct m0_rpc_conn *conn)
Definition: at.c:462
M0_INTERNAL void m0_fom_wait_on(struct m0_fom *fom, struct m0_chan *chan, struct m0_fom_callback *cb)
Definition: fom.c:1490
uint64_t m0_bcount_t
Definition: types.h:77
int icr_rc
Definition: isc.h:171
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
static struct m0_reqh_service * iscs
Definition: service_ut.c:41
Definition: ub.c:49
struct m0_semaphore * ta_barrier
Definition: common.h:37
Definition: ut.h:77
static struct m0_rpc_item * item
Definition: item.c:56
M0_INTERNAL int m0_rpc_at_rep_get(struct m0_rpc_at_buf *sent, struct m0_rpc_at_buf *rcvd, struct m0_buf *out)
Definition: at.c:606
struct m0_fom * icp_fom
Definition: isc.h:134
struct m0_chan ve_chan
Definition: service_ut.c:118
struct m0_fid fid
Definition: di.c:46
static void isc_ut_client_stop()
Definition: service_ut.c:193
Definition: buf.h:37
static int strguess(struct m0_buf *in, struct m0_buf *out, struct m0_isc_comp_private *comp_data, int *rc)
Definition: service_ut.c:245
static void test_comp_signature(void)
Definition: service_ut.c:813
void m0_fop_put0_lock(struct m0_fop *fop)
Definition: fop.c:213
int i
Definition: dir.c:1033
static void vis_entry_fini(void)
Definition: service_ut.c:277
def args
Definition: addb2db.py:716
static void test_local_err_path(void)
Definition: service_ut.c:419
M0_INTERNAL void m0_fid_set(struct m0_fid *fid, uint64_t container, uint64_t key)
Definition: fid.c:116
return M0_ERR(-EOPNOTSUPP)
m0_bcount_t rm_bulk_cutoff
Definition: rpc_machine.h:157
struct m0_reqh_service_type m0_iscs_type
Definition: isc_service.c:76
char * isc_ut_server_args[]
Definition: service_ut.c:47
static void ret_codes_postcond(int exp_rc, void *arg)
Definition: service_ut.c:688
static void ret_codes_precond(int exp_rc, uint32_t buf_type, struct m0_fid *fid)
Definition: service_ut.c:654
const char * rsx_log_file_name
Definition: rpclib.h:81
static struct m0_rpc_machine * fom_rmach(const struct m0_fom *fom)
Definition: service_ut.c:209
int isc_ut_server_start(void)
Definition: service_ut.c:142
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
M0_INTERNAL int m0_isc_comp_state_probe(const struct m0_fid *fid)
Definition: isc.c:668
static void m0_fi_enable(const char *func, const char *tag)
Definition: finject.h:276
struct m0_net_transfer_mc rm_tm
Definition: rpc_machine.h:88
M0_INTERNAL void m0_chan_init(struct m0_chan *chan, struct m0_mutex *ch_guard)
Definition: chan.c:96
m0_bcount_t b_nob
Definition: buf.h:38
#define M0_ASSERT(cond)
uint32_t rcx_max_rpc_msg_size
Definition: rpclib.h:156
struct m0_fop_type m0_fop_isc_fopt
Definition: isc_fops.c:33
Definition: service_ut.c:116
M0_INTERNAL m0_bcount_t m0_rpc_max_msg_size(struct m0_net_domain *ndom, m0_bcount_t rpc_size)
Definition: rpc.c:302
static void vis_entry_init(uint32_t barrier_cnt)
Definition: service_ut.c:269
volatile uint32_t ve_count
Definition: service_ut.c:119
M0_INTERNAL void m0_reqh_service_fini(struct m0_reqh_service *service)
Definition: reqh_service.c:457
static struct m0_fop reply_fop
Definition: fsync.c:64
struct m0_fid fi_comp_id
Definition: isc_fops.h:57
uint64_t f_key
Definition: fid.h:329
struct m0_rpc_conn rcx_connection
Definition: rpclib.h:146
static int ret_codes[]
Definition: service_ut.c:123
static const char * SERVER_LOGFILE
Definition: service_ut.c:46
struct m0_rpc_at_buf fi_args
Definition: isc_fops.h:63
struct remote_invoke_var remote_call_info
#define M0_BUF_INIT0
Definition: buf.h:71
int m0_net_xprt_nr(void)
Definition: net.c:168
static void test_remote_err_path(void)
Definition: service_ut.c:911
int m0_rpc_client_stop(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:217
struct m0_fid ic_fid
Definition: isc_service.h:51
static void fid_get(const char *f_name, struct m0_fid *fid)
Definition: service_ut.c:135
struct m0_net_xprt * m0_net_xprt_default_get(void)
Definition: net.c:151
struct m0_cookie icr_cookie
Definition: isc.h:169
struct m0_fop * m0_fop_get(struct m0_fop *fop)
Definition: fop.c:162
int m0_rpc_client_start(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:160
struct m0_net_xprt ** rsx_xprts
Definition: rpclib.h:69
struct m0_rpc_item * ri_reply
Definition: item.h:163
M0_INTERNAL int m0_buf_alloc(struct m0_buf *buf, size_t size)
Definition: buf.c:43
void * m0_alloc(size_t size)
Definition: memory.c:126
static void isc_item_cb(struct m0_rpc_item *item)
Definition: service_ut.c:67
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
uint32_t rcx_recv_queue_min_length
Definition: rpclib.h:153
int m0_rpc_post_sync(struct m0_fop *fop, struct m0_rpc_session *session, const struct m0_rpc_item_ops *ri_ops, m0_time_t deadline)
Definition: rpclib.c:284
struct m0_ut_suite isc_service_ut
Definition: service_ut.c:940
M0_INTERNAL int m0_reqh_service_allocate(struct m0_reqh_service **out, const struct m0_reqh_service_type *stype, struct m0_reqh_context *rctx)
Definition: reqh_service.c:185
#define CLIENT_ENDPOINT_ADDR
Definition: service_ut.c:37
Definition: reqh.h:94
#define BARRIER_CNT
Definition: service_ut.c:39
Definition: dump.c:103
M0_INTERNAL m0_bcount_t m0_net_domain_get_max_buffer_size(struct m0_net_domain *dom)
Definition: chan.h:229
M0_INTERNAL int m0_fop_data_alloc(struct m0_fop *fop)
Definition: fop.c:71
static uint32_t cc_type
Definition: service_ut.c:45
M0_INTERNAL void m0_reqh_service_init(struct m0_reqh_service *service, struct m0_reqh *reqh, const struct m0_fid *fid)
Definition: reqh_service.c:428
M0_INTERNAL int m0_isc_comp_req_exec(struct m0_isc_comp_req *comp_req)
Definition: isc.c:497
static struct m0_rpc_server_ctx isc_ut_sctx
Definition: service_ut.c:42
static uint64_t min64u(uint64_t a, uint64_t b)
Definition: arith.h:66
struct m0_fid * rcx_fid
Definition: rpclib.h:161
struct m0_net_domain * rcx_net_dom
Definition: rpclib.h:128
M0_INTERNAL void m0_chan_signal_lock(struct m0_chan *chan)
Definition: chan.c:165
M0_INTERNAL void m0_isc_comp_unregister(const struct m0_fid *fid)
Definition: isc.c:652
int(* cra_comp)(struct m0_buf *arg_in, struct m0_buf *args_out, struct m0_isc_comp_private *comp_data, int *rc)
Definition: service_ut.c:127
struct m0_cookie fir_comp_cookie
Definition: isc_fops.h:77
uint64_t rcx_max_rpcs_in_flight
Definition: rpclib.h:136
void(* rio_replied)(struct m0_rpc_item *item)
Definition: item.h:300
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
uint64_t f_type
Definition: md_fops.h:398
Definition: fom.h:481
const char * ts_name
Definition: ut.h:99
Definition: common.h:32
M0_INTERNAL void m0_isc_comp_req_fini(struct m0_isc_comp_req *comp_req)
Definition: isc.c:567
static struct m0_net_domain isc_ut_client_ndom
Definition: service_ut.c:44
char * fixed_str
Definition: service_ut.c:133
M0_INTERNAL struct m0_reqh_service * m0_reqh_service_find(const struct m0_reqh_service_type *st, const struct m0_reqh *reqh)
Definition: reqh_service.c:538
struct m0_reqh reqh
Definition: rm_foms.c:48
uint32_t ve_wait_count
Definition: service_ut.c:120
static void comp_remote_invoke(struct comp_req_aux *cra, uint32_t f_type)
Definition: service_ut.c:796
int m0_net_domain_init(struct m0_net_domain *dom, const struct m0_net_xprt *xprt)
Definition: domain.c:36
int rsx_xprts_nr
Definition: rpclib.h:71
static uint32_t expected_output(uint32_t f_type)
Definition: service_ut.c:781
struct m0_rpc_session rcx_session
Definition: rpclib.h:147
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
Definition: fid.h:38
#define SERVER_ENDPOINT
Definition: service_ut.c:36
static void isc_ut_server_stop(void)
Definition: service_ut.c:164
M0_INTERNAL void m0_fop_release(struct m0_ref *ref)
Definition: fop.c:148
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
const struct m0_rpc_item_ops * ri_ops
Definition: item.h:149
#define M0_UT_CONF_PROCESS
Definition: misc.h:45
struct m0_rpc_at_buf fi_ret
Definition: isc_fops.h:67
struct m0_net_xprt ** m0_net_all_xprt_get(void)
Definition: net.c:161
static const struct m0_rpc_item_ops isc_item_ops
Definition: service_ut.c:83
struct m0_rpc_session * ri_session
Definition: item.h:147
static void req_fop_prepare(struct m0_fop *req_fop, uint32_t buf_type, struct m0_fid *fid, uint32_t f_type)
Definition: service_ut.c:598
const char * rcx_remote_addr
Definition: rpclib.h:134
m0_bcount_t size
Definition: di.c:39
M0_INTERNAL void m0_rpc_at_fini(struct m0_rpc_at_buf *ab)
Definition: at.c:441
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
void m0_fop_put_lock(struct m0_fop *fop)
Definition: fop.c:199
static void comp_req_init(void *arg, int tid)
Definition: service_ut.c:329
static int barrier(struct m0_buf *in, struct m0_buf *out, struct m0_isc_comp_private *comp_data, int *rc)
Definition: service_ut.c:288
struct m0_fop * m0_rpc_item_to_fop(const struct m0_rpc_item *item)
Definition: fop.c:346
const char * rcx_local_addr
Definition: rpclib.h:131
struct m0_chan riv_chan
Definition: service_ut.c:59
void m0_rpc_server_stop(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:85
static int string_update(struct m0_buf *in, struct m0_buf *out, struct m0_isc_comp_private *comp_data, int *rc)
Definition: service_ut.c:215
struct m0_rpc_machine rcx_rpc_machine
Definition: rpclib.h:145
M0_INTERNAL void m0_isc_comp_req_init(struct m0_isc_comp_req *comp_req, const struct m0_buf *comp_args, const struct m0_fid *comp_fid, const struct m0_cookie *comp_cookie, enum m0_isc_comp_req_type comp_req_type, struct m0_reqh *reqh)
Definition: isc.c:537
static void local_invocation(struct m0_isc_comp_req *comp_req, struct m0_fid *fid, int exp_rc)
Definition: service_ut.c:311
static void test_comp_launch(void)
Definition: service_ut.c:359
void * ta_data
Definition: common.h:36
#define M0_UT_PATH(name)
Definition: misc.h:41
#define out(...)
Definition: gen.c:41
static void comp_launch(void *args)
Definition: service_ut.c:256
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
static void test_comp_state(void)
Definition: service_ut.c:470
concc_type
Definition: service_ut.c:105
static void isc_ut_client_start(void)
Definition: service_ut.c:172
M0_INTERNAL void m0_chan_fini_lock(struct m0_chan *chan)
Definition: chan.c:112
Definition: mutex.h:47
M0_INTERNAL int m0_isc_comp_register(int(*ftn)(struct m0_buf *arg_in, struct m0_buf *args_out, struct m0_isc_comp_private *comp_data, int *rc), const char *f_name, const struct m0_fid *ftn_fid)
Definition: isc.c:609
struct m0_rpc_item f_item
Definition: fop.h:83
M0_INTERNAL void m0_chan_broadcast(struct m0_chan *chan)
Definition: chan.c:172
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
struct m0_fid g_process_fid
Definition: ut.c:689
struct m0_fom_callback fo_cb
Definition: fom.h:488
#define M0_UT_ASSERT(a)
Definition: ut.h:46
M0_INTERNAL unsigned int m0_full_name_hash(const unsigned char *name, unsigned int len)
Definition: misc.c:266
struct m0_motr rsx_motr_ctx
Definition: rpclib.h:84
struct m0_mutex riv_guard
Definition: service_ut.c:58
static uint32_t remote_invocation_async(struct m0_fid *fid, int exp_rc, uint32_t buf_type, uint32_t phase, struct m0_fop **arg_fop)
Definition: service_ut.c:546
const m0_time_t M0_TIME_IMMEDIATELY
Definition: time.c:107
Definition: fop.h:79
M0_INTERNAL void cc_block_init(struct cnc_cntrl_block *cc_block, size_t size, void(*t_data_init)(void *, int))
Definition: common.c:29
funct_type
Definition: service_ut.c:90
struct visitor_entry vis_ent
M0_INTERNAL int m0_rpc_at_recv(struct m0_rpc_at_buf *ab, const struct m0_rpc_conn *conn, uint32_t len, bool force_bulk)
Definition: at.c:508
uint32_t ab_type
Definition: at.h:251