Crossfire Server, Trunk
check_account_char.cpp
Go to the documentation of this file.
1 /*
2  * This is the unit tests file for server/account.c
3  */
4 
5 #include "global.h"
6 
7 #include <check.h>
8 #include <stdlib.h>
9 #include <sys/stat.h>
10 
11 #include "account_char.h"
12 #include "loader.h"
13 #include "sproto.h"
14 #include "toolkit_common.h"
15 #include "toolkit_server.h"
16 
17 static void setup(void) {
18 }
19 
20 static void teardown(void) {
21  /* put any cleanup steps here, they will be run after each testcase */
22 }
23 
24 
25 
26 /* This test tries to add some accounts. As a final action, we try
27  * to save the account file out.
28  */
29 START_TEST(test_account_char_add) {
30  player *pl;
31  Account_Chars *chars;
32  char path[MAX_BUF];
33 
34  pl = static_cast<player *>(calloc(1, sizeof(player)));
35  chars = account_char_load("testaccount");
36 
37  /* The account_character code takes a player structure to
38  * fill in the values, so we create a fake one here -
39  * we just fill in the fields that are used.
40  */
41  pl->ob = create_archetype("human_player");
42  pl->ob->level = 1;
43  pl->ob->name = add_string("test character");
44  pl->ob->contr = pl;
45  strcpy(pl->maplevel, "test map");
46 
47  account_char_add(chars, pl);
48  fail_unless(chars->chars.size() == 1, "account_char_add returned empty list on initial character");
49 
50  pl->ob->level = 2;
51  account_char_add(chars, pl);
52  fail_unless(chars->chars.size() == 1, "account_char_add didn't on update character");
53 
54  account_char_remove(chars, pl->ob->name);
55  fail_unless(chars->chars.empty(), "account_char_remove returned non empty list on final character removal");
56 
57  account_char_add(chars, pl);
58  fail_unless(chars->chars.size() == 1, "account_char_add didn't insert initial character");
59 
60  pl->ob->name = add_string("char 2");
61  pl->party = party_form(pl->ob, "rockon");
62 
63  account_char_add(chars, pl);
64  fail_unless(chars->chars.size() == 2, "account_char_add didn't add character");
65 
66  sprintf(path,"%s/account", settings.localdir);
67  mkdir(path, S_IRWXU);
68 
69  /* This does not return anything, but this at least checks for
70  * core dumps, etc
71  */
72  account_char_save(chars);
73 
74  /* Like above, this returns nothing but does check for core dumps */
75  account_char_free(chars);
76 }
77 END_TEST
78 
79 /* This tests the load logic. Since the only data were are loading is the data from above,
80  * we use that knowledge to check for proper existence accounts, etc.
81  */
82 START_TEST(test_account_char_load) {
83  Account_Chars *chars;
84  object *ob = create_archetype("human_player");
85 
86  chars = account_char_load("testaccount");
87  fail_unless(chars != NULL, "account_char_load returned NULL");
88  fail_unless(chars->chars.size() == 2, "account_char_load didn't load the file");
89 
90  /* As of now, the account order is in FIFO order */
91 
92  fail_unless(!strcmp(chars->chars[0]->name, "test character"),
93  "Name for first character is not test char");
94 
95  fail_unless(!strcmp(chars->chars[0]->race, ob->race),
96  "Race for first character does not match");
97 
98  fail_unless(chars->chars[0]->level == 2,
99  "Level for first character is not 2");
100 
101  fail_unless(!strcmp(chars->chars[0]->face, ob->face->name),
102  "Face for first character does not match");
103 
104  fail_unless(chars->chars[0]->party[0] == 0,
105  "Party for first character is not blank");
106 
107  fail_unless(!strcmp(chars->chars[0]->map, "test map"),
108  "Map for first character does not match");
109 
110  /* The presumption here is that if it loaded the first entry
111  * successfully, so it should the second, but we do check for the fields
112  * which are different.
113  */
114 
115  fail_unless(!strcmp(chars->chars[1]->name, "char 2"),
116  "Name for second character does not match");
117 
118  fail_unless(!strcmp(chars->chars[1]->party, "rockon"),
119  "Party for second character does not match");
120 
121  account_char_free(chars);
122 }
123 
124 END_TEST
125 
126 START_TEST(test_account_char_load_duplicate) {
127  Account_Chars *first, *second;
128 
129  first = account_char_load("dummy");
130  second = account_char_load("dummy");
131  fail_unless(first == second, "account_char_load should return the same structure for the same name");
132 
134  account_char_free(second);
135 }
136 END_TEST
137 
138 static Suite *account_suite(void) {
139  Suite *s = suite_create("account_char");
140  TCase *tc_core = tcase_create("Core");
141 
142  /*setup and teardown will be called before each test in testcase 'tc_core' */
143  tcase_add_checked_fixture(tc_core, setup, teardown);
144 
145  suite_add_tcase(s, tc_core);
146  tcase_add_test(tc_core, test_account_char_add);
147  tcase_add_test(tc_core, test_account_char_load);
148  tcase_add_test(tc_core, test_account_char_load_duplicate);
149 
150  return s;
151 }
152 
153 int main(void) {
154  int nf;
155  Suite *s = account_suite();
156  SRunner *sr = srunner_create(s);
157 
158  /* If you wish to debug the program, uncomment this line. */
159  /*srunner_set_fork_status (sr, CK_NOFORK);*/
160 
162  /* Not sure if there is a better place to put this file - basically,
163  * the account code usings the localdir to determine where to read/write
164  * the accounts file from - we don't want to be altering the real version of
165  * that file.
166  */
167  settings.localdir = strdup_local("/tmp/");
168  cctk_setdatadir(SOURCE_ROOT "lib");
170  init(0, NULL);
171 
172  srunner_set_xml(sr, LOGDIR "/unit/server/account_char.xml");
173  srunner_set_log(sr, LOGDIR "/unit/server/account_char.out");
174  srunner_run_all(sr, CK_ENV); /*verbosity from env variable*/
175  nf = srunner_ntests_failed(sr);
176  srunner_free(sr);
177 
179  return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
180 }
global.h
settings
struct Settings settings
Definition: init.cpp:139
llevError
@ llevError
Definition: logger.h:11
player
Definition: player.h:105
strdup_local
#define strdup_local
Definition: compat.h:29
cctk_setdatadir
void cctk_setdatadir(const char *datadir)
Definition: toolkit_common.cpp:69
Settings::debug
LogLevel debug
Definition: global.h:243
Account_Chars
Definition: account_char.h:27
guildjoin.ob
ob
Definition: guildjoin.py:42
Settings::localdir
const char * localdir
Definition: global.h:249
toolkit_server.h
account_suite
static END_TEST Suite * account_suite(void)
Definition: check_account_char.cpp:138
setup
static void setup(void)
Definition: check_account_char.cpp:17
toolkit_common.h
account_char_free
void account_char_free(Account_Chars *chars)
Definition: account_char.cpp:345
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
clean_test_account_data
void clean_test_account_data(void)
Definition: toolkit_server.cpp:5
init
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin it tries to load all available files in the SHARE plugins directory as plugin libraries It first displays the Initializing the plugin has the opportunity to signal itself by a message on the console Then the server displays an informative message containing both the plugin content and its keyword For the Python the standard load process thus GreenGoblin When a plugin has been it can request to be warned whenever a global event and are named freely by the developer If the directory doesn t nothing will happen< event name > can be init
Definition: plugins.txt:54
sproto.h
START_TEST
START_TEST(test_account_char_add)
Definition: check_account_char.cpp:29
party_form
partylist * party_form(object *op, const char *partyname)
Definition: party.cpp:40
MAX_BUF
#define MAX_BUF
Definition: define.h:35
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
path
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin path(SHARE/plugins). Console messages. ----------------- When Crossfire starts
main
int main(void)
Definition: check_account_char.cpp:153
Account_Chars::chars
std::vector< Account_Char * > chars
Definition: account_char.h:30
account_char_add
void account_char_add(Account_Chars *chars, player *pl)
Definition: account_char.cpp:207
loader.h
account_char.h
first
Crossfire Protocol most of the time after the actual code was already omit certain important and possibly make life miserable any new developer or curious player should be able to find most of the relevant information here If inconsistencies are found or this documentation proves to be consider the latest server side protocol code in the public source code repository as the authoritative reference Introduction If you were ever curious enough to telnet or netcat to a Crossfire chances are you were sorely disappointed While the protocol may seem to use plain text at first
Definition: protocol.txt:20
account_char_load
Account_Chars * account_char_load(const char *account_name)
Definition: account_char.cpp:135
account_char_save
void account_char_save(Account_Chars *chars)
Definition: account_char.cpp:158
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
teardown
static void teardown(void)
Definition: check_account_char.cpp:20
account_char_remove
void account_char_remove(Account_Chars *chars, const char *pl_name)
Definition: account_char.cpp:313