From a8561778e964503223816ed1f9eb81d7bee69d73 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Mon, 13 Mar 2017 21:30:37 -0400 Subject: [PATCH] Added C99 Solution --- c99/GildedRose.c | 90 +++++++++++++++++++++++++++++++++++++++ c99/GildedRose.h | 9 ++++ c99/GildedRoseTextTests.c | 43 +++++++++++++++++++ c99/Makefile | 51 ++++++++++++++++++++++ c99/README.md | 41 ++++++++++++++++++ c99/test_main.c | 31 ++++++++++++++ c99/test_rose.c | 34 +++++++++++++++ 7 files changed, 299 insertions(+) create mode 100644 c99/GildedRose.c create mode 100644 c99/GildedRose.h create mode 100644 c99/GildedRoseTextTests.c create mode 100644 c99/Makefile create mode 100644 c99/README.md create mode 100644 c99/test_main.c create mode 100644 c99/test_rose.c diff --git a/c99/GildedRose.c b/c99/GildedRose.c new file mode 100644 index 00000000..afb97bbe --- /dev/null +++ b/c99/GildedRose.c @@ -0,0 +1,90 @@ +#include +#include "GildedRose.h" + +Item* +init_item(Item* item, const char *name, int sellIn, int quality) +{ + item->sellIn = sellIn; + item->quality = quality; + item->name = strdup(name); + + return item; +} + +void update_quality(Item items[], int size) +{ + int i; + + for (i = 0; i < size; i++) + { + if (strcmp(items[i].name, "Aged Brie") && strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].quality > 0) + { + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + + if (!strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].sellIn < 11) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) + { + if (strcmp(items[i].name, "Aged Brie")) + { + if (strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].quality > 0) + { + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + items[i].quality = items[i].quality - items[i].quality; + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } +} diff --git a/c99/GildedRose.h b/c99/GildedRose.h new file mode 100644 index 00000000..78d54a08 --- /dev/null +++ b/c99/GildedRose.h @@ -0,0 +1,9 @@ +typedef struct +{ + char *name; + int sellIn; + int quality; +} Item; + +extern Item* init_item(Item* item, const char *name, int sellIn, int quality); +extern void update_quality(Item items[], int size); diff --git a/c99/GildedRoseTextTests.c b/c99/GildedRoseTextTests.c new file mode 100644 index 00000000..d200ca0c --- /dev/null +++ b/c99/GildedRoseTextTests.c @@ -0,0 +1,43 @@ +#include +#include "GildedRose.h" + +int +print_item(Item *item) +{ + return printf("%s, %d, %d\n", item->name, item->sellIn, item->quality); +} + +int main() +{ + Item items[9]; + int last = 0; + int day; + int index; + + init_item(items + last++, "+5 Dexterity Vest", 10, 20); + init_item(items + last++, "Aged Brie", 2, 0); + init_item(items + last++, "Elixir of the Mongoose", 5, 7); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", 0, 80); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", -1, 80); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 15, 20); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 10, 49); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 5, 49); + // this Conjured item doesn't yet work properly + init_item(items + last++, "Conjured Mana Cake", 3, 6); + + puts("OMGHAI!"); + + for (day = 0; day <= 30; day++) + { + printf("-------- day %d --------\n", day); + printf("name, sellIn, quality\n"); + for(index = 0; index < last; index++) { + print_item(items + index); + } + + printf("\n"); + + update_quality(items, last); + } + return 0; +} diff --git a/c99/Makefile b/c99/Makefile new file mode 100644 index 00000000..113d1552 --- /dev/null +++ b/c99/Makefile @@ -0,0 +1,51 @@ +# Makefile for building the kata file with the Google Testing Framework +# +# SYNOPSIS: +# +# make [all] - makes everything, runs tests +# make TARGET - makes the given target. +# make clean - removes all files generated by make. +# make memtest - run memory leak analysis + +# The _POSIX_C_SOURCE definition prevents the compiler from throwing warnings +CFLAGS = `pkg-config --cflags check` -g --std=c99 -D_POSIX_C_SOURCE=200809L +LIBS = `pkg-config --libs check` + +# All files that should be part of your test should start with 'test_' +TEST_SRC = $(wildcard test_*.c) +TEST_BASE = $(basename ${TEST_SRC}) +TEST_OBJECTS = $(addsuffix .o, ${TEST_BASE}) + +# All files that should be part of your main program should start with 'gilded_' +PROG_SRC = $(wildcard gilded_*.c) +PROG_BASE = $(basename ${PROG_SRC}) +PROG_OBJECTS = $(addsuffix .o, ${PROG_BASE}) + +OBJECT_UNDER_TEST = GildedRose.o ${PROG_OBJECTS} + +# This is the test application. You can run this program to see your test output +TEST_APP = test_gildedrose + + +# This will generate output for several products over a course of several days. +# You can run this application to build golden rule tests +GOLDEN_APP = golden_rose + +all: ${TEST_APP} ${GOLDEN_APP} + ./${TEST_APP} + +${TEST_APP}: ${TEST_OBJECTS} ${OBJECT_UNDER_TEST} + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) + +${GOLDEN_APP}: GildedRoseTextTests.o ${OBJECT_UNDER_TEST} + $(CC) $(CFLAGS) -o $@ $^ + +# If you're not on a mac, you should run memtest (in fact, consider adding it to the 'all' target). +# If you're on a mac, complain to apple for breaking an important development tool. +memtest: ${TEST_APP} + valgrind --leak-check=full --error-exitcode=1 ./${TEST_APP} --nofork + +clean: + rm -f *.o + rm -f ${TEST_APP} + rm -f ${GOLDEN_APP} diff --git a/c99/README.md b/c99/README.md new file mode 100644 index 00000000..ec2cd02e --- /dev/null +++ b/c99/README.md @@ -0,0 +1,41 @@ +# Gilded Rose, C99 Edition + +The command "make" will build and run your tests, as well as build the program +golden_rose, which can serve as the basis for a golden-rule test. + + +## Assumptions + - gnu make and a C compiler (like gcc) is installed on your system and is in the PATH + - The check unit testing library is installed on your system (https://libcheck.github.io/check/) + - pkg-config is installed on your system + +## Usage + - Run `make` to build the program and run all tests + - Files which contain tests should be named `test_*.c` They will automatically + be included in your test suite. + - `GildedRose.h` should not be modified. The Goblin threat is real. + - New program logic may be included in files named `gilded_*.c` which will + automatically be included in both your tests and the final program. + +## Golden Rule tests + - The program `golden_rose` will generate text output. If you capture this + output after your first `make` you can use this as a reference for a golden + rule test. + - You can test your work against this reference by directing the output of your + current golden_rose to a file and using the `diff` utility to compare that + to the reference file you created above. + - To avoid the Goblin threat you can use `git diff GildedRose.h`, which should + have no output if you have left the precious Item structure unchanged. + +## Notes + - This project is tweaked to run on Linux systems, and will mostly work on Macs. + With some changes to the Makefile it can be made to run on BSD systems with + BSD make. An adventurous person could also get it to run on Windows. + - If you are working on a Macintosh computer you cannot run the memtest target, + because valgrind and OS X don't play nice any more. If you want to use the + memory checker OS X does run docker as a first class citizen. + - If you don't have pkg-config on your system, the only changes you'll need to + make are for the requirements of the check library. Mostly you need to + set the appropriate flags for threaded binaries, which may include some + special linker flags. The libcheck documentation will cover what you need + if you want to undertake this change. diff --git a/c99/test_main.c b/c99/test_main.c new file mode 100644 index 00000000..0d5a0de0 --- /dev/null +++ b/c99/test_main.c @@ -0,0 +1,31 @@ +#include +#include +#include + +Suite *suite_rose(void); + +int main(int argc, char **argv) +{ + Suite *s; + SRunner *runner; + int number_fails; + int forkme = 1; + + if (argc > 1 && strcmp(argv[1], "--nofork") == 0) { + forkme = 0; + } + + s = suite_rose(); + runner = srunner_create(s); + + if (0 == forkme) { + srunner_set_fork_status(runner, CK_NOFORK); + } + + srunner_run_all(runner, CK_NORMAL); + number_fails = srunner_ntests_failed(runner); + + srunner_free(runner); + + return number_fails; +} diff --git a/c99/test_rose.c b/c99/test_rose.c new file mode 100644 index 00000000..30cc7544 --- /dev/null +++ b/c99/test_rose.c @@ -0,0 +1,34 @@ +#include +#include "GildedRose.h" + + + +START_TEST(roseFoo) +{ + Item items[1]; + init_item(items, "foo", 0, 0); + update_quality(items, 1); + + ck_assert_str_eq("fixme", items[0].name); +} +END_TEST + +TCase *tcase_rose(void) +{ + TCase *tc; + + tc = tcase_create("gilded-rose"); + tcase_add_test(tc, roseFoo); + + return tc; +} + +Suite *suite_rose(void) +{ + Suite *s; + + s = suite_create("characterization-tests"); + suite_add_tcase(s, tcase_rose()); + + return s; +}