From 534e11cccb7fe32105e1abb51cd5101bb1f4e892 Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Fri, 16 Oct 2020 19:42:12 +0200 Subject: [PATCH] Added tests --- src/qmckl.org | 13 ++- src/qmckl_context.org | 210 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 192 insertions(+), 31 deletions(-) diff --git a/src/qmckl.org b/src/qmckl.org index dd271fb..0a400d5 100644 --- a/src/qmckl.org +++ b/src/qmckl.org @@ -2,8 +2,8 @@ # vim: syntax=c #+TITLE: QMCkl C header -This file is included in all other C header files, and produces the -=qmckl.h= header file. +This file produces the =qmckl.h= header file, which is included in all +other C header files. It is the main entry point to the library. #+BEGIN_SRC C :tangle qmckl.h #ifndef QMCKL_H @@ -27,13 +27,20 @@ typedef int qmckl_exit_code; ** Precision-related constants + Controlling numerical precision enables optimizations. Here, the + default parameters determining the target numerical precision and + range are defined. + #+BEGIN_SRC C :tangle qmckl.h #define QMCKL_DEFAULT_PRECISION 53 -#define QMCKL_DEFAULT_RANGE 2 +#define QMCKL_DEFAULT_RANGE 11 #+END_SRC * Header files + All the functions expoed in the API are defined in the following + header files. + #+BEGIN_SRC C :tangle qmckl.h #include "qmckl_context.h" #+END_SRC diff --git a/src/qmckl_context.org b/src/qmckl_context.org index d8c5ddf..5a80a1c 100644 --- a/src/qmckl_context.org +++ b/src/qmckl_context.org @@ -5,48 +5,77 @@ This file is written in C because it is more natural to express the context in C than in Fortran. -#+BEGIN_SRC C :tangle qmckl_context.h +3 files are produced: +- a header file : =qmckl_context.h= +- a source file : =qmckl_context.c= +- a test file : =test_qmckl_context.c= + +*** Header + #+BEGIN_SRC C :tangle qmckl_context.h #ifndef QMCKL_CONTEXT_H #define QMCKL_CONTEXT_H #include "qmckl.h" -#+END_SRC + #+END_SRC -#+BEGIN_SRC C :tangle qmckl_context.c +*** Source + #+BEGIN_SRC C :tangle qmckl_context.c #include /* malloc */ #include "qmckl_context.h" -#+END_SRC + #+END_SRC + +*** Test + #+BEGIN_SRC C :tangle test_qmckl_context.c +#include "qmckl_context.h" +#include "qmckl_test.h" +int main() { + qmckl_exit_code rc; /* return code */ + rc = QMCKL_SUCCESS; + #+END_SRC * Context The context variable is a handle for the state of the library, and is stored in the following data structure, which can't be seen - outside of the library. + outside of the library. To simplify compatibility with other + languages, the pointer to the internal data structure is converted + into a 64-bit signed integer, defined in the =qmckl_context= type. + A value of 0 for the context is equivalent to a NULL pointer. - #+BEGIN_SRC C :tangle qmckl_context.h +*** Header + #+BEGIN_SRC C :tangle qmckl_context.h /* 64-bit integer */ typedef long long int qmckl_context ; - #+END_SRC + #+END_SRC - - #+BEGIN_SRC C :tangle qmckl_context.c +*** Source + #+BEGIN_SRC C :tangle qmckl_context.c typedef struct qmckl_context_struct { struct qmckl_context_struct * prev; int precision; int range; } qmckl_context_struct; - #+END_SRC + #+END_SRC + +*** Test + We declare here the variables used in the tests. + #+BEGIN_SRC C :tangle test_qmckl_context.c + qmckl_context context; + qmckl_context new_context; + #+END_SRC ** =qmckl_context_create= - To create a new context, use =qmckl_context_create()=. If the creation - failed, the function returns =0=. On success, a pointer to a context - is returned as a 64-bit integer. + To create a new context, use =qmckl_context_create()=. + - On success, returns a pointer to a context using the =qmckl_context= type + - Returns 0 upon failure to allocate the internal data structure - #+BEGIN_SRC C :tangle qmckl_context.h +*** Header + #+BEGIN_SRC C :tangle qmckl_context.h qmckl_context qmckl_context_create(); - #+END_SRC + #+END_SRC - #+BEGIN_SRC C :tangle qmckl_context.c +*** Source + #+BEGIN_SRC C :tangle qmckl_context.c qmckl_context qmckl_context_create() { qmckl_context_struct* context; @@ -62,20 +91,46 @@ qmckl_context qmckl_context_create() { return (qmckl_context) context; } - #+END_SRC + #+END_SRC + +*** Test + #+BEGIN_SRC C :tangle test_qmckl_context.c + context = qmckl_context_create(); + if (context == (qmckl_context) 0) { + eprintf("qmckl_context_create\n"); + rc = QMCKL_FAILURE; + } + if ( ((qmckl_context_struct*) new_context)->precision != QMCKL_DEFAULT_PRECISION ) { + eprintf("qmckl_context_copy: No access to data\n"); + rc = QMCKL_FAILURE; + } + #+END_SRC ** =qmckl_context_copy= + + This function makes a shallow copy of the current context. + - Copying the 0-valued context returns 0 + - On success, returns a pointer to the new context using the =qmckl_context= type + - Returns 0 upon failure to allocate the internal data structure + for the new context + +*** Header #+BEGIN_SRC C :tangle qmckl_context.h qmckl_context qmckl_context_copy(const qmckl_context context); #+END_SRC +*** Source #+BEGIN_SRC C :tangle qmckl_context.c qmckl_context qmckl_context_copy(const qmckl_context context) { qmckl_context_struct* old_context; qmckl_context_struct* new_context; + if (context == (qmckl_context) 0) { + return (qmckl_context) 0; + } + new_context = (qmckl_context_struct*) malloc (sizeof(qmckl_context_struct)); if (new_context == NULL) { return (qmckl_context) 0; @@ -91,32 +146,124 @@ qmckl_context qmckl_context_copy(const qmckl_context context) { } #+END_SRC -** =qmckl_context_destroy= +*** Test + #+BEGIN_SRC C :tangle test_qmckl_context.c + new_context = qmckl_context_copy(context); + if (new_context == (qmckl_context) 0) { + eprintf("qmckl_context_copy: Allocation failure\n"); + rc = QMCKL_FAILURE; + } + if (new_context == context ) { + eprintf("qmckl_context_copy: Same pointer\n"); + rc = QMCKL_FAILURE; + } + if ( ((qmckl_context_struct*) new_context)->precision != QMCKL_DEFAULT_PRECISION ) { + eprintf("qmckl_context_copy: No access to data\n"); + rc = QMCKL_FAILURE; + } + #+END_SRC - To delete a new context, use =qmckl_context_destroy()=. If the deletion - failed, the function returns =0=. On success, the function returns =1= - implying that the context has been freed. +** =qmckl_context_previous= + + Returns the previous context + - On success, returns the ancestor of the current context + - Returns 0 for the initial context + - Returns 0 for the 0-valued context +*** Header #+BEGIN_SRC C :tangle qmckl_context.h -int qmckl_context_destroy(qmckl_context context); +qmckl_context qmckl_context_previous(const qmckl_context context); #+END_SRC +*** Source #+BEGIN_SRC C :tangle qmckl_context.c -int qmckl_context_destroy(qmckl_context context) { +qmckl_context qmckl_context_previous(const qmckl_context context) { qmckl_context_struct* ctx; + if (context == (qmckl_context) 0) { + return (qmckl_context) 0; + } + ctx = (qmckl_context_struct*) context; + return (qmckl_context) ctx->prev; +} + #+END_SRC + +*** Test + #+BEGIN_SRC C :tangle test_qmckl_context.c + if (qmckl_context_previous(new_context) == (qmckl_context) 0) { + eprintf("qmckl_context_copy: Null pointer\n"); + rc = QMCKL_FAILURE; + } + if (qmckl_context_previous(new_context) != context) { + eprintf("qmckl_context_copy: Wrong pointer\n"); + rc = QMCKL_FAILURE; + } + if (qmckl_context_previous(context) != (qmckl_context) 0) { + eprintf("qmckl_context_copy: Expected null pointer (1)\n"); + rc = QMCKL_FAILURE; + } + if (qmckl_context_previous((qmckl_context) 0) != (qmckl_context) 0) { + eprintf("qmckl_context_copy: Expected null pointer (2)\n"); + rc = QMCKL_FAILURE; + } + #+END_SRC + +** =qmckl_context_destroy= + + Destroys the current context, leaving the ancestors untouched. + - Succeeds if the current context is properly destroyed + - Fails otherwise + - Fails is the 0-valued context is given in argument + + The context given in parameter is overwritten by the 0-valued + context, so a pointer is passed to the function. + +*** Header + #+BEGIN_SRC C :tangle qmckl_context.h +qmckl_exit_code qmckl_context_destroy(qmckl_context * context); + #+END_SRC + +*** Source + #+BEGIN_SRC C :tangle qmckl_context.c +qmckl_exit_code qmckl_context_destroy(qmckl_context *context) { + + qmckl_context_struct* ctx; + + ctx = (qmckl_context_struct*) *context; if (ctx == NULL) { - return 0; + return QMCKL_FAILURE; } free(ctx); - return 1; + *context = (qmckl_context) 0; + return QMCKL_SUCCESS; } #+END_SRC +*** Test + #+BEGIN_SRC C :tangle test_qmckl_context.c + if (new_context == (qmckl_context) 0) { + eprintf("qmckl_context_destroy: new_context is NULL\n"); + rc = QMCKL_FAILURE; + } + if (qmckl_context_destroy(&new_context) == QMCKL_FAILURE) { + eprintf("qmckl_context_destroy: Unable to destroy the new_context\n"); + rc = QMCKL_FAILURE; + } + if (new_context != (qmckl_context) 0) { + eprintf("qmckl_context_destroy: new_context should be NULL\n"); + rc = QMCKL_FAILURE; + } + if (qmckl_context_destroy((qmckl_context) 0) == QMCKL_SUCCESS) { + eprintf("qmckl_context_destroy: Failure expected with NULL pointer\n"); + rc = QMCKL_FAILURE; + } + #+END_SRC + + * Precision The following functions set and get the expected required precision @@ -239,9 +386,16 @@ int qmckl_context_get_range(const qmckl_context context) { -* End of header +* End of files -#+BEGIN_SRC C :tangle qmckl_context.h +*** Header + #+BEGIN_SRC C :tangle qmckl_context.h #endif -#+END_SRC + #+END_SRC + +*** Test + #+BEGIN_SRC C :tangle test_qmckl_context.c + return QMCKL_SUCCESS; +} + #+END_SRC