adding new ceedling test project
This commit is contained in:
22
test/vendor/ceedling/plugins/beep/README.md
vendored
Normal file
22
test/vendor/ceedling/plugins/beep/README.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
ceedling-beep
|
||||
=============
|
||||
|
||||
This is a simple plugin that just beeps at the end of a build and/or test sequence. Are you getting too distracted surfing
|
||||
the internet, chatting with coworkers, or swordfighting while it's building or testing? The friendly beep will let you know
|
||||
it's time to pay attention again.
|
||||
|
||||
This plugin has very few configuration options. At this time it can beep on completion of a task and/or on an error condition.
|
||||
For each of these, you can configure the method that it should beep.
|
||||
|
||||
```
|
||||
:tools:
|
||||
:beep_on_done: :bell
|
||||
:beep_on_error: :bell
|
||||
```
|
||||
|
||||
Each of these have the following options:
|
||||
|
||||
- :bell - this option uses the ASCII bell character out stdout
|
||||
- :speaker_test - this uses the linux speaker-test command if installed
|
||||
|
||||
Very likely, we'll be adding to this list if people find this to be useful.
|
||||
40
test/vendor/ceedling/plugins/beep/lib/beep.rb
vendored
Normal file
40
test/vendor/ceedling/plugins/beep/lib/beep.rb
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
|
||||
class Beep < Plugin
|
||||
|
||||
attr_reader :config
|
||||
|
||||
def setup
|
||||
@config = {
|
||||
:on_done => ((defined? TOOLS_BEEP_ON_DONE) ? TOOLS_BEEP_ON_DONE : :bell ),
|
||||
:on_error => ((defined? TOOLS_BEEP_ON_ERROR) ? TOOLS_BEEP_ON_ERROR : :bell ),
|
||||
}
|
||||
end
|
||||
|
||||
def post_build
|
||||
beep @config[:on_done]
|
||||
end
|
||||
|
||||
def post_error
|
||||
beep @config[:on_error]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def beep(method = :none)
|
||||
case method
|
||||
when :bell
|
||||
if (SystemWrapper.windows?)
|
||||
puts "echo '\007'"
|
||||
else
|
||||
puts "echo -ne '\007'"
|
||||
end
|
||||
when :speaker_test
|
||||
`speaker-test -t sine -f 1000 -l 1`
|
||||
else
|
||||
#do nothing with illegal or :none
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
15
test/vendor/ceedling/plugins/bullseye/assets/template.erb
vendored
Normal file
15
test/vendor/ceedling/plugins/bullseye/assets/template.erb
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
% function_string = hash[:coverage][:functions].to_s
|
||||
% branch_string = hash[:coverage][:branches].to_s
|
||||
% format_string = "%#{[function_string.length, branch_string.length].max}i"
|
||||
<%=@ceedling[:plugin_reportinator].generate_banner("#{hash[:header]}: CODE COVERAGE SUMMARY")%>
|
||||
% if (!hash[:coverage][:functions].nil?)
|
||||
FUNCTIONS: <%=sprintf(format_string, hash[:coverage][:functions])%>%
|
||||
% else
|
||||
FUNCTIONS: none
|
||||
% end
|
||||
% if (!hash[:coverage][:branches].nil?)
|
||||
BRANCHES: <%=sprintf(format_string, hash[:coverage][:branches])%>%
|
||||
% else
|
||||
BRANCHES: none
|
||||
% end
|
||||
|
||||
169
test/vendor/ceedling/plugins/bullseye/bullseye.rake
vendored
Normal file
169
test/vendor/ceedling/plugins/bullseye/bullseye.rake
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
directory(BULLSEYE_BUILD_OUTPUT_PATH)
|
||||
directory(BULLSEYE_RESULTS_PATH)
|
||||
directory(BULLSEYE_ARTIFACTS_PATH)
|
||||
directory(BULLSEYE_DEPENDENCIES_PATH)
|
||||
|
||||
CLEAN.include(File.join(BULLSEYE_BUILD_OUTPUT_PATH, '*'))
|
||||
CLEAN.include(File.join(BULLSEYE_RESULTS_PATH, '*'))
|
||||
CLEAN.include(File.join(BULLSEYE_DEPENDENCIES_PATH, '*'))
|
||||
|
||||
CLOBBER.include(File.join(BULLSEYE_BUILD_PATH, '**/*'))
|
||||
PLUGINS_BULLSEYE_LIB_PATH = 'C:\\tools\\BullseyeCoverage\\lib' if not defined?(PLUGINS_BULLSEYE_LIB_PATH)
|
||||
|
||||
rule(/#{BULLSEYE_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[:file_finder].find_compilation_input_file(task_name)
|
||||
end
|
||||
]) do |object|
|
||||
|
||||
if File.basename(object.source) =~ /^(#{PROJECT_TEST_FILE_PREFIX}|#{CMOCK_MOCK_PREFIX}|#{BULLSEYE_IGNORE_SOURCES.join('|')})/i
|
||||
@ceedling[:generator].generate_object_file(
|
||||
TOOLS_BULLSEYE_COMPILER,
|
||||
OPERATION_COMPILE_SYM,
|
||||
BULLSEYE_SYM,
|
||||
object.source,
|
||||
object.name,
|
||||
@ceedling[:file_path_utils].form_test_build_list_filepath(object.name)
|
||||
)
|
||||
else
|
||||
@ceedling[BULLSEYE_SYM].generate_coverage_object_file(object.source, object.name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
rule(/#{BULLSEYE_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_EXECUTABLE}$/) do |bin_file|
|
||||
@ceedling[:generator].generate_executable_file(
|
||||
TOOLS_BULLSEYE_LINKER,
|
||||
BULLSEYE_SYM,
|
||||
bin_file.prerequisites,
|
||||
bin_file.name,
|
||||
@ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name)
|
||||
)
|
||||
end
|
||||
|
||||
rule(/#{BULLSEYE_RESULTS_PATH}\/#{'.+\\'+EXTENSION_TESTPASS}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[:file_path_utils].form_test_executable_filepath(task_name)
|
||||
end
|
||||
]) do |test_result|
|
||||
@ceedling[:generator].generate_test_results(TOOLS_BULLSEYE_FIXTURE, BULLSEYE_SYM, test_result.source, test_result.name)
|
||||
end
|
||||
|
||||
rule(/#{BULLSEYE_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[:file_finder].find_compilation_input_file(task_name)
|
||||
end
|
||||
]) do |dep|
|
||||
@ceedling[:generator].generate_dependencies_file(
|
||||
TOOLS_TEST_DEPENDENCIES_GENERATOR,
|
||||
BULLSEYE_SYM,
|
||||
dep.source,
|
||||
File.join(BULLSEYE_BUILD_OUTPUT_PATH, File.basename(dep.source).ext(EXTENSION_OBJECT) ),
|
||||
dep.name
|
||||
)
|
||||
end
|
||||
|
||||
task :directories => [BULLSEYE_BUILD_OUTPUT_PATH, BULLSEYE_RESULTS_PATH, BULLSEYE_DEPENDENCIES_PATH, BULLSEYE_ARTIFACTS_PATH]
|
||||
|
||||
namespace BULLSEYE_SYM do
|
||||
task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{BULLSEYE_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}")
|
||||
|
||||
desc 'Run code coverage for all tests'
|
||||
task all: [:directories] do
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
|
||||
@ceedling[BULLSEYE_SYM].enableBullseye(true)
|
||||
@ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, BULLSEYE_SYM)
|
||||
@ceedling[:configurator].restore_config
|
||||
end
|
||||
|
||||
desc "Run single test w/ coverage ([*] real test or source file name, no path)."
|
||||
task :* do
|
||||
message = "\nOops! '#{BULLSEYE_ROOT_NAME}:*' isn't a real task. " +
|
||||
"Use a real test or source file name (no path) in place of the wildcard.\n" +
|
||||
"Example: rake #{BULLSEYE_ROOT_NAME}:foo.c\n\n"
|
||||
|
||||
@ceedling[:streaminator].stdout_puts( message )
|
||||
end
|
||||
|
||||
desc 'Run tests by matching regular expression pattern.'
|
||||
task :pattern, [:regex] => [:directories] do |_t, args|
|
||||
matches = []
|
||||
|
||||
COLLECTION_ALL_TESTS.each do |test|
|
||||
matches << test if test =~ /#{args.regex}/
|
||||
end
|
||||
|
||||
if !matches.empty?
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
|
||||
@ceedling[BULLSEYE_SYM].enableBullseye(true)
|
||||
@ceedling[:test_invoker].setup_and_invoke(matches, BULLSEYE_SYM, force_run: false)
|
||||
@ceedling[:configurator].restore_config
|
||||
else
|
||||
@ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.")
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Run tests whose test path contains [dir] or [dir] substring.'
|
||||
task :path, [:dir] => [:directories] do |_t, args|
|
||||
matches = []
|
||||
|
||||
COLLECTION_ALL_TESTS.each do |test|
|
||||
matches << test if File.dirname(test).include?(args.dir.tr('\\', '/'))
|
||||
end
|
||||
|
||||
if !matches.empty?
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
|
||||
@ceedling[BULLSEYE_SYM].enableBullseye(true)
|
||||
@ceedling[:test_invoker].setup_and_invoke(matches, BULLSEYE_SYM, force_run: false)
|
||||
@ceedling[:configurator].restore_config
|
||||
else
|
||||
@ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.")
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Run code coverage for changed files'
|
||||
task delta: [:directories] do
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
|
||||
@ceedling[BULLSEYE_SYM].enableBullseye(true)
|
||||
@ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, BULLSEYE_SYM, {:force_run => false})
|
||||
@ceedling[:configurator].restore_config
|
||||
end
|
||||
|
||||
# use a rule to increase efficiency for large projects
|
||||
# bullseye test tasks by regex
|
||||
rule(/^#{BULLSEYE_TASK_ROOT}\S+$/ => [
|
||||
proc do |task_name|
|
||||
test = task_name.sub(/#{BULLSEYE_TASK_ROOT}/, '')
|
||||
test = "#{PROJECT_TEST_FILE_PREFIX}#{test}" unless test.start_with?(PROJECT_TEST_FILE_PREFIX)
|
||||
@ceedling[:file_finder].find_test_from_file_path(test)
|
||||
end
|
||||
]) do |test|
|
||||
@ceedling[:rake_wrapper][:directories].invoke
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
|
||||
@ceedling[BULLSEYE_SYM].enableBullseye(true)
|
||||
@ceedling[:test_invoker].setup_and_invoke([test.source], BULLSEYE_SYM)
|
||||
@ceedling[:configurator].restore_config
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if PROJECT_USE_DEEP_DEPENDENCIES
|
||||
namespace REFRESH_SYM do
|
||||
task BULLSEYE_SYM do
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
|
||||
@ceedling[BULLSEYE_SYM].enableBullseye(true)
|
||||
@ceedling[:test_invoker].refresh_deep_dependencies
|
||||
@ceedling[:configurator].restore_config
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
namespace UTILS_SYM do
|
||||
|
||||
desc "Open Bullseye code coverage browser"
|
||||
task BULLSEYE_SYM do
|
||||
command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_BROWSER, [])
|
||||
@ceedling[:tool_executor].exec(command[:line], command[:options])
|
||||
end
|
||||
|
||||
end
|
||||
57
test/vendor/ceedling/plugins/bullseye/config/defaults.yml
vendored
Normal file
57
test/vendor/ceedling/plugins/bullseye/config/defaults.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
|
||||
:bullseye:
|
||||
:auto_license: TRUE
|
||||
:plugins:
|
||||
:bullseye_lib_path: []
|
||||
:paths:
|
||||
:bullseye_toolchain_include: []
|
||||
|
||||
:tools:
|
||||
:bullseye_instrumentation:
|
||||
:executable: covc
|
||||
:arguments:
|
||||
- '--file $': ENVIRONMENT_COVFILE
|
||||
- -q
|
||||
- ${1}
|
||||
:bullseye_compiler:
|
||||
:executable: gcc
|
||||
:arguments:
|
||||
- -g
|
||||
- -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR
|
||||
- -I"$": COLLECTION_PATHS_BULLSEYE_TOOLCHAIN_INCLUDE
|
||||
- -D$: COLLECTION_DEFINES_TEST_AND_VENDOR
|
||||
- -DBULLSEYE_COMPILER
|
||||
- -c "${1}"
|
||||
- -o "${2}"
|
||||
:bullseye_linker:
|
||||
:executable: gcc
|
||||
:arguments:
|
||||
- ${1}
|
||||
- -o ${2}
|
||||
- -L$: PLUGINS_BULLSEYE_LIB_PATH
|
||||
- -lcov
|
||||
:bullseye_fixture:
|
||||
:executable: ${1}
|
||||
:bullseye_report_covsrc:
|
||||
:executable: covsrc
|
||||
:arguments:
|
||||
- '--file $': ENVIRONMENT_COVFILE
|
||||
- -q
|
||||
- -w140
|
||||
:bullseye_report_covfn:
|
||||
:executable: covfn
|
||||
:stderr_redirect: :auto
|
||||
:arguments:
|
||||
- '--file $': ENVIRONMENT_COVFILE
|
||||
- --width 120
|
||||
- --no-source
|
||||
- '"${1}"'
|
||||
:bullseye_browser:
|
||||
:executable: CoverageBrowser
|
||||
:background_exec: :auto
|
||||
:optional: TRUE
|
||||
:arguments:
|
||||
- '"$"': ENVIRONMENT_COVFILE
|
||||
|
||||
...
|
||||
194
test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb
vendored
Normal file
194
test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
|
||||
BULLSEYE_ROOT_NAME = 'bullseye'
|
||||
BULLSEYE_TASK_ROOT = BULLSEYE_ROOT_NAME + ':'
|
||||
BULLSEYE_SYM = BULLSEYE_ROOT_NAME.to_sym
|
||||
|
||||
BULLSEYE_BUILD_PATH = "#{PROJECT_BUILD_ROOT}/#{BULLSEYE_ROOT_NAME}"
|
||||
BULLSEYE_BUILD_OUTPUT_PATH = "#{BULLSEYE_BUILD_PATH}/out"
|
||||
BULLSEYE_RESULTS_PATH = "#{BULLSEYE_BUILD_PATH}/results"
|
||||
BULLSEYE_DEPENDENCIES_PATH = "#{BULLSEYE_BUILD_PATH}/dependencies"
|
||||
BULLSEYE_ARTIFACTS_PATH = "#{PROJECT_BUILD_ARTIFACTS_ROOT}/#{BULLSEYE_ROOT_NAME}"
|
||||
|
||||
BULLSEYE_IGNORE_SOURCES = ['unity', 'cmock', 'cexception']
|
||||
|
||||
|
||||
class Bullseye < Plugin
|
||||
|
||||
def setup
|
||||
@result_list = []
|
||||
@environment = [ {:covfile => File.join( BULLSEYE_ARTIFACTS_PATH, 'test.cov' )} ]
|
||||
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
@coverage_template_all = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb'))
|
||||
end
|
||||
|
||||
def config
|
||||
{
|
||||
:project_test_build_output_path => BULLSEYE_BUILD_OUTPUT_PATH,
|
||||
:project_test_results_path => BULLSEYE_RESULTS_PATH,
|
||||
:project_test_dependencies_path => BULLSEYE_DEPENDENCIES_PATH,
|
||||
:defines_test => DEFINES_TEST + ['CODE_COVERAGE'],
|
||||
:collection_defines_test_and_vendor => COLLECTION_DEFINES_TEST_AND_VENDOR + ['CODE_COVERAGE']
|
||||
}
|
||||
end
|
||||
|
||||
def generate_coverage_object_file(source, object)
|
||||
arg_hash = {:tool => TOOLS_BULLSEYE_INSTRUMENTATION, :context => BULLSEYE_SYM, :source => source, :object => object}
|
||||
@ceedling[:plugin_manager].pre_compile_execute(arg_hash)
|
||||
|
||||
@ceedling[:streaminator].stdout_puts("Compiling #{File.basename(source)} with coverage...")
|
||||
compile_command =
|
||||
@ceedling[:tool_executor].build_command_line(
|
||||
TOOLS_BULLSEYE_COMPILER,
|
||||
@ceedling[:flaginator].flag_down( OPERATION_COMPILE_SYM, BULLSEYE_SYM, source ),
|
||||
source,
|
||||
object,
|
||||
@ceedling[:file_path_utils].form_test_build_list_filepath( object ) )
|
||||
coverage_command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_INSTRUMENTATION, [], compile_command[:line] )
|
||||
|
||||
shell_result = @ceedling[:tool_executor].exec( coverage_command[:line], coverage_command[:options] )
|
||||
|
||||
arg_hash[:shell_result] = shell_result
|
||||
@ceedling[:plugin_manager].post_compile_execute(arg_hash)
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
result_file = arg_hash[:result_file]
|
||||
|
||||
if ((result_file =~ /#{BULLSEYE_RESULTS_PATH}/) and (not @result_list.include?(result_file)))
|
||||
@result_list << arg_hash[:result_file]
|
||||
end
|
||||
end
|
||||
|
||||
def post_build
|
||||
return if (not @ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}/))
|
||||
|
||||
# test results
|
||||
results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
|
||||
hash = {
|
||||
:header => BULLSEYE_ROOT_NAME.upcase,
|
||||
:results => results
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash) do
|
||||
message = ''
|
||||
message = 'Unit test failures.' if (results[:counts][:failed] > 0)
|
||||
message
|
||||
end
|
||||
|
||||
# coverage results
|
||||
return if (verify_coverage_file() == false)
|
||||
if (@ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}(all|delta)/))
|
||||
command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVSRC, [])
|
||||
shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options])
|
||||
report_coverage_results_all(shell_result[:output])
|
||||
else
|
||||
report_per_function_coverage_results(@ceedling[:test_invoker].sources)
|
||||
end
|
||||
end
|
||||
|
||||
def summary
|
||||
return if (verify_coverage_file() == false)
|
||||
result_list = @ceedling[:file_path_utils].form_pass_results_filelist( BULLSEYE_RESULTS_PATH, COLLECTION_ALL_TESTS )
|
||||
|
||||
# test results
|
||||
# get test results for only those tests in our configuration and of those only tests with results on disk
|
||||
hash = {
|
||||
:header => BULLSEYE_ROOT_NAME.upcase,
|
||||
:results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false})
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash)
|
||||
|
||||
# coverage results
|
||||
command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVSRC)
|
||||
shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options])
|
||||
report_coverage_results_all(shell_result[:output])
|
||||
end
|
||||
|
||||
def enableBullseye(enable)
|
||||
if BULLSEYE_AUTO_LICENSE
|
||||
if (enable)
|
||||
args = ['push', 'on']
|
||||
@ceedling[:streaminator].stdout_puts("Enabling Bullseye")
|
||||
else
|
||||
args = ['pop']
|
||||
@ceedling[:streaminator].stdout_puts("Reverting Bullseye to previous state")
|
||||
end
|
||||
|
||||
args.each do |arg|
|
||||
command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_BUILD_ENABLE_DISABLE, [], arg)
|
||||
shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options])
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
private ###################################
|
||||
|
||||
def report_coverage_results_all(coverage)
|
||||
results = {
|
||||
:header => BULLSEYE_ROOT_NAME.upcase,
|
||||
:coverage => {
|
||||
:functions => nil,
|
||||
:branches => nil
|
||||
}
|
||||
}
|
||||
|
||||
if (coverage =~ /^Total.*?=\s+([0-9]+)\%/)
|
||||
results[:coverage][:functions] = $1.to_i
|
||||
end
|
||||
|
||||
if (coverage =~ /^Total.*=\s+([0-9]+)\%\s*$/)
|
||||
results[:coverage][:branches] = $1.to_i
|
||||
end
|
||||
|
||||
@ceedling[:plugin_reportinator].run_report($stdout, @coverage_template_all, results)
|
||||
end
|
||||
|
||||
def report_per_function_coverage_results(sources)
|
||||
banner = @ceedling[:plugin_reportinator].generate_banner( "#{BULLSEYE_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" )
|
||||
@ceedling[:streaminator].stdout_puts "\n" + banner
|
||||
|
||||
coverage_sources = sources.clone
|
||||
coverage_sources.delete_if {|item| item =~ /#{CMOCK_MOCK_PREFIX}.+#{EXTENSION_SOURCE}$/}
|
||||
coverage_sources.delete_if {|item| item =~ /#{BULLSEYE_IGNORE_SOURCES.join('|')}#{EXTENSION_SOURCE}$/}
|
||||
|
||||
coverage_sources.each do |source|
|
||||
command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVFN, [], source)
|
||||
shell_results = @ceedling[:tool_executor].exec(command[:line], command[:options])
|
||||
coverage_results = shell_results[:output].deep_clone
|
||||
coverage_results.sub!(/.*\n.*\n/,'') # Remove the Bullseye tool banner
|
||||
if (coverage_results =~ /warning cov814: report is empty/)
|
||||
coverage_results = "WARNING: #{source} contains no coverage data!\n\n"
|
||||
@ceedling[:streaminator].stdout_puts(coverage_results, Verbosity::COMPLAIN)
|
||||
else
|
||||
coverage_results += "\n"
|
||||
@ceedling[:streaminator].stdout_puts(coverage_results)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def verify_coverage_file
|
||||
exist = @ceedling[:file_wrapper].exist?( ENVIRONMENT_COVFILE )
|
||||
|
||||
if (!exist)
|
||||
banner = @ceedling[:plugin_reportinator].generate_banner( "#{BULLSEYE_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" )
|
||||
@ceedling[:streaminator].stdout_puts "\n" + banner + "\nNo coverage file.\n\n"
|
||||
end
|
||||
|
||||
return exist
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# end blocks always executed following rake run
|
||||
END {
|
||||
# cache our input configurations to use in comparison upon next execution
|
||||
if (@ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}/))
|
||||
@ceedling[:cacheinator].cache_test_config( @ceedling[:setupinator].config_hash )
|
||||
@ceedling[BULLSEYE_SYM].enableBullseye(false)
|
||||
end
|
||||
}
|
||||
0
test/vendor/ceedling/plugins/bullseye/readme.txt
vendored
Normal file
0
test/vendor/ceedling/plugins/bullseye/readme.txt
vendored
Normal file
52
test/vendor/ceedling/plugins/command_hooks/README.md
vendored
Normal file
52
test/vendor/ceedling/plugins/command_hooks/README.md
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
ceedling-command-hooks
|
||||
======================
|
||||
|
||||
Plugin for easily calling command line tools at various points in the build process
|
||||
|
||||
Define any of these sections in :tools: to provide additional hooks to be called on demand:
|
||||
|
||||
```
|
||||
:pre_mock_generate
|
||||
:post_mock_generate
|
||||
:pre_runner_generate
|
||||
:post_runner_generate
|
||||
:pre_compile_execute
|
||||
:post_compile_execute
|
||||
:pre_link_execute
|
||||
:post_link_execute
|
||||
:pre_test_fixture_execute
|
||||
:pre_test_fixture_execute
|
||||
:pre_test
|
||||
:post_test
|
||||
:pre_release
|
||||
:post_release
|
||||
:pre_build
|
||||
:post_build
|
||||
```
|
||||
|
||||
Each of these tools can support an :executable string and an :args list, like so:
|
||||
|
||||
```
|
||||
:tools:
|
||||
:post_link_execute:
|
||||
:executable: objcopy.exe
|
||||
:args:
|
||||
- ${1} #This is replaced with the executable name
|
||||
- output.srec
|
||||
- --strip-all
|
||||
```
|
||||
|
||||
You may also specify an array of executables to be called in a particular place, like so:
|
||||
|
||||
```
|
||||
:tools:
|
||||
:post_test:
|
||||
- :executable: echo
|
||||
:args: "${1} was glorious!"
|
||||
- :executable: echo
|
||||
:args:
|
||||
- it kinda made me cry a little.
|
||||
- you?
|
||||
```
|
||||
|
||||
Happy Tweaking!
|
||||
75
test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb
vendored
Normal file
75
test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
|
||||
class CommandHooks < Plugin
|
||||
|
||||
attr_reader :config
|
||||
|
||||
def setup
|
||||
@config = {
|
||||
:pre_mock_generate => ((defined? TOOLS_PRE_MOCK_GENERATE) ? TOOLS_PRE_MOCK_GENERATE : nil ),
|
||||
:post_mock_generate => ((defined? TOOLS_POST_MOCK_GENERATE) ? TOOLS_POST_MOCK_GENERATE : nil ),
|
||||
:pre_runner_generate => ((defined? TOOLS_PRE_RUNNER_GENERATE) ? TOOLS_PRE_RUNNER_GENERATE : nil ),
|
||||
:post_runner_generate => ((defined? TOOLS_POST_RUNNER_GENERATE) ? TOOLS_POST_RUNNER_GENERATE : nil ),
|
||||
:pre_compile_execute => ((defined? TOOLS_PRE_COMPILE_EXECUTE) ? TOOLS_PRE_COMPILE_EXECUTE : nil ),
|
||||
:post_compile_execute => ((defined? TOOLS_POST_COMPILE_EXECUTE) ? TOOLS_POST_COMPILE_EXECUTE : nil ),
|
||||
:pre_link_execute => ((defined? TOOLS_PRE_LINK_EXECUTE) ? TOOLS_PRE_LINK_EXECUTE : nil ),
|
||||
:post_link_execute => ((defined? TOOLS_POST_LINK_EXECUTE) ? TOOLS_POST_LINK_EXECUTE : nil ),
|
||||
:pre_test_fixture_execute => ((defined? TOOLS_PRE_TEST_FIXTURE_EXECUTE) ? TOOLS_PRE_TEST_FIXTURE_EXECUTE : nil ),
|
||||
:post_test_fixture_execute => ((defined? TOOLS_POST_TEST_FIXTURE_EXECUTE) ? TOOLS_POST_TEST_FIXTURE_EXECUTE : nil ),
|
||||
:pre_test => ((defined? TOOLS_PRE_TEST) ? TOOLS_PRE_TEST : nil ),
|
||||
:post_test => ((defined? TOOLS_POST_TEST) ? TOOLS_POST_TEST : nil ),
|
||||
:pre_release => ((defined? TOOLS_PRE_RELEASE) ? TOOLS_PRE_RELEASE : nil ),
|
||||
: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__), '..'))
|
||||
end
|
||||
|
||||
def pre_mock_generate(arg_hash); run_hook(:pre_mock_generate, arg_hash[:header_file] ); end
|
||||
def post_mock_generate(arg_hash); run_hook(:post_mock_generate, arg_hash[:header_file] ); end
|
||||
def pre_runner_generate(arg_hash); run_hook(:pre_runner_generate, arg_hash[:source ] ); end
|
||||
def post_runner_generate(arg_hash); run_hook(:post_runner_generate, arg_hash[:runner_file] ); end
|
||||
def pre_compile_execute(arg_hash); run_hook(:pre_compile_execute, arg_hash[:source_file] ); end
|
||||
def post_compile_execute(arg_hash); run_hook(:post_compile_execute, arg_hash[:object_file] ); end
|
||||
def pre_link_execute(arg_hash); run_hook(:pre_link_execute, arg_hash[:executable] ); end
|
||||
def post_link_execute(arg_hash); run_hook(:post_link_execute, arg_hash[:executable] ); end
|
||||
def pre_test_fixture_execute(arg_hash); run_hook(:pre_test_fixture_execute, arg_hash[:executable] ); end
|
||||
def post_test_fixture_execute(arg_hash); run_hook(:post_test_fixture_execute, arg_hash[:executable] ); end
|
||||
def pre_test(test); run_hook(:pre_test, test ); end
|
||||
def post_test(test); run_hook(:post_test, test ); end
|
||||
def pre_release; run_hook(:pre_release ); end
|
||||
def post_release; run_hook(:post_release ); end
|
||||
def pre_build; run_hook(:pre_build ); end
|
||||
def post_build; run_hook(:post_build ); end
|
||||
def post_error; run_hook(:post_error ); end
|
||||
|
||||
private
|
||||
|
||||
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] )
|
||||
end
|
||||
end
|
||||
|
||||
def run_hook(which_hook, name="")
|
||||
if (@config[which_hook])
|
||||
@ceedling[:streaminator].stdout_puts("Running Hook #{which_hook}...", Verbosity::NORMAL)
|
||||
if (@config[which_hook].is_a? Array)
|
||||
@config[which_hook].each do |hook|
|
||||
run_hook_step(hook, name)
|
||||
end
|
||||
elsif (@config[which_hook].is_a? Hash)
|
||||
run_hook_step( @config[which_hook], name )
|
||||
else
|
||||
@ceedling[:streaminator].stdout_puts("Hook #{which_hook} was poorly formed", Verbosity::COMPLAINT)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
250
test/vendor/ceedling/plugins/fake_function_framework/README.md
vendored
Normal file
250
test/vendor/ceedling/plugins/fake_function_framework/README.md
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
# A Fake Function Framework Plug-in for Ceedling
|
||||
|
||||
This is a plug-in for [Ceedling](https://github.com/ThrowTheSwitch/Ceedling) to use the [Fake Function Framework](https://github.com/meekrosoft/fff) for mocking instead of CMock.
|
||||
|
||||
Using fff provides less strict mocking than CMock, and allows for more loosely-coupled tests.
|
||||
And, when tests fail -- since you get the actual line number of the failure -- it's a lot easier to figure out what went wrong.
|
||||
|
||||
## Installing the plug-in
|
||||
|
||||
To use the plugin you need to 1) get the contents of this repo and 2) configure your project to use it.
|
||||
|
||||
### Get the source
|
||||
|
||||
The easiest way to get the source is to just clone this repo into the Ceedling plugin folder for your existing Ceedling project.
|
||||
(Don't have a Ceedling project already? [Here are instructions to create one.](http://www.electronvector.com/blog/try-embedded-test-driven-development-right-now-with-ceedling))
|
||||
From within `<your-project>/vendor/ceedling/plugins`, run:
|
||||
|
||||
`git clone https://github.com/ElectronVector/fake_function_framework.git`
|
||||
|
||||
This will create a new folder named `fake_function_framework` in the plugins folder.
|
||||
|
||||
### Enable the plug-in.
|
||||
|
||||
The plug-in is enabled from within your project.yml file.
|
||||
|
||||
In the `:plugins` configuration, add `fake_function_framework` to the list of enabled plugins:
|
||||
|
||||
```yaml
|
||||
:plugins:
|
||||
:load_paths:
|
||||
- vendor/ceedling/plugins
|
||||
:enabled:
|
||||
- stdout_pretty_tests_report
|
||||
- module_generator
|
||||
- fake_function_framework
|
||||
```
|
||||
*Note that you could put the plugin source in some other loaction.
|
||||
In that case you'd need to add a new path the `:load_paths`.*
|
||||
|
||||
## How to use it
|
||||
|
||||
You use fff with Ceedling the same way you used to use CMock.
|
||||
Modules can still be generated with the default module generator: `rake module:create[my_module]`.
|
||||
If you want to "mock" `some_module.h` in your tests, just `#include "mock_some_module.h"`.
|
||||
This creates a fake function for each of the functions defined in `some_module.h`.
|
||||
|
||||
The name of each fake is the original function name with an appended `_fake`.
|
||||
For example, if we're generating fakes for a stack module with `push` and `pop` functions, we would have the fakes `push_fake` and `pop_fake`.
|
||||
These fakes are linked into our test executable so that any time our unit under test calls `push` or `pop` our fakes are called instead.
|
||||
|
||||
Each of these fakes is actually a structure containing information about how the function was called, and what it might return.
|
||||
We can use Unity to inspect these fakes in our tests, and verify the interactions of our units.
|
||||
There is also a global structure named `fff` which we can use to check the sequence of calls.
|
||||
|
||||
The fakes can also be configured to return particular values, so you can exercise the unit under test however you want.
|
||||
|
||||
The examples below explain how to use fff to test a variety of module interactions.
|
||||
Each example uses fakes for a "display" module, created from a display.h file with `#include "mock_display.h"`. The `display.h` file must exist and must contain the prototypes for the functions to be faked.
|
||||
|
||||
### Test that a function was called once
|
||||
|
||||
```c
|
||||
void
|
||||
test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff()
|
||||
{
|
||||
// When
|
||||
event_deviceReset();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count);
|
||||
}
|
||||
```
|
||||
|
||||
### Test that a function was NOT called
|
||||
|
||||
```c
|
||||
void
|
||||
test_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void)
|
||||
{
|
||||
// When
|
||||
event_powerReadingUpdate(4);
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count);
|
||||
}
|
||||
```
|
||||
|
||||
## Test that a single function was called with the correct argument
|
||||
|
||||
```c
|
||||
void
|
||||
test_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void)
|
||||
{
|
||||
// When
|
||||
event_volumeKnobMaxed();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count);
|
||||
TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val);
|
||||
}
|
||||
```
|
||||
|
||||
## Test that calls are made in a particular sequence
|
||||
|
||||
```c
|
||||
void
|
||||
test_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void)
|
||||
{
|
||||
// When
|
||||
event_modeSelectButtonPressed();
|
||||
event_modeSelectButtonPressed();
|
||||
event_modeSelectButtonPressed();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMinimum, fff.call_history[0]);
|
||||
TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMaximum, fff.call_history[1]);
|
||||
TEST_ASSERT_EQUAL_PTR((void*)display_setModeToAverage, fff.call_history[2]);
|
||||
}
|
||||
```
|
||||
|
||||
## Fake a return value from a function
|
||||
|
||||
```c
|
||||
void
|
||||
test_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void)
|
||||
{
|
||||
// Given
|
||||
display_isError_fake.return_val = true;
|
||||
|
||||
// When
|
||||
event_devicePoweredOn();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);
|
||||
}
|
||||
```
|
||||
|
||||
## Fake a function with a value returned by reference
|
||||
|
||||
```c
|
||||
void
|
||||
test_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void)
|
||||
{
|
||||
// Given
|
||||
char mockedEntry[] = "sleep";
|
||||
void return_mock_value(char * entry, int length)
|
||||
{
|
||||
if (length > strlen(mockedEntry))
|
||||
{
|
||||
strncpy(entry, mockedEntry, length);
|
||||
}
|
||||
}
|
||||
display_getKeyboardEntry_fake.custom_fake = return_mock_value;
|
||||
|
||||
// When
|
||||
event_keyboardCheckTimerExpired();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);
|
||||
}
|
||||
```
|
||||
|
||||
## Fake a function with a function pointer parameter
|
||||
|
||||
```
|
||||
void
|
||||
test_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void)
|
||||
{
|
||||
// A mock function for capturing the callback handler function pointer.
|
||||
void(*registeredCallback)(void) = 0;
|
||||
void mock_display_updateData(int data, void(*callback)(void))
|
||||
{
|
||||
//Save the callback function.
|
||||
registeredCallback = callback;
|
||||
}
|
||||
display_updateData_fake.custom_fake = mock_display_updateData;
|
||||
|
||||
// Given
|
||||
event_newDataAvailable(10);
|
||||
|
||||
// When
|
||||
if (registeredCallback != 0)
|
||||
{
|
||||
registeredCallback();
|
||||
}
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete());
|
||||
}
|
||||
```
|
||||
|
||||
## Helper macros
|
||||
|
||||
For convenience, there are also some helper macros that create new Unity-style asserts:
|
||||
|
||||
- `TEST_ASSERT_CALLED(function)`: Asserts that a function was called once.
|
||||
- `TEST_ASSERT_NOT_CALLED(function)`: Asserts that a function was never called.
|
||||
- `TEST_ASSERT_CALLED_TIMES(times, function)`: Asserts that a function was called a particular number of times.
|
||||
- `TEST_ASSERT_CALLED_IN_ORDER(order, function)`: Asserts that a function was called in a particular order.
|
||||
|
||||
Here's how you might use one of these instead of simply checking the call_count value:
|
||||
|
||||
```c
|
||||
void
|
||||
test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff()
|
||||
{
|
||||
// When
|
||||
event_deviceReset();
|
||||
|
||||
// Then
|
||||
// This how to directly use fff...
|
||||
TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count);
|
||||
// ...and this is how to use the helper macro.
|
||||
TEST_ASSERT_CALLED(display_turnOffStatusLed);
|
||||
}
|
||||
```
|
||||
|
||||
## Test setup
|
||||
|
||||
All of the fake functions, and any fff global state are all reset automatically between each test.
|
||||
|
||||
## CMock configuration
|
||||
|
||||
Use still use some of the CMock configuration options for setting things like the mock prefix, and for including additional header files in the mock files.
|
||||
|
||||
```yaml
|
||||
:cmock:
|
||||
:mock_prefix: mock_
|
||||
:includes:
|
||||
-
|
||||
:includes_h_pre_orig_header:
|
||||
-
|
||||
:includes_h_post_orig_header:
|
||||
-
|
||||
:includes_c_pre_header:
|
||||
-
|
||||
:includes_c_post_header:
|
||||
```
|
||||
|
||||
## Running the tests
|
||||
|
||||
There are unit and integration tests for the plug-in itself.
|
||||
These are run with the default `rake` task.
|
||||
The integration test runs the tests for the example project in examples/fff_example.
|
||||
For the integration tests to succeed, this repository must be placed in a Ceedling tree in the plugins folder.
|
||||
|
||||
## More examples
|
||||
|
||||
There is an example project in examples/fff_example.
|
||||
It shows how to use the plug-in with some full-size examples.
|
||||
19
test/vendor/ceedling/plugins/fake_function_framework/Rakefile
vendored
Normal file
19
test/vendor/ceedling/plugins/fake_function_framework/Rakefile
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
require 'rake'
|
||||
require 'rspec/core/rake_task'
|
||||
|
||||
desc "Run all rspecs"
|
||||
RSpec::Core::RakeTask.new(:spec) do |t|
|
||||
t.pattern = Dir.glob('spec/**/*_spec.rb')
|
||||
t.rspec_opts = '--format documentation'
|
||||
# t.rspec_opts << ' more options'
|
||||
end
|
||||
|
||||
desc "Run integration test on example"
|
||||
task :integration_test do
|
||||
chdir("./examples/fff_example") do
|
||||
sh "rake clobber"
|
||||
sh "rake test:all"
|
||||
end
|
||||
end
|
||||
|
||||
task :default => [:spec, :integration_test]
|
||||
71
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml
vendored
Normal file
71
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
|
||||
# Notes:
|
||||
# Sample project C code is not presently written to produce a release artifact.
|
||||
# As such, release build options are disabled.
|
||||
# This sample, therefore, only demonstrates running a collection of unit tests.
|
||||
|
||||
:project:
|
||||
:use_exceptions: FALSE
|
||||
:use_test_preprocessor: TRUE
|
||||
:use_auxiliary_dependencies: TRUE
|
||||
:build_root: build
|
||||
# :release_build: TRUE
|
||||
:test_file_prefix: test_
|
||||
|
||||
#:release_build:
|
||||
# :output: MyApp.out
|
||||
# :use_assembly: FALSE
|
||||
|
||||
:environment:
|
||||
|
||||
:extension:
|
||||
:executable: .out
|
||||
|
||||
:paths:
|
||||
:test:
|
||||
- +:test/**
|
||||
:source:
|
||||
- src/**
|
||||
:support:
|
||||
|
||||
:defines:
|
||||
# in order to add common defines:
|
||||
# 1) remove the trailing [] from the :common: section
|
||||
# 2) add entries to the :common: section (e.g. :test: has TEST defined)
|
||||
:commmon: &common_defines []
|
||||
:test:
|
||||
- *common_defines
|
||||
- TEST
|
||||
:test_preprocess:
|
||||
- *common_defines
|
||||
- TEST
|
||||
|
||||
:cmock:
|
||||
:mock_prefix: mock_
|
||||
:when_no_prototypes: :warn
|
||||
:enforce_strict_ordering: TRUE
|
||||
:plugins:
|
||||
- :ignore
|
||||
- :callback
|
||||
:treat_as:
|
||||
uint8: HEX8
|
||||
uint16: HEX16
|
||||
uint32: UINT32
|
||||
int8: INT8
|
||||
bool: UINT8
|
||||
|
||||
#:tools:
|
||||
# Ceedling defaults to using gcc for compiling, linking, etc.
|
||||
# As [:tools] is blank, gcc will be used (so long as it's in your system path)
|
||||
# See documentation to configure a given toolchain for use
|
||||
|
||||
:plugins:
|
||||
:load_paths:
|
||||
# This change from the default is for running Ceedling out of another folder.
|
||||
- ../../../../plugins
|
||||
:enabled:
|
||||
- stdout_pretty_tests_report
|
||||
- module_generator
|
||||
- fake_function_framework
|
||||
...
|
||||
7
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb
vendored
Normal file
7
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# This change from the default is for running Ceedling out of another folder.
|
||||
PROJECT_CEEDLING_ROOT = "../../../.."
|
||||
load "#{PROJECT_CEEDLING_ROOT}/lib/ceedling.rb"
|
||||
|
||||
Ceedling.load_project
|
||||
|
||||
task :default => %w[ test:all release ]
|
||||
1
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c
vendored
Normal file
1
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c
vendored
Normal file
@@ -0,0 +1 @@
|
||||
#include "bar.h"
|
||||
14
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h
vendored
Normal file
14
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef bar_H
|
||||
#define bar_H
|
||||
|
||||
#include "custom_types.h"
|
||||
|
||||
void bar_turn_on(void);
|
||||
void bar_print_message(const char * message);
|
||||
void bar_print_message_formatted(const char * format, ...);
|
||||
void bar_numbers(int one, int two, char three);
|
||||
void bar_const_test(const char * a, char * const b, const int c);
|
||||
custom_t bar_needs_custom_type(void);
|
||||
const char * bar_return_const_ptr(int one);
|
||||
|
||||
#endif // bar_H
|
||||
6
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h
vendored
Normal file
6
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef custom_types_H
|
||||
#define custom_types_H
|
||||
|
||||
typedef int custom_t;
|
||||
|
||||
#endif
|
||||
7
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c
vendored
Normal file
7
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include "display.h"
|
||||
|
||||
void display_turnOffStatusLed(void)
|
||||
{
|
||||
printf("Display: Status LED off");
|
||||
}
|
||||
16
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h
vendored
Normal file
16
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
void display_turnOffStatusLed(void);
|
||||
void display_turnOnStatusLed(void);
|
||||
void display_setVolume(int level);
|
||||
void display_setModeToMinimum(void);
|
||||
void display_setModeToMaximum(void);
|
||||
void display_setModeToAverage(void);
|
||||
bool display_isError(void);
|
||||
void display_powerDown(void);
|
||||
void display_updateData(int data, void(*updateCompleteCallback)(void));
|
||||
|
||||
/*
|
||||
The entry is returned (up to `length` bytes) in the provided `entry` buffer.
|
||||
*/
|
||||
void display_getKeyboardEntry(char * entry, int length);
|
||||
93
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c
vendored
Normal file
93
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
This module implements some business logic to test.
|
||||
|
||||
Signal events by calling the functions on the module.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "event_processor.h"
|
||||
#include "display.h"
|
||||
|
||||
void event_deviceReset(void)
|
||||
{
|
||||
//printf ("Device reset\n");
|
||||
display_turnOffStatusLed();
|
||||
}
|
||||
|
||||
void event_volumeKnobMaxed(void)
|
||||
{
|
||||
display_setVolume(11);
|
||||
}
|
||||
|
||||
void event_powerReadingUpdate(int powerReading)
|
||||
{
|
||||
if (powerReading >= 5)
|
||||
{
|
||||
display_turnOnStatusLed();
|
||||
}
|
||||
}
|
||||
|
||||
void event_modeSelectButtonPressed(void)
|
||||
{
|
||||
static int mode = 0;
|
||||
|
||||
if (mode == 0)
|
||||
{
|
||||
display_setModeToMinimum();
|
||||
mode++;
|
||||
}
|
||||
else if (mode == 1)
|
||||
{
|
||||
display_setModeToMaximum();
|
||||
mode++;
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
display_setModeToAverage();
|
||||
mode++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void event_devicePoweredOn(void)
|
||||
{
|
||||
if (display_isError())
|
||||
{
|
||||
display_powerDown();
|
||||
}
|
||||
}
|
||||
|
||||
void event_keyboardCheckTimerExpired(void)
|
||||
{
|
||||
char userEntry[100];
|
||||
|
||||
display_getKeyboardEntry(userEntry, 100);
|
||||
|
||||
if (strcmp(userEntry, "sleep") == 0)
|
||||
{
|
||||
display_powerDown();
|
||||
}
|
||||
}
|
||||
|
||||
static bool event_lastComplete = false;
|
||||
|
||||
/* Function called when the display update is complete. */
|
||||
static void displayUpdateComplete(void)
|
||||
{
|
||||
event_lastComplete = true;
|
||||
}
|
||||
|
||||
void event_newDataAvailable(int data)
|
||||
{
|
||||
event_lastComplete = false;
|
||||
display_updateData(data, displayUpdateComplete);
|
||||
}
|
||||
|
||||
bool eventProcessor_isLastEventComplete(void)
|
||||
{
|
||||
return event_lastComplete;
|
||||
}
|
||||
11
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h
vendored
Normal file
11
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
void event_deviceReset(void);
|
||||
void event_volumeKnobMaxed(void);
|
||||
void event_powerReadingUpdate(int powerReading);
|
||||
void event_modeSelectButtonPressed(void);
|
||||
void event_devicePoweredOn(void);
|
||||
void event_keyboardCheckTimerExpired(void);
|
||||
void event_newDataAvailable(int data);
|
||||
|
||||
bool eventProcessor_isLastEventComplete(void);
|
||||
16
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c
vendored
Normal file
16
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "foo.h"
|
||||
#include "bar.h"
|
||||
#include "subfolder/zzz.h"
|
||||
|
||||
void foo_turn_on(void) {
|
||||
bar_turn_on();
|
||||
zzz_sleep(1, "sleepy");
|
||||
}
|
||||
|
||||
void foo_print_message(const char * message) {
|
||||
bar_print_message(message);
|
||||
}
|
||||
|
||||
void foo_print_special_message(void) {
|
||||
bar_print_message_formatted("The numbers are %d, %d and %d", 1, 2, 3);
|
||||
}
|
||||
8
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h
vendored
Normal file
8
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef foo_H
|
||||
#define foo_H
|
||||
|
||||
void foo_turn_on(void);
|
||||
void foo_print_message(const char * message);
|
||||
void foo_print_special_message(void);
|
||||
|
||||
#endif // foo_H
|
||||
@@ -0,0 +1 @@
|
||||
#include "zzz.h"
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef zzz_H
|
||||
#define zzz_H
|
||||
|
||||
int zzz_sleep(int time, char * name);
|
||||
|
||||
#endif // zzz_H
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "unity.h"
|
||||
#include "event_processor.h"
|
||||
#include "mock_display.h"
|
||||
#include <string.h>
|
||||
|
||||
void setUp (void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown (void)
|
||||
{
|
||||
}
|
||||
/*
|
||||
Test that a single function was called.
|
||||
*/
|
||||
void
|
||||
test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff()
|
||||
{
|
||||
// When
|
||||
event_deviceReset();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count);
|
||||
// or use the helper macro...
|
||||
TEST_ASSERT_CALLED(display_turnOffStatusLed);
|
||||
}
|
||||
|
||||
/*
|
||||
Test that a single function is NOT called.
|
||||
*/
|
||||
void
|
||||
test_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void)
|
||||
{
|
||||
// When
|
||||
event_powerReadingUpdate(4);
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count);
|
||||
// or use the helper macro...
|
||||
TEST_ASSERT_NOT_CALLED(display_turnOffStatusLed);
|
||||
}
|
||||
|
||||
/*
|
||||
Test that a single function was called with the correct arugment.
|
||||
*/
|
||||
void
|
||||
test_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void)
|
||||
{
|
||||
// When
|
||||
event_volumeKnobMaxed();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count);
|
||||
// or use the helper macro...
|
||||
TEST_ASSERT_CALLED(display_setVolume);
|
||||
TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val);
|
||||
}
|
||||
|
||||
/*
|
||||
Test a sequence of calls.
|
||||
*/
|
||||
|
||||
void
|
||||
test_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void)
|
||||
{
|
||||
// When
|
||||
event_modeSelectButtonPressed();
|
||||
event_modeSelectButtonPressed();
|
||||
event_modeSelectButtonPressed();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL_PTR((void *)display_setModeToMinimum, fff.call_history[0]);
|
||||
TEST_ASSERT_EQUAL_PTR((void *)display_setModeToMaximum, fff.call_history[1]);
|
||||
TEST_ASSERT_EQUAL_PTR((void *)display_setModeToAverage, fff.call_history[2]);
|
||||
// or use the helper macros...
|
||||
TEST_ASSERT_CALLED_IN_ORDER(0, display_setModeToMinimum);
|
||||
TEST_ASSERT_CALLED_IN_ORDER(1, display_setModeToMaximum);
|
||||
TEST_ASSERT_CALLED_IN_ORDER(2, display_setModeToAverage);
|
||||
}
|
||||
|
||||
/*
|
||||
Mock a return value from a function.
|
||||
*/
|
||||
void
|
||||
test_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void)
|
||||
{
|
||||
// Given
|
||||
display_isError_fake.return_val = true;
|
||||
|
||||
// When
|
||||
event_devicePoweredOn();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);
|
||||
// or use the helper macro...
|
||||
TEST_ASSERT_CALLED(display_powerDown);
|
||||
}
|
||||
|
||||
/*
|
||||
Mock a sequence of calls with return values.
|
||||
*/
|
||||
|
||||
/*
|
||||
Mocking a function with a value returned by reference.
|
||||
*/
|
||||
void
|
||||
test_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void)
|
||||
{
|
||||
// Given
|
||||
char mockedEntry[] = "sleep";
|
||||
void return_mock_value(char * entry, int length)
|
||||
{
|
||||
if (length > strlen(mockedEntry))
|
||||
{
|
||||
strncpy(entry, mockedEntry, length);
|
||||
}
|
||||
}
|
||||
display_getKeyboardEntry_fake.custom_fake = return_mock_value;
|
||||
|
||||
// When
|
||||
event_keyboardCheckTimerExpired();
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);
|
||||
// or use the helper macro...
|
||||
TEST_ASSERT_CALLED(display_powerDown);
|
||||
}
|
||||
|
||||
/*
|
||||
Mock a function with a function pointer parameter.
|
||||
*/
|
||||
void
|
||||
test_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void)
|
||||
{
|
||||
// A mock function for capturing the callback handler function pointer.
|
||||
void(*registeredCallback)(void) = 0;
|
||||
void mock_display_updateData(int data, void(*callback)(void))
|
||||
{
|
||||
//Save the callback function.
|
||||
registeredCallback = callback;
|
||||
}
|
||||
display_updateData_fake.custom_fake = mock_display_updateData;
|
||||
|
||||
// Given
|
||||
event_newDataAvailable(10);
|
||||
|
||||
// When
|
||||
if (registeredCallback != 0)
|
||||
{
|
||||
registeredCallback();
|
||||
}
|
||||
|
||||
// Then
|
||||
TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete());
|
||||
}
|
||||
47
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c
vendored
Normal file
47
test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "unity.h"
|
||||
#include "foo.h"
|
||||
#include "mock_bar.h"
|
||||
#include "mock_zzz.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_foo(void)
|
||||
{
|
||||
//When
|
||||
foo_turn_on();
|
||||
|
||||
//Then
|
||||
TEST_ASSERT_EQUAL(1, bar_turn_on_fake.call_count);
|
||||
TEST_ASSERT_EQUAL(1, zzz_sleep_fake.call_count);
|
||||
TEST_ASSERT_EQUAL_STRING("sleepy", zzz_sleep_fake.arg1_val);
|
||||
}
|
||||
|
||||
void test_foo_again(void)
|
||||
{
|
||||
//When
|
||||
foo_turn_on();
|
||||
|
||||
//Then
|
||||
TEST_ASSERT_EQUAL(1, bar_turn_on_fake.call_count);
|
||||
}
|
||||
|
||||
void test_foo_mock_with_const(void)
|
||||
{
|
||||
foo_print_message("123");
|
||||
|
||||
TEST_ASSERT_EQUAL(1, bar_print_message_fake.call_count);
|
||||
TEST_ASSERT_EQUAL_STRING("123", bar_print_message_fake.arg0_val);
|
||||
}
|
||||
|
||||
void test_foo_mock_with_variable_args(void)
|
||||
{
|
||||
foo_print_special_message();
|
||||
TEST_ASSERT_EQUAL(1, bar_print_message_formatted_fake.call_count);
|
||||
TEST_ASSERT_EQUAL_STRING("The numbers are %d, %d and %d", bar_print_message_formatted_fake.arg0_val);
|
||||
}
|
||||
87
test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb
vendored
Normal file
87
test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'fff_mock_generator'
|
||||
|
||||
class FakeFunctionFramework < Plugin
|
||||
|
||||
# Set up Ceedling to use this plugin.
|
||||
def setup
|
||||
# Get the location of this plugin.
|
||||
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
puts "Using fake function framework (fff)..."
|
||||
|
||||
# Switch out the cmock_builder with our own.
|
||||
@ceedling[:cmock_builder].cmock = FffMockGeneratorForCMock.new(@ceedling[:setupinator].config_hash[:cmock])
|
||||
|
||||
# Add the path to fff.h to the include paths.
|
||||
COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << "#{@plugin_root}/vendor/fff"
|
||||
COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << "#{@plugin_root}/src"
|
||||
end
|
||||
|
||||
def post_runner_generate(arg_hash)
|
||||
# After the test runner file has been created, append the FFF globals
|
||||
# definition to the end of the test runner. These globals will be shared by
|
||||
# all mocks linked into the test.
|
||||
File.open(arg_hash[:runner_file], 'a') do |f|
|
||||
f.puts
|
||||
f.puts "//=======Defintions of FFF variables====="
|
||||
f.puts %{#include "fff.h"}
|
||||
f.puts "DEFINE_FFF_GLOBALS;"
|
||||
end
|
||||
end
|
||||
|
||||
end # class FakeFunctionFramework
|
||||
|
||||
class FffMockGeneratorForCMock
|
||||
|
||||
def initialize(options=nil)
|
||||
@cm_config = CMockConfig.new(options)
|
||||
@cm_parser = CMockHeaderParser.new(@cm_config)
|
||||
@silent = (@cm_config.verbosity < 2)
|
||||
|
||||
# These are the additional files to include in the mock files.
|
||||
@includes_h_pre_orig_header = (@cm_config.includes || @cm_config.includes_h_pre_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_h_post_orig_header = (@cm_config.includes_h_post_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_c_pre_header = (@cm_config.includes_c_pre_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_c_post_header = (@cm_config.includes_c_post_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
end
|
||||
|
||||
def setup_mocks(files)
|
||||
[files].flatten.each do |src|
|
||||
generate_mock (src)
|
||||
end
|
||||
end
|
||||
|
||||
def generate_mock (header_file_to_mock)
|
||||
module_name = File.basename(header_file_to_mock, '.h')
|
||||
puts "Creating mock for #{module_name}..." unless @silent
|
||||
mock_name = @cm_config.mock_prefix + module_name + @cm_config.mock_suffix
|
||||
mock_path = @cm_config.mock_path
|
||||
if @cm_config.subdir
|
||||
# If a subdirectory has been configured, append it to the mock path.
|
||||
mock_path = "#{mock_path}/#{@cm_config.subdir}"
|
||||
end
|
||||
full_path_for_mock = "#{mock_path}/#{mock_name}"
|
||||
|
||||
# Parse the header file so we know what to mock.
|
||||
parsed_header = @cm_parser.parse(module_name, File.read(header_file_to_mock))
|
||||
|
||||
# Create the directory if it doesn't exist.
|
||||
mkdir_p full_path_for_mock.pathmap("%d")
|
||||
|
||||
# Generate the mock header file.
|
||||
puts "Creating mock: #{full_path_for_mock}.h"
|
||||
|
||||
# Create the mock header.
|
||||
File.open("#{full_path_for_mock}.h", 'w') do |f|
|
||||
f.write(FffMockGenerator.create_mock_header(module_name, mock_name, parsed_header,
|
||||
@includes_h_pre_orig_header, @includes_h_post_orig_header))
|
||||
end
|
||||
|
||||
# Create the mock source file.
|
||||
File.open("#{full_path_for_mock}.c", 'w') do |f|
|
||||
f.write(FffMockGenerator.create_mock_source(mock_name, parsed_header,
|
||||
@includes_c_pre_orig_header, @includes_c_post_orig_header))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
163
test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb
vendored
Normal file
163
test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
# Creates mock files from parsed header files that can be linked into applications.
|
||||
# The mocks created are compatible with CMock for use with Ceedling.
|
||||
|
||||
class FffMockGenerator
|
||||
|
||||
def self.create_mock_header(module_name, mock_name, parsed_header, pre_includes=nil,
|
||||
post_includes=nil)
|
||||
output = StringIO.new
|
||||
write_opening_include_guard(mock_name, output)
|
||||
output.puts
|
||||
write_extra_includes(pre_includes, output)
|
||||
write_header_includes(module_name, output)
|
||||
write_extra_includes(post_includes, output)
|
||||
output.puts
|
||||
write_typedefs(parsed_header, output)
|
||||
output.puts
|
||||
write_function_declarations(parsed_header, output)
|
||||
output.puts
|
||||
write_control_function_prototypes(mock_name, output)
|
||||
output.puts
|
||||
write_closing_include_guard(mock_name, output)
|
||||
output.string
|
||||
end
|
||||
|
||||
def self.create_mock_source (mock_name, parsed_header, pre_includes=nil,
|
||||
post_includes=nil)
|
||||
output = StringIO.new
|
||||
write_extra_includes(pre_includes, output)
|
||||
write_source_includes(mock_name, output)
|
||||
write_extra_includes(post_includes, output)
|
||||
output.puts
|
||||
write_function_definitions(parsed_header, output)
|
||||
output.puts
|
||||
write_control_function_definitions(mock_name, parsed_header, output)
|
||||
output.string
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Header file generation functions.
|
||||
|
||||
def self.write_opening_include_guard(mock_name, output)
|
||||
output.puts "#ifndef #{mock_name}_H"
|
||||
output.puts "#define #{mock_name}_H"
|
||||
end
|
||||
|
||||
def self.write_header_includes(module_name, output)
|
||||
output.puts %{#include "fff.h"}
|
||||
output.puts %{#include "fff_unity_helper.h"}
|
||||
output.puts %{#include "#{module_name}.h"}
|
||||
end
|
||||
|
||||
def self.write_typedefs(parsed_header, output)
|
||||
return unless parsed_header.key?(:typedefs)
|
||||
parsed_header[:typedefs].each do |typedef|
|
||||
output.puts typedef
|
||||
end
|
||||
end
|
||||
|
||||
def self.write_function_declarations(parsed_header, output)
|
||||
write_function_macros("DECLARE", parsed_header, output)
|
||||
end
|
||||
|
||||
|
||||
def self.write_control_function_prototypes(mock_name, output)
|
||||
output.puts "void #{mock_name}_Init(void);"
|
||||
output.puts "void #{mock_name}_Verify(void);"
|
||||
output.puts "void #{mock_name}_Destroy(void);"
|
||||
end
|
||||
|
||||
def self.write_closing_include_guard(mock_name, output)
|
||||
output.puts "#endif // #{mock_name}_H"
|
||||
end
|
||||
|
||||
# Source file generation functions.
|
||||
|
||||
def self.write_source_includes (mock_name, output)
|
||||
output.puts "#include <string.h>"
|
||||
output.puts %{#include "fff.h"}
|
||||
output.puts %{#include "#{mock_name}.h"}
|
||||
end
|
||||
|
||||
def self.write_function_definitions(parsed_header, output)
|
||||
write_function_macros("DEFINE", parsed_header, output)
|
||||
end
|
||||
|
||||
def self.write_control_function_definitions(mock_name, parsed_header, output)
|
||||
output.puts "void #{mock_name}_Init(void)"
|
||||
output.puts "{"
|
||||
# In the init function, reset the FFF globals. These are used for things
|
||||
# like the call history.
|
||||
output.puts " FFF_RESET_HISTORY();"
|
||||
|
||||
# Also, reset all of the fakes.
|
||||
if parsed_header[:functions]
|
||||
parsed_header[:functions].each do |function|
|
||||
output.puts " RESET_FAKE(#{function[:name]})"
|
||||
end
|
||||
end
|
||||
output.puts "}"
|
||||
output.puts "void #{mock_name}_Verify(void)"
|
||||
output.puts "{"
|
||||
output.puts "}"
|
||||
output.puts "void #{mock_name}_Destroy(void)"
|
||||
output.puts "{"
|
||||
output.puts "}"
|
||||
end
|
||||
|
||||
# Shared functions.
|
||||
|
||||
def self.write_extra_includes(includes, output)
|
||||
if includes
|
||||
includes.each {|inc| output.puts "#include #{inc}\n"}
|
||||
end
|
||||
end
|
||||
|
||||
def self.write_function_macros(macro_type, parsed_header, output)
|
||||
return unless parsed_header.key?(:functions)
|
||||
parsed_header[:functions].each do |function|
|
||||
name = function[:name]
|
||||
return_type = function[:return][:type]
|
||||
if function.has_key? :modifier
|
||||
# Prepend any modifier. If there isn't one, trim any leading whitespace.
|
||||
return_type = "#{function[:modifier]} #{return_type}".lstrip
|
||||
end
|
||||
arg_count = function[:args].size
|
||||
|
||||
# Check for variable arguments.
|
||||
var_arg_suffix = ""
|
||||
if function[:var_arg]
|
||||
# If there are are variable arguments, then we need to add this argument
|
||||
# to the count, update the suffix that will get added to the macro.
|
||||
arg_count += 1
|
||||
var_arg_suffix = "_VARARG"
|
||||
end
|
||||
|
||||
# Generate the correct macro.
|
||||
if return_type == 'void'
|
||||
output.print "#{macro_type}_FAKE_VOID_FUNC#{arg_count}#{var_arg_suffix}(#{name}"
|
||||
else
|
||||
output.print "#{macro_type}_FAKE_VALUE_FUNC#{arg_count}#{var_arg_suffix}(#{return_type}, #{name}"
|
||||
end
|
||||
|
||||
# Append each argument type.
|
||||
function[:args].each do |arg|
|
||||
output.print ", "
|
||||
if arg[:const?]
|
||||
output.print "const "
|
||||
end
|
||||
output.print "#{arg[:type]}"
|
||||
end
|
||||
|
||||
# If this argument list ends with a variable argument, add it here at the end.
|
||||
if function[:var_arg]
|
||||
output.print ", ..."
|
||||
end
|
||||
|
||||
# Close the declaration.
|
||||
output.puts ");"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
304
test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb
vendored
Normal file
304
test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
require 'stringio'
|
||||
require 'fff_mock_generator.rb'
|
||||
require 'header_generator.rb'
|
||||
|
||||
# Test the contents of the .h file created for the mock.
|
||||
describe "FffMockGenerator.create_mock_header" do
|
||||
|
||||
context "when there is nothing to mock," do
|
||||
let(:mock_header) {
|
||||
parsed_header = {}
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated header file starts with an opening include guard" do
|
||||
expect(mock_header).to start_with(
|
||||
"#ifndef mock_display_H\n" +
|
||||
"#define mock_display_H")
|
||||
end
|
||||
it "then the generated file ends with a closing include guard" do
|
||||
expect(mock_header).to end_with(
|
||||
"#endif // mock_display_H\n")
|
||||
end
|
||||
it "then the generated file includes the fff header" do
|
||||
expect(mock_header).to include(
|
||||
%{#include "fff.h"\n})
|
||||
end
|
||||
it "then the generated file has a prototype for the init function" do
|
||||
expect(mock_header).to include(
|
||||
"void mock_display_Init(void);")
|
||||
end
|
||||
it "then the generated file has a prototype for the verify function" do
|
||||
expect(mock_header).to include(
|
||||
"void mock_display_Verify(void);")
|
||||
end
|
||||
it "then the generated file has a prototype for the destroy function" do
|
||||
expect(mock_header).to include(
|
||||
"void mock_display_Destroy(void);")
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with no args and a void return," do
|
||||
let(:mock_header) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
[{:name => 'display_turnOffStatusLed', :return_type => 'void'}])
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated header file starts with an opening include guard" do
|
||||
expect(mock_header).to start_with(
|
||||
"#ifndef mock_display_H\n" +
|
||||
"#define mock_display_H")
|
||||
end
|
||||
it "then the generated header file contains a fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VOID_FUNC0(display_turnOffStatusLed);"
|
||||
)
|
||||
end
|
||||
it "then the generated file ends with a closing include guard" do
|
||||
expect(mock_header).to end_with(
|
||||
"#endif // mock_display_H\n")
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with no args and a bool return," do
|
||||
let(:mock_header) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
[{:name => 'display_isError', :return_type => 'bool'}])
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VALUE_FUNC0(bool, display_isError);"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with no args and an int return," do
|
||||
let(:mock_header) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
[{:name => 'display_isError', :return_type => 'int'}])
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VALUE_FUNC0(int, display_isError);"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with args and a void return," do
|
||||
let(:mock_header) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
[{:name => 'display_setVolume', :return_type => 'void', :args => ['int']}])
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VOID_FUNC1(display_setVolume, int);"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with args and a value return," do
|
||||
let(:mock_header) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
[{:name => 'a_function', :return_type => 'int', :args => ['char *']}])
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"FAKE_VALUE_FUNC1(int, a_function, char *);"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with many args and a void return," do
|
||||
let(:mock_header) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
[{:name => 'a_function', :return_type => 'void',
|
||||
:args => ['int', 'char *', 'int', 'int', 'bool', 'applesauce']}])
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VOID_FUNC6(a_function, int, char *, int, int, bool, applesauce);"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are multiple functions," do
|
||||
let(:mock_header) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
[ {:name => 'a_function', :return_type => 'int', :args => ['char *']},
|
||||
{:name => 'another_function', :return_type => 'void'},
|
||||
{:name => 'three', :return_type => 'bool', :args => ['float', 'int']}
|
||||
])
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the first fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VALUE_FUNC1(int, a_function, char *);"
|
||||
)
|
||||
end
|
||||
it "then the generated file contains the second fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VOID_FUNC0(another_function);"
|
||||
)
|
||||
end
|
||||
it "then the generated file contains the third fake function declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VALUE_FUNC2(bool, three, float, int);"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a typedef," do
|
||||
let(:mock_header) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
nil, ["typedef void (*displayCompleteCallback) (void);"])
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the typedef" do
|
||||
expect(mock_header).to include(
|
||||
"typedef void (*displayCompleteCallback) (void);"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a void function with variable arguments" do
|
||||
let(:mock_header){
|
||||
parsed_header = {}
|
||||
parsed_header[:functions] = [{
|
||||
:name => "function_with_var_args",
|
||||
:return => {:type => "void"},
|
||||
:var_arg => "...",
|
||||
:args => [{:type => 'char *'}]
|
||||
}]
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the vararg declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VOID_FUNC2_VARARG(function_with_var_args, char *, ...)"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with a return value and variable arguments" do
|
||||
let(:mock_header){
|
||||
parsed_header = {}
|
||||
parsed_header[:functions] = [{
|
||||
:name => "function_with_var_args",
|
||||
:return => {:type => "int"},
|
||||
:var_arg => "...",
|
||||
:args => [{:type => 'char *'}]
|
||||
}]
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the vararg declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VALUE_FUNC2_VARARG(int, function_with_var_args, char *, ...)"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a void function with variable arguments and " +
|
||||
"additional arguments" do
|
||||
let(:mock_header){
|
||||
parsed_header = {}
|
||||
parsed_header[:functions] = [{
|
||||
:name => "function_with_var_args",
|
||||
:return => {:type => "void"},
|
||||
:var_arg => "...",
|
||||
:args => [{:type => 'char *'}, {:type => 'int'}]
|
||||
}]
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the vararg declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VOID_FUNC3_VARARG(function_with_var_args, char *, int, ...)"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with a pointer to a const value" do
|
||||
let(:mock_header){
|
||||
parsed_header = {}
|
||||
parsed_header[:functions] = [{
|
||||
:name => "const_test_function",
|
||||
:return => {:type => "void"},
|
||||
:args => [{:type => "char *", :name => "a", :ptr? => false, :const? => true},
|
||||
{:type => "char *", :name => "b", :ptr? => false, :const? => false}]
|
||||
}]
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the correct const argument in the declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VOID_FUNC2(const_test_function, const char *, char *)"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function that returns a const pointer" do
|
||||
let(:mock_header){
|
||||
parsed_header = {}
|
||||
parsed_header[:functions] = [{
|
||||
:name => "return_const_pointer_test_function",
|
||||
:modifier => "const",
|
||||
:return => {:type => "char *" },
|
||||
:args => [{:type => "int", :name => "a"}]
|
||||
}]
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the correct const return value in the declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VALUE_FUNC1(const char *, return_const_pointer_test_function, int)"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function that returns a const int" do
|
||||
let(:mock_header){
|
||||
parsed_header = {}
|
||||
parsed_header[:functions] = [{
|
||||
:name => "return_const_int_test_function",
|
||||
:modifier => "const",
|
||||
:return => {:type => "int" },
|
||||
:args => []
|
||||
}]
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the correct const return value in the declaration" do
|
||||
expect(mock_header).to include(
|
||||
"DECLARE_FAKE_VALUE_FUNC0(const int, return_const_int_test_function)"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are pre-includes" do
|
||||
let(:mock_header) {
|
||||
parsed_header = {}
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header,
|
||||
[%{"another_header.h"}])
|
||||
}
|
||||
it "then they are included before the other files" do
|
||||
expect(mock_header).to include(
|
||||
%{#include "another_header.h"\n} +
|
||||
%{#include "fff.h"}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are post-includes" do
|
||||
let(:mock_header) {
|
||||
parsed_header = {}
|
||||
FffMockGenerator.create_mock_header("display", "mock_display", parsed_header,
|
||||
nil, [%{"another_header.h"}])
|
||||
}
|
||||
it "then they are included after the other files" do
|
||||
expect(mock_header).to include(
|
||||
%{#include "display.h"\n} +
|
||||
%{#include "another_header.h"\n}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
149
test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb
vendored
Normal file
149
test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
require 'stringio'
|
||||
require 'fff_mock_generator.rb'
|
||||
|
||||
# Test the contents of the .c file created for the mock.
|
||||
describe "FffMockGenerator.create_mock_source" do
|
||||
|
||||
context "when there is nothing to mock," do
|
||||
let(:mock_source) {
|
||||
parsed_header = {}
|
||||
FffMockGenerator.create_mock_source("mock_my_module", parsed_header)
|
||||
}
|
||||
it "then the generated file includes the fff header" do
|
||||
expect(mock_source).to include(
|
||||
# fff.h also requires including string.h
|
||||
%{#include <string.h>\n} +
|
||||
%{#include "fff.h"}
|
||||
)
|
||||
end
|
||||
it "then the generated file includes the mock header" do
|
||||
expect(mock_source).to include(
|
||||
%{#include "mock_my_module.h"\n}
|
||||
)
|
||||
end
|
||||
it "then the generated file defines the init function" do
|
||||
expect(mock_source).to include(
|
||||
"void mock_my_module_Init(void)\n" +
|
||||
"{\n" +
|
||||
" FFF_RESET_HISTORY();\n" +
|
||||
"}"
|
||||
)
|
||||
end
|
||||
it "then the generated file defines the verify function" do
|
||||
expect(mock_source).to include(
|
||||
"void mock_my_module_Verify(void)\n" +
|
||||
"{\n" +
|
||||
"}"
|
||||
)
|
||||
end
|
||||
it "then the generated file defines the destroy function" do
|
||||
expect(mock_source).to include(
|
||||
"void mock_my_module_Destroy(void)\n" +
|
||||
"{\n" +
|
||||
"}"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are multiple functions," do
|
||||
let(:mock_source) {
|
||||
parsed_header = create_cmock_style_parsed_header(
|
||||
[ {:name => 'a_function', :return_type => 'int', :args => ['char *']},
|
||||
{:name => 'another_function', :return_type => 'void'},
|
||||
{:name => 'three', :return_type => 'bool', :args => ['float', 'int']}
|
||||
])
|
||||
FffMockGenerator.create_mock_source("mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the first fake function definition" do
|
||||
expect(mock_source).to include(
|
||||
"DEFINE_FAKE_VALUE_FUNC1(int, a_function, char *);"
|
||||
)
|
||||
end
|
||||
it "then the generated file contains the second fake function definition" do
|
||||
expect(mock_source).to include(
|
||||
"DEFINE_FAKE_VOID_FUNC0(another_function);"
|
||||
)
|
||||
end
|
||||
it "then the generated file contains the third fake function definition" do
|
||||
expect(mock_source).to include(
|
||||
"DEFINE_FAKE_VALUE_FUNC2(bool, three, float, int);"
|
||||
)
|
||||
end
|
||||
it "then the init function resets all of the fakes" do
|
||||
expect(mock_source).to include(
|
||||
"void mock_display_Init(void)\n" +
|
||||
"{\n" +
|
||||
" FFF_RESET_HISTORY();\n" +
|
||||
" RESET_FAKE(a_function)\n" +
|
||||
" RESET_FAKE(another_function)\n" +
|
||||
" RESET_FAKE(three)\n" +
|
||||
"}"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a void function with variable arguments and " +
|
||||
"additional arguments" do
|
||||
let(:mock_source){
|
||||
parsed_header = {}
|
||||
parsed_header[:functions] = [{
|
||||
:name => "function_with_var_args",
|
||||
:return => {:type => "void"},
|
||||
:var_arg => "...",
|
||||
:args => [{:type => 'char *'}, {:type => 'int'}]
|
||||
}]
|
||||
FffMockGenerator.create_mock_source("mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the vararg definition" do
|
||||
expect(mock_source).to include(
|
||||
"DEFINE_FAKE_VOID_FUNC3_VARARG(function_with_var_args, char *, int, ...)"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a function with a pointer to a const value" do
|
||||
let(:mock_source){
|
||||
parsed_header = {}
|
||||
parsed_header[:functions] = [{
|
||||
:name => "const_test_function",
|
||||
:return => {:type => "void"},
|
||||
:args => [{:type => "char *", :name => "a", :ptr? => false, :const? => true},
|
||||
{:type => "char *", :name => "b", :ptr? => false, :const? => false}]
|
||||
}]
|
||||
FffMockGenerator.create_mock_source("mock_display", parsed_header)
|
||||
}
|
||||
it "then the generated file contains the correct const argument in the declaration" do
|
||||
expect(mock_source).to include(
|
||||
"DEFINE_FAKE_VOID_FUNC2(const_test_function, const char *, char *)"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are pre-includes" do
|
||||
let(:mock_source) {
|
||||
parsed_source = {}
|
||||
FffMockGenerator.create_mock_source("mock_display", parsed_source,
|
||||
[%{"another_header.h"}])
|
||||
}
|
||||
it "then they are included before the other files" do
|
||||
expect(mock_source).to include(
|
||||
%{#include "another_header.h"\n} +
|
||||
%{#include <string.h>}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are post-includes" do
|
||||
let(:mock_source) {
|
||||
parsed_source = {}
|
||||
FffMockGenerator.create_mock_source("mock_display", parsed_source,
|
||||
nil, [%{"another_header.h"}])
|
||||
}
|
||||
it "then they are included before the other files" do
|
||||
expect(mock_source).to include(
|
||||
%{#include "mock_display.h"\n} +
|
||||
%{#include "another_header.h"\n}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
51
test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb
vendored
Normal file
51
test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# Create a CMock-style parsed header hash. This the type of hash created by
|
||||
# CMock when parsing header files for automock generation. It contains all of
|
||||
# includes, typedefs and functions (with return types and arguments) parsed from
|
||||
# the header file.
|
||||
def create_cmock_style_parsed_header(functions, typedefs = nil)
|
||||
parsed_header = {
|
||||
:includes => nil,
|
||||
:functions => [],
|
||||
:typedefs => []
|
||||
}
|
||||
|
||||
# Add the typedefs.
|
||||
if typedefs
|
||||
typedefs.each do |typedef|
|
||||
parsed_header[:typedefs] << typedef
|
||||
end
|
||||
end
|
||||
|
||||
# Add the functions.
|
||||
if functions
|
||||
functions.each do |function|
|
||||
# Build the array of arguments.
|
||||
args = []
|
||||
if function.key?(:args)
|
||||
function[:args].each do |arg|
|
||||
args << {
|
||||
:type => arg
|
||||
}
|
||||
end
|
||||
end
|
||||
parsed_header[:functions] << {
|
||||
:name => function[:name],
|
||||
:modifier => "",
|
||||
:return => {
|
||||
:type => function[:return_type],
|
||||
:name => "cmock_to_return",
|
||||
:ptr? => false,
|
||||
:const? => false,
|
||||
:str => "void cmock_to_return",
|
||||
:void? => true
|
||||
},
|
||||
:var_arg => nil,
|
||||
:args_string => "void",
|
||||
:args => args,
|
||||
:args_call => "",
|
||||
:contains_ptr? => false
|
||||
}
|
||||
end
|
||||
end
|
||||
parsed_header
|
||||
end
|
||||
96
test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb
vendored
Normal file
96
test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
# This file was generated by the `rspec --init` command. Conventionally, all
|
||||
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
||||
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
||||
# this file to always be loaded, without a need to explicitly require it in any
|
||||
# files.
|
||||
#
|
||||
# Given that it is always loaded, you are encouraged to keep this file as
|
||||
# light-weight as possible. Requiring heavyweight dependencies from this file
|
||||
# will add to the boot time of your test suite on EVERY test run, even for an
|
||||
# individual file that may not need all of that loaded. Instead, consider making
|
||||
# a separate helper file that requires the additional dependencies and performs
|
||||
# the additional setup, and require it from the spec files that actually need
|
||||
# it.
|
||||
#
|
||||
# The `.rspec` file also contains a few flags that are not defaults but that
|
||||
# users commonly want.
|
||||
#
|
||||
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
||||
RSpec.configure do |config|
|
||||
# rspec-expectations config goes here. You can use an alternate
|
||||
# assertion/expectation library such as wrong or the stdlib/minitest
|
||||
# assertions if you prefer.
|
||||
config.expect_with :rspec do |expectations|
|
||||
# This option will default to `true` in RSpec 4. It makes the `description`
|
||||
# and `failure_message` of custom matchers include text for helper methods
|
||||
# defined using `chain`, e.g.:
|
||||
# be_bigger_than(2).and_smaller_than(4).description
|
||||
# # => "be bigger than 2 and smaller than 4"
|
||||
# ...rather than:
|
||||
# # => "be bigger than 2"
|
||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
||||
end
|
||||
|
||||
# rspec-mocks config goes here. You can use an alternate test double
|
||||
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
||||
config.mock_with :rspec do |mocks|
|
||||
# Prevents you from mocking or stubbing a method that does not exist on
|
||||
# a real object. This is generally recommended, and will default to
|
||||
# `true` in RSpec 4.
|
||||
mocks.verify_partial_doubles = true
|
||||
end
|
||||
|
||||
# The settings below are suggested to provide a good initial experience
|
||||
# with RSpec, but feel free to customize to your heart's content.
|
||||
=begin
|
||||
# These two settings work together to allow you to limit a spec run
|
||||
# to individual examples or groups you care about by tagging them with
|
||||
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
||||
# get run.
|
||||
config.filter_run :focus
|
||||
config.run_all_when_everything_filtered = true
|
||||
|
||||
# Allows RSpec to persist some state between runs in order to support
|
||||
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
||||
# you configure your source control system to ignore this file.
|
||||
config.example_status_persistence_file_path = "spec/examples.txt"
|
||||
|
||||
# Limits the available syntax to the non-monkey patched syntax that is
|
||||
# recommended. For more details, see:
|
||||
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
|
||||
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
||||
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
|
||||
config.disable_monkey_patching!
|
||||
|
||||
# This setting enables warnings. It's recommended, but in some cases may
|
||||
# be too noisy due to issues in dependencies.
|
||||
config.warnings = true
|
||||
|
||||
# Many RSpec users commonly either run the entire suite or an individual
|
||||
# file, and it's useful to allow more verbose output when running an
|
||||
# individual spec file.
|
||||
if config.files_to_run.one?
|
||||
# Use the documentation formatter for detailed output,
|
||||
# unless a formatter has already been configured
|
||||
# (e.g. via a command-line flag).
|
||||
config.default_formatter = 'doc'
|
||||
end
|
||||
|
||||
# Print the 10 slowest examples and example groups at the
|
||||
# end of the spec run, to help surface which specs are running
|
||||
# particularly slow.
|
||||
config.profile_examples = 10
|
||||
|
||||
# Run specs in random order to surface order dependencies. If you find an
|
||||
# order dependency and want to debug it, you can fix the order by providing
|
||||
# the seed, which is printed after each run.
|
||||
# --seed 1234
|
||||
config.order = :random
|
||||
|
||||
# Seed global randomization in this process using the `--seed` CLI option.
|
||||
# Setting this allows you to use `--seed` to deterministically reproduce
|
||||
# test failures related to randomization by passing the same `--seed` value
|
||||
# as the one that triggered the failure.
|
||||
Kernel.srand config.seed
|
||||
=end
|
||||
end
|
||||
33
test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h
vendored
Normal file
33
test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef fff_unity_helper_H
|
||||
#define fff_unity_helper_H
|
||||
|
||||
/*
|
||||
FFF helper macros for Unity.
|
||||
*/
|
||||
|
||||
/*
|
||||
Fail if the function was not called the expected number of times.
|
||||
*/
|
||||
#define TEST_ASSERT_CALLED_TIMES(times_, function_) \
|
||||
TEST_ASSERT_EQUAL_MESSAGE(times_, \
|
||||
function_ ## _fake.call_count, \
|
||||
"Function " #function_ " called the incorrect number of times.")
|
||||
/*
|
||||
Fail if the function was not called exactly once.
|
||||
*/
|
||||
#define TEST_ASSERT_CALLED(function_) TEST_ASSERT_CALLED_TIMES(1, function_)
|
||||
|
||||
/*
|
||||
Fail if the function was called 1 or more times.
|
||||
*/
|
||||
#define TEST_ASSERT_NOT_CALLED(function_) TEST_ASSERT_CALLED_TIMES(0, function_)
|
||||
|
||||
/*
|
||||
Fail if the function was not called in this particular order.
|
||||
*/
|
||||
#define TEST_ASSERT_CALLED_IN_ORDER(order_, function_) \
|
||||
TEST_ASSERT_EQUAL_PTR_MESSAGE((void *) function_, \
|
||||
fff.call_history[order_], \
|
||||
"Function " #function_ " not called in order " #order_ )
|
||||
|
||||
#endif
|
||||
42
test/vendor/ceedling/plugins/gcov/README.md
vendored
Normal file
42
test/vendor/ceedling/plugins/gcov/README.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
ceedling-gcov
|
||||
=============
|
||||
|
||||
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 reports as a utility. The
|
||||
normal gcov plugin _must_ be run first for this report to generate.
|
||||
|
||||
Gcovr can be installed via pip like so:
|
||||
|
||||
```
|
||||
pip install gcovr
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
:gcov:
|
||||
:html_report_type: basic
|
||||
```
|
||||
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`.
|
||||
|
||||
|
||||
|
||||
# To-Do list
|
||||
|
||||
- Generate overall report (combined statistics from all files with coverage)
|
||||
- Generate coverage output files
|
||||
- Easier option override for better customisation
|
||||
15
test/vendor/ceedling/plugins/gcov/assets/template.erb
vendored
Normal file
15
test/vendor/ceedling/plugins/gcov/assets/template.erb
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
% function_string = hash[:coverage][:functions].to_s
|
||||
% branch_string = hash[:coverage][:branches].to_s
|
||||
% format_string = "%#{[function_string.length, branch_string.length].max}i"
|
||||
<%=@ceedling[:plugin_reportinator].generate_banner("#{GCOV_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY")%>
|
||||
% if (!hash[:coverage][:functions].nil?)
|
||||
FUNCTIONS: <%=sprintf(format_string, hash[:coverage][:functions])%>%
|
||||
% else
|
||||
FUNCTIONS: none
|
||||
% end
|
||||
% if (!hash[:coverage][:branches].nil?)
|
||||
BRANCHES: <%=sprintf(format_string, hash[:coverage][:branches])%>%
|
||||
% else
|
||||
BRANCHES: none
|
||||
% end
|
||||
|
||||
66
test/vendor/ceedling/plugins/gcov/config/defaults.yml
vendored
Normal file
66
test/vendor/ceedling/plugins/gcov/config/defaults.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
|
||||
:tools:
|
||||
:gcov_compiler:
|
||||
:executable: gcc
|
||||
:arguments:
|
||||
- -g
|
||||
- -fprofile-arcs
|
||||
- -ftest-coverage
|
||||
- -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR
|
||||
- -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE
|
||||
- -D$: COLLECTION_DEFINES_TEST_AND_VENDOR
|
||||
- -DGCOV_COMPILER
|
||||
- -c "${1}"
|
||||
- -o "${2}"
|
||||
:gcov_linker:
|
||||
:executable: gcc
|
||||
:arguments:
|
||||
- -fprofile-arcs
|
||||
- -ftest-coverage
|
||||
- ${1}
|
||||
- -o ${2}
|
||||
:gcov_fixture:
|
||||
:executable: ${1}
|
||||
:gcov_report:
|
||||
:executable: gcov
|
||||
:arguments:
|
||||
- -n
|
||||
- -p
|
||||
- -b
|
||||
- -o "$": GCOV_BUILD_OUTPUT_PATH
|
||||
- "\"${1}\""
|
||||
:gcov_post_report:
|
||||
:executable: gcovr
|
||||
:optional: TRUE
|
||||
:arguments:
|
||||
- -p
|
||||
- -b
|
||||
- -e "${1}"
|
||||
- --html
|
||||
- -r .
|
||||
- -o GcovCoverageResults.html
|
||||
:gcov_post_report_basic:
|
||||
:executable: gcovr
|
||||
:optional: TRUE
|
||||
:arguments:
|
||||
- -p
|
||||
- -b
|
||||
- -e "${1}"
|
||||
- --html
|
||||
- -r .
|
||||
- -o "$": GCOV_ARTIFACTS_FILE
|
||||
:gcov_post_report_advanced:
|
||||
:executable: gcovr
|
||||
:optional: TRUE
|
||||
:arguments:
|
||||
- -p
|
||||
- -b
|
||||
- -e "${1}"
|
||||
- --html
|
||||
- --html-details
|
||||
- -r .
|
||||
- -o "$": GCOV_ARTIFACTS_FILE
|
||||
|
||||
|
||||
...
|
||||
180
test/vendor/ceedling/plugins/gcov/gcov.rake
vendored
Normal file
180
test/vendor/ceedling/plugins/gcov/gcov.rake
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
directory(GCOV_BUILD_OUTPUT_PATH)
|
||||
directory(GCOV_RESULTS_PATH)
|
||||
directory(GCOV_ARTIFACTS_PATH)
|
||||
directory(GCOV_DEPENDENCIES_PATH)
|
||||
|
||||
CLEAN.include(File.join(GCOV_BUILD_OUTPUT_PATH, '*'))
|
||||
CLEAN.include(File.join(GCOV_RESULTS_PATH, '*'))
|
||||
CLEAN.include(File.join(GCOV_ARTIFACTS_PATH, '*'))
|
||||
CLEAN.include(File.join(GCOV_DEPENDENCIES_PATH, '*'))
|
||||
|
||||
CLOBBER.include(File.join(GCOV_BUILD_PATH, '**/*'))
|
||||
|
||||
rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_OBJECT}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[:file_finder].find_compilation_input_file(task_name)
|
||||
end
|
||||
]) do |object|
|
||||
|
||||
if File.basename(object.source) =~ /^(#{PROJECT_TEST_FILE_PREFIX}|#{CMOCK_MOCK_PREFIX}|#{GCOV_IGNORE_SOURCES.join('|')})/i
|
||||
@ceedling[:generator].generate_object_file(
|
||||
TOOLS_GCOV_COMPILER,
|
||||
OPERATION_COMPILE_SYM,
|
||||
GCOV_SYM,
|
||||
object.source,
|
||||
object.name,
|
||||
@ceedling[:file_path_utils].form_test_build_list_filepath(object.name)
|
||||
)
|
||||
else
|
||||
@ceedling[GCOV_SYM].generate_coverage_object_file(object.source, object.name)
|
||||
end
|
||||
end
|
||||
|
||||
rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_EXECUTABLE}$/) do |bin_file|
|
||||
@ceedling[:generator].generate_executable_file(
|
||||
TOOLS_GCOV_LINKER,
|
||||
GCOV_SYM,
|
||||
bin_file.prerequisites,
|
||||
bin_file.name,
|
||||
@ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name)
|
||||
)
|
||||
end
|
||||
|
||||
rule(/#{GCOV_RESULTS_PATH}\/#{'.+\\' + EXTENSION_TESTPASS}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[:file_path_utils].form_test_executable_filepath(task_name)
|
||||
end
|
||||
]) do |test_result|
|
||||
@ceedling[:generator].generate_test_results(TOOLS_GCOV_FIXTURE, GCOV_SYM, test_result.source, test_result.name)
|
||||
end
|
||||
|
||||
rule(/#{GCOV_DEPENDENCIES_PATH}\/#{'.+\\' + EXTENSION_DEPENDENCIES}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[:file_finder].find_compilation_input_file(task_name)
|
||||
end
|
||||
]) do |dep|
|
||||
@ceedling[:generator].generate_dependencies_file(
|
||||
TOOLS_TEST_DEPENDENCIES_GENERATOR,
|
||||
GCOV_SYM,
|
||||
dep.source,
|
||||
File.join(GCOV_BUILD_OUTPUT_PATH, File.basename(dep.source).ext(EXTENSION_OBJECT)),
|
||||
dep.name
|
||||
)
|
||||
end
|
||||
|
||||
task directories: [GCOV_BUILD_OUTPUT_PATH, GCOV_RESULTS_PATH, GCOV_DEPENDENCIES_PATH, GCOV_ARTIFACTS_PATH]
|
||||
|
||||
namespace GCOV_SYM do
|
||||
task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{GCOV_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}")
|
||||
|
||||
desc 'Run code coverage for all tests'
|
||||
task all: [:directories] do
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
|
||||
@ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, GCOV_SYM)
|
||||
@ceedling[:configurator].restore_config
|
||||
end
|
||||
|
||||
desc 'Run single test w/ coverage ([*] real test or source file name, no path).'
|
||||
task :* do
|
||||
message = "\nOops! '#{GCOV_ROOT_NAME}:*' isn't a real task. " \
|
||||
"Use a real test or source file name (no path) in place of the wildcard.\n" \
|
||||
"Example: rake #{GCOV_ROOT_NAME}:foo.c\n\n"
|
||||
|
||||
@ceedling[:streaminator].stdout_puts(message)
|
||||
end
|
||||
|
||||
desc 'Run tests by matching regular expression pattern.'
|
||||
task :pattern, [:regex] => [:directories] do |_t, args|
|
||||
matches = []
|
||||
|
||||
COLLECTION_ALL_TESTS.each do |test|
|
||||
matches << test if test =~ /#{args.regex}/
|
||||
end
|
||||
|
||||
if !matches.empty?
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
|
||||
@ceedling[:test_invoker].setup_and_invoke(matches, GCOV_SYM, force_run: false)
|
||||
@ceedling[:configurator].restore_config
|
||||
else
|
||||
@ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.")
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Run tests whose test path contains [dir] or [dir] substring.'
|
||||
task :path, [:dir] => [:directories] do |_t, args|
|
||||
matches = []
|
||||
|
||||
COLLECTION_ALL_TESTS.each do |test|
|
||||
matches << test if File.dirname(test).include?(args.dir.tr('\\', '/'))
|
||||
end
|
||||
|
||||
if !matches.empty?
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
|
||||
@ceedling[:test_invoker].setup_and_invoke(matches, GCOV_SYM, force_run: false)
|
||||
@ceedling[:configurator].restore_config
|
||||
else
|
||||
@ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.")
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Run code coverage for changed files'
|
||||
task delta: [:directories] do
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
|
||||
@ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, GCOV_SYM, force_run: false)
|
||||
@ceedling[:configurator].restore_config
|
||||
end
|
||||
|
||||
# use a rule to increase efficiency for large projects
|
||||
# gcov test tasks by regex
|
||||
rule(/^#{GCOV_TASK_ROOT}\S+$/ => [
|
||||
proc do |task_name|
|
||||
test = task_name.sub(/#{GCOV_TASK_ROOT}/, '')
|
||||
test = "#{PROJECT_TEST_FILE_PREFIX}#{test}" unless test.start_with?(PROJECT_TEST_FILE_PREFIX)
|
||||
@ceedling[:file_finder].find_test_from_file_path(test)
|
||||
end
|
||||
]) do |test|
|
||||
@ceedling[:rake_wrapper][:directories].invoke
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
|
||||
@ceedling[:test_invoker].setup_and_invoke([test.source], GCOV_SYM)
|
||||
@ceedling[:configurator].restore_config
|
||||
end
|
||||
end
|
||||
|
||||
if PROJECT_USE_DEEP_DEPENDENCIES
|
||||
namespace REFRESH_SYM do
|
||||
task GCOV_SYM do
|
||||
@ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
|
||||
@ceedling[:test_invoker].refresh_deep_dependencies
|
||||
@ceedling[:configurator].restore_config
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
namespace UTILS_SYM do
|
||||
desc 'Create gcov code coverage html report (must run ceedling gcov first)'
|
||||
task GCOV_SYM do
|
||||
|
||||
if !File.directory? GCOV_ARTIFACTS_PATH
|
||||
FileUtils.mkdir_p GCOV_ARTIFACTS_PATH
|
||||
end
|
||||
|
||||
filter = @ceedling[:configurator].project_config_hash[:gcov_html_report_filter] || GCOV_FILTER_EXPR
|
||||
|
||||
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])
|
||||
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)
|
||||
@ceedling[:tool_executor].exec(command[:line], command[:options])
|
||||
end
|
||||
puts "Done."
|
||||
end
|
||||
end
|
||||
106
test/vendor/ceedling/plugins/gcov/lib/gcov.rb
vendored
Normal file
106
test/vendor/ceedling/plugins/gcov/lib/gcov.rb
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
require 'gcov_constants'
|
||||
|
||||
class Gcov < Plugin
|
||||
attr_reader :config
|
||||
|
||||
def setup
|
||||
@result_list = []
|
||||
|
||||
@config = {
|
||||
project_test_build_output_path: GCOV_BUILD_OUTPUT_PATH,
|
||||
project_test_build_output_c_path: GCOV_BUILD_OUTPUT_PATH,
|
||||
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
|
||||
}
|
||||
|
||||
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
@coverage_template_all = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb'))
|
||||
end
|
||||
|
||||
def generate_coverage_object_file(source, object)
|
||||
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[:streaminator].stdout_puts("Compiling #{File.basename(source)} with coverage...")
|
||||
@ceedling[:tool_executor].exec(compile_command[:line], compile_command[:options])
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
result_file = arg_hash[:result_file]
|
||||
|
||||
if (result_file =~ /#{GCOV_RESULTS_PATH}/) && !@result_list.include?(result_file)
|
||||
@result_list << arg_hash[:result_file]
|
||||
end
|
||||
end
|
||||
|
||||
def post_build
|
||||
return unless @ceedling[:task_invoker].invoked?(/^#{GCOV_TASK_ROOT}/)
|
||||
|
||||
# test results
|
||||
results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
|
||||
hash = {
|
||||
header: GCOV_ROOT_NAME.upcase,
|
||||
results: results
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash) do
|
||||
message = ''
|
||||
message = 'Unit test failures.' if results[:counts][:failed] > 0
|
||||
message
|
||||
end
|
||||
|
||||
report_per_file_coverage_results(@ceedling[:test_invoker].sources)
|
||||
end
|
||||
|
||||
def summary
|
||||
result_list = @ceedling[:file_path_utils].form_pass_results_filelist(GCOV_RESULTS_PATH, COLLECTION_ALL_TESTS)
|
||||
|
||||
# test results
|
||||
# get test results for only those tests in our configuration and of those only tests with results on disk
|
||||
hash = {
|
||||
header: GCOV_ROOT_NAME.upcase,
|
||||
results: @ceedling[:plugin_reportinator].assemble_test_results(result_list, boom: false)
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash)
|
||||
end
|
||||
|
||||
private ###################################
|
||||
|
||||
def report_per_file_coverage_results(sources)
|
||||
banner = @ceedling[:plugin_reportinator].generate_banner "#{GCOV_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY"
|
||||
@ceedling[:streaminator].stdout_puts "\n" + banner
|
||||
|
||||
coverage_sources = sources.clone
|
||||
coverage_sources.delete_if { |item| item =~ /#{CMOCK_MOCK_PREFIX}.+#{EXTENSION_SOURCE}$/ }
|
||||
coverage_sources.delete_if { |item| item =~ /#{GCOV_IGNORE_SOURCES.join('|')}#{EXTENSION_SOURCE}$/ }
|
||||
|
||||
coverage_sources.each do |source|
|
||||
basename = File.basename(source)
|
||||
command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_REPORT, [], [basename])
|
||||
shell_results = @ceedling[:tool_executor].exec(command[:line], command[:options])
|
||||
coverage_results = shell_results[:output]
|
||||
|
||||
if coverage_results.strip =~ /(File\s+'#{Regexp.escape(source)}'.+$)/m
|
||||
report = Regexp.last_match(1).lines.to_a[1..-1].map { |line| basename + ' ' + line }.join('')
|
||||
@ceedling[:streaminator].stdout_puts(report + "\n\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# end blocks always executed following rake run
|
||||
END {
|
||||
# cache our input configurations to use in comparison upon next execution
|
||||
@ceedling[:cacheinator].cache_test_config(@ceedling[:setupinator].config_hash) if @ceedling[:task_invoker].invoked?(/^#{GCOV_TASK_ROOT}/)
|
||||
}
|
||||
18
test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb
vendored
Normal file
18
test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
GCOV_ROOT_NAME = 'gcov'.freeze
|
||||
GCOV_TASK_ROOT = GCOV_ROOT_NAME + ':'
|
||||
GCOV_SYM = GCOV_ROOT_NAME.to_sym
|
||||
|
||||
GCOV_BUILD_PATH = File.join(PROJECT_BUILD_ROOT, GCOV_ROOT_NAME)
|
||||
GCOV_BUILD_OUTPUT_PATH = File.join(GCOV_BUILD_PATH, "out")
|
||||
GCOV_RESULTS_PATH = File.join(GCOV_BUILD_PATH, "results")
|
||||
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_IGNORE_SOURCES = %w(unity cmock cexception).freeze
|
||||
|
||||
GCOV_FILTER_EXPR = '^vendor.*|^build.*|^test.*|^lib.*'
|
||||
|
||||
|
||||
118
test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb
vendored
Normal file
118
test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
|
||||
class JunitTestsReport < Plugin
|
||||
|
||||
def setup
|
||||
@results_list = {}
|
||||
@test_counter = 0
|
||||
@time_result = []
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
context = arg_hash[:context]
|
||||
|
||||
@results_list[context] = [] if (@results_list[context].nil?)
|
||||
|
||||
@results_list[context] << arg_hash[:result_file]
|
||||
@time_result << arg_hash[:shell_result][:time]
|
||||
|
||||
end
|
||||
|
||||
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' )
|
||||
|
||||
@ceedling[:file_wrapper].open( file_path, 'w' ) do |f|
|
||||
@testsuite_counter = 0
|
||||
@testcase_counter = 0
|
||||
suites = reorganise_results( results )
|
||||
|
||||
write_header( results, f )
|
||||
suites.each{|suite| write_suite( suite, f ) }
|
||||
write_footer( f )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def write_header( results, stream )
|
||||
results[:counts][:time] = @time_result.reduce(0, :+)
|
||||
stream.puts '<?xml version="1.0" encoding="utf-8" ?>'
|
||||
stream.puts('<testsuites tests="%<total>d" failures="%<failed>d" skipped="%<ignored>d" time="%<time>f">' % results[:counts])
|
||||
end
|
||||
|
||||
def write_footer( stream )
|
||||
stream.puts '</testsuites>'
|
||||
end
|
||||
|
||||
def reorganise_results( results )
|
||||
# Reorganise the output by test suite instead of by result
|
||||
suites = Hash.new{ |h,k| h[k] = {collection: [], total: 0, success: 0, failed: 0, ignored: 0, stdout: []} }
|
||||
results[:successes].each do |result|
|
||||
source = result[:source]
|
||||
name = source[:file].sub(/\..{1,4}$/, "")
|
||||
suites[name][:collection] += result[:collection].map{|test| test.merge(result: :success)}
|
||||
suites[name][:total] += result[:collection].length
|
||||
suites[name][:success] += result[:collection].length
|
||||
end
|
||||
results[:failures].each do |result|
|
||||
source = result[:source]
|
||||
name = source[:file].sub(/\..{1,4}$/, "")
|
||||
suites[name][:collection] += result[:collection].map{|test| test.merge(result: :failed)}
|
||||
suites[name][:total] += result[:collection].length
|
||||
suites[name][:failed] += result[:collection].length
|
||||
end
|
||||
results[:ignores].each do |result|
|
||||
source = result[:source]
|
||||
name = source[:file].sub(/\..{1,4}$/, "")
|
||||
suites[name][:collection] += result[:collection].map{|test| test.merge(result: :ignored)}
|
||||
suites[name][:total] += result[:collection].length
|
||||
suites[name][:ignored] += result[:collection].length
|
||||
end
|
||||
results[:stdout].each do |result|
|
||||
source = result[:source]
|
||||
name = source[:file].sub(/\..{1,4}$/, "")
|
||||
suites[name][:stdout] += result[:collection]
|
||||
end
|
||||
suites.map{|name, data| data.merge(name: name) }
|
||||
end
|
||||
|
||||
def write_suite( suite, stream )
|
||||
suite[:time] = @time_result.shift
|
||||
stream.puts(' <testsuite name="%<name>s" tests="%<total>d" failures="%<failed>d" skipped="%<ignored>d" time="%<time>f">' % suite)
|
||||
|
||||
suite[:collection].each do |test|
|
||||
write_test( test, stream )
|
||||
end
|
||||
|
||||
unless suite[:stdout].empty?
|
||||
stream.puts(' <system-out>')
|
||||
suite[:stdout].each{|line| stream.puts line }
|
||||
stream.puts(' </system-out>')
|
||||
end
|
||||
|
||||
stream.puts(' </testsuite>')
|
||||
end
|
||||
|
||||
def write_test( test, stream )
|
||||
case test[:result]
|
||||
when :success
|
||||
stream.puts(' <testcase name="%<test>s" />' % test)
|
||||
when :failed
|
||||
stream.puts(' <testcase name="%<test>s">' % test)
|
||||
if test[:message].empty?
|
||||
stream.puts(' <failure />')
|
||||
else
|
||||
stream.puts(' <failure message="%s" />' % test[:message])
|
||||
end
|
||||
stream.puts(' </testcase>')
|
||||
when :ignored
|
||||
stream.puts(' <testcase name="%<test>s">' % test)
|
||||
stream.puts(' <skipped />')
|
||||
stream.puts(' </testcase>')
|
||||
end
|
||||
end
|
||||
end
|
||||
4
test/vendor/ceedling/plugins/module_generator/config/module_generator.yml
vendored
Normal file
4
test/vendor/ceedling/plugins/module_generator/config/module_generator.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
:module_generator:
|
||||
:project_root: ./
|
||||
:source_root: src/
|
||||
:test_root: test/
|
||||
51
test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb
vendored
Normal file
51
test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
require 'erb'
|
||||
require 'fileutils'
|
||||
|
||||
class ModuleGenerator < Plugin
|
||||
|
||||
attr_reader :config
|
||||
|
||||
def create(module_name, optz={})
|
||||
|
||||
require "generate_module.rb" #From Unity Scripts
|
||||
|
||||
if ((!optz.nil?) && (optz[:destroy]))
|
||||
UnityModuleGenerator.new( divine_options(optz) ).destroy(module_name)
|
||||
else
|
||||
UnityModuleGenerator.new( divine_options(optz) ).generate(module_name)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def divine_options(optz={})
|
||||
unity_generator_options =
|
||||
{
|
||||
:path_src => ((defined? MODULE_GENERATOR_SOURCE_ROOT ) ? MODULE_GENERATOR_SOURCE_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '') : "src" ),
|
||||
:path_inc => ((defined? MODULE_GENERATOR_INC_ROOT ) ?
|
||||
MODULE_GENERATOR_INC_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '')
|
||||
: (defined? MODULE_GENERATOR_SOURCE_ROOT ) ?
|
||||
MODULE_GENERATOR_SOURCE_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '')
|
||||
: "src" ),
|
||||
:path_tst => ((defined? MODULE_GENERATOR_TEST_ROOT ) ? MODULE_GENERATOR_TEST_ROOT.gsub( '\\', '/').sub(/^\//, '').sub(/\/$/, '') : "test" ),
|
||||
:pattern => optz[:pattern],
|
||||
:test_prefix => ((defined? PROJECT_TEST_FILE_PREFIX ) ? PROJECT_TEST_FILE_PREFIX : "Test" ),
|
||||
:mock_prefix => ((defined? CMOCK_MOCK_PREFIX ) ? CMOCK_MOCK_PREFIX : "Mock" ),
|
||||
:includes => ((defined? MODULE_GENERATOR_INCLUDES ) ? MODULE_GENERATOR_INCLUDES : {} ),
|
||||
:boilerplates => ((defined? MODULE_GENERATOR_BOILERPLATES) ? MODULE_GENERATOR_BOILERPLATES : {} ),
|
||||
:naming => ((defined? MODULE_GENERATOR_NAMING ) ? MODULE_GENERATOR_NAMING : nil ),
|
||||
:update_svn => ((defined? MODULE_GENERATOR_UPDATE_SVN ) ? MODULE_GENERATOR_UPDATE_SVN : false ),
|
||||
}
|
||||
|
||||
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])
|
||||
end
|
||||
|
||||
return unity_generator_options
|
||||
end
|
||||
|
||||
end
|
||||
43
test/vendor/ceedling/plugins/module_generator/module_generator.rake
vendored
Normal file
43
test/vendor/ceedling/plugins/module_generator/module_generator.rake
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
namespace :module do
|
||||
module_root_separator = ":"
|
||||
|
||||
desc "Generate module (source, header and test files)"
|
||||
task :create, :module_path do |t, args|
|
||||
files = [args[:module_path]] + (args.extras || [])
|
||||
optz = { :module_root_path => "" }
|
||||
["dh", "dih", "mch", "mvp", "src", "test"].each do |pat|
|
||||
p = files.delete(pat)
|
||||
optz[:pattern] = p unless p.nil?
|
||||
end
|
||||
files.each {
|
||||
|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
|
||||
|
||||
desc "Destroy module (source, header and test files)"
|
||||
task :destroy, :module_path do |t, args|
|
||||
files = [args[:module_path]] + (args.extras || [])
|
||||
optz = { :destroy => true, :module_root_path => "" }
|
||||
["dh", "dih", "mch", "mvp", "src", "test"].each do |pat|
|
||||
p = files.delete(pat)
|
||||
optz[:pattern] = p unless p.nil?
|
||||
end
|
||||
files.each {
|
||||
|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
|
||||
41
test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb
vendored
Normal file
41
test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
|
||||
class RawOutputReport < Plugin
|
||||
def setup
|
||||
@log_paths = {}
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
output = strip_output(arg_hash[:shell_result][:output])
|
||||
write_raw_output_log(arg_hash, output)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def strip_output(raw_output)
|
||||
output = ""
|
||||
raw_output.each_line do |line|
|
||||
next if line =~ /^\n$/
|
||||
next if line =~ /^.*:\d+:.*:(IGNORE|PASS|FAIL)/
|
||||
return output if line =~/^-----------------------\n$/
|
||||
output << line
|
||||
end
|
||||
end
|
||||
def write_raw_output_log(arg_hash, output)
|
||||
logging = generate_log_path(arg_hash)
|
||||
@ceedling[:file_wrapper].write(logging[:path], output , logging[:flags]) unless logging.nil?
|
||||
end
|
||||
|
||||
def generate_log_path(arg_hash)
|
||||
f_name = File.basename(arg_hash[:result_file], '.pass')
|
||||
base_path = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, arg_hash[:context].to_s)
|
||||
file_path = File.join(base_path, f_name + '.log')
|
||||
|
||||
if @ceedling[:file_wrapper].exist?(base_path)
|
||||
return { path: file_path, flags: 'w' }
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
84
test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb
vendored
Normal file
84
test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
% ignored = hash[:results][:counts][:ignored]
|
||||
% failed = hash[:results][:counts][:failed]
|
||||
% stdout_count = hash[:results][:counts][:stdout]
|
||||
% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '')
|
||||
% banner_width = 25 + header_prepend.length # widest message
|
||||
% results = {}
|
||||
% hash[:results][:successes].each do |testresult|
|
||||
% results[ testresult[:source][:file] ] = testresult[:collection]
|
||||
% results[ testresult[:source][:file] ].length.times do |i|
|
||||
% results[ testresult[:source][:file] ][i][:pass] = true
|
||||
% end
|
||||
% end
|
||||
% hash[:results][:ignores].each do |testresult|
|
||||
% if (results[ testresult[:source][:file] ].nil?)
|
||||
% results[ testresult[:source][:file] ] = testresult[:collection]
|
||||
% else
|
||||
% results[ testresult[:source][:file] ] += testresult[:collection]
|
||||
% end
|
||||
% results[ testresult[:source][:file] ].length.times do |i|
|
||||
% results[ testresult[:source][:file] ][i][:pass] = true
|
||||
% end
|
||||
% end
|
||||
% hash[:results][:failures].each do |testresult|
|
||||
% if (results[ testresult[:source][:file] ].nil?)
|
||||
% results[ testresult[:source][:file] ] = testresult[:collection]
|
||||
% else
|
||||
% results[ testresult[:source][:file] ] += testresult[:collection]
|
||||
% end
|
||||
% end
|
||||
|
||||
|
||||
[==========] Running <%=hash[:results][:counts][:total].to_s%> tests from <%=results.length.to_s%> test cases.
|
||||
[----------] Global test environment set-up.
|
||||
% results.each_pair do |modulename, moduledetails|
|
||||
[----------] <%=moduledetails.length.to_s%> tests from <%=modulename%>
|
||||
% moduledetails.each do |item|
|
||||
[ RUN ] <%=modulename%>.<%=item[:test]%>
|
||||
% if (not item[:pass])
|
||||
% if (not item[:message].empty?)
|
||||
<%=modulename%>(<%=item[:line]%>): error: <%=item[:message]%>
|
||||
|
||||
% m = item[:message].match(/Expected\s+(.*)\s+Was\s+([^\.]*)\./)
|
||||
% if m.nil?
|
||||
Actual: FALSE
|
||||
Expected: TRUE
|
||||
% else
|
||||
Actual: <%=m[2]%>
|
||||
Expected: <%=m[1]%>
|
||||
% end
|
||||
% else
|
||||
<%=modulename%>(<%=item[:line]%>): fail: <%=item[:message]%>
|
||||
Actual: FALSE
|
||||
Expected: TRUE
|
||||
% end
|
||||
[ FAILED ] <%=modulename%>.<%=item[:test]%> (0 ms)
|
||||
% else
|
||||
[ OK ] <%=modulename%>.<%=item[:test]%> (0 ms)
|
||||
% end
|
||||
% end
|
||||
[----------] <%=moduledetails.length.to_s%> tests from <%=modulename%> (0 ms total)
|
||||
% end
|
||||
|
||||
% if (hash[:results][:counts][:total] > 0)
|
||||
[----------] Global test environment tear-down.
|
||||
[==========] <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases ran.
|
||||
[ PASSED ] <%=hash[:results][:counts][:passed].to_s%> tests.
|
||||
% if (failed == 0)
|
||||
[ FAILED ] 0 tests.
|
||||
|
||||
0 FAILED TESTS
|
||||
% else
|
||||
[ FAILED ] <%=failed.to_s%> tests, listed below:
|
||||
% hash[:results][:failures].each do |failure|
|
||||
% failure[:collection].each do |item|
|
||||
[ FAILED ] <%=failure[:source][:file]%>.<%=item[:test]%>
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
|
||||
<%=failed.to_s%> FAILED TESTS
|
||||
% else
|
||||
|
||||
No tests executed.
|
||||
% end
|
||||
59
test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy
vendored
Normal file
59
test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
% ignored = hash[:results][:counts][:ignored]
|
||||
% failed = hash[:results][:counts][:failed]
|
||||
% stdout_count = hash[:results][:counts][:stdout]
|
||||
% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '')
|
||||
% banner_width = 25 + header_prepend.length # widest message
|
||||
|
||||
|
||||
% if (stdout_count > 0)
|
||||
[==========] Running <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases.
|
||||
[----------] Global test environment set-up.
|
||||
% end
|
||||
% if (failed > 0)
|
||||
% hash[:results][:failures].each do |failure|
|
||||
[----------] <%=failure[:collection].length.to_s%> tests from <%=failure[:source][:file]%>
|
||||
% failure[:collection].each do |item|
|
||||
[ RUN ] <%=failure[:source][:file]%>.<%=item[:test]%>
|
||||
% if (not item[:message].empty?)
|
||||
<%=failure[:source][:file]%>(<%=item[:line]%>): error: <%=item[:message]%>
|
||||
|
||||
% m = item[:message].match(/Expected\s+(.*)\s+Was\s+([^\.]*)\./)
|
||||
% if m.nil?
|
||||
Actual: FALSE
|
||||
Expected: TRUE
|
||||
% else
|
||||
Actual: <%=m[2]%>
|
||||
Expected: <%=m[1]%>
|
||||
% end
|
||||
% else
|
||||
<%=failure[:source][:file]%>(<%=item[:line]%>): fail: <%=item[:message]%>
|
||||
Actual: FALSE
|
||||
Expected: TRUE
|
||||
% end
|
||||
[ FAILED ] <%=failure[:source][:file]%>.<%=item[:test]%> (0 ms)
|
||||
% end
|
||||
[----------] <%=failure[:collection].length.to_s%> tests from <%=failure[:source][:file]%> (0 ms total)
|
||||
% end
|
||||
% end
|
||||
% if (hash[:results][:counts][:total] > 0)
|
||||
[----------] Global test environment tear-down.
|
||||
[==========] <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases ran.
|
||||
[ PASSED ] <%=hash[:results][:counts][:passed].to_s%> tests.
|
||||
% if (failed == 0)
|
||||
[ FAILED ] 0 tests.
|
||||
|
||||
0 FAILED TESTS
|
||||
% else
|
||||
[ FAILED ] <%=failed.to_s%> tests, listed below:
|
||||
% hash[:results][:failures].each do |failure|
|
||||
% failure[:collection].each do |item|
|
||||
[ FAILED ] <%=failure[:source][:file]%>.<%=item[:test]%>
|
||||
% end
|
||||
% end
|
||||
|
||||
<%=failed.to_s%> FAILED TESTS
|
||||
% end
|
||||
% else
|
||||
|
||||
No tests executed.
|
||||
% end
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
:plugins:
|
||||
# tell Ceedling we got results display taken care of
|
||||
:display_raw_test_results: FALSE
|
||||
43
test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb
vendored
Normal file
43
test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/defaults'
|
||||
|
||||
class StdoutGtestlikeTestsReport < Plugin
|
||||
|
||||
def setup
|
||||
@result_list = []
|
||||
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
template = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb'))
|
||||
@ceedling[:plugin_reportinator].register_test_results_template( template )
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
return if not (arg_hash[:context] == TEST_SYM)
|
||||
|
||||
@result_list << arg_hash[:result_file]
|
||||
end
|
||||
|
||||
def post_build
|
||||
return if not (@ceedling[:task_invoker].test_invoked?)
|
||||
|
||||
results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
|
||||
hash = {
|
||||
:header => '',
|
||||
:results => results
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash)
|
||||
end
|
||||
|
||||
def summary
|
||||
result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS )
|
||||
|
||||
# get test results for only those tests in our configuration and of those only tests with results on disk
|
||||
hash = {
|
||||
:header => '',
|
||||
:results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false})
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash)
|
||||
end
|
||||
|
||||
end
|
||||
4
test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml
vendored
Normal file
4
test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
:plugins:
|
||||
# tell Ceedling we got results display taken care of
|
||||
:display_raw_test_results: FALSE
|
||||
44
test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb
vendored
Normal file
44
test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/defaults'
|
||||
|
||||
class StdoutIdeTestsReport < Plugin
|
||||
|
||||
def setup
|
||||
@result_list = []
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
return if not (arg_hash[:context] == TEST_SYM)
|
||||
|
||||
@result_list << arg_hash[:result_file]
|
||||
end
|
||||
|
||||
def post_build
|
||||
return if (not @ceedling[:task_invoker].test_invoked?)
|
||||
|
||||
results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
|
||||
hash = {
|
||||
:header => '',
|
||||
:results => results
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash) do
|
||||
message = ''
|
||||
message = 'Unit test failures.' if (hash[:results][:counts][:failed] > 0)
|
||||
message
|
||||
end
|
||||
end
|
||||
|
||||
def summary
|
||||
result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS )
|
||||
|
||||
# get test results for only those tests in our configuration and of those only tests with results on disk
|
||||
hash = {
|
||||
:header => '',
|
||||
:results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false})
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash)
|
||||
end
|
||||
|
||||
end
|
||||
59
test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb
vendored
Normal file
59
test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
% ignored = hash[:results][:counts][:ignored]
|
||||
% failed = hash[:results][:counts][:failed]
|
||||
% stdout_count = hash[:results][:counts][:stdout]
|
||||
% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '')
|
||||
% banner_width = 25 + header_prepend.length # widest message
|
||||
|
||||
% if (stdout_count > 0)
|
||||
<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'TEST OUTPUT')%>
|
||||
% hash[:results][:stdout].each do |string|
|
||||
[<%=string[:source][:file]%>]
|
||||
% string[:collection].each do |item|
|
||||
- "<%=item%>"
|
||||
% end
|
||||
|
||||
% end
|
||||
% end
|
||||
% if (ignored > 0)
|
||||
<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'IGNORED TEST SUMMARY')%>
|
||||
% hash[:results][:ignores].each do |ignore|
|
||||
[<%=ignore[:source][:file]%>]
|
||||
% ignore[:collection].each do |item|
|
||||
Test: <%=item[:test]%>
|
||||
% if (not item[:message].empty?)
|
||||
At line (<%=item[:line]%>): "<%=item[:message]%>"
|
||||
% else
|
||||
At line (<%=item[:line]%>)
|
||||
% end
|
||||
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
% if (failed > 0)
|
||||
<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'FAILED TEST SUMMARY')%>
|
||||
% hash[:results][:failures].each do |failure|
|
||||
[<%=failure[:source][:file]%>]
|
||||
% failure[:collection].each do |item|
|
||||
Test: <%=item[:test]%>
|
||||
% if (not item[:message].empty?)
|
||||
At line (<%=item[:line]%>): "<%=item[:message]%>"
|
||||
% else
|
||||
At line (<%=item[:line]%>)
|
||||
% end
|
||||
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
% total_string = hash[:results][:counts][:total].to_s
|
||||
% format_string = "%#{total_string.length}i"
|
||||
<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'OVERALL TEST SUMMARY')%>
|
||||
% if (hash[:results][:counts][:total] > 0)
|
||||
TESTED: <%=hash[:results][:counts][:total].to_s%>
|
||||
PASSED: <%=sprintf(format_string, hash[:results][:counts][:passed])%>
|
||||
FAILED: <%=sprintf(format_string, failed)%>
|
||||
IGNORED: <%=sprintf(format_string, ignored)%>
|
||||
% else
|
||||
|
||||
No tests executed.
|
||||
% end
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
:plugins:
|
||||
# tell Ceedling we got results display taken care of
|
||||
:display_raw_test_results: FALSE
|
||||
47
test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb
vendored
Normal file
47
test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/defaults'
|
||||
|
||||
class StdoutPrettyTestsReport < Plugin
|
||||
|
||||
def setup
|
||||
@result_list = []
|
||||
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
template = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb'))
|
||||
@ceedling[:plugin_reportinator].register_test_results_template( template )
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
return if not (arg_hash[:context] == TEST_SYM)
|
||||
|
||||
@result_list << arg_hash[:result_file]
|
||||
end
|
||||
|
||||
def post_build
|
||||
return if not (@ceedling[:task_invoker].test_invoked?)
|
||||
|
||||
results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
|
||||
hash = {
|
||||
:header => '',
|
||||
:results => results
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash) do
|
||||
message = ''
|
||||
message = 'Unit test failures.' if (results[:counts][:failed] > 0)
|
||||
message
|
||||
end
|
||||
end
|
||||
|
||||
def summary
|
||||
result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS )
|
||||
|
||||
# get test results for only those tests in our configuration and of those only tests with results on disk
|
||||
hash = {
|
||||
:header => '',
|
||||
:results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false})
|
||||
}
|
||||
|
||||
@ceedling[:plugin_reportinator].run_test_results_report(hash)
|
||||
end
|
||||
|
||||
end
|
||||
63
test/vendor/ceedling/plugins/subprojects/README.md
vendored
Normal file
63
test/vendor/ceedling/plugins/subprojects/README.md
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
ceedling-subprojects
|
||||
====================
|
||||
|
||||
Plugin for supporting subprojects that are built as static libraries. It continues to support
|
||||
dependency tracking, without getting confused between your main project files and your
|
||||
subproject files. It accepts different compiler flags and linker flags, allowing you to
|
||||
optimize for your situation.
|
||||
|
||||
First, you're going to want to add the extension to your list of known extensions:
|
||||
|
||||
```
|
||||
:extension:
|
||||
:subprojects: '.a'
|
||||
```
|
||||
|
||||
Define a new section called :subprojects. There, you can list as many subprojects
|
||||
as you may need under the :paths key. For each, you specify a unique place to build
|
||||
and a unique name.
|
||||
|
||||
```
|
||||
:subprojects:
|
||||
:paths:
|
||||
- :name: libprojectA
|
||||
:source:
|
||||
- ./subprojectA/first/dir
|
||||
- ./subprojectA/second/dir
|
||||
:include:
|
||||
- ./subprojectA/include/dir
|
||||
:build_root: ./subprojectA/build/dir
|
||||
:defines:
|
||||
- DEFINE_JUST_FOR_THIS_FILE
|
||||
- AND_ANOTHER
|
||||
- :name: libprojectB
|
||||
:source:
|
||||
- ./subprojectB/only/dir
|
||||
:include:
|
||||
- ./subprojectB/first/include/dir
|
||||
- ./subprojectB/second/include/dir
|
||||
:build_root: ./subprojectB/build/dir
|
||||
:defines: [] #none for this one
|
||||
```
|
||||
|
||||
You can specify the compiler and linker, just as you would a release build:
|
||||
|
||||
```
|
||||
:tools:
|
||||
:subprojects_compiler:
|
||||
:executable: gcc
|
||||
:arguments:
|
||||
- -g
|
||||
- -I"$": COLLECTION_PATHS_SUBPROJECTS
|
||||
- -D$: COLLECTION_DEFINES_SUBPROJECTS
|
||||
- -c "${1}"
|
||||
- -o "${2}"
|
||||
:subprojects_linker:
|
||||
:executable: ar
|
||||
:arguments:
|
||||
- rcs
|
||||
- ${2}
|
||||
- ${1}
|
||||
```
|
||||
|
||||
That's all there is to it! Happy Hacking!
|
||||
33
test/vendor/ceedling/plugins/subprojects/config/defaults.yml
vendored
Normal file
33
test/vendor/ceedling/plugins/subprojects/config/defaults.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
#:extension:
|
||||
# :subprojects: '.a'
|
||||
|
||||
:subprojects:
|
||||
:paths: []
|
||||
# - :name: subprojectA
|
||||
# :source:
|
||||
# - ./first/subproject/dir
|
||||
# - ./second/subproject/dir
|
||||
# :include:
|
||||
# - ./first/include/dir
|
||||
# :build_root: ./subproject/build/dir
|
||||
# :defines:
|
||||
# - FIRST_DEFINE
|
||||
|
||||
:tools:
|
||||
:subprojects_compiler:
|
||||
:executable: gcc
|
||||
:arguments:
|
||||
- -g
|
||||
- -I"$": COLLECTION_PATHS_SUBPROJECTS
|
||||
- -D$: COLLECTION_DEFINES_SUBPROJECTS
|
||||
- -c "${1}"
|
||||
- -o "${2}"
|
||||
:subprojects_linker:
|
||||
:executable: ar
|
||||
:arguments:
|
||||
- rcs
|
||||
- ${2}
|
||||
- ${1}
|
||||
|
||||
...
|
||||
92
test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb
vendored
Normal file
92
test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
|
||||
SUBPROJECTS_ROOT_NAME = 'subprojects'
|
||||
SUBPROJECTS_TASK_ROOT = SUBPROJECTS_ROOT_NAME + ':'
|
||||
SUBPROJECTS_SYM = SUBPROJECTS_ROOT_NAME.to_sym
|
||||
|
||||
class Subprojects < Plugin
|
||||
|
||||
def setup
|
||||
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
|
||||
# Add to the test paths
|
||||
SUBPROJECTS_PATHS.each do |subproj|
|
||||
subproj[:source].each do |path|
|
||||
COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << path
|
||||
end
|
||||
subproj[:include].each do |path|
|
||||
COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << path
|
||||
end
|
||||
end
|
||||
|
||||
#gather information about the subprojects
|
||||
@subprojects = {}
|
||||
@subproject_lookup_by_path = {}
|
||||
SUBPROJECTS_PATHS.each do |subproj|
|
||||
@subprojects[ subproj[:name] ] = subproj.clone
|
||||
@subprojects[ subproj[:name] ][:c] = []
|
||||
@subprojects[ subproj[:name] ][:asm] = []
|
||||
subproj[:source].each do |path|
|
||||
search_path = "#{path[-1].match(/\\|\//) ? path : "#{path}/"}*#{EXTENSION_SOURCE}"
|
||||
@subprojects[ subproj[:name] ][:c] += Dir[search_path]
|
||||
if (EXTENSION_ASSEMBLY && !EXTENSION_ASSEMBLY.empty?)
|
||||
search_path = "#{path[-1].match(/\\|\//) ? path : "#{path}/"}*#{EXTENSION_ASSEMBLY}"
|
||||
@subprojects[ subproj[:name] ][:asm] += Dir[search_path]
|
||||
end
|
||||
end
|
||||
@subproject_lookup_by_path[ subproj[:build_root] ] = subproj[:name]
|
||||
end
|
||||
end
|
||||
|
||||
def find_my_project( c_file, file_type = :c )
|
||||
@subprojects.each_pair do |subprojname, subproj|
|
||||
return subprojname if (subproj[file_type].include?(c_file))
|
||||
end
|
||||
end
|
||||
|
||||
def find_my_paths( c_file, file_type = :c )
|
||||
@subprojects.each_pair do |subprojname, subproj|
|
||||
return (subproj[:source] + (subproj[:include] || [])) if (subproj[file_type].include?(c_file))
|
||||
end
|
||||
return []
|
||||
end
|
||||
|
||||
def find_my_defines( c_file, file_type = :c )
|
||||
@subprojects.each_pair do |subprojname, subproj|
|
||||
return (subproj[:defines] || []) if (subproj[file_type].include?(c_file))
|
||||
end
|
||||
return []
|
||||
end
|
||||
|
||||
def list_all_object_files_for_subproject( lib_name )
|
||||
subproj = File.basename(lib_name, EXTENSION_SUBPROJECTS)
|
||||
objpath = "#{@subprojects[subproj][:build_root]}/out/c"
|
||||
bbb = @subprojects[subproj][:c].map{|f| "#{objpath}/#{File.basename(f,EXTENSION_SOURCE)}#{EXTENSION_OBJECT}" }
|
||||
bbb
|
||||
end
|
||||
|
||||
def find_library_source_file_for_object( obj_name )
|
||||
cname = "#{File.basename(obj_name, EXTENSION_OBJECT)}#{EXTENSION_SOURCE}"
|
||||
dname = File.dirname(obj_name)[0..-7]
|
||||
pname = @subproject_lookup_by_path[dname]
|
||||
return @ceedling[:file_finder].find_file_from_list(cname, @subprojects[pname][:c], :error)
|
||||
end
|
||||
|
||||
def find_library_assembly_file_for_object( obj_name )
|
||||
cname = "#{File.basename(obj_name, EXTENSION_OBJECT)}#{EXTENSION_ASEMBLY}"
|
||||
dname = File.dirname(obj_name)[0..-7]
|
||||
pname = @subproject_lookup_by_path[dname]
|
||||
return @ceedling[:file_finder].find_file_from_list(cname, @subprojects[pname][:asm], :error)
|
||||
end
|
||||
|
||||
def replace_constant(constant, new_value)
|
||||
Object.send(:remove_const, constant.to_sym) if (Object.const_defined? constant)
|
||||
Object.const_set(constant, new_value)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# end blocks always executed following rake run
|
||||
END {
|
||||
}
|
||||
78
test/vendor/ceedling/plugins/subprojects/subprojects.rake
vendored
Normal file
78
test/vendor/ceedling/plugins/subprojects/subprojects.rake
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
|
||||
SUBPROJECTS_PATHS.each do |subproj|
|
||||
|
||||
subproj_source = subproj[:source]
|
||||
subproj_include = subproj[:include]
|
||||
subproj_name = subproj[:name]
|
||||
subproj_build_root = subproj[:build_root]
|
||||
subproj_build_out = "#{subproj[:build_root]}/out"
|
||||
subproj_build_c = "#{subproj[:build_root]}/out/c"
|
||||
subproj_build_asm = "#{subproj[:build_root]}/out/asm"
|
||||
subproj_directories = [ subproj_build_root, subproj_build_out, subproj_build_c, subproj_build_asm ]
|
||||
|
||||
subproj_directories.each do |subdir|
|
||||
directory(subdir)
|
||||
end
|
||||
|
||||
CLEAN.include(File.join(subproj_build_root, '*'))
|
||||
CLEAN.include(File.join(subproj_build_out, '*'))
|
||||
|
||||
CLOBBER.include(File.join(subproj_build_root, '**/*'))
|
||||
|
||||
# Add a rule for building the actual static library from our object files
|
||||
rule(/#{subproj_build_root}#{'.+\\'+EXTENSION_SUBPROJECTS}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[SUBPROJECTS_SYM].list_all_object_files_for_subproject(task_name)
|
||||
end
|
||||
]) do |bin_file|
|
||||
@ceedling[:generator].generate_executable_file(
|
||||
TOOLS_SUBPROJECTS_LINKER,
|
||||
SUBPROJECTS_SYM,
|
||||
bin_file.prerequisites,
|
||||
bin_file.name,
|
||||
@ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name))
|
||||
end
|
||||
|
||||
# Add a rule for building object files from assembly files to link into a library
|
||||
if (RELEASE_BUILD_USE_ASSEMBLY)
|
||||
rule(/#{subproj_build_asm}#{'.+\\'+EXTENSION_OBJECT}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[SUBPROJECTS_SYM].find_library_assembly_file_for_object(task_name)
|
||||
end
|
||||
]) do |object|
|
||||
@ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_PATHS_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_paths(object.source, :asm))
|
||||
@ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_DEFINES_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_defines(object.source, :asm))
|
||||
@ceedling[:generator].generate_object_file(
|
||||
TOOLS_SUBPROJECTS_ASSEMBLER,
|
||||
OPERATION_ASSEMBLE_SYM,
|
||||
SUBPROJECTS_SYM,
|
||||
object.source,
|
||||
object.name )
|
||||
end
|
||||
end
|
||||
|
||||
# Add a rule for building object files from C files to link into a library
|
||||
rule(/#{subproj_build_c}#{'.+\\'+EXTENSION_OBJECT}$/ => [
|
||||
proc do |task_name|
|
||||
@ceedling[SUBPROJECTS_SYM].find_library_source_file_for_object(task_name)
|
||||
end
|
||||
]) do |object|
|
||||
@ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_PATHS_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_paths(object.source, :c))
|
||||
@ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_DEFINES_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_defines(object.source, :c))
|
||||
@ceedling[:generator].generate_object_file(
|
||||
TOOLS_SUBPROJECTS_COMPILER,
|
||||
OPERATION_COMPILE_SYM,
|
||||
SUBPROJECTS_SYM,
|
||||
object.source,
|
||||
object.name,
|
||||
@ceedling[:file_path_utils].form_release_build_c_list_filepath( object.name ) )
|
||||
end
|
||||
|
||||
# Add the subdirectories involved to our list of those that should be autogenerated
|
||||
task :directories => subproj_directories.clone
|
||||
|
||||
# Finally, add the static library to our RELEASE build dependency list
|
||||
task RELEASE_SYM => ["#{subproj_build_root}/#{subproj_name}#{EXTENSION_SUBPROJECTS}"]
|
||||
end
|
||||
|
||||
4
test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml
vendored
Normal file
4
test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
:plugins:
|
||||
# tell Ceedling we got results display taken care of
|
||||
:display_raw_test_results: FALSE
|
||||
57
test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb
vendored
Normal file
57
test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/defaults'
|
||||
|
||||
class TeamcityTestsReport < Plugin
|
||||
|
||||
def setup
|
||||
@suite_started = nil
|
||||
@output_enabled = !defined?(TEAMCITY_BUILD) || TEAMCITY_BUILD
|
||||
end
|
||||
|
||||
def escape(string)
|
||||
string.gsub(/['|\[\]]/, '|\0').gsub('\r', '|r').gsub('\n', '|n')
|
||||
end
|
||||
|
||||
def pre_test(test)
|
||||
teamcity_message "testSuiteStarted name='#{File.basename(test, '.c')}'"
|
||||
@suite_started = Time.now
|
||||
end
|
||||
|
||||
def post_test(test)
|
||||
teamcity_message "testSuiteFinished name='#{File.basename(test, '.c')}'"
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
duration = (Time.now - @suite_started) * 1000
|
||||
results = @ceedling[:plugin_reportinator].assemble_test_results([arg_hash[:result_file]])
|
||||
avg_duration = (duration / [1, results[:counts][:passed] + results[:counts][:failed]].max).round
|
||||
|
||||
results[:successes].each do |success|
|
||||
success[:collection].each do |test|
|
||||
teamcity_message "testStarted name='#{test[:test]}'"
|
||||
teamcity_message "testFinished name='#{test[:test]}' duration='#{avg_duration}'"
|
||||
end
|
||||
end
|
||||
|
||||
results[:failures].each do |failure|
|
||||
failure[:collection].each do |test|
|
||||
teamcity_message "testStarted name='#{test[:test]}'"
|
||||
teamcity_message "testFailed name='#{test[:test]}' message='#{escape(test[:message])}' details='File: #{failure[:source][:path]}/#{failure[:source][:file]} Line: #{test[:line]}'"
|
||||
teamcity_message "testFinished name='#{test[:test]}' duration='#{avg_duration}'"
|
||||
end
|
||||
end
|
||||
|
||||
results[:ignores].each do |failure|
|
||||
failure[:collection].each do |test|
|
||||
teamcity_message "testIgnored name='#{test[:test]}' message='#{escape(test[:message])}'"
|
||||
end
|
||||
end
|
||||
|
||||
# We ignore stdout
|
||||
end
|
||||
|
||||
def teamcity_message(content)
|
||||
puts "##teamcity[#{content}]" unless !@output_enabled
|
||||
end
|
||||
|
||||
end
|
||||
69
test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb
vendored
Normal file
69
test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
|
||||
class WarningsReport < Plugin
|
||||
def setup
|
||||
@stderr_redirect = nil
|
||||
@log_paths = {}
|
||||
end
|
||||
|
||||
def pre_compile_execute(arg_hash)
|
||||
# at beginning of compile, override tool's stderr_redirect so we can parse $stderr + $stdout
|
||||
set_stderr_redirect(arg_hash)
|
||||
end
|
||||
|
||||
def post_compile_execute(arg_hash)
|
||||
# after compilation, grab output for parsing/logging, restore stderr_redirect, log warning if it exists
|
||||
output = arg_hash[:shell_result][:output]
|
||||
restore_stderr_redirect(arg_hash)
|
||||
write_warning_log(arg_hash[:context], output)
|
||||
end
|
||||
|
||||
def pre_link_execute(arg_hash)
|
||||
# at beginning of link, override tool's stderr_redirect so we can parse $stderr + $stdout
|
||||
set_stderr_redirect(arg_hash)
|
||||
end
|
||||
|
||||
def post_link_execute(arg_hash)
|
||||
# after linking, grab output for parsing/logging, restore stderr_redirect, log warning if it exists
|
||||
output = arg_hash[:shell_result][:output]
|
||||
restore_stderr_redirect(arg_hash)
|
||||
write_warning_log(arg_hash[:context], output)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_stderr_redirect(hash)
|
||||
@stderr_redirect = hash[:tool][:stderr_redirect]
|
||||
hash[:tool][:stderr_redirect] = StdErrRedirect::AUTO
|
||||
end
|
||||
|
||||
def restore_stderr_redirect(hash)
|
||||
hash[:tool][:stderr_redirect] = @stderr_redirect
|
||||
end
|
||||
|
||||
def write_warning_log(context, output)
|
||||
# if $stderr/$stdout contain "warning", log it
|
||||
if output =~ /warning/i
|
||||
# generate a log path & file io write flags
|
||||
logging = generate_log_path(context)
|
||||
@ceedling[:file_wrapper].write(logging[:path], output + "\n", logging[:flags]) unless logging.nil?
|
||||
end
|
||||
end
|
||||
|
||||
def generate_log_path(context)
|
||||
# if path has already been generated, return it & 'append' file io flags (append to log)
|
||||
return { path: @log_paths[context], flags: 'a' } unless @log_paths[context].nil?
|
||||
|
||||
# first time through, generate path & 'write' file io flags (create new log)
|
||||
base_path = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s)
|
||||
file_path = File.join(base_path, 'warnings.log')
|
||||
|
||||
if @ceedling[:file_wrapper].exist?(base_path)
|
||||
@log_paths[context] = file_path
|
||||
return { path: file_path, flags: 'w' }
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
108
test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb
vendored
Normal file
108
test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
require 'ceedling/plugin'
|
||||
require 'ceedling/constants'
|
||||
|
||||
class XmlTestsReport < Plugin
|
||||
def setup
|
||||
@results_list = {}
|
||||
@test_counter = 0
|
||||
end
|
||||
|
||||
def post_test_fixture_execute(arg_hash)
|
||||
context = arg_hash[:context]
|
||||
|
||||
@results_list[context] = [] if @results_list[context].nil?
|
||||
|
||||
@results_list[context] << arg_hash[:result_file]
|
||||
end
|
||||
|
||||
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')
|
||||
|
||||
@ceedling[:file_wrapper].open(file_path, 'w') do |f|
|
||||
@test_counter = 1
|
||||
write_results(results, f)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def write_results(results, stream)
|
||||
write_header(stream)
|
||||
write_failures(results[:failures], stream)
|
||||
write_tests(results[:successes], stream, 'SuccessfulTests')
|
||||
write_tests(results[:ignores], stream, 'IgnoredTests')
|
||||
write_statistics(results[:counts], stream)
|
||||
write_footer(stream)
|
||||
end
|
||||
|
||||
def write_header(stream)
|
||||
stream.puts "<?xml version='1.0' encoding='utf-8' ?>"
|
||||
stream.puts '<TestRun>'
|
||||
end
|
||||
|
||||
def write_failures(results, stream)
|
||||
if results.size.zero?
|
||||
stream.puts "\t<FailedTests/>"
|
||||
return
|
||||
end
|
||||
|
||||
stream.puts "\t<FailedTests>"
|
||||
|
||||
results.each do |result|
|
||||
result[:collection].each do |item|
|
||||
filename = File.join(result[:source][:path], result[:source][:file])
|
||||
|
||||
stream.puts "\t\t<Test id=\"#{@test_counter}\">"
|
||||
stream.puts "\t\t\t<Name>#{filename}::#{item[:test]}</Name>"
|
||||
stream.puts "\t\t\t<FailureType>Assertion</FailureType>"
|
||||
stream.puts "\t\t\t<Location>"
|
||||
stream.puts "\t\t\t\t<File>#{filename}</File>"
|
||||
stream.puts "\t\t\t\t<Line>#{item[:line]}</Line>"
|
||||
stream.puts "\t\t\t</Location>"
|
||||
stream.puts "\t\t\t<Message>#{item[:message]}</Message>"
|
||||
stream.puts "\t\t</Test>"
|
||||
@test_counter += 1
|
||||
end
|
||||
end
|
||||
|
||||
stream.puts "\t</FailedTests>"
|
||||
end
|
||||
|
||||
def write_tests(results, stream, tag)
|
||||
if results.size.zero?
|
||||
stream.puts "\t<#{tag}/>"
|
||||
return
|
||||
end
|
||||
|
||||
stream.puts "\t<#{tag}>"
|
||||
|
||||
results.each do |result|
|
||||
result[:collection].each do |item|
|
||||
stream.puts "\t\t<Test id=\"#{@test_counter}\">"
|
||||
stream.puts "\t\t\t<Name>#{File.join(result[:source][:path], result[:source][:file])}::#{item[:test]}</Name>"
|
||||
stream.puts "\t\t</Test>"
|
||||
@test_counter += 1
|
||||
end
|
||||
end
|
||||
|
||||
stream.puts "\t</#{tag}>"
|
||||
end
|
||||
|
||||
def write_statistics(counts, stream)
|
||||
stream.puts "\t<Statistics>"
|
||||
stream.puts "\t\t<Tests>#{counts[:total]}</Tests>"
|
||||
stream.puts "\t\t<Ignores>#{counts[:ignored]}</Ignores>"
|
||||
stream.puts "\t\t<FailuresTotal>#{counts[:failed]}</FailuresTotal>"
|
||||
stream.puts "\t\t<Errors>0</Errors>"
|
||||
stream.puts "\t\t<Failures>#{counts[:failed]}</Failures>"
|
||||
stream.puts "\t</Statistics>"
|
||||
end
|
||||
|
||||
def write_footer(stream)
|
||||
stream.puts '</TestRun>'
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user