]> infiniteadaptability.org Git - workouts/commitdiff
removed hand-rolled opt parser
authoralex <[email protected]>
Sun, 25 Oct 2020 21:06:54 +0000 (14:06 -0700)
committeralex <[email protected]>
Sun, 25 Oct 2020 21:06:54 +0000 (14:06 -0700)
added getopt_long
added new unit tests
fixed integration tests accordingly
added custom logging functionality

55 files changed:
Dockerfile
Makefile.am
include/add.h
include/attr.h
include/default.h
include/log.h [new file with mode: 0644]
include/ls.h
include/main.h
include/new.h
include/opt.h
include/recent.h
include/toggle.h
include/usage.h
src/add.c
src/attr.c
src/default.c
src/log.c [new file with mode: 0644]
src/ls.c
src/main.c
src/new.c
src/opt.c [deleted file]
src/opt/homedir.c
src/opt/loglvl.c [new file with mode: 0644]
src/opt/rows.c
src/opt/verbose.c [deleted file]
src/recent.c
src/toggle.c
src/usage.c
test/integration/test/add.integration.test.js
test/integration/test/attr.integration.test.js
test/integration/test/basic.test.js
test/integration/test/ls.integration.test.js
test/integration/test/new.integration.test.js
test/integration/test/toggle.integration.test.js
test/unit/Makefile.am
test/unit/add.tests.c [new file with mode: 0644]
test/unit/add.tests.h [new file with mode: 0644]
test/unit/attr.tests.c
test/unit/attr.tests.h
test/unit/data.attr.tests.c [new file with mode: 0644]
test/unit/data.attr.tests.h [new file with mode: 0644]
test/unit/data.recent.tests.c [new file with mode: 0644]
test/unit/data.recent.tests.h [new file with mode: 0644]
test/unit/data.workout.tests.c [moved from test/unit/workout.tests.c with 98% similarity]
test/unit/data.workout.tests.h [moved from test/unit/workout.tests.h with 100% similarity]
test/unit/ls.tests.c [new file with mode: 0644]
test/unit/ls.tests.h [new file with mode: 0644]
test/unit/new.tests.c [new file with mode: 0644]
test/unit/new.tests.h [new file with mode: 0644]
test/unit/recent.tests.c
test/unit/recent.tests.h
test/unit/test_utils.c
test/unit/test_utils.h
test/unit/toggle.tests.c [new file with mode: 0644]
test/unit/toggle.tests.h [new file with mode: 0644]

index a131cd27ea9cb85a1079d34825786fac0e4b337f..9c057c1c1cacf527f72f05594f27220db2ca7bdf 100644 (file)
@@ -28,7 +28,7 @@ WORKDIR /build
 COPY --from=core /workouts-${VERSION}/ /build/
 
 RUN ./configure
-RUN make check
+RUN make check || cat test/unit/test-suite.log
 
 FROM node:latest as integration-tester
 ARG VERSION
index c1173f4f38a7178d5790ca1ed5d033d228a3c8f6..fa9774e0a0f386e839cadd58bbd6f51899aa686b 100644 (file)
@@ -6,10 +6,10 @@ workouts_SOURCES = \
        src/attr.c \
        src/data/attr.c \
        src/default.c \
+       src/log.c \
        src/ls.c \
        src/main.c \
        src/new.c \
-       src/opt.c \
        src/recent.c \
        src/toggle.c \
        src/usage.c \
@@ -17,13 +17,14 @@ workouts_SOURCES = \
        src/data/setup.c \
        src/data/workout.c \
        src/opt/homedir.c \
-       src/opt/rows.c \
-       src/opt/verbose.c
+       src/opt/loglvl.c \
+       src/opt/rows.c
 workouts_SOURCES += \
        include/add.h \
        include/attr.h \
        include/data.h \
        include/default.h \
+       include/log.h \
        include/ls.h \
        include/main.h \
        include/new.h \
index f120771728e520700bf898159b3e576bf3033412..0c656bea66a45594fb1ec7925df17dbee68fb6ac 100644 (file)
@@ -6,8 +6,9 @@
 #include<time.h>
 
 #include<data.h>
+#include<log.h>
 #include<usage.h>
 
-int add(int,int,char**);
+int add(int,char**);
 
 #endif
\ No newline at end of file
index 1a47e0d7618d708be105f1b67997fc0b62b0196c..3b51239762f84a865e8f2cd301d2333a0980d377 100644 (file)
@@ -6,9 +6,17 @@
 #include<string.h>
 
 #include<data.h>
+#include<log.h>
 #include<usage.h>
 
-int attr(int,int,char**);
+#define ATTR_ADD_STRING "add"
+#define ATTR_LS_STRING "ls"
+#define ATTR_MESSAGE_WRONG_NO_ARGS "wrong number of arguments for attr add\n"
+#define ATTR_MESSAGE_UNKNOWN_COMMAND "unknown command attr \"%s\"\n"
+#define ATTR_MESSAGE_ATTR_INSERT_FAILED "attribute insert failed\n"
+#define ATTR_MESSAGE_ATTR_ADDED "New attribute added: %s\n"
+
+int attr(int,char**);
 int attr_add(char*);
 int attr_ls();
 void print_attr(const unsigned char*);
index 7706e2e91793d56a2f65c731f4db6f926ec62599..5def141ee129e3e9cdbc09c972d88f2b13e152b8 100644 (file)
@@ -4,6 +4,7 @@
 #include<stdio.h>
 #include<stdlib.h>
 
+#include<log.h>
 #include<opt.h>
 
 int defaults();
diff --git a/include/log.h b/include/log.h
new file mode 100644 (file)
index 0000000..6f5e669
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __LOG_H_
+#define __LOG_H_
+
+#include<stdarg.h>
+#include<stdio.h>
+
+extern int verbose_flag;
+
+enum log_level {
+       LOG_LEVEL_SILENT = 0, /* suppresses all output */
+       LOG_LEVEL_ERRORS = 1,  /* only prints errors */
+       LOG_LEVEL_DEFAULT = 2, /* normal output */
+       LOG_LEVEL_VERBOSE = 3  /* logging and debugging info */
+};
+
+#define log_err(...) log_message(LOG_LEVEL_ERRORS,stderr,__VA_ARGS__)
+#define log_info(...) log_message(LOG_LEVEL_VERBOSE,stdout,__VA_ARGS__)
+#define log_msg(...) log_message(LOG_LEVEL_DEFAULT,stdout,__VA_ARGS__)
+
+void log_message(enum log_level,FILE*,const char*,...);
+
+#endif
\ No newline at end of file
index d87e3ef98401224bf780f6168cee43db5f6d175d..a1490b41e8af7b030e77226e5d8699e638df3460 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __LS_H_
 #define __LS_H_
 
+#include<getopt.h>
 #include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
@@ -8,7 +9,7 @@
 #include<data.h>
 #include<usage.h>
 
-int ls(int,int,char**);
+int ls(int,char**);
 void print_header(const unsigned char*);
 void print_workout(const unsigned char*,int,const unsigned char*);
 
index 7d6091120f7577e14a6d0273af2274e189d4f76b..30c865a54810a08cb97a32333abd50ace6c011cf 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __MAIN_H_
 #define __MAIN_H_
 
+#include<getopt.h>
 #include<stdio.h>
 #include<stdlib.h>
 
index 404006016138c8567cf10fc5c49a90b9cf5f3734..9880eaafa185c983d6e45ffdf31f4e9d720aee77 100644 (file)
@@ -8,6 +8,10 @@
 #include<opt.h>
 #include<usage.h>
 
-int new_workout(int,int,char**);
+#define NEW_MESSAGE_NUM_ATTRS_MISMATCH "number of attributes don't match\n"
+#define NEW_MESSAGE_INSERT_FAILED "workout insert failed\n"
+#define NEW_MESSAGE_WORKOUT_ADDED "New workout added: %s\n"
+
+int new_workout(int,char**);
 
 #endif
\ No newline at end of file
index 980d45fe2e42291708c72d329c7bbca0cc8facaa..db46dff76a2a1c15827bf13c287fb664a383d444 100644 (file)
@@ -7,32 +7,21 @@
 #include<stdlib.h>
 #include<string.h>
 
+#include<log.h>
+
 // global options
 struct options {
        char *db_location;
        char *homedir;
        int rows;
-       unsigned char verbose;
+       enum log_level verbose;
 };
 
 extern struct options global_opts;
 
