diff --git a/lib/stack.c b/lib/stack.c index f90ebfa..373fd6a 100644 --- a/lib/stack.c +++ b/lib/stack.c @@ -38,7 +38,10 @@ void delete_stack(struct stack *stack) { } bool empty(struct stack *stack) { - return(stack->card->value == NO_VALUE); + return(stack->card->value == NO_VALUE && + stack->card->suit == NO_SUIT && + stack->card->face == NO_FACE && + !stack->next); } int length(struct stack *stack) { @@ -59,29 +62,32 @@ int length(struct stack *stack) { void push(struct stack **stack, struct card *card) { struct stack *new_stack = NULL; - if (empty(*stack)) { - (*stack)->card = card; - } else { - allocate_stack(&new_stack); - new_stack->card = card; - new_stack->next = (*stack); - *stack = new_stack; + if (card) { + if (empty(*stack)) { + (*stack)->card = card; + } else { + allocate_stack(&new_stack); + new_stack->card = card; + new_stack->next = (*stack); + *stack = new_stack; + } } } -/* FIXME: hack hack hack to get the old coordinates after clearing the structure */ struct stack *pop(struct stack **stack) { struct stack *popped_entry = NULL; if(!empty(*stack)) { popped_entry = *stack; + /* As what's considered an empty stack is an allocated and initialized + * stack structure, we make sure pop doesn't make '*stack' point to NULL + * when popping a stack with only 1 element. */ if (length(*stack) == 1) { - int start_y, start_x; - start_y = (*stack)->card->frame->start_y; - start_x = (*stack)->card->frame->start_x; allocate_stack(stack); initialize_stack(*stack); - set_frame((*stack)->card->frame, start_y, start_x); + set_frame((*stack)->card->frame, + (*stack)->card->frame->start_y, + (*stack)->card->frame->start_x); } else { *stack = (*stack)->next; } @@ -99,8 +105,9 @@ void move_card(struct stack **origin, struct stack **destination) { if (!empty(*destination) && maneuvre_stack(*destination)) { (*origin)->card->frame->start_y++; } - stack = pop(origin); - push(destination, stack->card); + if ((stack = pop(origin))) { + push(destination, stack->card); + } return; } diff --git a/test/stack_test.c b/test/stack_test.c index 8d9729f..934e6aa 100644 --- a/test/stack_test.c +++ b/test/stack_test.c @@ -1,8 +1,330 @@ #include #include "../lib/stack.h" +#include "test_helper.h" -void test_stack() { - assert(true); +void test_initialize_stack() { + struct stack *stack; + + allocate_stack(&stack); + initialize_stack(stack); + + assert(stack->card->value == NO_VALUE); + assert(!stack->next); + + delete_stack(stack); + + return; +} + +void test_empty_on_empty_stack() { + struct stack *stack; + + allocate_stack(&stack); + initialize_stack(stack); + + assert(empty(stack)); + + delete_stack(stack); + + return; +} + +void test_empty_on_non_empty_stack() { + struct stack *stack; + struct card *card; + + allocate_card(&card); + initialize_card(card); + set_card(card, ACE, SPADES, EXPOSED, 0, 0); + + allocate_stack(&stack); + initialize_stack(stack); + push(&stack, card); + + assert(!empty(stack)); + + delete_stack(stack); + + return; +} + +void test_push_on_empty_stack() { + struct stack *stack; + struct card *card; + + allocate_card(&card); + initialize_card(card); + set_card(card, ACE, SPADES, EXPOSED, 0, 0); + + allocate_stack(&stack); + initialize_stack(stack); + push(&stack, card); + + assert(stack->card == card); + assert(!stack->next); + + delete_stack(stack); + + return; +} + +void test_push_on_non_empty_stack() { + struct stack *stack; + struct card *card_0, *card_1; + + allocate_card(&card_0); + allocate_card(&card_1); + initialize_card(card_0); + initialize_card(card_1); + set_card(card_0, ACE, SPADES, EXPOSED, 0, 0); + set_card(card_1, ACE, HEARTS, EXPOSED, 0, 0); + + allocate_stack(&stack); + initialize_stack(stack); + push(&stack, card_0); + push(&stack, card_1); + + assert(stack->card == card_1); + assert(stack->next->card == card_0); + assert(!stack->next->next); + + delete_stack(stack); + + return; +} + +void test_push_null_on_empty_stack() { + struct stack *stack, *old_stack; + + allocate_stack(&stack); + initialize_stack(stack); + old_stack = stack; + push(&stack, NULL); + + assert(stack->card == old_stack->card); + assert(stack->next == NULL); + + delete_stack(stack); + + return; +} + +void test_push_null_on_non_empty_stack() { + struct stack *stack, *old_stack; + struct card *card; + + allocate_card(&card); + initialize_card(card); + set_card(card, ACE, SPADES, EXPOSED, 0, 0); + + allocate_stack(&stack); + initialize_stack(stack); + old_stack = stack; + push(&stack, NULL); + + assert(stack->card == old_stack->card); + assert(stack->next == old_stack->next); + + delete_stack(stack); + + return; +} + +void test_pop_on_empty_stack() { + struct stack *stack; + struct stack *popped_entry; + + allocate_stack(&stack); + allocate_stack(&popped_entry); + initialize_stack(stack); + popped_entry = pop(&stack); + + assert(empty(stack)); + assert(!popped_entry); + + delete_stack(stack); + + return; +} + +void test_pop_on_stack_with_one_element() { + struct stack *stack, *popped_entry; + struct card *card; + + allocate_card(&card); + initialize_card(card); + set_card(card, ACE, SPADES, EXPOSED, 0, 0); + + allocate_stack(&stack); + initialize_stack(stack); + push(&stack, card); + popped_entry = pop(&stack); + + assert(empty(stack)); + assert(popped_entry->card == card); + assert(!popped_entry->next); + + delete_stack(stack); + + return; +} + +void test_pop_on_stack_with_more_than_one_element() { + struct stack *stack, *old_stack_next, *popped_entry; + struct card *card[3]; + + allocate_stack(&stack); + initialize_stack(stack); + for (int i = 0; i < 3; i++) { + allocate_card(&card[i]); + initialize_card(card[i]); + set_card(card[i], ACE, SPADES, EXPOSED, 0, 0); + push(&stack, card[i]); + } + old_stack_next = stack->next; + popped_entry = pop(&stack); + + assert(length(stack) == 2); + assert(stack == old_stack_next); + assert(popped_entry->card == card[2]); + assert(!popped_entry->next); + + delete_stack(stack); + + return; +} + +void test_move_card_from_empty_stack_to_empty_stack() { + struct stack *origin, *destination, + *new_origin, *new_destination, + *origin_duplicate, *destination_duplicate; + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + new_origin = origin; + new_destination = destination; + origin_duplicate = duplicate_stack(origin); + destination_duplicate = duplicate_stack(destination); + move_card(&new_origin, &new_destination); + + assert(origin == new_origin); + assert(stacks_equal(origin, origin_duplicate)); + assert(destination == new_destination); + assert(stacks_equal(destination, destination_duplicate)); + + delete_stack(origin); + delete_stack(destination); + + return; +} + +void test_move_card_from_empty_stack_to_non_empty_stack() { + struct stack *origin, *destination, + *new_origin, *new_destination, + *origin_duplicate, *destination_duplicate; + struct card *card; + + allocate_card(&card); + initialize_card(card); + set_card(card, ACE, SPADES, EXPOSED, 0, 0); + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + new_origin = origin; + new_destination = destination; + push(&new_destination, card); + origin_duplicate = duplicate_stack(origin); + destination_duplicate = duplicate_stack(destination); + move_card(&new_origin, &new_destination); + + assert(origin == new_origin); + assert(stacks_equal(origin, origin_duplicate)); + assert(destination == new_destination); + assert(stacks_equal(destination, destination_duplicate)); + + delete_stack(origin); + delete_stack(destination); + + return; +} + +void test_move_card_from_non_empty_stack_to_empty_stack() { + struct stack *origin, *destination; + struct card *card; + + allocate_card(&card); + initialize_card(card); + set_card(card, ACE, SPADES, EXPOSED, 0, 0); + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + push(&origin, card); + move_card(&origin, &destination); + + assert(empty(origin)); + assert(length(destination) == 1); + assert(cards_equal(destination->card, card)); + + delete_stack(origin); + delete_stack(destination); + + return; +} + +void test_move_card_from_non_empty_stack_to_non_empty_stack() { + struct stack *origin, *destination; + struct card *card[2]; + + allocate_card(&card[0]); + allocate_card(&card[1]); + initialize_card(card[0]); + initialize_card(card[1]); + set_card(card[0], ACE, SPADES, EXPOSED, 1, 1); + set_card(card[1], KING, HEARTS, EXPOSED, 1, 1); + + allocate_stack(&origin); + allocate_stack(&destination); + initialize_stack(origin); + initialize_stack(destination); + push(&origin, card[0]); + push(&destination, card[1]); + move_card(&origin, &destination); + + assert(empty(origin)); + assert(length(destination) == 2); + assert(cards_equal(destination->card, card[0])); + assert(cards_equal(destination->next->card, card[1])); + + delete_stack(origin); + delete_stack(destination); + + return; +} + +void test_stack() { + test_initialize_stack(); + + test_empty_on_empty_stack(); + test_empty_on_non_empty_stack(); + + test_push_on_empty_stack(); + test_push_on_non_empty_stack(); + test_push_null_on_empty_stack(); + + test_pop_on_empty_stack(); + test_pop_on_stack_with_one_element(); + test_pop_on_stack_with_more_than_one_element(); + + test_move_card_from_empty_stack_to_empty_stack(); + test_move_card_from_empty_stack_to_non_empty_stack(); + test_move_card_from_non_empty_stack_to_empty_stack(); + test_move_card_from_non_empty_stack_to_non_empty_stack(); return; }