OpenVPN
calculator.c
Go to the documentation of this file.
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 cmocka testing library. */
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 #include <assert.h>
23 #ifdef HAVE_MALLOC_H
24 #include <malloc.h>
25 #endif
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 /* If this is being built for a unit test. */
31 #ifdef UNIT_TESTING
32 
33 /* Redirect printf to a function in the test application so it's possible to
34  * test the standard output. */
35 #ifdef printf
36 #undef printf
37 #endif /* printf */
38 extern int example_test_printf(const char *format, ...);
39 #define printf example_test_printf
40 
41 extern void print_message(const char *format, ...);
42 
43 /* Redirect fprintf to a function in the test application so it's possible to
44  * test error messages. */
45 #ifdef fprintf
46 #undef fprintf
47 #endif /* fprintf */
48 #define fprintf example_test_fprintf
49 
50 extern int example_test_fprintf(FILE * const file, const char *format, ...);
51 
52 /* Redirect assert to mock_assert() so assertions can be caught by cmocka. */
53 #ifdef assert
54 #undef assert
55 #endif /* assert */
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,
59  const int line);
60 
61 /* Redirect calloc and free to test_calloc() and test_free() so cmocka can
62  * check for memory leaks. */
63 #ifdef calloc
64 #undef calloc
65 #endif /* calloc */
66 #define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
67 #ifdef free
68 #undef free
69 #endif /* free */
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);
74 
75 int example_main(int argc, char *argv[]);
76 /* main is defined in the unit test so redefine name of the the main function
77  * here. */
78 #define main example_main
79 
80 /* All functions in this object need to be exposed to the test application,
81  * so redefine static to nothing. */
82 #define static
83 
84 #endif /* UNIT_TESTING */
85 
86 
87 /* A binary arithmetic integer operation (add, subtract etc.) */
88 typedef int (*BinaryOperator)(int a, int b);
89 
90 /* Structure which maps operator strings to functions. */
91 typedef struct OperatorFunction {
92  const char* operator;
93  BinaryOperator function;
95 
96 
98  const size_t number_of_operator_functions,
99  const OperatorFunction * const operator_functions,
100  const char* const operator_string);
101 
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);
108 
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);
113 
114 /* Associate operator strings to functions. */
116  {"+", add},
117  {"-", subtract},
118  {"*", multiply},
119  {"/", divide},
120 };
121 
122 static int add(int a, int b) {
123  return a + b;
124 }
125 
126 static int subtract(int a, int b) {
127  return a - b;
128 }
129 
130 static int multiply(int a, int b) {
131  return a * b;
132 }
133 
134 static int divide(int a, int b) {
135  assert(b); /* Check for divide by zero. */
136  return a / b;
137 }
138 
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.
142  */
144  const size_t number_of_operator_functions,
145  const OperatorFunction * const operator_functions,
146  const char* const operator_string) {
147  size_t i;
148  assert(!number_of_operator_functions || operator_functions);
149  assert(operator_string != NULL);
150 
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;
156  }
157  }
158  return NULL;
159 }
160 
161 /* Perform a series of binary arithmetic integer operations with no operator
162  * precedence.
163  *
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().
170  *
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.
174  */
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;
182  int value;
183  int i;
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);
189 
190  *error_occurred = 0;
191  *number_of_intermediate_values = 0;
192  *intermediate_values = NULL;
193  if (!number_of_arguments)
194  return 0;
195 
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",
201  arguments[0]);
202  *error_occurred = 1;
203  return 0;
204  }
205 
206  /* Allocate an array for the output values. */
207  *intermediate_values = calloc(((number_of_arguments - 1) / 2),
208  sizeof(**intermediate_values));
209 
210  i = 1;
211  while (i < number_of_arguments) {
212  int other_value;
213  const char* const operator_string = arguments[i];
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) ++;
219 
220  if (!function) {
221  fprintf(stderr, "Unknown operator %s, argument %d\n",
222  operator_string, i);
223  *error_occurred = 1;
224  break;
225  }
226  i ++;
227 
228  if (i == number_of_arguments) {
229  fprintf(stderr, "Binary operator %s missing argument\n",
230  operator_string);
231  *error_occurred = 1;
232  break;
233  }
234 
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",
239  arguments[i], i);
240  *error_occurred = 1;
241  break;
242  }
243  i ++;
244 
245  /* Perform the operation and store the intermediate value. */
246  *intermediate_value = function(value, other_value);
247  value = *intermediate_value;
248  }
249  if (*error_occurred) {
250  free(*intermediate_values);
251  *intermediate_values = NULL;
252  *number_of_intermediate_values = 0;
253  return 0;
254  }
255  return value;
256 }
257 
258 int main(int argc, char *argv[]) {
259  int return_value;
260  int number_of_intermediate_values;
261  int *intermediate_values;
262  /* Peform the operation. */
263  const int result = perform_operation(
264  argc - 1, &argv[1],
265  sizeof(operator_function_map) / sizeof(operator_function_map[0]),
266  operator_function_map, &number_of_intermediate_values,
267  &intermediate_values, &return_value);
268 
269  /* If no errors occurred display the result. */
270  if (!return_value && argc > 1) {
271  int i;
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++]);
278  }
279  printf("= %d\n", result);
280  }
281  if (intermediate_values) {
282  free(intermediate_values);
283  }
284 
285  return return_value;
286 }
int example_main(int argc, char *argv[])
int int example_test_printf(const char *format,...) CMOCKA_PRINTF_ATTRIBUTE(1
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)
Definition: calculator.c:175
void mock_assert(const int result, const char *const expression, const char *const file, const int line)
Function to replace assert(3) in tested code.
Definition: cmocka.c:1520
static int add(int a, int b)
Definition: calculator.c:122
static OperatorFunction operator_function_map[]
Definition: calculator.c:115
void _test_free(void *const ptr, const char *file, const int line)
Definition: cmocka.c:1810
static int divide(int a, int b)
Definition: calculator.c:134
int example_test_fprintf(FILE *const file, const char *format,...) CMOCKA_PRINTF_ATTRIBUTE(2
int(* BinaryOperator)(int a, int b)
Definition: calculator.c:88
void print_message(const char *const format,...) CMOCKA_PRINTF_ATTRIBUTE(1
const char * operator
Definition: calculator.c:92
static int subtract(int a, int b)
Definition: calculator.c:126
void * _test_calloc(const size_t number_of_elements, const size_t size, const char *file, const int line)
Definition: cmocka.c:1798
static int multiply(int a, int b)
Definition: calculator.c:130
struct OperatorFunction OperatorFunction
#define free
Definition: cmocka.c:1850
int main(int argc, char *argv[])
Definition: calculator.c:258
Definition: argv.h:35
BinaryOperator find_operator_function_by_string(const size_t number_of_operator_functions, const OperatorFunction *const operator_functions, const char *const operator_string)
Definition: calculator.c:143
BinaryOperator function
Definition: calculator.c:93