2 * Copyright 2008 Google Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* A calculator example used to demonstrate the cmocka testing library. */
30 /* If this is being built for a unit test. */
33 /* Redirect printf to a function in the test application so it's possible to
34 * test the standard output. */
38 extern int example_test_printf(const char *format, ...);
39 #define printf example_test_printf
41 extern void print_message(const char *format, ...);
43 /* Redirect fprintf to a function in the test application so it's possible to
44 * test error messages. */
48 #define fprintf example_test_fprintf
50 extern int example_test_fprintf(FILE * const file, const char *format, ...);
52 /* Redirect assert to mock_assert() so assertions can be caught by cmocka. */
56 #define assert(expression) \
57 mock_assert((int)(expression), #expression, __FILE__, __LINE__)
58 void mock_assert(const int result, const char* expression, const char *file,
61 /* Redirect calloc and free to test_calloc() and test_free() so cmocka can
62 * check for memory leaks. */
66 #define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
70 #define free(ptr) _test_free(ptr, __FILE__, __LINE__)
71 void* _test_calloc(const size_t number_of_elements, const size_t size,
72 const char* file, const int line);
73 void _test_free(void* const ptr, const char* file, const int line);
75 int example_main(int argc, char *argv[]);
76 /* main is defined in the unit test so redefine name of the the main function
78 #define main example_main
80 /* All functions in this object need to be exposed to the test application,
81 * so redefine static to nothing. */
84 #endif /* UNIT_TESTING */
87 /* A binary arithmetic integer operation (add, subtract etc.) */
88 typedef int (*BinaryOperator)(int a, int b);
90 /* Structure which maps operator strings to functions. */
91 typedef struct OperatorFunction {
93 BinaryOperator function;
97 BinaryOperator find_operator_function_by_string(
98 const size_t number_of_operator_functions,
99 const OperatorFunction * const operator_functions,
100 const char* const operator_string);
102 int perform_operation(
103 int number_of_arguments, char *arguments[],
104 const size_t number_of_operator_functions,
105 const OperatorFunction * const operator_functions,
106 int * const number_of_intermediate_values,
107 int ** const intermediate_values, int * const error_occurred);
109 static int add(int a, int b);
110 static int subtract(int a, int b);
111 static int multiply(int a, int b);
112 static int divide(int a, int b);
114 /* Associate operator strings to functions. */
115 static OperatorFunction operator_function_map[] = {
122 static int add(int a, int b) {
126 static int subtract(int a, int b) {
130 static int multiply(int a, int b) {
134 static int divide(int a, int b) {
135 assert(b); /* Check for divide by zero. */
139 /* Searches the specified array of operator_functions for the function
140 * associated with the specified operator_string. This function returns the
141 * function associated with operator_string if successful, NULL otherwise.
143 BinaryOperator find_operator_function_by_string(
144 const size_t number_of_operator_functions,
145 const OperatorFunction * const operator_functions,
146 const char* const operator_string) {
148 assert(!number_of_operator_functions || operator_functions);
149 assert(operator_string != NULL);
151 for (i = 0; i < number_of_operator_functions; i++) {
152 const OperatorFunction *const operator_function =
153 &operator_functions[i];
154 if (strcmp(operator_function->operator, operator_string) == 0) {
155 return operator_function->function;
161 /* Perform a series of binary arithmetic integer operations with no operator
164 * The input expression is specified by arguments which is an array of
165 * containing number_of_arguments strings. Operators invoked by the expression
166 * are specified by the array operator_functions containing
167 * number_of_operator_functions, OperatorFunction structures. The value of
168 * each binary operation is stored in a pointer returned to intermediate_values
169 * which is allocated by malloc().
171 * If successful, this function returns the integer result of the operations.
172 * If an error occurs while performing the operation error_occurred is set to
173 * 1, the operation is aborted and 0 is returned.
175 int perform_operation(
176 int number_of_arguments, char *arguments[],
177 const size_t number_of_operator_functions,
178 const OperatorFunction * const operator_functions,
179 int * const number_of_intermediate_values,
180 int ** const intermediate_values, int * const error_occurred) {
181 char *end_of_integer;
184 assert(!number_of_arguments || arguments);
185 assert(!number_of_operator_functions || operator_functions);
186 assert(error_occurred != NULL);
187 assert(number_of_intermediate_values != NULL);
188 assert(intermediate_values != NULL);
191 *number_of_intermediate_values = 0;
192 *intermediate_values = NULL;
193 if (!number_of_arguments)
196 /* Parse the first value. */
197 value = (int)strtol(arguments[0], &end_of_integer, 10);
198 if (end_of_integer == arguments[0]) {
199 /* If an error occurred while parsing the integer. */
200 fprintf(stderr, "Unable to parse integer from argument %s\n",
206 /* Allocate an array for the output values. */
207 *intermediate_values = calloc(((number_of_arguments - 1) / 2),
208 sizeof(**intermediate_values));
211 while (i < number_of_arguments) {
213 const char* const operator_string = arguments[i];
214 const BinaryOperator function = find_operator_function_by_string(
215 number_of_operator_functions, operator_functions, operator_string);
216 int * const intermediate_value =
217 &((*intermediate_values)[*number_of_intermediate_values]);
218 (*number_of_intermediate_values) ++;
221 fprintf(stderr, "Unknown operator %s, argument %d\n",
228 if (i == number_of_arguments) {
229 fprintf(stderr, "Binary operator %s missing argument\n",
235 other_value = (int)strtol(arguments[i], &end_of_integer, 10);
236 if (end_of_integer == arguments[i]) {
237 /* If an error occurred while parsing the integer. */
238 fprintf(stderr, "Unable to parse integer %s of argument %d\n",
245 /* Perform the operation and store the intermediate value. */
246 *intermediate_value = function(value, other_value);
247 value = *intermediate_value;
249 if (*error_occurred) {
250 free(*intermediate_values);
251 *intermediate_values = NULL;
252 *number_of_intermediate_values = 0;
258 int main(int argc, char *argv[]) {
260 int number_of_intermediate_values;
261 int *intermediate_values;
262 /* Peform the operation. */
263 const int result = perform_operation(
265 sizeof(operator_function_map) / sizeof(operator_function_map[0]),
266 operator_function_map, &number_of_intermediate_values,
267 &intermediate_values, &return_value);
269 /* If no errors occurred display the result. */
270 if (!return_value && argc > 1) {
272 int intermediate_value_index = 0;
273 printf("%s\n", argv[1]);
274 for (i = 2; i < argc; i += 2) {
275 assert(intermediate_value_index < number_of_intermediate_values);
276 printf(" %s %s = %d\n", argv[i], argv[i + 1],
277 intermediate_values[intermediate_value_index++]);
279 printf("= %d\n", result);
281 if (intermediate_values) {
282 free(intermediate_values);