changeset 107:6f4965c26ceb

Server: add basic accounts tests, #682
author David Demelier <markand@malikania.fr>
date Tue, 05 Sep 2017 13:33:57 +0200
parents f8c6d2244795
children 2562eb64860d
files CMakeLists.txt database/CMakeLists.txt docs/specs/db/account.md libserver-test/CMakeLists.txt libserver-test/malikania/server/account_dao_test.cpp libserver-test/malikania/server/account_dao_test.hpp libserver-test/malikania/server/character_dao_test.cpp libserver-test/malikania/server/character_dao_test.hpp libserver-test/malikania/server/database_test.cpp libserver-test/malikania/server/database_test.hpp libserver-test/malikania/server/db/test_account.cpp libserver-test/malikania/server/db/test_account.hpp libserver-test/malikania/server/db/test_database.cpp libserver-test/malikania/server/db/test_database.hpp libserver-test/malikania/server/spell_dao_test.cpp libserver-test/malikania/server/spell_dao_test.hpp libserver/malikania/server/db/account.cpp libserver/malikania/server/db/database.hpp tests/libcommon/CMakeLists.txt tests/libserver/CMakeLists.txt tests/libserver/dao-character/main.cpp tests/libserver/db/account/main.cpp
diffstat 22 files changed, 563 insertions(+), 414 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Mon Sep 04 19:41:18 2017 +0200
+++ b/CMakeLists.txt	Tue Sep 05 13:33:57 2017 +0200
@@ -62,8 +62,7 @@
 add_subdirectory(libclient)
 add_subdirectory(libclient-js)
 add_subdirectory(libserver)
-#add_subdirectory(libserver-test)
-#add_subdirectory(libdb-sqlite)
+add_subdirectory(libserver-test)
 add_subdirectory(client)
 add_subdirectory(server)
 
--- a/database/CMakeLists.txt	Mon Sep 04 19:41:18 2017 +0200
+++ b/database/CMakeLists.txt	Tue Sep 05 13:33:57 2017 +0200
@@ -19,4 +19,4 @@
 project(database)
 
 #add_subdirectory(postgresql)
-add_subdirectory(sqlite)
+#add_subdirectory(sqlite)
--- a/docs/specs/db/account.md	Mon Sep 04 19:41:18 2017 +0200
+++ b/docs/specs/db/account.md	Tue Sep 05 13:33:57 2017 +0200
@@ -7,9 +7,10 @@
 | field         | type                      |
 |---------------|---------------------------|
 | id            | big integer (primary key) |
-| login         | string not null           |
+| login         | string unique not null    |
+| password      | string not null           |
 | email         | string not null           |
-| firstname     | string not null           |
+| firstname     | string                    |
 | lastname      | string                    |
 | createdate    | date (default to now)     |
 
@@ -17,11 +18,6 @@
 
 ````nohighlight
 +---------------+       0..* +---------------+
-| account       +-----+------+ character     |
-+---------------+     |      +---------------+
-                      |
-                      |
-                      | 0..* +---------------+
-                      +------+ connect_log   +
-                             +---------------+
+| account       +------------+ character     |
++---------------+            +---------------+
 ````