-enum option_code {
-       OPTION_ERROR,
-       OPTION_EXIT,
-       OPTION_HELP,
-       OPTION_INVALID,
-       OPTION_NO_MORE,
-       OPTION_SUCCESS
-};
-
-int option(char*);
-int long_option(char*);
-int short_option(char*);
-
 // specific option setters
-int set_homedir(char*);
-void set_rows(int);
-void set_verbose(unsigned char);
+int opt_set_homedir(char*);
+void opt_set_rows(int);
+void opt_set_log_level(enum log_level);
 
 #endif
\ No newline at end of file
index fe5337b44a350a4b108a2d1990dcdc6470d62399..fd99363684cedfa855b08afbde5664520d81271a 100644 (file)
@@ -5,7 +5,9 @@
 
 #include<data.h>
 
+#define RECENT_COMMAND_FAILED "command failed\n"
+
 void print_recent(const unsigned char*,const unsigned char*);
-int recent(int,int,char**);
+int recent();
 
 #endif
\ No newline at end of file
index 8e7cce888cd4ffe0a9b53eef5aef7cf63ccc28a0..1c03d3b571758bd559d6364bbafed052c3eb3c7d 100644 (file)
@@ -7,6 +7,10 @@
 #include<data.h>
 #include<usage.h>
 
-int toggle(int,int,char**);
+#define TOGGLE_MESSAGE_WRONG_NUM_ARGS "wrong number of arguments for toggle\n"
+#define TOGGLE_MESSAGE_UNABLE "unable to toggle attribute %s for workout %s\n"
+#define TOGGLE_MESSAGE_SUCCESS "Successfully toggled %s attribute for workout %s\n"
+
+int toggle(int,char**);
 
 #endif
\ No newline at end of file
index 70ae527d74c3009a006e698a31ce4a996949d1d6..97a1b21154c4982a9a3a9793a456fa1a0c1bf6d3 100644 (file)
@@ -3,6 +3,8 @@
 
 #include<stdio.h>
 
+#include<log.h>
+
 void usage();
 
 #endif
\ No newline at end of file
index bbad5b19f54aa7bb8bcc286fe5f8e16d47139223..636ada6cc92fb6eda211e57a5a1719167c56c930 100644 (file)
--- a/src/add.c
+++ b/src/add.c
@@ -1,15 +1,15 @@
 #include<add.h>
 
