Top Level Namespace

Includes:
Rake::DSL

Defined Under Namespace

Modules: Ceedling, Rake Classes: Application, BuildBatchinator, Cacheinator, CacheinatorHelper, CeedlingException, ConfigMatchinator, ConfigWalkinator, Configurator, ConfiguratorBuilder, ConfiguratorPlugins, ConfiguratorSetup, ConfiguratorValidator, Defineinator, Dependinator, DurationCounts, ErbWrapper, FileFinder, FileFinderHelper, FilePathCollectionUtils, FilePathUtils, FileSystemWrapper, FileWrapper, Flaginator, Generator, GeneratorHelper, GeneratorMocks, GeneratorTestResults, GeneratorTestResultsBacktrace, GeneratorTestResultsSanityChecker, GeneratorTestRunner, IncludePathinator, LogLabels, Loginator, Object, PATTERNS, ParsingParcels, Plugin, PluginManager, PluginManagerHelper, PluginReportinator, PluginReportinatorHelper, Preprocessinator, PreprocessinatorExtractor, PreprocessinatorFileHandler, PreprocessinatorIncludesHandler, RakeUtils, RakeWrapper, ReleaseInvoker, ReleaseInvokerHelper, Reportinator, Setupinator, ShellException, StdErrRedirect, StreamWrapper, String, Symbol, SystemUtils, SystemWrapper, TaskInvoker, TestContextExtractor, TestInvoker, TestInvokerHelper, TestResultsSanityChecks, TestRunnerManager, ToolExecutor, ToolExecutorHelper, ToolValidator, Verbosinator, Verbosity, YamlWrapper

Constant Summary collapse

CEEDLING_VENDOR =

Assign a default value for system testing where CEEDLING_APPCFG may not be present TODO: Create code config & test structure that does not internalize a test path like this

defined?( CEEDLING_APPCFG ) ? CEEDLING_APPCFG[:ceedling_vendor_path] : File.expand_path( File.dirname(__FILE__) + '/../../vendor' )
CEEDLING_PLUGINS =
[]
DEFAULT_TEST_COMPILER_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_test_compiler'.freeze,
:optional => false.freeze,
:arguments => [
  "-I\"${5}\"".freeze, # Per-test executable search paths
  "-D\"${6}\"".freeze, # Per-test executable defines
  "-DGNU_COMPILER".freeze, # OSX clang
  "-g".freeze,
  "-c \"${1}\"".freeze,
  "-o \"${2}\"".freeze,
  # gcc's list file output options are complex; no use of ${3} parameter in default config
  "-MMD".freeze,
  "-MF \"${4}\"".freeze,
  ].freeze
}
DEFAULT_TEST_ASSEMBLER_TOOL =
{
:executable => FilePathUtils.os_executable_ext('as').freeze,
:name => 'default_test_assembler'.freeze,
:optional => false.freeze,
:arguments => [
  "-I\"${3}\"".freeze, # Search paths
  # Any defines (${4}) are not included since GNU assembler ignores them
  "\"${1}\"".freeze,
  "-o \"${2}\"".freeze,
  ].freeze
}
DEFAULT_TEST_LINKER_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_test_linker'.freeze,
:optional => false.freeze,
:arguments => [
  "${1}".freeze,
  "${5}".freeze,
  "-o \"${2}\"".freeze,
  "".freeze,
  "${4}".freeze,
  ].freeze
}
DEFAULT_TEST_FIXTURE_TOOL =
{
:executable => '${1}'.freeze, # Unity test runner executable
:name => 'default_test_fixture'.freeze,
:optional => false.freeze,
:arguments => [].freeze
}
DEFAULT_TEST_FIXTURE_SIMPLE_BACKTRACE_TOOL =
{
:executable => '${1}'.freeze, # Unity test runner executable
:name => 'default_test_fixture_simple_backtrace'.freeze,
:optional => false.freeze,
:arguments => [
  '-n ${2}'.freeze # Exact test case name matching flag
  ].freeze
}
DEFAULT_TEST_SHALLOW_INCLUDES_PREPROCESSOR_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_test_shallow_includes_preprocessor'.freeze,
:optional => false.freeze,
:arguments => [
  '-E'.freeze,             # Run only through preprocessor stage with its output
  '-MM'.freeze,            # Output make rule + suppress header files found in system header directories
  '-MG'.freeze,            # Assume missing header files are generated files (do not discard)
  '-MP'.freeze,            # Create make "phony" rules for each include dependency
  "-D\"${2}\"".freeze,     # Per-test executable defines
  "-DGNU_COMPILER".freeze, # OSX clang
  '-nostdinc'.freeze,      # Ignore standard include paths
  "-x c".freeze,           # Force C language
  "\"${1}\"".freeze
  ].freeze
}
DEFAULT_TEST_NESTED_INCLUDES_PREPROCESSOR_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_test_nested_includes_preprocessor'.freeze,
:optional => false.freeze,
:arguments => [
  '-E'.freeze,             # Run only through preprocessor stage with its output
  '-MM'.freeze,            # Output make rule + suppress header files found in system header directories
  '-MG'.freeze,            # Assume missing header files are generated files (do not discard)
  '-H'.freeze,             # Also output #include list with depth
  "-I\"${2}\"".freeze,     # Per-test executable search paths
  "-D\"${3}\"".freeze,     # Per-test executable defines
  "-DGNU_COMPILER".freeze, # OSX clang
  '-nostdinc'.freeze,      # Ignore standard include paths
  "-x c".freeze,           # Force C language
  "\"${1}\"".freeze
  ].freeze
}
DEFAULT_TEST_FILE_FULL_PREPROCESSOR_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_test_file_full_preprocessor'.freeze,
:optional => false.freeze,
:arguments => [
  '-E'.freeze,
  "-I\"${4}\"".freeze, # Per-test executable search paths
  "-D\"${3}\"".freeze, # Per-test executable defines
  "-DGNU_COMPILER".freeze, # OSX clang
  # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX
  "-x c".freeze,           # Force C language
  "\"${1}\"".freeze,
  "-o \"${2}\"".freeze
  ].freeze
}
DEFAULT_TEST_FILE_DIRECTIVES_ONLY_PREPROCESSOR_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_test_file_directives_only_preprocessor'.freeze,
:optional => false.freeze,
:arguments => [
  '-E'.freeze,
  "-I\"${4}\"".freeze, # Per-test executable search paths
  "-D\"${3}\"".freeze, # Per-test executable defines
  "-DGNU_COMPILER".freeze, # OSX clang
  # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX
  "-x c".freeze,           # Force C language
  "-fdirectives-only",     # Only preprocess directives
  "\"${1}\"".freeze,
  "-o \"${2}\"".freeze
  ].freeze
}
MD_FLAG =

