Heather Lee Wilson | bdd62c5 | 2013-12-28 15:12:39 -0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2008 Google Inc. |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | // A calculator example used to demonstrate the cmockery testing library. |
| 18 | |
| 19 | #include <assert.h> |
| 20 | #include <stdio.h> |
| 21 | #include <stdlib.h> |
| 22 | #include <string.h> |
| 23 | |
| 24 | // If this is being built for a unit test. |
| 25 | #if UNIT_TESTING |
| 26 | |
| 27 | /* Redirect printf to a function in the test application so it's possible to |
| 28 | * test the standard output. */ |
| 29 | #ifdef printf |
| 30 | #undef printf |
| 31 | #endif // printf |
| 32 | #define printf example_test_printf |
| 33 | |
| 34 | extern void print_message(const char *format, ...); |
| 35 | |
| 36 | /* Redirect fprintf to a function in the test application so it's possible to |
| 37 | * test error messages. */ |
| 38 | #ifdef fprintf |
| 39 | #undef fprintf |
| 40 | #endif // fprintf |
| 41 | #define fprintf example_test_fprintf |
| 42 | |
| 43 | extern int example_test_fprintf(FILE * const file, const char *format, ...); |
| 44 | |
| 45 | // Redirect assert to mock_assert() so assertions can be caught by cmockery. |
| 46 | #ifdef assert |
| 47 | #undef assert |
| 48 | #endif // assert |
| 49 | #define assert(expression) \ |
| 50 | mock_assert((int)(expression), #expression, __FILE__, __LINE__) |
| 51 | void mock_assert(const int result, const char* expression, const char *file, |
| 52 | const int line); |
| 53 | |
| 54 | /* Redirect calloc and free to test_calloc() and test_free() so cmockery can |
| 55 | * check for memory leaks. */ |
| 56 | #ifdef calloc |
| 57 | #undef calloc |
| 58 | #endif // calloc |
| 59 | #define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__) |
| 60 | #ifdef free |
| 61 | #undef free |
| 62 | #endif // free |
| 63 | #define free(ptr) _test_free(ptr, __FILE__, __LINE__) |
| 64 | void* _test_calloc(const size_t number_of_elements, const size_t size, |
| 65 | const char* file, const int line); |
| 66 | void _test_free(void* const ptr, const char* file, const int line); |
| 67 | |
| 68 | /* main is defined in the unit test so redefine name of the the main function |
| 69 | * here. */ |
| 70 | #define main example_main |
| 71 | |
| 72 | /* All functions in this object need to be exposed to the test application, |
| 73 | * so redefine static to nothing. */ |
| 74 | #define static |
| 75 | |
| 76 | #endif // UNIT_TESTING |
| 77 | |
| 78 | |
| 79 | // A binary arithmetic integer operation (add, subtract etc.) |
| 80 | typedef int (*BinaryOperator)(int a, int b); |
| 81 | |
| 82 | // Structure which maps operator strings to functions. |
| 83 | typedef struct OperatorFunction { |
| 84 | const char* operator; |
| 85 | BinaryOperator function; |
| 86 | } OperatorFunction; |
| 87 | |
| 88 | |
| 89 | static int add(int a, int b); |
| 90 | static int subtract(int a, int b); |
| 91 | static int multiply(int a, int b); |
| 92 | static int divide(int a, int b); |
| 93 | |
| 94 | // Associate operator strings to functions. |
| 95 | static OperatorFunction operator_function_map[] = { |
| 96 | {"+", add}, |
| 97 | {"-", subtract}, |
| 98 | {"*", multiply}, |
| 99 | {"/", divide}, |
| 100 | }; |
| 101 | |
| 102 | static int add(int a, int b) { |
| 103 | return a + b; |
| 104 | } |
| 105 | |
| 106 | static int subtract(int a, int b) { |
| 107 | return a - b; |
| 108 | } |
| 109 | |
| 110 | static int multiply(int a, int b) { |
| 111 | return a * b; |
| 112 | } |
| 113 | |
| 114 | static int divide(int a, int b) { |
| 115 | assert(b); // Check for divde by zero. |
| 116 | return a / b; |
| 117 | } |
| 118 | |
| 119 | /* Searches the specified array of operator_functions for the function |
| 120 | * associated with the specified operator_string. This function returns the |
| 121 | * function associated with operator_string if successful, NULL otherwise. |
| 122 | */ |
| 123 | static BinaryOperator find_operator_function_by_string( |
| 124 | const size_t number_of_operator_functions, |
| 125 | const OperatorFunction * const operator_functions, |
| 126 | const char* const operator_string) { |
| 127 | size_t i; |
| 128 | assert(!number_of_operator_functions || operator_functions); |
| 129 | assert(operator_string); |
| 130 | |
| 131 | for (i = 0; i < number_of_operator_functions; i++) { |
| 132 | const OperatorFunction *const operator_function = |
| 133 | &operator_functions[i]; |
| 134 | if (strcmp(operator_function->operator, operator_string) == 0) { |
| 135 | return operator_function->function; |
| 136 | } |
| 137 | } |
| 138 | return NULL; |
| 139 | } |
| 140 | |
| 141 | /* Perform a series of binary arithmetic integer operations with no operator |
| 142 | * precedence. |
| 143 | * |
| 144 | * The input expression is specified by arguments which is an array of |
| 145 | * containing number_of_arguments strings. Operators invoked by the expression |
| 146 | * are specified by the array operator_functions containing |
| 147 | * number_of_operator_functions, OperatorFunction structures. The value of |
| 148 | * each binary operation is stored in a pointer returned to intermediate_values |
| 149 | * which is allocated by malloc(). |
| 150 | * |
| 151 | * If successful, this function returns the integer result of the operations. |
| 152 | * If an error occurs while performing the operation error_occurred is set to |
| 153 | * 1, the operation is aborted and 0 is returned. |
| 154 | */ |
| 155 | static int perform_operation( |
| 156 | int number_of_arguments, char *arguments[], |
| 157 | const size_t number_of_operator_functions, |
| 158 | const OperatorFunction * const operator_functions, |
| 159 | int * const number_of_intermediate_values, |
| 160 | int ** const intermediate_values, int * const error_occurred) { |
| 161 | char *end_of_integer; |
| 162 | int value; |
| 163 | unsigned int i; |
| 164 | assert(!number_of_arguments || arguments); |
| 165 | assert(!number_of_operator_functions || operator_functions); |
| 166 | assert(error_occurred); |
| 167 | assert(number_of_intermediate_values); |
| 168 | assert(intermediate_values); |
| 169 | |
| 170 | *error_occurred = 0; |
| 171 | *number_of_intermediate_values = 0; |
| 172 | *intermediate_values = NULL; |
| 173 | if (!number_of_arguments) |
| 174 | return 0; |
| 175 | |
| 176 | // Parse the first value. |
| 177 | value = (int)strtol(arguments[0], &end_of_integer, 10); |
| 178 | if (end_of_integer == arguments[0]) { |
| 179 | // If an error occurred while parsing the integer. |
| 180 | fprintf(stderr, "Unable to parse integer from argument %s\n", |
| 181 | arguments[0]); |
| 182 | *error_occurred = 1; |
| 183 | return 0; |
| 184 | } |
| 185 | |
| 186 | // Allocate an array for the output values. |
| 187 | *intermediate_values = calloc(((number_of_arguments - 1) / 2), |
| 188 | sizeof(**intermediate_values)); |
| 189 | |
| 190 | i = 1; |
| 191 | while (i < number_of_arguments) { |
| 192 | int other_value; |
| 193 | const char* const operator_string = arguments[i]; |
| 194 | const BinaryOperator function = find_operator_function_by_string( |
| 195 | number_of_operator_functions, operator_functions, operator_string); |
| 196 | int * const intermediate_value = |
| 197 | &((*intermediate_values)[*number_of_intermediate_values]); |
| 198 | (*number_of_intermediate_values) ++; |
| 199 | |
| 200 | if (!function) { |
| 201 | fprintf(stderr, "Unknown operator %s, argument %d\n", |
| 202 | operator_string, i); |
| 203 | *error_occurred = 1; |
| 204 | break; |
| 205 | } |
| 206 | i ++; |
| 207 | |
| 208 | if (i == number_of_arguments) { |
| 209 | fprintf(stderr, "Binary operator %s missing argument\n", |
| 210 | operator_string); |
| 211 | *error_occurred = 1; |
| 212 | break; |
| 213 | } |
| 214 | |
| 215 | other_value = (int)strtol(arguments[i], &end_of_integer, 10); |
| 216 | if (end_of_integer == arguments[i]) { |
| 217 | // If an error occurred while parsing the integer. |
| 218 | fprintf(stderr, "Unable to parse integer %s of argument %d\n", |
| 219 | arguments[i], i); |
| 220 | *error_occurred = 1; |
| 221 | break; |
| 222 | } |
| 223 | i ++; |
| 224 | |
| 225 | // Perform the operation and store the intermediate value. |
| 226 | *intermediate_value = function(value, other_value); |
| 227 | value = *intermediate_value; |
| 228 | } |
| 229 | if (*error_occurred) { |
| 230 | free(*intermediate_values); |
| 231 | *intermediate_values = NULL; |
| 232 | *number_of_intermediate_values = 0; |
| 233 | return 0; |
| 234 | } |
| 235 | return value; |
| 236 | } |
| 237 | |
| 238 | int main(int argc, char *argv[]) { |
| 239 | int return_value; |
| 240 | int number_of_intermediate_values; |
| 241 | int *intermediate_values; |
| 242 | // Peform the operation. |
| 243 | const int result = perform_operation( |
| 244 | argc - 1, &argv[1], |
| 245 | sizeof(operator_function_map) / sizeof(operator_function_map[0]), |
| 246 | operator_function_map, &number_of_intermediate_values, |
| 247 | &intermediate_values, &return_value); |
| 248 | |
| 249 | // If no errors occurred display the result. |
| 250 | if (!return_value && argc > 1) { |
| 251 | unsigned int i; |
| 252 | unsigned int intermediate_value_index = 0; |
| 253 | printf("%s\n", argv[1]); |
| 254 | for (i = 2; i < argc; i += 2) { |
| 255 | assert(intermediate_value_index < number_of_intermediate_values); |
| 256 | printf(" %s %s = %d\n", argv[i], argv[i + 1], |
| 257 | intermediate_values[intermediate_value_index++]); |
| 258 | } |
| 259 | printf("= %d\n", result); |
| 260 | } |
| 261 | if (intermediate_values) { |
| 262 | free(intermediate_values); |
| 263 | } |
| 264 | |
| 265 | return return_value; |
| 266 | } |