From a1397756723d15d4e46092ad1e9b591de2af6d6a Mon Sep 17 00:00:00 2001 From: Mark VanderVoord Date: Wed, 5 Apr 2017 11:38:57 -0400 Subject: [PATCH] Update CMock documentation --- docs/CMock_Summary.md | 410 ++++++++++++++++++++++++++++++------------ 1 file changed, 293 insertions(+), 117 deletions(-) diff --git a/docs/CMock_Summary.md b/docs/CMock_Summary.md index 58a9b0f..26d2f86 100644 --- a/docs/CMock_Summary.md +++ b/docs/CMock_Summary.md @@ -1,15 +1,14 @@ -[All code is copyright © 2007-2014 Cmock Project +[All code is copyright © 2007-2017 ThrowTheSwitch.org 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 +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: @@ -60,7 +59,23 @@ 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). +It uses Ruby to do all the main work (versions 2.0.0 and above). + + +Installing +========== + +The first thing you need to do to install CMock is to get yourself +a copy of Ruby. If you're on linux or osx, you probably already +have it. You can prove it by typing the following: + + ruby --version + + +If it replied in a way that implies ignorance, then you're going to +need to install it. You can go to ruby-lang.org to get the latest +version. You're also going to need to do that if it replied with a +version that is older than 2.0.0. Go ahead. We'll wait. Generated Mock Module Summary @@ -76,7 +91,11 @@ Expect: ------- Your basic staple Expects which will be used for most of your day -to day CMock work. +to day CMock work. By calling this, you are telling CMock that you +expect that function to be called during your test. It also specifies +which arguments you expect it to be called with, and what return +value you want returned when that happens. You can call this function +multiple times back to back in order to queue up multiple calls. * `void func(void)` => `void func_Expect(void)` * `void func(params)` => `void func_Expect(expected_params)` @@ -84,10 +103,30 @@ to day CMock work. * `retval func(params)` => `void func_ExpectAndReturn(expected_params, retval_to_return)` +ExpectAnyArgs: +-------------- + +This behaves just like the Expects calls, except that it doesn't really +care what the arguments are that the mock gets called with. It still counts +the number of times the mock is called and it still handles return values +if there are some. + +* `void func(void)` => `void func_ExpectAnyArgs(void)` +* `void func(params)` => `void func_ExpectAnyArgs(void)` +* `retval func(void)` => `void func_ExpectAnyArgsAndReturn(retval_to_return)` +* `retval func(params)` => `void func_ExpectAnyArgsAndReturn(retval_to_return)` + + Array: ------ -An ExpectWithArray will check as many elements as you specify. +An ExpectWithArray is another variant of Expect. Like expect, it cares about +the number of times a mock is called, the arguments it is called with, and the +values it is to return. This variant has another feature, though. For anything +that resembles a pointer or array, it breaks the argument into TWO arguments. +The first is the original pointer. The second specify the number of elements +it is to verify of that array. If you specify 1, it'll check one object. If 2, +it'll assume your pointer is pointing at the first of two elements in an array. If you specify zero elements, it will check just the pointer if `:smart` mode is configured or fail if `:compare_data` is set. @@ -97,14 +136,59 @@ If you specify zero elements, it will check just the pointer if * `retval func(other, ptr* param)` => `void func_ExpectWithArrayAndReturn(other, ptr* param, int param_depth, retval_to_return)` +Ignore: +------- + +Maybe you don't care about the number of times a particular function is called or +the actual arguments it is called with. In that case, you want to use Ignore. Ignore +only needs to be called once per test. It will then ignore any further calls to that +particular mock. The IgnoreAndReturn works similarly, except that it has the added +benefit of knowing what to return when that call happens. If the mock is called more +times than IgnoreAndReturn was called, it will keep returning the last value without +complaint. If it's called less times, it will also ignore that. You SAID you didn't +care how many times it was called, right? + +* `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)` + + +Ignore Args: +------------ + +Maybe you overall want to use Expect and its similar variations, but you don't care +what is passed to a particular argument. This is particularly useful when that argument +is a pointer to a value that is supposed to be filled in by the function. You don't want +to use ExpectAnyArgs, because you still care about the other arguments. Instead, before +any of your Expect calls are made, you can call this function. It tells CMock to ignore +a particular argument for the rest of this test, for this mock function. + +* `void func(params)` => `void func_IgnoreArg_paramName(void)` + + +ReturnThruPtr: +-------------- + +Another option which operates on a particular argument of a function is the ReturnThruPtr +plugin. For every argument that resembles a pointer or reference, CMock generates an +instance of this function. Just as the AndReturn functions support injecting one or more +return values into a queue, this function lets you specify one or more return values which +are queued up and copied into the space being pointed at each time the mock is called. + +* `void func(param1)` => `void func_ReturnThruPtr_paramName(val_to_return)` +* => `void func_ReturnArrayThruPtr_paramName(cal_to_return, len)` +* => `void func_ReturnMemThruPtr_paramName(val_to_return, size)` + + 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. +If all those other options don't work, and you really need to do something custom, you +still have a choice. 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)` @@ -119,10 +203,9 @@ 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. +Finally, 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 first. * `void func(void)` => `void func_ExpectAndThrow(value_to_throw)` * `void func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)` @@ -130,43 +213,6 @@ parameters. * `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)` - - -Ignore Args: ------------- - -This plugin adds the ability to specify specifc arguments to ignore -for a function, instead of ignoring all the arguments or the entire -function call, as the Ignore plugin supports. This will create a function -for each argument and each function. - -* `void func(params)` => `void func_IgnoreArg_paramName(void)` - - -ReturnThruPtr: --------------- - -This plugin adds a number of options for returning data through arguments -that are pointers. This is fled separately from the Expect/Ignore call, so -you will want to issue one of those calls each time as well. This will only -create an extra call for arguments that are pointers. It will create one per -pointer argument. - -* `void func(param1)` => `void func_ReturnThruPtr_paramName(val_to_return)` -* => `void func_ReturnArrayThruPtr_paramName(cal_to_return, len)` -* => `void func_ReturnMemThruPtr_paramName(val_to_return, size)` Running CMock ============= @@ -174,10 +220,11 @@ 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. +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). @@ -191,6 +238,7 @@ 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 ---------------------------- @@ -201,6 +249,7 @@ three ways. You may specify nothing, allowing it to run with default settings: + require 'cmock.rb' cmock = CMock.new You may specify a YAML file containing the configuration options @@ -212,7 +261,9 @@ 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. @@ -229,81 +280,136 @@ Defined in the yaml file, they look more like this: - __intrinsic :when_ptr: :compare +In all cases, you can just include the things that you want to override +from the defaults. We've tried to specify what the defaults are below. * `:attributes`: These are attributes that CMock should ignore for you for testing purposes. Custom compiler extensions and externs are handy things to - put here. + put here. If your compiler is choking on some extended syntax, this + is often a good place to look. + + * defaults: ['__ramfunc', '__irq', '__fiq', 'register', 'extern'] + +* `:c_calling_conventions`: + Similarly, CMock may need to understand which C calling conventions + might show up in your codebase. If it encounters something it doesn't + recognize, it's not going to mock it. We have the most common covered, + but there are many compilers out there, and therefore many other options. + + * defaults: ['__stdcall', '__cdecl', '__fastcall'] * `: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. + Tell `:callback` plugin to do the normal argument checking **before** it + calls the callback function by setting this to true. WHen false, the + callback function is called **instead** of the argument verification. + + * default: false * `: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. + + * default: true * `:cexception_include`: - Tell `:cexception` plugin where to find CException.h... only need to - define if it's not in your build path already. + Tell `:cexception` plugin where to find CException.h... You only need to + define this if it's not in your build path already... which it usually + will be for the purpose of your builds. + + * default: *nil* * `: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 + *also* want to make sure that all different functions are called in a particular order. If so, set this to true. + + * default: false * `: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. + + : default: :unity * `: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 + the includes get placed. You can define any or all of these options. + + * `:includes` + * `:includes_h_pre_orig_header` + * `:includes_h_post_orig_header` + * `:includes_c_pre_header` + * `:includes_c_post_header` + * default: nil #for all 5 options * `: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. + C developers create a lot of types, either through typedef or preprocessor + macros. CMock isn't going to automatically know what you were thinking all + the time (though it tries its best). If it comes across a type it doesn't + recognize, you have a choice on how you want it to handle it. It can either + perform a raw memory comparison and report any differences, or it can fail + with a meaningful message. Either way, this feature will only happen after + all other mechanisms have failed (The thing encountered isn't a standard + type. It isn't in the :treat_as list. It isn't in a custom unity_helper). + * default: true + * `:mock_path`: The directory where you would like the mock files generated to be placed. + + * default: mocks * `: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” + The prefix to prepend to your mock files. For example, if it's “Mock”, a file + “USART.h” will get a mock called “MockUSART.c”. This CAN be used with a suffix + at the same time. + + * default: Mock * `:mock_suffix`: - The suffix to append to your mock files. Defaults to “”. - -* `:weak`: - When set to some value, the generated mocks are defined as weak symbols using the configured format. Defaults to ''. - Set to '__attribute ((weak))' for weak mocks when using GCC. Set to any non-empty string for weak mocks when using IAR. - + The suffix to append to your mock files. For example, it it's "_Mock", a file + "USART.h" will get a mock called "USART_Mock.h". This CAN be used with a prefix + at the same time. + + * default: "" + * `:subdir`: - Relative subdir for your mocks. Set this to e.g. "sys" in order to - create mock for `sys/types.h` in `:mock_path`/sys/ + This is a relative subdirectory for your mocks. Set this to e.g. "sys" in + order to create a mock for `sys/types.h` in `(:mock_path)/sys/`. + + * default: "" * `:plugins`: - An array of which plugins to enable. 'expect' is always active. Also - available currently are `:ignore,` `:ignore_arg,` `:array,` - `:cexception,` `:callback,` and `:return_thru_ptr` + An array of which plugins to enable. ':expect' is always active. Also + available currently: + + * `:ignore` + * `:ignore_arg` + * `:expect_any_args` + * `:array` + * `:cexception` + * `:callback` + * `:return_thru_ptr` * `:strippables`: - An array containing a list of items to remove from the mocked header. - For example, use `:strippables: ['(?:functionName\s*\(+.*?\)+)']` - to prevent a function from being mocked. + An array containing a list of items to remove from the header + before deciding what should be mocked. This can be something simple + like a compiler extension CMock wouldn't recognize, or could be a + regex to reject certain function name patterns. For example, use + `:strippables: ['(?:functionName\s*\(+.*?\)+)']` + to prevent a function `functionName` from being mocked. By default, it + is ignoring all gcc attribute extensions. + + * default: ['(?:__attribute__\s*\(+.*?\)+)'] * `:treat_as`: The `:treat_as` list is a shortcut for when you have created typedefs @@ -313,36 +419,106 @@ Defined in the yaml file, they look more like this: 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*' + + * NOTE: unlike the other options, your specifications MERGE with the + default list. Therefore, if you want to override something, you must + reassign it to something else (or to *nil* if you don't want it) + + * default: { + 'int' => 'INT', + 'char' => 'INT8', + 'short' => 'INT16', + 'long' => 'INT', + 'int8' => 'INT8', + 'int16' => 'INT16', + 'int32' => 'INT', + 'int8_t' => 'INT8', + 'int16_t' => 'INT16', + 'int32_t' => 'INT', + 'INT8_T' => 'INT8', + 'INT16_T' => 'INT16', + 'INT32_T' => 'INT', + 'bool' => 'INT', + 'bool_t' => 'INT', + 'BOOL' => 'INT', + 'BOOL_T' => 'INT', + 'unsigned int' => 'HEX32', + 'unsigned long' => 'HEX32', + 'uint32' => 'HEX32', + 'uint32_t' => 'HEX32', + 'UINT32' => 'HEX32', + 'UINT32_T' => 'HEX32', + 'void*' => 'HEX8_ARRAY', + 'unsigned short' => 'HEX16', + 'uint16' => 'HEX16', + 'uint16_t' => 'HEX16', + 'UINT16' => 'HEX16', + 'UINT16_T' => 'HEX16', + 'unsigned char' => 'HEX8', + 'uint8' => 'HEX8', + 'uint8_t' => 'HEX8', + 'UINT8' => 'HEX8', + 'UINT8_T' => 'HEX8', + 'char*' => 'STRING', + 'pCHAR' => 'STRING', + 'cstring' => 'STRING', + 'CSTRING' => 'STRING', + 'float' => 'FLOAT', + 'double' => 'FLOAT' + } * `: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. + + * default: [] * `:treat_externs`: - Set to `:include` to mock externed functions or `:exclude` to ignore - them (the default). + This specifies how you want CMock to handle functions that have been + marked as extern in the header file. Should it mock them? + + * `:include` will mock externed functions + * `:exclude` will ignore externed functions (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 + `UNITY_TEST_ASSERT_EQUAL_YourType`. If it finds macros of the right + shape that match that pattern, it'll use them. + + * default: [] * `:verbosity`: - 0 for errors only. 1 for errors and warnings. 2 for normal. 3 for - verbose + How loud shoudl CMock be? + + * 0 for errors only + * 1 for errors and warnings + * 2 for normal (default) + * 3 for verbose + +* `:weak`: + When set this to some value, the generated mocks are defined as weak + symbols using the configured format. This allows them to be overridden + in particular tests. + + * Set to '__attribute ((weak))' for weak mocks when using GCC. + * Set to any non-empty string for weak mocks when using IAR. + * default: "" * `: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 + set this to `:warn,` `:ignore,` or `:error` + + * default: :warn * `:when_ptr`: You can customize how CMock deals with pointers (c strings result in - string comparisons... we're talking about other pointers here). Your + 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 @@ -350,42 +526,42 @@ Defined in the yaml file, they look more like this: 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). + + * default: :smart Compiled Options: ----------------- A number of #defines also exist for customizing the cmock experience. +Feel free to pass these into your compiler or whatever is most +convenient. CMock will otherwise do its best to guess what you want +based on other settings, particularly Unity's settings. -CMOCK_MEM_STATIC or CMOCK_MEM_DYNAMIC +* `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. -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_SIZE +* `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. -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_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_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. +* `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.