diff --git a/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/Makefile b/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/Makefile new file mode 100644 index 0000000..b3a1fea --- /dev/null +++ b/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/Makefile @@ -0,0 +1,7 @@ +SNP_SHARED_MAKEFILE := $(if $(SNP_SHARED_MAKEFILE),$(SNP_SHARED_MAKEFILE),"~/snp/shared.mk") + +TARGET := bin/weekday +SOURCES := src/main.c +TSTSOURCES := tests/tests.c + +include $(SNP_SHARED_MAKEFILE) diff --git a/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/src/main.c b/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/src/main.c new file mode 100644 index 0000000..d339a3e --- /dev/null +++ b/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/src/main.c @@ -0,0 +1,122 @@ + /* ---------------------------------------------------------------------------- + * -- _____ ______ _____ - + * -- |_ _| | ____|/ ____| - + * -- | | _ __ | |__ | (___ Institute of Embedded Systems - + * -- | | | '_ \| __| \___ \ Zuercher Hochschule Winterthur - + * -- _| |_| | | | |____ ____) | (University of Applied Sciences) - + * -- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - + * ---------------------------------------------------------------------------- + */ +/** + * @file + * @brief Lab P02 weekday + */ +#include +#include +#include + + +// *** TASK1: typedef enum types for month_t (Jan=1,...Dec} *** +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + + + +// *** TASK1: typedef struct for date_t *** +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + + + +// *** TASK2: typedef enum weekday_t (Sun=0, Mon, ...Sat) *** +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + +/** + * @brief TASK1: Checks if the given date is a leap year. + * @returns 0 = is not leap year, 1 = is leap year + */ +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + + +/** + * @brief TASK1: Calculates the length of the month given by the data parameter + * @returns 28, 29, 30, 31 if a valid month, else 0 + */ +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + +/** + * @brief TASK1: Checks if the given date is in the gregorian date range + * @returns 0 = no, 1 = yes + */ +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + + +/** + * @brief TASK1: Checks if the given date is a valid date. + * @returns 0 = is not valid date, 1 = is valid date + */ +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + + +/** + * @brief TASK2: calculated from a valid date the weekday + * @returns returns a weekday in the range Sun...Sat + */ +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + + + +/** + * @brief TASK2: print weekday as 3-letter abreviated English day name + */ +// BEGIN-STUDENTS-TO-ADD-CODE + + +// END-STUDENTS-TO-ADD-CODE + +/** + * @brief main function + * @param argc [in] number of entries in argv + * @param argv [in] program name plus command line arguments + * @returns returns success if valid date is given, failure otherwise + */ +int main(int argc, const char *argv[]) +{ + // TASK1: parse the mandatory argument into a date_t variable and check if the date is valid + // BEGIN-STUDENTS-TO-ADD-CODE + + + // END-STUDENTS-TO-ADD-CODE + + + // TASK2: calculate the weekday and print it in this format: "%04d-%02d-%02d is a %s\n" + // BEGIN-STUDENTS-TO-ADD-CODE + + + // END-STUDENTS-TO-ADD-CODE + + return EXIT_SUCCESS; +} + diff --git a/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/tests/tests.c b/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/tests/tests.c new file mode 100644 index 0000000..57ea23d --- /dev/null +++ b/P02_Funktionen_Datentyp_enum/work/wochentag-berechnung/tests/tests.c @@ -0,0 +1,197 @@ +/* ---------------------------------------------------------------------------- + * -- _____ ______ _____ - + * -- |_ _| | ____|/ ____| - + * -- | | _ __ | |__ | (___ Institute of Embedded Systems - + * -- | | | '_ \| __| \___ \ Zuercher Hochschule Winterthur - + * -- _| |_| | | | |____ ____) | (University of Applied Sciences) - + * -- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - + * ---------------------------------------------------------------------------- + */ +/** + * @file + * @brief Test suite for the given package. + */ +#include +#include +#include +#include +#include +#include +#include "test_utils.h" + +#ifndef TARGET // must be given by the make file --> see test target +#error missing TARGET define +#endif + +/// @brief alias for EXIT_SUCCESS +#define OK EXIT_SUCCESS +/// @brief alias for EXIT_FAILURE +#define FAIL EXIT_FAILURE + +/// @brief The name of the STDOUT text file. +#define OUTFILE "stdout.txt" +/// @brief The name of the STDERR text file. +#define ERRFILE "stderr.txt" + +// setup & cleanup +static int setup(void) +{ + remove_file_if_exists(OUTFILE); + remove_file_if_exists(ERRFILE); + return 0; // success +} + +static int teardown(void) +{ + // Do nothing. + // Especially: do not remove result files - they are removed in int setup(void) *before* running a test. + return 0; // success +} + +static struct tm now() +{ + time_t t = time(NULL); + return *localtime(&t); +} + +static const char* weekday_name(int wday) +{ + assert(0 <= wday && wday <= 6); + static const char* days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + return days[wday]; +} + +// tests +static void test_task1_fail_no_arg(void) +{ + // arrange & act & assert + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " >" OUTFILE " 2>" ERRFILE)), FAIL); +} + +static void test_task1_fail_not_gregorian(void) +{ + // arrange & act & assert + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1291-08-01 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1582-10-14 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1583-10-14 >" OUTFILE " 2>" ERRFILE)), OK); +} + +static void test_task1_fail_month_out_of_range(void) +{ + // arrange & act & assert + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-13-13 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-00-13 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-12-13 >" OUTFILE " 2>" ERRFILE)), OK); +} + +static void test_task1_fail_day_out_of_range(void) +{ + // arrange & act & assert + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-01-32 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-01-31 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-02-30 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-02-29 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2019-02-29 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2019-02-28 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2019-02-29 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2019-02-28 >" OUTFILE " 2>" ERRFILE)), OK); +} + +static void test_task1_fail_leap_year(void) +{ + // arrange & act & assert + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1900-02-29 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1900-02-28 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2000-02-30 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2000-02-29 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2001-02-29 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2001-02-28 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2004-02-30 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2004-02-29 >" OUTFILE " 2>" ERRFILE)), OK); +} + +static void test_task1_valid_date(void) +{ + // arrange & act & assert + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-01-01 >" OUTFILE " 2>" ERRFILE)), OK); + + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-01-31 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-02-29 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-03-31 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-04-30 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-05-31 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-06-30 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-07-31 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-08-31 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-09-30 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-10-31 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-11-30 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-12-31 >" OUTFILE " 2>" ERRFILE)), OK); + + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-01-32 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-02-30 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-03-32 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-04-31 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-05-32 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-06-31 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-07-32 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-08-32 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-09-31 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-10-32 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-11-31 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 2020-12-32 >" OUTFILE " 2>" ERRFILE)), FAIL); +} + +static void test_task2_start_gregorian(void) +{ + // arrange & act & assert + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1581-10-14 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1581-10-15 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1582-10-14 >" OUTFILE " 2>" ERRFILE)), FAIL); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1582-10-15 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1583-10-14 >" OUTFILE " 2>" ERRFILE)), OK); + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1583-10-15 >" OUTFILE " 2>" ERRFILE)), OK); + + const char *out_txt[] = { "1582-10-15 is a Fri\n" }; + CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " 1582-10-15 >" OUTFILE " 2>" ERRFILE)), OK); + assert_lines(OUTFILE, out_txt, sizeof(out_txt)/sizeof(*out_txt)); +} + +static void test_task2_today(void) +{ + // arrange + const size_t SIZE = 1000; + char command[SIZE]; + struct tm t = now(); + snprintf(command, SIZE, "%s %04d-%02d-%02d 2>%s | tail -1 >%s", XSTR(TARGET), t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, ERRFILE, OUTFILE); + + char buffer[SIZE]; + snprintf(buffer, SIZE, "%04d-%02d-%02d is a %s\n", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, weekday_name(t.tm_wday)); + const char *out_txt[] = { buffer }; + const char *err_txt[] = { NULL }; + + // act & assert + CU_ASSERT_EQUAL(WEXITSTATUS(system(command)), OK); + assert_lines(OUTFILE, out_txt, sizeof(out_txt)/sizeof(*out_txt)); + assert_lines(ERRFILE, err_txt, sizeof(err_txt)/sizeof(*err_txt)); +} + +/** + * @brief Registers and runs the tests. + * @returns success (0) or one of the CU_ErrorCode (>0) + */ +int main(void) +{ + // setup, run, teardown + TestMainBasic("lab test", setup, teardown + , test_task1_fail_no_arg + , test_task1_fail_not_gregorian + , test_task1_fail_month_out_of_range + , test_task1_fail_day_out_of_range + , test_task1_fail_leap_year + , test_task1_valid_date + , test_task2_start_gregorian + , test_task2_today + ); +} +