update ceedling to 0.29.0

This commit is contained in:
hathach
2019-11-01 17:48:59 +07:00
parent 774a9f63ab
commit b25faa97c2
59 changed files with 1962 additions and 736 deletions
+6 -5
View File
@@ -15,7 +15,6 @@ Define any of these sections in :tools: to provide additional hooks to be called
:pre_link_execute
:post_link_execute
:pre_test_fixture_execute
:pre_test_fixture_execute
:pre_test
:post_test
:pre_release
@@ -24,13 +23,13 @@ Define any of these sections in :tools: to provide additional hooks to be called
:post_build
```
Each of these tools can support an :executable string and an :args list, like so:
Each of these tools can support an :executable string and an :arguments list, like so:
```
:tools:
:post_link_execute:
:executable: objcopy.exe
:args:
:arguments:
- ${1} #This is replaced with the executable name
- output.srec
- --strip-all
@@ -42,11 +41,13 @@ You may also specify an array of executables to be called in a particular place,
:tools:
:post_test:
- :executable: echo
:args: "${1} was glorious!"
:arguments: "${1} was glorious!"
- :executable: echo
:args:
:arguments:
- it kinda made me cry a little.
- you?
```
Please note that it varies which arguments are being parsed down to the
hooks. For now see `command_hooks.rb` to figure out which suits you best.
Happy Tweaking!
@@ -1,6 +1,5 @@
require 'ceedling/plugin'
require 'ceedling/constants'
class CommandHooks < Plugin
attr_reader :config
@@ -23,7 +22,6 @@ class CommandHooks < Plugin
:post_release => ((defined? TOOLS_POST_RELEASE) ? TOOLS_POST_RELEASE : nil ),
:pre_build => ((defined? TOOLS_PRE_BUILD) ? TOOLS_PRE_BUILD : nil ),
:post_build => ((defined? TOOLS_POST_BUILD) ? TOOLS_POST_BUILD : nil ),
:post_build => ((defined? TOOLS_POST_BUILD) ? TOOLS_POST_BUILD : nil ),
:post_error => ((defined? TOOLS_POST_ERROR) ? TOOLS_POST_ERROR : nil ),
}
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
@@ -49,14 +47,33 @@ class CommandHooks < Plugin
private
##
# Run a hook if its available.
#
# :args:
# - hook: Name of the hook to run
# - name: Name of file (default: "")
#
# :return:
# shell_result.
#
def run_hook_step(hook, name="")
if (hook[:executable])
args = ( (hook[:args].is_a? Array) ? hook[:args] : [] )
cmd = @ceedling[:tool_executor].build_command_line( hook, args, name )
shell_result = @ceedling[:tool_executor].exec( cmd[:line], cmd[:options] )
# Handle argument replacemant ({$1}), and get commandline
cmd = @ceedling[:tool_executor].build_command_line( hook, [], name )
shell_result = @ceedling[:tool_executor].exec(cmd[:line], cmd[:options])
end
end
##
# Run a hook if its available.
#
# If __which_hook__ is an array, run each of them sequentially.
#
# :args:
# - which_hook: Name of the hook to run
# - name: Name of file
#
def run_hook(which_hook, name="")
if (@config[which_hook])
@ceedling[:streaminator].stdout_puts("Running Hook #{which_hook}...", Verbosity::NORMAL)
+67 -8
View File
@@ -1,13 +1,16 @@
ceedling-gcov
=============
# Plugin Overview
Plugin for integrating GNU GCov code coverage tool into Ceedling projects.
Currently only designed for the gcov command (like LCOV for example). In the
future we could configure this to work with other code coverage tools.
This plugin currently uses `gcovr` to generate HTML and/or XML reports as a
utility. The normal gcov plugin _must_ be run first for this report to generate.
This plugin currently uses `gcovr` to generate HTML reports as a utility. The
normal gcov plugin _must_ be run first for this report to generate.
## Installation
Gcovr can be installed via pip like so:
@@ -15,27 +18,83 @@ Gcovr can be installed via pip like so:
pip install gcovr
```
## Configuration
The gcov plugin supports configuration options via your `project.yml` provided
by Ceedling.
Generation of HTML reports may be enabled or disabled with the following
config. Set to `true` to enable or set to `false` to disable.
```
:gcov:
:html_report: true
```
Generation of XML reports may be enabled or disabled with the following
config. Set to `true` to enable or set to `false` to disable.
```
:gcov:
:xml_report: true
```
There are two types of gcovr HTML reports that can be configured in your
`project.yml`. To create a basic HTML report with only the overall file
information use the following config.
`project.yml`. To create a basic HTML report, with only the overall file
information, use the following config.
```
:gcov:
:html_report_type: basic
```
To create a detailed HTML report with line by line breakdown of the coverage use
the following config.
To create a detailed HTML report, with line by line breakdown of the
coverage, use the following config.
```
:gcov:
:html_report_type: detailed
```
These reports will be found in `build/artifacts/gcov`.
There are a number of options to control which files are considered part of
the coverage report. Most often, we only care about coverage on our source code, and not
on tests or automatically generated mocks, runners, etc. However, there are times
where this isn't true... or there are times where we've moved ceedling's directory
structure so that the project file isn't at the root of the project anymore. In these
cases, you may need to tweak the following:
```
:gcov:
:report_root: "."
:report_exclude: "^build|^vendor|^test|^support"
:report_include: "^src"
```
One important note about html_report_root: gcovr will only take a single root folder, unlike
Ceedling's ability to take as many as you like. So you will need to choose a folder which is
a superset of ALL the folders you want, and then use the include or exclude options to set up
patterns of files to pay attention to or ignore. It's not ideal, but it works.
# To-Do list
Finally, there are a number of settings which can be specified in order to adjust the
default behaviors of gcov:
```
:gcov:
:html_medium_threshold: 75
:html_high_threshold: 90
:fail_under_line: 30
:fail_under_branch: 30
```
These HTML and XML reports will be found in `build/artifacts/gcov`.
## Example Usage
```
ceedling gcov:all utils:gcov
```
## To-Do list
- Generate overall report (combined statistics from all files with coverage)
- Generate coverage output files
+14 -7
View File
@@ -11,6 +11,7 @@
- -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE
- -D$: COLLECTION_DEFINES_TEST_AND_VENDOR
- -DGCOV_COMPILER
- -DCODE_COVERAGE
- -c "${1}"
- -o "${2}"
:gcov_linker:
@@ -20,6 +21,7 @@
- -ftest-coverage
- ${1}
- -o ${2}
- ${3}
:gcov_fixture:
:executable: ${1}
:gcov_report:
@@ -36,9 +38,8 @@
:arguments:
- -p
- -b
- -e "${1}"
- ${1}
- --html
- -r .
- -o GcovCoverageResults.html
:gcov_post_report_basic:
:executable: gcovr
@@ -46,9 +47,8 @@
:arguments:
- -p
- -b
- -e "${1}"
- ${1}
- --html
- -r .
- -o "$": GCOV_ARTIFACTS_FILE
:gcov_post_report_advanced:
:executable: gcovr
@@ -56,11 +56,18 @@
:arguments:
- -p
- -b
- -e "${1}"
- ${1}
- --html
- --html-details
- -r .
- -o "$": GCOV_ARTIFACTS_FILE
:gcov_post_report_xml:
:executable: gcovr
:optional: TRUE
:arguments:
- -p
- -b
- ${1}
- --xml
- -o "$": GCOV_ARTIFACTS_FILE_XML
...
+53 -13
View File
@@ -31,11 +31,14 @@ rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_OBJECT}$/ => [
end
rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_EXECUTABLE}$/) do |bin_file|
lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments()
@ceedling[:generator].generate_executable_file(
TOOLS_GCOV_LINKER,
GCOV_SYM,
bin_file.prerequisites,
bin_file.name,
lib_args,
@ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name)
)
end
@@ -151,6 +154,17 @@ if PROJECT_USE_DEEP_DEPENDENCIES
end
namespace UTILS_SYM do
def gcov_args_builder(opts)
args = ""
args += "-r \"#{opts[:gcov_report_root] || '.'}\" "
args += "-f \"#{opts[:gcov_report_include]}\" " unless opts[:gcov_report_include].nil?
args += "-e \"#{opts[:gcov_report_exclude] || GCOV_FILTER_EXCLUDE}\" "
[ :gcov_fail_under_line, :gcov_fail_under_branch, :gcov_html_medium_threshold, :gcov_html_high_threshold].each do |opt|
args += "--#{opt.to_s.gsub('_','-').sub(/:?gcov-/,'')} #{opts[opt]} " unless opts[opt].nil?
end
return args
end
desc 'Create gcov code coverage html report (must run ceedling gcov first)'
task GCOV_SYM do
@@ -158,23 +172,49 @@ namespace UTILS_SYM do
FileUtils.mkdir_p GCOV_ARTIFACTS_PATH
end
filter = @ceedling[:configurator].project_config_hash[:gcov_html_report_filter] || GCOV_FILTER_EXPR
args = gcov_args_builder(@ceedling[:configurator].project_config_hash)
if @ceedling[:configurator].project_config_hash[:gcov_html_report_type] == 'basic'
puts "Creating a basic html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_BASIC, [], filter)
@ceedling[:tool_executor].exec(command[:line], command[:options])
elsif @ceedling[:configurator].project_config_hash[:gcov_html_report_type] == 'detailed'
puts "Creating a detailed html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_ADVANCED, [], filter)
@ceedling[:tool_executor].exec(command[:line], command[:options])
if @ceedling[:configurator].project_config_hash[:gcov_html_report].nil?
puts "In your project.yml, define: \n\n:gcov:\n :html_report:\n\n to true or false to refine this feature."
puts "For now, assumimg you want an html report generated."
html_enabled = true
else
puts "In your project.yml, define: \n\n:gcov:\n :html_report_type:\n\n to basic or detailed to refine this feature."
puts "For now, just creating basic."
puts "Creating a basic html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_BASIC, [], filter)
html_enabled = @ceedling[:configurator].project_config_hash[:gcov_html_report]
end
if @ceedling[:configurator].project_config_hash[:gcov_xml_report].nil?
puts "In your project.yml, define: \n\n:gcov:\n :xml_report:\n\n to true or false to refine this feature."
puts "For now, assumimg you do not want an xml report generated."
xml_enabled = false
else
xml_enabled = @ceedling[:configurator].project_config_hash[:gcov_xml_report]
end
if html_enabled
if @ceedling[:configurator].project_config_hash[:gcov_html_report_type] == 'basic'
puts "Creating a basic html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_BASIC, [], args)
@ceedling[:tool_executor].exec(command[:line], command[:options])
elsif @ceedling[:configurator].project_config_hash[:gcov_html_report_type] == 'detailed'
puts "Creating a detailed html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_ADVANCED, [], args)
@ceedling[:tool_executor].exec(command[:line], command[:options])
else
puts "In your project.yml, define: \n\n:gcov:\n :html_report_type:\n\n to basic or detailed to refine this feature."
puts "For now, just creating basic."
puts "Creating a basic html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_BASIC, [], args)
@ceedling[:tool_executor].exec(command[:line], command[:options])
end
end
if xml_enabled
puts "Creating an xml report of gcov results in #{GCOV_ARTIFACTS_FILE_XML}..."
command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_XML, [], filter)
@ceedling[:tool_executor].exec(command[:line], command[:options])
end
puts "Done."
end
end
+10 -3
View File
@@ -14,8 +14,7 @@ class Gcov < Plugin
project_test_results_path: GCOV_RESULTS_PATH,
project_test_dependencies_path: GCOV_DEPENDENCIES_PATH,
defines_test: DEFINES_TEST + ['CODE_COVERAGE'],
collection_defines_test_and_vendor: COLLECTION_DEFINES_TEST_AND_VENDOR + ['CODE_COVERAGE'],
gcov_html_report_filter: GCOV_FILTER_EXPR
gcov_html_report_filter: GCOV_FILTER_EXCLUDE
}
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
@@ -23,13 +22,15 @@ class Gcov < Plugin
end
def generate_coverage_object_file(source, object)
lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments()
compile_command =
@ceedling[:tool_executor].build_command_line(
TOOLS_GCOV_COMPILER,
@ceedling[:flaginator].flag_down(OPERATION_COMPILE_SYM, GCOV_SYM, source),
source,
object,
@ceedling[:file_path_utils].form_test_build_list_filepath(object)
@ceedling[:file_path_utils].form_test_build_list_filepath(object),
lib_args
)
@ceedling[:streaminator].stdout_puts("Compiling #{File.basename(source)} with coverage...")
@ceedling[:tool_executor].exec(compile_command[:line], compile_command[:options])
@@ -96,6 +97,12 @@ class Gcov < Plugin
@ceedling[:streaminator].stdout_puts(report + "\n\n")
end
end
COLLECTION_ALL_SOURCE.each do |source|
unless coverage_sources.include?(source)
@ceedling[:streaminator].stdout_puts("Could not find coverage results for " + source + "\n")
end
end
end
end
+2 -1
View File
@@ -10,9 +10,10 @@ GCOV_DEPENDENCIES_PATH = File.join(GCOV_BUILD_PATH, "dependencies")
GCOV_ARTIFACTS_PATH = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, GCOV_ROOT_NAME)
GCOV_ARTIFACTS_FILE = File.join(GCOV_ARTIFACTS_PATH, "GcovCoverageResults.html")
GCOV_ARTIFACTS_FILE_XML = File.join(GCOV_ARTIFACTS_PATH, "GcovCoverageResults.xml")
GCOV_IGNORE_SOURCES = %w(unity cmock cexception).freeze
GCOV_FILTER_EXPR = '^vendor.*|^build.*|^test.*|^lib.*'
GCOV_FILTER_EXCLUDE = '^vendor.*|^build.*|^test.*|^lib.*'
@@ -22,7 +22,10 @@ class JunitTestsReport < Plugin
def post_build
@results_list.each_key do |context|
results = @ceedling[:plugin_reportinator].assemble_test_results(@results_list[context])
file_path = File.join( PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s, 'report.xml' )
artifact_filename = @ceedling[:configurator].project_config_hash[:junit_tests_report_artifact_filename] || 'report.xml'
artifact_fullpath = @ceedling[:configurator].project_config_hash[:junit_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s)
file_path = File.join(artifact_fullpath, artifact_filename)
@ceedling[:file_wrapper].open( file_path, 'w' ) do |f|
@testsuite_counter = 0
@@ -90,7 +93,14 @@ class JunitTestsReport < Plugin
unless suite[:stdout].empty?
stream.puts(' <system-out>')
suite[:stdout].each{|line| stream.puts line }
suite[:stdout].each do |line|
line.gsub!(/&/, '&amp;')
line.gsub!(/</, '&lt;')
line.gsub!(/>/, '&gt;')
line.gsub!(/"/, '&quot;')
line.gsub!(/'/, '&apos;')
stream.puts(line)
end
stream.puts(' </system-out>')
end
@@ -98,6 +108,7 @@ class JunitTestsReport < Plugin
end
def write_test( test, stream )
test[:test].gsub!('"', '&quot;')
case test[:result]
when :success
stream.puts(' <testcase name="%<test>s" />' % test)
@@ -39,10 +39,29 @@ class ModuleGenerator < Plugin
:update_svn => ((defined? MODULE_GENERATOR_UPDATE_SVN ) ? MODULE_GENERATOR_UPDATE_SVN : false ),
}
# Read Boilerplate template file.
if (defined? MODULE_GENERATOR_BOILERPLATE_FILES)
bf = MODULE_GENERATOR_BOILERPLATE_FILES
if !bf[:src].nil? && File.exists?(bf[:src])
unity_generator_options[:boilerplates][:src] = File.read(bf[:src])
end
if !bf[:inc].nil? && File.exists?(bf[:inc])
unity_generator_options[:boilerplates][:inc] = File.read(bf[:inc])
end
if !bf[:tst].nil? && File.exists?(bf[:tst])
unity_generator_options[:boilerplates][:tst] = File.read(bf[:tst])
end
end
# If using "create[<module_root>:<module_name>]" option from command line.
unless optz[:module_root_path].to_s.empty?
unity_generator_options[:path_src] = File.join(optz[:module_root_path], unity_generator_options[:path_src])
unity_generator_options[:path_inc] = File.join(optz[:module_root_path], unity_generator_options[:path_inc])
unity_generator_options[:path_tst] = File.join(optz[:module_root_path], unity_generator_options[:path_tst])
unity_generator_options[:path_src] = File.join(optz[:module_root_path], unity_generator_options[:path_src])
unity_generator_options[:path_inc] = File.join(optz[:module_root_path], unity_generator_options[:path_inc])
unity_generator_options[:path_tst] = File.join(optz[:module_root_path], unity_generator_options[:path_tst])
end
return unity_generator_options
@@ -10,15 +10,20 @@ namespace :module do
p = files.delete(pat)
optz[:pattern] = p unless p.nil?
end
files.each {
|v|
files.each do |v|
module_root_path, module_name = v.split(module_root_separator, 2)
if module_name
optz[:module_root_path] = module_root_path
v = module_name
end
@ceedling[:module_generator].create(v, optz)
}
if (v =~ /^test_?/i)
# If the name of the file starts with test, automatically treat it as one
@ceedling[:module_generator].create(v.sub(/^test_?/i,''), optz.merge({:pattern => 'test'}))
else
# Otherwise, go through the normal procedure
@ceedling[:module_generator].create(v, optz)
end
end
end
desc "Destroy module (source, header and test files)"
@@ -29,15 +34,14 @@ namespace :module do
p = files.delete(pat)
optz[:pattern] = p unless p.nil?
end
files.each {
|v|
files.each do |v|
module_root_path, module_name = v.split(module_root_separator, 2)
if module_name
optz[:module_root_path] = module_root_path
v = module_name
end
@ceedling[:module_generator].create(v, optz)
}
end
end
end
@@ -19,7 +19,9 @@ class XmlTestsReport < Plugin
@results_list.each_key do |context|
results = @ceedling[:plugin_reportinator].assemble_test_results(@results_list[context])
file_path = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s, 'report.xml')
artifact_filename = @ceedling[:configurator].project_config_hash[:xml_tests_report_artifact_filename] || 'report.xml'
artifact_fullpath = @ceedling[:configurator].project_config_hash[:xml_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s)
file_path = File.join(artifact_fullpath, artifact_filename)
@ceedling[:file_wrapper].open(file_path, 'w') do |f|
@test_counter = 1