first version of libdice
This commit is contained in:
		
						commit
						baeea3eee6
					
				
							
								
								
									
										3
									
								
								AUTHORS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								AUTHORS
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| Here is a list of authors that have worked on this software: | ||||
| 
 | ||||
| 2018-  Florian Stinglmayr <florian@n0la.org> | ||||
							
								
								
									
										165
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,165 @@ | ||||
|                    GNU LESSER GENERAL PUBLIC LICENSE | ||||
|                        Version 3, 29 June 2007 | ||||
| 
 | ||||
|  Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
| 
 | ||||
| 
 | ||||
|   This version of the GNU Lesser General Public License incorporates | ||||
| the terms and conditions of version 3 of the GNU General Public | ||||
| License, supplemented by the additional permissions listed below. | ||||
| 
 | ||||
|   0. Additional Definitions. | ||||
| 
 | ||||
|   As used herein, "this License" refers to version 3 of the GNU Lesser | ||||
| General Public License, and the "GNU GPL" refers to version 3 of the GNU | ||||
| General Public License. | ||||
| 
 | ||||
|   "The Library" refers to a covered work governed by this License, | ||||
| other than an Application or a Combined Work as defined below. | ||||
| 
 | ||||
|   An "Application" is any work that makes use of an interface provided | ||||
| by the Library, but which is not otherwise based on the Library. | ||||
| Defining a subclass of a class defined by the Library is deemed a mode | ||||
| of using an interface provided by the Library. | ||||
| 
 | ||||
|   A "Combined Work" is a work produced by combining or linking an | ||||
| Application with the Library.  The particular version of the Library | ||||
| with which the Combined Work was made is also called the "Linked | ||||
| Version". | ||||
| 
 | ||||
|   The "Minimal Corresponding Source" for a Combined Work means the | ||||
| Corresponding Source for the Combined Work, excluding any source code | ||||
| for portions of the Combined Work that, considered in isolation, are | ||||
| based on the Application, and not on the Linked Version. | ||||
| 
 | ||||
|   The "Corresponding Application Code" for a Combined Work means the | ||||
| object code and/or source code for the Application, including any data | ||||
| and utility programs needed for reproducing the Combined Work from the | ||||
| Application, but excluding the System Libraries of the Combined Work. | ||||
| 
 | ||||
|   1. Exception to Section 3 of the GNU GPL. | ||||
| 
 | ||||
|   You may convey a covered work under sections 3 and 4 of this License | ||||
| without being bound by section 3 of the GNU GPL. | ||||
| 
 | ||||
|   2. Conveying Modified Versions. | ||||
| 
 | ||||
|   If you modify a copy of the Library, and, in your modifications, a | ||||
| facility refers to a function or data to be supplied by an Application | ||||
| that uses the facility (other than as an argument passed when the | ||||
| facility is invoked), then you may convey a copy of the modified | ||||
| version: | ||||
| 
 | ||||
|    a) under this License, provided that you make a good faith effort to | ||||
|    ensure that, in the event an Application does not supply the | ||||
|    function or data, the facility still operates, and performs | ||||
|    whatever part of its purpose remains meaningful, or | ||||
| 
 | ||||
|    b) under the GNU GPL, with none of the additional permissions of | ||||
|    this License applicable to that copy. | ||||
| 
 | ||||
|   3. Object Code Incorporating Material from Library Header Files. | ||||
| 
 | ||||
|   The object code form of an Application may incorporate material from | ||||
| a header file that is part of the Library.  You may convey such object | ||||
| code under terms of your choice, provided that, if the incorporated | ||||
| material is not limited to numerical parameters, data structure | ||||
| layouts and accessors, or small macros, inline functions and templates | ||||
| (ten or fewer lines in length), you do both of the following: | ||||
| 
 | ||||
|    a) Give prominent notice with each copy of the object code that the | ||||
|    Library is used in it and that the Library and its use are | ||||
|    covered by this License. | ||||
| 
 | ||||
|    b) Accompany the object code with a copy of the GNU GPL and this license | ||||
|    document. | ||||
| 
 | ||||
|   4. Combined Works. | ||||
| 
 | ||||