-int add(int i, int argc, char **argv) {
-       if(i==argc) {
-               printf("`workouts add` requires at least 1 argument\n");
+int add(int argc, char **argv) {
+       if(1==argc) {
+               log_err("`workouts add` requires at least 1 argument\n");
                usage();
                return EXIT_FAILURE;
        }
 
 
        char buf[11];
-       if(i+1==argc) { // no date given
+       if(2==argc) { // no date given
                time_t t = time(NULL);
                struct tm now = *localtime(&t);
                if(strftime(buf,11,"%Y-%m-%d",&now)==0) { return EXIT_FAILURE; }
@@ -17,8 +17,8 @@ int add(int i, int argc, char **argv) {
                int YY, MM, DD;
                struct tm when = {0};
 
-               if(sscanf(argv[i+1],"%d-%d-%d", &YY, &MM, &DD)!=3) {
-                       printf("invalid date given\n");
+               if(sscanf(argv[2],"%d-%d-%d", &YY, &MM, &DD)!=3) {
+                       log_err("invalid date given\n");
                        return EXIT_FAILURE;
                }
 
@@ -28,12 +28,12 @@ int add(int i, int argc, char **argv) {
                if(strftime(buf,11,"%Y-%m-%d",&when)==0) { return EXIT_FAILURE; }
        }
 
-       if(recent_insert(argv[i],buf)<0) {
-               printf("add failed\n");
+       if(recent_insert(argv[1],buf)<0) {
+               log_err("add failed\n");
                return EXIT_FAILURE;
        }
 
-       printf("added workout %s on %s\n",argv[i],buf);
+       log_msg("added workout %s on %s\n",argv[1],buf);
 
        return EXIT_SUCCESS;
 }
\ No newline at end of file
index 227f57b9664fd54ef5d0d21330b5c3d5631c19cc..a5cea7e69248bdd2c4f06fa8773f5cb0cb136293 100644 (file)
@@ -1,22 +1,20 @@
 #include<attr.h>
 
-int attr(int i, int argc, char **argv) {
-       if(i>argc) { return EXIT_FAILURE; }
+int attr(int argc, char **argv) {
+       if(1==argc) { return attr_ls(); }
 
-       if(i==argc) { return attr_ls(); }
-
-       if(0==memcmp(argv[i],"add",3)) {
-               if(i+2!=argc) {
-                       printf("wrong number of arguments for attr add\n");
+       if(0==strcmp(argv[1],ATTR_ADD_STRING)) {
+               if(3!=argc) {
+                       log_err(ATTR_MESSAGE_WRONG_NO_ARGS);
                        usage();
                        return EXIT_FAILURE;
                }
 
-               return attr_add(argv[i+1]);
+               return attr_add(argv[2]);
        }
-
-       if(i+1!=argc) {
-               printf("unknown command attr \"%s\"\n",argv[i+1]);
+       
+       if((2!=argc)||(0!=strcmp(argv[1],ATTR_LS_STRING))) {
+               log_err(ATTR_MESSAGE_UNKNOWN_COMMAND,argv[1]);
                usage();
                return EXIT_FAILURE;
        }
@@ -26,19 +24,16 @@ int attr(int i, int argc, char **argv) {
 
 int attr_add(char *name) {
        if(attribute_insert(name)<0) {
-               printf("attribute insert failed\n");
+               log_err(ATTR_MESSAGE_ATTR_INSERT_FAILED);
                return EXIT_FAILURE;
        }
 
-       printf("New attribute added: %s\n",name);
+       log_msg(ATTR_MESSAGE_ATTR_ADDED,name);
        return EXIT_SUCCESS;
 }
 
 int attr_ls() {
-       if(attribute_get(&print_attr)<0) {
-               printf("command failed\n");
-               return EXIT_FAILURE;
-       }
+       if(attribute_get(&print_attr)<0) { return EXIT_FAILURE; }
 
        return EXIT_SUCCESS;
 }
index b7f48e1e2b38910fff157f997232493432699cae..8bfd754c12f68c0a55d7ae2b63d171d1c6abddd6 100644 (file)
@@ -1,5 +1,12 @@
 #include<default.h>
 
+struct options global_opts = {
+       NULL, /* db_location */
+       NULL, /* homedir */
+       -1, /* rows */
+       0 /* verbose */
+};
+
 int defaults() {
        char *p;
        
@@ -8,19 +15,19 @@ int defaults() {
        if(p==NULL) {
                p = getenv("HOME");
                if(NULL==p) {
-                       printf("HOME or WORKOUTS_HOME env variable must be defined\n");
+                       log_err("HOME or WORKOUTS_HOME env variable must be defined\n");
                        return -1;
                }
        }
 
-       if(set_homedir(p)<0) {
-               printf("HOME or WORKOUTS_HOME env value invalid\n");
+       if(opt_set_homedir(p)<0) {
+               log_err("HOME or WORKOUTS_HOME env value invalid\n");
                return -1;
        }
 
-       set_rows(-1);
+       opt_set_rows(-1);
        
-       set_verbose(0);
+       opt_set_log_level(LOG_LEVEL_DEFAULT);
 
        return 0;
 }
\ No newline at end of file
diff --git a/src/log.c b/src/log.c
new file mode 100644 (file)
index 0000000..732d1a1
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,12 @@
+#include<log.h>
+
+int verbose_flag = LOG_LEVEL_DEFAULT;
+
+void log_message(enum log_level level, FILE *out_stream, const char *format,...) {
+       if(level<=verbose_flag) {
+               va_list args;
+               va_start(args,format);
+               vfprintf(out_stream,format,args);
+               va_end(args);
+       }
+}
\ No newline at end of file
index 2ed755e216f524591f28e9bc1080c0de6efb30e1..06a641a7e7c331939f209b55962a9841936f59a1 100644 (file)
--- a/src/ls.c
+++ b/src/ls.c
@@ -10,60 +10,86 @@ struct ls_helper helper = {
        0
 };
 
-int ls(int i, int argc, char **argv) {
-       char *filter_p = NULL;
+static struct option ls_long_options[] = {
+       {"filter", required_argument, 0, 'f'},
+       {0,0,0,0}
+};
+
+int ls(int argc, char **argv) {
        /*
-       Cases:
-       -filter by attribute value: workouts --filter 011xx100
-       -search by name: workouts P90X
-       
-       All together: workouts --filter 01xx1001 P90X
+        * Cases:
+        * -filter by attribute value: workouts --filter 011xx100
+        * -search by name: workouts P90X
+        *
+        * All together: workouts --filter 01xx1001 P90X
+        *
+        * 0: must not have attribute
+        * 1: must have attribute
+        * x: can have attribute
+        */
+
+       int c;
+       char *filter_p = NULL;
+       char *search_term = NULL;
 
-       0: must not have attribute
-       1: must have attribute
-       x: can have attribute
-       */
+       // reset optind; see `man getopt.3` NOTES section for justification
+       optind = 0;
+       while(1) {
+               int option_index = 0;
 
-       helper.attr_count = attribute_count();
-       if(attribute_get(&print_header)<0) { return -1; }
+               if((c = getopt_long(argc,argv,"f:",ls_long_options,&option_index))==-1) { break; }
+
+               switch(c) {
+                       case 0:
+                               if(ls_long_options[option_index].flag!=0) { break; }
 
-       if(i+1<argc) {
-               if(memcmp(argv[i],"--filter",8)==0) {
-                       filter_p = argv[i+1];
-                       i += 2;
+                               log_err("option %s",ls_long_options[option_index].name);
+                               if(optarg) {
+                                       log_err(" with arg %s",optarg);
+                               }
+                               log_err("\n");
+                               return EXIT_FAILURE;
+                               
+                               break;
+                       case 'f':
+                               filter_p = optarg;
+                               break;
+                       case '?':
+                       default:
+                               usage();
+                               return EXIT_FAILURE;
                }
        }
-       
-       switch(argc-i) {
-               case 0:
-                       return (workout_get(
-                               NULL, /* term */
-                               filter_p, /* filter */
-                               global_opts.rows, /* limit */
-                               &print_workout /* print_function */
-                       )<0)?EXIT_FAILURE:EXIT_SUCCESS;
-               case 1:
-                       return (workout_get(
-                               argv[i], /* term */
-                               filter_p, /* filter */
-                               global_opts.rows, /* limit */
-                               &print_workout /* print function */
-                       )<0)?EXIT_FAILURE:EXIT_SUCCESS;
-               default:
-                       printf("invalid usage\n");
-                       usage();
-                       return EXIT_FAILURE;
+
+       if(optind<argc) {
+               search_term = argv[optind];
        }
+
+       helper.attr_count = attribute_count();
+       if(attribute_get(&print_header)<0) { return -1; }
+
+       if(workout_get(
+               search_term, /* term */
+               filter_p, /* filter */
+               global_opts.rows, /* limit */
+               &print_workout /* print_function */
+       )<0) { return EXIT_FAILURE; }
+
+       return EXIT_SUCCESS;
 }
 
+#define ATTRIBUTE_PRINT_HEADER "Attributes:\t"
+#define ATTRIBUTE_PRINT_ROW "%s\t"
+#define ATTRIBUTE_PRINT_END "\n"
+
 void print_header(const unsigned char *name) {
        if((helper.attr_count>0)&&(helper.i==0)) {
-               printf("Attributes:\t");
+               printf(ATTRIBUTE_PRINT_HEADER);
        }
-       printf("%s\t",name);
+       printf(ATTRIBUTE_PRINT_ROW,name);
        helper.i++;
        if(helper.i==helper.attr_count) {
-               printf("\n");
+               printf(ATTRIBUTE_PRINT_END);
        }
 }
 
index ddfbce9b17629aed810909c96df6fb4b329c631c..f182d397cd605267a161a9396068507113941f59 100644 (file)
@@ -1,61 +1,85 @@
-#include<config.h>
 #include<main.h>
 
+static struct option long_options[] = {
+       {"help", no_argument, 0, 'h'},
+       {"homedir", required_argument, 0, 'd'},
+       {"quiet", no_argument, &verbose_flag, LOG_LEVEL_SILENT},
+       {"rows", required_argument, 0, 'r'},
+       {"verbose", no_argument, &verbose_flag, LOG_LEVEL_VERBOSE},
+       {0,0,0,0}
+};
+
 int main(int argc, char **argv) {
-       int i,ret;
+       int c;
 
        if(defaults()<0) { return EXIT_FAILURE; }
 
-       i = 1;
-       do {
-               ret = option(argv[i]);
-               switch(ret) {
-                       case OPTION_NO_MORE:
-                               goto exit_options;
-                       case OPTION_HELP:
-                               usage();
-                               return EXIT_SUCCESS;
-                       case OPTION_INVALID:
-                               printf("invalid option: %s\n\n",argv[i]);
-                               usage();
-                               return EXIT_FAILURE;
-                       case OPTION_ERROR:
-                               printf("unknown error occured\n");
+       while(1) {
+               int option_index = 0;
+
+               /* The '+' at the beginning of the string means getopt_long will
+                * stop processing after finding the first non-option argument.
+                */
+               if((c = getopt_long(argc,argv,"+d:hqr:v",long_options,&option_index))==-1) { break; }
+
+               switch(c) {
+                       case 0:
+                               if(long_options[option_index].flag!=0) { break; }
+
+                               log_err("option %s",long_options[option_index].name);
+                               if(optarg) {
+                                       log_err(" with arg %s",optarg);
+                               }
+                               log_err("\n");
                                return EXIT_FAILURE;
-                       case OPTION_EXIT:
+                               
+                               break;
+                       case 'd':
+                               if(opt_set_homedir(optarg)<0) { return EXIT_FAILURE; }
+                               break;
+                       case 'h':
+                               usage();
                                return EXIT_FAILURE;
-                       default:
-                               i++;
                                break;
+                       case 'q':
+                               opt_set_log_level(LOG_LEVEL_SILENT);
+                               break;
+                       case 'r':
+                               opt_set_rows(strtoul(optarg,NULL,10));
+                               break;
+                       case 'v':
+                               opt_set_log_level(LOG_LEVEL_VERBOSE);
+                               break;
+                       case '?':
+                       default:
+                               return EXIT_FAILURE;
                }
-       } while(ret>0);
-
-       exit_options:
-               if(setup()<0) { return EXIT_FAILURE; }
-               char *cmd = argv[i];
-
-               if(NULL!=cmd) {
-                       i++;
-                       if(strcmp(cmd,UTIL_ADD)==0) {
-                               return add(i,argc,argv);
-                       } else if(strcmp(cmd,UTIL_ATTR)==0) {
-                               return attr(i,argc,argv);
-                       } else if(strcmp(cmd,UTIL_LS)==0) {
-                               return ls(i,argc,argv);
-                       } else if(strcmp(cmd,UTIL_NEW)==0) {
-                               return new_workout(i,argc,argv);
-                       } else if(strcmp(cmd,UTIL_RECENT)==0) {
-                               return recent(i,argc,argv);
-                       } else if(strcmp(cmd,UTIL_TOGGLE)==0) {
-                               return toggle(i,argc,argv);
-                       } else if(strcmp(cmd,UTIL_VERSION)==0) {
-                               printf("Version: 0.0.0\n");
-                               return EXIT_SUCCESS;
-                       } else {
-                               // decrement to allow for args to ls
-                               i--;
-                       }
+       }
+
+       if(setup()<0) { return EXIT_FAILURE; }
+
+       if(optind<argc) {
+               char *cmd = argv[optind];
+               argc -=  optind;
+               argv = &(argv[optind]);
+               
+               if(strcmp(cmd,UTIL_ADD)==0) {
+                       return add(argc,argv);
+               } else if(strcmp(cmd,UTIL_ATTR)==0) {
+                       return attr(argc,argv);
+               } else if(strcmp(cmd,UTIL_LS)==0) {
+                       return ls(argc,argv);
+               } else if(strcmp(cmd,UTIL_NEW)==0) {
+                       return new_workout(argc,argv);
+               } else if(strcmp(cmd,UTIL_RECENT)==0) {
+                       return recent();
+               } else if(strcmp(cmd,UTIL_TOGGLE)==0) {
+                       return toggle(argc,argv);
+               } else {
+                       log_err("Unknown cmd: %s\n",cmd);
+                       return EXIT_FAILURE;
                }
-       
-               return ls(i,argc,argv);
+       }
+
+       return ls(argc,argv);
 }
\ No newline at end of file
index 5ea4ecd5083f0269a6c61c6cd68fd8f166c937ca..f1aad638ec1b50c007b3c0109e230be10bbe7037 100644 (file)
--- a/src/new.c
+++ b/src/new.c
@@ -1,21 +1,17 @@
 #include<new.h>
 
-int new_workout(int i, int argc, char **argv) {
-       if(i>=argc) {
-               printf("not enough arguments for new\n");
-               usage();
-               return EXIT_FAILURE;
-       }
-
+int new_workout(int argc, char **argv) {
+       if(argc<2) { return EXIT_FAILURE; }
+       
        // check if attribute template provided
        unsigned int attr_flags = 0;
-       if(i+1<argc) {
+       if(2<argc) {
                int count = attribute_count();
-               char *attr_p = argv[i+1];
+               char *attr_p = argv[2];
                int len = strlen(attr_p);
 
                if(len!=count) {
-                       printf("number of attributes don't match\n");
+                       log_err(NEW_MESSAGE_NUM_ATTRS_MISMATCH);
                        return EXIT_FAILURE;
                }
 
@@ -27,12 +23,12 @@ int new_workout(int i, int argc, char **argv) {
                }
        }
 
-       if(workout_insert(argv[i],attr_flags)<0) {
-               printf("workout insert failed\n");
+       if(workout_insert(argv[1],attr_flags)<0) {
+               log_err(NEW_MESSAGE_INSERT_FAILED);
                return EXIT_FAILURE;
        }
 
-       printf("New workout added: %s\n",argv[i]);
+       log_msg(NEW_MESSAGE_WORKOUT_ADDED,argv[1]);
 
        return EXIT_SUCCESS;
 }
\ No newline at end of file
diff --git a/src/opt.c b/src/opt.c
deleted file mode 100644 (file)
index d4905a0..0000000
--- a/src/opt.c
+++ /dev/null
@@ -1,74 +0,0 @@
-#include<opt.h>
-
-struct options global_opts = {
-       NULL,
-       NULL,
-       -1,
-       0
-};
-
-int option(char *str) {
-       int len;
-
-       if(NULL==str) { return OPTION_NO_MORE; }
-       len = strlen(str);
-       if(len<2) { return OPTION_NO_MORE; }
-
-       if('-'==str[0]) {
-               if('-'==str[1]) {
-                       return long_option(&(str[2]));
-               } else {
-                       return short_option(&(str[1]));
-               }
-       }
-       
-       return OPTION_NO_MORE;
-}
-
-#define LONG_OPTION_HELP "help"
-#define LONG_OPTION_HELP_LENGTH 4
-#define LONG_OPTION_HOMEDIR "homedir"
-#define LONG_OPTION_HOMEDIR_LENGTH 7
-#define LONG_OPTION_ROWS "rows"
-#define LONG_OPTION_ROWS_LENGTH 4
-#define LONG_OPTION_VERBOSE "verbose"
-#define LONG_OPTION_VERBOSE_LENGTH 7
-
-int long_option(char *str) {
-       if(memcmp(str,LONG_OPTION_HELP,LONG_OPTION_HELP_LENGTH)==0) {
-               return OPTION_HELP;
-       } else if(memcmp(str,LONG_OPTION_VERBOSE,LONG_OPTION_VERBOSE_LENGTH)==0) {
-               set_verbose(1);
-               return OPTION_SUCCESS;
-       } else if(memcmp(str,LONG_OPTION_HOMEDIR,LONG_OPTION_HOMEDIR_LENGTH)==0) {
-               int len = strlen(str);
-               len -= (LONG_OPTION_HOMEDIR_LENGTH+1);
-               if(len<1) { return OPTION_INVALID; }
-
-               if(set_homedir(&(str[LONG_OPTION_HOMEDIR_LENGTH+1]))<0) {
-                       printf("unable to set home directory: %s\nCheck directory exists and has correct permissions\n",&(str[LONG_OPTION_HOMEDIR_LENGTH+1]));
-                       return OPTION_EXIT;
-               }
-               return OPTION_SUCCESS;
-       } else if(memcmp(str,LONG_OPTION_ROWS,LONG_OPTION_ROWS_LENGTH)==0) {
-               char *end_p;
-               set_rows(strtoul(&(str[LONG_OPTION_ROWS_LENGTH+1]),&end_p,10));
-               return OPTION_SUCCESS;
-       } else {
-               return OPTION_INVALID;
-       }
-}
-
-#define SHORT_OPTION_HELP 'h'
-#define SHORT_OPTION_VERBOSE 'v'
-
-int short_option(char *str) {
-       if(SHORT_OPTION_HELP==str[0]) {
-               return OPTION_HELP;
-       } else if(SHORT_OPTION_VERBOSE==str[0]) {
-               set_verbose(1);
-               return OPTION_SUCCESS;
-       } else {
-               return OPTION_INVALID;
-       }
-}
\ No newline at end of file
index f79d628256d7ecb0b3c702536db4d3c7c71bff0f..7890513853331fabd168461b440bebeb61f72720 100644 (file)
@@ -3,7 +3,7 @@
 #define DB_FILENAME "workouts.db"
 #define DB_FILENAME_LENGTH 11
 
-int set_homedir(char *to_set) {
+int opt_set_homedir(char *to_set) {
        int len = strlen(to_set);
        if(len<1) { return -1; }
 
diff --git a/src/opt/loglvl.c b/src/opt/loglvl.c
new file mode 100644 (file)
index 0000000..e11716b
--- /dev/null
@@ -0,0 +1,5 @@
+#include<opt.h>
+
+void opt_set_log_level(enum log_level level) {
+       global_opts.verbose = level;
+}
\ No newline at end of file
index b65a674dc351daa1a37590a885e9816b0fc17e56..18b67b52e5f1a444ee901f7afebced1e122fb853 100644 (file)
@@ -1,5 +1,5 @@
 #include<opt.h>
 
-void set_rows(int to_set) {
+void opt_set_rows(int to_set) {
        global_opts.rows = to_set;
 }
\ No newline at end of file
diff --git a/src/opt/verbose.c b/src/opt/verbose.c
deleted file mode 100644 (file)
index 934eb9e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#include<opt.h>
-
-void set_verbose(unsigned char val) {
-       if(val>0) {
-               global_opts.verbose = 1;
-       } else {
-               global_opts.verbose = 0;
-       }
-}
\ No newline at end of file
index c5eaf80ad4c80014e4ca4b6cdddda6c666c26241..2c23adf161ccacc2b5463e6feb652af3b7c5f591 100644 (file)
@@ -1,17 +1,14 @@
 #include<recent.h>
 
+#define RECENT_PRINT_FORMAT "%s\t%s\n"
+
 void print_recent(const unsigned char *workout, const unsigned char *date) {
-       printf("%s\t%s\n",workout,date);
+       printf(RECENT_PRINT_FORMAT,workout,date);
 }
 
-int recent(int i, int argc, char **argv) {
-       if(i!=argc) {
-               printf("wrong number of arguments for recent\n");
-               return EXIT_FAILURE;
-       }
-
+int recent() {
        if(recent_get(global_opts.rows,&print_recent)<0) {
-               printf("command failed\n");
+               log_err(RECENT_COMMAND_FAILED);
                return EXIT_FAILURE;
        }
 
index f485fea713d6f729385ff0a53393e3f9fda1b9b4..4a2541c86a0cbc3b10c314c17009f21159304a9b 100644 (file)
@@ -1,18 +1,18 @@
 #include<toggle.h>
 
-int toggle(int i, int argc, char **argv) {
-       if(i+2!=argc) {
-               printf("wrong number of arguments for toggle\n");
+int toggle(int argc, char **argv) {
+       if(3!=argc) {
+               log_err(TOGGLE_MESSAGE_WRONG_NUM_ARGS);
                usage();
                return EXIT_FAILURE;
        }
 
-       if(workout_toggle(argv[i],argv[i+1])<0) {
-               printf("unable to toggle attribute %s for workout %s\n",argv[i+1],argv[i]);
+       if(workout_toggle(argv[1],argv[2])<0) {
+               log_err(TOGGLE_MESSAGE_UNABLE,argv[2],argv[1]);
                return EXIT_FAILURE;
        }
 
-       printf("Successfully toggled %s attribute for workout %s\n",argv[i+1],argv[i]);
+       log_msg(TOGGLE_MESSAGE_SUCCESS,argv[2],argv[1]);
 
        return EXIT_SUCCESS;
 }
\ No newline at end of file
index bac721c34323f6eea53b128ea27f273780e67ba1..4149c6b7f137d082083647fecc245ce36237c805 100644 (file)
@@ -1,21 +1,23 @@
 #include<usage.h>
 
 void usage() {
-       printf("Usage:\n");
-       printf("\tworkouts [options] [ls] [--filter {attribute filter}] [search term]\n");
-       printf("\tworkouts [options] add [!name] [date]\n");
-       printf("\tworkouts [options] new [!name] [attributes]\n");
-       printf("\tworkouts [options] attr [ls]\n");
-       printf("\tworkouts [options] attr add [!name]\n");
-       printf("\tworkouts [options] toggle [!workout name] [!attr]\n");
-       printf("\tworkouts [options] recent\n");
-       printf("\n");
-       printf("Options:\n");
-       printf("\t--help,-h\n");
-       printf("\t--homedir=<path>\n");
-       printf("\t--rows=<number>\n");
-       printf("\t--verbose,-v\n");
-       printf("\n");
-       printf("{attribute filter} refers to string in bit flags corresponding to active attributes.\n\n");
-       printf("The character '!' in front of a variable name means required.\n");
+       log_err("Usage:\n");
+       log_err("\tworkouts [options] [ls] [--filter {attribute filter}] [search term]\n");
+       log_err("\tworkouts [options] add [!name] [date]\n");
+       log_err("\tworkouts [options] new [!name] [attributes]\n");
+       log_err("\tworkouts [options] attr [ls]\n");
+       log_err("\tworkouts [options] attr add [!name]\n");
+       log_err("\tworkouts [options] toggle [!workout name] [!attr]\n");
+       log_err("\tworkouts [options] recent\n");
+       log_err("\n");
+       log_err("Options:\n");
+       log_err("\t--help, -h\n");
+       log_err("\t--homedir, -d <path>\n");
+       log_err("\t--quiet, -q\n");
+       log_err("\t--rows, -r <number>\n");
+       log_err("\t--verbose, -v\n");
+       log_err("\n");
+       log_err("{attribute filter} refers to a string of bit flags (0 = not, 1 = has, x = either) corresponding to active attributes.\n");
+       log_err("Ex: 0100x00\n\n");
+       log_err("The character '!' in front of a variable name means required.\n");
 }
\ No newline at end of file
index 5a2265d9666093e720803437d45b5aa52687ae16..9f383572c060e4cd1122c151dd8a03553b534b15 100644 (file)
@@ -55,7 +55,7 @@ describe('add integration tests', () => {
                await assert.doesNotReject(async() => await exec('./workouts add workout1 2020-06-10'));
 
                await assert.doesNotReject(async() => {
-                       const {stdout,stderr} = await exec('./workouts workout1');
+                       const {stdout,stderr} = await exec('./workouts ls workout1');
 
                        let expected = `Attributes:\tlower\tupper\t\n`;
                        expected += `workout1 [2] [Last done: 2020-07-10]\n`;
index d560e1ccee48302281d8b037c426c458d3ff813f..f76b406e90475e30d1c6c6eb2b27d648d8c0b19c 100644 (file)
@@ -57,7 +57,6 @@ describe('attr integration tests', () => {
 
                        await assert.doesNotReject(async() => {
                                const {stdout,stderr} = await exec(`./workouts attr ls`);
-
                                let expected = "";
                                for(const attr of attributes) {
                                        expected += `${attr}\n`;
index 7bcfa69dd32b707cc23abb5c3c79228b4011ec91..c286dcff1c4c1fb9c60481ed9b45d01cd090f277 100644 (file)
@@ -14,7 +14,6 @@ describe('basic tests', () => {
        });
 
        it('should print usage options when run with --help option', async() => {
-               const {stdout,stderr} = await exec('./workouts --help');
                let usage = `Usage:\n`;
                usage += `\tworkouts [options] [ls] [--filter {attribute filter}] [search term]\n`;
                usage += `\tworkouts [options] add [!name] [date]\n`;
@@ -25,18 +24,32 @@ describe('basic tests', () => {
                usage += `\tworkouts [options] recent\n`;
                usage += `\n`;
                usage += `Options:\n`;
-               usage += `\t--help,-h\n`;
-               usage += `\t--homedir=<path>\n`;
-               usage += `\t--rows=<number>\n`;
-               usage += `\t--verbose,-v\n`;
+               usage += `\t--help, -h\n`;
+               usage += `\t--homedir, -d <path>\n`;
+               usage += `\t--quiet, -q\n`;
+               usage += `\t--rows, -r <number>\n`;
+               usage += `\t--verbose, -v\n`;
                usage += `\n`;
-               usage += `{attribute filter} refers to string in bit flags corresponding to active attributes.\n\n`;
+               usage += `{attribute filter} refers to a string of bit flags (0 = not, 1 = has, x = either) corresponding to active attributes.\n`;
+               usage += `Ex: 0100x00\n\n`
                usage += `The character '!' in front of a variable name means required.\n`;
-               assert.strictEqual(stdout,usage);
+
+               await assert.rejects(async() => await exec('./workouts --help'),(err) => {
+                       assert.strictEqual(err.code,1);
+                       assert.strictEqual(err.message,`Command failed: ./workouts --help\n`+usage);
+                       return true;
+               });
+
+               await assert.rejects(async() => await exec('./workouts -h'),(err) => {
+                       assert.strictEqual(err.code,1);
+                       assert.strictEqual(err.message,`Command failed: ./workouts -h\n`+usage);
+                       return true;
+               });
        });
 
        it(`should throw when given option --homedir which doesn't exist`, async() => {
                await assert.rejects(async() => await exec('./workouts --homedir=`pwd`/doesnt_exist'));
+               await assert.rejects(async() => await exec('./workouts -d `pwd`/doesnt_exist'));
        });
 
        after(async() => {
index 8755ce086ed39191fe12331d45ecf098a9a57258..773093e30e4830f367cddd9736473c624828da0a 100644 (file)
@@ -36,7 +36,7 @@ describe('ls integration tests', () => {
 
        it('should successfully limit rows grabbed', async() => {
                await assert.doesNotReject(async() => {
-                       const {stdout,stderr} = await exec('./workouts --rows=1');
+                       const {stdout,stderr} = await exec('./workouts --rows=1 ls');
 
                        let expected = `Attributes:\tlower\tupper\t\n`;
                        expected += `apple [3] [Last done: N/A]\n`;
@@ -46,7 +46,7 @@ describe('ls integration tests', () => {
 
        it('should successfully search for workouts', async() => {
                await assert.doesNotReject(async() => {
-                       const {stdout,stderr} = await exec('./workouts workout');
+                       const {stdout,stderr} = await exec('./workouts ls workout');
 
                        let expected = `Attributes:\tlower\tupper\t\n`;
                        expected += `workout1 [2] [Last done: N/A]\n`;
index c084c2b9f245399303fdf01cb8adba28638dd017..88fb12052ce3f116b94cde478cb8aeddd0749167 100644 (file)
@@ -24,7 +24,10 @@ describe('new integration tests', () => {
        });
 
        it('should fail to create a workout when given the wrong number of attributes', async() => {
-               await assert.rejects(async() => await exec('./workouts new workout1 0'));
+               await assert.rejects(async() => {
+                       const res = await exec('./workouts new workout1 0');
+                       console.log(res);
+               });
                await assert.rejects(async() => await exec('./workouts new workout1 110'));
        });
 
index 7c9d7c79d566527bf261dd47200a3ee2fac1c57a..e6affab36e111afd7a3ac3511404fffaf9ba1a14 100644 (file)
@@ -36,7 +36,7 @@ describe('toggle integration tests', () => {
                });
 
                await assert.doesNotReject(async() => {
-                       const {stdout,stderr} = await exec('./workouts workout1');
+                       const {stdout,stderr} = await exec('./workouts ls workout1');
 
                        let expected = `Attributes:\tlower\tupper\t\n`;
                        expected += `workout1 [3] [Last done: N/A]\n`;
@@ -51,7 +51,7 @@ describe('toggle integration tests', () => {
                });
 
                await assert.doesNotReject(async() => {
-                       const {stdout,stderr} = await exec('./workouts workout1');
+                       const {stdout,stderr} = await exec('./workouts ls workout1');
 
                        let expected = `Attributes:\tlower\tupper\t\n`;
                        expected += `workout1 [2] [Last done: N/A]\n`;
index 53bfe830149ccbaadfc2648bc35ad51d71ae4e1d..84d1af84a8f66a9f9683570b106154ab815160e3 100644 (file)
@@ -6,11 +6,17 @@ AM_CPPFLAGS = \
 
 EXTRA_DIST = \
        test_utils.h \
-       workout.tests.h \
+       add.tests.h \
+       attr.tests.h \
+       data.attr.tests.h \
+       data.recent.tests.h \
+       data.workout.tests.h \
+       ls.tests.h \
+       new.tests.h \
        recent.tests.h \
-       attr.tests.h
+       toggle.tests.h
 
-check_PROGRAMS = attr.tests recent.tests workout.tests
+check_PROGRAMS = add.tests attr.tests data.attr.tests data.recent.tests data.workout.tests ls.tests new.tests recent.tests toggle.tests
 TESTS = $(check_PROGRAMS)
 
 if ENABLE_MEMCHECK
@@ -22,25 +28,71 @@ common_SOURCES = test_utils.c
 
 TEST_SRC_DIR = $(top_srcdir)/src
 
-common_SOURCES += $(TEST_SRC_DIR)/default.c $(TEST_SRC_DIR)/opt.c
+common_SOURCES += $(TEST_SRC_DIR)/default.c $(TEST_SRC_DIR)/log.c
 common_SOURCES += $(TEST_SRC_DIR)/data/setup.c
-common_SOURCES += $(TEST_SRC_DIR)/opt/homedir.c $(TEST_SRC_DIR)/opt/rows.c $(TEST_SRC_DIR)/opt/verbose.c
+common_SOURCES += $(TEST_SRC_DIR)/opt/homedir.c $(TEST_SRC_DIR)/opt/loglvl.c $(TEST_SRC_DIR)/opt/rows.c
+
+add_tests_SOURCES = \
+       $(common_SOURCES) \
+       add.tests.c \
+       $(TEST_SRC_DIR)/add.c \
+       $(TEST_SRC_DIR)/data/attr.c \
+       $(TEST_SRC_DIR)/data/recent.c \
+       $(TEST_SRC_DIR)/data/workout.c \
+       $(TEST_SRC_DIR)/usage.c
 
 attr_tests_SOURCES = \
        $(common_SOURCES) \
        attr.tests.c \
+       $(TEST_SRC_DIR)/attr.c \
+       $(TEST_SRC_DIR)/data/attr.c \
+       $(TEST_SRC_DIR)/usage.c
+
+data_attr_tests_SOURCES = \
+       $(common_SOURCES) \
+       data.attr.tests.c \
        $(TEST_SRC_DIR)/data/attr.c
 
-recent_tests_SOURCES = \
+data_recent_tests_SOURCES = \
        $(common_SOURCES) \
-       recent.tests.c \
+       data.recent.tests.c \
        $(TEST_SRC_DIR)/data/recent.c \
        $(TEST_SRC_DIR)/data/workout.c \
        $(TEST_SRC_DIR)/data/attr.c
 
-workout_tests_SOURCES = \
+data_workout_tests_SOURCES = \
        $(common_SOURCES) \
-       workout.tests.c \
+       data.workout.tests.c \
        $(TEST_SRC_DIR)/data/workout.c \
        $(TEST_SRC_DIR)/data/attr.c \
-       $(TEST_SRC_DIR)/data/recent.c
\ No newline at end of file
+       $(TEST_SRC_DIR)/data/recent.c
+
+ls_tests_SOURCES = \
+       $(common_SOURCES) \
+       ls.tests.c \
+       $(TEST_SRC_DIR)/data/attr.c \
+       $(TEST_SRC_DIR)/data/workout.c \
+       $(TEST_SRC_DIR)/ls.c \
+       $(TEST_SRC_DIR)/usage.c
+
+new_tests_SOURCES = \
+       $(common_SOURCES) \
+       new.tests.c \
+       $(TEST_SRC_DIR)/data/attr.c \
+       $(TEST_SRC_DIR)/data/workout.c \
+       $(TEST_SRC_DIR)/new.c \
+       $(TEST_SRC_DIR)/usage.c
+
+recent_tests_SOURCES = \
+       $(common_SOURCES) \
+       recent.tests.c \
+       $(TEST_SRC_DIR)/data/recent.c \
+       $(TEST_SRC_DIR)/recent.c
+
+toggle_tests_SOURCES = \
+       $(common_SOURCES) \
+       toggle.tests.c \
+       $(TEST_SRC_DIR)/data/attr.c \
+       $(TEST_SRC_DIR)/data/workout.c \
+       $(TEST_SRC_DIR)/toggle.c \
+       $(TEST_SRC_DIR)/usage.c
\ No newline at end of file
diff --git a/test/unit/add.tests.c b/test/unit/add.tests.c
new file mode 100644 (file)
index 0000000..0c8bedc
--- /dev/null
@@ -0,0 +1,40 @@
+#include<add.tests.h>
+
+int main() {
+       setup_env();
+
+       add_basic_test();
+
+       clean();
+
+       return EXIT_SUCCESS;
+}
+
+void add_basic_test() {
+       char *bad_argv[] = {
+               "add",
+               "testworkout1notindb",
+               "sdofjasdfiasjdof",
+               "sldfkjalskdfjasd",
+               NULL
+       };
+
+       char *argv[] = {
+               "add",
+               "testworkout1",
+               "2020-10-06",
+               NULL
+       };
+
+       assert(1==workout_insert("testworkout1",0));
+
+       assert(EXIT_FAILURE==add(1,argv));
+       assert(EXIT_SUCCESS==add(2,argv));
+       assert(EXIT_SUCCESS==add(3,argv));
+
+       assert(EXIT_FAILURE==add(1,bad_argv));
+       assert(EXIT_FAILURE==add(2,bad_argv));
+       assert(EXIT_FAILURE==add(3,bad_argv));
+
+       reset_env();
+}
\ No newline at end of file
diff --git a/test/unit/add.tests.h b/test/unit/add.tests.h
new file mode 100644 (file)
index 0000000..13cfe79
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __ADD_TESTS_H_
+#define __ADD_TESTS_H_
+
+#include<test_utils.h>
+
+#include<add.h>
+
+int main();
+void add_basic_test();
+
+#endif
\ No newline at end of file
index dbb0e489305391e3c64a495812a58831da03b560..a6f46cbbb4cf5f01c53a206f8d5009ba8b8b2add 100644 (file)
@@ -3,87 +3,44 @@
 int main() {
        setup_env();
 
-       attribute_count_test();
-       attribute_get_test();
-       attribute_index_test();
-       attribute_insert_test();
-       attribute_parse_test();
+       attr_basic_test();
 
        clean();
 
        return EXIT_SUCCESS;
 }
 
-void attribute_count_test() {
-       assert(attribute_count()==0);
-
-       assert(attribute_insert("test")==1);
-       assert(attribute_count()==1);
-
-       assert(attribute_insert("test2")==1);
-       assert(attribute_count()==2);
+void attr_basic_test() {
+       char *argv[] = {
+               "attr",
+               "add",
+               "alsdkfjalksdfj",
+               NULL
+       };
+
+       char *ls_argv[] = {
+               "attr",
+               "ls",
+               NULL
+       };
+
+       char *bad_argv[] = {
+               "attr",
+               "hahaha",
+               "asdfoiasdf",
+               NULL
+       };
+
+       assert(EXIT_SUCCESS==attr(1,ls_argv));
+       assert(EXIT_SUCCESS==attr(2,ls_argv));
+
+       assert(EXIT_SUCCESS==attr(1,bad_argv));
+       assert(EXIT_FAILURE==attr(2,bad_argv));
+       assert(EXIT_FAILURE==attr(3,bad_argv));
+
+       assert(EXIT_SUCCESS==attr(1,argv));
+       assert(EXIT_FAILURE==attr(2,argv));
+       assert(EXIT_SUCCESS==attr(3,argv));
 
        reset_env();
-}
-
-int i;
-
-void attribute_get_test() {
-       i = 0;
-       assert(attribute_get(&attribute_get_test_helper)==1);
-       assert(i==0);
-
-       assert(attribute_insert("test")==1);
-       assert(attribute_get(&attribute_get_test_helper)==1);
-       assert(i==1);
-
-       reset_env();
-}
-
-void attribute_get_test_helper(const unsigned char *attr) {
-       i++;
-}
-
-void attribute_index_test() {
-       assert(attribute_index("test")<0);
-
-       assert(attribute_insert("test")==1);
-       assert(attribute_index("test")==0);
-       assert(attribute_index("test2")<0);
-
-       assert(attribute_insert("test2")==1);
-       assert(attribute_index("test")==0);
-       assert(attribute_index("test2")==1);
-
-       assert(attribute_insert("hello")==1);
-       assert(attribute_index("test")==0);
-       assert(attribute_index("test2")==1);
-       assert(attribute_index("hello")==2);
-
-       reset_env();
-}
-
-void attribute_insert_test() {
-       assert(attribute_insert("test")==1);
-
-       reset_env();
-}
-
-void attribute_parse_test() {
-       int required = 0;
-       int exclude = 0;
-       
-       assert(attribute_parse("311",&required,&exclude)<0);
-
-       required = 0;
-       exclude = 0;
-       assert(attribute_parse("011",&required,&exclude)==1);
-       assert(required==3);
-       assert(exclude==4);
-
-       required = 0;
-       exclude = 0;
-       assert(attribute_parse("x01",&required,&exclude)==1);
-       assert(required==1);
-       assert(exclude==2);
 }
\ No newline at end of file
index ee0abacf7997c732381ddb38a57598f0dba103e7..f12cde39409289c63f13905da3178a8a6bbbe05a 100644 (file)
@@ -3,12 +3,9 @@
 
 #include<test_utils.h>
 
+#include<attr.h>
+
 int main();
-void attribute_count_test();
-void attribute_get_test();
-void attribute_get_test_helper(const unsigned char*);
-void attribute_index_test();
-void attribute_insert_test();
-void attribute_parse_test();
+void attr_basic_test();
 
 #endif
\ No newline at end of file
diff --git a/test/unit/data.attr.tests.c b/test/unit/data.attr.tests.c
new file mode 100644 (file)
index 0000000..4953dd7
--- /dev/null
@@ -0,0 +1,89 @@
+#include<data.attr.tests.h>
+
+int main() {
+       setup_env();
+
+       attribute_count_test();
+       attribute_get_test();
+       attribute_index_test();
+       attribute_insert_test();
+       attribute_parse_test();
+
+       clean();
+
+       return EXIT_SUCCESS;
+}
+
+void attribute_count_test() {
+       assert(attribute_count()==0);
+
+       assert(attribute_insert("test")==1);
+       assert(attribute_count()==1);
+
+       assert(attribute_insert("test2")==1);
+       assert(attribute_count()==2);
+
+       reset_env();
+}
+
+int i;
+
+void attribute_get_test() {
+       i = 0;
+       assert(attribute_get(&attribute_get_test_helper)==1);
+       assert(i==0);
+
+       assert(attribute_insert("test")==1);
+       assert(attribute_get(&attribute_get_test_helper)==1);
+       assert(i==1);
+
+       reset_env();
+}
+
+void attribute_get_test_helper(const unsigned char *attr) {
+       i++;
+}
+
+void attribute_index_test() {
+       assert(attribute_index("test")<0);
+
+       assert(attribute_insert("test")==1);
+       assert(attribute_index("test")==0);
+       assert(attribute_index("test2")<0);
+
+       assert(attribute_insert("test2")==1);
+       assert(attribute_index("test")==0);
+       assert(attribute_index("test2")==1);
+
+       assert(attribute_insert("hello")==1);
+       assert(attribute_index("test")==0);
+       assert(attribute_index("test2")==1);
+       assert(attribute_index("hello")==2);
+
+       reset_env();
+}
+
+void attribute_insert_test() {
+       assert(attribute_insert("test")==1);
+
+       reset_env();
+}
+
+void attribute_parse_test() {
+       int required = 0;
+       int exclude = 0;
+       
+       assert(attribute_parse("311",&required,&exclude)<0);
+
+       required = 0;
+       exclude = 0;
+       assert(attribute_parse("011",&required,&exclude)==1);
+       assert(required==3);
+       assert(exclude==4);
+
+       required = 0;
+       exclude = 0;
+       assert(attribute_parse("x01",&required,&exclude)==1);
+       assert(required==1);
+       assert(exclude==2);
+}
\ No newline at end of file
diff --git a/test/unit/data.attr.tests.h b/test/unit/data.attr.tests.h
new file mode 100644 (file)
index 0000000..ee0abac
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ATTR_TESTS_H_
+#define __ATTR_TESTS_H_
+
+#include<test_utils.h>
+
+int main();
+void attribute_count_test();
+void attribute_get_test();
+void attribute_get_test_helper(const unsigned char*);
+void attribute_index_test();
+void attribute_insert_test();
+void attribute_parse_test();
+
+#endif
\ No newline at end of file
diff --git a/test/unit/data.recent.tests.c b/test/unit/data.recent.tests.c
new file mode 100644 (file)
index 0000000..c9fc484
--- /dev/null
@@ -0,0 +1,50 @@
+#include<data.recent.tests.h>
+
+int main() {
+       setup_env();
+       
+       recent_get_test();
+       recent_insert_test();
+
+       clean();
+
+       return EXIT_SUCCESS;
+}
+
+int i;
+
+void recent_get_test() {
+       i = 0;
+       assert(recent_get(-1,&recent_get_test_helper)==1);
+       assert(i==0);
+
+       assert(workout_insert("test",0)==1);
+       assert(workout_insert("test2",0)==1);
+
+       assert(recent_insert("test","2020-07-04")==1);
+       assert(recent_insert("test2","2020-07-04")==1);
+
+       assert(recent_get(-1,&recent_get_test_helper)==1);
+       assert(i==2);
+
+       i = 0;
+       assert(recent_get(1,&recent_get_test_helper)==1);
+       assert(i==1);
+
+       reset_env();
+}
+
+void recent_get_test_helper(const unsigned char *name, const unsigned char *date) {
+       i++;
+}
+
+void recent_insert_test() {
+       assert(workout_insert("test",0)==1);
+       assert(workout_insert("test2",0)==1);
+
+       assert(recent_insert("test","2020-07-04")==1);
+       assert(recent_insert("test2","2020-07-04")==1);
+       assert(recent_insert("test2","2020-07-04")==-1);
+
+       reset_env();
+}
\ No newline at end of file
diff --git a/test/unit/data.recent.tests.h b/test/unit/data.recent.tests.h
new file mode 100644 (file)
index 0000000..ffb2f70
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __RECENT_TESTS_H_
+#define __RECENT_TESTS_H_
+
+#include<test_utils.h>
+
+int main();
+void recent_get_test();
+void recent_get_test_helper(const unsigned char*,const unsigned char*);
+void recent_insert_test();
+
+
+#endif
\ No newline at end of file
similarity index 98%
rename from test/unit/workout.tests.c
rename to test/unit/data.workout.tests.c
index 6276e42d956774053207be348626d6321393543c..62f93faa7c9617adb21752f55f2499477655bcc3 100644 (file)
@@ -1,4 +1,4 @@
-#include<workout.tests.h>
+#include<data.workout.tests.h>
 
 int main() {
        setup_env();
diff --git a/test/unit/ls.tests.c b/test/unit/ls.tests.c
new file mode 100644 (file)
index 0000000..c4c86f2
--- /dev/null
@@ -0,0 +1,68 @@
+#include<ls.tests.h>
+
+int main() {
+       setup_env();
+
+       ls_basic_test();
+
+       clean();
+
+       return EXIT_SUCCESS;
+}
+
+void ls_basic_test() {
+       char *bad_opt[] = {
+               "ls",
+               "-b",
+               NULL
+       };
+
+       assert(attribute_insert("test")==1);
+       assert(attribute_insert("test2")==1);
+       assert(attribute_insert("test3")==1);
+       assert(attribute_insert("test4")==1);
+       assert(attribute_insert("test5")==1);
+       assert(attribute_insert("test6")==1);
+
+       assert(EXIT_SUCCESS==ls(1,bad_opt));
+       assert(EXIT_FAILURE==ls(2,bad_opt));
+
+       char *badfilter[] = {
+               "ls",
+               "--filter",
+               "lkasdlfkjsldkf",
+               NULL
+       };
+
+       assert(EXIT_SUCCESS==ls(1,badfilter));
+       assert(EXIT_FAILURE==ls(2,badfilter));
+       assert(EXIT_FAILURE==ls(3,badfilter));
+
+       char *argv[] = {
+               "ls",
+               "--filter",
+               "00x0x1",
+               "P90X",
+               NULL
+       };
+
+       assert(EXIT_SUCCESS==ls(1,argv));
+       assert(EXIT_FAILURE==ls(2,argv));
+       assert(EXIT_SUCCESS==ls(3,argv));
+       assert(EXIT_SUCCESS==ls(4,argv));
+       
+       char *argv_reversed[] = {
+               "ls",
+               "P90X",
+               "-f",
+               "01x0x0",
+               NULL
+       };
+
+       assert(EXIT_SUCCESS==ls(1,argv_reversed));
+       assert(EXIT_SUCCESS==ls(2,argv_reversed));
+       assert(EXIT_FAILURE==ls(3,argv_reversed));
+       assert(EXIT_SUCCESS==ls(4,argv_reversed));
+
+       reset_env();
+}
\ No newline at end of file
diff --git a/test/unit/ls.tests.h b/test/unit/ls.tests.h
new file mode 100644 (file)
index 0000000..6c416fe
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __LS_TESTS_H_
+#define __LS_TESTS_H_
+
+#include<test_utils.h>
+
+#include<ls.h>
+
+int main();
+void ls_basic_test();
+
+#endif
\ No newline at end of file
diff --git a/test/unit/new.tests.c b/test/unit/new.tests.c
new file mode 100644 (file)
index 0000000..69a5f67
--- /dev/null
@@ -0,0 +1,42 @@
+#include<new.tests.h>
+
+int main() {
+       setup_env();
+
+       new_basic_test();
+
+       clean();
+
+       return EXIT_SUCCESS;
+}
+
+void new_basic_test() {
+       char *bad[] = {
+               "new",
+               "testworkout",
+               "012001",
+               NULL
+       };
+
+       assert(attribute_insert("test")==1);
+       assert(attribute_insert("test2")==1);
+       assert(attribute_insert("test3")==1);
+       assert(attribute_insert("test4")==1);
+       assert(attribute_insert("test5")==1);
+       assert(attribute_insert("test6")==1);
+
+       assert(EXIT_FAILURE==new_workout(1,bad));
+       assert(EXIT_SUCCESS==new_workout(2,bad));
+       assert(EXIT_FAILURE==new_workout(3,bad));
+
+       char *argv[] = {
+               "new",
+               "test workout",
+               "010001",
+               NULL
+       };
+
+       assert(EXIT_SUCCESS==new_workout(3,argv));
+
+       reset_env();
+}
\ No newline at end of file
diff --git a/test/unit/new.tests.h b/test/unit/new.tests.h
new file mode 100644 (file)
index 0000000..e276ac8
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __NEW_TESTS_H_
+#define __NEW_TESTS_H_
+
+#include<test_utils.h>
+
+#include<new.h>
+
+int main();
+void new_basic_test();
+
+#endif
\ No newline at end of file
index c976677bef96b898a910c621e5df64d1c68d899f..b651811ee7b27e9c0705de712ba06b70142f074e 100644 (file)
@@ -2,49 +2,14 @@
 
 int main() {
        setup_env();
-       
-       recent_get_test();
-       recent_insert_test();
+
+       recent_basic_test();
 
        clean();
 
        return EXIT_SUCCESS;
 }
 
-int i;
-
-void recent_get_test() {
-       i = 0;
-       assert(recent_get(-1,&recent_get_test_helper)==1);
-       assert(i==0);
-
-       assert(workout_insert("test",0)==1);
-       assert(workout_insert("test2",0)==1);
-
-       assert(recent_insert("test","2020-07-04")==1);
-       assert(recent_insert("test2","2020-07-04")==1);
-
-       assert(recent_get(-1,&recent_get_test_helper)==1);
-       assert(i==2);
-
-       i = 0;
-       assert(recent_get(1,&recent_get_test_helper)==1);
-       assert(i==1);
-
-       reset_env();
-}
-
-void recent_get_test_helper(const unsigned char *name, const unsigned char *date) {
-       i++;
-}
-
-void recent_insert_test() {
-       assert(workout_insert("test",0)==1);
-       assert(workout_insert("test2",0)==1);
-
-       assert(recent_insert("test","2020-07-04")==1);
-       assert(recent_insert("test2","2020-07-04")==1);
-       assert(recent_insert("test2","2020-07-04")==-1);
-
-       reset_env();
+void recent_basic_test() {
+       assert(EXIT_SUCCESS==recent());
 }
\ No newline at end of file
index ffb2f70cfdc46de892c713a9a8ecf704c109cd5c..031ba8a9407c6ef7d95ac6f06f8f5117271d4c95 100644 (file)
@@ -3,10 +3,9 @@
 
 #include<test_utils.h>
 
-int main();
-void recent_get_test();
-void recent_get_test_helper(const unsigned char*,const unsigned char*);
-void recent_insert_test();
+#include<recent.h>
 
+int main();
+void recent_basic_test();
 
 #endif
\ No newline at end of file
index 61b8fca6a7d6ec9fd0166a50b315420e66d1213d..634451a68a8a4c7982cd4c8de6869bf2b01eaa56 100644 (file)
@@ -6,11 +6,11 @@ void clean() {
 }
 
 void reset_env() {
-       assert(remove(global_opts.db_location)==0);
+       assert((remove(global_opts.db_location)==0)||(errno==ENOENT));
        assert(setup()==1);
 }
 
 void setup_env() {
        assert(defaults()==0);
-       assert(setup()==1);
+       reset_env();
 }
\ No newline at end of file
index 5172929ffa1d55f7b988c54248110848e254e2e4..1fb9639593b283667f32b70c4e4b30d688c63b85 100644 (file)
@@ -2,6 +2,7 @@
 #define __TEST_UTILS_H_
 
 #include<assert.h>
+#include<errno.h>
 #include<stdio.h>
 #include<stdlib.h>
 
diff --git a/test/unit/toggle.tests.c b/test/unit/toggle.tests.c
new file mode 100644 (file)
index 0000000..309b515
--- /dev/null
@@ -0,0 +1,46 @@
+#include<toggle.tests.h>
+
+int main() {
+       setup_env();
+
+       toggle_basic_test();
+
+       clean();
+
+       return EXIT_SUCCESS;
+}
+
+void toggle_basic_test() {
+       assert(attribute_insert("test")==1);
+       assert(attribute_insert("test2")==1);
+       assert(attribute_insert("test3")==1);
+       assert(attribute_insert("test4")==1);
+       assert(attribute_insert("test5")==1);
+       assert(attribute_insert("test6")==1);
+
+       assert(workout_insert("test",0)==1);
+
+       char *bad[] = {
+               "toggle",
+               "test",
+               "notanattribute",
+               NULL
+       };
+
+       assert(EXIT_FAILURE==toggle(1,bad));
+       assert(EXIT_FAILURE==toggle(2,bad));
+       assert(EXIT_FAILURE==toggle(3,bad));
+
+       char *argv[] = {
+               "toggle",
+               "test",
+               "test3",
+               NULL
+       };
+
+       assert(EXIT_FAILURE==toggle(1,argv));
+       assert(EXIT_FAILURE==toggle(2,argv));
+       assert(EXIT_SUCCESS==toggle(3,argv));
+
+       reset_env();
+}
\ No newline at end of file
diff --git a/test/unit/toggle.tests.h b/test/unit/toggle.tests.h
new file mode 100644 (file)
index 0000000..3c9bbb8
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __TOGGLE_TESTS_H_
+#define __TOGGLE_TESTS_H_
+
+#include<test_utils.h>
+
+#include<toggle.h>
+
+int main();
+void toggle_basic_test();
+
+#endif
\ No newline at end of file