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