CUnit for Mr.Ando.

Japanese -->

# How to(More...)

The following typical test cases are introduced in this chapter.

- Sequence
- Selection
- Foreach

If these are used, a still more advanced test can be performed.

## Sequence

This is the easiest test case. It tests in the following codes. This is the function which does sums. A result is returned to ans. However, this function is foolish. If 100 is exceeded,An error will be returned.

    #include "plus.h"

    /** Sums are done. A result is returned to ans.
     * However, he is stupid.
     * The numerical value to which he exceeds 100
     * writes except zero to a return value.
     * @param data1 imput paramater 1
     * @param data2 imput paramater 2
     * @param ans return paramater
     * @return 0:normal, Other 0:abnormal
     */
    unsigned int plus(
        unsigned int data1,
        unsigned int data2,
        unsigned int *ans) {
        unsigned int max = 100;
        *ans = data1 + data2;
        if ((max <= data1) || (max <= data2) || (max <= *ans)) {
            return 1;
        }
        return 0;
    }

A header file is made in this code. A fool does not write a header file. A sage writes a header file. If you do not write a header file, it will have very bad influence on quality.

    #ifndef _PLUS_H_
    #define _PLUS_H_

    unsigned int plus(
        unsigned int data1,
        unsigned int data2,
        unsigned int *ans);

    #endif

Please put the following description into a header file. This is used for double include prevention. This is common sense.

    #ifndef _PLUS_H_
    #define _PLUS_H_

      /* text */

    #endif

Please describe the following, when you use C++.

    #ifdef __cplusplus
    extern "C" {
    #endif

      /* text */

    #ifdef __cplusplus
    }
    #endif

The following is a test code.
As for the function name to test, "test + function name" is recommended.
As for the file name to test, "file name + Test" is recommended.
It is recommended that the file to test and a test file separate a folder.
Supposing you think that a test is inadequate, a test will be written more.

    #include <stdio.h>
    #include <testRunner.h>
    #include "plus.h"

    static unsigned int testPlus(void);

    /** Main function. */
    int main(void) {
        return (int) testRunner(testPlus);
    }

    static unsigned int testPlus(void) {
        unsigned int err;
        unsigned int ans;
        unsigned int data1;
        unsigned int data2;

        data1 = 1;
        data2 = 1;
        err = plus(data1,data2,&ans); // do Test
        TEST_ASSERT_EQUALS((data1 + data2),(int)ans);
        TEST_ASSERT_EQUALS(err,0);

        data1 = 100;
        data2 = 1;
        err = plus(data1,data2,&ans); // do Test
        TEST_ASSERT(err != 0);

        data1 = 0;
        data2 = 0xffffffffu; // -1
        err = plus(data1,data2,&ans); // do Test
        TEST_ASSERT(err != 0);

        data1 = 1;
        data2 = 99;
        err = plus(data1,data2,&ans); // do Test
        TEST_ASSERT(err != 0);

        return 0;
    }

If the above is seen, "The test of main() is not made." will understand in CUnit for Mr.Ando.
If possible,separation of the test enviroment. Mixture is not cool!
Figure : Separation of test folder.
The following name space is used in CUnit for Mr.Ando.

TEST_ASSERT
Name | Description
TEST_ASSERT(_a) | A test is failure when _a is 0.
TEST_ASSERT_EQUALS(_a,_b) | A test is success when _a == _b.
TEST_ASSERT_NOT_EQUALS(_a,_b) | A test is success when _a != _b.

The test result is as follows.

    $ make run
    gcc  -ggdb -Wall -I../../CUnitForAndo/include -I../real/include -I./include -c ../real/src/plus.c
    gcc  -ggdb -Wall -I../../CUnitForAndo/include -I../real/include -I./include -c ./src/plusTest.c
    gcc  -ggdb -Wall -I../../CUnitForAndo/include -I../real/include -I./include -c ../../CUnitForAndo/src/testRunner.c
    gcc  -ggdb -Wall  -ggdb -Wall -I../../CUnitForAndo/include -I../real/include -I./include -o ./runExe.exe plus.o plusTest.o testRunner.o
    ./runExe.exe
    OK (5 tests)

