Crossfire Server, Trunk
check_account.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_check_account_c =
3  * "$Id: check_account.c 11817 2009-06-12 15:46:56Z akirschbaum $";
4  */
5 
6 /*
7  * CrossFire, A Multiplayer game for X-windows
8  *
9  * Copyright (C) 2010 Mark Wedel & Crossfire Development Team
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  * The authors can be reached via e-mail at crossfire-devel@real-time.com
26  */
27 
28 /*
29  * This is the unit tests file for server/account.c
30  */
31 
32 #include <global.h>
33 #include <stdlib.h>
34 #include <check.h>
35 #include <loader.h>
36 #include <toolkit_common.h>
37 #include <sproto.h>
38 #include <unistd.h>
39 #include <toolkit_server.h>
40 
41 static void setup(void) {
42 }
43 
44 static void teardown(void) {
45  /* put any cleanup steps here, they will be run after each testcase */
46 }
47 
48 
49 /* This test makes sure account_check_string() behaves as expected -
50  * rejects strings with bad characters in them, etc.
51  */
52 START_TEST(test_account_check_string) {
53  char longname[MAX_NAME+3];
54  int i;
55 
56  i=account_check_string(" abcd");
57  fail_unless(i != 0, "string started with spaces should not be considered valid");
58  /* We test one string with colon at end, other starting with semicolon -
59  * in that way, we also do some basic testing to make sure entire string is being checked.
60  */
61  i=account_check_string("abcd:");
62  fail_unless(i != 0, "string with colons should not be considered valid");
63  i=account_check_string("a;bcd");
64  fail_unless(i != 0, "string with semicolons should not be considered valid");
65  i=account_check_string("a/bcd");
66  fail_unless(i != 0, "string with slash should not be considered valid");
67  i=account_check_string("a'bcd");
68  fail_unless(i != 0, "string with quote should not be considered valid");
69 
70  i=account_check_string("abc\n\nefg");
71  fail_unless(i != 0, "string with non printable characters should not be considered valid");
72 
73  i=account_check_string("$abc");
74  fail_unless(i != 0, "string starting with non alphanumeric should not be considered valid");
75 
76  i=account_check_string("abc ");
77  fail_unless(i != 0, "string ending in space should not be considered valid");
78 
79  for (i=0; i<=MAX_NAME; i++) {
80  longname[i]='a';
81  }
82  longname[i]='\0';
83  i=account_check_string(longname);
84 
85  fail_unless(i != 0, "Too long string should not be considered valid");
86 
87  i=account_check_string("Some Body");
88  fail_unless(i == 0, "Valid string not considered valid");
89 
90 }
91 END_TEST
92 
93 /* This test tries to add some accounts. As a final action, we try
94  * to save the account file out.
95  */
96 START_TEST(test_account_add_account) {
97  int i,j;
98  char names[50];
99  char **char_names;
100 
101  /* Note that we run explicit checks for valid account names/passwords.
102  * As such, the focus here is not checking valid strings again, but checking
103  * duplicate account names, saving them out, etc.
104  */
105  i=account_new("Some Body", "mypassword");
106  fail_unless(i == 0, "Could not add valid account, got code %d", i);
107 
108  i=account_new("Some Body", "mypassword");
109  fail_unless(i != 0, "Duplicate account successfully added");
110 
111  /* This is mainly here to have 2 valid accounts */
112  i=account_new("No Body", "mypassword");
113  fail_unless(i == 0, "Could not add valid account, got code %d", i);
114 
115  /* This third account is to have one with no players associated to it */
116  i=account_new("Every Body", "hispassword");
117  fail_unless(i == 0, "Could not add valid account");
118 
119  i=account_link("foobar", "foobar");
120  fail_unless(i != 0, "Added player to non existent character name");
121 
122  i=account_link("Some Body", "foobar");
123  fail_unless(i == 0, "Failed to add player to valid account");
124 
125  for (j=0; j<30; j++) {
126  sprintf(names,"char-%02d", j);
127  account_link("No Body", names);
128  }
129 
130  char_names = account_get_players_for_account("foobar");
131  fail_unless(char_names == NULL, "Got non null value for players on account with non existant accoun");
132 
133  char_names = account_get_players_for_account("No Body");
134  fail_unless(char_names != NULL, "Got null value for players on account");
135 
136  /* No return value here */
137  accounts_save();
138 }
139 END_TEST
140 
141 /* This tests the load logic. Since the only data were are loading is the data from above,
142  * we use that knowledge to check for proper existence accounts, etc.
143  */
144 START_TEST(test_account_load_entries) {
145  int i,j;
146  char **char_names;
147  const char *ae;
148 
149  accounts_clear();
150  accounts_load();
151 
152  ae = account_exists("Every Body");
153  fail_unless(ae != NULL, "Could not find valid account");
154  ae = account_exists("Some Body");
155  fail_unless(ae != NULL, "Could not find valid account");
156 
157  char_names = account_get_players_for_account("No Body");
158  fail_unless(char_names != NULL, "Got null value for players on account");
159 
160  /* This is sort of data integrity testing - if char_names is not properly
161  * null terminated, with will fail. if char_names[] is corrupt, it should also
162  * core.
163  */
164  i=0;
165  while (char_names[i] != NULL) {
166  j=strlen(char_names[i]);
167  i++;
168  }
169  char_names = account_get_players_for_account("Some Body");
170  fail_unless(char_names != NULL, "Got null value for players on account");
171  fail_unless(strcmp(char_names[0],"foobar") == 0, "Can not match on name we put in");
172 
173  /* while we do this same check in test_account_add_account, doing it
174  * again here makes sure the code is properly detecting the end of the accounts
175  * list after loading it up.
176  */
177  char_names = account_get_players_for_account("foobar");
178  fail_unless(char_names == NULL, "Got non null value for players on account with non existant account");
179 
180  i = account_remove_player("foobar", "1foobar");
181  fail_unless(i!=0, "Got successsful return code on account_remove_player_from_account with non existent account");
182 
183  i = account_remove_player("No Body", "1foobar");
184  fail_unless(i!=0, "Got successsful return code on account_remove_player_from_account with non existent player");
185 
186  char_names = account_get_players_for_account("No Body");
187  j=0;
188  while (char_names[j] != NULL) {
189  j++;
190  }
191 
192  i = account_remove_player("No Body", "char-01");
193  fail_unless(i==0, "Got error removing player when it should have worked");
194 
195  char_names = account_get_players_for_account("No Body");
196 
197  i=0;
198  while (char_names[i] != NULL) {
199  i++;
200  }
201  fail_unless((i+1) == j, "Player removal get unexpected result - %d != %d", i+1, j);
202 }
203 END_TEST
204 
205 static Suite *account_suite(void) {
206  Suite *s = suite_create("account");
207  TCase *tc_core = tcase_create("Core");
208 
209  /*setup and teardown will be called before each test in testcase 'tc_core' */
210  tcase_add_checked_fixture(tc_core, setup, teardown);
211 
212  suite_add_tcase(s, tc_core);
213  tcase_add_test(tc_core, test_account_check_string);
214  tcase_add_test(tc_core, test_account_add_account);
215  tcase_add_test(tc_core, test_account_load_entries);
216 
217  return s;
218 }
219 
220 int main(void) {
221  int nf;
222  Suite *s = account_suite();
223  SRunner *sr = srunner_create(s);
224 
225  /* If you wish to debug the program, uncomment this line. */
226  /*srunner_set_fork_status (sr, CK_NOFORK);*/
227 
228  settings.debug = 0;
229  /* Not sure if there is a better place to put this file - basically,
230  * the account code usings the localdir to determine where to read/write
231  * the accounts file from - we don't want to be altering the real version of
232  * that file.
233  */
234  settings.localdir = strdup_local("/tmp/");
235  cctk_setdatadir(SOURCE_ROOT "lib");
237  init(0, NULL);
238 
239  srunner_set_xml(sr, LOGDIR "/unit/server/account.xml");
240  srunner_set_log(sr, LOGDIR "/unit/server/account.out");
241  srunner_run_all(sr, CK_ENV); /*verbosity from env variable*/
242  nf = srunner_ntests_failed(sr);
243  srunner_free(sr);
245  return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
246 }
global.h
strdup_local
#define strdup_local
Definition: compat.h:29
cctk_setdatadir
void cctk_setdatadir(const char *datadir)
Definition: toolkit_common.c:69
account_get_players_for_account
char ** account_get_players_for_account(const char *account_name)
Definition: account.c:525
accounts_save
void accounts_save(void)
Definition: account.c:260
account_link
int account_link(const char *account_name, const char *player_name)
Definition: account.c:447
toolkit_server.h
settings
struct Settings settings
Definition: init.c:39
toolkit_common.h
Settings::debug
LogLevel debug
Definition: global.h:239
account_remove_player
int account_remove_player(const char *account_name, const char *player_name)
Definition: account.c:479
setup
static void setup(void)
Definition: check_account.c:41
clean_test_account_data
void clean_test_account_data(void)
Definition: toolkit_server.c:5
MAX_NAME
#define MAX_NAME
Definition: define.h:41
account_new
int account_new(const char *account_name, const char *account_password)
Definition: account.c:401
sproto.h
START_TEST
START_TEST(test_account_check_string)
Definition: check_account.c:52
accounts_clear
void accounts_clear(void)
Definition: account.c:148
accounts_load
void accounts_load(void)
Definition: account.c:157
main
int main(void)
Definition: check_account.c:220
guildbuy.names
list names
Definition: guildbuy.py:18
account_suite
static END_TEST Suite * account_suite(void)
Definition: check_account.c:205
init
void init(int argc, char **argv)
Definition: init.c:1108
loader.h
account_check_string
int account_check_string(const char *str)
Definition: account.c:362
account_exists
const char * account_exists(const char *account_name)
Definition: account.c:302
teardown
static void teardown(void)
Definition: check_account.c:44
Settings::localdir
const char * localdir
Definition: global.h:244