/* * Copyright 2015 Kevin M Greenan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY * THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * vi: set noai tw=79 ts=4 sw=4: */ #include #include #include #include #include #include #include #include int test_make_systematic_matrix(int k, int m) { int *matrix = make_systematic_matrix(k, m); int is_identity = is_identity_matrix(matrix, k); if (!is_identity) { printf("Generating systematic matrix did not work!\n"); printf("Generator matrix: \n\n"); print_matrix(matrix, m+k, k); } free_systematic_matrix(matrix); return is_identity; } void dump_buffer(char *buf, int size, const char* filename) { int fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); ssize_t nbytes = write(fd, buf, size); if (nbytes < 0) { printf("dump_buffer: write error!\n"); } close(fd); } int test_invert_systematic_matrix(int k, int m, int num_missing) { int *inverse = (int*)malloc(sizeof(int)*k*k); int *prod = (int*)malloc(sizeof(int)*k*k); int *missing = (int*)malloc(sizeof(int)*(num_missing+1)); int *matrix = make_systematic_matrix(k, m); int *decoding_matrix = (int*)malloc(sizeof(int)*k*k); int *decoding_matrix_cpy = (int*)malloc(sizeof(int)*k*k); int n = k+m; int i, res; srand((unsigned int)time(0)); for (i = 0;i < num_missing+1; i++) { missing[i] = -1; } for (i = 0;i < num_missing; i++) { int idx = rand() % n; while (is_missing(missing, idx)) { idx = rand() % n; } missing[i] = idx; } create_decoding_matrix(matrix, decoding_matrix, missing, k, m); create_decoding_matrix(matrix, decoding_matrix_cpy, missing, k, m); gaussj_inversion(decoding_matrix, inverse, k); square_matrix_multiply(decoding_matrix_cpy, inverse, prod, k); res = is_identity_matrix(prod, k); if (!res) { printf("Inverting decoding matrix did not work!\n"); printf("Generator matrix: \n\n"); print_matrix(matrix, n, k); printf("Decoding matrix: \n\n"); print_matrix(decoding_matrix_cpy, k, k); printf("Inverse Decoding matrix: \n\n"); print_matrix(inverse, k, k); printf("Missing: \n\n"); print_matrix(missing, 1, num_missing); } free(inverse); free(prod); free(missing); free(decoding_matrix); free(decoding_matrix_cpy); free_systematic_matrix(matrix); return res; } char* gen_random_buffer(int blocksize) { int i; char *buf = (char*)malloc(blocksize); for (i = 0; i < blocksize; i++) { buf[i] = (char)(rand() % 255); } return buf; } int test_encode_decode(int k, int m, int num_missing, int blocksize) { char **data = (char**)malloc(sizeof(char*)*k); char **parity = (char**)malloc(sizeof(char*)*m); char **missing_bufs = (char**)malloc(sizeof(char*)*num_missing); int *missing = (int*)malloc(sizeof(int)*(num_missing+1)); int *matrix = make_systematic_matrix(k, m); int n = k + m; int i; int ret = 1; srand((unsigned int)time(0)); for (i = 0; i < k; i++) { data[i] = gen_random_buffer(blocksize); } for (i = 0; i < m; i++) { parity[i] = (char*)malloc(blocksize); } for (i = 0;i < num_missing+1; i++) { missing[i] = -1; } // Encode liberasurecode_rs_vand_encode(matrix, data, parity, k, m, blocksize); // Copy data and parity for (i = 0;i < num_missing; i++) { int idx = rand() % n; while (is_missing(missing, idx)) { idx = rand() % n; } missing_bufs[i] = (char*)malloc(blocksize); memcpy(missing_bufs[i], idx < k ? data[idx] : parity[idx - k], blocksize); missing[i] = idx; } // Zero missing bufs for (i = 0;i < num_missing; i++) { if (missing[i] < k) { memset(data[missing[i]], 0, blocksize); } else { memset(parity[missing[i] - k], 0, blocksize); } } // Decode and check liberasurecode_rs_vand_decode(matrix, data, parity, k, m, missing, blocksize, 1); for (i = 0; i < num_missing; i++) { int idx = missing[i]; if (idx < k) { if (memcmp(data[idx], missing_bufs[i], blocksize)) { dump_buffer(data[idx], blocksize, "decoded_buffer"); dump_buffer(missing_bufs[i], blocksize, "orig_buffer"); ret = 0; } } else if (memcmp(parity[idx - k], missing_bufs[i], blocksize)) { ret = 0; } } for (i = 0; i < k; i++) { free(data[i]); } free(data); for (i = 0; i < m; i++) { free(parity[i]); } free(parity); for (i = 0; i < num_missing; i++) { free(missing_bufs[i]); } free(missing_bufs); free(missing); free(matrix); return ret; } int test_reconstruct(int k, int m, int num_missing, int blocksize) { char **data = (char**)malloc(sizeof(char*)*k); char **parity = (char**)malloc(sizeof(char*)*m); char **missing_bufs = (char**)malloc(sizeof(char*)*num_missing); int *missing = (int*)malloc(sizeof(int)*(num_missing+1)); int *matrix = make_systematic_matrix(k, m); int destination_idx = 0; int n = k + m; int i; int ret = 1; srand((unsigned int)time(0)); for (i = 0; i < k; i++) { data[i] = gen_random_buffer(blocksize); } for (i = 0; i < m; i++) { parity[i] = (char*)malloc(blocksize); } for (i = 0;i < num_missing+1; i++) { missing[i] = -1; } // Encode liberasurecode_rs_vand_encode(matrix, data, parity, k, m, blocksize); // Copy data and parity for (i = 0; i < num_missing; i++) { int idx = rand() % n; while (is_missing(missing, idx)) { idx = rand() % n; } missing_bufs[i] = (char*)malloc(blocksize); memcpy(missing_bufs[i], idx < k ? data[idx] : parity[idx - k], blocksize); missing[i] = idx; if (i == 0) { destination_idx = missing[i]; } } // Zero missing bufs for (i = 0;i < num_missing; i++) { if (missing[i] < k) { memset(data[missing[i]], 0, blocksize); } else { memset(parity[missing[i] - k], 0, blocksize); } } // Reconstruct and check destination buffer liberasurecode_rs_vand_reconstruct(matrix, data, parity, k, m, missing, destination_idx, blocksize); // The original copy of the destination buffer is in the 0th buffer (see above) if (destination_idx < k) { if (memcmp(data[destination_idx], missing_bufs[0], blocksize)) { dump_buffer(data[destination_idx], blocksize, "decoded_buffer"); dump_buffer(missing_bufs[0], blocksize, "orig_buffer"); ret = 0; } } else if (memcmp(parity[destination_idx - k], missing_bufs[0], blocksize)) { ret = 0; } for (i = 0; i < k; i++) { free(data[i]); } free(data); for (i = 0; i < m; i++) { free(parity[i]); } free(parity); for (i = 0; i < num_missing; i++) { free(missing_bufs[i]); } free(missing_bufs); free(missing); free(matrix); return ret; } int matrix_dimensions[][2] = { {12, 6}, {12, 3}, {12, 2}, {12, 1}, {5, 3}, {5, 2}, {5, 1}, {1, 1}, {-1, -1} }; int main() { int i = 0; int blocksize = 4096; while (matrix_dimensions[i][0] >= 0) { int k = matrix_dimensions[i][0], m = matrix_dimensions[i][1]; init_liberasurecode_rs_vand(k, m); int make_systematic_res = test_make_systematic_matrix(k, m); if (!make_systematic_res) { fprintf(stderr, "Error running make systematic matrix for k=%d, m=%d\n", k, m); return 1; } int invert_res = test_invert_systematic_matrix(k, m, m); if (!invert_res) { fprintf(stderr, "Error running inversion test for k=%d, m=%d\n", k, m); return 1; } int enc_dec_res = test_encode_decode(k, m, m, blocksize); if (!enc_dec_res) { fprintf(stderr, "Error running encode/decode test for k=%d, m=%d, bs=%d\n", k, m, blocksize); return 1; } int reconstr_res = test_reconstruct(k, m, m, blocksize); if (!reconstr_res) { fprintf(stderr, "Error running reconstruction test for k=%d, m=%d, bs=%d\n", k, m, blocksize); return 1; } deinit_liberasurecode_rs_vand(); i++; } return 0; }