The week was spent trying to finish up the implementation of the caching mechanism. Overall, I had no major issues regarding the implementation, but there was one thing that caught me unexpectedly.

Whenever there are any modifications to the cache, such as adding new entries or expiration of entries, a so-called Replace event is invoked. This event can be caught in our own self-defined Strategy class which is responsible for flushing the expired cached files to the user’s storage at the occurrence of such event, as mentioned before. As a reminder, the expiration strategies that is used in the application’s cache is Least Recently Used (LRU) and Time-based. For a Time-based strategy, in our case, it is expected that after a certain amount of time a particular cache entry should automatically be expired and subsequently flush to the user’s storage.

Poco’s Cache Framework, however, does not utilize a background process to periodically check for expired cache entries after the predetermined time. It is only done whenever the cache is accessed and its contents are being modified, i.e adding new entries to the cache. That’s when the Replace event is invoked, and the entries, that had already went pass their expected lifetime, would be given to a method in our Strategy class in order to do something to them before they are actually removed. Reading from the cache does not invoke the Replace event as there are no modifications to the cache contents. It is possible though to tell Poco to force invoke the Replace event anytime using one of the class methods of the cache.

I found out about this by reading the slides regarding their cache framework on their website, and then did small experiments to see it for myself. This is actually a no biggie, in fact I think this is better as we have control of when we want to actually expire the cache entries. I just thought of sharing it here for those who may not have realized it yet like I did.

Now that I have finished up the implementation, it is important for me to test it out to ensure that it is working as expected. The cURL requests testing I had already done to test the REST endpoints is not sufficient enough for testing the internals of the cache. For that, it is about time to use a C++ Testing Framework, which is none other than Google’s! In addition to having unit tests, it also has a mocking framework in order for you to mock the classes in your codebase.

What is mocking actually? Basically, there is always a part of the application where it is dependent on an external service for its required functionalities, like cloud storage and the database in our case. These services are important in the production of our application, but they could slow us down when we want test the application. It is a requirement that all tests should run considerably fast. Let’s go through an example, say we have a class that is responsible for mounting and unmounting a remote storage:

class CloudInterface {
public:

void mountStorage(const std::string &uri, const std::string &mountpoint);
void unmountStorage(const std::string &mountpoint);

};

This class would be used in a method of another of our self-defined class:

class MyClass {
public:

void foo() {

CloudInterface cloud;
cloud.mountStorage(uri, mountpoint);

}
};

If the CloudInterface class is not mocked, then everytime we run the test for foo(), we would have to wait for the mounting operation to finish before the remaining of the method can be executed. Here is how we would mock the class using Google’s Mock Framework:

#include <gmock/gmock.h>

class MockCloudInterface : public CloudInterface {
public:


MOCK_METHOD2(mountStorage, void(const std::string &url, const std::string &mountpoint));
MOCK_METHOD1(unmountStorage, void(const std::string &mountpoint));


};

So we have the mock class definining the interfaces of the CloudInterface class to be mocked. Do note that the interfaces in CloudInterface need to be virtual in order to be mocked. Using Dependancy Injection, we could pass in the MockCloudInterface class to MyClass, and since the interfaces are the same nothing would break:

class MyClass {
public:
MyClass(std::unique_ptr<CloudInterface> cloud) : _cloud(std::move(cloud)) { }

void foo() {

_cloud->mountStorage(uri, mountpoint);

}

private:
std::unique_ptr<CloudInterface> _cloud;
};

Depending on the test, we would need to specify the behaviour of the mocked method, such as how many times it is expected to be called and what it should return:

TEST(MyClass, foo) {

MockCloudInterface cloud;

EXPECT_CALL(cloud, mountStorage(_,_)).Times(1).WillOnce(Return());

 

MyClass myClass(cloud);

myClass.foo();

}

And that’s it! It was good to have this Testing Framework come into play. Although I have not done much with it yet, I’m already reaping its benefits. It kinda forces me to have sufficiently good design in the codebase, so that I could easily test out the classes and the functionalities. I may need to do some refactoring for that. I’ll see you in the next blog post.


0 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.