Next, in the following case, it tests using a Mock function. Only caller function can be tested by using Mock function.

    #include "plus.h"
    #include "sequence.h"

    unsigned int sequence(
        unsigned int data1,
        unsigned int data2,
        unsigned int *ans) {
        unsigned int err;

        err = plus(data1,data2,ans);

        return err;
    }

Next, in the following case, it tests using a Mock function. plus() is set to Mock function in sequence(). Variable inPlus_data1 and inPlus_data2 are prepared for input data. Variable outPlus_ans and returnPlus are prepared for output data.

    #include
    #include
    #include "plus.h"
    #include "sequence.h"

    static unsigned int testSequence(void);

    /* test data */
    static unsigned int inPlus_data1;
    static unsigned int inPlus_data2;
    static unsigned int outPlus_ans;
    static unsigned int returnPlus;

    /** Main function. */
    int main(void) {
        return (int) testRunner(testSequence);
    }

    static unsigned int testSequence(void) {
        unsigned int err;
        unsigned int ans;
        unsigned int data1;
        unsigned int data2;

        /////////////////////////////////////////////////
        // Normal test
        data1 = 0; // 0-0xffffffffu
        data2 = 0xffffffffu; // 0-0xffffffffu
        inPlus_data1 = 0xffffffffu; // pollute
        inPlus_data2 = 0xffffffffu; // pollute
        outPlus_ans = 99; // 0-99
        returnPlus = 0; // 0(Normal),1-0xffffffffu(Abnormal)

        err = sequence(data1,data2,&ans); // run!

        TEST_ASSERT_EQUALS(err,(int)returnPlus);
        TEST_ASSERT_EQUALS(data1,(int)inPlus_data1);
        TEST_ASSERT_EQUALS(data2,(int)inPlus_data2);
        TEST_ASSERT_EQUALS(ans,(int)outPlus_ans);

        /////////////////////////////////////////////////
        // Abnormal test
        data1 = 0; // 0-0xffffffffu
        data2 = 0xffffffffu; // 0-0xffffffffu
        inPlus_data1 = 0xffffffffu; // pollute
        inPlus_data2 = 0xffffffffu; // pollute
        outPlus_ans = 1; // 0-99
        returnPlus = 1; // 0(Normal),1-0xffffffffu(Abnormal)

        err = sequence(data1,data2,&ans); // run!

        TEST_ASSERT_EQUALS(err,(int)returnPlus);
        TEST_ASSERT_EQUALS(data1,(int)inPlus_data1);
        TEST_ASSERT_EQUALS(data2,(int)inPlus_data2);

        return 0;
    }

    /** driver */
    unsigned int plus(
        unsigned int data1,
        unsigned int data2,
        unsigned int *ans) {
        inPlus_data1 = data1;
        inPlus_data2 = data2;
        *ans = outPlus_ans;
        return returnPlus;
    }

plus.c cannot be compiled together. Please prepare another environment. This is restrictions not to make overwrite like Java in the C language.
Figure : Separation of test environment.

### selection

It is the test of if() or switch(). This is a file for a test.

    #include "select.h"

    /** @see select.h */
    unsigned int hardAccsess(
        unsigned int address,
        unsigned int data,
        HARD_TYPE_t select) {
        unsigned int err = 0;
        switch (select) {
        case HARD_TYPE_A:
            err = setDataA(address,data);
            break;
        case HARD_TYPE_B:
        default:
            if ((data & 0xffff0000u) != 0) {
                err = 1;
            } else {
                writeAccessB(address,(unsigned short)data);
            }
            break;
        }
        return err;
    }

