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 
add(int a,int b)102 static int add(int a, int b) {
103 	return a + b;
104 }
105 
subtract(int a,int b)106 static int subtract(int a, int b) {
107 	return a - b;
108 }
109 
multiply(int a,int b)110 static int multiply(int a, int b) {
111 	return a * b;
112 }
113 
divide(int a,int b)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  */
find_operator_function_by_string(const size_t number_of_operator_functions,const OperatorFunction * const operator_functions,const char * const operator_string)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  */
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)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 
main(int argc,char * argv[])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 }
267