{"id":15750268,"url":"https://github.com/objarni/poorprogrammersccodecoverage","last_synced_at":"2026-02-19T01:04:02.366Z","repository":{"id":142954219,"uuid":"417754175","full_name":"objarni/PoorProgrammersCCodeCoverage","owner":"objarni","description":"An hack using the preprocessor to get (non-branching) line code coverage","archived":false,"fork":false,"pushed_at":"2021-10-27T06:07:05.000Z","size":29,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-06T11:55:25.553Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/objarni.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-16T07:31:44.000Z","updated_at":"2021-11-10T23:24:25.000Z","dependencies_parsed_at":"2023-04-29T12:46:40.990Z","dependency_job_id":null,"html_url":"https://github.com/objarni/PoorProgrammersCCodeCoverage","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objarni%2FPoorProgrammersCCodeCoverage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objarni%2FPoorProgrammersCCodeCoverage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objarni%2FPoorProgrammersCCodeCoverage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/objarni%2FPoorProgrammersCCodeCoverage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/objarni","download_url":"https://codeload.github.com/objarni/PoorProgrammersCCodeCoverage/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246429493,"owners_count":20775808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-04T06:23:13.297Z","updated_at":"2025-10-12T21:13:48.582Z","avatar_url":"https://github.com/objarni.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Poor Programmers C Code Coverage (or, if you prefer, PreProCessor Code Coverage)\nA hack using the preprocessor to get (non-branching) code coverage.\n\n# Idea\n\nWhy not use the `__LINE__` preprocessor directive to keep track of what lines have been executed?\n\nLet's say we have simple function like this:\n\n  ```cpp\n  void maybe_trigger(float temperature) {\n      if(temperature \u003e 100) {\n          printf(\"Triggered at value %d.\\n\", temperature);\n      }\n      else {\n          printf(Not triggered yet.\\n\");\n      }\n  }\n  ```\n\nWe want to write unit tests to cover as much as possible of this function, be we don't have the\ntooling available. What can we do?\n\nWell, we can define a macro C (for cover) like this:\n\n  ```cpp\n  #define C  (lineVisited[numLinesVisited++] = __LINE__);\n  int lineVisited[50000];\n  int numLinesVisited = 0;\n  ```\n\n`lineVisited` together with `numLinesVisited` keeps track of what lines are visited, using the\n`__LINE__` preprocessor macro. They can e.g be defined just above the function we want to cover.\n\nThen we can put this C macro at the start of every line we want to cover:\n\n  ```cpp\n  void maybe_trigger(float temperature) {     // Line 37\n  C    if(temperature \u003e 100) {\n  C        printf(\"Triggered at value %d.\\n\", a);\n  C    }\n       else {                                 // Line 40\n  C        printf(Not triggered yet.\\n\");\n  C    }                                      // Line 42\n  }\n  ```\n\nNote that we cannot put a coverage C on line 40, since it would break the syntax of the language\nputting a statement inbetween '}' and 'else'.\n\nNow we can write unit tests, which will update the lineVisited buffer, and using this\nlittle helper function, we can display what coverage we have in percent, and what lines\nare missing:\n\n   ```cpp\n   void coverageReport(int lineStart, int lineEnd) {\n      int totalLines = lineEnd - lineStart + 1;\n      int numCovered = 0;\n      for(int line = lineStart; line \u003c= lineEnd; line++) {\n        int covered = 0;\n        for(int i=0; i\u003cnumLinesVisited; i++) {\n          if(lineVisited[i] == line) {\n            covered = 1;\n            numCovered++;\n            break;\n          }\n        }\n        if(!covered)\n          printf(\"Line %d was not covered.\\n\", line);\n      }\n      printf(\"Coverage: %1.1f\\n\", 100 * numCovered / totalLines);\n   }\n   ```\n   \nNote that `coverageReport` needs to know what line to start and end with. For example, maybe\nthe above function was defined at line 37-42 in some module, then it would be called like this:\n\n   ```cpp\n   coverageReport(37, 42);\n   ```\n\nOne final challenge: when to call coverageReport? Well, one idea is from a 'reportTest' unit test,\nwhich is somehow run last, after all other (relevant) unit tests. In CGreen[1] style:\n\n   ```cpp\n   Ensure(some_suite_name, reportTest) {\n     coverageReport(37, 42);\n   }\n   ```\n\n\n1. https://cgreen-devs.github.io/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobjarni%2Fpoorprogrammersccodecoverage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobjarni%2Fpoorprogrammersccodecoverage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobjarni%2Fpoorprogrammersccodecoverage/lists"}