Summary

There’s plenty more we could do (such as actually checking whether the queue is empty/full before popping/pushing!), but that’s the end of this kata. Congratulations on learning how to apply Google Test/Google Mock to interaction-style TDD-ing in C++!

I used to really struggle writing tests in C++. BoostTest and Mockpp were the best solutions I had found to date. These are reasonable frameworks, but the ease of use of Google Test/Google Mock blows them away IMO.

In summary: I'm very impressed with both Google Test and Google Mock and look forward to using them more in the future.

Back to the beginning of this kata

googlemock project




Full source code:

QueueControl.h

#ifndef __QUEUE_CONTROL_H_
#define __QUEUE_CONTROL_H_

class QueueControl {
public:
        virtual ~QueueControl() {}
        virtual void Resume() = 0;
        virtual void Pause() = 0;

};

#endif

BoundedQueueTest.cpp

#include "BoundedQueue.h"
#include <gmock/gmock.h>

class MockQueueControl : public QueueControl {
public:
        MOCK_METHOD0(Resume, void());
        MOCK_METHOD0(Pause, void());

};

class BoundedQueueTest : public ::testing::Test {
public:
        BoundedQueueTest() : q(SetUpProducer(), SetUpConsumer(), BOUND) { 
                Mock::VerifyAndClear(&producer);
                Mock::VerifyAndClear(&consumer);
        }
        MockQueueControl& SetUpProducer() {
                EXPECT_CALL(producer, Resume());
                return producer;
        }
        MockQueueControl& SetUpConsumer() {
                EXPECT_CALL(consumer, Pause());
                return consumer;
        }
        MockQueueControl producer;
        MockQueueControl consumer;
        static const size_t BOUND = 3;
        BoundedQueue<int> q;
};

TEST_F(BoundedQueueTest, CreateResumesProducer) {
        EXPECT_CALL(producer, Resume());
        BoundedQueue<int> q(producer, consumer);
}

TEST_F(BoundedQueueTest, CreatePausesConsumer) {
        EXPECT_CALL(consumer, Pause());
        BoundedQueue<int> q(producer, consumer);
}

TEST_F(BoundedQueueTest, EnqueueResumesConsumer) {
        EXPECT_CALL(consumer, Resume());
        q.enqueue(5);
}

TEST_F(BoundedQueueTest, FirstInFirstOut) {
        q.enqueue(1);
        q.enqueue(2);
        ASSERT_EQ(1, q.dequeue());
        ASSERT_EQ(2, q.dequeue());
}

TEST_F(BoundedQueueTest, EnqueueResumesConsumerOnFirstItemOnly) {
        EXPECT_CALL(consumer, Resume()).Times(1);
        q.enqueue(5);
        q.enqueue(5);
}

TEST_F(BoundedQueueTest, DequeuePausesConsumerWhenQueueIsEmpty) {
        q.enqueue(3);
        q.enqueue(6);
        EXPECT_CALL(consumer, Pause());
        q.dequeue();
        q.dequeue();
}

TEST_F(BoundedQueueTest, EnqueuePausesProducerWhenQueueIsFull) {
        EXPECT_CALL(producer, Pause());
        q.enqueue(4);
        q.enqueue(4);
        q.enqueue(4);
}

BoundedQueue.h

#ifndef __bounded_queue_h_
#define __bounded_queue_h_

#include "QueueControl.h"
#include <queue>

template <typename T>
class BoundedQueue {
public:
public:
        BoundedQueue(QueueControl& producer, QueueControl& consumer, size_t size = 100)  
                : producer(producer), consumer(consumer), max_size(size) {
                producer.Resume();
                consumer.Pause();
        }
                
        void enqueue(const T& item) {
                q.push(item);
                if (q.size() == 1) {
                        consumer.Resume();
                }
                if (q.size() == max_size) {
                        producer.Pause();
                }
        }
                
        const T& dequeue() {
                const T& item = q.front();
                q.pop();
                if (q.size() == 0) {
                        consumer.Pause();
                }
                return item;
        }
                
private:
        QueueControl& consumer;
        QueueControl& producer;
        std::queue<T> q;
        size_t max_size;                
};

#endif

Makefile

LIB = /usr/local/lib

all: BoundedQueueTest
        ./BoundedQueueTest

BoundedQueueTest: BoundedQueueTest.o
        g++ -o BoundedQueueTest $(LIB)/libgmock_main.a $(LIB)/libgmock.a $(LIB)/libgtest.a BoundedQueueTest.o

BoundedQueueTest.o: BoundedQueueTest.cpp BoundedQueue.h QueueControl.h
        g++ -c BoundedQueueTest.cpp

clean: 
        rm *.o
        rm BoundedQueueTest

BoundedQueueKataSummary (last edited 2010-01-17 23:51:08 by ZhonJohansen)