Question
Help me answer these questions! Code listed under image. The first part is the Main.C. Each bolded part is the file/test runs. /* About this
Help me answer these questions! Code listed under image. The first part is the Main.C. Each bolded part is the file/test runs.
/*
About this program:
- This program counts words.
- The specific words that will be counted are passed in as command-line
arguments.
- The program reads words (one word per line) from standard input until EOF or
an input line starting with a dot '.'
- The program prints out a summary of the number of times each word has
appeared.
- Various command-line options alter the behavior of the program.
E.g., count the number of times 'cat', 'nap' or 'dog' appears.
> ./main cat nap dog
Given input:
cat
.
Expected output:
Looking for 3 words
Result:
cat:1
nap:0
dog:0
*/
#include
#include
#include
#include
#define LENGTH(s) (sizeof(s) / sizeof(*s))
/* Structures */
typedef struct {
char *word;
int counter;
} WordCountEntry;
int process_stream(WordCountEntry entries[], int entry_count)
{
short line_count = 0;
char buffer[30];
while (get(buffer)) {
if (*buffer == '.')
break;
/* Compare against each entry */
int i = 0;
while (i
if (!strcmp(entries[i].word, buffer))
entries[i].counter++;
i++;
}
line_count++;
}
return line_count;
}
void print_result(WordCountEntry entries[], int entry_count)
{
printf("Result: ");
while (entry_count-- > 0) {
printf("%s:%d ", entries->word, entries->counter);
}
}
void printHelp(const char *name)
{
printf("usage: %s [-h]
}
int main(int argc, char **argv)
{
const char *prog_name = *argv;
WordCountEntry entries[5];
int entryCount = 0;
/* Entry point for the testrunner program */
if (argc > 1 && !strcmp(argv[1], "-test")) {
run_smp0_tests(argc - 1, argv + 1);
return EXIT_SUCCESS;
}
while (*argv != NULL) {
if (**argv == '-') {
switch ((*argv)[1]) {
case 'h':
printHelp(prog_name);
default:
printf("%s: Invalid option %s. Use -h for help. ",
prog_name, *argv);
}
}
else {
if (entryCount
entries[entryCount].word = *argv;
entries[entryCount++].counter = 0;
}
}
argv++;
}
if (entryCount == 0) {
printf("%s: Please supply at least one word. Use -h for help. ",
prog_name);
return EXIT_FAILURE;
}
if (entryCount == 1) {
printf("Looking for a single word ");
}
else {
printf("Looking for %d words ", entryCount);
}
process_stream(entries, entryCount);
print_result(entries, entryCount);
return EXIT_SUCCESS;
}
_____________________
( smp0.tests.c )
/*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/
#define _GNU_SOURCE
#include
#undef _GNU_SOURCE
#include
#include
#include
#include "testrunner.h"
#include "smp0_tests.h"
#define quit_if(cond) do {if (cond) exit(EXIT_FAILURE);} while(0)
/* test of -h switch behavior (B3) */
int test_help_switch(int argc, char **argv)
{
char *args[] = {"./main", "-h", NULL};
FILE *out, *err, *tmp;
char buffer[100];
freopen("/devull", "r", stdin);
freopen("smp0.out", "w", stdout);
freopen("smp0.err", "w", stderr);
quit_if(main(2, args) != EXIT_FAILURE);
fclose(stdout);
fclose(stderr);
out = fopen("smp0.out", "r");
err = fopen("smp0.err", "r");
if (fgets(buffer, 100, out) != NULL && !strncmp(buffer, "usage:", 6)) {
tmp = out;
}
else {
quit_if(fgets(buffer, 100, err) == NULL);
quit_if(strncmp(buffer, "usage:", 6));
tmp = err;
}
if (fgets(buffer, 100, tmp) != NULL) {
quit_if(!strcmp(buffer, "./main: Invalid option -h. Use -h for help. "));
}
fclose(out);
fclose(err);
return EXIT_SUCCESS;
}
/* test of basic functionality (B4, B5) */
int test_basic_functionality(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 "};
FILE *out;
int i;
char buffer[100];
out = fopen("smp0.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("smp0.in", "r", stdin);
freopen("smp0.out", "w", stdout);
quit_if(main(4, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("smp0.out", "r");
for (i = 0; i
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
/* test of stderr output support (C1) */
int test_stderr_output(int argc, char **argv)
{
char *args[] = {"./main", "-wrong", NULL};
char *result[] = {"./main: Invalid option -wrong. Use -h for help. ",
"./main: Please supply at least one word. Use -h for help. "};
FILE *err;
int i;
char buffer[100];
freopen("/devull", "r", stdin);
freopen("/devull", "w", stdout);
freopen("smp0.err", "w", stderr);
quit_if(main(2, args) != EXIT_FAILURE);
fclose(stderr);
err = fopen("smp0.err", "r");
for (i = 0; i
quit_if(fgets(buffer, 100, err) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(err);
return EXIT_SUCCESS;
}
/* test of -fFILENAME switch behavior (C2) */
int test_file_output(int argc, char **argv)
{
char *args[] = {"./main", "-fsmp0.out", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 "};
FILE *out;
int i;
char buffer[100];
out = fopen("smp0.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("/devull", "w", stdout);
freopen("smp0.in", "r", stdin);
quit_if(main(5, args) != EXIT_SUCCESS);
fflush(0);
quit_if((out = fopen("smp0.out", "r")) == NULL);
for (i = 0; i
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
/* test of supporting an arbitrary number of words (C3) */
int test_malloc(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", "c", "a", "t", NULL};
char *result[] = {"Looking for 6 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 ",
"c:0 ", "a:0 ", "t:0 "};
FILE *out;
int i;
char buffer[100];
quit_if(system("grep malloc main.c > /devull"));
out = fopen("smp0.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("smp0.in", "r", stdin);
freopen("smp0.out", "w", stdout);
quit_if(main(7, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("smp0.out", "r");
for (i = 0; i
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
/* test of fgets usage (C4) */
int test_fgets(int argc, char **argv)
{
quit_if(system("grep fgets main.c > /devull"));
return EXIT_SUCCESS;
}
/* test of multiple words per line support (C5) */
int test_strtok(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:2 ",
"nap:1 "};
FILE *out;
int i;
char buffer[100];
out = fopen("smp0.in", "w");
fprintf(out, "cat ");
fprintf(out, "dog dog nap ");
fprintf(out, ". ");
fclose(out);
freopen("smp0.in", "r", stdin);
freopen("smp0.out", "w", stdout);
quit_if(main(4, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("smp0.out", "r");
for (i = 0; i
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
void delete_temp_files()
{
unlink("smp0.in");
unlink("smp0.out");
unlink("smp0.err");
}
/*
* Main entry point for SMP0 test harness
*/
int run_smp0_tests(int argc, char **argv)
{
/* Tests can be invoked by matching their name or their suite name
or 'all'*/
testentry_t tests[] = {
{"help_switch", "suite1", test_help_switch},
{"basic_functionality", "suite1",
test_basic_functionality},
{"stderr_output", "suite1", test_stderr_output},
{"file_output", "suite1", test_file_output},
{"malloc", "suite1", test_malloc},
{"fgets", "suite1", test_fgets},
{"strtok", "suite1", test_strtok}};
atexit(delete_temp_files);
return run_testrunner(argc, argv, tests, sizeof(tests) / sizeof (testentry_t));
}
____________________________
smp0.tests.h
/*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ int run_smp0_tests(int argc, char **argv); int main(int argc, char **argv);
____________________________________________________________________________
testrunner. c
/*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/
/*
A simple testrunner framework
Original Author: L. Angrave
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "testrunner.h"
/* Constants */
#define false (0)
#define true (1)
#define test_killed (2)
/* defaults */
static int default_timeout_seconds=5;
static int timeout_seconds;
void set_testrunner_default_timeout(int s) {
assert(s>0);
default_timeout_seconds=s;
}
void set_testrunner_timeout(int s) {
assert(s>0);
timeout_seconds=s;
}
/* --- Helper macros and functions --- */
#define DIE(mesg) {fprintf(stderr," %s(%d):%s ",__fname__,__LINE__,mesg); exit(1);}
static int eql( char*s1, char*s2) {return s1&&s2&&!strcmp(s1,s2);}
/* Callback function for qsort on strings */
static int mystrcmp( const void *p1, const void *p2) {
return eql( ( char*)p1, ( char*)p2);
}
/* Stats of all tests run so far */
typedef struct
{
int ran, passed, failed;
} stats_t;
/* -- Signal handlers -- */
static pid_t child_pid;
static int sent_child_timeout_kill_signal;
static void kill_child_signal_handler(intsigno) {
if(!child_pid) return;
char m[]="-Timeout(Killing test process)-";
write(0,m,sizeof(m)-1);
kill(child_pid,SIGKILL);
sent_child_timeout_kill_signal=1;
}
/* Internal function to run a test as a forked child. The child process is terminated if it runs for more than a few seconds */
static int invoke_test_with_timelimit(testentry_t* test, int redirect_stdouterr,int argc, char **argv)
{
char fname[255];
int wait_status;
pid_t wait_val;
struct sigaction action;
assert(!child_pid);
assert(test && test->test_function && test->name);
set_testrunner_timeout(default_timeout_seconds);
errno=0;
child_pid = fork ();
if (child_pid == -1) {
fprintf(stderr,"-fork failed so running test inline-");
return test->test_function (argc, argv);
}
if (child_pid == 0)
{
if(redirect_stdouterr) {
snprintf(fname,(int)sizeof(fname),"stdout-%s.txt",test->name);
fname[sizeof(fname)-1]=0;
freopen(fname, "w", stdout);
memcpy(fname+3,"err",3);
freopen(fname, "w", stderr);
}
exit(test->test_function(argc,argv));
}else {
wait_status=-1;
sigemptyset(&action.sa_mask);
action.sa_handler=kill_child_signal_handler;
sigaction(SIGALRM,&action,NULL);
sent_child_timeout_kill_signal=0;
alarm(timeout_seconds);
wait_val = waitpid (child_pid, &wait_status, 0);
int child_exited_normally= WIFEXITED (wait_status);
int child_exit_value=WEXITSTATUS (wait_status);
int child_term_by_signal=WIFSIGNALED(wait_status);
int child_term_signal=WTERMSIG(wait_status);
if(child_term_by_signal) {
fprintf(stderr,"testrunner:Test terminated by signal %d ",child_term_signal);
fprintf(stderr,"testrunner:waitpid returned %d (child_pid=%d,wait_status=%d)",wait_val,child_pid,wait_status);
}
if(child_pid != wait_val)
fprintf(stderr,"testrunner: strange... wait_val != child_pid ");
int passed= (child_pid == wait_val) && (child_exit_value==0) && (child_exited_normally!=0);
alarm(0);
kill(child_pid,SIGKILL);
child_pid=0;
return sent_child_timeout_kill_signal ? test_killed : passed ? 0 : 1;
}
}
/*
* run a test and update the stats. The main guts of this functionality is provided by invoke_test_with_timelimit
* This outer wrapper updates thes output and statistics before and after running the test.
*/
static int
run_one_test (stats_t * stats, testentry_t * test, int redirect_stdouterr,int argc, char **argv)
{
int test_result;
assert (stats && test->name && argc > 0 && argv && *argv);
stats->ran++;
stats->failed++;
printf ("%2d.%-20s:", stats->ran, test->name);
fflush(stdout);
test_result=invoke_test_with_timelimit(test,redirect_stdouterr,argc,argv);
if (test_result == 0)
{
stats->failed--;
stats->passed++;
}
printf(":%s ", (test_result == 0 ? "pass" : test_result ==
2 ? "TIMEOUT * " : "FAIL *"));
return test_result!=0;
}
/* Help functionality to print out sorted list of test names and suite names */
static void print_targets(testentry_t tests[], int count) {
char**array;
char *previous;
int i;
array=(char**)calloc(sizeof(char*),count);
/* Sort the test names and print unique entries*/
for(i=0;i qsort(array,count,sizeof(array[0]),mystrcmp); printf(" Valid tests : all"); for(i=0,previous="";i /* Sort the suite names and print unique entries*/ for(i=0;i qsort(array, count,sizeof(array[0]),mystrcmp); printf(" Valid suites:"); for(i=0,previous="";i printf(" "); } /* * Main entry point for test harness */ int run_testrunner(int argc, char **argv,testentry_t tests[],int test_count) { char *test_name, *target; int i; stats_t stats; int target_matched,max_errors_before_quit,redirect_stdouterr; memset (&stats, 0, sizeof (stats)); max_errors_before_quit=1; redirect_stdouterr=0; assert (tests != NULL); assert(test_count>0); assert (argc > 0 && argv && *argv); while(true) { target = argc > 1 ? argv[1] : ""; assert (target); if(*target!='-') break; argc--;argv++; if(target[1]=='f' && target[2]) max_errors_before_quit=atoi(target+1); else if(target[1]=='r') redirect_stdouterr=1; } target_matched = false; for (i=0;i test_name = tests[i].name; assert(test_name); assert(tests[i].suite); assert(tests[i].test_function); if (eql(target,test_name)||eql(target,"all") || eql (target,tests[i].suite) ) { if(!target_matched) printf("Running tests... "); target_matched = true; run_one_test (&stats, &tests[i],redirect_stdouterr, argc - 1,argv + 1); } } if (!target_matched) { fprintf (stderr, "Test '%s' not found", (strlen(target)>0?target : "(empty)")); print_targets(tests,test_count); } else { printf (" Test Results:%d tests,%d passed,%d failed. ", stats.ran, stats.passed, stats.failed); } return stats.passed == stats.ran && target_matched ? 0 : 1; } ________________________________________________________ testrunner.h /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ typedef int (*test_fp) (int, char **); typedef struct { char *name; char *suite; test_fp test_function; } testentry_t; int run_testrunner(int argc, char **argv, testentry_t *entries,int entry_count); void set_testrunner_default_timeout(int s); void set_testrunner_timeout(int s);
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started