Clang doesn’t support the -MD flag

'-MD'
DEFAULT_RELEASE_DEPENDENCIES_GENERATOR_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_release_dependencies_generator'.freeze,
:optional => false.freeze,
:arguments => [
  '-E'.freeze,
  {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR'}.freeze,
  {"-I\"$\"" => 'COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE'}.freeze,
  {"-D$" => 'COLLECTION_DEFINES_RELEASE_AND_VENDOR'}.freeze,
  {"-D$" => 'DEFINES_RELEASE_PREPROCESS'}.freeze,
  "-DGNU_COMPILER".freeze,
  "-MT \"${3}\"".freeze,
  '-MM'.freeze,
  MD_FLAG.freeze,
  '-MG'.freeze,
  "-MF \"${2}\"".freeze,
  "-x c".freeze, # Force C language
  "-c \"${1}\"".freeze,
  # '-nostdinc'.freeze,
  ].freeze
}
DEFAULT_RELEASE_COMPILER_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_release_compiler'.freeze,
:optional => false.freeze,
:arguments => [
  "-I\"${5}\"".freeze, # Search paths
  "-D\"${6}\"".freeze, # Defines
  "-DGNU_COMPILER".freeze,
  "-c \"${1}\"".freeze,
  "-o \"${2}\"".freeze,
  # gcc's list file output options are complex; no use of ${3} parameter in default config
  "-MMD".freeze,
  "-MF \"${4}\"".freeze,
  ].freeze
}
DEFAULT_RELEASE_ASSEMBLER_TOOL =
{
:executable => FilePathUtils.os_executable_ext('as').freeze,
:name => 'default_release_assembler'.freeze,
:optional => false.freeze,
:arguments => [
  "-I\"${3}\"".freeze, # Search paths
  "-D\"${4}\"".freeze, # Defines (FYI--allowed with GNU assembler but ignored)
  "\"${1}\"".freeze,
  "-o \"${2}\"".freeze,
  ].freeze
}
DEFAULT_RELEASE_LINKER_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gcc').freeze,
:name => 'default_release_linker'.freeze,
:optional => false.freeze,
:arguments => [
  "\"${1}\"".freeze,
  "${5}".freeze,
  "-o \"${2}\"".freeze,
  "".freeze,
  "${4}".freeze,
  ].freeze
}
DEFAULT_TEST_BACKTRACE_GDB_TOOL =
{
:executable => FilePathUtils.os_executable_ext('gdb').freeze,
:name => 'default_test_backtrace_gdb'.freeze,
:optional => false.freeze,
:arguments => [
  '-q'.freeze,
  '--batch'.freeze,
  '--eval-command run'.freeze,
  "--command \"${1}\"".freeze, # Debug script file to run
  '--args'.freeze,
  '${2}'.freeze,               # Test executable
  '-n ${3}'.freeze             # Exact test case name matching flag
  ].freeze
}
DEFAULT_TOOLS_TEST =
{
:tools => {
  :test_compiler => DEFAULT_TEST_COMPILER_TOOL,
  :test_linker   => DEFAULT_TEST_LINKER_TOOL,
  :test_fixture  => DEFAULT_TEST_FIXTURE_TOOL,
  :test_fixture_simple_backtrace => DEFAULT_TEST_FIXTURE_SIMPLE_BACKTRACE_TOOL
  }
}
DEFAULT_TOOLS_TEST_GDB_BACKTRACE =
{
:tools => {
  :test_backtrace_gdb => DEFAULT_TEST_BACKTRACE_GDB_TOOL
  }
}
DEFAULT_TOOLS_TEST_ASSEMBLER =
{
:tools => {
  :test_assembler => DEFAULT_TEST_ASSEMBLER_TOOL,
  }
}
DEFAULT_TOOLS_TEST_PREPROCESSORS =
{
:tools => {
  :test_shallow_includes_preprocessor      => DEFAULT_TEST_SHALLOW_INCLUDES_PREPROCESSOR_TOOL,
  :test_nested_includes_preprocessor       => DEFAULT_TEST_NESTED_INCLUDES_PREPROCESSOR_TOOL,
  :test_file_full_preprocessor             => DEFAULT_TEST_FILE_FULL_PREPROCESSOR_TOOL,
  :test_file_directives_only_preprocessor  => DEFAULT_TEST_FILE_DIRECTIVES_ONLY_PREPROCESSOR_TOOL,
  }
}
DEFAULT_TOOLS_RELEASE =
{
:tools => {
  :release_compiler => DEFAULT_RELEASE_COMPILER_TOOL,
  :release_linker   => DEFAULT_RELEASE_LINKER_TOOL,
  }
}
DEFAULT_TOOLS_RELEASE_ASSEMBLER =
{
:tools => {
  :release_assembler => DEFAULT_RELEASE_ASSEMBLER_TOOL,
  }
}
DEFAULT_TOOLS_RELEASE_DEPENDENCIES =
{
:tools => {
  :release_dependencies_generator => DEFAULT_RELEASE_DEPENDENCIES_GENERATOR_TOOL,
  }
}
DEFAULT_RELEASE_TARGET_NAME =
'project'
DEFAULT_CEEDLING_PROJECT_CONFIG =
{
:project => {
  # :build_root must be set by user
  :use_mocks => true,
  :use_exceptions => false,
  :compile_threads => 1,
  :test_threads => 1,
  :use_test_preprocessor => :none,
  :use_deep_preprocessor => :none,
  :test_file_prefix => 'test_',
  :release_build => false,
  :use_backtrace => :simple
  },

:release_build => {
  # :output is set while building configuration -- allows smart default system-dependent file extension handling
  :use_assembly => false,
  :artifacts => []
  },

:test_build => {
  :use_assembly => false
  },

# Unlike other top-level entries, :environment is an array (of hashes) to preserve order
:environment => [],

:paths => {
  :test => [],    # Must be populated by user
  :source => [],  # Should be populated by user but TEST_INCLUDE_PATH() could be used exclusively instead
  :support => [],
  :include => [], # Must be populated by user
  :libraries => [],
  :test_toolchain_include => [],
  :release_toolchain_include => [],
  },

:files => {
  :test => [],
  :source => [],
  :assembly => [],
  :support => [],
  :include => [],
  },

:defines => {
  :use_test_definition => false,
  :test => [],   # List of symbols or matcher hashes with test executables as keys
  # :preprocess is identical to :test but lacks a default here as missing vs. empty values have additional meaning
  :release => [] # List of symbols only
  },

:flags => {
  # Test & release flags are validated for presence--empty flags causes an error
  # :test => {},   # hash/sub-hash of operations containing lists of flags or matcher hashes with test executables as keys
  # :release => {} # hash/sub-hashes of operations containing lists of flags
  },

:libraries => {
  :flag => '-l${1}',
  :path_flag => '-L ${1}',
  :test => [],
  :release => []
  },

:extension => {
  :header => '.h',
  :source => '.c',
  :assembly => '.s',
  :object => '.o',
  :libraries => ['.a','.so'],
  :executable => ( SystemWrapper.windows? ? EXTENSION_WIN_EXE : EXTENSION_NONWIN_EXE ),
  :map => '.map',
  :list => '.lst',
  :testpass => '.pass',
  :testfail => '.fail',
  :dependencies => '.d',
  :yaml => '.yml'
  },

:unity => {
  :defines => [],
  :use_param_tests => false
  },

:cmock => {
  :includes => [],
  :defines => [],
  :plugins => [],
  :unity_helper_path => [],
  # Yes, we're duplicating these defaults in CMock, but it's because:
  #  (A) We always need CMOCK_MOCK_PREFIX in Ceedling's environment
  #  (B) Test runner generator uses these same configuration values
  :mock_prefix => 'Mock',
  :mock_suffix => '',
  # CMock's default duplicated here.
  # We need a value present so preprocessing logic can safely reference it.
  :treat_inlines => :exclude,
  # Just because strict ordering is the way to go
  :enforce_strict_ordering => true
  },

:cexception => {
  :defines => []
 },

:test_runner => {
  :cmdline_args => false,
  :includes => [],
  :defines => [],
  :file_suffix => '_runner',
  },

# All tools populated while building up config / defaults structure
:tools => {},

}.freeze
CEEDLING_RUNTIME_CONFIG =
{
:unity => {
  :vendor_path => CEEDLING_VENDOR
  },

:cmock => {
  :vendor_path => CEEDLING_VENDOR
  },

:cexception => {
  :vendor_path => CEEDLING_VENDOR
  },

:plugins => {
  :load_paths => [],
  :enabled => CEEDLING_PLUGINS,
  }
}.freeze
DEFAULT_TESTS_RESULTS_REPORT_TEMPLATE =
%q{
% 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[:collection].each do |item|
<%=string[:source][:file]%>: "<%=item%>"
%     end
%   end

% end
% if (ignored > 0)
<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'IGNORED TEST SUMMARY')%>
%   hash[:results][:ignores].each do |ignore|
%     ignore[:collection].each do |item|
<%=ignore[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%>
% if (item[:message].length > 0)
: "<%=item[:message]%>"
% else
<%="\n"%>
% end
%     end
%   end

% end
% if (failed > 0)
<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'FAILED TEST SUMMARY')%>
%   hash[:results][:failures].each do |failure|
%     failure[:collection].each do |item|
<%=failure[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%>
% if (item[:message].length > 0)
: "<%=item[:message]%>"
% else
<%="\n"%>
% 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

}
VERBOSITY_OPTIONS =
{ 
  :silent    => Verbosity::SILENT,
  :errors    => Verbosity::ERRORS,
  :warnings  => Verbosity::COMPLAIN,
  :normal    => Verbosity::NORMAL,
  :obnoxious => Verbosity::OBNOXIOUS,
  :debug     => Verbosity::DEBUG,
}.freeze()
GIT_COMMIT_SHA_FILENAME =
'GIT_COMMIT_SHA'
NEWLINE_TOKEN =

