Much Ado About Nothing

When I left off last week I (and a few others) was having frustrating troubles using node ffi to create bindings to the Webvtt library. It is with great happiness that I say that those troubles are now over! (due to that path being abandoned…) Instead our class moved towards doing testing in C++ with googletest (the ctypes ffi option was also dropped).  And so this weekend I moved forward into the great unknown with googletest… until I discovered the tests I had written had already been written. In hindsight I probably should have checked in IRC who was going to be doing which tests, but in the end it was only a minor bump in the road.

After the unfortunate hurdle experienced with the cue-settings tests I moved towards trying to convert the cue-times tests. After reading the tests that had been done for cue settings I realized that the original way I had written mine was probably wrong anyways so when I started with the cue-times tests I made sure to change the way I wrote them. Following Caitp’s tests as a template I started my first test file with:

#include "cue_testfixture"
class CueTimeOrder : public CueTest { };

The first line specifies that the tests in the file should use the precoded test fixture written by another person in the class. The second derives a class from the CueTest class (the test fixture class) which will be used to house the test cases that will be written.

After this it was time to look up the error code that was going to be attached to the test. I found these in error.c and error.h inside a constant array:

static const char *errstr[] =
{
	/* WEBVTT_ALLOCATION_FAILED */ "error allocating object",
	/* WEBVTT_MALFORMED_TAG */ "malformed 'WEBVTT' tag",
	/* WEBVTT_EXPECTED_EOL */ "expected newline",
	/* WEBVTT_EXPECTED_WHITESPACE */ "expected whitespace",
	/* WEBVTT_LONG_COMMENT */ "very long tag-comment",
	/* WEBVTT_ID_TRUNCATED */ "webvtt-cue-id truncated",
	/* WEBVTT_MALFORMED_TIMESTAMP */ "malformed webvtt-timestamp",
	/* WEBVTT_EXPECTED_TIMESTAMP */ "expected webvtt-timestamp",
	/* WEBVTT_MISSING_CUETIME_SEPARATOR */ "missing webvtt-cuetime-separator `-->'",
	/* WEBVTT_MISSING_CUESETTING_DELIMITER */ "missing whitespace before webvtt-cuesetting",
	/* WEBVTT_INVALID_ENDTIME */ "webvtt-cue end-time must have value greater than start-time",
	/* WEBVTT_INVALID_CUESETTING */ "unrecognized webvtt-cue-setting",
	/* WEBVTT_VERTICAL_ALREADY_SET */ "'vertical' cue-setting already used",
	/* WEBVTT_VERTICAL_BAD_VALUE */ "'vertical' setting must have a value of either 'lr' or 'rl'",
	/* WEBVTT_LINE_ALREADY_SET */ "'line' cue-setting already used",
	/* WEBVTT_LINE_BAD_VALUE */ "'line' cue-setting must have a value that is an integer (signed) line number, or percentage (%) from top of video display",
	/* WEBVTT_POSITION_ALREADY_SET */ "'position' cue-setting already used",
	/* WEBVTT_POSITION_BAD_VALUE */ "'position' cue-setting must be a percentage (%) value representing the position in the direction orthogonal to the 'line' setting",
	/* WEBVTT_SIZE_ALREADY_SET */ "'size' cue-setting already used",
	/* WEBVTT_SIZE_BAD_VALUE */ "'size' cue-setting must have percentage (%) value",
	/* WEBVTT_ALIGN_ALREADY_SET */ "'align' cue-setting already used",
	/* WEBVTT_ALIGN_BAD_VALUE */ "'align' cue-setting must have a value of either 'start', 'middle', or 'end'",
	/* WEBVTT_CUE_CONTAINS_SEPARATOR */ "cue-text line contains unescaped timestamp separator '-->'",
	/* WEBVTT_CUE_INCOMPLETE */ "cue contains cue-id, but is missing cuetimes or cue text",
};

Where the 3rd error is WEBVTT_EXPECTED_WHITESPACE (the array is of course, 0-indexed).

Because alot of the coding was done in the test fixture, it made writing the rest of the tests almost mechanical as all tests could follow almost the same form, with just test names and files changed:

/* Test description *?
TEST_F(CueTimeTimestampDelimiter,HourMinuteBadDelimiterTimestamp1)
{
  loadVtt( "cue-times/timestamp/timestamp1/delimiter/hour_minute_bad_delimiter.vtt" );
  const Error& err = getError( 0 );
  ASSERT_EQ( WEBVTT_MALFORMED_TIMESTAMP, err.error() );
}

This of course only creates the most basic of tests where a file is passed in and the error is checked. There are a few other functions included in the test fixture for fancier tests like:

void loadVtt( const char *fileName, uint expectedNumberOfCues )
uint cueCount() const
uint errorCount() const

Which introduce the ability to count the number of cues, and number of errors expected in a test.

After the writing of the tests the next step was to include my tests in the include Makefile.am so that the build-system could see the tests that I had made. In order to do this I declared a new variable in the makefile just before the UNIT_TESTS variable:

CUETIMES_TESTS = \
  ctorder_unittest \
  ctseparator_unittest \
  cttimestampdelimiter_unittest \
  cttimestamphour_unittest \
  cttimestampminute_unittest \
  cttimestampsecond_unittest \
  cttimestampsecondfrac_unittest

UNIT_TESTS = \
  sample_unittest \
  sample2_unittest \
  $(CUESETTINGS_TESTS) \
  $(CUETIMES_TESTS) \
  payloadnode_unittest

It was technically not necessary to do this, however I felt it made it more organized (just like the cue settings were in the script).

The next step in the makefile was to set source variables of each unit test to their respective source files:

# Cue Times tests
ctorder_unittest_SOURCES = ctorder_unittest.cpp
ctseparator_unittest_SOURCES = ctseparator_unittest.cpp
cttimestampdelimiter_unittest_SOURCES = cttimestampdelimiter_unittest.cpp
cttimestamphour_unittest_SOURCES = cttimestamphour_unittest.cpp
cttimestampminute_unittest_SOURCES = cttimestampminute_unittest.cpp
cttimestampsecond_unittest_SOURCES = cttimestampsecond_unittest.cpp
cttimestampsecondfrac_unittest_SOURCES = cttimestampsecondfrac_unittest.cpp

And with that done I was finally able to run the tests using “make check”… Where I quickly found a lot of errors in my tests, alot of which were my own mistakes, but also the test parser throwing exceptions when meeting erroneous cues in certain situations (throwing the C++ exception “std::bad_alloc”). After fixing the errors of my own making, I looked up how to disable the failing tests so that they could be implemented without breaking the build. I found that the way to do this was by adding “DISABLED_” to the start of the name of the test when declaring the test fixture:

TEST_F(CueTimeTimestampDelimiter,DISABLED_HourMinuteBadDelimiterTimestamp1)

And finally, disabled tests aside, the tests suite was able to run through all the tests I had planned on working on. I can say now that my experience working with googletest has been alot more enjoyable than beating my head on the desk trying to figure out how I could decipher errors by reading values at memory locations in Node Inspector (this is of no fault to node inspector of course). It was also nice to finally be able to get something done after what had happened with WebKit and node-ffi. Moving forward I suppose I plan to complete more unit tests as well as maybe look into what happened to cause the errors to occur. If I could hazard a guess however, they all look to me like memory allocation errors when parser encounters something it is not expecting.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s