diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..253b985 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +test/system/build +test/system/generated \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 04a7aa6..33e8370 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "vendor/unity"] path = vendor/unity - url = git@github.com:ThrowTheSwitch/Unity.git + url = git://github.com/ThrowTheSwitch/Unity.git [submodule "vendor/c_exception"] path = vendor/c_exception url = git://github.com/ThrowTheSwitch/CException.git diff --git a/docs/CMock_Summary.md b/docs/CMock_Summary.md new file mode 100644 index 0000000..c352693 --- /dev/null +++ b/docs/CMock_Summary.md @@ -0,0 +1,356 @@ +[All code is copyright © 2007-2010 Cmock Project +by Mike Karlesky, Mark VanderVoord, and Greg Williams. + +This Documentation Is Released Under a Creative Commons 3.0 +Attribution Share-Alike License] + + +What the What? +============== + +CMock is a nice little tool which takes your header files and creates +a Mock interface for it so that you can more easily Unit test modules +that touch other modules. For each function prototype in your +header, like this one: + + int DoesSomething(int a, int b); + + +...you get an automatically generated DoesSomething function +that you can link to instead of your real DoesSomething function. +By using this Mocked version, you can then verify that it receives +the data you want, and make it return whatever data you desire, +make it throw errors when you want, and more... Create these for +everything your latest real module touches, and you're suddenly +in a position of power: You can control and verify every detail +of your latest creation. + +To make that easier, CMock also gives you a bunch of functions +like the ones below, so you can tell that generated DoesSomething +function how to behave for each test: + + void DoesSomething_ExpectAndReturn(int a, int b, int toReturn); + void DoesSomething_ExpectAndThrow(int a, int b, EXCEPTION_T error); + void DoesSomething_StubWithCallback(CMOCK_DoesSomething_CALLBACK YourCallback); + void DoesSomething_IgnoreAndReturn(int toReturn); + + +You can pile a bunch of these back to back, and it remembers what +you wanted to pass when, like so: + + test_CallsDoesSomething_ShouldDoJustThat(void) + { + DoesSomething_ExpectAndReturn(1,2,3); + DoesSomething_ExpectAndReturn(4,5,6); + DoesSomething_ExpectAndThrow(7,8, STATUS_ERROR_OOPS); + + CallsDoesSomething( ); + } + + +This test will call CallsDoesSomething, which is the function +we are testing. We are expecting that function to call DoesSomething +three times. The first time, we check to make sure it's called +as DoesSomething(1, 2) and we'll magically return a 3. The second +time we check for DoesSomething(4, 5) and we'll return a 6. The +third time we verify DoesSomething(7, 8) and we'll throw an error +instead of returning anything. If CallsDoesSomething gets +any of this wrong, it fails the test. It will fail if you didn't +call DoesSomething enough, or too much, or with the wrong arguments, +or in the wrong order. + +CMock is based on Unity, which it uses for all internal testing. +It uses Ruby to do all the main work (versions 1.8.6 through 1.9.2). + + +Generated Mock Module Summary +============================= + +In addition to the mocks themselves, CMock will generate the +following functions for use in your tests. The expect functions +are always generated. The other functions are only generated +if those plugins are enabled: + + +Expect: +------- + +Your basic staple Expects which will be used for most of your day +to day CMock work. + +* `void func(void)` => `void func_Expect(void)` +* `void func(params)` => `void func_Expect(expected_params)` +* `retval func(void)` => `void func_ExpectAndReturn(retval_to_return)` +* `retval func(params)` => `void func_ExpectAndReturn(expected_params, retval_to_return)` + + +Array: +------ + +An ExpectWithArray will check as many elements as you specify. +If you specify zero elements, it will check just the pointer if +`:smart` mode is configured or fail if `:compare_data` is set. + +* `void func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers) +* `void func(ptr * param, other)` => `void func_ExpectWithArray(ptr* param, int param_depth, other)` +* `retval func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers) +* `retval func(other, ptr* param)` => `void func_ExpectWithArrayAndReturn(other, ptr* param, int param_depth, retval_to_return)` + + +Callback: +--------- + +As soon as you stub a callback in a test, it will call the callback +whenever the mock is encountered and return the retval returned +from the callback (if any) instead of performing the usual expect +checks. It can be configured to check the arguments first (like +expects) or just jump directly to the callback. + +* `void func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` +where `CMOCK_func_CALLBACK` looks like: `void func(int NumCalls)` +* `void func(params)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` +where `CMOCK_func_CALLBACK` looks like: `void func(params, int NumCalls)` +* `retval func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` +where `CMOCK_func_CALLBACK` looks like: `retval func(int NumCalls)` +* `retval func(params)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` +where `CMOCK_func_CALLBACK` looks like: `retval func(params, int NumCalls)` + + +Cexception: +----------- + +If you are using Cexception for error handling, you can use this +to throw errors from inside mocks. Like Expects, it remembers +which call was supposed to throw the error, and it still checks +parameters. + +* `void func(void)` => `void func_ExpectAndThrow(value_to_throw)` +* `void func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)` +* `retval func(void)` => `void func_ExpectAndThrow(value_to_throw)` +* `retval func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)` + + +Ignore: +------- + +This plugin supports two modes. You can use it to force CMock to +ignore calls to specific functions or to just ignore the arguments +passed to those functions. Either way you can specify multiple +returns or a single value to always return, whichever you prefer. + +* `void func(void)` => `void func_Ignore(void)` +* `void func(params)` => `void func_Ignore(void)` +* `retval func(void)` => `void func_IgnoreAndReturn(retval_to_return)` +* `retval func(params)` => `void func_IgnoreAndReturn(retval_to_return)` + + +Running CMock +============= + +CMock is a Ruby script and class. You can therefore use it directly +from the command line, or include it in your own scripts or rakefiles. + +Mocking from the Command Line +----------------------------- + +After unpacking CMock, you will find CMock.rb in the 'lib' directory. +This is the file that you want to run. It takes a list of header files +to be mocked, as well as an optional yaml file for a more detailed +configuration (see config options below). + +For example, this will create three mocks using the configuration +specified in MyConfig.yml: + + ruby cmock.rb -oMyConfig.yml super.h duper.h awesome.h + +And this will create two mocks using the default configuration: + + ruby cmock.rb ../mocking/stuff/is/fun.h ../try/it/yourself.h + +Mocking From Scripts or Rake +---------------------------- + +CMock can be used directly from your own scripts or from a rakefile. +Start by including cmock.rb, then create an instance of CMock. +When you create your instance, you may initialize it in one of +three ways. + +You may specify nothing, allowing it to run with default settings: + + cmock = CMock.new + +You may specify a YAML file containing the configuration options +you desire: + + cmock = CMock.new('../MyConfig.yml') + +You may specify the options explicitly: + + cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/') + +Config Options: + +The following configuration options can be specified in the +yaml file or directly when instantiating. + +Passed as Ruby, they look like this: + + { :attributes => [“__funky”, “__intrinsic”], :when_ptr => :compare } + +Defined in the yaml file, they look more like this: + + :cmock: + :attributes: + - __funky + - __intrinsic + :when_ptr: :compare + + +* `:attributes`: + These are attributes that CMock should ignore for you for testing + purposes. Custom compiler extensions and externs are handy things to + put here. + +* `:callback_after_arg_check`: + Tell `:callback` plugin to do the normal argument checking before it + calls the callback function. This defaults to false, where the + callback function is called instead of the argument verification. + +* `:callback_include_count`: + Tell `:callback` plugin to include an extra parameter to specify the + number of times the callback has been called. If set to false, the + callback has the same interface as the mocked function. This can be + handy when you're wanting to use callback as a stub. + +* `:cexception_include`: + Tell `:cexception` plugin where to find CException.h... only need to + define if it's not in your build path already. + +* `:enforce_strict_ordering`: + CMock always enforces the order that you call a particular function, + so if you expect GrabNabber(int size) to be called three times, it + will verify that the sizes are in the order you specified. You might + also want to make sure that all different functions are called in a + particular order. If so, set this to true. + +* `:framework`: + Currently the only option is `:unity.` Eventually if we support other + unity test frameworks (or if you write one for us), they'll get added + here. + +* `:ignore`: + Tell `:ignore` plugin to ignore `:args_only` or `:args_and_calls` + (default) where it doesn't even care how many times the mock was + called + +* `:includes`: + An array of additional include files which should be added to the + mocks. Useful for global types and definitions used in your project. + There are more specific versions if you care WHERE in the mock files + the includes get placed. You can define any or all of + `:includes_h_pre_orig_header,` `:includes_h_post_orig_header, ` + `:includes_c_pre_header,` `:includes_c_post_header + +* `:memcmp_if_unknown`: + This is true by default. When true, CMock will just do a memory + comparison of types that it doesn't recognize (not standard types, not + in `:treat_as,` and not in a unity helper). If you instead want it to + throw an error, just set this to false. + +* `:mock_path`: + The directory where you would like the mock files generated to be + placed. + +* `:mock_prefix`: + The prefix to append to your mock files. Defaults to “Mock”, so a file + “USART.h” will get a mock called “MockUSART.c” + +* `:plugins`: + An array of which plugins to enable. 'expect' is always active. Also + available currently are `:ignore,` `:array,` `:cexception,` and + `:callback: + +* `:treat_as`: + The `:treat_as` list is a shortcut for when you have created typedefs + of standard types. Why create a custom unity helper for UINT16 when + the unity function TEST_ASSERT_EQUAL_HEX16 will work just perfectly? + Just add 'UINT16' => 'HEX16' to your list (actually, don't. We already + did that one for you). Maybe you have a type that is a pointer to an + array of unsigned characters? No problem, just add 'UINT8_T*' => + 'HEX8*' + +* `:treat_as_void`: + We've seen "fun" legacy systems typedef 'void' with a custom type, + like MY_VOID. Add any instances of those to this list to help CMock + understand how to deal with your code. + +* `:treat_externs`: + Set to `:include` to mock externed functions or `:exclude` to ignore + them (the default). + +* `:unity_helper_path`: + If you have created a header with your own extensions to unity to + handle your own types, you can set this argument to that path. CMock + will then automagically pull in your helpers and use them. The only + trick is that you make sure you follow the naming convention: + UNITY_TEST_ASSERT_EQUAL_YourType + +* `:verbosity`: + 0 for errors only. 1 for errors and warnings. 2 for normal. 3 for + verbose + +* `:when_no_prototypes`: + When you give CMock a header file and ask it to create a mock out of + it, it usually contains function prototypes (otherwise what was the + point?). You can control what happens when this isn't true. You can + set this to `:warn,` `:ignore,` or `:error + +* `:when_ptr`: + You can customize how CMock deals with pointers (c strings result in + string comparisons... we're talking about other pointers here). Your + options are `:compare_ptr` to just verify the pointers are the same, + `:compare_data` or `:smart` to verify that the data is the same. + `:compare_data` and `:smart` behaviors will change slightly based on + if you have the array plugin enabled. By default, they compare a + single element of what is being pointed to. So if you have a pointer + to a struct called ORGAN_T, it will compare one ORGAN_T (whatever that + is). + + +Compiled Options: +----------------- + +A number of #defines also exist for customizing the cmock experience. + +CMOCK_MEM_STATIC or CMOCK_MEM_DYNAMIC + +Define one of these to determine if you want to dynamically add +memory during tests as required from the heap. If static, you +can control the total footprint of Cmock. If dynamic, you will +need to make sure you make some heap space available for Cmock. + +CMOCK_MEM_SIZE + +In static mode this is the total amount of memory you are allocating +to Cmock. In Dynamic mode this is the size of each chunk allocated +at once (larger numbers grab more memory but require less mallocs). + +CMOCK_MEM_ALIGN + +The way to align your data to. Not everything is as flexible as +a PC, as most embedded designers know. This defaults to 2, meaning +align to the closest 2^2 -> 4 bytes (32 bits). You can turn off alignment +by setting 0, force alignment to the closest uint16 with 1 or even +to the closest uint64 with 3. + +CMOCK_MEM_PTR_AS_INT + +This is used internally to hold pointers... it needs to be big +enough. On most processors a pointer is the same as an unsigned +long... but maybe that's not true for yours? + +CMOCK_MEM_INDEX_TYPE + +This needs to be something big enough to point anywhere in Cmock's +memory space... usually it's an unsigned int. + diff --git a/rakefile.rb b/rakefile.rb index 79d00c4..c53e844 100644 --- a/rakefile.rb +++ b/rakefile.rb @@ -1,4 +1,4 @@ -# ========================================== + # ========================================== # CMock Project - Automatic Mock Generation for C # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams # [Released under MIT License. Please refer to license.txt for details] @@ -10,9 +10,26 @@ require 'rake/clean' require 'rake/testtask' require './rakefile_helper' +require 'rspec/core/rake_task' + include RakefileHelpers DEFAULT_CONFIG_FILE = 'gcc.yml' +CMOCK_ROOT = File.expand_path(File.dirname(__FILE__)) + +SYSTEM_TEST_SUPPORT_DIRS = [ + File.join(CMOCK_ROOT, 'test/system/generated'), + File.join(CMOCK_ROOT, 'test/system/build') +] + +SYSTEM_TEST_SUPPORT_DIRS.each do |dir| + p dir + directory(dir) + CLOBBER.include(dir) +end + + +task :prep_system_tests => SYSTEM_TEST_SUPPORT_DIRS configure_clean configure_toolchain(DEFAULT_CONFIG_FILE) @@ -29,7 +46,7 @@ end namespace :test do desc "Run all unit and system tests" - task :all => [:clobber, 'test:units', 'test:c', 'test:system'] + task :all => [:clobber, :prep_system_tests, 'test:units', 'test:c', 'test:system'] desc "Run Unit Tests" Rake::TestTask.new('units') do |t| @@ -46,12 +63,12 @@ namespace :test do end desc "Run C Unit Tests" - task :c do + task :c => [:prep_system_tests] do build_and_test_c_files end desc "Run System Tests" - task :system => [:clobber] do + task :system => [:clobber, :prep_system_tests] do #get a list of all system tests, removing unsupported tests for this compiler sys_unsupported = $cfg['unsupported'].map {|a| 'test/system/test_interactions/'+a+'.yml'} sys_tests_to_run = FileList['test/system/test_interactions/*.yml'] - sys_unsupported @@ -78,7 +95,7 @@ namespace :test do end desc "Profile Mock Generation" - task :profile => [:clobber] do + task :profile => [:clobber, :prep_system_tests] do run_system_test_profiles(FileList[SYSTEST_COMPILE_MOCKABLES_PATH + '*.h']) end end @@ -86,4 +103,9 @@ end task :no_color do $colour_output = false end + +RSpec::Core::RakeTask.new(:spec) do |t| + spec_path = File.join(CMOCK_ROOT, 'test/spec') + t.pattern = spec_path + '/*_spec.rb' +end \ No newline at end of file diff --git a/targets/gcc.yml b/targets/gcc.yml index ebc106b..8a625b2 100644 --- a/targets/gcc.yml +++ b/targets/gcc.yml @@ -46,6 +46,8 @@ linker: extension: '.exe' destination: *systest_build_path -unsupported: [] +unsupported: + - unity_64bit_support + - callingconv colour: true diff --git a/test/spec/cmock_file_writer_spec.rb b/test/spec/cmock_file_writer_spec.rb new file mode 100644 index 0000000..241a2c7 --- /dev/null +++ b/test/spec/cmock_file_writer_spec.rb @@ -0,0 +1,25 @@ +here = File.expand_path(File.dirname(__FILE__)) +require "#{here}/spec_helper" #add this to execute tests from the spec directory +require 'cmock_file_writer' + +describe CMockFileWriter do + before do + @cmConfig = Object.new + #create instance of class under test + @subject = CMockFileWriter.new(@cmConfig) + end + + describe 'initialize' do + it "have set up internal accessors correctly on init" do + result = @subject.config + result.should == @cmConfig + end + end + + describe 'create_file' do + it "complain if a block was not specified when calling create" do + expect {@subject.create_file("text.txt")}.should raise_error + # should.be_false + end + end +end diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb new file mode 100644 index 0000000..3899b5c --- /dev/null +++ b/test/spec/spec_helper.rb @@ -0,0 +1,12 @@ +require 'rubygems' + +proj_root = File.expand_path(File.dirname(__FILE__) + '/../..') +# require proj_root + '/config/environment' +$LOAD_PATH << proj_root + '/lib' + +require 'rspec' +require 'rr' + +RSpec.configure do |config| + config.mock_with :rr +end \ No newline at end of file diff --git a/vendor/unity b/vendor/unity index d0d5ec5..b7d9d00 160000 --- a/vendor/unity +++ b/vendor/unity @@ -1 +1 @@ -Subproject commit d0d5ec5d7569defaafd6c1bdb728d4c33783b69a +Subproject commit b7d9d007ce8265b8f0fdffae412e276bc377e331