star-mesh

Define and load a binary data format for meshes
git clone git://git.meso-star.fr/star-mesh.git
Log | Files | Refs | README | LICENSE

commit 82fb7a980b0a90b7ee3b9a106324f4336910e16d
parent 7137530d59a5ba18c6f1d75d437ce4c5fc4f06eb
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 14 Mar 2022 16:20:00 +0100

Test the load API

Diffstat:
Mcmake/CMakeLists.txt | 2+-
Asrc/test_smsh_load.c | 256+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 257 insertions(+), 1 deletion(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -82,7 +82,7 @@ if(NOT NO_TEST) endfunction() new_test(test_smsh) - #new_test(test_smsh_load) + new_test(test_smsh_load) endif() ################################################################################ diff --git a/src/test_smsh_load.c b/src/test_smsh_load.c @@ -0,0 +1,256 @@ +/* Copyright (C) 2020, 2021 |Meso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "smsh.h" + +#include <rsys/double3.h> +#include <rsys/math.h> +#include <rsys/mem_allocator.h> +#include <rsys/rsys.h> +#include <stdio.h> +#include <unistd.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +check_smsh_desc + (const struct smsh_desc* desc, + const uint64_t nnodes, + const uint64_t ncells, + const uint64_t dnode, + const uint64_t dcell) +{ + size_t i, j; + CHK(desc); + CHK(nnodes); + CHK(ncells); + CHK(dnode); + CHK(dcell); + + CHK(desc->nnodes == nnodes); + CHK(desc->ncells == ncells); + CHK(desc->dnode == dnode); + CHK(desc->dcell == dcell); + + FOR_EACH(i, 0, nnodes) { + const double* node0 = desc->nodes + i*dnode; + const double* node1 = smsh_desc_get_node(desc, i); + FOR_EACH(j, 0, dnode) { + CHK(node0[j] == node1[j]); + CHK(node0[j] == (double)i + (double)j*0.1); + } + } + + FOR_EACH(i, 0, ncells) { + const uint64_t* cell0 = desc->cells + i*dcell; + const uint64_t* cell1 = smsh_desc_get_cell(desc, i); + FOR_EACH(j, 0, dcell) { + CHK(cell0[j] == cell1[j]); + CHK(cell0[j] == (i*dcell+j)%nnodes); + } + } +} + +static void +test_load_tetrahedra(struct smsh* smsh) +{ + struct smsh_desc desc = SMSH_DESC_NULL; + FILE* fp = NULL; + const char* filename = "test_file.smsh"; + const uint64_t pagesize = 16384; + const uint64_t nnodes = 287; + const uint64_t ncells = 192; + const unsigned dnode = 3; + const unsigned dcell = 3; + size_t i; + char byte = 0; + ASSERT(smsh); + + fp = fopen(filename, "w+"); + CHK(fp); + + /* Write file header */ + CHK(fwrite(&pagesize, sizeof(pagesize), 1, fp) == 1); + CHK(fwrite(&nnodes, sizeof(nnodes), 1, fp) == 1); + CHK(fwrite(&ncells, sizeof(ncells), 1, fp) == 1); + CHK(fwrite(&dnode, sizeof(dnode), 1, fp) == 1); + CHK(fwrite(&dcell, sizeof(dcell), 1, fp) == 1); + + /* Padding */ + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); + + /* Write vertex nodes */ + FOR_EACH(i, 0, nnodes) { + double pos[3]; + pos[0] = (double)i + 0.0; + pos[1] = (double)i + 0.1; + pos[2] = (double)i + 0.2; + CHK(fwrite(pos, sizeof(*pos), 3, fp) == 3); + } + + /* Padding */ + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); + + /* Write tetrahedra */ + FOR_EACH(i, 0, ncells) { + uint64_t ids[4]; + ids[0] = (i*4 + 0) % nnodes; + ids[1] = (i*4 + 1) % nnodes; + ids[2] = (i*4 + 2) % nnodes; + ids[3] = (i*4 + 3) % nnodes; + CHK(fwrite(ids, sizeof(*ids), 4, fp) == 4); + } + + /* Padding. Write one char to position the EOF indicator */ + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0); + CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); + + rewind(fp); + CHK(smsh_load_stream(NULL, fp, filename) == RES_BAD_ARG); + CHK(smsh_load_stream(smsh, NULL, filename) == RES_BAD_ARG); + CHK(smsh_load_stream(smsh, fp, NULL) == RES_OK); + CHK(smsh_get_desc(NULL, &desc) == RES_BAD_ARG); + CHK(smsh_get_desc(smsh, NULL) == RES_BAD_ARG); + CHK(smsh_get_desc(smsh, &desc) == RES_OK); + check_smsh_desc(&desc, nnodes, ncells, dnode, dcell); + + rewind(fp); + CHK(smsh_load_stream(smsh, fp, filename) == RES_OK); + check_smsh_desc(&desc, nnodes, ncells, dnode, dcell); + + CHK(smsh_load(NULL, filename) == RES_BAD_ARG); + CHK(smsh_load(smsh, NULL) == RES_BAD_ARG); + CHK(smsh_load(smsh, "nop") == RES_IO_ERR); + CHK(smsh_load(smsh, filename) == RES_OK); + check_smsh_desc(&desc, nnodes, ncells, dnode, dcell); + + fclose(fp); +} + +static void +test_load_fail(struct smsh* smsh) +{ + const char byte = 0; + FILE* fp = NULL; + uint64_t pagesize; + uint64_t nnodes; + uint64_t ncells; + unsigned dnode; + unsigned dcell; + + /* Wrong pagesize */ + fp = tmpfile(); + CHK(fp); + pagesize = 1023; + nnodes = 10; + ncells = 10; + dnode = 3; + dcell = 4; + CHK(fwrite(&pagesize, sizeof(pagesize), 1, fp) == 1); + CHK(fwrite(&nnodes, sizeof(nnodes), 1, fp) == 1); + CHK(fwrite(&ncells, sizeof(ncells), 1, fp) == 1); + CHK(fwrite(&dnode, sizeof(dnode), 1, fp) == 1); + CHK(fwrite(&dcell, sizeof(dcell), 1, fp) == 1); + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); + CHK(fseek(fp, (long)(sizeof(double[3])*nnodes), SEEK_CUR) == 0); + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); + CHK(fseek(fp, (long)(sizeof(uint64_t[4])*ncells), SEEK_CUR) == 0); + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0); + CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); + rewind(fp); + CHK(smsh_load_stream(smsh, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + /* Wrong size */ + fp = tmpfile(); + CHK(fp); + pagesize = (uint64_t)sysconf(_SC_PAGESIZE); + nnodes = 10; + ncells = 10; + dnode = 3; + dcell = 4; + CHK(fwrite(&pagesize, sizeof(pagesize), 1, fp) == 1); + CHK(fwrite(&nnodes, sizeof(nnodes), 1, fp) == 1); + CHK(fwrite(&ncells, sizeof(ncells), 1, fp) == 1); + CHK(fwrite(&dnode, sizeof(dnode), 1, fp) == 1); + CHK(fwrite(&dcell, sizeof(dcell), 1, fp) == 1); + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); + CHK(fseek(fp, (long)(sizeof(double[3])*nnodes), SEEK_CUR) == 0); + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET) == 0); + CHK(fseek(fp, (long)(sizeof(uint64_t[4])*ncells), SEEK_CUR) == 0); + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-2, SEEK_SET) == 0); + CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); + rewind(fp); + CHK(smsh_load_stream(smsh, fp, NULL) == RES_IO_ERR); + fclose(fp); +} + +static void +test_load_files(struct smsh* smsh, int argc, char** argv) +{ + int i; + CHK(smsh); + FOR_EACH(i, 1, argc) { + struct smsh_desc desc = SMSH_DESC_NULL; + size_t inode; + size_t icell; + + printf("Load %s\n", argv[i]); + CHK(smsh_load(smsh, argv[i]) == RES_OK); + CHK(smsh_get_desc(smsh, &desc) == RES_OK); + + FOR_EACH(inode, 0, desc.nnodes) { + const double* pos = smsh_desc_get_node(&desc, inode); + CHK(pos[0] == pos[0]); /* !NaN */ + CHK(pos[1] == pos[1]); /* !NaN */ + CHK(pos[2] == pos[2]); /* !NaN */ + CHK(!IS_INF(pos[0])); + CHK(!IS_INF(pos[1])); + CHK(!IS_INF(pos[2])); + } + FOR_EACH(icell, 0, desc.ncells) { + const uint64_t* ids = smsh_desc_get_cell(&desc, icell); + /* Check non degenerated tetrahedron */ + CHK(ids[0] != ids[1]); + CHK(ids[0] != ids[2]); + CHK(ids[0] != ids[3]); + CHK(ids[1] != ids[2]); + CHK(ids[1] != ids[3]); + CHK(ids[2] != ids[3]); + } + } +} + +/******************************************************************************* + * Main function + ******************************************************************************/ +int +main(int argc, char** argv) +{ + struct smsh_create_args args = SMSH_CREATE_ARGS_DEFAULT; + struct smsh* smsh = NULL; + (void)argc, (void)argv; + + CHK(smsh_create(&args, &smsh) == RES_OK); + + test_load_tetrahedra(smsh); + test_load_fail(smsh); + test_load_files(smsh, argc, argv); + + CHK(smsh_ref_put(smsh) == RES_OK); + CHK(mem_allocated_size() == 0); + return 0; +}