lua代码检查脚本

RsCov.lua:


--[[
Sample:

-- test/test2/t.lua :

function testt()
	print("hello world")
	print("bad world")
end


-- test.lua :

require("RsCov")
require("test/test2/t")

RsCov.start_cov( "test/test2/t.lua" )


testt()

local dump = RsCov.dump_file("t.lua")
print(dump)

-- output :
hello world
bad world
Cov:3 Uncov:6 Total:9 Pct:0.33333333333333
1   0
2   0
3   0 function testt()
4   1 	print("hello world")
5   1 	print("bad world")
6   1 end
7   0
8   0
9   0


]]

file_tbl = file_tbl or {}
rawcoroutinecreate = rawcoroutinecreate or coroutine.create
rawcoroutinewrap = rawcoroutinewrap or coroutine.wrap
rawexit = rawexit or os.exit
IsStarted = IsStarted or false

function trim_path( name )
   	local s1,s2,s3
	s1= name:find("/", 1, true )
	while s1 do
		s2 = s1
		s1 = name:find("/", s1+1, true )
	end

	if s2 then
		s1,s3= name:find(".\\", s2+1, true )
	else
		s1,s3= name:find(".\\", 1, true )
	end

	while s1 do
		s2 = s3
		s1 = name:find(".\\", s2+1, true )
	end

	if s2 then
		name = name:sub( s2+1 )
	end
	return name
end


local function on_line(_, line_nr)
   -- get name of processed file; ignore Lua code loaded from raw strings
   local name = debug.getinfo(2, "S").source

   if not name:match("^@") then
		return
   end

	name = name:sub(2)
	name = trim_path( name )

   	local file = file_tbl[name]

    if not file then
		--print( "can't find :" .. name )
		return
    end

	local cov = file.cov
	cov[line_nr] = (cov[line_nr] or 0) + 1

end

function stop( )
   debug.sethook()
   coroutine.create = rawcoroutinecreate
   coroutine.wrap = rawcoroutinewrap
   os.exit = rawexit
   IsStarted = false
   file_tbl = {}
end

function start_cov( filename )
	local ret = "Ok"
	if filename then
		ret = add_cov_file( filename )
	end
	if not IsStarted then
   		debug.sethook(on_line, "l")
		IsStarted = true
        coroutine.create = function(...)
           local co = rawcoroutinecreate(...)
           debug.sethook(co, on_line, "l")
           return co
        end
        coroutine.wrap = function(...)
           local co = rawcoroutinecreate(...)
           debug.sethook(co, on_line, "l")
           return function()
              local r = { coroutine.resume(co) }
              if not r[1] then
                 error(r[2])
              end
              return unpack(r, 2)
           end
        end
  
        os.exit = function(...)
           on_exit()
           rawexit(...)
        end
   	end

   return ret
end


function clean( name )
	if type(name) == "table" then
		local ret = "fail with : "
		local fail = false
		for i,v in pairs( name ) do
			if clean( v ) ~= "Ok" then
				ret  = ret .. v .. ","
				fail = true
			end
		end
		if fail then
			return ret
		else
			return "Ok"
		end
	end

	if type(name) ~= "string" then
		return "clean file fail, need a string argument."
	end

	name = trim_path( name )

	local file = file_tbl[ name ]
	file.cov = {}
	return "Ok"
end


function add_cov_file( name )
	if type(name) == "table" then
		local ret = "fail with : "
		local fail = false
		for i,v in pairs( name ) do
			if add_cov_file( v ) ~= "Ok" then
				ret  = ret .. v .. ","
				fail = true
			end
		end
		if fail then
			return ret
		else
			return "Ok"
		end
	end

	if type(name) ~= "string" then
		return "add coverage file fail, need a string argument."
	end

	local file = {}
	for line in io.lines(name) do
		table.insert( file, line )
	end
	local file_len = #file
	if file_len == 0 then
		return "read coverage file fail for " .. name
	end
	name = trim_path( name )

	file_tbl[ name ] = file
	file.cov = {}

	--print(name)
	--printTable( file )
	return "Ok"
end



function dump_file( name )
	name = trim_path( name )

   	local file = file_tbl[name]

    if not file then
		return "file is not in record"
    end

	local info = ""
	local has_cov = 0
	local un_cov = 0
	local cov = file.cov
	local show = {}
	local has_run = false
	for k,v in ipairs( file ) do
		local run = cov[ k ] or 0
		if run == 0 then
			show[k] = true
			show[k-1] = true
			show[k+1] = true

			--[[
			show[k-2] = true
			show[k-3] = true
			show[k+2] = true
			show[k+3] = true
			]]
		else
			has_run = true
			show[k] = false
		end
	end

	if not has_run then
			return "file has not been executed."
	end

	--printTable( show)
	for k, v in ipairs( file ) do
		local run = cov[ k ] or 0
		if run == 0 then
			if v ~= "" then
				un_cov = un_cov+1
			end
		else
			has_cov = has_cov +1
		end
		if show[k] then
			info = info .. k .. "   " .. run .. " " .. v .. "\n"
		else
			--info = info .. k .. "   " .. run .. " " .. "[classified]..." .. "\n"
		end
	end
	local total = un_cov + has_cov
	local pct = has_cov/total
	return "Cov:" .. tostring(has_cov) .. " Uncov:" .. tostring(un_cov) .. " Total:" .. tostring(total) ..  " Pct:" .. tostring(pct) .. "\n" .. info
end

function CovCode(UserInfo, Cmd, ...)
	local Useage = [[
		启动代码检漏#r
		$covcode start,module1,module2... #r
		停止代码检漏#r
		$covcode stop #r
		打印某模块结果#r
		$covcode dump,module1,module2,...#r
		清除某模块统计结果#r
		$covcode clean,module1,module2,...#r
	]]
	if not Cmd then
		return Useage
	end
	if not RS_COV then
		RS_COV = Import("cmd/RsCov.lua")
	end
	local files = {...}
	if Cmd == "start" then
		local Ret = RS_COV.start_cov(files)
		return true, "#R已经启动代码检漏,执行结果:"..Ret.."。使用$dumpcodecov打印结果,$stop"
	end
	if Cmd == "stop" then
		RS_COV.stop()
		return true
	end
	if Cmd == "dump" then
		for _, v in ipairs(files) do
			local Ret = RS_COV.dump_file(v)
			_DEBUG(Ret)
			print(Ret)
		end
		return true, "结果已经打印到日志中"
	end
	if Cmd == "clean" then
		for _, v in ipairs(files) do
			local Ret = RS_COV.clean(v)
			print(Ret)
		end
		return true, "已经清理"
	end
	return false, Useage
end

猜你喜欢

转载自blog.csdn.net/Hahaha_Val/article/details/81565403