test_smsh_load.c (9922B)
1 /* Copyright (C) 2020-2023, 2025 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #include "smsh.h" 17 18 #include <rsys/double3.h> 19 #include <rsys/math.h> 20 #include <rsys/mem_allocator.h> 21 #include <rsys/rsys.h> 22 23 #include <stdio.h> 24 #include <string.h> 25 #include <unistd.h> 26 27 /******************************************************************************* 28 * Helper functions 29 ******************************************************************************/ 30 static void 31 check_smsh_desc 32 (const struct smsh_desc* desc, 33 const uint64_t nnodes, 34 const uint64_t ncells, 35 const uint64_t dnode, 36 const uint64_t dcell) 37 { 38 size_t i, j; 39 CHK(desc); 40 CHK(nnodes); 41 CHK(ncells); 42 CHK(dnode); 43 CHK(dcell); 44 45 CHK(desc->nnodes == nnodes); 46 CHK(desc->ncells == ncells); 47 CHK(desc->dnode == dnode); 48 CHK(desc->dcell == dcell); 49 50 FOR_EACH(i, 0, nnodes) { 51 const double* node0 = desc->nodes + i*dnode; 52 const double* node1 = smsh_desc_get_node(desc, i); 53 FOR_EACH(j, 0, dnode) { 54 CHK(node0[j] == node1[j]); 55 CHK(node0[j] == (double)i + (double)j*0.1); 56 } 57 } 58 59 FOR_EACH(i, 0, ncells) { 60 const uint64_t* cell0 = desc->cells + i*dcell; 61 const uint64_t* cell1 = smsh_desc_get_cell(desc, i); 62 FOR_EACH(j, 0, dcell) { 63 CHK(cell0[j] == cell1[j]); 64 CHK(cell0[j] == (i*dcell+j)%nnodes); 65 } 66 } 67 } 68 69 static void 70 test_load_mesh(struct smsh* smsh, const uint32_t dnode, const uint32_t dcell) 71 { 72 hash256_T hash0; 73 hash256_T hash1; 74 struct smsh_desc desc = SMSH_DESC_NULL; 75 struct smsh_load_args args = SMSH_LOAD_ARGS_NULL; 76 struct smsh_load_stream_args stream_args = SMSH_LOAD_STREAM_ARGS_NULL; 77 FILE* fp = NULL; 78 const char* filename = "test_file.smsh"; 79 const uint64_t pagesize = 16384; 80 const uint64_t nnodes = 287; 81 const uint64_t ncells = 192; 82 size_t i, j; 83 char byte = 0; 84 ASSERT(smsh); 85 86 fp = fopen(filename, "w+"); 87 CHK(fp); 88 89 /* Write file header */ 90 CHK(fwrite(&pagesize, sizeof(pagesize), 1, fp) == 1); 91 CHK(fwrite(&nnodes, sizeof(nnodes), 1, fp) == 1); 92 CHK(fwrite(&ncells, sizeof(ncells), 1, fp) == 1); 93 CHK(fwrite(&dnode, sizeof(dnode), 1, fp) == 1); 94 CHK(fwrite(&dcell, sizeof(dcell), 1, fp) == 1); 95 96 /* Padding */ 97 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); 98 99 /* Write vertex nodes */ 100 FOR_EACH(i, 0, nnodes) { 101 FOR_EACH(j, 0, dnode) { 102 const double dbl = (double)i + (double)j * 0.1; 103 CHK(fwrite(&dbl, sizeof(dbl), 1, fp) == 1); 104 } 105 } 106 107 /* Padding */ 108 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); 109 110 /* Write tetrahedra */ 111 FOR_EACH(i, 0, ncells) { 112 FOR_EACH(j, 0, dcell) { 113 const uint64_t ui64 = (i*dcell + j) % nnodes; 114 CHK(fwrite(&ui64, sizeof(ui64), 1, fp) == 1); 115 } 116 } 117 118 /* Padding. Write one char to position the EOF indicator */ 119 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0); 120 CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); 121 122 rewind(fp); 123 124 stream_args.stream = fp; 125 stream_args.name = filename; 126 CHK(smsh_load_stream(NULL, &stream_args) == RES_BAD_ARG); 127 CHK(smsh_load_stream(smsh, NULL) == RES_BAD_ARG); 128 stream_args.stream = NULL; 129 CHK(smsh_load_stream(smsh, &stream_args) == RES_BAD_ARG); 130 stream_args.stream = fp; 131 stream_args.name = NULL; 132 CHK(smsh_load_stream(smsh, &stream_args) == RES_BAD_ARG); 133 stream_args.name = filename; 134 CHK(smsh_load_stream(smsh, &stream_args) == RES_OK); 135 CHK(smsh_get_desc(NULL, &desc) == RES_BAD_ARG); 136 CHK(smsh_get_desc(smsh, NULL) == RES_BAD_ARG); 137 CHK(smsh_get_desc(smsh, &desc) == RES_OK); 138 check_smsh_desc(&desc, nnodes, ncells, dnode, dcell); 139 140 CHK(smsh_desc_compute_hash(NULL, hash0) == RES_BAD_ARG); 141 CHK(smsh_desc_compute_hash(&desc, NULL) == RES_BAD_ARG); 142 CHK(smsh_desc_compute_hash(&desc, hash0) == RES_OK); 143 144 rewind(fp); 145 stream_args.name = SMSH_LOAD_STREAM_ARGS_NULL.name; 146 stream_args.memory_mapping = 1; 147 CHK(smsh_load_stream(smsh, &stream_args) == RES_OK); 148 CHK(smsh_get_desc(smsh, &desc) == RES_OK); 149 check_smsh_desc(&desc, nnodes, ncells, dnode, dcell); 150 151 CHK(smsh_desc_compute_hash(&desc, hash1) == RES_OK); 152 CHK(hash256_eq(hash0, hash1)); 153 CHK(fclose(fp) == 0); 154 155 args.path = filename; 156 CHK(smsh_load(NULL, &args) == RES_BAD_ARG); 157 CHK(smsh_load(smsh, NULL) == RES_BAD_ARG); 158 args.path = NULL; 159 CHK(smsh_load(smsh, &args) == RES_BAD_ARG); 160 args.path = "nop"; 161 CHK(smsh_load(smsh, &args) == RES_IO_ERR); 162 args.path = filename; 163 CHK(smsh_load(smsh, &args) == RES_OK); 164 CHK(smsh_get_desc(smsh, &desc) == RES_OK); 165 check_smsh_desc(&desc, nnodes, ncells, dnode, dcell); 166 CHK(smsh_desc_compute_hash(&desc, hash1) == RES_OK); 167 CHK(hash256_eq(hash0, hash1)); 168 169 args.memory_mapping = 1; 170 CHK(smsh_load(smsh, &args) == RES_OK); 171 CHK(smsh_get_desc(smsh, &desc) == RES_OK); 172 check_smsh_desc(&desc, nnodes, ncells, dnode, dcell); 173 CHK(smsh_desc_compute_hash(&desc, hash1) == RES_OK); 174 CHK(hash256_eq(hash0, hash1)); 175 } 176 177 static void 178 test_load_fail(struct smsh* smsh) 179 { 180 struct smsh_load_stream_args args = SMSH_LOAD_STREAM_ARGS_NULL; 181 const char byte = 0; 182 FILE* fp = NULL; 183 uint64_t pagesize; 184 uint64_t nnodes; 185 uint64_t ncells; 186 unsigned dnode; 187 unsigned dcell; 188 189 /* Wrong pagesize */ 190 fp = tmpfile(); 191 CHK(fp); 192 pagesize = 1023; 193 nnodes = 10; 194 ncells = 10; 195 dnode = 3; 196 dcell = 4; 197 CHK(fwrite(&pagesize, sizeof(pagesize), 1, fp) == 1); 198 CHK(fwrite(&nnodes, sizeof(nnodes), 1, fp) == 1); 199 CHK(fwrite(&ncells, sizeof(ncells), 1, fp) == 1); 200 CHK(fwrite(&dnode, sizeof(dnode), 1, fp) == 1); 201 CHK(fwrite(&dcell, sizeof(dcell), 1, fp) == 1); 202 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); 203 CHK(fseek(fp, (long)(sizeof(double[3])*nnodes), SEEK_CUR) == 0); 204 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); 205 CHK(fseek(fp, (long)(sizeof(uint64_t[4])*ncells), SEEK_CUR) == 0); 206 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0); 207 CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); 208 rewind(fp); 209 args.stream = fp; 210 CHK(smsh_load_stream(smsh, &args) == RES_BAD_ARG); 211 CHK(fclose(fp) == 0); 212 213 /* Wrong size */ 214 fp = tmpfile(); 215 CHK(fp); 216 pagesize = (uint64_t)sysconf(_SC_PAGESIZE); 217 nnodes = 10; 218 ncells = 10; 219 dnode = 3; 220 dcell = 4; 221 CHK(fwrite(&pagesize, sizeof(pagesize), 1, fp) == 1); 222 CHK(fwrite(&nnodes, sizeof(nnodes), 1, fp) == 1); 223 CHK(fwrite(&ncells, sizeof(ncells), 1, fp) == 1); 224 CHK(fwrite(&dnode, sizeof(dnode), 1, fp) == 1); 225 CHK(fwrite(&dcell, sizeof(dcell), 1, fp) == 1); 226 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); 227 CHK(fseek(fp, (long)(sizeof(double[3])*nnodes), SEEK_CUR) == 0); 228 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); 229 CHK(fseek(fp, (long)(sizeof(uint64_t[4])*ncells), SEEK_CUR) == 0); 230 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-2, SEEK_SET) == 0); 231 CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); 232 rewind(fp); 233 args.stream = fp; 234 CHK(smsh_load_stream(smsh, &args) == RES_IO_ERR); 235 CHK(fclose(fp) == 0); 236 } 237 238 static void 239 test_load_files(struct smsh* smsh, int argc, char** argv) 240 { 241 hash256_T hash; 242 int i; 243 CHK(smsh); 244 FOR_EACH(i, 1, argc) { 245 struct smsh_desc desc = SMSH_DESC_NULL; 246 size_t j; 247 size_t inode; 248 size_t icell; 249 250 /* Load from file */ 251 if(strcmp(argv[i], "-") != 0) { 252 struct smsh_load_args args = SMSH_LOAD_ARGS_NULL; 253 printf("Load %s\n", argv[i]); 254 args.path = argv[i]; 255 args.memory_mapping = 1; 256 CHK(smsh_load(smsh, &args) == RES_OK); 257 258 /* Load from stdin */ 259 } else { 260 struct smsh_load_stream_args args = SMSH_LOAD_STREAM_ARGS_NULL; 261 printf("Load from stdin\n"); 262 args.stream = stdin; 263 args.name = "stdin"; 264 args.memory_mapping = 1; 265 CHK(smsh_load_stream(smsh, &args) == RES_BAD_ARG); 266 args.memory_mapping = 0; 267 CHK(smsh_load_stream(smsh, &args) == RES_OK); 268 } 269 CHK(smsh_get_desc(smsh, &desc) == RES_OK); 270 CHK(smsh_desc_compute_hash(&desc, hash) == RES_OK); 271 272 FOR_EACH(inode, 0, desc.nnodes) { 273 const double* node = smsh_desc_get_node(&desc, inode); 274 FOR_EACH(j, 0, desc.dnode) { 275 CHK(node[j] == node[j]); /* !NaN */ 276 CHK(!IS_INF(node[j])); 277 } 278 } 279 FOR_EACH(icell, 0, desc.ncells) { 280 const uint64_t* ids = smsh_desc_get_cell(&desc, icell); 281 FOR_EACH(j, 0, desc.dcell) { 282 size_t k; 283 FOR_EACH(k, 0, desc.dcell) { 284 if(k == j) continue; 285 CHK(ids[j] != ids[k]); /* Check non degenerated cell */ 286 } 287 } 288 } 289 } 290 } 291 292 /******************************************************************************* 293 * Main function 294 ******************************************************************************/ 295 int 296 main(int argc, char** argv) 297 { 298 struct smsh_create_args args = SMSH_CREATE_ARGS_DEFAULT; 299 struct smsh* smsh = NULL; 300 (void)argc, (void)argv; 301 302 args.verbose = 1; 303 CHK(smsh_create(&args, &smsh) == RES_OK); 304 305 if(argc > 1) { 306 test_load_files(smsh, argc, argv); 307 } else { 308 test_load_mesh(smsh, 3, 4); /* Tetrahedra */ 309 test_load_mesh(smsh, 3, 3); /* Triangles 3D */ 310 test_load_mesh(smsh, 2, 3); /* Triangles 2D */ 311 test_load_fail(smsh); 312 } 313 314 CHK(smsh_ref_put(smsh) == RES_OK); 315 CHK(mem_allocated_size() == 0); 316 return 0; 317 }