|   You may convey a Combined Work under terms of your choice that, | ||||
| taken together, effectively do not restrict modification of the | ||||
| portions of the Library contained in the Combined Work and reverse | ||||
| engineering for debugging such modifications, if you also do each of | ||||
| the following: | ||||
| 
 | ||||
|    a) Give prominent notice with each copy of the Combined Work that | ||||
|    the Library is used in it and that the Library and its use are | ||||
|    covered by this License. | ||||
| 
 | ||||
|    b) Accompany the Combined Work with a copy of the GNU GPL and this license | ||||
|    document. | ||||
| 
 | ||||
|    c) For a Combined Work that displays copyright notices during | ||||
|    execution, include the copyright notice for the Library among | ||||
|    these notices, as well as a reference directing the user to the | ||||
|    copies of the GNU GPL and this license document. | ||||
| 
 | ||||
|    d) Do one of the following: | ||||
| 
 | ||||
|        0) Convey the Minimal Corresponding Source under the terms of this | ||||
|        License, and the Corresponding Application Code in a form | ||||
|        suitable for, and under terms that permit, the user to | ||||
|        recombine or relink the Application with a modified version of | ||||
|        the Linked Version to produce a modified Combined Work, in the | ||||
|        manner specified by section 6 of the GNU GPL for conveying | ||||
|        Corresponding Source. | ||||
| 
 | ||||
|        1) Use a suitable shared library mechanism for linking with the | ||||
|        Library.  A suitable mechanism is one that (a) uses at run time | ||||
|        a copy of the Library already present on the user's computer | ||||
|        system, and (b) will operate properly with a modified version | ||||
|        of the Library that is interface-compatible with the Linked | ||||
|        Version. | ||||
| 
 | ||||
|    e) Provide Installation Information, but only if you would otherwise | ||||
|    be required to provide such information under section 6 of the | ||||
|    GNU GPL, and only to the extent that such information is | ||||
|    necessary to install and execute a modified version of the | ||||
|    Combined Work produced by recombining or relinking the | ||||
|    Application with a modified version of the Linked Version. (If | ||||
|    you use option 4d0, the Installation Information must accompany | ||||
|    the Minimal Corresponding Source and Corresponding Application | ||||
|    Code. If you use option 4d1, you must provide the Installation | ||||
|    Information in the manner specified by section 6 of the GNU GPL | ||||
|    for conveying Corresponding Source.) | ||||
| 
 | ||||
|   5. Combined Libraries. | ||||
| 
 | ||||
|   You may place library facilities that are a work based on the | ||||
| Library side by side in a single library together with other library | ||||
| facilities that are not Applications and are not covered by this | ||||
| License, and convey such a combined library under terms of your | ||||
| choice, if you do both of the following: | ||||
| 
 | ||||
|    a) Accompany the combined library with a copy of the same work based | ||||
|    on the Library, uncombined with any other library facilities, | ||||
|    conveyed under the terms of this License. | ||||
| 
 | ||||
|    b) Give prominent notice with the combined library that part of it | ||||
|    is a work based on the Library, and explaining where to find the | ||||
|    accompanying uncombined form of the same work. | ||||
| 
 | ||||
|   6. Revised Versions of the GNU Lesser General Public License. | ||||
| 
 | ||||
|   The Free Software Foundation may publish revised and/or new versions | ||||
| of the GNU Lesser General Public License from time to time. Such new | ||||
| versions will be similar in spirit to the present version, but may | ||||
| differ in detail to address new problems or concerns. | ||||
| 
 | ||||
|   Each version is given a distinguishing version number. If the | ||||
| Library as you received it specifies that a certain numbered version | ||||
| of the GNU Lesser General Public License "or any later version" | ||||
| applies to it, you have the option of following the terms and | ||||
| conditions either of that published version or of any later version | ||||
| published by the Free Software Foundation. If the Library as you | ||||
| received it does not specify a version number of the GNU Lesser | ||||
| General Public License, you may choose any version of the GNU Lesser | ||||
| General Public License ever published by the Free Software Foundation. | ||||
| 
 | ||||
