Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Inital commit
  • Loading branch information
john committed Mar 23, 2018
1 parent 8789e27 commit d9c77dd
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 2 deletions.
22 changes: 22 additions & 0 deletions Makefile
@@ -0,0 +1,22 @@
CC=gcc
CFLAGS=-g -std=c99
SUT_DIR=simple_unit_test
OFILES=queue.o queue_test.o $(addprefix $(SUT_DIR)/, simple_unit_test.o)

all: queue_test

queue_test: $(OFILES)
$(CC) -o $@ $(OFILES)

queue.o: queue.c
$(CC) $(CFLAGS) -c $<

queue_test.o: queue_test.c
$(CC) $(CFLAGS) -c $<

simple_unit_test.o: $(SUT_DIR)/simple_unit_test.c
$(CC) $(CFLAGS) -c $<

clean:
@echo "Cleaning..."
rm -f *.o $(SUT_DIR)/*.o queue_test
50 changes: 48 additions & 2 deletions README.md
@@ -1,2 +1,48 @@
# queue
A queue for you
# A queue for you!

This is dead a simple queue implementation that only supports integers and
has the following interface:
```c
/* Create a brand new queue out of thin air. */
Queue* create_queue();

/* Take a peek at what's at the front of the queue. */
int front(Queue* queue);

/* Take a peek at what's at the back of the queue. */
int back(Queue* queue);

/* Enqueue an integer to the front of the queue. */
void enqueue(Queue* queue, int data);

/* Dequeue an integer from the queue. */
int dequeue(Queue* queue);

/* Send the queue into non-existance. */
void destroy_queue(Queue* queue);

/* Print out all of the elements of the queue. */
void print_queue(Queue* queue);

/* Determine how many elements are in the queue. */
size_t size(Queue* queue);