--- a/libserver-test/CMakeLists.txt	Mon Sep 04 19:41:18 2017 +0200
+++ b/libserver-test/CMakeLists.txt	Tue Sep 05 13:33:57 2017 +0200
@@ -20,18 +20,14 @@
 
 set(
     HEADERS
-    ${libmlk-server-test_SOURCE_DIR}/malikania/server/account_dao_test.hpp
-    ${libmlk-server-test_SOURCE_DIR}/malikania/server/character_dao_test.hpp
-    ${libmlk-server-test_SOURCE_DIR}/malikania/server/database_test.hpp
-    ${libmlk-server-test_SOURCE_DIR}/malikania/server/spell_dao_test.hpp
+    ${libmlk-server-test_SOURCE_DIR}/malikania/server/db/test_account.hpp
+    ${libmlk-server-test_SOURCE_DIR}/malikania/server/db/test_database.hpp
 )
 
 set(
     SOURCES
-    ${libmlk-server-test_SOURCE_DIR}/malikania/server/account_dao_test.cpp
-    ${libmlk-server-test_SOURCE_DIR}/malikania/server/character_dao_test.cpp
-    ${libmlk-server-test_SOURCE_DIR}/malikania/server/database_test.cpp
-    ${libmlk-server-test_SOURCE_DIR}/malikania/server/spell_dao_test.cpp
+    ${libmlk-server-test_SOURCE_DIR}/malikania/server/db/test_account.cpp
+    ${libmlk-server-test_SOURCE_DIR}/malikania/server/db/test_database.cpp
 )
 
 malikania_define_library(
--- a/libserver-test/malikania/server/account_dao_test.cpp	Mon Sep 04 19:41:18 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * account_dao_test.cpp -- database account interface test
- *
- * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <malikania/server/db/account.hpp>
-
-#include "account_dao_test.hpp"
-
-namespace mlk {
-
-namespace server {
-
-std::shared_ptr<account> account_dao_test::authenticate(const std::string& login,
-                                                        const std::string& password)
-{
-    return nullptr;
-}
-
-void account_dao_test::set_email(account& ac, const std::string& email)
-{
-
-}
-
-void account_dao_test::set_firstname(account& ac, const std::string& name)
-{
-
-}
-
-void account_dao_test::set_lastname(account& ac, const std::string& name)
-{
-
-}
-
-void account_dao_test::save(account& ac)
-{
-    ac.set_id(id_++);
-    accounts_.push_back(ac.shared_from_this());
-}
-
-} // !server
-
-} // !mlk
--- a/libserver-test/malikania/server/account_dao_test.hpp	Mon Sep 04 19:41:18 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * account_dao_test.hpp -- database account interface test
- *
- * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_SERVER_ACCOUNT_DAO_TEST_HPP
-#define MALIKANIA_SERVER_ACCOUNT_DAO_TEST_HPP
-
-#include <vector>
-
-#include <malikania/server/db/account_dao.hpp>
-
-namespace mlk {
-
-namespace server {
-
-class account_dao_test : public account_dao {
-private:
-    std::uint64_t id_{0};
-    std::vector<std::shared_ptr<account>> accounts_;
-
-public:
-    std::shared_ptr<account> authenticate(const std::string& login,
-                                          const std::string& password) override;
-
-    void set_email(account& ac, const std::string& email) override;
-    void set_firstname(account& ac, const std::string& name) override;
-    void set_lastname(account& ac, const std::string& name) override;
-    void save(account& ac) override;
-};
-
-} // !server
-
-} // !mlk
-
-#endif // !MALIKANIA_SERVER_ACCOUNT_DAO_TEST_HPP
--- a/libserver-test/malikania/server/character_dao_test.cpp	Mon Sep 04 19:41:18 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * character_dao_test.cpp -- database character interface test
- *
- * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <malikania/server/db/character.hpp>
-
-#include "character_dao_test.hpp"
-
-namespace mlk {
-
-namespace server {
-
-void character_dao_test::save(character&)
-{
-
-}
-
-void character_dao_test::remove(character&)
-{
-
-}
-
-void character_dao_test::set_name(character&, const std::string&)
-{
-
-}
-
-} // !server
-
-} // !mlk
--- a/libserver-test/malikania/server/character_dao_test.hpp	Mon Sep 04 19:41:18 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * character_dao_test.hpp -- database character interface test
- *
- * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_SERVER_CHARACTER_DAO_TEST_HPP
-#define MALIKANIA_SERVER_CHARACTER_DAO_TEST_HPP
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include <malikania/server/db/character_dao.hpp>
-
-namespace mlk {
-
-namespace server {
-
-class character_dao_test : public character_dao {
-private:
-    std::uint64_t id_{0};
-    std::vector<std::shared_ptr<character>> characters_;
-
-public:
-    void save(character&) override;
-    void remove(character&) override;
-    void set_name(character&, const std::string&) override;
-};
-
-} // !server
-
-} // !mlk
-
-#endif // !MALIKANIA_SERVER_CHARACTER_DAO_TEST_HPP
--- a/libserver-test/malikania/server/database_test.cpp	Mon Sep 04 19:41:18 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * database_test.cpp -- database test
- *
- * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "database_test.hpp"
-#include "account_dao_test.hpp"
-#include "character_dao_test.hpp"
-#include "spell_dao_test.hpp"
-
-namespace mlk {
-
-namespace server {
-
-std::unique_ptr<class account_dao> database_test::account_dao()
-{
-    return std::make_unique<account_dao_test>();
-}
-
-std::unique_ptr<class character_dao> database_test::character_dao()
-{
-    return nullptr;
-}
-
-std::unique_ptr<class spell_dao> database_test::spell_dao()
-{
-    return nullptr;
-}
-
-} // !server
-
-} // !mlk
--- a/libserver-test/malikania/server/database_test.hpp	Mon Sep 04 19:41:18 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * database_test.hpp -- database test
- *
- * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_SERVER_DATABASE_TEST_HPP
-#define MALIKANIA_SERVER_DATABASE_TEST_HPP
-
-#include <malikania/server/db/database.hpp>
-
-namespace mlk {
-
-namespace server {
-
-class database_test : public database {
-public:
-    std::unique_ptr<class account_dao> account_dao() override;
-    std::unique_ptr<class character_dao> character_dao() override;
-    std::unique_ptr<class spell_dao> spell_dao() override;
-};
-
-} // !server
-
-} // !mlk
-
-#endif // !MALIKANIA_SERVER_DATABASE_TEST_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver-test/malikania/server/db/test_account.cpp	Tue Sep 05 13:33:57 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * test_account.cpp -- database account object (memory implementation)
+ *
+ * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "test_account.hpp"
+
+namespace mlk {
+
+namespace server {
+
+using test_dao = test_account::test_dao;
+
+test_account::test_account(std::shared_ptr<test_dao> dao,
+                           std::string login,
+                           std::string password) noexcept
+    : account(std::move(login), std::move(password))
+    , dao_(std::move(dao))
+{
+}
+
+void test_account::do_save()
+{
+    id_ = dao_->next_id();
+    dao_->accounts().emplace(id_, *this);
+}
+
+void test_account::do_set_password(const std::string& password)
+{
+    assert(dao_->accounts().count(id_));
+
+    dao_->accounts().at(id_).password_ = password;
+}
+
+void test_account::do_set_email(const std::string& email)
+{
+    assert(dao_->accounts().count(id_));
+
+    dao_->accounts().at(id_).email_ = email;
+}
+
+void test_account::do_set_firstname(const std::string& name)
+{
+    assert(dao_->accounts().count(id_));
+
+    dao_->accounts().at(id_).firstname_ = name;
+}
+
+void test_account::do_set_lastname(const std::string& name)
+{
+    assert(dao_->accounts().count(id_));
+
+    dao_->accounts().at(id_).lastname_ = name;
+}
+
+std::shared_ptr<account> test_dao::do_find_by_login(const std::string& login)
+{
+    for (const auto& pair : accounts_) {
+        if (pair.second.login() == login) {
+            auto a = std::make_shared<test_account>(shared_from_this(),
+                pair.second.login(), pair.second.password());
+
+            a->id_ = pair.first;
+            a->email_ = pair.second.email_;
+            a->firstname_ = pair.second.firstname_;
+            a->lastname_ = pair.second.lastname_;
+
+            return a;
+        }
+    }
+
+    return nullptr;
+}
+
+} // !server
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver-test/malikania/server/db/test_account.hpp	Tue Sep 05 13:33:57 2017 +0200
@@ -0,0 +1,137 @@
+/*
+ * test_account.hpp -- database account object (memory implementation)
+ *
+ * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_SERVER_TEST_ACCOUNT_HPP
+#define MALIKANIA_SERVER_TEST_ACCOUNT_HPP
+
+/**
+ * \file test_account.hpp
+ * \brief Database account object (memory implementation)
+ */
+
+#include <unordered_map>
+
+#include <malikania/server/db/account.hpp>
+
+namespace mlk {
+
+namespace server {
+
+/**
+ * \brief Database account object (memory implementation)
+ */
+class test_account : public account {
+public:
+    class test_dao;
+
+private:
+    std::shared_ptr<test_dao> dao_;
+
+public:
+    /**
+     * Construct a test_account.
+     *
+     * \param dao the dao owner
+     * \param login the login
+     * \param password the password
+     */
+    test_account(std::shared_ptr<test_dao> dao,
+                 std::string login,
+                 std::string password) noexcept;
+
+    /**
+     * \copydoc account::do_save
+     */
+    void do_save() override;
+
+    /**
+     * \copydoc account::do_set_password
+     */
+    void do_set_password(const std::string& password) override;
+
+    /**
+     * \copydoc account::do_set_email
+     */
+    void do_set_email(const std::string& email) override;
+
+    /**
+     * \copydoc account::do_set_firstname
+     */
+    void do_set_firstname(const std::string& name) override;
+
+    /**
+     * \copydoc account::do_set_lastname
+     */
+    void do_set_lastname(const std::string& name) override;
+};
+
+/**
+ * \brief Account dao for test_account.
+ *
+ * This class saves accounts in memory, thus once deleted the no accounts are
+ * available anymore.
+ */
+class test_account::test_dao
+    : public account::dao
+    , public std::enable_shared_from_this<test_account::test_dao> {
+private:
+    std::unordered_map<std::int64_t, test_account> accounts_;
+    std::int64_t sequence_{0};
+
+public:
+    /**
+     * Get the in memory accounts.
+     *
+     * \return the account map
+     */
+    inline const std::unordered_map<std::int64_t, test_account>& accounts() const noexcept
+    {
+        return accounts_;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the account map
+     */
+    inline std::unordered_map<std::int64_t, test_account>& accounts() noexcept
+    {
+        return accounts_;
+    }
+
+    /**
+     * Compute the next id from the internal sequence.
+     *
+     * \return the next id
+     */
+    inline std::int64_t next_id() noexcept
+    {
+        return ++sequence_;
+    }
+
+    /**
+     * \copydoc dao::do_find_by_login
+     */
+    std::shared_ptr<account> do_find_by_login(const std::string& login) override;
+};
+
+} // !server
+
+} // !mlk
+
+#endif // !MALIKANIA_SERVER_TEST_ACCOUNT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver-test/malikania/server/db/test_database.cpp	Tue Sep 05 13:33:57 2017 +0200
@@ -0,0 +1,43 @@
+/*
+ * test_database.cpp -- database test (memory implementation)
+ *
+ * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
+ * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "test_database.hpp"
+
+namespace mlk {
+
+namespace server {
+
+std::shared_ptr<account> test_database::account_draft(std::string login, std::string password)
+{
+    return std::make_shared<test_account>(account_dao_, std::move(login), std::move(password));
+}
+
+std::shared_ptr<account::dao> test_database::account_dao()
+{
+    return account_dao_;
+}
+
+std::shared_ptr<character> test_database::character_draft()
+{
+    return nullptr;
+}
+
+} // !server
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libserver-test/malikania/server/db/test_database.hpp	Tue Sep 05 13:33:57 2017 +0200
@@ -0,0 +1,74 @@
+/*
+ * test_database.hpp -- database test (memory implementation)
+ *
+ * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
+ * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_SERVER_TEST_DATABASE_HPP
+#define MALIKANIA_SERVER_TEST_DATABASE_HPP
+
+/**
+ * \file test_database.hpp
+ * \brief In memory database implementation for test purposes.
+ */
+
+#include <malikania/server/db/database.hpp>
+
+#include "test_account.hpp"
+
+namespace mlk {
+
+namespace server {
+
+/**
+ * \brief In memory database implementation for test purposes.
+ */
+class test_database : public database {
+private:
+    std::shared_ptr<test_account::test_dao> account_dao_{new test_account::test_dao};
+
+public:
+    /**
+     * Get the real underlying test_dao type.
+     *
+     * \return the test_dao instance
+     */
+    inline std::shared_ptr<test_account::test_dao> test_account_dao() noexcept
+    {
+        return account_dao_;
+    }
+
+    /**
+     * \copydoc database::account_draft
+     */
+    std::shared_ptr<account> account_draft(std::string login, std::string password) override;
+
+    /**
+     * \copydoc database::account_dao
+     */
+    std::shared_ptr<account::dao> account_dao() override;
+
+    /**
+     * \copydoc database::character_draft
+     */
+    std::shared_ptr<character> character_draft() override;
+};
+
+} // !server
+
+} // !mlk
+
+#endif // !MALIKANIA_SERVER_TEST_DATABASE_HPP
--- a/libserver-test/malikania/server/spell_dao_test.cpp	Mon Sep 04 19:41:18 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * spell_dao_test.cpp -- database spell interface test
- *
- * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <malikania/server/db/spell.hpp>
-
-#include "spell_dao_test.hpp"
-
-namespace mlk {
-
-namespace server {
-
-void spell_dao_test::save(spell&, character&)
-{
-
-}
-
-void spell_dao_test::set_level(spell&, std::uint8_t)
-{
-
-}
-
-void spell_dao_test::remove(spell&)
-{
-
-}
-
-} // !server
-
-} // !mlk
--- a/libserver-test/malikania/server/spell_dao_test.hpp	Mon Sep 04 19:41:18 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * spell_dao_test.hpp -- database spell interface test
- *
- * Copyright (c) 2013-2017 Alexis Dörr <nanahara@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_SERVER_SPELL_DAO_TEST_HPP
-#define MALIKANIA_SERVER_SPELL_DAO_TEST_HPP
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <malikania/server/db/spell_dao.hpp>
-
-namespace mlk {
-
-namespace server {
-
-class spell_dao_test : public spell_dao {
-private:
-    std::uint64_t id_{0};
-    std::vector<std::shared_ptr<spell>> spells;
-
-public:
-    void save(spell&, character&) override;
-    void set_level(spell&, std::uint8_t) override;
-    void remove(spell&) override;
-};
-
-} // !server
-
-} // !mlk
-
-#endif // !MALIKANIA_SERVER_SPELL_DAO_TEST_HPP
--- a/libserver/malikania/server/db/account.cpp	Mon Sep 04 19:41:18 2017 +0200
+++ b/libserver/malikania/server/db/account.cpp	Tue Sep 05 13:33:57 2017 +0200
@@ -92,7 +92,7 @@
     if (!ac || ac->password() != password)
         return nullptr;
 
-    return nullptr;
+    return ac;
 }
 
 } // !server
--- a/libserver/malikania/server/db/database.hpp	Mon Sep 04 19:41:18 2017 +0200
+++ b/libserver/malikania/server/db/database.hpp	Tue Sep 05 13:33:57 2017 +0200
@@ -44,16 +44,20 @@
     /**
      * Initialize database.
      */
-    virtual void init() = 0;
+    virtual void init()
+    {
+    }
 
     /**
      * Create a draft account.
      *
      * \param login the login name
+     * \param password the password
      * \return a draft account
      * \post value->is_draft()
+     * \see account::account
      */
-    virtual std::shared_ptr<account> account_draft(std::string login) = 0;
+    virtual std::shared_ptr<account> account_draft(std::string login, std::string password) = 0;
 
     /**
      * Create the account dao.
--- a/tests/libcommon/CMakeLists.txt	Mon Sep 04 19:41:18 2017 +0200
+++ b/tests/libcommon/CMakeLists.txt	Tue Sep 05 13:33:57 2017 +0200
@@ -18,6 +18,7 @@
 
 add_subdirectory(util)
 add_subdirectory(size)
+add_subdirectory(weak_array)
 
 # JavaScript bindings
 add_subdirectory(js-elapsed-timer)
--- a/tests/libserver/CMakeLists.txt	Mon Sep 04 19:41:18 2017 +0200
+++ b/tests/libserver/CMakeLists.txt	Tue Sep 05 13:33:57 2017 +0200
@@ -17,6 +17,4 @@
 #
 
 add_subdirectory(id)
-add_subdirectory(dao-character)
 add_subdirectory(db/account)
-# add_subdirectory(dao-account)
--- a/tests/libserver/dao-character/main.cpp	Mon Sep 04 19:41:18 2017 +0200
+++ b/tests/libserver/dao-character/main.cpp	Tue Sep 05 13:33:57 2017 +0200
@@ -20,6 +20,8 @@
 #include <boost/test/unit_test.hpp>
 
 #include <malikania/server/db/dynlib_database.hpp>
+#include <malikania/server/db/account.hpp>
+#include <malikania/server/db/account_dao.hpp>
 #include <malikania/server/db/character_dao.hpp>
 #include <malikania/server/db/character.hpp>
 
@@ -33,25 +35,74 @@
 
     fixture()
         : db_(new dynlib_database(SQLITE_SHARED_LIBRARY, {
-            { "path", CMAKE_CURRENT_BINARY_DIR "/charcter.db" }
+            { "path", CMAKE_CURRENT_BINARY_DIR "/character.db" }
         }))
     {
     }
 };
 
-BOOST_FIXTURE_TEST_SUITE(account_dao_suite, fixture)
+BOOST_FIXTURE_TEST_SUITE(character_dao_suite, fixture)
 
 BOOST_AUTO_TEST_CASE(save)
 {
     {
-        auto ac = std::make_shared<character>(db_, "francis");
+        auto ac = std::make_shared<account>(db_, "francis");
+        ac->set_email("francis@world.org");
+        ac->set_firstname("Francis");
+        ac->set_lastname("Meyer");
+        ac->save();
 
-        BOOST_TEST(ac->is_draft());
-        ac->save();
+        auto ch = std::make_shared<character>(db_, "blackmage");
+        ac->add_character(ch);
+
         BOOST_TEST(ac->is_published());
+        BOOST_TEST(ac == ch->account());
+        BOOST_TEST(ac->characters().size() == 1U);
+        BOOST_TEST(ch->is_published());
     }
 
-    auto ac =
+    auto ac = db_->account_dao()->find("francis");
+
+    BOOST_TEST(ac->email() == "francis@world.org");
+    BOOST_TEST(ac->firstname() == "Francis");
+    BOOST_TEST(ac->lastname() == "Meyer");
+}
+
+BOOST_AUTO_TEST_CASE(direct_save)
+{
+    auto ac = std::make_shared<account>(db_, "francis");
+    ac->save();
+
+    auto ch = std::make_shared<character>(db_, "blackmage");
+    ch->save(ac);
+
+    BOOST_TEST(ac->is_published());
+    BOOST_TEST(ch->is_published());
+    BOOST_TEST(ac == ch->account());
+}
+
+BOOST_AUTO_TEST_CASE(remove)
+{
+    auto ac = std::make_shared<account>(db_, "francis");
+    ac->save();
+    auto ch = std::make_shared<character>(db_, "blackmage");
+    ac->add_character(ch);
+    ac->remove_character(ch);
+
+    BOOST_TEST(ch->is_draft());
+    BOOST_TEST(ac->characters().size() == 0U);
+}
+
+BOOST_AUTO_TEST_CASE(direct_remove)
+{
+    auto ac = std::make_shared<account>(db_, "francis");
+    ac->save();
+    auto ch = std::make_shared<character>(db_, "blackmage");
+    ch->save(ac);
+    ch->remove();
+
+    BOOST_TEST(ch->is_draft());
+    BOOST_TEST(ac->characters().size() == 0U);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/libserver/db/account/main.cpp	Mon Sep 04 19:41:18 2017 +0200
+++ b/tests/libserver/db/account/main.cpp	Tue Sep 05 13:33:57 2017 +0200
@@ -19,29 +19,160 @@
 #define BOOST_TEST_MODULE "database account"
 #include <boost/test/unit_test.hpp>
 
-#include <malikania/server/database_test.hpp>
-#include <malikania/server/account_dao_test.hpp>
-#include <malikania/server/db/account.hpp>
+#include <malikania/server/db/test_database.hpp>
 
 namespace mlk {
 
 namespace server {
 
-BOOST_AUTO_TEST_SUITE(basic)
+class account_fixture {
+protected:
+    std::shared_ptr<test_database> db_{new test_database};
+};
+
+BOOST_FIXTURE_TEST_SUITE(basic_suite, account_fixture)
+
+BOOST_AUTO_TEST_CASE(save)
+{
+    auto acc = db_->account_draft("nanahara", "dummypassword");
+
+    // Initial creation must be draft.
+    BOOST_TEST(acc->is_draft());
+
+    /*
+     * Set some fields, the database must not be modified at all but fields
+     * must be set.
+     */
+    acc->set_email("nanahara@malikania.fr");
+    acc->set_firstname("Alexis");
+    acc->set_lastname("Dörr");
+
+    BOOST_TEST(acc->is_draft());
+    BOOST_TEST(!acc->is_published());
+    BOOST_TEST(acc->email() == "nanahara@malikania.fr");
+    BOOST_TEST(acc->firstname() == "Alexis");
+    BOOST_TEST(acc->lastname() == "Dörr");
+    BOOST_TEST(db_->test_account_dao()->accounts().size() == 0U);
+
+    // Do save, database must be updated and account published.
+    acc->save();
+
+    BOOST_TEST(!acc->is_draft());
+    BOOST_TEST(acc->is_published());
+    BOOST_TEST(acc->email() == "nanahara@malikania.fr");
+    BOOST_TEST(acc->firstname() == "Alexis");
+    BOOST_TEST(acc->lastname() == "Dörr");
+    BOOST_TEST(db_->test_account_dao()->accounts().size() == 1U);
+}
+
+BOOST_AUTO_TEST_CASE(set_password)
+{
+    auto ac = db_->account_draft("markand", "nopassword");
+
+    ac->set_password("temporarypassword");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().size() == 0U);
+
+    ac->save();
+    ac->set_password("newpassword");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().at(ac->id()).password() == "newpassword");
+}
 
 BOOST_AUTO_TEST_CASE(set_email)
 {
-    auto db = std::make_shared<database_test>();
-    auto acc = std::make_shared<account>(db, "nanahara");
+    auto ac = db_->account_draft("markand", "nopassword");
+
+    ac->set_email("fake@malikania.fr");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().size() == 0U);
+
+    ac->save();
+    ac->set_email("markand@malikania.fr");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().at(ac->id()).email() == "markand@malikania.fr");
+}
+
+BOOST_AUTO_TEST_CASE(set_firstname)
+{
+    auto ac = db_->account_draft("markand", "nopassword");
+
+    ac->set_firstname("Jean");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().size() == 0U);
+
+    ac->save();
+    ac->set_firstname("David");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().at(ac->id()).firstname() == "David");
+}
+
+BOOST_AUTO_TEST_CASE(set_lastname)
+{
+    auto ac = db_->account_draft("markand", "nopassword");
+
+    ac->set_lastname("Bertrand");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().size() == 0U);
+
+    ac->save();
+    ac->set_lastname("Demelier");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().at(ac->id()).lastname() == "Demelier");
+}
+
+BOOST_AUTO_TEST_SUITE(find_by_login)
 