|   If the Library as you received it specifies that a proxy can decide | ||||
| whether future versions of the GNU Lesser General Public License shall | ||||
| apply, that proxy's public statement of acceptance of any version is | ||||
| permanent authorization for you to choose that version for the | ||||
| Library. | ||||
							
								
								
									
										14
									
								
								Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| AM_YFLAGS =		-d | ||||
| BUILT_SOURCES =		lib/dice_parse.h | ||||
| 
 | ||||
| lib_LTLIBRARIES =	libdice.la | ||||
| libdice_la_SOURCES =	lib/dice.h \
 | ||||
| 			lib/dice.c \
 | ||||
| 			lib/dice_parse.y \
 | ||||
| 			lib/dice_lexer.l | ||||
| 
 | ||||
| AM_CFLAGS =		-Ilib | ||||
| 
 | ||||
| libdice_la_LIBADD =	${BSD_LIBS} | ||||
| 
 | ||||
| SUBDIRS	=		. tests | ||||
							
								
								
									
										44
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								README
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| libdice is a small library used for parsing dice expression and rolling dice. | ||||
| It is mainly suitable for small projects that wish to support pen and paper | ||||
| style dice syntax. | ||||
| 
 | ||||
| Features: | ||||
| 
 | ||||
|   o Written in clean C | ||||
|   o Easy API as well as advanced API | ||||
|   o Solid and reliable RNG | ||||
|   o Unit tests | ||||
| 
 | ||||
| Dice syntax support: | ||||
| 
 | ||||
|   o Variable sides | ||||
|   o Variable amount | ||||
| 
 | ||||
| Requirements: | ||||
| 
 | ||||
|   o arc4random_uniform (or libbsd on non-BSDs) | ||||
|   o cmocka (for unit tests) | ||||
|   o bison | ||||
|   o flex | ||||
| 
 | ||||
| Compilation | ||||
| 
 | ||||
|   $ ./configure --prefix=/usr | ||||
|   $ make | ||||
|   $ doas make install | ||||
| 
 | ||||
| Usage: | ||||
| 
 | ||||
|   The functions ``dice_simple`` and ``dice_parse`` create a new ``dice_t`` | ||||
|   object which can be used in conjunction with ``dice_roll`` and | ||||
|   ``dice_evaluate`` to generate random numbers. ``dice_free`` must be used | ||||
|   to cleanup a created ``dice_t`` object. | ||||
| 
 | ||||
| 
 | ||||
|   dice_t d20 = dice_simple(1, 20); | ||||
|   int64_t res = dice_roll(d20); | ||||
|   dice_free(d20); | ||||
| 
 | ||||
| Authors: | ||||
| 
 | ||||
|   Florian Stinglmayr <florian@n0la.org> | ||||
							
								
								
									
										21
									
								
								configure.ac
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								configure.ac
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| AC_PREREQ([2.69]) | ||||
| AC_INIT([libdice], [0.1], [florian@n0la.org]) | ||||
| AM_INIT_AUTOMAKE([subdir-objects]) | ||||
| LT_INIT() | ||||
| AC_CONFIG_HEADERS([config.h]) | ||||
| 
 | ||||
| AC_PROG_CC | ||||
| 
 | ||||
| AC_PROG_LEX | ||||
| AC_PROG_YACC | ||||
| 
 | ||||
| PKG_CHECK_MODULES([CMOCKA], [cmocka]) | ||||
| 
 | ||||
| AC_CHECK_HEADER_STDBOOL() | ||||
| 
 | ||||
| AC_CHECK_FUNCS([arc4random arc4random_uniform strlcat strlcpy],, | ||||
|    [PKG_CHECK_MODULES([BSD], [libbsd])]) | ||||
| 
 | ||||
| AC_CONFIG_FILES([Makefile tests/Makefile]) | ||||
| 
 | ||||
| AC_OUTPUT | ||||
							
								
								
									
										178
									
								
								lib/dice.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								lib/dice.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,178 @@ | ||||
| #include "dice.h" | ||||
| #include "dice_parse.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #ifndef HAVE_ARC4RANDOM_UNIFORM | ||||
| #include <bsd/stdlib.h> | ||||
| #endif | ||||
| 
 | ||||
