diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/private/.tmcignore b/private/.tmcignore new file mode 100644 index 0000000..e69de29 diff --git a/private/template_project/Makefile b/private/template_project/Makefile new file mode 100644 index 0000000..570c07d --- /dev/null +++ b/private/template_project/Makefile @@ -0,0 +1,22 @@ +MAIN_DIR = src +TEST_DIR = test + +.PHONY: main test + +all: main test + +main: + $(MAKE) -C $(MAIN_DIR) + +test: + $(MAKE) -C $(TEST_DIR) + +clean: + $(MAKE) -C $(MAIN_DIR) clean + $(MAKE) -C $(TEST_DIR) clean + +run-main: + $(MAKE) -C $(MAIN_DIR) run + +run-test: + $(MAKE) -C $(TEST_DIR) run diff --git a/private/template_project/nbproject/Package-Default.bash b/private/template_project/nbproject/Package-Default.bash new file mode 100644 index 0000000..0d70205 --- /dev/null +++ b/private/template_project/nbproject/Package-Default.bash @@ -0,0 +1,75 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_PLATFORM=GNU-MacOSX +CND_CONF=Default +CND_DISTDIR=dist +CND_BUILDDIR=build +NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=MissingOutputInProject +OUTPUT_BASENAME=MissingOutputInProject +PACKAGE_TOP_DIR=setready-AES/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package +rm -rf ${NBTMPDIR} +mkdir -p ${NBTMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory "${NBTMPDIR}/setready-AES" +copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/setready-AES.tar +cd ${NBTMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/setready-AES.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${NBTMPDIR} diff --git a/private/template_project/nbproject/configurations.xml b/private/template_project/nbproject/configurations.xml new file mode 100644 index 0000000..26cce7f --- /dev/null +++ b/private/template_project/nbproject/configurations.xml @@ -0,0 +1,51 @@ + + + + + + main.c + + + tmc-check.c + tmc-check.h + + + + Makefile + + + ^(nbproject)$ + + . + + Makefile + + + + LOCAL_SOURCES + default + + + + + + . + ${MAKE} -f Makefile + ${MAKE} -f Makefile clean + + + + + + + + + + + + + + diff --git a/private/template_project/nbproject/private/Default.properties b/private/template_project/nbproject/private/Default.properties new file mode 100644 index 0000000..e69de29 diff --git a/private/template_project/nbproject/private/configurations.xml b/private/template_project/nbproject/private/configurations.xml new file mode 100644 index 0000000..736456b --- /dev/null +++ b/private/template_project/nbproject/private/configurations.xml @@ -0,0 +1,39 @@ + + + Makefile + + + + localhost + 4 + + + + + + + + + + + + + + + gdb + + + + "${OUTPUT_PATH}" + + "${OUTPUT_PATH}" + . + true + 0 + 0 + + + + + + diff --git a/private/template_project/nbproject/private/private.xml b/private/template_project/nbproject/private/private.xml new file mode 100644 index 0000000..1c50948 --- /dev/null +++ b/private/template_project/nbproject/private/private.xml @@ -0,0 +1,11 @@ + + + + true + + + 0 + 0 + + + diff --git a/private/template_project/nbproject/project.xml b/private/template_project/nbproject/project.xml new file mode 100644 index 0000000..a9c4bed --- /dev/null +++ b/private/template_project/nbproject/project.xml @@ -0,0 +1,23 @@ + + + org.netbeans.modules.cnd.makeproject + + + template_project + c + + h + UTF-8 + + + . + + + + Default + 0 + + + + + diff --git a/private/template_project/src/Makefile b/private/template_project/src/Makefile new file mode 100644 index 0000000..05a27b6 --- /dev/null +++ b/private/template_project/src/Makefile @@ -0,0 +1,13 @@ +SRC_FILES=main.c + +all: main + +main: $(SRC_FILES) + gcc -Wall -o $@ $(SRC_FILES) + +clean: + rm -f main + +run: main + # Running our main function from file main.c + ./main diff --git a/private/template_project/src/main.c b/private/template_project/src/main.c new file mode 100644 index 0000000..1662620 --- /dev/null +++ b/private/template_project/src/main.c @@ -0,0 +1,6 @@ +#include + +int main( int argc, const char* argv[] ) +{ + printf( "\nHello World\n" ); +} \ No newline at end of file diff --git a/private/template_project/test/Makefile b/private/template_project/test/Makefile new file mode 100644 index 0000000..e36e266 --- /dev/null +++ b/private/template_project/test/Makefile @@ -0,0 +1,17 @@ +CHECK_CFLAGS=$(shell pkg-config --cflags check) +CHECK_LDFLAGS=$(shell pkg-config --libs check) +SRC_FILES=tmc-check.c + +all: test + +test: $(SRC_FILES) + gcc $(CHECK_CFLAGS) -Wall -o $@ $(SRC_FILES) $(CHECK_LDFLAGS) + +clean: + # rm -f test tmc_available_points.txt tmc_test_results.xml valgrind.log + +run: test + # Printing available points + ./test --print-available-points + # Running test. There should be one success and one failure. + ./test diff --git a/private/template_project/test/tmc-check.c b/private/template_project/test/tmc-check.c new file mode 100644 index 0000000..1bc0b37 --- /dev/null +++ b/private/template_project/test/tmc-check.c @@ -0,0 +1,233 @@ + +#include "tmc-check.h" +#include +#include +#include +#include + +typedef struct SuitePoints +{ + Suite *s; + const char *s_name; + const char *points; + struct SuitePoints *next; +} SuitePoints; + +typedef struct PointsAssoc +{ + TCase *tc; + const char *tc_name; + const char *points; + struct PointsAssoc *next; +} PointsAssoc; + +typedef struct PointsList +{ + char *point; + struct PointsList *next; +} PointsList; + +typedef struct MemTest +{ + const char *tf_name; + int check_leaks; + int max_bytes_allocated; // Value -1 will represent no max_alloc check + struct MemTest *next; +} MemTest; + +static PointsAssoc *points_assocs = NULL; +static SuitePoints *suite_points = NULL; +static PointsList *all_points = NULL; +static MemTest *memtests = NULL; + +static void parse_points(const char *points, PointsList **target_list); +static void add_to_point_set(const char *point, ssize_t len, PointsList **target_list); +static int points_list_contains(const PointsList *list, const char *point, ssize_t len); + +void _tmc_register_memtest(const char *tf_name, int check_leaks, int max_bytes_allocated) +{ + MemTest *memtest = malloc(sizeof(MemTest)); + memtest->tf_name = tf_name; + memtest->check_leaks = check_leaks; + memtest->max_bytes_allocated = max_bytes_allocated; + + memtest->next = memtests; + memtests = memtest; +} + +void tmc_set_tcase_points(TCase *tc, const char *tc_name, const char *points) +{ + PointsAssoc *pa = (PointsAssoc*)malloc(sizeof(PointsAssoc)); + pa->tc = tc; + pa->tc_name = tc_name; + pa->points = points; + pa->next = points_assocs; + points_assocs = pa; + + parse_points(points, &all_points); +} + +void _tmc_register_test(Suite *s, TFun tf, const char *fname, const char *points) +{ + TCase *tc = tcase_create(fname); + tmc_set_tcase_points(tc, fname, points); + _tcase_add_test(tc, tf, fname, 0, 0, 0, 1); + suite_add_tcase(s, tc); +} + +void tmc_set_suite_points(Suite *s, const char *s_name, const char *points) +{ + SuitePoints *sp = (SuitePoints*) malloc(sizeof(SuitePoints)); + sp->s = s; + sp->points = points; + sp->s_name = s_name; + sp->next = suite_points; + suite_points = sp; + + parse_points(points, &all_points); +} + +Suite* tmc_suite_create(const char *name, const char *points) +{ + Suite *s = suite_create(name); + tmc_set_suite_points(s, name, points); + return s; +} + +int tmc_run_tests(int argc, const char **argv, Suite *s) +{ + int i; + for (i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--print-available-points") == 0) { + return tmc_print_available_points(stdout, '\n'); + } + + if (strcmp(argv[i], "--print-memory-tests") == 0) { + return tmc_print_memory_tests(stdout, ' ', '\n'); + } + } + + FILE *points_file = fopen("tmc_available_points.txt", "wb"); + FILE *memtest_file = fopen("tmc_memory_test_info.txt", "wb"); + if (tmc_print_suite_points(points_file) != 0) { + fclose(points_file); + return EXIT_FAILURE; + } + if (tmc_print_test_points(points_file) != 0) { + fclose(points_file); + return EXIT_FAILURE; + } + if (tmc_print_memory_tests(memtest_file, ' ', '\n') != 0) { + fclose(memtest_file); + return EXIT_FAILURE; + } + fclose(points_file); + fclose(memtest_file); + + SRunner *sr = srunner_create(s); + srunner_set_xml(sr, "tmc_test_results.xml"); + srunner_run_all(sr, CK_VERBOSE); + srunner_free(sr); + + return EXIT_SUCCESS; +} + +int tmc_print_available_points(FILE *f, char delimiter) +{ + const PointsList *pl = all_points; + while (pl != NULL) { + fputs(pl->point, f); + fputc(delimiter, f); + pl = pl->next; + } + fflush(f); + return 0; +} + +int tmc_print_memory_tests(FILE *f, char attr_delimiter, char line_delimiter) +{ + const MemTest *mt = memtests; + while (mt != NULL) { + fputs(mt->tf_name, f); + fputc(attr_delimiter, f); + fprintf(f, "%d", mt->check_leaks); + fputc(attr_delimiter, f); + fprintf(f, "%d", mt->max_bytes_allocated); + fputc(line_delimiter, f); + mt = mt->next; + } + fflush(f); + return 0; +} + +int tmc_print_test_points(FILE *f) +{ + const PointsAssoc *pa = points_assocs; + while (pa != NULL) { + fprintf(f, "[test] %s %s\n", pa->tc_name, pa->points); + pa = pa->next; + } + fflush(f); + return 0; +} + +int tmc_print_suite_points(FILE *f) +{ + const SuitePoints *sp = suite_points; + while (sp != NULL) { + fprintf(f, "[suite] %s %s\n", sp->s_name, sp->points); + sp = sp->next; + } + fflush(f); + return 0; +} + +static void parse_points(const char *points, PointsList **target_list) +{ + const char *p = points; + const char *q = p; + while (*q != '\0') { + if (isspace(*q)) { + const ssize_t len = q - p; + + if (!isspace(*p)) { + add_to_point_set(p, len, target_list); + } + + p = q + 1; + q = p; + } else { + q++; + } + } + + if (!isspace(*p) && q > p) { + const ssize_t len = q - p; + add_to_point_set(p, len, target_list); + } +} + +static void add_to_point_set(const char *point, ssize_t len, PointsList **target_list) +{ + if (!points_list_contains(*target_list, point, len)) { + PointsList *pl = (PointsList*)malloc(sizeof(PointsList)); + pl->point = malloc(len + 1); + memcpy(pl->point, point, len); + pl->point[len] = '\0'; + pl->next = *target_list; + *target_list = pl; + } +} + +static int points_list_contains(const PointsList *list, const char *point, ssize_t len) +{ + const PointsList *pl = all_points; + while (pl != NULL) { + if (strncmp(pl->point, point, len) == 0) { + return 1; + } + pl = pl->next; + } + return 0; +} + diff --git a/private/template_project/test/tmc-check.h b/private/template_project/test/tmc-check.h new file mode 100644 index 0000000..8100cbb --- /dev/null +++ b/private/template_project/test/tmc-check.h @@ -0,0 +1,58 @@ + +#include +#include + +/***** Main API *****/ + +/** A shorthand to make one test suite with the given points */ +Suite* tmc_suite_create(const char *name, const char *points); + +/** A shorthand to make a one function testcase with the given points into a suite. */ +#define tmc_register_test(suite, tf, points) _tmc_register_test((suite), (tf), "" # tf, points) +void _tmc_register_test(Suite *s, TFun tf, const char *fname, const char *points); + +/** A shorthand to make one memory test for a test function with given parameters */ +#define tmc_register_memtest(tf, check_leaks, max_bytes_allocated) _tmc_register_memtest("" # tf, check_leaks, max_bytes_allocated) +void _tmc_register_memtest(const char *tf_name, int chek_leaks, int max_bytes_allocated); + +/** A shorthand for registering a test with memtest at the same time */ +#define tmc_register_test_with_memtest(suite, tf, points, check_leaks, max_bytes_allocated) tmc_register_test(suite, tf, points); tmc_register_memtest(tf, check_leaks, max_bytes_allocated) + +/** + * Runs a test suite so that tmc_test_results.xml and tmc_test_points.txt are created. + * + * To be called from main() after creating the Suite. + * + * If --print-available-points is given, it only outputs all available points + * (in an undefined order) to stdout and exits. + * + * Returns an error code that can be returned from main. + * Normally this will be 0 even if test fail. + */ +int tmc_run_tests(int argc, const char **argv, Suite *s); + + +/***** Low-level API *****/ + +/** + * Set the points of a test case. + * + * This is a lower level alternative to using tmc_register_test. + */ +void tmc_set_tcase_points(TCase *tc, const char *tc_name, const char *points); + +/** + * Set the points of a test suite + * + * This is a lower level alternative to using tmc_suite_create. + */ +void tmc_set_suite_points (Suite *s, const char *s_name, const char *points); + +/** Prints all registered points once (in no particular order) to the given file. */ +int tmc_print_available_points(FILE *f, char delimiter); +int tmc_print_memory_tests(FILE *f, char attr_delimiter, char line_delimiter); + +/** Prints lines like "[test] testname pointname1 pointname2" to the given file. */ +int tmc_print_test_points(FILE *f); +/** Prints lines with "[suite] suitename pointname1 pointname2" to given file */ +int tmc_print_suite_points(FILE *f); \ No newline at end of file diff --git a/scripts/create-project b/scripts/create-project new file mode 100755 index 0000000..d681496 --- /dev/null +++ b/scripts/create-project @@ -0,0 +1,45 @@ +#!/usr/bin/env ruby +require 'fileutils' + +include FileUtils +cd File.dirname(File.dirname(__FILE__)) + +if !ARGV[0] || ['-h', '--help'].include?(ARGV[0]) + puts"Creates a new project from the project template." + puts + puts "Usage: #{__FILE__} [category/]project-name" + puts + exit 0 +end + +def gsub_in_file!(filename, search, replacement) + text = File.read(filename) + text.gsub!(search, replacement) + File.open(filename, 'wb') {|f| f.write(text) } +end + + +dest_path = ARGV[0] + +dest_category = dest_path.split('/').reverse.drop(1).reverse.join('/') +dest_name = dest_path.split('/').last + +template_name = 'template_project' +template_path = "private/#{template_name}" + +puts "Copying from #{template_path} to #{dest_path}" +mkdir_p dest_category unless dest_category.empty? +cp_r template_path, dest_path + +puts "Replacing occurrences of #{template_name} with #{dest_name}" +files_with_project_name = [ + 'nbproject/project.xml' +] +for file in files_with_project_name + puts " in #{dest_path}/#{file}" + gsub_in_file!("#{dest_path}/#{file}", template_name, dest_name) +end + +puts +puts "Done!" +puts diff --git a/viikko1/demoTehtava/Makefile b/viikko1/demoTehtava/Makefile new file mode 100644 index 0000000..ed79bd8 --- /dev/null +++ b/viikko1/demoTehtava/Makefile @@ -0,0 +1,25 @@ +MAIN_DIR = src +TEST_DIR = test + +.PHONY: main test + +all: main test + +main: + $(MAKE) -C $(MAIN_DIR) + +test: + $(MAKE) -C $(TEST_DIR) + +clean: + $(MAKE) -C $(MAIN_DIR) clean + $(MAKE) -C $(TEST_DIR) clean + +get-points: + $(MAKE) -C $(TEST_DIR) get-points + +run-main: + $(MAKE) -C $(MAIN_DIR) run + +run-test: + $(MAKE) -C $(TEST_DIR) run diff --git a/viikko1/demoTehtava/nbproject/Package-Default.bash b/viikko1/demoTehtava/nbproject/Package-Default.bash new file mode 100644 index 0000000..0d70205 --- /dev/null +++ b/viikko1/demoTehtava/nbproject/Package-Default.bash @@ -0,0 +1,75 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_PLATFORM=GNU-MacOSX +CND_CONF=Default +CND_DISTDIR=dist +CND_BUILDDIR=build +NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=MissingOutputInProject +OUTPUT_BASENAME=MissingOutputInProject +PACKAGE_TOP_DIR=setready-AES/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package +rm -rf ${NBTMPDIR} +mkdir -p ${NBTMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory "${NBTMPDIR}/setready-AES" +copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/setready-AES.tar +cd ${NBTMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/setready-AES.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${NBTMPDIR} diff --git a/viikko1/demoTehtava/nbproject/configurations.xml b/viikko1/demoTehtava/nbproject/configurations.xml new file mode 100644 index 0000000..26cce7f --- /dev/null +++ b/viikko1/demoTehtava/nbproject/configurations.xml @@ -0,0 +1,51 @@ + + + + + + main.c + + + tmc-check.c + tmc-check.h + + + + Makefile + + + ^(nbproject)$ + + . + + Makefile + + + + LOCAL_SOURCES + default + + + + + + . + ${MAKE} -f Makefile + ${MAKE} -f Makefile clean + + + + + + + + + + + + + + diff --git a/viikko1/demoTehtava/nbproject/private/Default.properties b/viikko1/demoTehtava/nbproject/private/Default.properties new file mode 100644 index 0000000..e69de29 diff --git a/viikko1/demoTehtava/nbproject/private/configurations.xml b/viikko1/demoTehtava/nbproject/private/configurations.xml new file mode 100644 index 0000000..736456b --- /dev/null +++ b/viikko1/demoTehtava/nbproject/private/configurations.xml @@ -0,0 +1,39 @@ + + + Makefile + + + + localhost + 4 + + + + + + + + + + + + + + + gdb + + + + "${OUTPUT_PATH}" + + "${OUTPUT_PATH}" + . + true + 0 + 0 + + + + + + diff --git a/viikko1/demoTehtava/nbproject/private/private.xml b/viikko1/demoTehtava/nbproject/private/private.xml new file mode 100644 index 0000000..1c50948 --- /dev/null +++ b/viikko1/demoTehtava/nbproject/private/private.xml @@ -0,0 +1,11 @@ + + + + true + + + 0 + 0 + + + diff --git a/viikko1/demoTehtava/nbproject/project.xml b/viikko1/demoTehtava/nbproject/project.xml new file mode 100644 index 0000000..a6ea3e9 --- /dev/null +++ b/viikko1/demoTehtava/nbproject/project.xml @@ -0,0 +1,23 @@ + + + org.netbeans.modules.cnd.makeproject + + + demoTehtava + c + + h + UTF-8 + + + . + + + + Default + 0 + + + + + diff --git a/viikko1/demoTehtava/src/Makefile b/viikko1/demoTehtava/src/Makefile new file mode 100644 index 0000000..5247a67 --- /dev/null +++ b/viikko1/demoTehtava/src/Makefile @@ -0,0 +1,13 @@ +SRC_FILES=main.c tested.c + +all: main + +main: $(SRC_FILES) + gcc -Wall -o $@ $(SRC_FILES) + +clean: + rm -f main + +run: main + # Running our main function from file main.c + ./main diff --git a/viikko1/demoTehtava/src/main.c b/viikko1/demoTehtava/src/main.c new file mode 100644 index 0000000..1662620 --- /dev/null +++ b/viikko1/demoTehtava/src/main.c @@ -0,0 +1,6 @@ +#include + +int main( int argc, const char* argv[] ) +{ + printf( "\nHello World\n" ); +} \ No newline at end of file diff --git a/viikko1/demoTehtava/src/tested.c b/viikko1/demoTehtava/src/tested.c new file mode 100644 index 0000000..d0cbc12 --- /dev/null +++ b/viikko1/demoTehtava/src/tested.c @@ -0,0 +1,9 @@ +#include "tested.h" + +int my_sum_function(int a, int b) { + /* BEGIN SOLUTION */ + return a + b; + /* END SOLUTION */ + + /* STUB: return 0 */ +} \ No newline at end of file diff --git a/viikko1/demoTehtava/src/tested.h b/viikko1/demoTehtava/src/tested.h new file mode 100644 index 0000000..4809781 --- /dev/null +++ b/viikko1/demoTehtava/src/tested.h @@ -0,0 +1,5 @@ +#ifndef TESTED_H +#define TESTED_H +int my_sum_function(int a, int b); +#endif /* TESTED_H */ + diff --git a/viikko1/demoTehtava/test/Makefile b/viikko1/demoTehtava/test/Makefile new file mode 100644 index 0000000..98484e5 --- /dev/null +++ b/viikko1/demoTehtava/test/Makefile @@ -0,0 +1,20 @@ +CHECK_CFLAGS=$(shell pkg-config --cflags check) +CHECK_LDFLAGS=$(shell pkg-config --libs check) +SRC_FILES=tmc-check.c test-file.c ../src/tested.c + +all: test + +test: $(SRC_FILES) + gcc $(CHECK_CFLAGS) -Wall -o $@ $(SRC_FILES) $(CHECK_LDFLAGS) + +clean: + # rm -f test tmc_available_points.txt tmc_test_results.xml valgrind.log + +get-points: + ./test --print-available-points + +run: test + # Printing available points + ./test --print-available-points + # Running test. There should be one success and one failure. + ./test diff --git a/viikko1/demoTehtava/test/test b/viikko1/demoTehtava/test/test new file mode 100755 index 0000000..6234d2e Binary files /dev/null and b/viikko1/demoTehtava/test/test differ diff --git a/viikko1/demoTehtava/test/test-file.c b/viikko1/demoTehtava/test/test-file.c new file mode 100644 index 0000000..f6239e4 --- /dev/null +++ b/viikko1/demoTehtava/test/test-file.c @@ -0,0 +1,20 @@ +#include +#include "tmc-check.h" +#include "../src/tested.h" +#include + + +START_TEST(my_first) +{ + fail_unless(my_sum_function(1, 2) == 3, "My own sum function should sum 1 and 2 resulting in 3"); +} +END_TEST + +int main(int argc, const char* argv[]) +{ + Suite *s = suite_create("Test suite"); + + tmc_register_test(s, my_first_test, "1.1"); + + return tmc_run_tests(argc, argv, s); +} diff --git a/viikko1/demoTehtava/test/tmc-check.c b/viikko1/demoTehtava/test/tmc-check.c new file mode 100644 index 0000000..1bc0b37 --- /dev/null +++ b/viikko1/demoTehtava/test/tmc-check.c @@ -0,0 +1,233 @@ + +#include "tmc-check.h" +#include +#include +#include +#include + +typedef struct SuitePoints +{ + Suite *s; + const char *s_name; + const char *points; + struct SuitePoints *next; +} SuitePoints; + +typedef struct PointsAssoc +{ + TCase *tc; + const char *tc_name; + const char *points; + struct PointsAssoc *next; +} PointsAssoc; + +typedef struct PointsList +{ + char *point; + struct PointsList *next; +} PointsList; + +typedef struct MemTest +{ + const char *tf_name; + int check_leaks; + int max_bytes_allocated; // Value -1 will represent no max_alloc check + struct MemTest *next; +} MemTest; + +static PointsAssoc *points_assocs = NULL; +static SuitePoints *suite_points = NULL; +static PointsList *all_points = NULL; +static MemTest *memtests = NULL; + +static void parse_points(const char *points, PointsList **target_list); +static void add_to_point_set(const char *point, ssize_t len, PointsList **target_list); +static int points_list_contains(const PointsList *list, const char *point, ssize_t len); + +void _tmc_register_memtest(const char *tf_name, int check_leaks, int max_bytes_allocated) +{ + MemTest *memtest = malloc(sizeof(MemTest)); + memtest->tf_name = tf_name; + memtest->check_leaks = check_leaks; + memtest->max_bytes_allocated = max_bytes_allocated; + + memtest->next = memtests; + memtests = memtest; +} + +void tmc_set_tcase_points(TCase *tc, const char *tc_name, const char *points) +{ + PointsAssoc *pa = (PointsAssoc*)malloc(sizeof(PointsAssoc)); + pa->tc = tc; + pa->tc_name = tc_name; + pa->points = points; + pa->next = points_assocs; + points_assocs = pa; + + parse_points(points, &all_points); +} + +void _tmc_register_test(Suite *s, TFun tf, const char *fname, const char *points) +{ + TCase *tc = tcase_create(fname); + tmc_set_tcase_points(tc, fname, points); + _tcase_add_test(tc, tf, fname, 0, 0, 0, 1); + suite_add_tcase(s, tc); +} + +void tmc_set_suite_points(Suite *s, const char *s_name, const char *points) +{ + SuitePoints *sp = (SuitePoints*) malloc(sizeof(SuitePoints)); + sp->s = s; + sp->points = points; + sp->s_name = s_name; + sp->next = suite_points; + suite_points = sp; + + parse_points(points, &all_points); +} + +Suite* tmc_suite_create(const char *name, const char *points) +{ + Suite *s = suite_create(name); + tmc_set_suite_points(s, name, points); + return s; +} + +int tmc_run_tests(int argc, const char **argv, Suite *s) +{ + int i; + for (i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--print-available-points") == 0) { + return tmc_print_available_points(stdout, '\n'); + } + + if (strcmp(argv[i], "--print-memory-tests") == 0) { + return tmc_print_memory_tests(stdout, ' ', '\n'); + } + } + + FILE *points_file = fopen("tmc_available_points.txt", "wb"); + FILE *memtest_file = fopen("tmc_memory_test_info.txt", "wb"); + if (tmc_print_suite_points(points_file) != 0) { + fclose(points_file); + return EXIT_FAILURE; + } + if (tmc_print_test_points(points_file) != 0) { + fclose(points_file); + return EXIT_FAILURE; + } + if (tmc_print_memory_tests(memtest_file, ' ', '\n') != 0) { + fclose(memtest_file); + return EXIT_FAILURE; + } + fclose(points_file); + fclose(memtest_file); + + SRunner *sr = srunner_create(s); + srunner_set_xml(sr, "tmc_test_results.xml"); + srunner_run_all(sr, CK_VERBOSE); + srunner_free(sr); + + return EXIT_SUCCESS; +} + +int tmc_print_available_points(FILE *f, char delimiter) +{ + const PointsList *pl = all_points; + while (pl != NULL) { + fputs(pl->point, f); + fputc(delimiter, f); + pl = pl->next; + } + fflush(f); + return 0; +} + +int tmc_print_memory_tests(FILE *f, char attr_delimiter, char line_delimiter) +{ + const MemTest *mt = memtests; + while (mt != NULL) { + fputs(mt->tf_name, f); + fputc(attr_delimiter, f); + fprintf(f, "%d", mt->check_leaks); + fputc(attr_delimiter, f); + fprintf(f, "%d", mt->max_bytes_allocated); + fputc(line_delimiter, f); + mt = mt->next; + } + fflush(f); + return 0; +} + +int tmc_print_test_points(FILE *f) +{ + const PointsAssoc *pa = points_assocs; + while (pa != NULL) { + fprintf(f, "[test] %s %s\n", pa->tc_name, pa->points); + pa = pa->next; + } + fflush(f); + return 0; +} + +int tmc_print_suite_points(FILE *f) +{ + const SuitePoints *sp = suite_points; + while (sp != NULL) { + fprintf(f, "[suite] %s %s\n", sp->s_name, sp->points); + sp = sp->next; + } + fflush(f); + return 0; +} + +static void parse_points(const char *points, PointsList **target_list) +{ + const char *p = points; + const char *q = p; + while (*q != '\0') { + if (isspace(*q)) { + const ssize_t len = q - p; + + if (!isspace(*p)) { + add_to_point_set(p, len, target_list); + } + + p = q + 1; + q = p; + } else { + q++; + } + } + + if (!isspace(*p) && q > p) { + const ssize_t len = q - p; + add_to_point_set(p, len, target_list); + } +} + +static void add_to_point_set(const char *point, ssize_t len, PointsList **target_list) +{ + if (!points_list_contains(*target_list, point, len)) { + PointsList *pl = (PointsList*)malloc(sizeof(PointsList)); + pl->point = malloc(len + 1); + memcpy(pl->point, point, len); + pl->point[len] = '\0'; + pl->next = *target_list; + *target_list = pl; + } +} + +static int points_list_contains(const PointsList *list, const char *point, ssize_t len) +{ + const PointsList *pl = all_points; + while (pl != NULL) { + if (strncmp(pl->point, point, len) == 0) { + return 1; + } + pl = pl->next; + } + return 0; +} + diff --git a/viikko1/demoTehtava/test/tmc-check.h b/viikko1/demoTehtava/test/tmc-check.h new file mode 100644 index 0000000..8100cbb --- /dev/null +++ b/viikko1/demoTehtava/test/tmc-check.h @@ -0,0 +1,58 @@ + +#include +#include + +/***** Main API *****/ + +/** A shorthand to make one test suite with the given points */ +Suite* tmc_suite_create(const char *name, const char *points); + +/** A shorthand to make a one function testcase with the given points into a suite. */ +#define tmc_register_test(suite, tf, points) _tmc_register_test((suite), (tf), "" # tf, points) +void _tmc_register_test(Suite *s, TFun tf, const char *fname, const char *points); + +/** A shorthand to make one memory test for a test function with given parameters */ +#define tmc_register_memtest(tf, check_leaks, max_bytes_allocated) _tmc_register_memtest("" # tf, check_leaks, max_bytes_allocated) +void _tmc_register_memtest(const char *tf_name, int chek_leaks, int max_bytes_allocated); + +/** A shorthand for registering a test with memtest at the same time */ +#define tmc_register_test_with_memtest(suite, tf, points, check_leaks, max_bytes_allocated) tmc_register_test(suite, tf, points); tmc_register_memtest(tf, check_leaks, max_bytes_allocated) + +/** + * Runs a test suite so that tmc_test_results.xml and tmc_test_points.txt are created. + * + * To be called from main() after creating the Suite. + * + * If --print-available-points is given, it only outputs all available points + * (in an undefined order) to stdout and exits. + * + * Returns an error code that can be returned from main. + * Normally this will be 0 even if test fail. + */ +int tmc_run_tests(int argc, const char **argv, Suite *s); + + +/***** Low-level API *****/ + +/** + * Set the points of a test case. + * + * This is a lower level alternative to using tmc_register_test. + */ +void tmc_set_tcase_points(TCase *tc, const char *tc_name, const char *points); + +/** + * Set the points of a test suite + * + * This is a lower level alternative to using tmc_suite_create. + */ +void tmc_set_suite_points (Suite *s, const char *s_name, const char *points); + +/** Prints all registered points once (in no particular order) to the given file. */ +int tmc_print_available_points(FILE *f, char delimiter); +int tmc_print_memory_tests(FILE *f, char attr_delimiter, char line_delimiter); + +/** Prints lines like "[test] testname pointname1 pointname2" to the given file. */ +int tmc_print_test_points(FILE *f); +/** Prints lines with "[suite] suitename pointname1 pointname2" to given file */ +int tmc_print_suite_points(FILE *f); \ No newline at end of file diff --git a/viikko1/demoTehtava/test/tmc_available_points.txt b/viikko1/demoTehtava/test/tmc_available_points.txt new file mode 100644 index 0000000..89538e3 --- /dev/null +++ b/viikko1/demoTehtava/test/tmc_available_points.txt @@ -0,0 +1,2 @@ +[test] my_first_real_test 1.2 +[test] my_first_test 1.1 diff --git a/viikko1/demoTehtava/test/tmc_memory_test_info.txt b/viikko1/demoTehtava/test/tmc_memory_test_info.txt new file mode 100644 index 0000000..e69de29 diff --git a/viikko1/demoTehtava/test/tmc_test_results.xml b/viikko1/demoTehtava/test/tmc_test_results.xml new file mode 100644 index 0000000..f9cf2c6 --- /dev/null +++ b/viikko1/demoTehtava/test/tmc_test_results.xml @@ -0,0 +1,24 @@ + + + 2013-05-08 12:07:36 + + Test suite + + . + test-file.c:8 + my_first_test + 0 + my_first_test + Passed + + + . + test-file.c:14 + my_first_real_test + 0 + my_first_real_test + Passed + + + 0.000000 +