/* Determine if the queue is empty like my soul. */
int is_empty(Queue* queue);
```
## How to use
To use this wonderful queue, just include `"queue.h"` and you're good to go!
## Testing
If you'd like to verify this queue implementation actually works, you can run
the unit tests! All the unit tests are located in `queue_test.c` and make use
of my amazing `simple_unit_test` testing framework.
To run the unit tests:
```c
$ make
$ ./queue_test
```
60 changes: 60 additions & 0 deletions queue.c
@@ -0,0 +1,60 @@
#include <assert.h>
#include <stdlib.h>
#include "queue.h"

Queue* create_queue() {
Queue* queue = malloc(sizeof(Queue));
queue->size = 0;
queue->head = NULL;
queue->tail = NULL;
return queue;
}

int front(Queue* queue) {
assert(!is_empty(queue));
return queue->head->data;
}

int back(Queue* queue) {
assert(!is_empty(queue));
return queue->tail->data;
}

void enqueue(Queue* queue, int data) {
QueueNode* node = malloc(sizeof(QueueNode));
node->data = data;
node->next = queue->head;
if (is_empty(queue)) {
queue->head = queue->tail = node;
} else {
queue->tail->next = node;
queue->tail = node;
}
queue->size++;
}

int dequeue(Queue* queue) {
assert(!is_empty(queue));
int data = front(queue);
QueueNode* dequeued_node = queue->head;
queue->head = queue->head->next;
free(dequeued_node);
queue->size--;
return data;
}

void destroy_queue(Queue* queue) {
return;
}

void print_queue(Queue* queue) {
return;
}

size_t size(Queue* queue) {
return queue->size;
}

int is_empty(Queue* queue) {
return queue->size == 0;
}
44 changes: 44 additions & 0 deletions queue.h
@@ -0,0 +1,44 @@
#ifndef __QUEUE_H
#define __QUEUE_H

#include <stdlib.h>

typedef struct QueueNode {
int data;
struct QueueNode* next;
} QueueNode;

typedef struct Queue {
size_t size;
QueueNode* head;
QueueNode* tail;
} Queue;

/* Create a brand new queue out of thin air. */
Queue* create_queue();

/* Take a peek at what's at the front of the queue. */
int front(Queue* queue);

/* Take a peek at what's at the back of the queue. */
int back(Queue* queue);

/* Enqueue an integer to the front of the queue. */
void enqueue(Queue* queue, int data);

/* Dequeue an integer from the queue. */
int dequeue(Queue* queue);

/* Send the queue into non-existance. */
void destroy_queue(Queue* queue);

/* Print out all of the elements of the queue. */
void print_queue(Queue* queue);

/* Determine how many elements are in the queue. */
size_t size(Queue* queue);

/* Determine if the queue is empty like my soul. */
int is_empty(Queue* queue);

#endif
57 changes: 57 additions & 0 deletions queue_test.c
@@ -0,0 +1,57 @@
#include <stdio.h>
#include <stdlib.h>

#include "./simple_unit_test/simple_unit_test.h"
#include "queue.h"


int test_create_queue() {
Queue* queue = create_queue();
CHECK(assert_not_null(queue));
CHECK(assert_equal_int(size(queue), 0));
CHECK(assert_true(is_empty(queue)));
destroy_queue(queue);
return 0;
}

int test_enqueue() {
Queue* queue = create_queue();

enqueue(queue, 1);
CHECK(assert_equal_int(size(queue), 1));
CHECK(assert_false(is_empty(queue)));
CHECK(assert_equal_int(front(queue), 1));
CHECK(assert_equal_int(back(queue), 1));

enqueue(queue, 2);
CHECK(assert_equal_int(size(queue), 2));
CHECK(assert_equal_int(front(queue), 1));
CHECK(assert_equal_int(back(queue), 2));
return 0;
}

int test_dequeue() {
Queue* queue = create_queue();

enqueue(queue, 1);
dequeue(queue);
CHECK(assert_true(is_empty(queue)));

for (int i = 1; i <= 10; i++) {
enqueue(queue, i);
}

dequeue(queue);
dequeue(queue);
CHECK(assert_equal_int(size(queue), 8));
CHECK(assert_equal_int(front(queue), 3));
CHECK(assert_equal_int(back(queue), 10));
return 0;
}

int main() {
run_test("test_create_queue", test_create_queue);
run_test("test_enqueue", test_enqueue);
run_test("test_dequeue", test_dequeue);
return 0;
}
52 changes: 52 additions & 0 deletions simple_unit_test/simple_unit_test.c
@@ -0,0 +1,52 @@
#include "simple_unit_test.h"


void run_test(const char* test_name, TestProcedure procedure) {
printf("%s======== Running test: %s =========%s\n", KCYN, test_name, KWHT);
int test_result = procedure();
if (test_result > 0) {
fprintf(stderr, "TEST %sFAILED%s: Exiting\n", KRED, KWHT);
} else {
printf("TEST %sPASSED%s\n", KGRN, KWHT);
}
}

int assert_equal_int(int actual, int expected) {
if (actual != expected) {
printf("Assertion error: expected %d, but got %d\n", expected, actual);
return 1;
}
return 0;
}

int assert_true(int val) {
if (!val) {
printf("Assertion error: %d is not true\n", val);
return 1;
}
return 0;
}

int assert_false(int val) {
if (val) {
printf("Assertion error: %d is not false\n", val);
return 1;
}
return 0;
}

int assert_null(void* ptr) {
if (ptr != NULL) {
printf("Assertion error: %p is not NULL\n", ptr);
return 1;
}
return 0;
}

int assert_not_null(void* ptr) {
if (ptr == NULL) {
printf("Assertion error: %p value is not non-NULL\n", ptr);
return 1;
}
return 0;
}
38 changes: 38 additions & 0 deletions simple_unit_test/simple_unit_test.h
@@ -0,0 +1,38 @@
#ifndef __SIMPLE_UNIT_TEST_H
#define __SIMPLE_UNIT_TEST_H

#include <stdio.h>
#include <stdlib.h>

#define CHECK(val) if (val) { printf("Line number %d\n", __LINE__); return 1; }
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"


typedef int (*TestProcedure)(void);

/* Run a test with the given name and procedure. */
void run_test(const char* test_name, TestProcedure procedure);

/* Assert that two integers are equal. */
int assert_equal_int(int actual, int expected);

/* Assert that a value is true. */
int assert_true(int val);

/* Assert that a value is false. */
int assert_false(int val);

/* Assert that a pointer is null. */
int assert_null(void* ptr);

/* Assert that a pointer is not null. */
int assert_not_null(void* ptr);

#endif

0 comments on commit d9c77dd

Please sign in to comment.