OpenVPN
waiter_test_wrap.c
Go to the documentation of this file.
1 /*
2  * Copyright 2013 (c) Andreas Schneider <asn@cynapses.org>
3  * Jakub Hrozek <jakub.hrozek@gmail.com>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <errno.h>
19 #include <stdbool.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include <stdarg.h>
25 #include <stddef.h>
26 #include <setjmp.h>
27 #include <cmocka.h>
28 
29 #include "waiter_test_wrap.h"
30 #include "chef.h"
31 
32 /*
33  * This is a mocked Chef object. A real Chef would look if he knows
34  * the dish in some kind of internal database and check his storage for
35  * ingredients. This chef simply retrieves this information from the test
36  * that is calling him.
37  *
38  * This object is also wrapped - if any code links with this file and is
39  * compiled with linker option --wrap chef_cook, any calls of that code to
40  * chef_cook will end up calling __wrap_chef_cook.
41  *
42  * If for any reason the wrapped function wanted to call the real chef_cook()
43  * function, it could do so by calling the special symbol __real_chef_cook().
44  *
45  * Please note that when setting return codes for the chef_cook function, we
46  * use this wrapper as a parameter for the will_return() macro, not the
47  * real function.
48  *
49  * A chef object would return:
50  * 0 - cooking dish went fine
51  * -1 - unknown dish
52  * -2 - ran out of ingredients for the dish
53  * any other error code -- unexpected error while cooking
54  *
55  * The return codes should be consistent between the real and mocked objects.
56  */
57 int __wrap_chef_cook(const char *order, char **dish_out)
58 {
59  bool has_ingredients;
60  bool knows_dish;
61  char *dish;
62 
63  check_expected_ptr(order);
64 
65  knows_dish = mock_type(bool);
66  if (knows_dish == false) {
67  return -1;
68  }
69 
70  has_ingredients = mock_type(bool);
71  if (has_ingredients == false) {
72  return -2;
73  }
74 
75  dish = mock_ptr_type(char *);
76  *dish_out = strdup(dish);
77  if (*dish_out == NULL) return ENOMEM;
78 
79  return mock_type(int);
80 }
81 
82 /* Waiter return codes:
83  * 0 - success
84  * -1 - kitchen failed
85  * -2 - kitchen succeeded, but cooked a different food
86  */
87 static int waiter_process(const char *order, char **dish)
88 {
89  int rv;
90 
91  rv = chef_cook(order, dish);
92  if (rv != 0) {
93  fprintf(stderr, "Chef couldn't cook %s: %s\n",
94  order, chef_strerror(rv));
95  return -1;
96  }
97 
98  /* Check if we received the dish we wanted from the kitchen */
99  if (strcmp(order, *dish) != 0) {
100  free(*dish);
101  *dish = NULL;
102  return -2;
103  }
104 
105  return 0;
106 }
107 
108 static void test_order_hotdog(void **state)
109 {
110  int rv;
111  char *dish;
112 
113  (void) state; /* unused */
114 
115  /* We expect the chef to receive an order for a hotdog */
116  expect_string(__wrap_chef_cook, order, "hotdog");
117  /* And we tell the test chef that ke knows how to cook a hotdog
118  * and has the ingredients
119  */
122  /* The result will be a hotdog and the cooking process will succeed */
125 
126  /* Test the waiter */
127  rv = waiter_process("hotdog", &dish);
128 
129  /* We expect the cook to succeed cooking the hotdog */
130  assert_int_equal(rv, 0);
131  /* And actually receive one */
132  assert_string_equal(dish, "hotdog");
133  if (dish != NULL) {
134  free(dish);
135  }
136 }
137 
138 static void test_bad_dish(void **state)
139 {
140  int rv;
141  char *dish;
142 
143  (void) state; /* unused */
144 
145  /* We expect the chef to receive an order for a hotdog */
146  expect_string(__wrap_chef_cook, order, "hotdog");
147  /* And we tell the test chef that ke knows how to cook a hotdog
148  * and has the ingredients
149  */
152  /* The result will be a burger and the cooking process will succeed.
153  * We expect the waiter to handle the bad dish and return an error
154  * code
155  */
158 
159  /* Test the waiter */
160  rv = waiter_process("hotdog", &dish);
161 
162  /* According to the documentation the waiter should return -2 now */
163  assert_int_equal(rv, -2);
164  /* And do not give the bad dish to the customer */
165  assert_null(dish);
166 }
167 
168 int main(void)
169 {
170  const struct CMUnitTest tests[] = {
173  };
174 
175  return cmocka_run_group_tests(tests, NULL, NULL);
176 }
#define cmocka_unit_test(f)
Initializes a CMUnitTest structure.
Definition: cmocka.h:1653
int main(void)
static int waiter_process(const char *order, char **dish)
#define mock_type(type)
Definition: cmocka.h:236
int __wrap_chef_cook(const char *order, char **dish_out)
#define assert_string_equal(a, b)
Definition: cmocka.h:1214
int chef_cook(const char *order, char **dish_out)
Definition: chef.c:33
#define will_return(function, value)
Definition: cmocka.h:294
#define cast_ptr_to_largest_integral_type(value)
Definition: cmocka.h:133
#define cmocka_run_group_tests(group_tests, group_setup, group_teardown)
Definition: cmocka.h:1749
static void test_order_hotdog(void **state)
#define assert_null(c)
Definition: cmocka.h:1119
#define free
Definition: cmocka.c:1850
#define mock_ptr_type(type)
Definition: cmocka.h:263
const char * chef_strerror(int error)
Definition: chef.c:41
#define check_expected_ptr(parameter)
Definition: cmocka.h:1004
#define expect_string(function, parameter, string)
Definition: cmocka.h:753
#define assert_int_equal(a, b)
Definition: cmocka.h:1174
static void test_bad_dish(void **state)