Writing unit tests using Google Test

Its been a while since I last made a blog post I guess. In this post I want to talk about what I have been on since then. So, after we discarded the idea of using node.js and node-ffi framework to write our unit tests, David Humphrey was suggested by Ted to write unit tests using google test (gtest). Personally, I liked googletest to write our unit tests far more than writing them in javascript using node-ffi. Before our 0.3 release, all I did was just researched about how to use javascript to write unit tests. And then barely did I understand how the bindings were working. It was almost a non productive release for me because at the end of it, only thing I had was some learning and no actual work that I could submit although I was trying to get some work done. Also, there is very little documentation available on how to use these frameworks.

Using google test is much easier. I started off by reading the documentation available on gtest. The documentation is very helpful. It tells you everything you need to do get googletest working in your project. Since I started reading google documentation a little late after we decided to go with gtest, caitlin and rick already had the C++ bindings and the test fixture ready for us to use them in writing the actual unit tests. Writing unit tests in googletest is fairly easy and straightforward. And I also like the fact that you can disable a test by just adding DISABLED_ keyword before the test name. You can even run the disabled tests by invoking the  test program with –gtest_also_run_disabled_tests  flag. There is an advanced guide available on gtest to learn a whole lot of things about gtest framework.

I planned to start by writing some unit tests for timestamps in cues. I created a new directory called cue-timings in directory ‘unit’ to hold the webvtt test files that will be used in unit tests to test the timestamps. I added two files to start with.

WEBVTT

11:12:13.123 –> 14:15:16.456

WEBVTT

10:00:11.123 –> 11:00:13.456

And then I wrote a test case file to hold the actual unit tests. A test case file can hold one or many unit tests. gtest guide suggests us to group our tests into test case that reflect the structure of the tested code. The makefile.am was also needed to be modified to include the newly created unit tests. I added these lines where appropriate in the makefile.

  • CUETIMING_TESTS = \

cscuetimings_unittest

  • $(CUETIMING_TESTS)

and got an error below.

So, I went onto irc for some help. Presumably, my test case file was not being run. Rick told me to add the line below in makefile which, I guess, will tell the gtest that cscuetimings_unittest tests are located in file cscuetimings_unittest.cpp. And it worked beautifully then.

The pull request I sent has been reviewed by a couple of people and I am going to fix whatever needs to be fixed in that and also write the unit tests for test files that was decided in class today. Right now, I am not clear only about the BOM the character test files that i am going to test those. But I will try to finish the rest first and then ask someone else to help me on those ones.

Advertisements

0.3 release Unit testing

For our 0.3 release of implementing WebVTT parser, we had to do a bunch of things like finishing the cue text parsing part, implementing tests automation, writing unit tests etc. I was sort of interested in writing unit tests. So to begin with I pulled all the changes from humphd’s seneca branch and then build the parser using ./configure and make commands. It built successfully. Although I had a bit of trouble building it because I was not building it from root directory. So it was giving me all sorts of errors when I was trying to build from other directories and not from root. But I figured that out soon enough. Then I went ahead and installed the modules for node-ffi, ref, and ref-struct since we are using node-ffi for data bindings. It was a one command process. The command is “sudo npm install ffi ref ref-struct”.
To make myself a bit familiar with generating dynamic libraries and all, I used the factorial example provided by node-ffi team. The command I ran to test the factorial example was “gcc -dynamiclib -undefined suppress -flat_namespace factorial.c -o libfactorial.dylib”. And it worked with no errors. And then I was on IRC and dperit mentioned that he had a sample program to test the node ffi bindings done by caitp . I pulled his github repo and merged it with mine. But it had some errors probably because the export function in the unit-test.js file expects four variables and we were only passing three in sample.js. Anyways, so I was trying to study the code in unit-test.js and in sample.js because I had no previous experience working with javascript. And then I came across this another javascript framework named o2. The owner of this project also has blog posts about how to write unit tests in javascript and he goes on to explain how u can manage a queue of unit tests. Basically, what he has for his o2 project is a o2.unit.core.js file and the file manages a queue of tests, manages total number of failed and passed tests, the time interval between tests, completion status, etc. The test files from elsewhere can call the methods in this library to perform testing. I am looking to implement the same kind of approach for our project too. So, I have took their file and i am trying to modify it to suite our needs. For this, I have studied a lot of code. I suppose, it should also make the test automation easier for us.

0.2 release final update

Introduction
For the 0.2 release me and my partner Anh worked together. Here is the final update made by Anh to his github repo. To begin with, he created a new repository for us to work on C parser. Although I did forked his repo, for the most part we were not collaborating through github directly (e.g. we were not pushing and pulling changes on regular basis). What we did was I went into separate direction of working on ‘parsing cue text’ and he went into separate direction of working on cue timings and settings. And since he had better understanding of the spec, he was also integrating my work which I sent him through email. After we had bunch of work done, he made an update to his repo. As you can see here we only had two commits to our repo, both made by Anh. I was kind of scared of making commits directly to our github repo because I still don’t have attained a comfortable level on working with git. But, with upcoming releases, I will try to work more and more on git. Also, since my compiler had some problem, I was working off my matrix account. And making a significant progress, I just copied the file and email Anh. This is kind of an introduction to what I was working on and how I was working. Below is the details to what I was working on.

C Parser

As said earlier and also in my other blog post, I was working on cue payload. Here is the link to the file I was working on. It is not solely made by me. A lot in it has been added by Anh. I will just try to explain the code in it. Almost all of it has come from following the spec.
Node is used to represent a specific portion of cue text. There are two types of node objects leaf node and internal node. Leaf node objects are the ones that can not contain children objects and the internal node objects are the ones that can contain children objects. Tags such as class, italics, bold, underline, ruby, rubytext, and voice are extended using internal node class. While the timestamp tags and text strings are extended using internal node class.

