diff options
Diffstat (limited to 'cmockery_0_1_2/src/example/calculator.c')
-rw-r--r-- | cmockery_0_1_2/src/example/calculator.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/cmockery_0_1_2/src/example/calculator.c b/cmockery_0_1_2/src/example/calculator.c new file mode 100644 index 0000000..da3775b --- /dev/null +++ b/cmockery_0_1_2/src/example/calculator.c @@ -0,0 +1,266 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// A calculator example used to demonstrate the cmockery testing library. + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// If this is being built for a unit test. +#if UNIT_TESTING + +/* Redirect printf to a function in the test application so it's possible to + * test the standard output. */ +#ifdef printf +#undef printf +#endif // printf +#define printf example_test_printf + +extern void print_message(const char *format, ...); + +/* Redirect fprintf to a function in the test application so it's possible to + * test error messages. */ +#ifdef fprintf +#undef fprintf +#endif // fprintf +#define fprintf example_test_fprintf + +extern int example_test_fprintf(FILE * const file, const char *format, ...); + +// Redirect assert to mock_assert() so assertions can be caught by cmockery. +#ifdef assert +#undef assert +#endif // assert +#define assert(expression) \ + mock_assert((int)(expression), #expression, __FILE__, __LINE__) +void mock_assert(const int result, const char* expression, const char *file, + const int line); + +/* Redirect calloc and free to test_calloc() and test_free() so cmockery can + * check for memory leaks. */ +#ifdef calloc +#undef calloc +#endif // calloc +#define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__) +#ifdef free +#undef free +#endif // free +#define free(ptr) _test_free(ptr, __FILE__, __LINE__) +void* _test_calloc(const size_t number_of_elements, const size_t size, + const char* file, const int line); +void _test_free(void* const ptr, const char* file, const int line); + +/* main is defined in the unit test so redefine name of the the main function + * here. */ +#define main example_main + +/* All functions in this object need to be exposed to the test application, + * so redefine static to nothing. */ +#define static + +#endif // UNIT_TESTING + + +// A binary arithmetic integer operation (add, subtract etc.) +typedef int (*BinaryOperator)(int a, int b); + +// Structure which maps operator strings to functions. +typedef struct OperatorFunction { + const char* operator; + BinaryOperator function; +} OperatorFunction; + + +static int add(int a, int b); +static int subtract(int a, int b); +static int multiply(int a, int b); +static int divide(int a, int b); + +// Associate operator strings to functions. +static OperatorFunction operator_function_map[] = { + {"+", add}, + {"-", subtract}, + {"*", multiply}, + {"/", divide}, +}; + +static int add(int a, int b) { + return a + b; +} + +static int subtract(int a, int b) { + return a - b; +} + +static int multiply(int a, int b) { + return a * b; +} + +static int divide(int a, int b) { + assert(b); // Check for divde by zero. + return a / b; +} + +/* Searches the specified array of operator_functions for the function + * associated with the specified operator_string. This function returns the + * function associated with operator_string if successful, NULL otherwise. + */ +static BinaryOperator find_operator_function_by_string( + const size_t number_of_operator_functions, + const OperatorFunction * const operator_functions, + const char* const operator_string) { + size_t i; + assert(!number_of_operator_functions || operator_functions); + assert(operator_string); + + for (i = 0; i < number_of_operator_functions; i++) { + const OperatorFunction *const operator_function = + &operator_functions[i]; + if (strcmp(operator_function->operator, operator_string) == 0) { + return operator_function->function; + } + } + return NULL; +} + +/* Perform a series of binary arithmetic integer operations with no operator + * precedence. + * + * The input expression is specified by arguments which is an array of + * containing number_of_arguments strings. Operators invoked by the expression + * are specified by the array operator_functions containing + * number_of_operator_functions, OperatorFunction structures. The value of + * each binary operation is stored in a pointer returned to intermediate_values + * which is allocated by malloc(). + * + * If successful, this function returns the integer result of the operations. + * If an error occurs while performing the operation error_occurred is set to + * 1, the operation is aborted and 0 is returned. + */ +static int perform_operation( + int number_of_arguments, char *arguments[], + const size_t number_of_operator_functions, + const OperatorFunction * const operator_functions, + int * const number_of_intermediate_values, + int ** const intermediate_values, int * const error_occurred) { + char *end_of_integer; + int value; + unsigned int i; + assert(!number_of_arguments || arguments); + assert(!number_of_operator_functions || operator_functions); + assert(error_occurred); + assert(number_of_intermediate_values); + assert(intermediate_values); + + *error_occurred = 0; + *number_of_intermediate_values = 0; + *intermediate_values = NULL; + if (!number_of_arguments) + return 0; + + // Parse the first value. + value = (int)strtol(arguments[0], &end_of_integer, 10); + if (end_of_integer == arguments[0]) { + // If an error occurred while parsing the integer. + fprintf(stderr, "Unable to parse integer from argument %s\n", + arguments[0]); + *error_occurred = 1; + return 0; + } + + // Allocate an array for the output values. + *intermediate_values = calloc(((number_of_arguments - 1) / 2), + sizeof(**intermediate_values)); + + i = 1; + while (i < number_of_arguments) { + int other_value; + const char* const operator_string = arguments[i]; + const BinaryOperator function = find_operator_function_by_string( + number_of_operator_functions, operator_functions, operator_string); + int * const intermediate_value = + &((*intermediate_values)[*number_of_intermediate_values]); + (*number_of_intermediate_values) ++; + + if (!function) { + fprintf(stderr, "Unknown operator %s, argument %d\n", + operator_string, i); + *error_occurred = 1; + break; + } + i ++; + + if (i == number_of_arguments) { + fprintf(stderr, "Binary operator %s missing argument\n", + operator_string); + *error_occurred = 1; + break; + } + + other_value = (int)strtol(arguments[i], &end_of_integer, 10); + if (end_of_integer == arguments[i]) { + // If an error occurred while parsing the integer. + fprintf(stderr, "Unable to parse integer %s of argument %d\n", + arguments[i], i); + *error_occurred = 1; + break; + } + i ++; + + // Perform the operation and store the intermediate value. + *intermediate_value = function(value, other_value); + value = *intermediate_value; + } + if (*error_occurred) { + free(*intermediate_values); + *intermediate_values = NULL; + *number_of_intermediate_values = 0; + return 0; + } + return value; +} + +int main(int argc, char *argv[]) { + int return_value; + int number_of_intermediate_values; + int *intermediate_values; + // Peform the operation. + const int result = perform_operation( + argc - 1, &argv[1], + sizeof(operator_function_map) / sizeof(operator_function_map[0]), + operator_function_map, &number_of_intermediate_values, + &intermediate_values, &return_value); + + // If no errors occurred display the result. + if (!return_value && argc > 1) { + unsigned int i; + unsigned int intermediate_value_index = 0; + printf("%s\n", argv[1]); + for (i = 2; i < argc; i += 2) { + assert(intermediate_value_index < number_of_intermediate_values); + printf(" %s %s = %d\n", argv[i], argv[i + 1], + intermediate_values[intermediate_value_index++]); + } + printf("= %d\n", result); + } + if (intermediate_values) { + free(intermediate_values); + } + + return return_value; +} |