#include /* C='^[/][/*]SH_';O=${0##*[/]};R=`dirname $0`;R=${R%/}/;R0=$R$O;Rb=$R${O%%.*};O=" ";R=${0##*.};Rs=$Rb.$R;Rm=$Rb.tmp.$R;Rh=$Rb.h;R=$Rs$Rh$Rm;Rp='printf %s\n ';Rc=: [ "${R##*$0*}" = '' ]&&$Rp"$0:NG suffix"&&exit 1;R='sed -ne ';Cm=$R'"/[E]ND/!d :l;n;p;bl"<$R0>$Rm;$Rp"$Rm"';RB=$($R"s/${C}OP//p"<$R0|(F=mw;while read -r a b;do B=${a%:};F=`$Rp"$F"|$R"s#$B:*##1;p"`${a%_};$Rp"C$B=\$(cat<<'E'$O$b${O}E$O)";done $Rp"R1=$F"));Rw=$R'"/$C$R/!d;:l;n;/${C}ED/q;p;bl"<$R0';Cw="(R=LS;$Rw;$Rw>&3;R=HD $Rw;R=SC;$Rw>&3)"'>$Rh 3>$Rs;$Rp"$Rh $Rs"';Re=eval\ ;$Re"$RB";while getopts $R1\ R;do case $R in \?)exit 1;;*)$Re"O$R=\$OPTARG";Rc=$Rc$O`$Re'$Rp"$C'$R\"`;;esac done;[ "$Rc" = : ]&&Rc=$Cm;shift $((OPTIND-1));$Re"$C_$O$Rc";exit #END */ /*SH_LS*/ /* Copyright (C) 2019 Momi-g * 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 . */ /* add license cmt from cutest-1.5 README.txt */ /* NOTE The license is based on the zlib/libpng license. For more details see http://www.opensource.org/licenses/zlib-license.html. The intent of the license is to: - keep the license as simple as possible - encourage the use of CuTest in both free and commercial applications and libraries - keep the source code together - give credit to the CuTest contributors for their work If you ship CuTest in source form with your source distribution, the following license document must be included with it in unaltered form. If you find CuTest useful we would like to hear about it. LICENSE Copyright (c) 2003 Asim Jalis This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /*SH_ED*/ /*SH_HD*/ /*-* @_name HCUT_ADD, HCUT_RUN, eq, eq_s/i/d/p @auther momi-g @brief Header inc C Unit Test, portable unittest macros. @_synopsys void HCUT_ADD(fcname) int HCUT_RUN(const char* logfile, int msglv, fcname1, fcname2, ...) void eq(int cmp) void eq_s(void* s1, void* s2) void eq_i(int i1, int i2) void eq_d(double d1, double d2) void eq_p(void* p1, void* p2) ... eq asserts can take lastarg as cmt, eq_i(1,2, "failtest_cmt") etc. @_eg #include #include "hcut.hpp" //direct include. header+src in one-file. int hw() { puts("hw"); return 0; } HCUT_ADD(anyname_hw) { int ck = 123; eq( hw()==10 ); eq_i( hw(), 100, "mycmt" ); printf("bin:%s\n", argv[0]); } HCUT_RUN("./mytest.log", 1, anyname_hw ); //holding main() func // ~$ cc hw.c && ./a.out && echo $? >> drop ./mytest.log @_eg -- hw.c #include int hw() { puts("hw"); return 0; } -- test_hw.c #include "hcut.hpp" HCUT_ADD(t_hw1) { eq_i( hw(), 0, "mymsg" ); } HCUT_ADD(t_hw2) { printf("ag1:%s\n", argv[1]); eq( hw()==1 ); } HCUT_RUN("stderr", 2, t_hw1, t_hw2 ); // disp to stderr // ~$ cc hw.c test_hw.c && ./a.out xyz && echo $? @param fcname testfunc(test suite) name. @param logfile msgout fname. "stdout","stderr","NULL" are used as FILE* / noout. @param lv verbose lv. 0/1/2 ... quiet/normal/verbose. @param fcname1,2- test tgt. test all suite you set here. @return HCUT_RUN() returns failed assert cnt. @details HCUT_RUN() holds "int main(int argc, char** argv){...}" func. you can use cmdin data 'argc/argv' in HCUR_ADD() block. @_note other sample src is at srcend. ref:https://sourceforge.net/projects/cutest/files/cutest/1.5/ ref:https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks @_conforming c99+ (200112L+) @version 1.2.2, 2020-10-28 -*/ // change... sed -i 'HCUT_9611a28d' 'some_new_prefix_str' #ifndef HCUT_9611a28d #define HCUT_9611a28d //api_macro...see this srcend sample #define HCUT_ADD(a) HCUT_9611a28d_ADD(a) #define HCUT_RUN(...) HCUT_9611a28d_RUN(__VA_ARGS__) #define eq(a, ...) HCUT_9611a28d_assert_eq(__FILE__, __LINE__, #a, a, __VA_ARGS__ +0) #define eq_s(a,b, ...) HCUT_9611a28d_assert_eqs(__FILE__, __LINE__, #a "," #b, a, b, __VA_ARGS__ +0) #define eq_i(a,b, ...) HCUT_9611a28d_assert_eqi(__FILE__, __LINE__, #a "," #b, a, b, __VA_ARGS__ +0) #define eq_d(a,b, ...) HCUT_9611a28d_assert_eqd(__FILE__, __LINE__, #a "," #b, a, b, __VA_ARGS__ +0) #define eq_p(a,b, ...) HCUT_9611a28d_assert_eqp(__FILE__, __LINE__, #a "," #b, a, b, __VA_ARGS__ +0) //mainsrc #include #if ( _POSIX_C_SOURCE +0 < 200112L ) #error "needs compiler posix-2001 or upper(c99+)" #include "...dmy inc, preprocess stoper" #endif #include #include #if (199901L <= __STDC_VERSION__ +0) /* nealy 200112L, _POSIX_C_SOURCE c99*/ #define ERRact(xpr, msg, act) do{if(xpr){ fprintf(stderr, \ "ERR: %s %d: %s():%s msg:%s sys:%s\n",__FILE__,__LINE__, __func__,\ "hit(" #xpr ")", msg, strerror(errno) );act ;} }while(0) #else #define ERRact(xpr, msg, act) do{if(xpr){ fprintf(stderr, \ "ERR: %s %d: %s():%s msg:%s sys:%s\n",__FILE__,__LINE__, "func:c99+",\ "hit(" #xpr ")", msg, strerror(errno) );act ;} }while(0) #endif #include #include #include typedef struct HCUT_9611a28d_cmn_tag{ FILE* fp; int outlv; const char* fcname; int fail; int suc; } HCUT_9611a28d_cmn_t; static HCUT_9611a28d_cmn_t HCUT_9611a28d_cmn; int HCUT_9611a28d_pf(int lv, const char* fmt, ...){ if( HCUT_9611a28d_cmn.outlv < lv ){ return 0;} if( HCUT_9611a28d_cmn.fp == NULL ){ return 0;} va_list va; va_start(va, fmt); int rc = vfprintf(HCUT_9611a28d_cmn.fp, fmt, va); va_end(va); return rc; } #define HCUT_9611a28d_ADD(tfname) void tfname ## _sub(int argc, char** argv); \ void tfname(int argc, char** argv){ HCUT_9611a28d_cmn.fcname = #tfname; tfname ## _sub(argc, argv);} \ void tfname ## _sub(int argc, char** argv) #define HCUT_9611a28d_RUN(out, lv, ...) int main(int argc, char** argv){ \ HCUT_9611a28d_tf_t tfarr[]={ __VA_ARGS__, NULL}; \ return HCUT_9611a28d_run(out, lv, tfarr, argc, argv); \ } typedef void (*HCUT_9611a28d_tf_t)(int argc, char** argv); int HCUT_9611a28d_run(const char* out, int lv, HCUT_9611a28d_tf_t* tfarr, int argc, char** argv) { if(strcmp(out, "stdout")==0 ){ HCUT_9611a28d_cmn.fp = stdout;} else if(strcmp(out, "stderr")==0 ){ HCUT_9611a28d_cmn.fp = stderr;} else if(strcmp(out, "NULL")==0 ){ HCUT_9611a28d_cmn.fp = NULL;} else if(1){ FILE* fp = fopen(out, "w+"); ERRact(fp==NULL, "fopen() failed: ", fputs(out, stderr);exit(1); ); HCUT_9611a28d_cmn.fp = fp; } if( lv<0 || 2 #include "hcut.hpp" int hw() { puts("hw"); return 0; } // expand to "void t_hw(void){...}" HCUT_ADD(t_hw) { int ck = 123; eq(hw() == 0 ); eq(hw() == ck, "cmt if last arg(void*) is exist" ); } int gw() { puts("gw"); return 0; } HCUT_ADD(test_gw12345) { //assert type: cmp, int, dbl, str, ptr eq(1==2, "all asserts support lastarg cmt"); eq_i( gw(), 3); eq_d(1.01, (double)666); eq_s("aaa", "bbb"); eq_p("aaa", NULL, "my_cmt"); puts("my_test_end?"); } HCUT_RUN("stderr", 1, t_hw, test_gw12345 ); // HCUT_RUN() holds "int main(int argc, char** argv){..}" and returns fail cnt. // arg1 : msgout filename. "stdout","stderr","NULL" are used as FILE* or noout. // arg2 : verbose lv. 0/1/2 ... quiet/normal/verbose // arg3-: select test tgt. test all suite you set here. // rtn: cnt failed assert. rtn 0 if all asserts are success. /*SH_SMPE*/ /* change log -- 2020-10-28 Momi-g * hcut.sh.c: v1.2.2 release * hcut.sh.c(*SH_bn*): rename srcfile name, header suffix .cc -> .hpp * (brp.sh): add Rh="$bn.hpp", change .cc to .hpp 2020-10-25 Momi-g * hcut.sh.cc(assert_eqs): debug rc strcmp() >> (strcmp==0) change eqs args type void* >> const char* 2020-10-19 Momi-g * hcut.sh.cc: support cmdline data (argc, argv) at HCUT_ADD() codeblock * (doc): fix doc. 2020-06-30 Momi-g * hcut.sh.cc: v1.1.0 rewrite. 2020-02-02 Momi-g * hcut.sh.cc: v1.0.2 releases. * hcut.sh.cc (#define ast): change API stirng, ast->eq. * hcut.sh.cc (@sh-opt): fix Doc. 2020-1-11 Momi-g * hcut.sh.cc (@sh-opt): fix Doc. 2019-11-3 Momi-g * hcut.sh.cc: v1.0.1 releases. * hcut.sh.cc: (@sh-opt): build opt -b add. fix Doc. 2019-10-15 Momi-g * hcut.sh.cc: v1.0.0 releases. */ /*SH_ED*/ /*SH_OP _ a=`sed -ne "/${C}DF/!d;:l;n;/${C}DE/q;p;bl"<$R0`;eval "$a" #*/ /*SH_OP g cat $*|sed -ne 's/.*\*SH_co\*\([^*]*\).*$/\1/p'|$u #*/ /*SH_OP d find `dirname $0` -type d|sed -e 's/\(.*\)/ -I\1 -L\1 /g'|$N #*/ /*SH_OP A (fo "$@";$e"$Cg$O$Cd")|$N #*/ /*SH_OP h $p"-t/s/b:test/smpl/bld /T:t+mem /f:functop" #*/ /*SH_OP f sed -ne 's@^HCUT_ADD(\([^)]*\).*@\1,@p'<$R0;sed -e '/^[a-z].*)/!d;/;/d'<$R0 #*/ /*SH_OP t $e"$CW";[ "$1" != "" ]&&$i4;cat $Rs $tf>$Rm;$p'cc -g $Rm `fA $Rm`'|fv #*/ /*SH_OP s $e"$CB";f0 "${C}SMP" "${C}SMPE"<$Rs>eg.c;$p'cc eg.c `fA eg.c`'|fv #*/ /*SH_OP b $e"$CW";$p'cc -c $Rs -O2 -Wall'|fv;$p"$bn.o" #*/ /*SH_OP B $e"$Cb";$p"ar r lib$bn.a `fo $Rh $Rs` $bn.o"|fv;$p"lib$bn.a" #*/ /*SH_OP S $e"$CW";$p'cc $Rs `fo $Rh $Rs` `$e"$Cg$O$Cd"` -O2 -Wall -shared -fPIC -o lib'$bn'.so'|fv;$p"lib$bn.so" #*/ /*SH_OP W $e"$Cm$O$Cw";$i0;$i1;$cn<$Rh>$Rm;mv $Rm $Rh;$p"$Rs $tf" #*/ /*SH_DF #--name bn=`basename ${Rs%.*}` tf=${bn}_ts.${Rs##*.} Rh="$bn.hpp" #--cmd e="eval " p="$Rp" cn=$e'sed -e "s@\*${C##*]}bn\*@$bn@g"' n=$e"tr ' \t' '\n'|grep -v ^$" N=$e'(tr "\n" " ";$p)' u=$e'$n|sort -u|$N' f0()(sed -ne "/$1/!d;:l;n;/$2/d;p;bl"|$cn) f1()(sed -e "/$1/!d;:l;/$2/{p;d};n;bl"|$cn) fo()(a=$#;set `cat $@|(sed -ne 's/^#in.*"\(.*\.h\)".*$/\1/p';$p"$@")|$u` if [ $a = $# ];then $p"$@"|$n|sed -ne 's/\.h$/.o/p'|grep -Fv "$bn.o";else fo "$@";fi) fv()(while read -r a;do $e"cat</dev/stderr;$e"$a";done) fA()(set -- "$@";(fo "$@";$e"$Cg$O$Cd")|$N) i0=$e'f0 "^#ifdef TEST" "^#endif"<$Rm|$cn>$tf' i1=$e'sed -ne "/^#ifdef TEST/bl;p;d;:l;n;/^#endif/d;bl"<$Rs|$cn>$Rm;mv $Rm $Rs' # i3=$e'cat $a|(sed -ne "s/^#in.*\"\(.*\.h\)\".*$/\1/p";$p"$a")|$u' i4=$e'sed -ne "p;/_MAIN/bl;d;:l;n;/_AFT/{i\\$O$1);$O p;d};bl"<$tf>$Rm;mv $Rm $tf' # i5=$e'sed -ne "/${C}SMP/!d;:l;n;/${C}SMPE/q;p;bl"' # i5=$e'f0 "${C}SMP" "${C}SMPE"' /*SH_DE*/