This is test file.

    #include <stdio.h>
    #include <testRunner.h>
    #include "select.h"

    /* A test is divided. */
    static unsigned int testAll(void);
    static unsigned int testHardA(void);
    static unsigned int testHardB(void);

    /* A domain is secured. */
    static unsigned int inSetDataA_address;
    static unsigned int inSetDataA_data;
    static unsigned int returnSetDataA;
    static unsigned int inWriteAccessB_address;
    static unsigned short inWriteAccessB_data;

    int main(int argc,char **argv) {
        return (int) testRunner(testAll);
    }

    static unsigned int testAll(void) {
        TEST_ASSERT(! testHardA());
        TEST_ASSERT(! testHardB());
        return 0;
    }

    static unsigned int testHardA(void) {
        unsigned int err;
        unsigned int address;
        unsigned int data;
        HARD_TYPE_t select;

        /////////////////////////////////////////////////
        // setDataA normal
        address = 0x85000038u; // 0x0-ffffffffu
        data = 456; // 0x0-ffffffffu
        select = HARD_TYPE_A; // HARD_TYPE_A,HARD_TYPE_B
        inSetDataA_address = 0xffffffffu;// imput(dirty)
        inSetDataA_data = 0xffffffffu;// imput(dirty)
        returnSetDataA = 0; // 0:normal,1-0xffffffffu:abnormal
        inWriteAccessB_address = 0xffffffffu; // imput(dirty)
        inWriteAccessB_data = 0xffffu; // imput(dirty)

        err = hardAccsess(address,data,select); // do test

        TEST_ASSERT_EQUALS(err,0); // normal
        TEST_ASSERT_EQUALS(inSetDataA_address,(int)address); // Check!
        TEST_ASSERT_EQUALS(inSetDataA_data,(int)data); // Check!
        TEST_ASSERT_EQUALS(inWriteAccessB_address,(int)0xffffffffu); // no access
        TEST_ASSERT_EQUALS(inWriteAccessB_data,0xffffu); // no access

        /////////////////////////////////////////////////
        // setDataA abnormal
        address = 0x86540004u; // 0x0-ffffffffu
        data = 22; // 0x0-ffffffffu
        select = HARD_TYPE_A; // HARD_TYPE_A,HARD_TYPE_B
        inSetDataA_address = 0xffffffffu;// imput(dirty)
        inSetDataA_data = 0xffffffffu;// imput(dirty)
        returnSetDataA = 0x31u; // 0:normal,1-0xffffffffu:abnormal
        inWriteAccessB_address = 0xffffffffu; // imput(dirty)
        inWriteAccessB_data = 0xffffu; // imput(dirty)

        err = hardAccsess(address,data,select); // do test

        TEST_ASSERT(err != 0); // abnormal
        TEST_ASSERT_EQUALS(inSetDataA_address,(int)address); // Check!
        TEST_ASSERT_EQUALS(inSetDataA_data,(int)data); // Check!
        TEST_ASSERT_EQUALS(inWriteAccessB_address,(int)0xffffffffu); // no access
        TEST_ASSERT_EQUALS(inWriteAccessB_data,0xffffu); // no access
        return 0;
    }

    static unsigned int testHardB(void) {
        unsigned int err;
        unsigned int address;
        unsigned int data;
        HARD_TYPE_t select;

        /////////////////////////////////////////////////
        // writeAccessB normal
        address = 0x36540004u; // 0x0-ffffffffu
        data = 22; // 0x0-0000ffffu:normal,0x00010000-0xffff0000:abnormal
        select = HARD_TYPE_B; // HARD_TYPE_A,HARD_TYPE_B
        inSetDataA_address = 0xffffffffu;// imput(dirty)
        inSetDataA_data = 0xffffffffu;// imput(dirty)
        returnSetDataA = 0; // 0:normal,1-0xffffffffu:abnormal
        inWriteAccessB_address = 0xffffffffu; // imput(dirty)
        inWriteAccessB_data = 0xffffu; // imput(dirty)

        err = hardAccsess(address,data,select); // do test

        TEST_ASSERT_EQUALS(err , 0); // normal
        TEST_ASSERT_EQUALS(inSetDataA_address,(int)0xffffffffu); // no access
        TEST_ASSERT_EQUALS(inSetDataA_data,(int)0xffffffffu); // no access
        TEST_ASSERT_EQUALS(inWriteAccessB_address,(int)address); // Check!
        TEST_ASSERT_EQUALS(inWriteAccessB_data,data); // Check!

        /////////////////////////////////////////////////
        // writeAccessB abnormal
        address = 0x36500027u; // 0x0-ffffffffu
        data = 0x04000003u; // 0x0-0000ffffu:normal,0x00010000-0xffff0000:abnormal
        select = HARD_TYPE_B; // HARD_TYPE_A,HARD_TYPE_B
        inSetDataA_address = 0xffffffffu;// imput(dirty)
        inSetDataA_data = 0xffffffffu;// imput(dirty)
        returnSetDataA = 0; // 0:normal,1-0xffffffffu:abnormal
        inWriteAccessB_address = 0xffffffffu; // imput(dirty)
        inWriteAccessB_data = 0xffffu; // imput(dirty)

        err = hardAccsess(address,data,select);

        TEST_ASSERT(err != 0); // abnormal
        TEST_ASSERT_EQUALS(inSetDataA_address,(int)0xffffffffu); // no access
        TEST_ASSERT_EQUALS(inSetDataA_data,(int)0xffffffffu); // no access
        TEST_ASSERT_EQUALS(inWriteAccessB_address,(int)0xffffffffu); // no access
        TEST_ASSERT_EQUALS(inWriteAccessB_data,0xffffu); // no access
        return 0;
    }

    /** Unit A Access driver. */
    unsigned int setDataA(
        unsigned int address,unsigned int data) {
        inSetDataA_address = address;
        inSetDataA_data = data;
        return returnSetDataA;
    }

    /** Unit B Access driver. */
    void writeAccessB(
        unsigned int address,unsigned short data) {
        inWriteAccessB_address = address;
        inWriteAccessB_data = data;
    }