Escaped newline literal (literally double-slash-n) for “encoding” multiline strings as single string

'\\n'
DEFAULT_PROJECT_FILENAME =
'project.yml'
DEFAULT_BUILD_LOGS_PATH =
'logs'
GENERATED_DIR_PATH =
[['vendor', 'ceedling'], 'src', "test", ['test', 'support'], 'build'].each{|p| File.join(*p)}
EXTENSION_WIN_EXE =
'.exe'
EXTENSION_NONWIN_EXE =
'.out'
EXTENSION_CORE_SOURCE =

Vendor frameworks, generated mocks, generated runners are always .c files

'.c'
PREPROCESS_SYM =
:preprocess
CEXCEPTION_SYM =
:cexception
CEXCEPTION_ROOT_PATH =
'c_exception'
CEXCEPTION_LIB_PATH =
"#{CEXCEPTION_ROOT_PATH}/lib"
CEXCEPTION_C_FILE =
'CException.c'
CEXCEPTION_H_FILE =
'CException.h'
UNITY_SYM =
:unity
UNITY_ROOT_PATH =
'unity'
UNITY_LIB_PATH =
"#{UNITY_ROOT_PATH}/src"
UNITY_C_FILE =
'unity.c'
UNITY_H_FILE =
'unity.h'
UNITY_INTERNALS_H_FILE =
'unity_internals.h'
RUNNER_BUILD_CMDLINE_ARGS_DEFINE =
'UNITY_USE_COMMAND_LINE_ARGS'
CMOCK_SYM =
:cmock
CMOCK_ROOT_PATH =
'cmock'
CMOCK_LIB_PATH =
"#{CMOCK_ROOT_PATH}/src"
CMOCK_C_FILE =
'cmock.c'
CMOCK_H_FILE =
'cmock.h'
DEFAULT_CEEDLING_LOGFILE =
'ceedling.log'
BACKTRACE_GDB_SCRIPT_FILE =
'backtrace.gdb'
INPUT_CONFIGURATION_CACHE_FILE =