Writing C Parser

So, I had started working on C parser. But, I have had some issues compiling C source code. Following is the screenshot of error.

Image

 

 

I researched a lot to figure out the possible reason of the failure (problem linking libraries, trying -m32 to change compilation environment) but none of them seemed to work. So, I started working on my Windows machine rather than wasting a lot of time on fixing this.

The code I was working on for the majority of the time was the cue payload (text). It essentially covers one of the major portion of the parser code. So, I will be blogging about cue text. If anything else, I think, should be included in the blogs, I will blog about it. To start with, Kyle spec was a big help. It is very readable and understandable. Parsing cue text includes you deal with a couple of things. One is the escape characters and the another is text tags. According to the spec, cue text may have newlines but not a blank line. As pointed by Kyle, one way to overcome this is by inserting a space in between two new line characters. This will let you have a blank line within cue text. In cue text, you cannot have an ‘&’ sign and ‘<‘ sign. Here is a table of escape sequence for special characters taken from Kyle’s blog.

Escape sequences

Name Character Escape Sequence
Ampersand & &amp;
Less-than < &lt;
Greater-than > &gt;
Left-to-right mark   &lrm;
Right-to-left mark   &rlm;
Non-breaking space    &nbsp;

Another thing you have to deal with in cue text is the ‘Text Tags’. You can have a timestamp tag within the cue text provided the time is greater than the start time of the cue and less than the end time of the cue. Other text tags you can have in the cue text are common class tags, italics tags, underline tags, ruby tags, ruby text tags, and voice tags.

This is the berief explanation of what I am working on and that it will be implemented in the parser. I will post one more blog post when I am done with it. A little trouble I had working on the C parser was that it had been quite long since I had studied or used C language. So, I didn’t quite remember the data types and the syntax of C although it is very simple.

WebVTT Parser in C

To implement WebVTT parser, I went through the spec written by Kyle and also the pseudo code he wrote for the parser. The document is really insightful. Me and Anh are working together to write the parser. Before I started working on it, he already had a version of it released in his Github repo. He used Raplh’s code for parser as basis for the final version. The version he has right now tests, for the most part, the webvtt files that have correct syntax. I have started to work on the coding part. For now, I am trying to implement the file structure part of the spec. Following is the method that I am trying to make follow the spec. I will post another blog once I have made some considerable progress and I am going to start working on another part of the spec.

int hasRequiredFileIdentifier(webvtt_parser *ctx) {

  char *p = ctx->buffer;

  // Check for signature

  //if the length of the buffer is less than 6 chracters, print error

  if (ctx->length < 6) {

    fprintf(stderr, “Too short. Not a webvtt file\n”);

    return 0;

  }

  //check if the file has BOM characters in the beginning, do following

  if (p[0] == (char)0xef && p[1] == (char)0xbb && p[2] == (char)0xbf) {

    fprintf(stderr, “Byte order mark\n”);

    //move the offset by 3

    ctx->offset += 3;

    //check again if the buffer has less than 9 charcters including BOM characters, print error

    if (ctx->length < 9) {

      fprintf(stderr, “Too short. Not a webvtt file\n”);

      return 0;

    }

  }

  if (memcmp(p + ctx->offset, “WEBVTT”, 6)) {

    fprintf(stderr, “Bad magic. Not a webvtt file?\n”);

    return 0;

  }

  ctx->offset += 6;

  /*

  if(memcmp(p + ctx->offset, “\t”, 7) || memcmp(p + ctx->offset, “\ “, 7)){

    fprintf(stderr, “Bad magic. Not a webvtt file?\n”);

    return 0;

  }

  */

  fprintf(stderr, “Found signature\n”);

  return 1;

}

Learning Git and WebVTT Test Suite for DPS909

Wrote some tests for webvtt test suite.

Bad files

/*

when missing a new line between a line and cue timing
*/
WEBVTT

00:11.000 –> 00:13.000 vertical:rl
<v Roger Bingham>We are in New York City
00:13.000 –> 00:16.000
<v Roger Bingham>We’re actually at the Lucern Hotel, just down the street

/*
Line break between two text lines
*/
WEBVTT

00:13.000 –> 00:16.000
Introduction
Hello world!

/*
Missing cue identifier after WEBVTT and before text line
It should fail
*/
WEBVTT

Hello world!

 

Good Files

/*
Missing the text line in between two cue identifiers
*/
WEBVTT

00:00.000 –> 01:24.000

00:00.000 –> 00:44.000

 

/*
A bunch of new lines at the bottom of file
*/
WEBVTT

00:13.000 –> 00:16.000
Introduction
Hello world!

 

Regarding GIT, I am still trying to get used to it. As of now, I still do forget some commands sometimes. But using them frequently definitely helps. Listed below are some git commands and their description as per my understanding

Git clone – copies the entire history of a repository.

Git status – shows any changes made in current branch

Git branch – shows the current branch with *

git branch -s – lists all branches

git branch newbranch – creates a new branch ‘newbranch’ from the current branch

git checkout newbranch – switch to newbranch

git remote add <shortname> git-url – adds a new remote branch to your local repo

git fetch <shortname> – fetch all data from remote branch

git checkout – – reverse an action

git merge ‘branchname’ – merge two branches and move the head of current branch to new commit

git pull <remote> <branch> – copy a remote commit

git push <remote> <branch> – creates a new commit and merge a remote branch into your current branch