### Foreach

This is a file for a test.

    #include "select.h"
    #include "loop.h"

    unsigned int loop(void) {
        unsigned int err;
        unsigned int loopErr = 0;
        unsigned int i = 0;
        for (i = 0 ; i < 10 ; i++) {
            unsigned int address = 0x85000000u + ( i + 8);
            err = setDataA(address,i);
            if (err && (! loopErr)) {
                loopErr = err;
            }
        }
        return loopErr;
    }

This is test file.

    #include <stdio.h>
    #include <string.h>
    #include <testRunner.h>
    #include "select.h"
    #include "loop.h"

    /* A domain is secured. */
    #define DATA_ARRAY 100
    static unsigned int inSetDataA_address[DATA_ARRAY];
    static unsigned int inSetDataA_data[DATA_ARRAY];
    static unsigned int returnSetDataA[DATA_ARRAY];
    static unsigned int countSetDataA = 0;

    static unsigned int testLoop(void);

    /** Main function. */
    int main() {
        return (int) testRunner(testLoop);
    }

    static unsigned int testLoop(void) {
        unsigned int err;
        unsigned int i;

        /////////////////////////////////////////////////
        // normal
        memset(inSetDataA_address,0xffffffffu,sizeof(unsigned int)*DATA_ARRAY);
        memset(inSetDataA_data,0xffffffffu,sizeof(unsigned int)*DATA_ARRAY);
        memset(returnSetDataA,0,sizeof(unsigned int)*DATA_ARRAY);
        countSetDataA = 0;

        err = loop(); // do test

        TEST_ASSERT_EQUALS(err,0); // normal
        TEST_ASSERT_EQUALS(countSetDataA,10); //
        for (i = 0 ; i < 10 ; i++) {
            TEST_ASSERT_EQUALS(inSetDataA_address[i] ,(int) (0x85000000u + (i + 8)));
            TEST_ASSERT_EQUALS(inSetDataA_data[i] ,(int) i);
        }

        /////////////////////////////////////////////////
        // abnormal
        memset(inSetDataA_address,0xffffffffu,sizeof(unsigned int)*DATA_ARRAY);
        memset(inSetDataA_data,0xffffffffu,sizeof(unsigned int)*DATA_ARRAY);
        memset(returnSetDataA,0,sizeof(unsigned int)*DATA_ARRAY);
        returnSetDataA[3] = 5; // A mistake is mixed.
        countSetDataA = 0;

        err = loop(); // do test

        TEST_ASSERT(err != 0); // abnormal
        // Even if there is an error, a hard setup has run
        TEST_ASSERT_EQUALS(countSetDataA,10);
        for (i = 0 ; i < 10 ; i++) {
            TEST_ASSERT_EQUALS(inSetDataA_address[i] ,(int) (0x85000000u + (i + 8)));
            TEST_ASSERT_EQUALS(inSetDataA_data[i] ,(int) i);
        }
        return 0;
    }

    /** Unit A Access driver. */
    unsigned int setDataA(
        unsigned int address,unsigned int data) {
        inSetDataA_address[countSetDataA] = address;
        inSetDataA_data[countSetDataA] = data;
        countSetDataA++;
        return returnSetDataA[countSetDataA];
    }