-    BOOST_TEST(acc->is_draft());
-    acc->set_email("nanahara@malikania.fr");
-    BOOST_TEST(acc->is_draft());
-    BOOST_TEST(acc->email() == "nanahara@malikania.fr");
-    acc->save();
-    BOOST_TEST((acc->is_published() && !acc->is_draft()));
+BOOST_AUTO_TEST_CASE(simple)
+{
+    db_->account_draft("markand", "nopassword")->save();
+
+    auto ac = db_->account_dao()->find_by_login("markand");
+
+    BOOST_TEST(ac);
+    BOOST_TEST(ac->is_published());
+    BOOST_TEST(ac->login() == "markand");
+}
+
+BOOST_AUTO_TEST_CASE(not_found)
+{
+    auto ac = db_->account_dao()->find_by_login("doesnotexist");
+
+    BOOST_TEST(!ac);
+}
+
+BOOST_AUTO_TEST_CASE(same_instance)
+{
+    db_->account_draft("markand", "nopassword")->save();
+
+    auto a1 = db_->account_dao()->find_by_login("markand");
+    auto a2 = db_->account_dao()->find_by_login("markand");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().size() == 1U);
+    BOOST_TEST(a1 == a2);
+}
+
+BOOST_AUTO_TEST_CASE(new_instance)
+{
+    db_->account_draft("markand", "nopassword")->save();
+
+    /*
+     * Get rid of a1 reference, account::dao is supposed to call
+     * do_find_by_login again, creating a new pointer to the account.
+     */
+    auto a1 = db_->account_dao()->find_by_login("markand");
+    a1 = nullptr;
+
+    auto a2 = db_->account_dao()->find_by_login("markand");
+
+    BOOST_TEST(db_->test_account_dao()->accounts().size() == 1U);
+    BOOST_TEST(a1 != a2);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
+
+BOOST_AUTO_TEST_SUITE_END()
+
 } // !server
+
 } // !mlk