gf_vect_dot_prod_test.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /**********************************************************************
  2. Copyright(c) 2011-2015 Intel Corporation All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions
  5. are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in
  10. the documentation and/or other materials provided with the
  11. distribution.
  12. * Neither the name of Intel Corporation nor the names of its
  13. contributors may be used to endorse or promote products derived
  14. from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  16. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  17. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  18. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  19. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  20. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  21. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. **********************************************************************/
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h> // for memset, memcmp
  30. #include "erasure_code.h"
  31. #include "test.h"
  32. #ifndef FUNCTION_UNDER_TEST
  33. # define FUNCTION_UNDER_TEST gf_vect_dot_prod
  34. #endif
  35. #ifndef TEST_MIN_SIZE
  36. # define TEST_MIN_SIZE 32
  37. #endif
  38. #define str(s) #s
  39. #define xstr(s) str(s)
  40. #define TEST_LEN 8192
  41. #define TEST_SIZE (TEST_LEN/2)
  42. #ifndef TEST_SOURCES
  43. # define TEST_SOURCES 16
  44. #endif
  45. #ifndef RANDOMS
  46. # define RANDOMS 20
  47. #endif
  48. #define MMAX TEST_SOURCES
  49. #define KMAX TEST_SOURCES
  50. #ifdef EC_ALIGNED_ADDR
  51. // Define power of 2 range to check ptr, len alignment
  52. # define PTR_ALIGN_CHK_B 0
  53. # define LEN_ALIGN_CHK_B 0 // 0 for aligned only
  54. #else
  55. // Define power of 2 range to check ptr, len alignment
  56. # define PTR_ALIGN_CHK_B 32
  57. # define LEN_ALIGN_CHK_B 32 // 0 for aligned only
  58. #endif
  59. typedef unsigned char u8;
  60. void dump(unsigned char *buf, int len)
  61. {
  62. int i;
  63. for (i = 0; i < len;) {
  64. printf(" %2x", 0xff & buf[i++]);
  65. if (i % 32 == 0)
  66. printf("\n");
  67. }
  68. printf("\n");
  69. }
  70. void dump_matrix(unsigned char **s, int k, int m)
  71. {
  72. int i, j;
  73. for (i = 0; i < k; i++) {
  74. for (j = 0; j < m; j++) {
  75. printf(" %2x", s[i][j]);
  76. }
  77. printf("\n");
  78. }
  79. printf("\n");
  80. }
  81. void dump_u8xu8(unsigned char *s, int k, int m)
  82. {
  83. int i, j;
  84. for (i = 0; i < k; i++) {
  85. for (j = 0; j < m; j++) {
  86. printf(" %2x", 0xff & s[j + (i * m)]);
  87. }
  88. printf("\n");
  89. }
  90. printf("\n");
  91. }
  92. int main(int argc, char *argv[])
  93. {
  94. int i, j, rtest, srcs, m, k, nerrs, r, err;
  95. void *buf;
  96. u8 g[TEST_SOURCES], g_tbls[TEST_SOURCES * 32], src_in_err[TEST_SOURCES];
  97. u8 *dest, *dest_ref, *temp_buff, *buffs[TEST_SOURCES];
  98. u8 a[MMAX * KMAX], b[MMAX * KMAX], d[MMAX * KMAX];
  99. u8 src_err_list[TEST_SOURCES], *recov[TEST_SOURCES];
  100. int align, size;
  101. unsigned char *efence_buffs[TEST_SOURCES];
  102. unsigned int offset;
  103. u8 *ubuffs[TEST_SOURCES];
  104. u8 *udest_ptr;
  105. printf(xstr(FUNCTION_UNDER_TEST) ": %dx%d ", TEST_SOURCES, TEST_LEN);
  106. // Allocate the arrays
  107. for (i = 0; i < TEST_SOURCES; i++) {
  108. if (posix_memalign(&buf, 64, TEST_LEN)) {
  109. printf("alloc error: Fail");
  110. return -1;
  111. }
  112. buffs[i] = buf;
  113. }
  114. if (posix_memalign(&buf, 64, TEST_LEN)) {
  115. printf("alloc error: Fail");
  116. return -1;
  117. }
  118. dest = buf;
  119. if (posix_memalign(&buf, 64, TEST_LEN)) {
  120. printf("alloc error: Fail");
  121. return -1;
  122. }
  123. dest_ref = buf;
  124. if (posix_memalign(&buf, 64, TEST_LEN)) {
  125. printf("alloc error: Fail");
  126. return -1;
  127. }
  128. temp_buff = buf;
  129. // Test of all zeros
  130. for (i = 0; i < TEST_SOURCES; i++)
  131. memset(buffs[i], 0, TEST_LEN);
  132. memset(dest, 0, TEST_LEN);
  133. memset(temp_buff, 0, TEST_LEN);
  134. memset(dest_ref, 0, TEST_LEN);
  135. memset(g, 0, TEST_SOURCES);
  136. for (i = 0; i < TEST_SOURCES; i++)
  137. gf_vect_mul_init(g[i], &g_tbls[i * 32]);
  138. gf_vect_dot_prod_base(TEST_LEN, TEST_SOURCES, &g_tbls[0], buffs, dest_ref);
  139. FUNCTION_UNDER_TEST(TEST_LEN, TEST_SOURCES, g_tbls, buffs, dest);
  140. if (0 != memcmp(dest_ref, dest, TEST_LEN)) {
  141. printf("Fail zero " xstr(FUNCTION_UNDER_TEST) " \n");
  142. dump_matrix(buffs, 5, TEST_SOURCES);
  143. printf("dprod_base:");
  144. dump(dest_ref, 25);
  145. printf("dprod:");
  146. dump(dest, 25);
  147. return -1;
  148. }
  149. #ifdef TEST_VERBOSE
  150. else
  151. putchar('.');
  152. #endif
  153. // Rand data test
  154. for (rtest = 0; rtest < RANDOMS; rtest++) {
  155. for (i = 0; i < TEST_SOURCES; i++)
  156. for (j = 0; j < TEST_LEN; j++)
  157. buffs[i][j] = rand();
  158. for (i = 0; i < TEST_SOURCES; i++)
  159. g[i] = rand();
  160. for (i = 0; i < TEST_SOURCES; i++)
  161. gf_vect_mul_init(g[i], &g_tbls[i * 32]);
  162. gf_vect_dot_prod_base(TEST_LEN, TEST_SOURCES, &g_tbls[0], buffs, dest_ref);
  163. FUNCTION_UNDER_TEST(TEST_LEN, TEST_SOURCES, g_tbls, buffs, dest);
  164. if (0 != memcmp(dest_ref, dest, TEST_LEN)) {
  165. printf("Fail rand " xstr(FUNCTION_UNDER_TEST) " 1\n");
  166. dump_matrix(buffs, 5, TEST_SOURCES);
  167. printf("dprod_base:");
  168. dump(dest_ref, 25);
  169. printf("dprod:");
  170. dump(dest, 25);
  171. return -1;
  172. }
  173. #ifdef TEST_VERBOSE
  174. putchar('.');
  175. #endif
  176. }
  177. // Rand data test with varied parameters
  178. for (rtest = 0; rtest < RANDOMS; rtest++) {
  179. for (srcs = TEST_SOURCES; srcs > 0; srcs--) {
  180. for (i = 0; i < srcs; i++)
  181. for (j = 0; j < TEST_LEN; j++)
  182. buffs[i][j] = rand();
  183. for (i = 0; i < srcs; i++)
  184. g[i] = rand();
  185. for (i = 0; i < srcs; i++)
  186. gf_vect_mul_init(g[i], &g_tbls[i * 32]);
  187. gf_vect_dot_prod_base(TEST_LEN, srcs, &g_tbls[0], buffs, dest_ref);
  188. FUNCTION_UNDER_TEST(TEST_LEN, srcs, g_tbls, buffs, dest);
  189. if (0 != memcmp(dest_ref, dest, TEST_LEN)) {
  190. printf("Fail rand " xstr(FUNCTION_UNDER_TEST) " test 2\n");
  191. dump_matrix(buffs, 5, srcs);
  192. printf("dprod_base:");
  193. dump(dest_ref, 5);
  194. printf("dprod:");
  195. dump(dest, 5);
  196. return -1;
  197. }
  198. #ifdef TEST_VERBOSE
  199. putchar('.');
  200. #endif
  201. }
  202. }
  203. // Test erasure code using gf_vect_dot_prod
  204. // Pick a first test
  205. m = 9;
  206. k = 5;
  207. if (m > MMAX || k > KMAX)
  208. return -1;
  209. gf_gen_rs_matrix(a, m, k);
  210. // Make random data
  211. for (i = 0; i < k; i++)
  212. for (j = 0; j < TEST_LEN; j++)
  213. buffs[i][j] = rand();
  214. // Make parity vects
  215. for (i = k; i < m; i++) {
  216. for (j = 0; j < k; j++)
  217. gf_vect_mul_init(a[k * i + j], &g_tbls[j * 32]);
  218. #ifndef USEREF
  219. FUNCTION_UNDER_TEST(TEST_LEN, k, g_tbls, buffs, buffs[i]);
  220. #else
  221. gf_vect_dot_prod_base(TEST_LEN, k, &g_tbls[0], buffs, buffs[i]);
  222. #endif
  223. }
  224. // Random buffers in erasure
  225. memset(src_in_err, 0, TEST_SOURCES);
  226. for (i = 0, nerrs = 0; i < k && nerrs < m - k; i++) {
  227. err = 1 & rand();
  228. src_in_err[i] = err;
  229. if (err)
  230. src_err_list[nerrs++] = i;
  231. }
  232. // construct b by removing error rows
  233. for (i = 0, r = 0; i < k; i++, r++) {
  234. while (src_in_err[r]) {
  235. r++;
  236. continue;
  237. }
  238. for (j = 0; j < k; j++)
  239. b[k * i + j] = a[k * r + j];
  240. }
  241. if (gf_invert_matrix((u8 *) b, (u8 *) d, k) < 0)
  242. printf("BAD MATRIX\n");
  243. for (i = 0, r = 0; i < k; i++, r++) {
  244. while (src_in_err[r]) {
  245. r++;
  246. continue;
  247. }
  248. recov[i] = buffs[r];
  249. }
  250. // Recover data
  251. for (i = 0; i < nerrs; i++) {
  252. for (j = 0; j < k; j++)
  253. gf_vect_mul_init(d[k * src_err_list[i] + j], &g_tbls[j * 32]);
  254. #ifndef USEREF
  255. FUNCTION_UNDER_TEST(TEST_LEN, k, g_tbls, recov, temp_buff);
  256. #else
  257. gf_vect_dot_prod_base(TEST_LEN, k, &g_tbls[0], recov, temp_buff);
  258. #endif
  259. if (0 != memcmp(temp_buff, buffs[src_err_list[i]], TEST_LEN)) {
  260. printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
  261. printf("recov %d:", src_err_list[i]);
  262. dump(temp_buff, 25);
  263. printf("orig :");
  264. dump(buffs[src_err_list[i]], 25);
  265. return -1;
  266. }
  267. }
  268. // Do more random tests
  269. for (rtest = 0; rtest < RANDOMS; rtest++) {
  270. while ((m = (rand() % MMAX)) < 2) ;
  271. while ((k = (rand() % KMAX)) >= m || k < 1) ;
  272. if (m > MMAX || k > KMAX)
  273. continue;
  274. gf_gen_rs_matrix(a, m, k);
  275. // Make random data
  276. for (i = 0; i < k; i++)
  277. for (j = 0; j < TEST_LEN; j++)
  278. buffs[i][j] = rand();
  279. // Make parity vects
  280. for (i = k; i < m; i++) {
  281. for (j = 0; j < k; j++)
  282. gf_vect_mul_init(a[k * i + j], &g_tbls[j * 32]);
  283. #ifndef USEREF
  284. FUNCTION_UNDER_TEST(TEST_LEN, k, g_tbls, buffs, buffs[i]);
  285. #else
  286. gf_vect_dot_prod_base(TEST_LEN, k, &g_tbls[0], buffs, buffs[i]);
  287. #endif
  288. }
  289. // Random errors
  290. memset(src_in_err, 0, TEST_SOURCES);
  291. for (i = 0, nerrs = 0; i < k && nerrs < m - k; i++) {
  292. err = 1 & rand();
  293. src_in_err[i] = err;
  294. if (err)
  295. src_err_list[nerrs++] = i;
  296. }
  297. if (nerrs == 0) { // should have at least one error
  298. while ((err = (rand() % KMAX)) >= k) ;
  299. src_err_list[nerrs++] = err;
  300. src_in_err[err] = 1;
  301. }
  302. // construct b by removing error rows
  303. for (i = 0, r = 0; i < k; i++, r++) {
  304. while (src_in_err[r]) {
  305. r++;
  306. continue;
  307. }
  308. for (j = 0; j < k; j++)
  309. b[k * i + j] = a[k * r + j];
  310. }
  311. if (gf_invert_matrix((u8 *) b, (u8 *) d, k) < 0)
  312. printf("BAD MATRIX\n");
  313. for (i = 0, r = 0; i < k; i++, r++) {
  314. while (src_in_err[r]) {
  315. r++;
  316. continue;
  317. }
  318. recov[i] = buffs[r];
  319. }
  320. // Recover data
  321. for (i = 0; i < nerrs; i++) {
  322. for (j = 0; j < k; j++)
  323. gf_vect_mul_init(d[k * src_err_list[i] + j], &g_tbls[j * 32]);
  324. #ifndef USEREF
  325. FUNCTION_UNDER_TEST(TEST_LEN, k, g_tbls, recov, temp_buff);
  326. #else
  327. gf_vect_dot_prod_base(TEST_LEN, k, &g_tbls[0], recov, temp_buff);
  328. #endif
  329. if (0 != memcmp(temp_buff, buffs[src_err_list[i]], TEST_LEN)) {
  330. printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
  331. printf(" - erase list = ");
  332. for (i = 0; i < nerrs; i++)
  333. printf(" %d", src_err_list[i]);
  334. printf("\na:\n");
  335. dump_u8xu8((u8 *) a, m, k);
  336. printf("inv b:\n");
  337. dump_u8xu8((u8 *) d, k, k);
  338. printf("orig data:\n");
  339. dump_matrix(buffs, m, 25);
  340. printf("orig :");
  341. dump(buffs[src_err_list[i]], 25);
  342. printf("recov %d:", src_err_list[i]);
  343. dump(temp_buff, 25);
  344. return -1;
  345. }
  346. }
  347. #ifdef TEST_VERBOSE
  348. putchar('.');
  349. #endif
  350. }
  351. // Run tests at end of buffer for Electric Fence
  352. align = (LEN_ALIGN_CHK_B != 0) ? 1 : 16;
  353. for (size = TEST_MIN_SIZE; size <= TEST_SIZE; size += align) {
  354. for (i = 0; i < TEST_SOURCES; i++)
  355. for (j = 0; j < TEST_LEN; j++)
  356. buffs[i][j] = rand();
  357. for (i = 0; i < TEST_SOURCES; i++) // Line up TEST_SIZE from end
  358. efence_buffs[i] = buffs[i] + TEST_LEN - size;
  359. for (i = 0; i < TEST_SOURCES; i++)
  360. g[i] = rand();
  361. for (i = 0; i < TEST_SOURCES; i++)
  362. gf_vect_mul_init(g[i], &g_tbls[i * 32]);
  363. gf_vect_dot_prod_base(size, TEST_SOURCES, &g_tbls[0], efence_buffs, dest_ref);
  364. FUNCTION_UNDER_TEST(size, TEST_SOURCES, g_tbls, efence_buffs, dest);
  365. if (0 != memcmp(dest_ref, dest, size)) {
  366. printf("Fail rand " xstr(FUNCTION_UNDER_TEST) " test 3\n");
  367. dump_matrix(efence_buffs, 5, TEST_SOURCES);
  368. printf("dprod_base:");
  369. dump(dest_ref, align);
  370. printf("dprod:");
  371. dump(dest, align);
  372. return -1;
  373. }
  374. #ifdef TEST_VERBOSE
  375. putchar('.');
  376. #endif
  377. }
  378. // Test rand ptr alignment if available
  379. for (rtest = 0; rtest < RANDOMS; rtest++) {
  380. size = (TEST_LEN - PTR_ALIGN_CHK_B) & ~(TEST_MIN_SIZE - 1);
  381. srcs = rand() % TEST_SOURCES;
  382. if (srcs == 0)
  383. continue;
  384. offset = (PTR_ALIGN_CHK_B != 0) ? 1 : PTR_ALIGN_CHK_B;
  385. // Add random offsets
  386. for (i = 0; i < srcs; i++)
  387. ubuffs[i] = buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
  388. udest_ptr = dest + (rand() & (PTR_ALIGN_CHK_B - offset));
  389. memset(dest, 0, TEST_LEN); // zero pad to check write-over
  390. for (i = 0; i < srcs; i++)
  391. for (j = 0; j < size; j++)
  392. ubuffs[i][j] = rand();
  393. for (i = 0; i < srcs; i++)
  394. g[i] = rand();
  395. for (i = 0; i < srcs; i++)
  396. gf_vect_mul_init(g[i], &g_tbls[i * 32]);
  397. gf_vect_dot_prod_base(size, srcs, &g_tbls[0], ubuffs, dest_ref);
  398. FUNCTION_UNDER_TEST(size, srcs, g_tbls, ubuffs, udest_ptr);
  399. if (memcmp(dest_ref, udest_ptr, size)) {
  400. printf("Fail rand " xstr(FUNCTION_UNDER_TEST) " ualign srcs=%d\n",
  401. srcs);
  402. dump_matrix(ubuffs, 5, TEST_SOURCES);
  403. printf("dprod_base:");
  404. dump(dest_ref, 25);
  405. printf("dprod:");
  406. dump(udest_ptr, 25);
  407. return -1;
  408. }
  409. // Confirm that padding around dests is unchanged
  410. memset(dest_ref, 0, PTR_ALIGN_CHK_B); // Make reference zero buff
  411. offset = udest_ptr - dest;
  412. if (memcmp(dest, dest_ref, offset)) {
  413. printf("Fail rand ualign pad start\n");
  414. return -1;
  415. }
  416. if (memcmp(dest + offset + size, dest_ref, PTR_ALIGN_CHK_B - offset)) {
  417. printf("Fail rand ualign pad end\n");
  418. return -1;
  419. }
  420. #ifdef TEST_VERBOSE
  421. putchar('.');
  422. #endif
  423. }
  424. // Test all size alignment
  425. align = (LEN_ALIGN_CHK_B != 0) ? 1 : 16;
  426. for (size = TEST_LEN; size >= TEST_MIN_SIZE; size -= align) {
  427. srcs = TEST_SOURCES;
  428. for (i = 0; i < srcs; i++)
  429. for (j = 0; j < size; j++)
  430. buffs[i][j] = rand();
  431. for (i = 0; i < srcs; i++)
  432. g[i] = rand();
  433. for (i = 0; i < srcs; i++)
  434. gf_vect_mul_init(g[i], &g_tbls[i * 32]);
  435. gf_vect_dot_prod_base(size, srcs, &g_tbls[0], buffs, dest_ref);
  436. FUNCTION_UNDER_TEST(size, srcs, g_tbls, buffs, dest);
  437. if (memcmp(dest_ref, dest, size)) {
  438. printf("Fail rand " xstr(FUNCTION_UNDER_TEST) " ualign len=%d\n",
  439. size);
  440. dump_matrix(buffs, 5, TEST_SOURCES);
  441. printf("dprod_base:");
  442. dump(dest_ref, 25);
  443. printf("dprod:");
  444. dump(dest, 25);
  445. return -1;
  446. }
  447. }
  448. printf("done all: Pass\n");
  449. return 0;
  450. }