1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2018. ALL RIGHTS RESERVED.
3 * See file LICENSE for terms.
4 */
5
6 #include "ucp_datatype.h"
7 #include "ucp_test.h"
8
9 #include <common/test_helpers.h>
10
11 namespace ucp {
12
13
14 data_type_desc_t &
make(ucp_datatype_t datatype,const void * buf,size_t length,size_t iov_cnt)15 data_type_desc_t::make(ucp_datatype_t datatype, const void *buf, size_t length,
16 size_t iov_cnt)
17 {
18 EXPECT_FALSE(is_valid());
19
20 if (m_length == 0) {
21 m_length = length;
22 }
23
24 if (m_origin == uintptr_t(NULL)) {
25 m_origin = uintptr_t(buf);
26 }
27
28 m_dt = datatype;
29 memset(m_iov, 0, sizeof(m_iov));
30
31 switch (m_dt & UCP_DATATYPE_CLASS_MASK) {
32 case UCP_DATATYPE_CONTIG:
33 m_buf = buf;
34 m_count = length / ucp_contig_dt_elem_size(datatype);
35 break;
36 case UCP_DATATYPE_IOV:
37 {
38 const size_t iov_length = (length > iov_cnt) ?
39 ucs::rand() % (length / iov_cnt) : 0;
40 size_t iov_length_it = 0;
41 for (size_t iov_it = 0; iov_it < iov_cnt - 1; ++iov_it) {
42 m_iov[iov_it].buffer = (char *)(buf) + iov_length_it;
43 m_iov[iov_it].length = iov_length;
44 iov_length_it += iov_length;
45 }
46
47 /* Last entry */
48 m_iov[iov_cnt - 1].buffer = (char *)(buf) + iov_length_it;
49 m_iov[iov_cnt - 1].length = length - iov_length_it;
50
51 m_buf = m_iov;
52 m_count = iov_cnt;
53 break;
54 }
55 case UCP_DATATYPE_GENERIC:
56 m_buf = buf;
57 m_count = length;
58 break;
59 default:
60 m_buf = NULL;
61 m_count = 0;
62 EXPECT_TRUE(false) << "Unsupported datatype";
63 break;
64 }
65
66 return *this;
67 }
68
69 int dt_gen_start_count = 0;
70 int dt_gen_finish_count = 0;
71
dt_common_start(void * context,size_t count)72 static void* dt_common_start(void *context, size_t count)
73 {
74 dt_gen_state *dt_state = new dt_gen_state;
75
76 dt_state->count = count;
77 dt_state->started = 1;
78 dt_state->magic = ucp::MAGIC;
79 dt_state->context = context;
80 dt_gen_start_count++;
81
82 return dt_state;
83 }
84
dt_common_start_pack(void * context,const void * buffer,size_t count)85 static void* dt_common_start_pack(void *context, const void *buffer,
86 size_t count)
87 {
88 return dt_common_start(NULL, count);
89 }
90
dt_common_start_unpack(void * context,void * buffer,size_t count)91 static void* dt_common_start_unpack(void *context, void *buffer, size_t count)
92 {
93 return dt_common_start(context, count);
94 }
95
96 template <typename T>
dt_packed_size(void * state)97 size_t dt_packed_size(void *state)
98 {
99 dt_gen_state *dt_state = (dt_gen_state*)state;
100
101 return dt_state->count * sizeof(T);
102 }
103
104 template <typename T>
dt_pack(void * state,size_t offset,void * dest,size_t max_length)105 size_t dt_pack(void *state, size_t offset, void *dest, size_t max_length)
106 {
107 dt_gen_state *dt_state = (dt_gen_state*)state;
108 T *p = reinterpret_cast<T*> (dest);
109 uint32_t count;
110
111 EXPECT_GT(dt_gen_start_count, dt_gen_finish_count);
112 EXPECT_EQ(1, dt_state->started);
113 EXPECT_EQ(uint32_t(MAGIC), dt_state->magic);
114
115 ucs_assert((offset % sizeof(T)) == 0);
116
117 count = std::min(max_length / sizeof(T),
118 dt_state->count - (offset / sizeof(T)));
119 for (unsigned i = 0; i < count; ++i) {
120 p[i] = (offset / sizeof(T)) + i;
121 }
122 return count * sizeof(T);
123 }
124
125 template <typename T>
dt_unpack(void * state,size_t offset,const void * src,size_t length)126 ucs_status_t dt_unpack(void *state, size_t offset, const void *src,
127 size_t length)
128 {
129 dt_gen_state *dt_state = (dt_gen_state*)state;
130 std::vector<T> *ctx;
131 uint32_t count;
132
133 EXPECT_GT(dt_gen_start_count, dt_gen_finish_count);
134 EXPECT_EQ(1, dt_state->started);
135 EXPECT_EQ(uint32_t(MAGIC), dt_state->magic);
136
137 ctx = reinterpret_cast<std::vector<T>*>(dt_state->context);
138 count = length / sizeof(T);
139 for (unsigned i = 0; i < count; ++i) {
140 T expected = ctx ? (*ctx)[offset / sizeof(T) + i] :
141 (offset / sizeof(T)) + i;
142 T actual = ((T*)src)[i];
143 if (actual != expected) {
144 UCS_TEST_ABORT("Invalid data at index " << i << ". expected: " <<
145 expected << " actual: " << actual << " offset: " <<
146 offset << ".");
147 }
148 }
149 return UCS_OK;
150 }
151
dt_err_unpack(void * state,size_t offset,const void * src,size_t length)152 static ucs_status_t dt_err_unpack(void *state, size_t offset, const void *src,
153 size_t length)
154 {
155 dt_gen_state *dt_state = (dt_gen_state*)state;
156
157 EXPECT_GT(dt_gen_start_count, dt_gen_finish_count);
158 EXPECT_EQ(1, dt_state->started);
159 EXPECT_EQ(uint32_t(MAGIC), dt_state->magic);
160
161 return UCS_ERR_NO_MEMORY;
162 }
163
dt_common_finish(void * state)164 static void dt_common_finish(void *state)
165 {
166 dt_gen_state *dt_state = (dt_gen_state*)state;
167
168 --dt_state->started;
169 EXPECT_EQ(0, dt_state->started);
170 dt_gen_finish_count++;
171 delete dt_state;
172 }
173
174 ucp_generic_dt_ops test_dt_uint32_ops = {
175 dt_common_start_pack,
176 dt_common_start_unpack,
177 dt_packed_size<uint32_t>,
178 dt_pack<uint32_t>,
179 dt_unpack<uint32_t>,
180 dt_common_finish
181 };
182
183 ucp_generic_dt_ops test_dt_uint8_ops = {
184 dt_common_start_pack,
185 dt_common_start_unpack,
186 dt_packed_size<uint8_t>,
187 dt_pack<uint8_t>,
188 dt_unpack<uint8_t>,
189 dt_common_finish
190 };
191
192 ucp_generic_dt_ops test_dt_uint32_err_ops = {
193 dt_common_start_pack,
194 dt_common_start_unpack,
195 dt_packed_size<uint32_t>,
196 dt_pack<uint32_t>,
197 dt_err_unpack,
198 dt_common_finish
199 };
200
201 } // ucp
202