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
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 \
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 \
#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
#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*);
#include<stdio.h>
#include<stdlib.h>
+#include<log.h>
#include<opt.h>
int defaults();
--- /dev/null
+#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
#ifndef __LS_H_
#define __LS_H_
+#include<getopt.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#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*);
#ifndef __MAIN_H_
#define __MAIN_H_
+#include<getopt.h>
#include<stdio.h>
#include<stdlib.h>
#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
#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
#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
#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
#include<stdio.h>
+#include<log.h>
+
void usage();
#endif
\ No newline at end of file
#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; }
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;
}
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
#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;
}
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;
}
#include<default.h>
+struct options global_opts = {
+ NULL, /* db_location */
+ NULL, /* homedir */
+ -1, /* rows */
+ 0 /* verbose */
+};
+
int defaults() {
char *p;
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
--- /dev/null
+#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
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);
}
}
-#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
#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;
}
}
}
- 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
+++ /dev/null
-#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
#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; }
--- /dev/null
+#include<opt.h>
+
+void opt_set_log_level(enum log_level level) {
+ global_opts.verbose = level;
+}
\ No newline at end of file
#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
+++ /dev/null
-#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
#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;
}
#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
#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
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`;
await assert.doesNotReject(async() => {
const {stdout,stderr} = await exec(`./workouts attr ls`);
-
let expected = "";
for(const attr of attributes) {
expected += `${attr}\n`;
});
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`;
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() => {
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`;
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`;
});
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'));
});
});
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`;
});
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`;
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
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
--- /dev/null
+#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
--- /dev/null
+#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
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
#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
-#include<workout.tests.h>
+#include<data.workout.tests.h>
int main() {
setup_env();
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
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
#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
}
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
#define __TEST_UTILS_H_
#include<assert.h>
+#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
--- /dev/null
+#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
--- /dev/null
+#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