| extern void *yy_scan_string(char const *s); | ||||
| extern void yy_delete_buffer(void *b); | ||||
| 
 | ||||
| struct dice_ | ||||
| { | ||||
|     uint32_t amount; | ||||
|     uint32_t sides; | ||||
| 
 | ||||
|     char *errmsg; | ||||
| }; | ||||
| 
 | ||||
| static dice_t dice_new(void) | ||||
| { | ||||
|     dice_t tmp = calloc(1, sizeof(struct dice_)); | ||||
| 
 | ||||
|     if (tmp == NULL) { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     return tmp; | ||||
| } | ||||
| 
 | ||||
| void dice_free(dice_t t) | ||||
| { | ||||
|     if (t == NULL) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     free(t); | ||||
| } | ||||
| 
 | ||||
| void dice_result_free(dice_result_t *r) | ||||
| { | ||||
|     if (r == NULL) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     free(r); | ||||
| } | ||||
| 
 | ||||
| void dice_result_freev(dice_result_t *r, size_t len) | ||||
| { | ||||
|     if (r == NULL || len == 0) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     free(r); | ||||
| } | ||||
| 
 | ||||
| dice_t dice_simple(uint32_t amount, uint32_t sides) | ||||
| { | ||||
|     dice_t tmp = dice_new(); | ||||
| 
 | ||||
|     if (amount == 0 || sides == 0) { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     if (tmp == NULL) { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     tmp->amount = amount; | ||||
|     tmp->sides = sides; | ||||
| 
 | ||||
|     return tmp; | ||||
| } | ||||
| 
 | ||||
| dice_t dice_parse(char const *s) | ||||
| { | ||||
|     dice_t d = NULL; | ||||
|     void *buffer = NULL; | ||||
|     int ret = 0; | ||||
| 
 | ||||
|     d = dice_new(); | ||||
|     if (d == NULL) { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     buffer = yy_scan_string(s); | ||||
|     ret = yyparse(d); | ||||
|     yy_delete_buffer(buffer); | ||||
| 
 | ||||
|     if (ret) { | ||||
|         dice_free(d); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     return d; | ||||
| } | ||||
| 
 | ||||
| bool dice_set(dice_t d, dice_option_t opt, ...) | ||||
| { | ||||
|     va_list lst; | ||||
| 
 | ||||
|     va_start(lst, opt); | ||||
|     switch (opt) { | ||||
|     case DICEOPTION_AMOUNT: d->amount = va_arg(lst, uint32_t); break; | ||||
|     case DICEOPTION_SIDES: d->sides = va_arg(lst, uint32_t); break; | ||||
| 
 | ||||
|     default: return false; | ||||
|     } | ||||
|     va_end(lst); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool dice_get(dice_t d, dice_option_t opt, ...) | ||||
| { | ||||
|     va_list lst; | ||||
| 
 | ||||
|     va_start(lst, opt); | ||||
|     switch (opt) { | ||||
|     case DICEOPTION_AMOUNT: | ||||
|     { | ||||
|         uint32_t *ptr = va_arg(lst, uint32_t*); | ||||
|         *ptr = d->amount; | ||||
|     } break; | ||||
| 
 | ||||
|     case DICEOPTION_SIDES: | ||||
|     { | ||||
|         uint32_t *ptr = va_arg(lst, uint32_t*); | ||||
|         *ptr = d->sides; | ||||
|     } break; | ||||
| 
 | ||||
|     default: return false; | ||||
|     } | ||||
|     va_end(lst); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| int64_t dice_roll(dice_t d) | ||||
| { | ||||
|     int64_t result = 0; | ||||
|     uint32_t i = 0; | ||||
| 
 | ||||
|     for (i = 0; i < d->amount; i++) { | ||||
|         result += arc4random_uniform(d->sides) + 1; | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| bool dice_evaluate(dice_t d, dice_result_t **res, size_t *reslen) | ||||
| { | ||||
|     size_t len = 0; | ||||
|     dice_result_t *r = NULL; | ||||
|     uint32_t i = 0; | ||||
| 
 | ||||
|     if (d == NULL || d->amount <= 0 || d->sides <= 0) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     len = d->amount; | ||||
|     r = calloc(len, sizeof(dice_result_t)); | ||||
|     if (r == NULL) { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < d->amount; i++) { | ||||
|         r[i].result = arc4random_uniform(d->sides) + 1; | ||||
|     } | ||||
| 
 | ||||
|     *reslen = len; | ||||
|     *res = r; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
							
								
								
									
										34
									
								
								lib/dice.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								lib/dice.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| #ifndef LIBDICE_DICE_H | ||||
| #define LIBDICE_DICE_H | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stdint.h> | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| struct dice_; | ||||
| typedef struct dice_ * dice_t; | ||||
| 
 | ||||
| typedef struct { | ||||
|     int64_t result; | ||||
| } dice_result_t; | ||||
| 
 | ||||
| typedef enum { | ||||
|     DICEOPTION_AMOUNT = 0, | ||||
|     DICEOPTION_SIDES, | ||||
| } dice_option_t; | ||||
| 
 | ||||
| void dice_result_free(dice_result_t *r); | ||||
| void dice_result_freev(dice_result_t *r, size_t len); | ||||
| 
 | ||||
| void dice_free(dice_t t); | ||||
| dice_t dice_simple(uint32_t amount, uint32_t sides); | ||||
| dice_t dice_parse(char const *s); | ||||
| 
 | ||||
| bool dice_set(dice_t d, dice_option_t opt, ...); | ||||
| bool dice_get(dice_t d, dice_option_t opt, ...); | ||||
| 
 | ||||
| int64_t dice_roll(dice_t d); | ||||
| bool dice_evaluate(dice_t d, dice_result_t **res, size_t *reslen); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										9
									
								
								lib/dice_lexer.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								lib/dice_lexer.l
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| %{ | ||||
| #include "dice.h" | ||||
| #include "dice_parse.h" | ||||
| %} | ||||
| 
 | ||||
| %% | ||||
| [0-9]+ { yylval.integer = atoi(yytext); return TOK_INTEGER; } | ||||
| [d] return TOK_DICESEP; | ||||
| %% | ||||
							
								
								
									
										39
									
								
								lib/dice_parse.y
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lib/dice_parse.y
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| %parse-param {dice_t dice} | ||||
| 
 | ||||
| %{ | ||||
| #include "dice.h" | ||||
| 
 | ||||
| extern int yylex(void); | ||||
| 
 | ||||
| void yyerror(dice_t dice, char const *err) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| int yywrap(void) | ||||
| { | ||||
|     return 1; | ||||
| } | ||||
| %} | ||||
| 
 | ||||
| %union { | ||||
|     char *str; | ||||
|     int integer; | ||||
|     double number; | ||||
| } | ||||
| 
 | ||||
| %token TOK_DICESEP | ||||
| %token  <integer>           TOK_INTEGER | ||||
| 
 | ||||
| %% | ||||
| 
 | ||||
| dice:           TOK_INTEGER TOK_DICESEP TOK_INTEGER | ||||
|                 { | ||||
|                     dice_set(dice, DICEOPTION_AMOUNT, $1); | ||||
|                     dice_set(dice, DICEOPTION_SIDES, $3); | ||||
|                 } | ||||
|         |       TOK_DICESEP TOK_INTEGER | ||||
|                 { | ||||
|                     dice_set(dice, DICEOPTION_AMOUNT, 1); | ||||
|                     dice_set(dice, DICEOPTION_SIDES, $2); | ||||
|                 } | ||||
|         ; | ||||
							
								
								
									
										8
									
								
								tests/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tests/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| bin_PROGRAMS =	test_dice_simple_roll \
 | ||||
| 		test_dice_parse \
 | ||||
| 		test_dice_evaluate | ||||
| 
 | ||||
| AM_CFLAGS =	-I../lib ${CMOCKA_CFLAGS} | ||||
| AM_LDFLAGS =	${CMOCKA_LIBS} ../libdice.la | ||||
| 
 | ||||
| TESTS =		$(bin_PROGRAMS) | ||||
							
								
								
									
										72
									
								
								tests/test_dice_evaluate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								tests/test_dice_evaluate.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| #include <dice.h> | ||||
| 
 | ||||
| #include <setjmp.h> | ||||
| #include <cmocka.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| static void test_dice_evaluate_null(void **data) | ||||
| { | ||||
|     dice_t d = NULL; | ||||
|     dice_result_t *r = NULL; | ||||
|     size_t rlen = 0; | ||||
| 
 | ||||
|     assert_false(dice_evaluate(d, &r, &rlen)); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_evaluate_one(void **data) | ||||
| { | ||||
|     dice_t d = NULL; | ||||
|     dice_result_t *r = NULL; | ||||
|     size_t rlen = 0; | ||||
| 
 | ||||
|     d = dice_simple(1, 10); | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
|     assert_true(dice_evaluate(d, &r, &rlen)); | ||||
|     assert_non_null(r); | ||||
| 
 | ||||
|     assert_int_equal(rlen, 1); | ||||
|     assert_true(r[0].result >= 1 && r[0].result <= 10); | ||||
| 
 | ||||
|     dice_free(d); | ||||
|     dice_result_freev(r, rlen); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_evaluate_many(void **data) | ||||
| { | ||||
|     dice_t d = NULL; | ||||
|     dice_result_t *r = NULL; | ||||
|     size_t rlen = 0; | ||||
|     const int amount = 150; | ||||
|     int i = 0; | ||||
| 
 | ||||
|     /* your average evening playing Shadowrun...
 | ||||
|      */ | ||||
|     d = dice_simple(amount, 6); | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
|     assert_true(dice_evaluate(d, &r, &rlen)); | ||||
|     assert_non_null(r); | ||||
| 
 | ||||
|     assert_int_equal(rlen, amount); | ||||
| 
 | ||||
|     for (i = 0; i < amount; i++) { | ||||
|         assert_true(r[i].result >= 1 && r[i].result <= 6); | ||||
|     } | ||||
| 
 | ||||
|     dice_free(d); | ||||
|     dice_result_freev(r, rlen); | ||||
| } | ||||
| 
 | ||||
| int main(int ac, char **av) | ||||
| { | ||||
|     const struct CMUnitTest tests[] = { | ||||
|         cmocka_unit_test(test_dice_evaluate_null), | ||||
|         cmocka_unit_test(test_dice_evaluate_one), | ||||
|         cmocka_unit_test(test_dice_evaluate_many), | ||||
|     }; | ||||
| 
 | ||||
|     return cmocka_run_group_tests(tests, NULL, NULL); | ||||
| } | ||||
							
								
								
									
										60
									
								
								tests/test_dice_parse.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								tests/test_dice_parse.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| #include <dice.h> | ||||
| 
 | ||||
| #include <setjmp.h> | ||||
| #include <cmocka.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| static void test_dice_parse_none(void **data) | ||||
| { | ||||
|     dice_t d = dice_parse(""); | ||||
|     assert_null(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_parse_amount(void **data) | ||||
| { | ||||
|     dice_t d = dice_parse("3d"); | ||||
|     assert_null(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_parse_amount_sides(void **data) | ||||
| { | ||||
|     dice_t d = dice_parse("5d10"); | ||||
|     int i = 0; | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
| 
 | ||||
|     assert_true(dice_get(d, DICEOPTION_AMOUNT, &i)); | ||||
|     assert_int_equal(i, 5); | ||||
| 
 | ||||
|     assert_true(dice_get(d, DICEOPTION_SIDES, &i)); | ||||
|     assert_int_equal(i, 10); | ||||
| 
 | ||||
|     dice_free(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_parse_sides(void **data) | ||||
| { | ||||
|     dice_t d = dice_parse("d12"); | ||||
|     int i = 0; | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
| 
 | ||||
|     assert_true(dice_get(d, DICEOPTION_SIDES, &i)); | ||||
|     assert_int_equal(i, 12); | ||||
| 
 | ||||
|     dice_free(d); | ||||
| } | ||||
| 
 | ||||
| int main(int ac, char **av) | ||||
| { | ||||
|     const struct CMUnitTest tests[] = { | ||||
|         cmocka_unit_test(test_dice_parse_none), | ||||
|         cmocka_unit_test(test_dice_parse_amount), | ||||
|         cmocka_unit_test(test_dice_parse_amount_sides), | ||||
|         cmocka_unit_test(test_dice_parse_sides), | ||||
|     }; | ||||
| 
 | ||||
|     return cmocka_run_group_tests(tests, NULL, NULL); | ||||
| } | ||||
							
								
								
									
										113
									
								
								tests/test_dice_simple_roll.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								tests/test_dice_simple_roll.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | ||||
| #include <dice.h> | ||||
| 
 | ||||
| #include <setjmp.h> | ||||
| #include <cmocka.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| static void test_dice_simple_null(void **data) | ||||
| { | ||||
|     dice_t d = dice_simple(0, 0); | ||||
|     assert_null(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_simple_one(void **data) | ||||
| { | ||||
|     dice_t d = dice_simple(1, 20); | ||||
|     assert_non_null(d); | ||||
|     dice_free(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_simple_roll(void **data) | ||||
| { | ||||
|     dice_t d = dice_simple(1, 20); | ||||
|     int i = 0; | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
| 
 | ||||
|     for (i = 0; i < 100000; i++) { | ||||
|         int64_t res = dice_roll(d); | ||||
|         assert_true(res >= 1 && res <= 20); | ||||
|     } | ||||
| 
 | ||||
|     dice_free(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_simple_multi(void **data) | ||||
| { | ||||
|     dice_t d = dice_simple(3, 6); | ||||
|     int i = 0; | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
| 
 | ||||
|     for (i = 0; i < 100000; i++) { | ||||
|         int64_t res = dice_roll(d); | ||||
|         assert_true(res >= 3 && res <= 18); | ||||
|     } | ||||
| 
 | ||||
|     dice_free(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_simple_get(void **data) | ||||
| { | ||||
|     dice_t d = dice_simple(8, 10); | ||||
|     int i = 0; | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
| 
 | ||||
|     assert_true(dice_get(d, DICEOPTION_AMOUNT, &i)); | ||||
|     assert_int_equal(i, 8); | ||||
| 
 | ||||
|     assert_true(dice_get(d, DICEOPTION_SIDES, &i)); | ||||
|     assert_int_equal(i, 10); | ||||
| 
 | ||||
|     dice_free(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_simple_set(void **data) | ||||
| { | ||||
|     dice_t d = dice_simple(1, 20); | ||||
|     int i = 0; | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
| 
 | ||||
|     assert_true(dice_set(d, DICEOPTION_AMOUNT, 20)); | ||||
|     assert_true(dice_set(d, DICEOPTION_SIDES, 4)); | ||||
| 
 | ||||
|     assert_true(dice_get(d, DICEOPTION_AMOUNT, &i)); | ||||
|     assert_int_equal(i, 20); | ||||
| 
 | ||||
|     assert_true(dice_get(d, DICEOPTION_SIDES, &i)); | ||||
|     assert_int_equal(i, 4); | ||||
| 
 | ||||
|     dice_free(d); | ||||
| } | ||||
| 
 | ||||
| static void test_dice_simple_invalid_getset(void **data) | ||||
| { | ||||
|     dice_t d = dice_simple(1, 20); | ||||
|     int i = 0; | ||||
| 
 | ||||
|     assert_non_null(d); | ||||
| 
 | ||||
|     assert_false(dice_set(d, 9001, 20)); | ||||
|     assert_false(dice_get(d, 9001, &i)); | ||||
| 
 | ||||
|     dice_free(d); | ||||
| } | ||||
| 
 | ||||
| int main(int ac, char **av) | ||||
| { | ||||
|     const struct CMUnitTest tests[] = { | ||||
|         cmocka_unit_test(test_dice_simple_null), | ||||
|         cmocka_unit_test(test_dice_simple_one), | ||||
|         cmocka_unit_test(test_dice_simple_roll), | ||||
|         cmocka_unit_test(test_dice_simple_multi), | ||||
|         cmocka_unit_test(test_dice_simple_set), | ||||
|         cmocka_unit_test(test_dice_simple_get), | ||||
|         cmocka_unit_test(test_dice_simple_invalid_getset), | ||||
|     }; | ||||
| 
 | ||||
|     return cmocka_run_group_tests(tests, NULL, NULL); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user