Add project tests
diff --git a/.coveragerc b/.coveragerc
index 10e4939..c35bfbc 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -3,6 +3,7 @@
 
 omit =
     *__init__*
+    *__main__*
     gstack/models/*.py
     gstack/configure.py
 
diff --git a/gstack/appserver.py b/gstack/__main__.py
similarity index 100%
rename from gstack/appserver.py
rename to gstack/__main__.py
diff --git a/setup.py b/setup.py
index 33325c9..576eb24 100755
--- a/setup.py
+++ b/setup.py
@@ -59,7 +59,7 @@
     zip_safe=False,
     entry_points="""
         [console_scripts]
-        gstack = gstack.appserver:main
+        gstack = gstack.__main__:main
         gstack-configure = gstack.configure:main
     """,
 )
diff --git a/tests/data/valid_describe_account.json b/tests/data/valid_describe_account.json
new file mode 100644
index 0000000..6fdf643
--- /dev/null
+++ b/tests/data/valid_describe_account.json
@@ -0,0 +1,73 @@
+{
+    "listaccountsresponse": {
+        "count": 1,
+        "account": [
+            {
+                "secondarystoragetotal": 0,
+                "primarystorageavailable": "Unlimited",
+                "domain": "brogand93@darrenbrogan.ie",
+                "domainid": "42f2b0d0-3953-485f-984d-b8d67185d358",
+                "vpclimit": "Unlimited",
+                "iplimit": "20",
+                "memorytotal": 0,
+                "secondarystorageavailable": "Unlimited",
+                "vmtotal": 0,
+                "cputotal": 0,
+                "vpctotal": 0,
+                "id": "ddbdf378-e8d9-47e0-964b-661d0d8414b8",
+                "networkavailable": "Unlimited",
+                "projectlimit": "Unlimited",
+                "networklimit": "Unlimited",
+                "iptotal": -27,
+                "volumetotal": 0,
+                "snapshotlimit": "0",
+                "state": "enabled",
+                "networktotal": 0,
+                "accounttype": 0,
+                "cpuavailable": "Unlimited",
+                "primarystoragetotal": 0,
+                "templatelimit": "0",
+                "snapshottotal": 0,
+                "templateavailable": "0",
+                "vmlimit": "20",
+                "vpcavailable": "0",
+                "primarystoragelimit": "Unlimited",
+                "volumelimit": "20",
+                "templatetotal": 0,
+                "secondarystoragelimit": "Unlimited",
+                "user": [
+                    {
+                        "username": "accountname",
+                        "account": "brogand93@darrenbrogan.ie",
+                        "domainid": "42f2b0d0-3953-485f-984d-b8d67185d358",
+                        "firstname": "brogand93",
+                        "created": "2013-09-17T15:35:34+0200",
+                        "lastname": "darrenbrogan.ie",
+                        "iscallerchilddomain": false,
+                        "domain": "brogand93@darrenbrogan.ie",
+                        "email": "brogand93@darrenbrogan.ie",
+                        "secretkey": "lM9fLm8XQwezvLOd10Qt3wXH7j9mRgaKbEg3nRDnj7FtlF3yx54EWd9mR5sB1ec5LQDV6gjpy6sfDo6ndUeeww",
+                        "state": "enabled",
+                        "apikey": "0ZyexOgzlfTx076LYBFz4oT_ShJvxUcezgvsW6gvRZ_BloSsb5uUTAm-FtHvKBvAUP0S7ZN6bIcRf4zEtbm3PQ",
+                        "accounttype": 0,
+                        "timezone": "CET",
+                        "id": "26a772da-dc25-4f2b-b0f1-e095e3717a30",
+                        "isdefault": false,
+                        "accountid": "ddbdf378-e8d9-47e0-964b-661d0d8414b8"
+                    }
+                ],
+                "projectavailable": "Unlimited",
+                "isdefault": false,
+                "memoryavailable": "Unlimited",
+                "projecttotal": 0,
+                "volumeavailable": "20",
+                "name": "accountname",
+                "vmavailable": "20",
+                "ipavailable": "0",
+                "memorylimit": "Unlimited",
+                "cpulimit": "Unlimited",
+                "snapshotavailable": "0"
+            }
+        ]
+    }
+}
diff --git a/tests/data/valid_describe_tags.json b/tests/data/valid_describe_tags.json
new file mode 100644
index 0000000..f95a11a
--- /dev/null
+++ b/tests/data/valid_describe_tags.json
@@ -0,0 +1,16 @@
+{
+    "listtagsresponse": {
+        "count": 1,
+        "tag": [
+            {
+                "account": "brogand93@darrenbrogan.ie",
+                "domainid": "42f2b0d0-3953-485f-984d-b8d67185d358",
+                "resourcetype": "UserVm",
+                "resourceid": "a0ae3a53-1f4d-42d3-bbb8-7227bb0e0d69",
+                "domain": "brogand93@darrenbrogan.ie",
+                "value": "test1",
+                "key": "testkey1"
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/valid_register_keypair.json b/tests/data/valid_register_keypair.json
new file mode 100644
index 0000000..37d4b80
--- /dev/null
+++ b/tests/data/valid_register_keypair.json
@@ -0,0 +1,8 @@
+{
+    "registersshkeypairresponse": {
+        "keypair": {
+            "name": "brogand93@darrenbrogan.ie",
+            "fingerprint": "68:56:2f:5e:86:2c:0d:17:5e:2b:bb:f5:0e:fd:1d:25"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/project_tests.py b/tests/project_tests.py
new file mode 100644
index 0000000..d3a58ee
--- /dev/null
+++ b/tests/project_tests.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+import mock
+import json
+
+from gstack.helpers import read_file
+from . import GStackAppTestCase
+
+class ProjectsTestCase(GStackAppTestCase):
+
+    def test_get_project(self):
+        get = mock.Mock()
+        get.return_value = json.loads(read_file('tests/data/valid_describe_account.json'))
+
+        get_tags = mock.Mock()
+        get_tags.return_value.text = read_file('tests/data/valid_describe_tags.json')
+        get_tags.return_value.status_code = 200
+
+        with mock.patch('requests.get', get_tags):
+            with(mock.patch('gstack.controllers.project._get_accounts', get)):
+                headers = {'authorization': 'Bearer ' + str(GStackAppTestCase.access_token)}
+                response = self.get('/compute/v1/projects/accountname', headers=headers)
+
+        self.assert_ok(response)
+
+    def test_get_project_project_not_found(self):
+        get = mock.Mock()
+        get.return_value = json.loads(read_file('tests/data/valid_describe_account.json'))
+
+        get_tags = mock.Mock()
+        get_tags.return_value.text = read_file('tests/data/valid_describe_tags.json')
+        get_tags.return_value.status_code = 200
+
+        with mock.patch('requests.get', get_tags):
+            with(mock.patch('gstack.controllers.project._get_accounts', get)):
+                headers = {'authorization': 'Bearer ' + str(GStackAppTestCase.access_token)}
+                response = self.get('/compute/v1/projects/invalidaccountname', headers=headers)
+
+        self.assert_not_found(response)
+        assert 'The resource \'/compute/v1/projects/invalidaccountname\' was not found' \
+                in response.data
+
+    def test_set_metadata(self):
+        data = {
+            'items': [{
+                'key': 'sshKeys',
+                'value': 'root:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDqQuui+xCVPXaFD4cP2MuWnDlktp9vMT/SNzF17UiAzKEbxT\
+                                        /mPayTDArDbY/BgGYC5bHuGlb/eE1r4EGpwSXZitGkTI4ThldrSp0Em7psO8AibdpYuFxlOmDFp9wK\
+                                        VD6xbY2HT1ySwvKi+ZwSR5yHcEKq15eV4eez/3qC1vIcssKmwu5+ZBneZAvWAfxHEKsQU0dsCVvHdn8\
+                                        g7tFXXtg4QCGtE4yzK5v3/+f1AdtIi4hvJoMyi8MV0KSa8e/ravdHbgj44PncFBB8O6epVdXPbClZwt\
+                                        kz9D6GEQaOArxk9tX8YEgTFnmsnNuaoZgs7giMj2N7jQe2qXh5R0nsTTuH brogand@microvac'
+            }],
+            'kind': 'compute#metadata'
+        }
+
+        data = json.dumps(data)
+
+        get = mock.Mock()
+        get.return_value.text = read_file('tests/data/valid_register_keypair.json')
+        get.return_value.status_code = 200
+
+        with mock.patch('requests.get', get):
+             headers = {
+                 'authorization': 'Bearer ' + str(GStackAppTestCase.access_token),
+             }
+
+             response = self.post_json('/compute/v1/projects/admin/setCommonInstanceMetadata', data=data, headers=headers)
+
+        self.assert_ok(response)