input configuration file dump

'input.yml'
DEFINES_DEPENDENCY_CACHE_FILE =

preprocessor definitions for files

'defines_dependency.yml'
TEST_ROOT_NAME =
'test'
TEST_TASK_ROOT =
TEST_ROOT_NAME + ':'
TEST_SYM =
:test
RELEASE_ROOT_NAME =
'release'
RELEASE_TASK_ROOT =
RELEASE_ROOT_NAME + ':'
RELEASE_SYM =
RELEASE_ROOT_NAME.to_sym
UTILS_ROOT_NAME =
'utils'
UTILS_TASK_ROOT =
UTILS_ROOT_NAME + ':'
UTILS_SYM =
UTILS_ROOT_NAME.to_sym
OPERATION_PREPROCESS_SYM =
:preprocess
OPERATION_COMPILE_SYM =
:compile
OPERATION_ASSEMBLE_SYM =
:assemble
:link
PREPROCESS_FULL_EXPANSION_DIR =
'full_expansion'
PREPROCESS_DIRECTIVES_ONLY_DIR =
'directives_only'
NULL_FILE_PATH =
'/dev/null'
TESTS_BASE_PATH =
TEST_ROOT_NAME
RELEASE_BASE_PATH =
RELEASE_ROOT_NAME
VENDORS_FILES =
%w(unity UnityHelper cmock CException).freeze
UNITY_TEST_RESULTS_TEMPLATE =

