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