##------------------------------------------------------------------------------
#   MockC:    a framework to implement mocking when unit-testing
#
#   Copyright (C) 2011  programming <at> kogro org
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
##------------------------------------------------------------------------------



  I N T R O D U C T I O N
  -----------------------
  Testing is verifying that your 'module under test', when triggered, interacts
  with its environment and delivers the result as expected.
  In this sentence, the three major parts in testing are mentioned:
  1) The trigger-part
     This is the part that calls the 'module under test' with defined
     parameters, so that the 'module under test' is submitted to a defined
     scenario.
  2) The 'module under test'
     This is the part that is being tested. It is called, interacts with its
     environment, and delivers a result. The interaction and the result is
     verified to be as expected.
  3) The 'environment' of the 'module under test'
     This is where this framework comes in. This mock-framework simulates the
     normal environment for the 'module under test', whereby it during the test
     verifies that it (the environment) is triggered as expected.

  The cooperation between these 3 items can be depicted as shown below:

        +-------+                                  +------+
        | CUnit |           expectations           | Mock |
        |       |  ----------------------------->  |      |
        |       |                                  |      |
        |       |            +--------+            |      |
        |       |  trigger   | Module |    mock    |      |
        |       |  ------->  | Under  |  <-------  |      |
        |       |            | Test   |            |      |
        |       |            |        |            |      |
        |       |            +--------+            |      |
        |       |                                  |      |
        |       |              verify              |      |
        |       |  <-----------------------------  |      |
        |       |                                  |      |
        +-------+                                  +------+

  S C O P E
  ---------
  This mocking framework is written to cooperate with CUnit.

  The 'module under test' is (a couple of) C-functions which, when in their
  normal program, call other C-functions. When the 'module under test' is
  isolated from their normal program and placed under CUnit, the Mock-functions
  take the place of the environment C-functions.

  P R I N C I P L E   O F   O P E R A T I O N
  -------------------------------------------
  In the beginning, the testsuite of CUnit announces the expectations for the
  Mock. CUnit tells the Mock, which parameters to expect and which return value
  to deliver.
  Next the testsuite of CUnit triggers the 'module under test', which interacts
  with its environment (and calls the Mock). The Mock notes the call and
  delivers the return value as announced during the expect.
  At the end of the testsuite the Mock reports whether all invocations were as
  expected.

  From the 'module under test' point of view, the Mock is a C function with a
  known signature (a certain number and type of parameters and a return type).

  From the CUnit point of view, the Mock has a double interface. First it is
  a C function where CUnit can set the expectations and tell the Mock that a
  new test is started. Secondly the Mock is a C function where CUnit can ask
  whether the invocation was successful.

  When the module under test in its environment needs a
  'int Func( char, float )' function, the Mock framework implements a:
    int  Func( char, float )    // the actual mocked function
    void Func_reset( void )     // to tell the Mock to restart for a new test
    void Func_expect(           // to tell the Mock the expectations
      int,                         // expected return value
      (int *)( char, char ),       // comparison function for 1st parameter
      char,                        // expected value for 1st parameter
      (int *)( float, float ),     // comparison function for 2nd parameter
      float )                      // expected value for 2nd parameter
    int  Func_verify( void )    // to ask the Mock for the result

  Internally, the Mock stores all expectations in an array and keeps a counter
  (counting the number of invocations) up to date. When called, the Mock uses
  the counter as an index in the array to find the expectation for this call.
  It uses then the comparison functions to check if the invocation was as
  expected and stores the result in the array and returns the return value to
  the module under test. When asked to verify, the Mock returns the summary of
  all 'CalledOk' results in the array.

  I M P L E M E N T A T I O N
  ---------------------------
  The implementation is driven by a number of constraints:
  - no limitations on the 'module under test' or 'environment to mock'
  - creating a testsuite using Mock must be as easy as possible
  - creating a new Mock must be as easy as possible

  According the first constraint, the Mock framework must be capable to mock
  any signature of environment function. This signature is only known at
  compile-time, not at design-time. To solve this, the Mock framework heavily
  relies on the preprocessor to create the necessary functions.

  There is a Mock file per number of parameters in the function. This Mock
  header file defines a number of macro's for the test-builder:
    MOCK_2                   // define the declaration for an environment
                             //   function with return type and 2 parameters
    MOCK_VOID_2              // define the declaration for an environment
                             //   function with void return and 2 parameters
    MOCKIMPL_2               // define the implementation for an environment
                             //   function with return type and 2 parameters
    MOCKIMPL_VOID_2          // define the implementation for an environment
                             //   function with void return and 2 parameters

  To extend the Mock framework for environment functions with another number of
  parameters in their prototype, this mock2.h can be copied and the
  implementation of the macro's changed so, that they are suitable for another
  number of parameters.

  The implementation of these macro's is based on more general mock macro's.
  These macro's are implemented in mock.h (this file). Unless the functionality
  of the Mock framework is changed, this file needs no maintenance.

  Graphically the design of the mock framework looks like:


                                          +-------+
              mock                        | Mock  |
              base                        +-------+
                                              ^
                                              |
                                  +-----------+----------+
                                  |           |          |
                              +--------+  +-------+  +--------+
              mock            | Mock0  |  | Mock1 |  | Mock2  |
              framework       +--------+  +-------+  +--------+
                                ^             ^        ^    ^
                                |             |        |    |
                                +----------------------+    |
                                |             |             |
                                |             +-------------+
                                |                           |
                              +--------+  +-------+  +--------+
              mock            | Unit 1 |  | Unit2 |  | Unit 3 |
              objects         | Mock   |  | Mock  |  | Mock   |
                              +--------+  +-------+  +--------+
                                  ^          ^           ^
  +--------+                      |          |           |
  | Module |                      |          |           |
  | Under  | ---------------------+----------+-----------+
  | Test   |
  +--------+

  The 'mock objects' are the instantiations of the environment functions. These
  files are owned by the test-builder, who 'creates' the functions to be
  mocked.

  The 'mock framework' are the macros that create mock functions with a defined
  number of parameters, with and without return type. These files are owned
  by the mock-builder, who creates a new file when a 'module under test' needs
  more parameters in a function signature.

  The 'mock base' are the base macros for the mock-framework. These macro's
  define the functionality of the framework. The mock-builder maintains this
  file when the functionality needs to be changed.

