1 // Eris Online RPG Protocol Library
2 // Copyright (C) 2007 Alistair Riddoch
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software Foundation,
16 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18 // $Id$
19
20 #ifdef NDEBUG
21 #undef NDEBUG
22 #endif
23 #ifndef DEBUG
24 #define DEBUG
25 #endif
26
27 #include <Eris/Account.h>
28
29 #include <Eris/Connection.h>
30 #include <Eris/Avatar.h>
31 #include <Eris/Exceptions.h>
32 #include <Eris/Log.h>
33 #include <Eris/SpawnPoint.h>
34 #include <Eris/CharacterType.h>
35
36 #include "SignalFlagger.h"
37
38 #include <Atlas/Objects/Anonymous.h>
39 #include <Atlas/Objects/Entity.h>
40 #include <Atlas/Objects/Operation.h>
41
42 #include <sigc++/adaptors/hide.h>
43
44 #include <iostream>
45
46 class TestConnection : public Eris::Connection {
47 public:
TestConnection(const std::string & name,const std::string & host,short port,bool debug)48 TestConnection(const std::string & name, const std::string & host,
49 short port, bool debug) :
50 Eris::Connection(name, host, port, debug) { }
51
test_setStatus(Eris::BaseConnection::Status sc)52 void test_setStatus(Eris::BaseConnection::Status sc) {
53 setStatus(sc);
54 }
55
send(const Atlas::Objects::Root & obj)56 virtual void send(const Atlas::Objects::Root &obj) {
57 std::cout << "Sending " << obj->getParents().front()
58 << std::endl << std::flush;
59 }
60 };
61
62 class TestAccount : public Eris::Account {
63 public:
TestAccount(Eris::Connection * con)64 TestAccount(Eris::Connection * con) : Eris::Account(con) { }
65
setup_setStatus(Eris::Account::Status s)66 void setup_setStatus(Eris::Account::Status s) {
67 m_status = s;
68 }
69
setup_setDoingCharacterRefresh(bool f)70 void setup_setDoingCharacterRefresh(bool f) {
71 m_doingCharacterRefresh = f;
72 }
73
setup_fakeCharacter(const std::string & id)74 void setup_fakeCharacter(const std::string & id) {
75 m_characterIds.insert(id);
76 }
77
setup_insertActiveCharacters(Eris::Avatar * ea)78 void setup_insertActiveCharacters(Eris::Avatar * ea) {
79 m_activeCharacters.insert(std::make_pair(ea->getId(), ea));
80 }
81
setup_setUsername(const std::string & u)82 void setup_setUsername(const std::string & u) {
83 m_username = u;
84 }
85
setup_setPassword(const std::string & p)86 void setup_setPassword(const std::string & p) {
87 m_pass = p;
88 }
89
query_getStatus() const90 Eris::Account::Status query_getStatus() const {
91 return m_status;
92 }
93
test_logoutResponse(const Atlas::Objects::Operation::RootOperation & op)94 void test_logoutResponse(const Atlas::Objects::Operation::RootOperation& op) {
95 logoutResponse(op);
96 }
97
test_loginComplete(const Atlas::Objects::Entity::Account & p)98 void test_loginComplete(const Atlas::Objects::Entity::Account &p) {
99 loginComplete(p);
100 }
101
test_updateFromObject(const Atlas::Objects::Entity::Account & p)102 void test_updateFromObject(const Atlas::Objects::Entity::Account &p) {
103 updateFromObject(p);
104 }
105
test_loginError(const Atlas::Objects::Operation::Error & err)106 void test_loginError(const Atlas::Objects::Operation::Error& err) {
107 loginError(err);
108 }
109
test_handleLoginTimeout()110 void test_handleLoginTimeout() {
111 handleLoginTimeout();
112 }
113
test_avatarResponse(const Atlas::Objects::Operation::RootOperation & op)114 void test_avatarResponse(const Atlas::Objects::Operation::RootOperation& op) {
115 avatarResponse(op);
116 }
117
test_internalDeactivateCharacter(Eris::Avatar * ea)118 void test_internalDeactivateCharacter(Eris::Avatar * ea) {
119 internalDeactivateCharacter(ea);
120 }
121
test_sightCharacter(const Atlas::Objects::Operation::RootOperation & op)122 void test_sightCharacter(const Atlas::Objects::Operation::RootOperation& op) {
123 sightCharacter(op);
124 }
125
test_netConnected()126 void test_netConnected() {
127 netConnected();
128 }
129
test_netDisconnecting()130 bool test_netDisconnecting() {
131 return netDisconnecting();
132 }
133
test_netFailure(const std::string & msg)134 void test_netFailure(const std::string & msg) {
135 netFailure(msg);
136 }
137
test_handleLogoutTimeout()138 void test_handleLogoutTimeout() {
139 handleLogoutTimeout();
140 }
141
test_avatarLogoutResponse(const Atlas::Objects::Operation::RootOperation & op)142 void test_avatarLogoutResponse(const Atlas::Objects::Operation::RootOperation& op) {
143 avatarLogoutResponse(op);
144 }
145
test_internalLogin(const std::string & u,const std::string & p)146 Eris::Result test_internalLogin(const std::string & u, const std::string & p) {
147 return internalLogin(u, p);
148 }
149
150 static const Eris::Account::Status DISCONNECTED = Eris::Account::DISCONNECTED;
151 static const Eris::Account::Status LOGGING_IN = Eris::Account::LOGGING_IN;
152 static const Eris::Account::Status LOGGED_IN = Eris::Account::LOGGED_IN;
153 static const Eris::Account::Status LOGGING_OUT = Eris::Account::LOGGING_OUT;
154 static const Eris::Account::Status CREATING_CHAR = Eris::Account::CREATING_CHAR;
155 static const Eris::Account::Status TAKING_CHAR = Eris::Account::TAKING_CHAR;
156 };
157
158 class TestAvatar : public Eris::Avatar {
159 public:
TestAvatar(Eris::Account * ac,const std::string & ent_id)160 TestAvatar(Eris::Account * ac, const std::string & ent_id) :
161 Eris::Avatar(*ac, ent_id) { }
162 };
163
writeLog(Eris::LogLevel,const std::string & msg)164 static void writeLog(Eris::LogLevel, const std::string & msg)
165 {
166 std::cerr << msg << std::endl << std::flush;
167 }
168
main()169 int main()
170 {
171 Eris::Logged.connect(sigc::ptr_fun(writeLog));
172 Eris::setLogLevel(Eris::LOG_DEBUG);
173
174 // Test constructor
175 {
176 Eris::Connection * con = new Eris::Connection("name", "localhost",
177 6767, true);
178
179 Eris::Account acc(con);
180 }
181 // Test constructor throws on a null connection.
182 {
183 try {
184 Eris::Account acc(0);
185 abort();
186 }
187 catch (Eris::InvalidOperation & eio) {
188 }
189 }
190 // Test getActiveCharacters()
191 {
192 Eris::Connection * con = new Eris::Connection("name", "localhost",
193 6767, true);
194
195 Eris::Account acc(con);
196
197 const Eris::ActiveCharacterMap & acm = acc.getActiveCharacters();
198
199 assert(acm.empty());
200 }
201 // Test getId()
202 {
203 Eris::Connection * con = new Eris::Connection("name", "localhost",
204 6767, true);
205
206 Eris::Account acc(con);
207
208 const std::string & id = acc.getId();
209
210 assert(id.empty());
211 }
212 // Test getUsername()
213 {
214 Eris::Connection * con = new Eris::Connection("name", "localhost",
215 6767, true);
216
217 Eris::Account acc(con);
218
219 const std::string & username = acc.getUsername();
220
221 assert(username.empty());
222 }
223
224 // Test getConnection()
225 {
226 Eris::Connection * con = new Eris::Connection("name", "localhost",
227 6767, true);
228
229 Eris::Account acc(con);
230
231 Eris::Connection * got_con = acc.getConnection();
232
233 assert(got_con == con);
234 }
235
236 // Test login() fails if not connected
237 {
238 TestConnection * con = new TestConnection("name", "localhost",
239 6767, true);
240
241 Eris::Account acc(con);
242
243 Eris::Result res = acc.login("foo", "bar");
244 assert(res == Eris::NOT_CONNECTED);
245 }
246
247 // Test login() fails if we fake connected and logged in
248 {
249 TestConnection * con = new TestConnection("name", "localhost",
250 6767, true);
251
252 TestAccount acc(con);
253
254 con->test_setStatus(Eris::BaseConnection::CONNECTED);
255 acc.setup_setStatus(TestAccount::LOGGING_IN);
256
257 Eris::Result res = acc.login("foo", "bar");
258 assert(res == Eris::ALREADY_LOGGED_IN);
259 }
260
261 // Test login() works if we fake connected
262 {
263 TestConnection * con = new TestConnection("name", "localhost",
264 6767, true);
265
266 TestAccount acc(con);
267
268 con->test_setStatus(Eris::BaseConnection::CONNECTED);
269
270 Eris::Result res = acc.login("foo", "bar");
271 assert(res == Eris::NO_ERR);
272 }
273
274 // Test createAccount() fails if not connected
275 {
276 TestConnection * con = new TestConnection("name", "localhost",
277 6767, true);
278
279 Eris::Account acc(con);
280
281 Eris::Result res = acc.createAccount("foo", "bar", "baz");
282 assert(res == Eris::NOT_CONNECTED);
283 }
284
285 // Test createAccount() works if we fake connected.
286 {
287 TestConnection * con = new TestConnection("name", "localhost",
288 6767, true);
289
290 TestAccount acc(con);
291
292 con->test_setStatus(Eris::BaseConnection::CONNECTED);
293
294 Eris::Result res = acc.createAccount("foo", "bar", "baz");
295 assert(res == Eris::NO_ERR);
296 }
297
298 // Test logout() fails if not connected.
299 {
300 TestConnection * con = new TestConnection("name", "localhost",
301 6767, true);
302
303 TestAccount acc(con);
304
305 Eris::Result res = acc.logout();
306 assert(res == Eris::NOT_CONNECTED);
307 }
308
309 // Test logout() does nothing if we fake connected, and logging out.
310 {
311 TestConnection * con = new TestConnection("name", "localhost",
312 6767, true);
313
314 TestAccount acc(con);
315 con->test_setStatus(Eris::BaseConnection::CONNECTED);
316 acc.setup_setStatus(TestAccount::LOGGING_OUT);
317
318 Eris::Result res = acc.logout();
319 assert(res == Eris::NO_ERR);
320 }
321
322 // Test logout() fails if we are fake connected but not logged in.
323 {
324 TestConnection * con = new TestConnection("name", "localhost",
325 6767, true);
326
327 TestAccount acc(con);
328 con->test_setStatus(Eris::BaseConnection::CONNECTED);
329
330 Eris::Result res = acc.logout();
331 assert(res == Eris::NOT_LOGGED_IN);
332 }
333
334 // Test logout() works if we are fake connected and logged in.
335 {
336 TestConnection * con = new TestConnection("name", "localhost",
337 6767, true);
338
339 TestAccount acc(con);
340 con->test_setStatus(Eris::BaseConnection::CONNECTED);
341 acc.setup_setStatus(TestAccount::LOGGED_IN);
342
343 Eris::Result res = acc.logout();
344 assert(res == Eris::NO_ERR);
345 }
346
347 // Test getCharacters()
348 {
349 TestConnection * con = new TestConnection("name", "localhost",
350 6767, true);
351
352 TestAccount acc(con);
353
354 const Eris::CharacterMap & ecm = acc.getCharacters();
355
356 assert(ecm.empty());
357 }
358
359 // Test refreshCharacterInfo() fails if not connected
360 {
361 TestConnection * con = new TestConnection("name", "localhost",
362 6767, true);
363
364 Eris::Account acc(con);
365
366 Eris::Result res = acc.refreshCharacterInfo();
367 assert(res == Eris::NOT_CONNECTED);
368 }
369
370 // Test refreshCharacterInfo() fails if we fake connected and logging in
371 {
372 TestConnection * con = new TestConnection("name", "localhost",
373 6767, true);
374
375 TestAccount acc(con);
376
377 con->test_setStatus(Eris::BaseConnection::CONNECTED);
378 acc.setup_setStatus(TestAccount::LOGGING_IN);
379
380 Eris::Result res = acc.refreshCharacterInfo();
381 assert(res == Eris::NOT_LOGGED_IN);
382 }
383
384 // Test refreshCharacterInfo() returns if we fake connected and logged in,
385 // and pretend a query is already occuring.
386 {
387 TestConnection * con = new TestConnection("name", "localhost",
388 6767, true);
389
390 TestAccount acc(con);
391
392 con->test_setStatus(Eris::BaseConnection::CONNECTED);
393 acc.setup_setStatus(TestAccount::LOGGED_IN);
394 acc.setup_setDoingCharacterRefresh(true);
395
396 Eris::Result res = acc.refreshCharacterInfo();
397 assert(res == Eris::NO_ERR);
398
399 // Make sure it no longer thinks it is connected, so it does not try
400 // to log out in the destructor.
401 acc.setup_setStatus(TestAccount::LOGGING_OUT);
402 }
403
404 // Test refreshCharacterInfo() returns if we fake connected and logged in,
405 // and have no characters IDs.
406 {
407 TestConnection * con = new TestConnection("name", "localhost",
408 6767, true);
409
410 TestAccount acc(con);
411 SignalFlagger gotAllCharacters_checker;
412
413 con->test_setStatus(Eris::BaseConnection::CONNECTED);
414 acc.setup_setStatus(TestAccount::LOGGED_IN);
415 acc.GotAllCharacters.connect(sigc::mem_fun(gotAllCharacters_checker,
416 &SignalFlagger::set));
417
418 assert(!gotAllCharacters_checker.flagged());
419 Eris::Result res = acc.refreshCharacterInfo();
420 assert(res == Eris::NO_ERR);
421 assert(gotAllCharacters_checker.flagged());
422
423 // Make sure it no longer thinks it is connected, so it does not try
424 // to log out in the destructor.
425 acc.setup_setStatus(TestAccount::LOGGING_OUT);
426 }
427
428 // Test refreshCharacterInfo() works if we fake connected and logged in,
429 // and have characters IDs.
430 {
431 TestConnection * con = new TestConnection("name", "localhost",
432 6767, true);
433
434 TestAccount acc(con);
435 SignalFlagger gotAllCharacters_checker;
436 std::string fake_char_id("1");
437
438 con->test_setStatus(Eris::BaseConnection::CONNECTED);
439 acc.setup_setStatus(TestAccount::LOGGED_IN);
440 acc.GotAllCharacters.connect(sigc::mem_fun(gotAllCharacters_checker,
441 &SignalFlagger::set));
442 acc.setup_fakeCharacter(fake_char_id);
443
444
445 assert(!gotAllCharacters_checker.flagged());
446 Eris::Result res = acc.refreshCharacterInfo();
447 assert(res == Eris::NO_ERR);
448 assert(!gotAllCharacters_checker.flagged());
449
450 // Make sure it no longer thinks it is connected, so it does not try
451 // to log out in the destructor.
452 acc.setup_setStatus(TestAccount::LOGGING_OUT);
453 }
454
455 // Test createCharacter() fails if not connected
456 {
457 TestConnection * con = new TestConnection("name", "localhost",
458 6767, true);
459
460 Eris::Account acc(con);
461 Atlas::Objects::Entity::Anonymous ent;
462
463 Eris::Result res = acc.createCharacter(ent);
464 assert(res == Eris::NOT_CONNECTED);
465 }
466
467 // Test createCharacter() fails if we fake connected and creating char
468 {
469 TestConnection * con = new TestConnection("name", "localhost",
470 6767, true);
471
472 TestAccount acc(con);
473 Atlas::Objects::Entity::Anonymous ent;
474
475 con->test_setStatus(Eris::BaseConnection::CONNECTED);
476 acc.setup_setStatus(TestAccount::CREATING_CHAR);
477
478 Eris::Result res = acc.createCharacter(ent);
479 assert(res == Eris::DUPLICATE_CHAR_ACTIVE);
480
481 // Make sure it no longer thinks it is connected, so it does not try
482 // to log out in the destructor.
483 acc.setup_setStatus(TestAccount::LOGGING_OUT);
484 }
485
486 // Test createCharacter() fails if we fake connected and taking char
487 {
488 TestConnection * con = new TestConnection("name", "localhost",
489 6767, true);
490
491 TestAccount acc(con);
492 Atlas::Objects::Entity::Anonymous ent;
493
494 con->test_setStatus(Eris::BaseConnection::CONNECTED);
495 acc.setup_setStatus(TestAccount::TAKING_CHAR);
496
497 Eris::Result res = acc.createCharacter(ent);
498 assert(res == Eris::DUPLICATE_CHAR_ACTIVE);
499
500 // Make sure it no longer thinks it is connected, so it does not try
501 // to log out in the destructor.
502 acc.setup_setStatus(TestAccount::LOGGING_OUT);
503 }
504
505 // Test createCharacter() fails if we fake connected but not logged in
506 {
507 TestConnection * con = new TestConnection("name", "localhost",
508 6767, true);
509
510 TestAccount acc(con);
511 Atlas::Objects::Entity::Anonymous ent;
512
513 con->test_setStatus(Eris::BaseConnection::CONNECTED);
514 acc.setup_setStatus(TestAccount::LOGGING_IN);
515
516 Eris::Result res = acc.createCharacter(ent);
517 assert(res == Eris::NOT_LOGGED_IN);
518 }
519
520 // Test createCharacter() works if we fake connected and logged in
521 {
522 TestConnection * con = new TestConnection("name", "localhost",
523 6767, true);
524
525 TestAccount acc(con);
526 Atlas::Objects::Entity::Anonymous ent;
527
528 con->test_setStatus(Eris::BaseConnection::CONNECTED);
529 acc.setup_setStatus(TestAccount::LOGGED_IN);
530
531 Eris::Result res = acc.createCharacter(ent);
532 assert(res == Eris::NO_ERR);
533 }
534
535 // Test takeCharacter() fails if ID is not a real character
536 {
537 TestConnection * con = new TestConnection("name", "localhost",
538 6767, true);
539
540 Eris::Account acc(con);
541 std::string fake_char_id("1");
542
543 Eris::Result res = acc.takeCharacter(fake_char_id);
544 assert(res == Eris::BAD_CHARACTER_ID);
545 }
546
547 // Test takeCharacter() fails if not connected
548 {
549 TestConnection * con = new TestConnection("name", "localhost",
550 6767, true);
551
552 TestAccount acc(con);
553 std::string fake_char_id("1");
554
555 acc.setup_fakeCharacter(fake_char_id);
556
557 Eris::Result res = acc.takeCharacter(fake_char_id);
558 assert(res == Eris::NOT_CONNECTED);
559 }
560
561 // Test takeCharacter() fails if we fake connected and logging in
562 {
563 TestConnection * con = new TestConnection("name", "localhost",
564 6767, true);
565
566 TestAccount acc(con);
567 std::string fake_char_id("1");
568
569 con->test_setStatus(Eris::BaseConnection::CONNECTED);
570 acc.setup_setStatus(TestAccount::LOGGING_IN);
571 acc.setup_fakeCharacter(fake_char_id);
572
573 Eris::Result res = acc.takeCharacter(fake_char_id);
574 assert(res == Eris::NOT_LOGGED_IN);
575 }
576
577 // Test takeCharacter() fails if we fake connected and logging in
578 {
579 TestConnection * con = new TestConnection("name", "localhost",
580 6767, true);
581
582 TestAccount acc(con);
583 std::string fake_char_id("1");
584
585 con->test_setStatus(Eris::BaseConnection::CONNECTED);
586 acc.setup_setStatus(TestAccount::CREATING_CHAR);
587 acc.setup_fakeCharacter(fake_char_id);
588
589 Eris::Result res = acc.takeCharacter(fake_char_id);
590 assert(res == Eris::DUPLICATE_CHAR_ACTIVE);
591
592 // Make sure it no longer thinks it is connected, so it does not try
593 // to log out in the destructor.
594 acc.setup_setStatus(TestAccount::LOGGING_OUT);
595 }
596
597 // Test takeCharacter() fails if we fake connected and logging in
598 {
599 TestConnection * con = new TestConnection("name", "localhost",
600 6767, true);
601
602 TestAccount acc(con);
603 std::string fake_char_id("1");
604
605 con->test_setStatus(Eris::BaseConnection::CONNECTED);
606 acc.setup_setStatus(TestAccount::TAKING_CHAR);
607 acc.setup_fakeCharacter(fake_char_id);
608
609 Eris::Result res = acc.takeCharacter(fake_char_id);
610 assert(res == Eris::DUPLICATE_CHAR_ACTIVE);
611
612 // Make sure it no longer thinks it is connected, so it does not try
613 // to log out in the destructor.
614 acc.setup_setStatus(TestAccount::LOGGING_OUT);
615 }
616
617 // Test takeCharacter() works if we fake connected and logged in
618 {
619 TestConnection * con = new TestConnection("name", "localhost",
620 6767, true);
621
622 TestAccount acc(con);
623 std::string fake_char_id("1");
624
625 con->test_setStatus(Eris::BaseConnection::CONNECTED);
626 acc.setup_setStatus(TestAccount::LOGGED_IN);
627 acc.setup_fakeCharacter(fake_char_id);
628
629 Eris::Result res = acc.takeCharacter(fake_char_id);
630 assert(res == Eris::NO_ERR);
631
632 // Make sure it no longer thinks it is connected, so it does not try
633 // to log out in the destructor.
634 acc.setup_setStatus(TestAccount::LOGGING_OUT);
635 }
636
637 // Test deactivateCharacter()
638 {
639 TestConnection * con = new TestConnection("name", "localhost",
640 6767, true);
641
642 TestAccount acc(con);
643 std::string fake_char_id("1");
644 Eris::Avatar * ea = new TestAvatar(&acc, fake_char_id);
645
646 Eris::Result res = acc.deactivateCharacter(ea);
647 assert(res == Eris::NO_ERR);
648 }
649
650 // Test isLoggedIn()
651 {
652 TestConnection * con = new TestConnection("name", "localhost",
653 6767, true);
654
655 TestAccount acc(con);
656
657 assert(!acc.isLoggedIn());
658 }
659
660 // Test isLoggedIn()
661 {
662 TestConnection * con = new TestConnection("name", "localhost",
663 6767, true);
664
665 TestAccount acc(con);
666
667 acc.setup_setStatus(TestAccount::LOGGED_IN);
668
669 assert(acc.isLoggedIn());
670 }
671
672 // Test isLoggedIn()
673 {
674 TestConnection * con = new TestConnection("name", "localhost",
675 6767, true);
676
677 TestAccount acc(con);
678
679 acc.setup_setStatus(TestAccount::TAKING_CHAR);
680
681 assert(acc.isLoggedIn());
682 }
683
684 // Test isLoggedIn()
685 {
686 TestConnection * con = new TestConnection("name", "localhost",
687 6767, true);
688
689 TestAccount acc(con);
690
691 acc.setup_setStatus(TestAccount::CREATING_CHAR);
692
693 assert(acc.isLoggedIn());
694 }
695
696 // Test internalLogin()
697 {
698 TestConnection * con = new TestConnection("name", "localhost",
699 6767, true);
700
701 TestAccount acc(con);
702
703 Eris::Result res = acc.test_internalLogin("foo", "bar");
704
705 assert(res == Eris::NO_ERR);
706 }
707
708 // FIXME Cover logoutResponse once we can fake connections.
709 #if 0
710 // Test logoutResponse() does nothing when given the wrong op.
711 {
712 TestConnection * con = new TestConnection("name", "localhost",
713 6767, true);
714
715 TestAccount acc(con);
716
717 Atlas::Objects::Operation::RootOperation op;
718 acc.test_logoutResponse(op);
719 }
720 #endif
721 // FIXME Cover internalLogout once we can fake connections.
722 // FIXME Cover loginResponse once we can fake connections.
723
724 // Test loginComplete() does nothing when not logged in.
725 {
726 TestConnection * con = new TestConnection("name", "localhost",
727 6767, true);
728
729 TestAccount acc(con);
730 Atlas::Objects::Entity::Account p;
731
732 p->setUsername("bob");
733
734 acc.test_loginComplete(p);
735 }
736
737 // Test loginComplete()
738 {
739 TestConnection * con = new TestConnection("name", "localhost",
740 6767, true);
741
742 TestAccount acc(con);
743 Atlas::Objects::Entity::Account p;
744 SignalFlagger loginSuccess_checker;
745
746 p->setUsername("bob");
747 acc.LoginSuccess.connect(sigc::mem_fun(loginSuccess_checker,
748 &SignalFlagger::set));
749
750 acc.test_loginComplete(p);
751
752 assert(acc.isLoggedIn());
753 assert(loginSuccess_checker.flagged());
754 // FIXME Verify timeout has been cleared?
755 }
756
757 // Test updateFromObject() with a bad character list
758 {
759 TestConnection * con = new TestConnection("name", "localhost",
760 6767, true);
761
762 TestAccount acc(con);
763 Atlas::Objects::Entity::Account p;
764
765 p->setAttr("character_types", "non-list");
766
767 acc.test_updateFromObject(p);
768 }
769
770 // Test updateFromObject() with a character list with something bad in it
771 {
772 TestConnection * con = new TestConnection("name", "localhost",
773 6767, true);
774
775 TestAccount acc(con);
776 Atlas::Objects::Entity::Account p;
777
778 Atlas::Message::ListType character_types;
779 character_types.push_back(1);
780 character_types.push_back("string");
781
782 p->setAttr("character_types", character_types);
783
784 acc.test_updateFromObject(p);
785 assert(acc.getCharacterTypes().size() == 1);
786 assert(acc.getCharacterTypes().front() == "string");
787
788 }
789
790 {
791 TestConnection * con = new TestConnection("name", "localhost",
792 6767, true);
793
794 TestAccount acc(con);
795 Atlas::Objects::Entity::Account p;
796
797 Atlas::Message::ListType spawnPoints;
798 Atlas::Message::MapType spawnPoint1;
799 spawnPoint1["name"] = "spawn1";
800 Atlas::Message::ListType charTypes1;
801 charTypes1.push_back(1);
802 charTypes1.push_back("string");
803 spawnPoint1["character_types"] = charTypes1;
804 spawnPoints.push_back(spawnPoint1);
805 spawnPoints.push_back(Atlas::Message::ListType());
806 p->setAttr("spawns", spawnPoints);
807
808 acc.test_updateFromObject(p);
809 assert(acc.getCharacterTypes().size() == 0);
810 assert(acc.getSpawnPoints().size() == 1);
811 assert(acc.getSpawnPoints().find("spawn1")->second.getAvailableCharacterTypes().size() == 1);
812 assert(acc.getSpawnPoints().find("spawn1")->second.getAvailableCharacterTypes().front().getName() == "string");
813
814 }
815 // Test loginError() with no arg
816 {
817 TestConnection * con = new TestConnection("name", "localhost",
818 6767, true);
819
820 TestAccount acc(con);
821 Atlas::Objects::Operation::Error err;
822
823 acc.test_loginError(err);
824 }
825
826 // Test loginError() with empty arg
827 {
828 TestConnection * con = new TestConnection("name", "localhost",
829 6767, true);
830
831 TestAccount acc(con);
832 Atlas::Objects::Operation::Error err;
833 Atlas::Objects::Root err_arg;
834 err->setArgs1(err_arg);
835
836 acc.test_loginError(err);
837 }
838
839 // Test loginError() with arg that has non-string message
840 {
841 TestConnection * con = new TestConnection("name", "localhost",
842 6767, true);
843
844 TestAccount acc(con);
845 Atlas::Objects::Operation::Error err;
846 Atlas::Objects::Root err_arg;
847 err_arg->setAttr("message", 1);
848 err->setArgs1(err_arg);
849
850 acc.test_loginError(err);
851 }
852
853 // Test loginError() with arg that has non-string message
854 {
855 TestConnection * con = new TestConnection("name", "localhost",
856 6767, true);
857
858 TestAccount acc(con);
859 Atlas::Objects::Operation::Error err;
860 Atlas::Objects::Root err_arg;
861 SignalFlagger loginFailure_checker;
862
863 err_arg->setAttr("message", "Yur loginz, let me show you them.");
864 err->setArgs1(err_arg);
865 acc.LoginFailure.connect(sigc::hide(sigc::mem_fun(loginFailure_checker,
866 &SignalFlagger::set)));
867
868 acc.test_loginError(err);
869
870 assert(loginFailure_checker.flagged());
871 }
872
873 // Test handleLoginTimeout()
874 {
875 TestConnection * con = new TestConnection("name", "localhost",
876 6767, true);
877
878 TestAccount acc(con);
879 SignalFlagger loginFailure_checker;
880
881 acc.LoginFailure.connect(sigc::hide(sigc::mem_fun(loginFailure_checker,
882 &SignalFlagger::set)));
883
884 acc.test_handleLoginTimeout();
885
886 assert(loginFailure_checker.flagged());
887 }
888
889 // Test avatarResponse() Error op
890 {
891 TestConnection * con = new TestConnection("name", "localhost",
892 6767, true);
893
894 TestAccount acc(con);
895 Atlas::Objects::Operation::Error op;
896 SignalFlagger avatarFailure_checker;
897
898 acc.AvatarFailure.connect(sigc::hide(sigc::mem_fun(avatarFailure_checker,
899 &SignalFlagger::set)));
900
901 acc.test_avatarResponse(op);
902 assert(avatarFailure_checker.flagged());
903 assert(acc.query_getStatus() == TestAccount::LOGGED_IN);
904
905 acc.setup_setStatus(TestAccount::DISCONNECTED);
906 }
907
908 // Test avatarResponse() Info op with no arg
909 {
910 TestConnection * con = new TestConnection("name", "localhost",
911 6767, true);
912
913 TestAccount acc(con);
914 Atlas::Objects::Operation::Info op;
915 SignalFlagger avatarSuccess_checker;
916
917 acc.AvatarSuccess.connect(sigc::hide(sigc::mem_fun(avatarSuccess_checker,
918 &SignalFlagger::set)));
919
920 acc.test_avatarResponse(op);
921 assert(!avatarSuccess_checker.flagged());
922 assert(acc.query_getStatus() == TestAccount::DISCONNECTED);
923 }
924
925 // Test avatarResponse() Info op with non-entity arg
926 {
927 TestConnection * con = new TestConnection("name", "localhost",
928 6767, true);
929
930 TestAccount acc(con);
931 Atlas::Objects::Operation::Info op;
932 Atlas::Objects::Root bad_arg;
933 SignalFlagger avatarSuccess_checker;
934
935 op->setArgs1(bad_arg);
936 acc.AvatarSuccess.connect(sigc::hide(sigc::mem_fun(avatarSuccess_checker,
937 &SignalFlagger::set)));
938
939 acc.test_avatarResponse(op);
940 assert(!avatarSuccess_checker.flagged());
941 assert(acc.query_getStatus() == TestAccount::DISCONNECTED);
942 }
943
944 // Test avatarResponse() Info op with entity arg
945 {
946 TestConnection * con = new TestConnection("name", "localhost",
947 6767, true);
948
949 TestAccount acc(con);
950 Atlas::Objects::Operation::Info op;
951 Atlas::Objects::Entity::Anonymous info_arg;
952 SignalFlagger avatarSuccess_checker;
953
954 op->setArgs1(info_arg);
955 acc.AvatarSuccess.connect(sigc::hide(sigc::mem_fun(avatarSuccess_checker,
956 &SignalFlagger::set)));
957
958 acc.test_avatarResponse(op);
959 assert(avatarSuccess_checker.flagged());
960 assert(acc.query_getStatus() == TestAccount::LOGGED_IN);
961
962 acc.setup_setStatus(TestAccount::DISCONNECTED);
963 }
964
965 // Test avatarResponse() Get (not info or error) op with entity arg
966 {
967 TestConnection * con = new TestConnection("name", "localhost",
968 6767, true);
969
970 TestAccount acc(con);
971 Atlas::Objects::Operation::Get op; // Arbitrary not Info or Error
972 Atlas::Objects::Entity::Anonymous info_arg;
973 SignalFlagger avatarSuccess_checker;
974
975 op->setArgs1(info_arg);
976 acc.AvatarSuccess.connect(sigc::hide(sigc::mem_fun(avatarSuccess_checker,
977 &SignalFlagger::set)));
978
979 acc.test_avatarResponse(op);
980 assert(!avatarSuccess_checker.flagged());
981 assert(acc.query_getStatus() == TestAccount::DISCONNECTED);
982 }
983
984 // Test internalDeactivateCharacter() indirectly
985 {
986 TestConnection * con = new TestConnection("name", "localhost",
987 6767, true);
988
989 TestAccount acc(con);
990 std::string fake_char_id("1");
991 Eris::Avatar * ea = new TestAvatar(&acc, fake_char_id);
992
993 acc.setup_insertActiveCharacters(ea);
994
995 assert(!acc.getActiveCharacters().empty());
996
997 // Eris::Avatar destructor calls
998 // Eris::Account::internalDeactivateCharacter
999 delete ea;
1000
1001 assert(acc.getActiveCharacters().empty());
1002 }
1003
1004 // Test internalDeactivateCharacter() directly
1005 {
1006 TestConnection * con = new TestConnection("name", "localhost",
1007 6767, true);
1008
1009 TestAccount acc(con);
1010 std::string fake_char_id("1");
1011 Eris::Avatar * ea = new TestAvatar(&acc, fake_char_id);
1012
1013 acc.setup_insertActiveCharacters(ea);
1014
1015 assert(!acc.getActiveCharacters().empty());
1016
1017 acc.test_internalDeactivateCharacter(ea);
1018
1019 assert(acc.getActiveCharacters().empty());
1020 }
1021
1022 // Test sightCharacter() with empty sight
1023 {
1024 TestConnection * con = new TestConnection("name", "localhost",
1025 6767, true);
1026
1027 TestAccount acc(con);
1028 Atlas::Objects::Operation::Sight sight;
1029 SignalFlagger gotCharacterInfo_checker;
1030
1031 acc.setup_setDoingCharacterRefresh(true);
1032 acc.GotCharacterInfo.connect(sigc::hide(sigc::mem_fun(gotCharacterInfo_checker,
1033 &SignalFlagger::set)));
1034
1035 acc.test_sightCharacter(sight);
1036
1037 assert(!gotCharacterInfo_checker.flagged());
1038 }
1039
1040 // Test sightCharacter() with Sight with bad args
1041 {
1042 TestConnection * con = new TestConnection("name", "localhost",
1043 6767, true);
1044
1045 TestAccount acc(con);
1046 Atlas::Objects::Operation::Sight sight;
1047 Atlas::Objects::Root bad_arg;
1048 SignalFlagger gotCharacterInfo_checker;
1049
1050 acc.setup_setDoingCharacterRefresh(true);
1051 acc.GotCharacterInfo.connect(sigc::hide(sigc::mem_fun(gotCharacterInfo_checker,
1052 &SignalFlagger::set)));
1053 sight->setArgs1(bad_arg);
1054
1055 acc.test_sightCharacter(sight);
1056
1057 assert(!gotCharacterInfo_checker.flagged());
1058 }
1059
1060 // Test sightCharacter() with Sight with valid args
1061 {
1062 TestConnection * con = new TestConnection("name", "localhost",
1063 6767, true);
1064
1065 TestAccount acc(con);
1066 Atlas::Objects::Operation::Sight sight;
1067 Atlas::Objects::Entity::Anonymous sight_arg;
1068 SignalFlagger gotCharacterInfo_checker, gotAllCharacters_checker;
1069
1070 acc.setup_setDoingCharacterRefresh(true);
1071 acc.GotCharacterInfo.connect(sigc::hide(sigc::mem_fun(gotCharacterInfo_checker,
1072 &SignalFlagger::set)));
1073 acc.GotAllCharacters.connect(sigc::mem_fun(gotAllCharacters_checker,
1074 &SignalFlagger::set));
1075 sight->setArgs1(sight_arg);
1076 acc.setup_fakeCharacter("1");
1077
1078 acc.test_sightCharacter(sight);
1079
1080 assert(gotCharacterInfo_checker.flagged());
1081 assert(gotAllCharacters_checker.flagged());
1082 }
1083
1084 // Test sightCharacter() with Sight with valid args, but one character reamining
1085 {
1086 TestConnection * con = new TestConnection("name", "localhost",
1087 6767, true);
1088
1089 TestAccount acc(con);
1090 Atlas::Objects::Operation::Sight sight;
1091 Atlas::Objects::Entity::Anonymous sight_arg;
1092 SignalFlagger gotCharacterInfo_checker, gotAllCharacters_checker;
1093
1094 acc.setup_setDoingCharacterRefresh(true);
1095 acc.GotCharacterInfo.connect(sigc::hide(sigc::mem_fun(gotCharacterInfo_checker,
1096 &SignalFlagger::set)));
1097 acc.GotAllCharacters.connect(sigc::mem_fun(gotAllCharacters_checker,
1098 &SignalFlagger::set));
1099 sight->setArgs1(sight_arg);
1100 acc.setup_fakeCharacter("1");
1101 acc.setup_fakeCharacter("2");
1102
1103 acc.test_sightCharacter(sight);
1104
1105 assert(gotCharacterInfo_checker.flagged());
1106 assert(!gotAllCharacters_checker.flagged());
1107 }
1108
1109 // Test netConnected() Does nothing with an empty password
1110 {
1111 TestConnection * con = new TestConnection("name", "localhost",
1112 6767, true);
1113
1114 TestAccount acc(con);
1115
1116 acc.test_netConnected();
1117 }
1118
1119 // Test netConnected() Does nothing with valid username and password,
1120 // but not DISCONNECTED
1121 {
1122 TestConnection * con = new TestConnection("name", "localhost",
1123 6767, true);
1124
1125 TestAccount acc(con);
1126
1127 acc.setup_setUsername("foo");
1128 acc.setup_setPassword("foo");
1129 acc.setup_setStatus(TestAccount::LOGGING_IN);
1130
1131 acc.test_netConnected();
1132 }
1133
1134 // Test netConnected() works with valid username and password,
1135 {
1136 TestConnection * con = new TestConnection("name", "localhost",
1137 6767, true);
1138
1139 TestAccount acc(con);
1140
1141 acc.setup_setUsername("foo");
1142 acc.setup_setPassword("foo");
1143
1144 acc.test_netConnected();
1145 }
1146
1147 // Test netDisconnecting() when account is not logged in.
1148 {
1149 TestConnection * con = new TestConnection("name", "localhost",
1150 6767, true);
1151
1152 TestAccount acc(con);
1153
1154 bool res = acc.test_netDisconnecting();
1155
1156 assert(res);
1157 }
1158
1159 // Test netDisconnecting() when account is logged in, but connection is
1160 // disconnected.
1161 {
1162 TestConnection * con = new TestConnection("name", "localhost",
1163 6767, true);
1164
1165 TestAccount acc(con);
1166
1167 acc.setup_setStatus(TestAccount::LOGGED_IN);
1168
1169 // The fact that the connection is not really connected will be
1170 // caught in Account::logout() safely.
1171 bool res = acc.test_netDisconnecting();
1172
1173 assert(!res);
1174
1175 acc.setup_setStatus(TestAccount::DISCONNECTED);
1176 }
1177
1178 // Test netFailure()
1179 {
1180 TestConnection * con = new TestConnection("name", "localhost",
1181 6767, true);
1182
1183 TestAccount acc(con);
1184
1185 acc.test_netFailure("foo");
1186 }
1187
1188 // Test handleLogoutTimeout()
1189 {
1190 TestConnection * con = new TestConnection("name", "localhost",
1191 6767, true);
1192
1193 TestAccount acc(con);
1194 SignalFlagger logoutComplete_checker;
1195
1196 acc.setup_setStatus(TestAccount::LOGGED_IN);
1197 acc.LogoutComplete.connect(sigc::hide(sigc::mem_fun(logoutComplete_checker, &SignalFlagger::set)));
1198
1199 acc.test_handleLogoutTimeout();
1200
1201 assert(acc.query_getStatus() == TestAccount::DISCONNECTED);
1202 assert(logoutComplete_checker.flagged());
1203 }
1204
1205 // Test avatarLogoutResponse() with non Info operation
1206 {
1207 TestConnection * con = new TestConnection("name", "localhost",
1208 6767, true);
1209
1210 TestAccount acc(con);
1211 SignalFlagger avatarDeactivated_checker;
1212 Atlas::Objects::Operation::Get op;
1213
1214 acc.AvatarDeactivated.connect(sigc::hide(sigc::mem_fun(avatarDeactivated_checker, &SignalFlagger::set)));
1215
1216 acc.test_avatarLogoutResponse(op);
1217
1218 assert(!avatarDeactivated_checker.flagged());
1219 }
1220
1221 // Test avatarLogoutResponse() with Info operation
1222 {
1223 TestConnection * con = new TestConnection("name", "localhost",
1224 6767, true);
1225
1226 TestAccount acc(con);
1227 SignalFlagger avatarDeactivated_checker;
1228 Atlas::Objects::Operation::Info op;
1229
1230 acc.AvatarDeactivated.connect(sigc::hide(sigc::mem_fun(avatarDeactivated_checker, &SignalFlagger::set)));
1231
1232 acc.test_avatarLogoutResponse(op);
1233
1234 assert(!avatarDeactivated_checker.flagged());
1235 }
1236
1237 // Test avatarLogoutResponse() with Info operation with bad args
1238 {
1239 TestConnection * con = new TestConnection("name", "localhost",
1240 6767, true);
1241
1242 TestAccount acc(con);
1243 SignalFlagger avatarDeactivated_checker;
1244 Atlas::Objects::Operation::Info op;
1245 Atlas::Objects::Root bad_arg;
1246 op->setArgs1(bad_arg);
1247
1248 acc.AvatarDeactivated.connect(sigc::hide(sigc::mem_fun(avatarDeactivated_checker, &SignalFlagger::set)));
1249
1250 acc.test_avatarLogoutResponse(op);
1251
1252 assert(!avatarDeactivated_checker.flagged());
1253 }
1254
1255 // Test avatarLogoutResponse() with Info operation with logout args, which
1256 // have no args
1257 {
1258 TestConnection * con = new TestConnection("name", "localhost",
1259 6767, true);
1260
1261 TestAccount acc(con);
1262 SignalFlagger avatarDeactivated_checker;
1263 Atlas::Objects::Operation::Info op;
1264 Atlas::Objects::Operation::Logout info_arg;
1265
1266 op->setArgs1(info_arg);
1267
1268 acc.AvatarDeactivated.connect(sigc::hide(sigc::mem_fun(avatarDeactivated_checker, &SignalFlagger::set)));
1269
1270 acc.test_avatarLogoutResponse(op);
1271
1272 assert(!avatarDeactivated_checker.flagged());
1273 }
1274
1275 // Test avatarLogoutResponse() with Info operation with completely well
1276 // formed args for an ID which does not exist
1277 {
1278 TestConnection * con = new TestConnection("name", "localhost",
1279 6767, true);
1280
1281 TestAccount acc(con);
1282 SignalFlagger avatarDeactivated_checker;
1283 Atlas::Objects::Operation::Info op;
1284 Atlas::Objects::Operation::Logout info_arg;
1285 Atlas::Objects::Entity::Anonymous logout_arg;
1286 std::string fake_char_id("1");
1287
1288 op->setArgs1(info_arg);
1289 info_arg->setArgs1(logout_arg);
1290 logout_arg->setId(fake_char_id);
1291
1292 acc.AvatarDeactivated.connect(sigc::hide(sigc::mem_fun(avatarDeactivated_checker, &SignalFlagger::set)));
1293
1294 acc.test_avatarLogoutResponse(op);
1295
1296 assert(!avatarDeactivated_checker.flagged());
1297 }
1298
1299 // Test avatarLogoutResponse() with Info operation with completely well
1300 // formed args for an ID which is one of our characters, but not currently
1301 // active
1302 {
1303 TestConnection * con = new TestConnection("name", "localhost",
1304 6767, true);
1305
1306 TestAccount acc(con);
1307 SignalFlagger avatarDeactivated_checker;
1308 Atlas::Objects::Operation::Info op;
1309 Atlas::Objects::Operation::Logout info_arg;
1310 Atlas::Objects::Entity::Anonymous logout_arg;
1311 std::string fake_char_id("1");
1312
1313 op->setArgs1(info_arg);
1314 info_arg->setArgs1(logout_arg);
1315 logout_arg->setId(fake_char_id);
1316 acc.setup_fakeCharacter(fake_char_id);
1317 acc.AvatarDeactivated.connect(sigc::hide(sigc::mem_fun(avatarDeactivated_checker, &SignalFlagger::set)));
1318
1319 acc.test_avatarLogoutResponse(op);
1320
1321 assert(!avatarDeactivated_checker.flagged());
1322 }
1323
1324 // Test avatarLogoutResponse() with Info operation with completely well
1325 // formed args for an ID which is one of our characters, and currently
1326 // active
1327 {
1328 TestConnection * con = new TestConnection("name", "localhost",
1329 6767, true);
1330
1331 TestAccount acc(con);
1332 SignalFlagger avatarDeactivated_checker;
1333 Atlas::Objects::Operation::Info op;
1334 Atlas::Objects::Operation::Logout info_arg;
1335 Atlas::Objects::Entity::Anonymous logout_arg;
1336 std::string fake_char_id("1");
1337 Eris::Avatar * ea = new TestAvatar(&acc, fake_char_id);
1338
1339 op->setArgs1(info_arg);
1340 info_arg->setArgs1(logout_arg);
1341 logout_arg->setId(fake_char_id);
1342 acc.setup_fakeCharacter(fake_char_id);
1343 acc.setup_insertActiveCharacters(ea);
1344 acc.AvatarDeactivated.connect(sigc::hide(sigc::mem_fun(avatarDeactivated_checker, &SignalFlagger::set)));
1345
1346 acc.test_avatarLogoutResponse(op);
1347
1348 assert(avatarDeactivated_checker.flagged());
1349 }
1350
1351
1352 return 0;
1353 }
1354