{"id":21071575,"url":"https://github.com/esrrhs/clua","last_synced_at":"2025-05-16T05:31:37.125Z","repository":{"id":57642163,"uuid":"276024014","full_name":"esrrhs/cLua","owner":"esrrhs","description":"Lua的代码覆盖率工具 Lua code coverage.","archived":false,"fork":false,"pushed_at":"2025-02-21T01:23:51.000Z","size":519,"stargazers_count":33,"open_issues_count":1,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-03T20:51:14.642Z","etag":null,"topics":["lua","luacov"],"latest_commit_sha":null,"homepage":"","language":"Go","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/esrrhs.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":"2020-06-30T07:05:40.000Z","updated_at":"2025-03-04T08:18:15.000Z","dependencies_parsed_at":"2024-11-19T18:53:48.471Z","dependency_job_id":"bc4f0246-a0af-4403-8b0f-5f0562c3a195","html_url":"https://github.com/esrrhs/cLua","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/esrrhs%2FcLua","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esrrhs%2FcLua/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esrrhs%2FcLua/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esrrhs%2FcLua/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/esrrhs","download_url":"https://codeload.github.com/esrrhs/cLua/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254474232,"owners_count":22077245,"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":["lua","luacov"],"created_at":"2024-11-19T18:53:39.845Z","updated_at":"2025-05-16T05:31:34.379Z","avatar_url":"https://github.com/esrrhs.png","language":"Go","readme":"# cLua\n[\u003cimg src=\"https://img.shields.io/github/license/esrrhs/cLua\"\u003e](https://github.com/esrrhs/cLua)\n[\u003cimg src=\"https://img.shields.io/github/languages/top/esrrhs/cLua\"\u003e](https://github.com/esrrhs/cLua)\n[\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/esrrhs/cLua/go.yml?branch=master\"\u003e](https://github.com/esrrhs/cLua/actions)\n\nlua的代码覆盖率工具\n\n# 特性\n* 数据采集用C++编写，性能更高，对宿主进程影响更小\n* 简单require即可使用，或通过[hookso](https://github.com/esrrhs/hookso)注入\n* 解析器用go编写，通过解析lua语法，精确计算文件及函数的覆盖率\n* 支持输出[lcov](http://ltp.sourceforge.net/coverage/lcov.php)格式，进而可生成html格式的图形展示\n* 配合lua_helper搭建覆盖率统计服务\n\n# 编译\n* 安装lua 5.3\n* 编译libclua.so\n```\n# cmake .\n# make\n```\n* 编译clua解析工具\n```\n# go get \"github.com/milochristiansen/lua\" \n# go build clua.go\n```\n* 编译cluahelper覆盖率服务\n```\n# go get \"github.com/esrrhs/go-engine/src/common\"\n# go get \"github.com/esrrhs/go-engine/src/fastwalk\"\n# go get \"github.com/esrrhs/go-engine/src/loggo\"\n# go build clua_helper.go\n```\n\n# 使用\n* 直接嵌入lua脚本中使用，lua文件里使用如下\n```\n-- 加载libclua.so\nlocal cl = require \"libclua\"\n-- 开始记录执行过程，生成结果文件\n-- 第一个参数为结果文件的文件名\n-- 第二个参数为定时生成结果文件的间隔（秒），0表示关闭\ncl.start(\"test.cov\", 5)\n\n-- 执行某些事情\ndo_something()\n\n-- 结束记录\ncl.stop()\n```\n* 或者使用[hookso](https://github.com/esrrhs/hookso)注入到进程中（假设进程id为PID），手动开启\n```\na) 首先获取进程中的Lua_State指针，比如进程调用了lua_settop(L)函数，那么就取第一个参数\n# ./hookso arg $PID liblua.so lua_settop 1 \n123456\n\nb) 加载libclua.so\n# ./hookso dlopen $PID ./libclua.so\n\nc) 执行libclua.so的start_cov手动开启，等价于start_cov(L, \"./test.cov\", 5)\n# ./hookso call $PID libclua.so start_cov i=123456 s=\"./test.cov\" i=5\n\nc) 执行libclua.so的stop_cov手动关闭，等价于stop_cov(L)\n# ./hookso call $PID libclua.so stop_cov i=123456\n```\n* 执行完上述两种方法的任一一种，用clua解析test.cov查看结果。clua更多参数参考-h\n```\n# ./clua -i test.cov\n```\n\n# 示例\n* 运行test.lua\n```\n# lua5.3 ./test.lua\n```\n* 查看目录下，已有test.cov文件\n```\n# ll test.cov\n```\n* 查看结果，每行前面的数字表示执行的次数，空表示没被执行，方便定位潜在bug。最后几行显示了总体覆盖率，以及每个函数的覆盖率\n```\n# ./clua -i test.cov     \ntotal points = 27, files = 1\ncoverage of /home/project/clua/test.lua:\n    local cl = require \"libclua\"\n    cl.start(\"test.cov\", 5)\n    \n1   function test1(i)\n10      if i % 2 then\n10          print(\"a \"..i)\n        else\n            print(\"b \"..i)\n        end\n11  end\n    \n1   function test2(i)\n40      if i \u003e 30 then\n19          print(\"c \"..i)\n        else\n21          print(\"d \"..i)\n        end\n41  end\n    \n1   function test3(i)\n    \n51      if i \u003e 0 then\n51          print(\"e \"..i)\n        else\n            print(\"f \"..i)\n        end\n    \n52  end\n    \n    test4 = function(i)\n    \n        local function test5(i)\n12          print(\"g \"..i)\n15      end\n    \n15      for i = 0, 3 do\n12          test5(i)\n        end\n    \n4   end\n    \n102 for i = 0, 100 do\n101     if i \u003c 10 then\n10          test1(i)\n91      elseif i \u003c 50 then\n40          test2(i)\n        else\n51          test3(i)\n        end\n    end\n    \n4   for i = 0, 2 do\n3       test4(i)\n    end\n    \n1   cl.stop()\n    \n/home/project/clua/test.lua total coverage 78% 22/28\n/home/project/clua/test.lua function coverage [function test1(i)] 66% 2/3\n/home/project/clua/test.lua function coverage [function test2(i)] 100% 3/3\n/home/project/clua/test.lua function coverage [function test3(i)] 66% 2/3\n/home/project/clua/test.lua function coverage [test4 = function(i)] 75% 3/4\n/home/project/clua/test.lua function coverage [local function test5(i)] 100% 1/1\n```\n* 也用lcov查看\n```\n# ./clua -i test.cov -lcov test.info    \n```\n* 此时目录下已有```test.info```文件，然后用lcov的工具输出html\n```\n# genhtml -o htmltest test.info \n```\n* 打开htmltest目录下的index.html如下\n![image](./lcov1.png)\n* 点击进入test.lua\n![image](./lcov2.png)\n* lcov还可以对info文件进行合并，更多操作参考官方文档\n\n## 覆盖率服务CluaHelper\n覆盖率服务分为客户端、服务器、生成器三部分，二进制文件为clua_helper，参数通过```./clua_helper -h```查看。\n\n#### CluaHelper客户端\n客户端搜索宿主进程，注入进程，打开覆盖率统计，监控代码路径变化，最后发送数据到服务器\n```\n# ./clua_helper -type client -bin 宿主bin名字 -getluastate \"获取LuaState的指令，如：liblua.so lua_settop 1\" -path 代码目录 -server http://server_ip:8877\n```\n\n#### CluaHelper服务端\n服务器接受客户端的数据，保存数据文件到本地，同时对外服务html结果目录的静态网页。\n```\n# ./clua_helper -type server -port 8877\n```\n\n#### CluaHelper生成器\n生成器读取服务器保存的数据文件，根据本地代码，自动把结果合并，最后生成html结果目录。\n```\n# ./clua_helper -type gen -covpath 服务端保存的结果目录 -path 本地的代码目录 -clientpath 客户端的代码目录\n```\n最后访问http://server_ip:8877/static/即可显示如下网页\n![image](./lcov1.png)\n\n## 其他\n[lua全家桶](https://github.com/esrrhs/lua-family-bucket)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesrrhs%2Fclua","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fesrrhs%2Fclua","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesrrhs%2Fclua/lists"}