{"id":8,"date":"2008-07-27T20:39:01","date_gmt":"2008-07-28T00:39:01","guid":{"rendered":"http:\/\/www.joshmatthews.net\/blog\/?p=8"},"modified":"2008-07-27T20:50:32","modified_gmt":"2008-07-28T00:50:32","slug":"testing-linked-lists","status":"publish","type":"post","link":"https:\/\/www.joshmatthews.net\/blog\/2008\/07\/testing-linked-lists\/","title":{"rendered":"Testing linked lists"},"content":{"rendered":"<p>I&#8217;m just finishing up the CS 136 class here at the University of Waterloo, which also goes by the name of &#8220;Elementary Algorithm Design and Data Abstraction.&#8221;  In other words, we make the transition from introductory Scheme to introductory C while learning about topics such as braun trees, hash tables, and more.  We&#8217;re also expected to use test driven design, or at least write tests and run them frequently, to ensure that our assignment programs are working correctly.  While most of the programs are rather elementary, the procedure to test data structures such as linked lists is rather annoying, because it ends up looking something like this:<\/p>\n<pre lang=\"c\">int i;\r\nint testNum[] = {0, 1, 2, 3}; List *l = list;\r\nfor(i = 0; i &lt; sizeof(testNum)\/sizeof(testNum[0]); i++)\r\n   assert(list-&gt;val == testNum[i]);<\/pre>\n<p>No imagine writing that over and over, especially if you have multiple fields that need testing.  Being unsatisfied with this setup, I took it upon myself to write a linked list field asserter, which can be used like so:<\/p>\n<pre lang=\"c\">int cmp_num(void *a, void *b)\r\n{\r\n    return (int)a - (int)b;\r\n}\r\n\r\nint testNum[] = {0, 1, 2, 3};\r\nassertListFieldEqual(list, offsetof(List, val), cmp_num, testNum, sizeof(int), offsetof(List, next));<\/pre>\n<p>As you can guess, it&#8217;s about as generic as you can get in straight C without the benefit  of C++ templates.  If you have a structure that is traversed via a pointer to the next structure, it can be asserted with this system.  <code>assertListFieldEqual<\/code> takes<\/p>\n<ul>\n<li>a pointer to the head element<\/li>\n<li><code>offsetof(list type, field to compare)<\/code><\/li>\n<li>a pointer to a comparison function<\/li>\n<li>a pointer to a list of expected values<\/li>\n<li>the size of a value<\/li>\n<li><code>offsetof(list type, traversal field)<\/code><\/li>\n<\/ul>\n<p>The function itself is not particularly difficult, but it does abuse pointers in very unethical ways:<\/p>\n<pre lang=\"c\">typedef int (*cmp_func)(void *, void *);\r\n\r\nvoid assertListFieldEqual(void *list, ptrdiff_t field, cmp_func cmp, void *cmp_to, size_t cmp_size, ptrdiff_t next)\r\n{\r\n    ptrdiff_t count = 0;\r\n    while(1)\r\n    {\r\n        assert(!cmp((void *)(*(ptrdiff_t *)(cmp_to + count * cmp_size)), (void *)(*(ptrdiff_t *)(list + field))));\r\n        if((void *)*((ptrdiff_t *)(list + next)) == NULL)\r\n            break;\r\n        list = (void *)(*(ptrdiff_t *)(list + next));\r\n        count++;\r\n    }\r\n}<\/pre>\n<p>I&#8217;m pretty sure all of my pointer abuse is fully sanctioned by the standard, so it should be portable to my knowledge.  Therefore, go forth and multiply, and test your lists well!  And if you&#8217;re in any doubt that this is not generic enough, behold, I give you string comparison!<\/p>\n<pre lang=\"c\">const char *testName[] = {\"1\", \"2\", \"3\", \"4\"};\r\nassertListFieldEqual(list, offsetof(List, name), (cmp_func)strcmp, testName, sizeof(char *), offsetof(List, next));<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m just finishing up the CS 136 class here at the University of Waterloo, which also goes by the name of &#8220;Elementary Algorithm Design and Data Abstraction.&#8221; In other words, we make the transition from introductory Scheme to introductory C &hellip; <a href=\"https:\/\/www.joshmatthews.net\/blog\/2008\/07\/testing-linked-lists\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[10,9],"class_list":["post-8","post","type-post","status-publish","format-standard","hentry","category-projects","tag-code","tag-hacks"],"_links":{"self":[{"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/posts\/8","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/comments?post=8"}],"version-history":[{"count":9,"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/posts\/8\/revisions"}],"predecessor-version":[{"id":17,"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/posts\/8\/revisions\/17"}],"wp:attachment":[{"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/media?parent=8"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/categories?post=8"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.joshmatthews.net\/blog\/wp-json\/wp\/v2\/tags?post=8"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}