Atrinik Server 2.5
tests/unit/server/check_object.c
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00026 #include <global.h>
00027 #include <check.h>
00028 
00029 START_TEST(test_CAN_MERGE)
00030 {
00031     object *ob1, *ob2;
00032 
00033     ob1 = get_archetype("bolt");
00034     ob2 = get_archetype("bolt");
00035     fail_if(CAN_MERGE(ob1, ob2) == 0, "Should be able to merge 2 same objects.");
00036     ob2->name = add_string("Not same name");
00037     fail_if(CAN_MERGE(ob1, ob2) == 1, "Should not be able to merge 2 objects with different names.");
00038     ob2 = get_archetype("bolt");
00039     ob2->type++;
00040     fail_if(CAN_MERGE(ob1, ob2) == 1, "Should not be able to merge 2 objects with different types.");
00041     ob2 = get_archetype("bolt");
00042     ob1->nrof = SINT32_MAX;
00043     ob2->nrof = 1;
00044     fail_if(CAN_MERGE(ob1, ob2) == 1, "Should not be able to merge 2 objects if result nrof goes to higher than SINT32_MAX");
00045 }
00046 END_TEST
00047 
00048 START_TEST(test_sum_weight)
00049 {
00050     object *ob1, *ob2, *ob3, *ob4;
00051     unsigned long sum;
00052 
00053     ob1 = get_archetype("sack");
00054     ob2 = get_archetype("sack");
00055     ob3 = get_archetype("sack");
00056     ob4 = get_archetype("sack");
00057     ob1->weight = 10;
00058     ob1->type = CONTAINER;
00059     /* 40% reduction of weight */
00060     ob1->weapon_speed = 0.6f;
00061     ob2->weight = 6;
00062     ob2->nrof = 10;
00063     ob3->weight = 7;
00064     ob4->weight = 8;
00065     insert_ob_in_ob(ob2, ob1);
00066     insert_ob_in_ob(ob3, ob1);
00067     insert_ob_in_ob(ob4, ob1);
00068     sum = sum_weight(ob1);
00069     fail_if(sum != 45, "Sum of object's inventory should be 45 ((6 * 10 + 7 + 8) * .6) but was %lu.", sum);
00070 }
00071 END_TEST
00072 
00073 START_TEST(test_add_weight)
00074 {
00075     object *ob1, *ob2, *ob3, *ob4;
00076     unsigned long sum;
00077 
00078     ob1 = get_archetype("sack");
00079     ob2 = get_archetype("sack");
00080     ob3 = get_archetype("sack");
00081     ob4 = get_archetype("sack");
00082     ob1->weight = 10;
00083     ob1->type = CONTAINER;
00084     ob2->type = CONTAINER;
00085     ob3->type = CONTAINER;
00086     /* 40% reduction of weight */
00087     ob1->weapon_speed = 0.6f;
00088     ob2->weight = 10;
00089     ob3->weight = 10;
00090     ob4->weight = 10;
00091     insert_ob_in_ob(ob2, ob1);
00092     insert_ob_in_ob(ob3, ob2);
00093     insert_ob_in_ob(ob4, ob3);
00094     sum = sum_weight(ob1);
00095     fail_if(sum != 18, "Sum of object's inventory should be 18 (30 * 0.6 + 10) but was %lu.", sum);
00096     add_weight(ob4, 10);
00097     fail_if(ob1->carrying != 24, "After call to add_weight, carrying of ob1 should be 24 but was %d.", ob1->carrying);
00098 }
00099 END_TEST
00100 
00101 START_TEST(test_sub_weight)
00102 {
00103     object *ob1, *ob2, *ob3, *ob4;
00104     unsigned long sum;
00105 
00106     ob1 = get_archetype("sack");
00107     ob2 = get_archetype("sack");
00108     ob3 = get_archetype("sack");
00109     ob4 = get_archetype("sack");
00110     ob1->weight = 10;
00111     ob1->type = CONTAINER;
00112     ob2->type = CONTAINER;
00113     ob3->type = CONTAINER;
00114     /* 40% reduction of weight */
00115     ob1->weapon_speed = 0.6f;
00116     ob2->weight = 10;
00117     ob3->weight = 10;
00118     ob4->weight = 10;
00119     insert_ob_in_ob(ob2, ob1);
00120     insert_ob_in_ob(ob3, ob2);
00121     insert_ob_in_ob(ob4, ob3);
00122     sum = sum_weight(ob1);
00123     fail_if(sum != 18, "Sum of object's inventory should be 18 (30 * 0.6 + 10) but was %lu.", sum);
00124     sub_weight(ob4, 10);
00125     fail_if(ob1->carrying != 12, "After call to sub_weight, carrying of ob1 should be 12 but was %d.", ob1->carrying);
00126 }
00127 END_TEST
00128 
00129 START_TEST(test_get_env_recursive)
00130 {
00131     object *ob1, *ob2, *ob3, *ob4, *result;
00132 
00133     ob1 = get_archetype("sack");
00134     ob2 = get_archetype("sack");
00135     ob3 = get_archetype("sack");
00136     ob4 = get_archetype("sack");
00137     insert_ob_in_ob(ob2, ob1);
00138     insert_ob_in_ob(ob3, ob2);
00139     insert_ob_in_ob(ob4, ob3);
00140     result = get_env_recursive(ob4);
00141     fail_if(result != ob1, "Getting top level container for ob4(%p) should bring ob1(%p) but brought %p.", ob4, ob1, result);
00142 }
00143 END_TEST
00144 
00145 START_TEST(test_is_player_inv)
00146 {
00147     object *ob1, *ob2, *ob3, *ob4, *result;
00148 
00149     ob1 = get_archetype("sack");
00150     ob2 = get_archetype("sack");
00151     ob3 = get_archetype("sack");
00152     ob4 = get_archetype("sack");
00153     insert_ob_in_ob(ob2, ob1);
00154     insert_ob_in_ob(ob3, ob2);
00155     insert_ob_in_ob(ob4, ob3);
00156     result = is_player_inv(ob4);
00157     fail_if(result != NULL, "Getting containing player for ob4(%p) should bring NULL but brought %p while not contained in a player.", ob4, result);
00158     ob1->type = PLAYER;
00159     result = is_player_inv(ob4);
00160     fail_if(result != ob1, "Getting containing player for ob4(%p) should bring ob1(%p) but brought %p while ob1 is player.", ob4, ob1, result);
00161 }
00162 END_TEST
00163 
00164 START_TEST(test_dump_object)
00165 {
00166     object *ob1, *ob2, *ob3;
00167     StringBuffer *sb;
00168     char *result;
00169 
00170     ob1 = get_archetype("sack");
00171     ob2 = get_archetype("sack");
00172     ob3 = get_archetype("sack");
00173     insert_ob_in_ob(ob2, ob1);
00174     insert_ob_in_ob(ob3, ob2);
00175     sb = stringbuffer_new();
00176     dump_object(ob1, sb);
00177     result = stringbuffer_finish(sb);
00178     fail_if(strstr(result, "arch") == 0, "The object dump should contain 'arch' but was %s", result);
00179     free(result);
00180 }
00181 END_TEST
00182 
00183 START_TEST(test_insert_ob_in_map)
00184 {
00185     mapstruct *map;
00186     object *first, *second, *third, *floor , *got;
00187 
00188     map = get_empty_map(5, 5);
00189     fail_if(map == NULL, "get_empty_map() returned NULL.");
00190 
00191     /* First, simple tests for insertion. */
00192     floor = get_archetype("water_still");
00193     floor->x = 3;
00194     floor->y = 3;
00195     got = insert_ob_in_map(floor, map, NULL, 0);
00196     fail_if(got != floor, "Water flood shouldn't disappear.");
00197     fail_if(floor != GET_MAP_OB(map, 3, 3), "Water floor should be first object.");
00198 
00199     first = get_archetype("letter");
00200     first->x = 3;
00201     first->y = 3;
00202     got = insert_ob_in_map(first, map, NULL, 0);
00203     fail_if(got != first, "Letter shouldn't disappear.");
00204     fail_if(floor != GET_MAP_OB(map, 3, 3), "Water floor should still be first object.");
00205     fail_if(floor->above != first, "Letter should be above floor.");
00206 
00207     second = get_archetype("bolt");
00208     second->nrof = 1;
00209     second->x = 3;
00210     second->y = 3;
00211     got = insert_ob_in_map(second, map, NULL, 0);
00212     fail_if(got != second, "Bolt shouldn't disappear.");
00213     fail_if(floor != GET_MAP_OB(map, 3, 3), "Water floor should still be first object.");
00214     fail_if(floor->above != second, "Bolt should be above floor.");
00215     fail_if(second->above != first, "Letter should be above bolt.");
00216 
00217     /* Merging tests. */
00218     third = get_archetype("bolt");
00219     third->nrof = 1;
00220     third->x = 3;
00221     third->y = 3;
00222     got = insert_ob_in_map(third, map, NULL, 0);
00223     fail_if(got != third, "Bolt shouldn't disappear.");
00224     fail_if(OBJECT_FREE(second), "First bolt should have been removed.");
00225     fail_if(third->nrof != 2, "Second bolt should have nrof 2.");
00226 
00227     second = get_archetype("bolt");
00228     second->nrof = 1;
00229     second->x = 3;
00230     second->y = 3;
00231     second->value = 1;
00232     got = insert_ob_in_map(second, map, NULL, 0);
00233     fail_if(got != second, "Modified bolt shouldn't disappear.");
00234     fail_if(second->nrof != 1, "Modified bolt should have nrof 1.");
00235 }
00236 END_TEST
00237 
00238 START_TEST(test_get_split_ob)
00239 {
00240     object *first, *second;
00241     char err[50];
00242 
00243     first = get_archetype("sack");
00244     first->nrof = 5;
00245 
00246     second = get_split_ob(first, 2, err, sizeof(err));
00247     fail_if(second == NULL, "Should return an item.");
00248     fail_if(second->nrof != 2, "2 expected to split.");
00249     fail_if(first->nrof != 3, "3 should be left.");
00250 
00251     second = get_split_ob(first, 3, err, sizeof(err));
00252     fail_if(second == NULL, "Should return an item.");
00253 
00254     first = get_split_ob(second, 10, err, sizeof(err));
00255     fail_if(first != NULL, "Should return NULL.");
00256     fail_if(second->nrof != 3, "3 should be left.");
00257 }
00258 END_TEST
00259 
00260 START_TEST(test_decrease_ob_nr)
00261 {
00262     object *first, *second;
00263 
00264     first = get_archetype("bolt");
00265     first->nrof = 5;
00266 
00267     second = decrease_ob_nr(first, 3);
00268     fail_if(second != first, "Bolt shouldn't be destroyed.");
00269 
00270     second = decrease_ob_nr(first, 2);
00271     fail_if(second != NULL, "object_decrease_nrof should return NULL");
00272 }
00273 END_TEST
00274 
00275 START_TEST(test_insert_ob_in_ob)
00276 {
00277     object *container, *item;
00278 
00279     item = get_archetype("bolt");
00280     item->weight = 50;
00281 
00282     container = get_archetype("sack");
00283     insert_ob_in_ob(item, container);
00284     fail_if(container->inv != item, "Item not inserted.");
00285     fail_if(container->carrying != 50, "Container should carry 50 and not %d.", container->carrying);
00286 
00287     remove_ob(item);
00288     fail_if(container->carrying != 0, "Container should carry 0 and not %d.", container->carrying);
00289 
00290     /* 50% weight reduction. */
00291     container->weapon_speed = 0.5f;
00292 
00293     insert_ob_in_ob(item, container);
00294     fail_if(container->inv != item, "Item not inserted.");
00295     fail_if(container->carrying != 25, "Container should carry 25 and not %d.", container->carrying);
00296 }
00297 END_TEST
00298 
00299 START_TEST(test_can_pick)
00300 {
00301     object *pl, *ob;
00302 
00303     pl = get_archetype("raas");
00304     pl->type = PLAYER;
00305     CLEAR_FLAG(pl, FLAG_SEE_INVISIBLE);
00306 
00307     ob = get_archetype("sack");
00308     fail_if(can_pick(pl, ob) == 0, "Player cannot pick up normal sack.");
00309     ob->weight = 0;
00310     fail_if(can_pick(pl, ob) == 1, "Player can pick up sack that weighs 0kg.");
00311     ob = get_archetype("sack");
00312     SET_FLAG(ob, FLAG_NO_PICK);
00313     fail_if(can_pick(pl, ob) == 1, "Player can pick up non-pickable sack.");
00314     SET_FLAG(ob, FLAG_UNPAID);
00315     fail_if(can_pick(pl, ob) == 0, "Player cannot pick up clone-shop sack.");
00316     ob = get_archetype("sack");
00317     SET_FLAG(ob, FLAG_IS_INVISIBLE);
00318     fail_if(can_pick(pl, ob) == 1, "Player cannot see invisible but can pick up invisible sack.");
00319     ob = get_archetype("raas");
00320     fail_if(can_pick(pl, ob) == 1, "Player can pick up a monster object.");
00321     ob = get_archetype("beholder_dread");
00322     CLEAR_FLAG(ob, FLAG_ALIVE);
00323     ob->type = MISC_OBJECT;
00324     fail_if(can_pick(pl, ob) == 1, "Player can pick up a multi-arch object.");
00325 }
00326 END_TEST
00327 
00328 START_TEST(test_object_create_clone)
00329 {
00330     object *ob, *clone;
00331 
00332     ob = get_archetype("raas");
00333     insert_ob_in_ob(get_archetype("sack"), ob);
00334     clone = object_create_clone(ob);
00335     fail_if(strcmp(clone->name, ob->name) != 0, "object_create_clone() created an object with name '%s', but it should have been named '%s'.", clone->name, ob->name);
00336     fail_if(clone->inv == NULL, "object_create_clone() created a clone object with no inventory.");
00337     fail_if(strcmp(clone->inv->name, ob->inv->name) != 0, "Object created using object_create_clone() had object '%s' in inventory, but it should have had '%s' instead.", clone->inv->name, ob->inv->name);
00338 }
00339 END_TEST
00340 
00341 START_TEST(test_was_destroyed)
00342 {
00343     object *ob, *ob2;
00344     tag_t ob_tag, ob2_tag;
00345     mapstruct *m;
00346 
00347     m = get_empty_map(1, 1);
00348 
00349     ob = get_archetype("sack");
00350     ob_tag = ob->count;
00351     insert_ob_in_map(ob, m, ob, 0);
00352     fail_if(was_destroyed(ob, ob_tag) == 1, "was_destroyed() returned 1 but object is still on map.");
00353     ob2 = get_archetype("bolt");
00354     ob2_tag = ob2->count;
00355     insert_ob_in_ob(ob2, ob);
00356     fail_if(was_destroyed(ob2, ob2_tag) == 1, "was_destroyed() returned 1 but object is in inventory of another object.");
00357     SET_FLAG(ob2, FLAG_REMOVED);
00358     fail_if(was_destroyed(ob2, ob2_tag) == 0, "was_destroyed() returned 0 but object had FLAG_REMOVED set.");
00359     CLEAR_FLAG(ob2, FLAG_REMOVED);
00360     remove_ob(ob);
00361     fail_if(was_destroyed(ob, ob_tag) == 0, "was_destroyed() returned 0 but object was removed from map.");
00362     object_gc();
00363     fail_if(was_destroyed(ob, ob_tag) == 0, "was_destroyed() returned 0 but object was freed.");
00364     fail_if(was_destroyed(ob2, ob2_tag) == 0, "was_destroyed() returned 0 but object was freed.");
00365 }
00366 END_TEST
00367 
00368 START_TEST(test_load_object_str)
00369 {
00370     object *ob;
00371 
00372     ob = load_object_str("arch sack\nend\n");
00373     fail_if(ob == NULL, "load_object_str() should not return NULL.");
00374     fail_if(strcmp(ob->arch->name, "sack") != 0, "load_object_str() created object with arch name '%s', but it should have been 'sack'.", ob->arch->name);
00375 
00376     ob = load_object_str("arch sack\nname magic sack\nweight 129\nend\n");
00377     fail_if(ob == NULL, "load_object_str() should not return NULL.");
00378     fail_if(strcmp(ob->name, "magic sack") != 0, "load_object_str() created object with name '%s', but name should have been 'magic sack'.", ob->name);
00379     fail_if(ob->weight != 129, "load_object_str() created object with weight %d, but it should have had 129 weight.", ob->weight);
00380 }
00381 END_TEST
00382 
00383 static Suite *object_suite()
00384 {
00385     Suite *s = suite_create("object");
00386     TCase *tc_core = tcase_create("Core");
00387 
00388     tcase_add_checked_fixture(tc_core, NULL, NULL);
00389 
00390     suite_add_tcase(s, tc_core);
00391     tcase_add_test(tc_core, test_CAN_MERGE);
00392     tcase_add_test(tc_core, test_sum_weight);
00393     tcase_add_test(tc_core, test_add_weight);
00394     tcase_add_test(tc_core, test_sub_weight);
00395     tcase_add_test(tc_core, test_get_env_recursive);
00396     tcase_add_test(tc_core, test_is_player_inv);
00397     tcase_add_test(tc_core, test_dump_object);
00398     tcase_add_test(tc_core, test_insert_ob_in_map);
00399     tcase_add_test(tc_core, test_get_split_ob);
00400     tcase_add_test(tc_core, test_decrease_ob_nr);
00401     tcase_add_test(tc_core, test_insert_ob_in_ob);
00402     tcase_add_test(tc_core, test_can_pick);
00403     tcase_add_test(tc_core, test_object_create_clone);
00404     tcase_add_test(tc_core, test_was_destroyed);
00405     tcase_add_test(tc_core, test_load_object_str);
00406 
00407     return s;
00408 }
00409 
00410 void check_server_object()
00411 {
00412     Suite *s = object_suite();
00413     SRunner *sr = srunner_create(s);
00414 
00415     srunner_set_xml(sr, "unit/server/object.xml");
00416     srunner_set_log(sr, "unit/server/object.out");
00417     srunner_run_all(sr, CK_ENV);
00418     srunner_ntests_failed(sr);
00419     srunner_free(sr);
00420 }