| /* |
| * Copyright 2013 (c) Andreas Schneider <asn@cynapses.org> |
| * Jakub Hrozek <jakub.hrozek@gmail.com> |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <errno.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include <stdarg.h> |
| #include <stddef.h> |
| #include <setjmp.h> |
| #include <cmocka.h> |
| |
| #include "waiter_test_wrap.h" |
| #include "chef.h" |
| |
| /* |
| * This is a mocked Chef object. A real Chef would look if he knows |
| * the dish in some kind of internal database and check his storage for |
| * ingredients. This chef simply retrieves this information from the test |
| * that is calling him. |
| * |
| * This object is also wrapped - if any code links with this file and is |
| * compiled with linker option --wrap chef_cook, any calls of that code to |
| * chef_cook will end up calling __wrap_chef_cook. |
| * |
| * If for any reason the wrapped function wanted to call the real chef_cook() |
| * function, it could do so by calling the special symbol __real_chef_cook(). |
| * |
| * Please note that when setting return codes for the chef_cook function, we |
| * use this wrapper as a parameter for the will_return() macro, not the |
| * real function. |
| * |
| * A chef object would return: |
| * 0 - cooking dish went fine |
| * -1 - unknown dish |
| * -2 - ran out of ingredients for the dish |
| * any other error code -- unexpected error while cooking |
| * |
| * The return codes should be consistent between the real and mocked objects. |
| */ |
| int __wrap_chef_cook(const char *order, char **dish_out) |
| { |
| bool has_ingredients; |
| bool knows_dish; |
| char *dish; |
| |
| check_expected(order); |
| |
| knows_dish = (bool) mock(); |
| if (knows_dish == false) { |
| return -1; |
| } |
| |
| has_ingredients = (bool) mock(); |
| if (has_ingredients == false) { |
| return -2; |
| } |
| |
| dish = (char *) mock(); |
| *dish_out = strdup(dish); |
| if (*dish_out == NULL) return ENOMEM; |
| |
| return mock(); |
| } |
| |
| /* Waiter return codes: |
| * 0 - success |
| * -1 - kitchen failed |
| * -2 - kitchen succeeded, but cooked a different food |
| */ |
| static int waiter_process(const char *order, char **dish) |
| { |
| int rv; |
| |
| rv = chef_cook(order, dish); |
| if (rv != 0) { |
| fprintf(stderr, "Chef couldn't cook %s: %s\n", |
| order, chef_strerror(rv)); |
| return -1; |
| } |
| |
| /* Check if we received the dish we wanted from the kitchen */ |
| if (strcmp(order, *dish) != 0) { |
| *dish = NULL; |
| return -2; |
| } |
| |
| return 0; |
| } |
| |
| static void test_order_hotdog(void **state) |
| { |
| int rv; |
| char *dish; |
| |
| (void) state; /* unused */ |
| |
| /* We expect the chef to receive an order for a hotdog */ |
| expect_string(__wrap_chef_cook, order, "hotdog"); |
| /* And we tell the test chef that ke knows how to cook a hotdog |
| * and has the ingredients |
| */ |
| will_return(__wrap_chef_cook, true); |
| will_return(__wrap_chef_cook, true); |
| /* The result will be a hotdog and the cooking process will succeed */ |
| will_return(__wrap_chef_cook, "hotdog"); |
| will_return(__wrap_chef_cook, 0); |
| |
| /* Test the waiter */ |
| rv = waiter_process("hotdog", &dish); |
| |
| /* We expect the cook to succeed cooking the hotdog */ |
| assert_int_equal(rv, 0); |
| /* And actually receive one */ |
| assert_string_equal(dish, "hotdog"); |
| } |
| |
| static void test_bad_dish(void **state) |
| { |
| int rv; |
| char *dish; |
| |
| (void) state; /* unused */ |
| |
| /* We expect the chef to receive an order for a hotdog */ |
| expect_string(__wrap_chef_cook, order, "hotdog"); |
| /* And we tell the test chef that ke knows how to cook a hotdog |
| * and has the ingredients |
| */ |
| will_return(__wrap_chef_cook, true); |
| will_return(__wrap_chef_cook, true); |
| /* The result will be a burger and the cooking process will succeed. |
| * We expect the waiter to handle the bad dish and return an error |
| * code |
| */ |
| will_return(__wrap_chef_cook, "burger"); |
| will_return(__wrap_chef_cook, 0); |
| |
| /* Test the waiter */ |
| rv = waiter_process("hotdog", &dish); |
| |
| /* According to the documentation the waiter should return -2 now */ |
| assert_int_equal(rv, -2); |
| /* And do not give the bad dish to the customer */ |
| assert_null(dish); |
| } |
| |
| int main(void) |
| { |
| const UnitTest tests[] = { |
| unit_test(test_order_hotdog), |
| unit_test(test_bad_dish), |
| }; |
| |
| return run_tests(tests); |
| } |