Ruby Here

<<~UNITY_TEST_RESULTS
  %{output}

  -----------------------
  %{total} Tests %{failed} Failures %{ignored} Ignored
  %{result}
UNITY_TEST_RESULTS

Instance Method Summary collapse

Instance Method Details

#ceedling_form_filepath(destination_path, original_filepath, new_extension = nil) ⇒ Object

global utility methods (for plugins, project files, etc.)



15
16
17
18
19
# File 'lib/ceedling/file_path_utils.rb', line 15

def ceedling_form_filepath(destination_path, original_filepath, new_extension=nil)
  filename = File.basename(original_filepath)
  filename.replace(filename.ext(new_extension)) if (!new_extension.nil?)
  return File.join( destination_path.gsub(/\\/, '/'), filename )
end

#log_runtime(run, start_time_s, end_time_s, enabled) ⇒ Object

Operation duration logging



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/ceedling/rakefile.rb', line 23

def log_runtime(run, start_time_s, end_time_s, enabled)
  return if !enabled
  return if !defined?(PROJECT_VERBOSITY)
  return if (PROJECT_VERBOSITY < Verbosity::NORMAL)

  duration = Reportinator.generate_duration( start_time_s: start_time_s, end_time_s: end_time_s )

  return if duration.empty?

  @ceedling[:loginator].log() # Blank line
  @ceedling[:loginator].log( "Ceedling #{run} completed in #{duration}", Verbosity::NORMAL)
end

#test_failures_handlerObject



102
103
104
105
# File 'lib/ceedling/rakefile.rb', line 102

def test_failures_handler()
  # $stdout test reporting plugins store test failures
  exit(1) if @ceedling[:plugin_manager].plugins_failed? && !CEEDLING_APPCFG.tests_graceful_fail?
end