{"id":1786,"date":"2021-08-10T11:43:21","date_gmt":"2021-08-10T15:43:21","guid":{"rendered":"https:\/\/www.yorku.ca\/professor\/drsmith\/?p=1786"},"modified":"2021-10-21T21:52:39","modified_gmt":"2021-10-22T01:52:39","slug":"vpl-simple-c-assignment-with-unit-testing","status":"publish","type":"post","link":"https:\/\/www.yorku.ca\/professor\/drsmith\/2021\/08\/10\/vpl-simple-c-assignment-with-unit-testing\/","title":{"rendered":"VPL: Simple C Assignment with Unit Testing"},"content":{"rendered":"\n<p class=\"has-text-align-right\">August 2021<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Background<\/h2>\n\n\n\n<p>Here, we're going to apply <a href=\"http:\/\/www.throwtheswitch.org\/unity\">ThrowTheSwitch's <em>Unity<\/em> <\/a><strong>unit test framework <\/strong>to C programs.  The test framework is available on <a href=\"https:\/\/github.com\/ThrowTheSwitch\/Unity\">GitHub<\/a>.  <a href=\"https:\/\/github.com\/ThrowTheSwitch\/Unity\/tree\/master\/src\">Three files<\/a> need to be <a href=\"https:\/\/github.com\/ThrowTheSwitch\/Unity\/tree\/master\/src\">downloaded<\/a> from the GitHub.  There are a few more files that need to be developed within VPL to make it work, and those are described below.<\/p>\n\n\n\n<p>We're targeting C in this activity because C is still relevant in engineering and computer science curricula, notably in domains like  operating systems and embedded systems (microcontrollers). <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1. First Steps<\/h2>\n\n\n\n<p>Start a VPL assignment as normal.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1a. Name &amp; description<\/h3>\n\n\n\n<p>Provide a name and any instructions for the student in the first screen of the VPL activity.  Save.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1b. Modify maximum grade<\/h3>\n\n\n\n<p>VPL assignments default to a grade out of 100.  I find that this provides too high a perceived weight to the assignment. Instead, I prefer to grade out of 1.  Hit save.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1c. Point to local VPL server<\/h3>\n\n\n\n<p>Go to Gear -&gt; Local execution servers (a.k.a. Advanced settings \/ Local execution servers) and type in<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:\/\/<mark class=\"kt-highlight\">xxxxxx<\/mark>.<mark class=\"kt-highlight\">yyyyy<\/mark>.yorku.ca\nend_of_jails.<\/code><\/pre>\n\n\n\n<p>You need to modify the above (<mark class=\"kt-highlight\">xxxxxx<\/mark>.<mark class=\"kt-highlight\">yyyyy<\/mark>.) to point to the specific VPL server for your department.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2. Add Student Template<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>studentTemplate.c (student will modify this)<\/li><li>studentTemplate.h (student not expected to modify)<\/li><\/ul>\n\n\n\n<p>This is the student template C file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ this is <mark class=\"kt-highlight\">studentTemplate.c<\/mark>.  Place it in the \"Requested Files\" section of VPL.\n#include \"studentTemplate.h\"\n\n\/* --------------------------------------------------\n * This is a C function.  Modify it as needed to run\n * a good for loop.  VPL will call this function and verify\n * that it returns the right value, answer, for an arbitrary \n * input, maxLoops.\n * -------------------------------------------------- *\/\nint32_t myForLoop(int32_t maxLoops)\n{\n    int32_t answer = 0;\n    int32_t loopNumber = 0;\n    \n    \/* -------------------------------------------------------------\n     * For loops in C are like for loops in Java and Matlab\n     * reference: https:\/\/www.programiz.com\/c-programming\/c-for-loop\n     * ------------------------------------------------------------- *\/\n    for(loopNumber = 0; loopNumber &lt;= maxLoops; loopNumber++){\n        \/\/ Update the value of answer each time the loop runs.\n        answer = answer + 3;\n    }\n    \n    \/\/ Give back the final answer.\n    \/\/ VPL will examine this value.\n    return answer;\n}<\/code><\/pre>\n\n\n\n<p>The studentTemplate.c file is what the students will modify.  In this case, there is nothing for the student to change.  The .c file will all a header (.h) file, hidden from the student:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ this is <mark class=\"kt-highlight\">studentTemplate.h<\/mark>.  Place it in the \"Execution Files\" section of VPL.\n#include &lt;stdint.h&gt;\n\nint32_t myForLoop(int32_t);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3. Add Unit tests (\"solution\")<\/h2>\n\n\n\n<p>Here you design your unit tests for the student submission in the file<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>testStudentTemplate.c<\/li><\/ul>\n\n\n\n<p>The file is stored in \"Execution files\" of VPL.  This is where you write up the unit tests.  The \"main\" function found at the bottom will run tests based on the unit tests you write in each function.  Note that the Unity framework uses function pointers to call the functions, so the brackets are missing when they get called.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ this is the <mark class=\"kt-highlight\">testStudentTemplate.c<\/mark> file.\n\/\/ it's what the prof uses to evaluate the student's submission.\n#include \"unity.h\"\n#include \"studentTemplate.h\"\n\n\/\/ add these two b\/c https:\/\/github.com\/ThrowTheSwitch\/Unity\/blob\/master\/docs\/UnityGettingStartedGuide.md \n\/\/ and https:\/\/stackoverflow.com\/questions\/61114392\/linker-error-with-unity-c-unit-testing-framework\nvoid setUp(void){\n        \/\/ set stuff up here\n}\n\nvoid tearDown(void){\n    \/\/ clean stuff up here.\n}\n\n\nvoid test_myForLoop_<mark class=\"kt-highlight\">40<\/mark>(void)\n{\n    \/\/ The specific test types are found in unity.h\n    TEST_ASSERT_EQUAL_INT32(40*3,myForLoop(40));     \/\/ expected out vs. input\n}\n\nvoid test_myForLoop_<mark class=\"kt-highlight\">10<\/mark>(void)\n{\n    \/\/ The specific test types are found in unity.h\n    TEST_ASSERT_EQUAL_INT32(10*3,myForLoop(10));     \/\/ expected out vs. input\n}\n\nvoid test_myForLoop_<mark class=\"kt-highlight\">0<\/mark>(void)\n{\n    \/\/ The specific test types are found in unity.h\n    TEST_ASSERT_EQUAL_INT32(0,myForLoop(0));     \/\/ expected out vs. input\n}\n\nvoid test_myForLoop_<mark class=\"kt-highlight\">5000000<\/mark>(void)\n{\n    \/\/ The specific test types are found in unity.h\n    TEST_ASSERT_EQUAL_INT32(5000000*3,myForLoop(5000000));     \/\/ expected out vs. input\n}\n\n\/\/ add more test functions here...\n\/\/ void test_function_name(void){}\n\n\/\/ Run the tests...\nint main(void)\n{\n    UNITY_BEGIN();\n    RUN_TEST(test_myForLoop_40);        \/\/ sub test 1\n    RUN_TEST(test_myForLoop_10);        \/\/ sub test 2\n    RUN_TEST(test_myForLoop_0);         \/\/ sub test 3\n    RUN_TEST(test_myForLoop_5000000);   \/\/ sub test 4\n\n    \/\/ add more RUN_TEST()s as needed.\n    return UNITY_END();\n}<\/code><\/pre>\n\n\n\n<p>There are four separate unit tests.  You can have more or you can have less.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>You can see, above, the use of TEST_ASSERT_EQUAL_INT32().  This will examine look for an equality condition on a 32-bit integer as the output of the student's function.  But there are more tests, all defined in <a href=\"https:\/\/github.com\/ThrowTheSwitch\/Unity\/blob\/master\/src\/unity.h\">unity.h<\/a>.  There are tests for floating point values...<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"688\" height=\"99\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-10.png\" alt=\"\" class=\"wp-image-1805\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-10.png 688w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-10-300x43.png 300w\" sizes=\"auto, (max-width: 688px) 100vw, 688px\" \/><figcaption>Some of the floating point unit test functions<\/figcaption><\/figure><\/div>\n\n\n\n<p>there are tests for strings and arrays...<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"734\" height=\"220\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-11.png\" alt=\"\" class=\"wp-image-1806\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-11.png 734w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-11-300x90.png 300w\" sizes=\"auto, (max-width: 734px) 100vw, 734px\" \/><figcaption>Some of the array and string tests<\/figcaption><\/figure><\/div>\n\n\n\n<p>... and boolean tests...<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"584\" height=\"101\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-12.png\" alt=\"\" class=\"wp-image-1807\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-12.png 584w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-12-300x52.png 300w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><figcaption>Boolean tests...<\/figcaption><\/figure><\/div>\n\n\n\n<p>... and lots and lots of integer tests.  Dig into <a href=\"https:\/\/github.com\/ThrowTheSwitch\/Unity\/blob\/master\/src\/unity.h\">unity.h<\/a> for more.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4. Add Unity files<\/h2>\n\n\n\n<p>The Unity unit testing framework files can be pulled directly from GitHub:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/ThrowTheSwitch\/Unity\/blob\/master\/src\/unity.c\">unity.c<\/a> (<a href=\"https:\/\/raw.githubusercontent.com\/ThrowTheSwitch\/Unity\/master\/src\/unity.c\">download<\/a> raw from GitHub)<\/li><li><a href=\"https:\/\/github.com\/ThrowTheSwitch\/Unity\/blob\/master\/src\/unity.h\">unity.h<\/a> (<a href=\"https:\/\/raw.githubusercontent.com\/ThrowTheSwitch\/Unity\/master\/src\/unity.h\">download<\/a> raw from GitHub)<\/li><li><a href=\"https:\/\/github.com\/ThrowTheSwitch\/Unity\/blob\/master\/src\/unity_internals.h\">unity_internals.h<\/a> (<a href=\"https:\/\/raw.githubusercontent.com\/ThrowTheSwitch\/Unity\/master\/src\/unity_internals.h\">download<\/a> raw from GitHub)<\/li><\/ol>\n\n\n\n<p>Each of these needs to be placed in VPL's Execution Files.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5. the Run and Evaluate scripts<\/h2>\n\n\n\n<p>The vpl_run.sh and vpl_execute.sh shell scripts do not need to be modified.  <strong>Leave them blank<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6. Evaluation <\/h2>\n\n\n\n<p>There is no need to modify the vpl_run.sh or vpl_evaluate.sh scripts.  Instead, we're going to rely on the Unity unit testing framework's \"standard out\" output.  This will be compared to the contents of the evaluate.cases file, which is found in the in the Gear -&gt; Execution Files (a.k.a. Advanced Settings \/ Execution files) menu.  The contents for <mark class=\"kt-highlight\">evaluate.cases<\/mark> is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>case : Test 1\noutput = \/(0\\sFailures)\/i<\/code><\/pre>\n\n\n\n<p>Basically, it'll look for the string \"0 Failures\" within the output.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6. Modify completion status<\/h2>\n\n\n\n<p>This is not required, but it's a <em>really good thing<\/em> to do in your class.  Completion tracking is a built-in feature in eClass\/Moodle.  You should activate it for your course and add it to each of your activities to <em>provide students with an easy-to-follow guide<\/em> that they can follow throughout the semester.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 7. Check as \"Demo Student\"<\/h2>\n\n\n\n<p>Check to see that the testing system has the right output for a given input.  Here you can see that when I ran the student template, and had configured the activity to only have a single test of the for loop, the Unity test told me that it failed (120 was expected but it got 123):<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"536\" height=\"135\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/Screen-Shot-2021-08-10-at-10.54.01-AM.png\" alt=\"\" class=\"wp-image-1799\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/Screen-Shot-2021-08-10-at-10.54.01-AM.png 536w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/Screen-Shot-2021-08-10-at-10.54.01-AM-300x76.png 300w\" sizes=\"auto, (max-width: 536px) 100vw, 536px\" \/><figcaption>The unit test showed that the wrong value was returned by the student's function.<\/figcaption><\/figure><\/div>\n\n\n\n<p>A quick update to the student submission and we can see that it's all good.  We got 120 as an output (40*3).<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"951\" height=\"594\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-7.png\" alt=\"\" class=\"wp-image-1796\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-7.png 951w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-7-300x187.png 300w\" sizes=\"auto, (max-width: 951px) 100vw, 951px\" \/><figcaption>Successful test of the student submission in \"Demo Student\" mode.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Next, I added three more tests of the For Loop: an input of 40, an input of 10, an input of 0 and an input of some large number.  With an incorrect student program, the evaluation tab produces this output:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"494\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-8-1024x494.png\" alt=\"\" class=\"wp-image-1800\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-8-1024x494.png 1024w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-8-300x145.png 300w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-8.png 1226w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Four different tests were run together. Three of the four failed, so the student got zero.  The student can see, from the comments, that the expected string, \"0 Failures\" was not found.<\/figcaption><\/figure><\/div>\n\n\n\n<p>After fixing the student code, we can see that the four little tests that make up the complete test were successful:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"936\" height=\"534\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-9.png\" alt=\"\" class=\"wp-image-1801\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-9.png 936w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/08\/image-9-300x171.png 300w\" sizes=\"auto, (max-width: 936px) 100vw, 936px\" \/><figcaption>Student success!  The student will get 1 out of 1.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Looking to Improve<\/h2>\n\n\n\n<p>There are limitations to this approach of conducting evaluations.  We are searching the output for the string \"0 Failures\".  It's possible to fake this output and mistakenly grade a student's incorrect solution as correct.  A more robust approach would require <strong>customizing the vpl_run.sh and vpl_evaluate.sh<\/strong> scripts to validate the student solution in a way that avoids this.  This customization is found in other blog posts on this site.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>James Andrew Smith is an associate professor in&nbsp;<a href=\"http:\/\/eecs.lassonde.yorku.ca\/\">Electrical Engineering and Computer Science Department<\/a>&nbsp;in York University's&nbsp;<a href=\"https:\/\/lassonde.yorku.ca\/\">Lassonde School<\/a>. &nbsp;He lived in Strasbourg, France and taught at the&nbsp;<a href=\"https:\/\/www.insa-strasbourg.fr\/en\/\">INSA Strasbourg<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/www.hs-karlsruhe.de\/\">Hochschule Karlsruhe<\/a>&nbsp;while on&nbsp;<a href=\"https:\/\/drsmith.blog.yorku.ca\/2019\/10\/sabbatical-report-summary\/\">sabbatical<\/a>&nbsp;in 2018-19 with his wife and kids. Some of his other blog posts discuss the family's sabbatical year, from both&nbsp;<a href=\"https:\/\/twitter.com\/search?q=(%23sabbaticallife)%20(from%3Aonnimikki)&amp;src=typed_query\">personal<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/twitter.com\/search?q=insa%20(from%3Ajasmith_yorku)&amp;src=typed_query\">professional<\/a>&nbsp;<a href=\"https:\/\/twitter.com\/search?q=karlsruhe%20(from%3Ajasmith_yorku)&amp;src=typed_query\">perspectives<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>August 2021 Background Here, we're going to apply ThrowTheSwitch's Unity unit test framework to C programs. The test framework is available on GitHub. Three files need to be downloaded from the GitHub. There are a few more files that need to be developed within VPL to make it work, and those are described below. We're [&hellip;]<\/p>\n","protected":false},"author":762,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","footnotes":""},"categories":[1],"tags":[12,278,192,290,291,261,263],"class_list":["post-1786","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-c-programming","tag-eclass","tag-microcontrollers","tag-unit-testing","tag-unity","tag-virtual-programming-lab","tag-vpl"],"taxonomy_info":{"category":[{"value":1,"label":"Uncategorized"}],"post_tag":[{"value":12,"label":"c programming"},{"value":278,"label":"eclass"},{"value":192,"label":"microcontrollers"},{"value":290,"label":"unit testing"},{"value":291,"label":"unity"},{"value":261,"label":"virtual programming lab"},{"value":263,"label":"VPL"}]},"featured_image_src_large":false,"author_info":{"display_name":"drsmith","author_link":"https:\/\/www.yorku.ca\/professor\/drsmith\/author\/drsmith\/"},"comment_info":"","category_info":[{"term_id":1,"name":"Uncategorized","slug":"uncategorized","term_group":0,"term_taxonomy_id":1,"taxonomy":"category","description":"","parent":0,"count":41,"filter":"raw","cat_ID":1,"category_count":41,"category_description":"","cat_name":"Uncategorized","category_nicename":"uncategorized","category_parent":0}],"tag_info":[{"term_id":12,"name":"c programming","slug":"c-programming","term_group":0,"term_taxonomy_id":12,"taxonomy":"post_tag","description":"","parent":0,"count":6,"filter":"raw"},{"term_id":278,"name":"eclass","slug":"eclass","term_group":0,"term_taxonomy_id":278,"taxonomy":"post_tag","description":"","parent":0,"count":7,"filter":"raw"},{"term_id":192,"name":"microcontrollers","slug":"microcontrollers","term_group":0,"term_taxonomy_id":192,"taxonomy":"post_tag","description":"","parent":0,"count":5,"filter":"raw"},{"term_id":290,"name":"unit testing","slug":"unit-testing","term_group":0,"term_taxonomy_id":290,"taxonomy":"post_tag","description":"","parent":0,"count":5,"filter":"raw"},{"term_id":291,"name":"unity","slug":"unity","term_group":0,"term_taxonomy_id":291,"taxonomy":"post_tag","description":"","parent":0,"count":3,"filter":"raw"},{"term_id":261,"name":"virtual programming lab","slug":"virtual-programming-lab","term_group":0,"term_taxonomy_id":261,"taxonomy":"post_tag","description":"","parent":0,"count":14,"filter":"raw"},{"term_id":263,"name":"VPL","slug":"vpl","term_group":0,"term_taxonomy_id":263,"taxonomy":"post_tag","description":"","parent":0,"count":13,"filter":"raw"}],"_links":{"self":[{"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/posts\/1786","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/users\/762"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/comments?post=1786"}],"version-history":[{"count":14,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/posts\/1786\/revisions"}],"predecessor-version":[{"id":2023,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/posts\/1786\/revisions\/2023"}],"wp:attachment":[{"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/media?parent=1786"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/categories?post=1786"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/tags?post=1786"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}