public inbox for [email protected]  
help / color / mirror / Atom feed
From: Navnath Gadakh <[email protected]>
To: Dave Page <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Cc: Kanchan Mohitey <[email protected]>
Subject: Re: pgAdmin IV : Unittest modular patch
Date: Tue, 2 Aug 2016 20:28:02 +0530
Message-ID: <CAOAJCYq94E=zhaVWWUORP62nSD-PJ2y2crJeL41Mmv-50i-VbQ@mail.gmail.com> (raw)
In-Reply-To: <CA+OCxoxKo1L9ZNH81h-kmzWvzn7Pj=T4fUnP6FpvchePpoAB0A@mail.gmail.com>
References: <CAOAJCYrcxBN2J_3dWq0Cwc82fkugzUi3NKD4jKoTKRBot=ev8w@mail.gmail.com>
	<CAOAJCYpSBXcfEC5d4Sv_=jV86m1=rKUK0tMkZFhdSHkPb=XT3A@mail.gmail.com>
	<CA+OCxowW0wjpNT-o0YF1Bg9rtD6Z7sqp35ZRUgoEguVKO4OtSw@mail.gmail.com>
	<CAOAJCYr1JwYK4x2wDYw2UVAZoXC5a0FQT7Yz1Y_Wn46kzPMmQg@mail.gmail.com>
	<CA+OCxoxqahNgLmvQqqErQZL2JS0EaQwyXkgkzvkFtGNh0OKV6w@mail.gmail.com>
	<CAOAJCYqQQ4MaudVaVwfcateuxum-W39HwRiEorhYP8zbqjxN0g@mail.gmail.com>
	<CA+OCxozZVCwB4t6hXjMeHbBV8Fx1cm_Cg1tknjWyYxLFZNYsEQ@mail.gmail.com>
	<CAFOhELes8Vu_VciiVu31wfaYtTuCFUReEF1mfNXB4nSMcTNrHA@mail.gmail.com>
	<CAOAJCYpY=u4T38s+XqQDOky10e7A_Wb_q9bbiwhx_=eF-6i-dQ@mail.gmail.com>
	<CA+OCxoxm9_f5PJVLhwrSk6bozmivv_-=o+spffXjkYk+qPDKeg@mail.gmail.com>
	<CAOAJCYpcye6nQAPB8os9vZXOhAf9wEvr6rA9i4vuZLDVrRYF0g@mail.gmail.com>
	<CA+OCxowE5D0N2oq-Da+eXh4+cZMA3=GqB85-nE+YHuaACfjhbQ@mail.gmail.com>
	<CAOAJCYonmDD-oqjwhJNVpWVHxyf-bTn_eJ8o7wNMr7sOOpBvkA@mail.gmail.com>
	<CA+OCxozHiy2UsJp6jvYRNfYv3RWTijdFeoPuZH4dqyyT-knnjQ@mail.gmail.com>
	<CAOAJCYo4Lyc3f+-6a7cYxsxjn9GKG7j7R8VYiDmxgrntyds-xg@mail.gmail.com>
	<CA+OCxoxKo1L9ZNH81h-kmzWvzn7Pj=T4fUnP6FpvchePpoAB0A@mail.gmail.com>
List-Unsubscribe:  <mailto:[email protected]?body=unsub%20pgadmin-hackers>

Hi Dave,
     Please find the attached patch.
*This patch includes:*
1. API test cases for Roles & Tablespaces node(Completed nodes: server
groups, servers, databases)
    You can run test-suite using following command
     for roles node
               python regression/runtests.py --pkg
browser.server_groups.servers.roles
     for tablespaces node
               python regression/runtests.py --pkg
browser.server_groups.servers.tablespaces
     for all nodes
               python regression/runtests.py
     You can also test with multiple  servers.
2. Delete database code in some of the missed test files.
3. Added advanced configurations in test_advanced_config.json.in for roles
& tablespaces. So, accordingly you need change the file
 test_advanced_config.json
4. Added one test user credentials in test_config.json.in to test the
‘valid password’ test case which is present in
browser/tests/test_change_password.py
    Why test user credentials in test_config.json.in?
           Currently, I am getting ‘UnicodeDecodeError’ when I run
test-suite(runtests.py) with existing code. I already explained the detail
about this error in RM(#1521 <https://redmine.postgresql.org/issues/1521;).
I am creating test user to test the ‘valid password’ test case.

*Notes:*
 1. Code not added to encode the password which is displaying in log file
while testing SMTP(Will add the code in next patch)
 2. Code not added to show enhanced the test summary report(that you
mentioned in the previous email). I will look into this, need to decide
approach what are the code changes required in the current code.

Thanks!


On Mon, Aug 1, 2016 at 3:56 PM, Dave Page <[email protected]>
wrote:

> Hi
>
> On Mon, Aug 1, 2016 at 10:54 AM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >
> > On Mon, Aug 1, 2016 at 3:17 PM, Dave Page <[email protected]>
> wrote:
> >> On Thu, Jul 28, 2016 at 8:12 AM, Navnath Gadakh
> >> <[email protected]> wrote:
> >>> Thanks Dave!
> >>>
> >>> On Wed, Jul 27, 2016 at 8:12 PM, Dave Page <[email protected]>
> wrote:
> >>>> Ahh, that explains it. Nice catch! It's working in both server and
> >>>> desktop modes now :-).
> >>>>
> >>>> I've committed the patch, but can you please look at the following
> issues:
> >>>>
> >>>> 1) When testing SMTP, the encoded password used to connect to the
> >>>> server is displayed in both the logs and stdout (the "send: 'AUTH
> >>>> PLAIN ....'" lines). Can you catch that, and replace it with *'s
> >>>> please? Sooner or later someone will reveal a password otherwise.
> >         Could you please send me your's regression.log file. While
> > testing SMTP I didn't see encoded password displayed on both logs and
> > stdout.
>
> Here's an extract from stdout (with the encoded password replaced with
> xxxxxx). I don't actually see the same in regression.log, but that may
> be because of the log settings I'm using - we should filter the same
> from there though to be safe:
>
> ...
> This function checks reset password functionality. (TestCase for
> Validating Valid_Email) ... send: 'ehlo
> piranha.ox.uk.enterprisedb.com\r\n'
> reply: '250-smtp.gmail.com at your service, [194.73.70.210]\r\n'
> reply: '250-SIZE 35882577\r\n'
> reply: '250-8BITMIME\r\n'
> reply: '250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER
> XOAUTH\r\n'
> reply: '250-ENHANCEDSTATUSCODES\r\n'
> reply: '250-PIPELINING\r\n'
> reply: '250-CHUNKING\r\n'
> reply: '250 SMTPUTF8\r\n'
> reply: retcode (250); Msg: smtp.gmail.com at your service, [194.73.70.210]
> SIZE 35882577
> 8BITMIME
> AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
> ENHANCEDSTATUSCODES
> PIPELINING
> CHUNKING
> SMTPUTF8
> send: 'AUTH PLAIN xxxxxx\r\n'
> reply: '235 2.7.0 Accepted\r\n'
> reply: retcode (235); Msg: 2.7.0 Accepted
> send: u'mail FROM:<no-reply@localhost> size=1122\r\n'
> reply: '250 2.1.0 OK v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (250); Msg: 2.1.0 OK v26sm44372678pfi.41 - gsmtp
> send: u'rcpt TO:<[email protected]>\r\n'
> reply: '250 2.1.5 OK v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (250); Msg: 2.1.5 OK v26sm44372678pfi.41 - gsmtp
> send: 'data\r\n'
> reply: '354  Go ahead v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (354); Msg: Go ahead v26sm44372678pfi.41 - gsmtp
> data: (354, 'Go ahead v26sm44372678pfi.41 - gsmtp')
> send: 'Content-Type: multipart/mixed;
> boundary="===============5947340609837468105=="\r\nMIME-Version:
> 1.0\r\nSubject: Password reset instructions for pgAdmin 4\r\nFrom:
> no-reply@localhost\r\nTo: [email protected]\r\nDate: Mon, 01 Aug 2016
> 11:18:01 +0100\r\nMessage-ID:
> <[email protected]
> >\r\n\r\n--===============5947340609837468105==\r\nContent-Type:
> multipart/alternative;\r\n
> boundary="===============4573645557236154244=="\r\nMIME-Version:
> 1.0\r\n\r\n--===============4573645557236154244==\r\nContent-Type:
> text/plain; charset="utf-8"\r\nMIME-Version:
> 1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\nClick the link below to
> reset your
> password:\r\n\r\nhttp://localhost/reset/WyIxIiwiYTY2ODY0ZTY0NzlmMzM1NTNhYTc0NzUwYzEwNDc5ZmQiXQ.CoCzVg.FE0MhiGBwOgVWTcX8mB3Xgq54yw\r\n--===============4573645557236154244==\r\nContent-Type:
> text/html; charset="utf-8"\r\nMIME-Version:
> 1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<p><a
> href="
> http://localhost/reset/WyIxIiwiYTY2ODY0ZTY0NzlmMzM1NTNhYTc0NzUwYzEwNDc5ZmQiXQ.CoCzVg.FE0MhiGBwOgVWTc...
> ">Click
> here to reset your
>
> password</a></p>\r\n--===============4573645557236154244==--\r\n\r\n--===============5947340609837468105==--\r\n.\r\n'
> reply: '250 2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (250); Msg: 2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp
> data: (250, '2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp')
> send: 'quit\r\n'
> reply: '221 2.0.0 closing connection v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (221); Msg: 2.0.0 closing connection v26sm44372678pfi.41 -
> gsmtp
> ok
> runTest
> (pgadmin.browser.server_groups.servers.tests.test_server_put.ServerUpdateTestCase)
> ...
>
> These are the relevant settings I'm using:
>
> # Debug mode
> DEBUG = True
>
> # App mode
> SERVER_MODE = True
>
> # Log
> CONSOLE_LOG_LEVEL = DEBUG
> FILE_LOG_LEVEL = DEBUG
>
> # Mail server settings
> MAIL_SERVER = 'smtp.gmail.com'
> MAIL_PORT = 465
> MAIL_USE_SSL = True
> MAIL_USERNAME = '[email protected]'
> MAIL_PASSWORD = 'xxxxxx'
>
>
> >>>>
> >>>> 2) Is the test count in the summary correct when you have multiple
> >>>> servers? I think it might be resetting between servers.
> >>>      In the current code runTest() function calls only one time for
> >>> single/multiple server/s that's why it's showing same count for both
> >>> (single & multiple).
> >>>    Question: What exactly we are looking for, only count? Or we need
> >>> any more logs like for adding database, it should display in which
> >>> server (PG/PPAS) its adding database if this is the case we need a
> >>> feasibility check.
> >>
> >> Right now I would like to see the summary updated so it outputs useful
> >> (and correct) information - for example, it could say something like:
> >>
> >> =====
> >> Testing completed:
> >>
> >> PostgreSQL 9.4:  23 tests passed, 0 tests failed
> >> EPAS 9.5:            25 tests passed, 2 tests failed (foo_test,
> bar_test)
> >> =====
> >>
> >> where PostgreSQL 9.4 and EPAS 9.5 are the two servers configured in
> >> test_config.py and foo_test and bar_test are the names of the tests
> >> that failed.
> >    Thanks for additional info.
> >>
> >>>> 3) Please ensure that test databases that are created are also dropped
> >>>> again. I'm getting tired of deleting them manually!
> >>>     I already added delete databases in tearDown () function, But
> >>> yeah, I found two test cases where this code missed. I will add this
> >>> in the next patch.
> >>
> >> Thanks.
> >>
> >>>>
> >>>> Thanks, Dave.
> >>>>
> >>>> On Wed, Jul 27, 2016 at 1:19 PM, Navnath Gadakh
> >>>> <[email protected]> wrote:
> >>>>> Hi Dave,
> >>>>>       We have reproduced the issue you mentioned in the previous
> >>>>> email. We need to skip the login related test cases when SERVER_MODE
> =
> >>>>> False in the web/config_local.py.
> >>>>>
> >>>>> Please find the revised patch for the same.
> >>>>>
> >>>>> Thanks!
> >>>>>
> >>>>>
> >>>>> On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <
> [email protected]> wrote:
> >>>>>> Hi
> >>>>>>
> >>>>>> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
> >>>>>> <[email protected]> wrote:
> >>>>>>> Hi Dave,
> >>>>>>>
> >>>>>>>    Please find the attached patch for pgAdmin4 unittest(Support of
> API
> >>>>>>> testing with different servers i.e. PG and PPAS).
> >>>>>>>
> >>>>>>> This patch includes-
> >>>>>>>
> >>>>>>> Test framework support API testing with multiple server for this
> we need to
> >>>>>>> modify test_config.json(for user it’s test_config.json.in) and
> >>>>>>> test_advanced_config.json(for user it’s
> test_advanced_config.json.in).
> >>>>>>> Server details of PG and  PPAS are included in both .in files.
> >>>>>>>
> >>>>>>> Removed the logic of logging in  the test client on each test
> scenario(As
> >>>>>>> per Khushboo's comment in previous email).  We need this logic in
> test cases
> >>>>>>> under ‘browser/tests/’ as for test scenarios like change password
> and
> >>>>>>> invalid login test cases as test client should be logged out
> first. So, as
> >>>>>>> per this the code is slightly modified in ‘browser/tests/’.
> >>>>>>
> >>>>>> OK in principle, but it doesn't seem to work:
> >>>>>>
> >>>>>> This function will add the server under default server group.
> (Default
> >>>>>> Server Node url) ... ok
> >>>>>>
> >>>>>>
> ======================================================================
> >>>>>> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >>>>>> This function checks reset password functionality. (TestCase for
> >>>>>> Validating Empty Email)
> >>>>>>
> ----------------------------------------------------------------------
> >>>>>> Traceback (most recent call last):
> >>>>>>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >>>>>> line 44, in runTest
> >>>>>>     'utf-8'))
> >>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in
> u'<!DOCTYPE
> >>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>>>>>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
> >>>>>> If not click the link.'
> >>>>>>
> >>>>>>
> ======================================================================
> >>>>>> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >>>>>> This function checks reset password functionality. (TestCase for
> >>>>>> Validating Invalid_Email)
> >>>>>>
> ----------------------------------------------------------------------
> >>>>>> Traceback (most recent call last):
> >>>>>>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >>>>>> line 44, in runTest
> >>>>>>     'utf-8'))
> >>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in
> u'<!DOCTYPE
> >>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>>>>>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
> >>>>>> If not click the link.'
> >>>>>>
> >>>>>>
> ======================================================================
> >>>>>> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >>>>>> This function checks reset password functionality. (TestCase for
> >>>>>> Validating Valid_Email)
> >>>>>>
> ----------------------------------------------------------------------
> >>>>>> Traceback (most recent call last):
> >>>>>>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >>>>>> line 44, in runTest
> >>>>>>     'utf-8'))
> >>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in
> u'<!DOCTYPE
> >>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>>>>>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
> >>>>>> If not click the link.'
> >>>>>>
> >>>>>>
> ----------------------------------------------------------------------
> >>>>>> Ran 26 tests in 30.109s
> >>>>>>
> >>>>>> FAILED (failures=3)
> >>>>>>
> >>>>>> It's very far from obvious what's wrong here (/reset looks just fine
> >>>>>> to me). How can we get more useful info out of the framework?
> >>>>>>
> >>>>>> --
> >>>>>> Dave Page
> >>>>>> VP, Chief Architect, Tools & Installers
> >>>>>> EnterpriseDB: http://www.enterprisedb.com
> >>>>>> The Enterprise PostgreSQL Company
> >>>>>>
> >>>>>> Blog: http://pgsnake.blogspot.com
> >>>>>> Twitter: @pgsnake
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> Thanks,
> >>>>> Navnath Gadakh
> >>>>> Software Engineer
> >>>>> EnterpriseDB Corporation
> >>>>> Mobile: +91 9975389878
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Dave Page
> >>>> VP, Chief Architect, Tools & Installers
> >>>> EnterpriseDB: http://www.enterprisedb.com
> >>>> The Enterprise PostgreSQL Company
> >>>>
> >>>> Blog: http://pgsnake.blogspot.com
> >>>> Twitter: @pgsnake
> >>>
> >>>
> >>>
> >>> --
> >>> Thanks,
> >>> Navnath Gadakh
> >>> Software Engineer
> >>> EnterpriseDB Corporation
> >>> Mobile: +91 9975389878
> >>
> >>
> >>
> >> --
> >> Dave Page
> >> VP, Chief Architect, Tools & Installers
> >> EnterpriseDB: http://www.enterprisedb.com
> >> The Enterprise PostgreSQL Company
> >>
> >> Blog: http://pgsnake.blogspot.com
> >> Twitter: @pgsnake
> >
> >
> >
> > --
> > Thanks,
> > Navnath Gadakh
> > Software Engineer
> > EnterpriseDB Corporation
> > Mobile: +91 9975389878
>
>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] pgadmin_unittest_roles_tablespaces.patch (49.3K, 3-pgadmin_unittest_roles_tablespaces.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
index 85dcc6c..22cd7ce 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -38,7 +38,7 @@ class DatabaseAddTestCase(BaseTestGenerator):
         """ This function will add database under 1st server of tree node. """
 
         server_connect_response, server_group, server_ids = \
-            utils.connect_server(self.tester)
+            utils.connect_server(self.tester, True)
 
         for server_connect, server_id in zip(server_connect_response,
                                              server_ids):
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
index 4615d34..6740534 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -70,5 +70,6 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
         :return: None
         """
 
+        utils.delete_database(self.tester)
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py
new file mode 100644
index 0000000..4a11bf8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py
@@ -0,0 +1,16 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class RoleGeneratorTestCase(BaseTestGenerator):
+
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py
new file mode 100644
index 0000000..27cae52
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py
@@ -0,0 +1,54 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression import test_utils as utils
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class LoginRoleAddTestCase(BaseTestGenerator):
+    """This class has add role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    def setUp(self):
+        """This function used to add the sever"""
+
+        # Add the server
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """This function test the add role scenario"""
+
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, True)
+
+        for server_connect, server_id in zip(server_connect_response,
+                                             server_ids):
+            if server_connect['data']['connected']:
+                data = utils.get_role_data()
+                response = self.tester.post(self.url + str(server_group) + '/'
+                                            + server_id + '/',
+                                            data=json.dumps(data),
+                                            content_type='html/json')
+                self.assertTrue(response.status_code, 200)
+                response_data = json.loads(response.data.decode('utf-8'))
+                utils.write_role_id(response_data)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_role(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py
new file mode 100644
index 0000000..47769cb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py
@@ -0,0 +1,63 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+
+import json
+from regression import test_utils as utils
+from pgadmin.utils.route import BaseTestGenerator
+from test_setup import config_data
+from regression.test_utils import get_ids
+
+
+class LoginRoleDeleteTestCase(BaseTestGenerator):
+    """This class has delete role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    def setUp(self):
+        """This function used to add the server"""
+
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the role
+        utils.add_role(self.tester, server_connect_response, server_group,
+                       server_ids)
+
+    def runTest(self):
+        """This function tests the delete role scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            role_response = utils.verify_role(self.tester, srv_grp, server_id,
+                                              role_id)
+            if len(role_response) == 0:
+                raise Exception("No roles(s) to delete!!!")
+            response = self.tester.delete(self.url + str(srv_grp) + '/' +
+                                          str(server_id) + '/' + str(role_id),
+                                          follow_redirects=True)
+            delete_response_data = json.loads(response.data.decode('utf-8'))
+            self.assertTrue(delete_response_data['success'], 1)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py
new file mode 100644
index 0000000..3c2ed9c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py
@@ -0,0 +1,53 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from regression import test_utils as utils
+from test_setup import config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression.test_utils import get_ids
+
+
+class LoginRoleGetTestCase(BaseTestGenerator):
+    """This class tests the get role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    def setUp(self):
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the role
+        utils.add_role(self.tester, server_connect_response, server_group,
+                       server_ids)
+
+    def runTest(self):
+        """This function test the get role scenario"""
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            response = self.tester.get(self.url + str(srv_grp) + '/' +
+                                       str(server_id) + '/' + str(role_id),
+                                       follow_redirects=True)
+            self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_role(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py
new file mode 100644
index 0000000..b1f8ba2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py
@@ -0,0 +1,68 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression import test_utils as utils
+from test_setup import config_data, advanced_config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression.test_utils import get_ids
+
+
+class LoginRolePutTestCase(BaseTestGenerator):
+    """This class has update role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    def setUp(self):
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the role
+        utils.add_role(self.tester, server_connect_response, server_group,
+                       server_ids)
+
+    def runTest(self):
+        """This function tests the update role data scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            role_response = utils.verify_role(self.tester, srv_grp, server_id,
+                                              role_id)
+            if len(role_response) == 0:
+                raise Exception("No roles(s) to update!!!")
+
+            data = {
+                "description": advanced_config_data["test_lr_update_data"]
+                ["test_comment"],
+                "lrid": role_id
+            }
+            put_response = self.tester.put(self.url + str(srv_grp) + '/' +
+                                           str(server_id) + '/' + str(role_id),
+                                           data=json.dumps(data),
+                                           follow_redirects=True)
+
+            self.assertEquals(put_response.status_code, 200)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_role(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py
new file mode 100644
index 0000000..3302027
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py
@@ -0,0 +1,16 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class TblspaceGeneratorTestCase(BaseTestGenerator):
+
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py
new file mode 100644
index 0000000..48c7628
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py
@@ -0,0 +1,53 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression import test_utils as utils
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class TableSpaceAddTestCase(BaseTestGenerator):
+    """This class will add tablespace node under server"""
+
+    scenarios = [
+        # Fetching default URL for tablespace node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    def setUp(self):
+        """This function used to add the sever"""
+
+        # Add the server
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """This function test the add tablespace scenario"""
+
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, True)
+
+        for server_connect, server_id in zip(server_connect_response,
+                                             server_ids):
+            if server_connect['data']['connected']:
+                data = utils.get_tablespace_data(server_connect)
+                response = self.tester.post(self.url + str(server_group) + '/'
+                                            + server_id + '/',
+                                            data=json.dumps(data),
+                                            content_type='html/json')
+                self.assertTrue(response.status_code, 200)
+                response_data = json.loads(response.data.decode('utf-8'))
+                utils.write_tablespace_id(response_data)
+
+    def tearDown(self):
+        """This function deletes the tablespace,server and parent id file"""
+
+        utils.delete_table_space(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py
new file mode 100644
index 0000000..298a8e8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py
@@ -0,0 +1,65 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+from regression import test_utils as utils
+from pgadmin.utils.route import BaseTestGenerator
+from test_setup import config_data
+from regression.test_utils import get_ids
+
+
+class TableSpaceDeleteTestCase(BaseTestGenerator):
+    """This class has delete table space scenario"""
+
+    scenarios = [
+        # Fetching default URL for tablespace node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    def setUp(self):
+        """This function used to add the server"""
+
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the table space
+        utils.add_table_space(self.tester, server_connect_response,
+                              server_group,
+                              server_ids)
+
+    def runTest(self):
+        """This function tests the delete table space scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        table_space_ids_dict = all_id["table_space_id"][0]
+
+        for server_id in server_ids:
+            table_space_id = table_space_ids_dict[int(server_id)]
+            table_space_response = utils.verify_table_space(self.tester,
+                                                            srv_grp, server_id,
+                                                            table_space_id)
+            if len(table_space_response) == 0:
+                raise Exception("No tablespace(s) to delete!!!")
+
+            response = self.tester.delete(self.url + str(srv_grp) + '/' +
+                                          str(server_id) + '/' + str(
+                table_space_id),
+                                          follow_redirects=True)
+            delete_response_data = json.loads(response.data.decode('utf-8'))
+            self.assertTrue(delete_response_data['success'], 1)
+
+    def tearDown(self):
+        """This function deletes the server and parent id file"""
+
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py
new file mode 100644
index 0000000..45e12c0
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py
@@ -0,0 +1,59 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from regression import test_utils as utils
+from test_setup import config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression.test_utils import get_ids
+
+
+class TablespaceGetTestCase(BaseTestGenerator):
+    """This class tests the get table space scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    def setUp(self):
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the table space
+        utils.add_table_space(self.tester, server_connect_response,
+                              server_group,
+                              server_ids)
+
+    def runTest(self):
+        """This function test the get table space scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        tablespace_ids_dict = all_id["table_space_id"][0]
+
+        for server_id in server_ids:
+            tablespace_id = tablespace_ids_dict[int(server_id)]
+            server_response = utils.verify_server(self.tester, srv_grp,
+                                                  server_id)
+            if server_response['data']['connected']:
+                response = self.tester.get(self.url + str(srv_grp) + '/' +
+                                           str(server_id) + '/' + str(
+                    tablespace_id),
+                                           follow_redirects=True)
+                self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_table_space(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py
new file mode 100644
index 0000000..927640f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py
@@ -0,0 +1,72 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression import test_utils as utils
+from test_setup import config_data, advanced_config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression.test_utils import get_ids
+
+
+class TableSpaceUpdateTestCase(BaseTestGenerator):
+    """This class has update tablespace scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    def setUp(self):
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the tablespace
+        utils.add_table_space(self.tester, server_connect_response,
+                              server_group,
+                              server_ids)
+
+    def runTest(self):
+        """This function tests the update tablespace data scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        tablespace_ids_dict = all_id["table_space_id"][0]
+
+        for server_id in server_ids:
+            tablespace_id = tablespace_ids_dict[int(server_id)]
+            tablespace_response = utils.verify_table_space(self.tester,
+                                                           srv_grp, server_id,
+                                                           tablespace_id)
+            if len(tablespace_response) == 0:
+                raise Exception("No tablespace(s) to update!!!")
+
+            data = {
+                "description": advanced_config_data["test_tbspc_update_data"]
+                ["test_comment"],
+                "table_space_id": tablespace_id
+            }
+
+            put_response = self.tester.put(self.url + str(srv_grp) + '/' +
+                                           str(server_id) + '/' + str(
+                tablespace_id),
+                                           data=json.dumps(data),
+                                           follow_redirects=True)
+
+            self.assertEquals(put_response.status_code, 200)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_table_space(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_add.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_add.py
index 2b1eb45..37d6949 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_add.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_add.py
@@ -32,10 +32,8 @@ class ServersAddTestCase(BaseTestGenerator):
             url = "{0}{1}/".format(self.url, server_group)
             response = self.tester.post(url, data=json.dumps(server_data),
                                         content_type='html/json')
-
             self.assertTrue(response.status_code, 200)
-
-            response_data = json.loads(response.data.decode())
+            response_data = json.loads(response.data.decode('utf-8'))
             utils.write_parent_id(response_data, pickle_id_dict)
 
     def tearDown(self):
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 5e810ba..9973359 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -68,5 +68,6 @@ class ServerUpdateTestCase(BaseTestGenerator):
         :return: None
         """
 
+        utils.delete_database(self.tester)
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index 2f714a7..3dbd386 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -11,6 +11,8 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.test_setup import config_data
+from regression import test_utils as utils
+from utils import change_password
 
 
 class ChangePasswordTestCase(BaseTestGenerator):
@@ -56,51 +58,58 @@ class ChangePasswordTestCase(BaseTestGenerator):
                 ['test_new_password']),
             respdata='Invalid password')),
 
-        # This testcase checks for valid password
+        # This test case checks for valid password
         ('TestCase for Changing Valid_Password', dict(
-            password=(config_data['pgAdmin4_login_credentials']
+            valid_password='reassigning_password',
+            username=(config_data['pgAdmin4_test_user_credentials']
+                      ['test_login_username']),
+            password=(config_data['pgAdmin4_test_user_credentials']
                       ['test_login_password']),
-            new_password=(config_data['pgAdmin4_login_credentials']
+            new_password=(config_data['pgAdmin4_test_user_credentials']
                           ['test_new_password']),
             new_password_confirm=(
-                config_data['pgAdmin4_login_credentials']
+                config_data['pgAdmin4_test_user_credentials']
                 ['test_new_password']),
-            respdata='You successfully changed your password.')),
-        ('Reassigning_Password', dict(
-            test_case='reassigning_password',
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_new_password']),
-            new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_login_password']),
-            new_password_confirm=(
-                config_data['pgAdmin4_login_credentials']
-                ['test_login_password']),
             respdata='You successfully changed your password.'))
-
     ]
 
+    def setUp(self):
+        pass
+
     def runTest(self):
         """This function will check change password functionality."""
 
-        # Check for 'test_case' exists in self For reassigning the password.
-        # Password gets change in change password test case.
-        if 'test_case' in dir(self):
-            email = \
-                config_data['pgAdmin4_login_credentials'][
-                    'test_login_username']
-            password = \
-                config_data['pgAdmin4_login_credentials'][
-                    'test_new_password']
+        # Check for 'valid_password' exists in self to test 'valid password'
+        # test case
+        if 'valid_password' in dir(self):
+            response = self.tester.post('/user_management/user/', data=dict(
+                email=self.username, newPassword=self.password,
+                confirmPassword=self.password, active=1, role="2"),
+                                        follow_redirects=True)
+            assert response.status_code == 200
+
+            # Logout the Administrator before login normal user
+            utils.logout_tester_account(self.tester)
+
             response = self.tester.post('/login', data=dict(
-                email=email, password=password), follow_redirects=True)
-
-        response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data.decode(
-            'utf-8'))
-
-        response = self.tester.post('/change', data=dict(
-            password=self.password,
-            new_password=self.new_password,
-            new_password_confirm=self.new_password_confirm),
-                                    follow_redirects=True)
-        self.assertIn(self.respdata, response.data.decode('utf-8'))
+                email=self.username, password=self.password),
+                                        follow_redirects=True)
+            assert response.status_code == 200
+
+            # test the 'change password' test case
+            change_password(self)
+
+            # Delete the normal user after changing it's password
+            utils.logout_tester_account(self.tester)
+
+            # Login the Administrator before deleting normal user
+            utils.login_tester_account(self.tester)
+            response = self.tester.delete('/user_management/user/2',
+                                          follow_redirects=True)
+            assert response.status_code == 200
+        else:
+            change_password(self)
+
+    def tearDown(self):
+        utils.login_tester_account(self.tester)
+
diff --git a/web/pgadmin/browser/tests/utils.py b/web/pgadmin/browser/tests/utils.py
new file mode 100644
index 0000000..18548ce
--- /dev/null
+++ b/web/pgadmin/browser/tests/utils.py
@@ -0,0 +1,21 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+
+def change_password(self):
+    response = self.tester.get('/change', follow_redirects=True)
+    self.assertIn('pgAdmin 4 Password Change', response.data.decode(
+        'utf-8'))
+
+    response = self.tester.post('/change', data=dict(
+        password=self.password,
+        new_password=self.new_password,
+        new_password_confirm=self.new_password_confirm),
+                                follow_redirects=True)
+    self.assertIn(self.respdata, response.data.decode('utf-8'))
\ No newline at end of file
diff --git a/web/regression/test_advanced_config.json.in b/web/regression/test_advanced_config.json.in
index c0d278b..8b679ad 100644
--- a/web/regression/test_advanced_config.json.in
+++ b/web/regression/test_advanced_config.json.in
@@ -194,6 +194,50 @@
   {
       "test_comment": "This is db update comment"
   }
- ]
+ ],
+ "test_lr_credentials": {
+      "test_can_login": "true",
+      "test_conn_limit": -1,
+      "test_create_role": "true",
+      "test_role_inherit": "true",
+      "test_role_membership": [],
+      "test_lr_name":  "testlrg1",
+      "test_lr_password": "edb",
+      "test_lr_validity": "12/27/2016",
+      "test_sec_lable": [],
+      "test_variable":[
+                        {"name":"work_mem",
+                          "database":"postgres",
+                          "value":65
+                        }]
+    },
+  "test_lr_update_data": {
+      "test_comment": "This is db update comment"
+  },
+
+  "test_tablespc_credentials":[{
+    "test_tblspace_name": "test_tablespace",
+    "test_spc_seclable": [],
+    "test_spc_acl": [
+      {
+        "grantee":"postgres",
+        "grantor":"postgres",
+        "privileges":[
+          {
+            "privilege_type":"C",
+            "privilege":true,
+            "with_grant":false
+          }
+        ]
+      }
+    ],
+    "test_spc_location": "/Library/PostgreSQL/9.6/data",
+    "test_spc_opts": [],
+    "test_spc_user": "postgres"
+  }],
+
+    "test_tbspc_update_data": {
+    "test_comment": "This is tablespace update comment"
+  }
 
-}
\ No newline at end of file
+}
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index 028d1e7..9fcf197 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -4,6 +4,11 @@
     "test_login_password": "PASSWORD",
     "test_login_username": "[email protected]"
   },
+  "pgAdmin4_test_user_credentials": {
+    "test_new_password": "NEWPASSWORD",
+    "test_login_password": "PASSWORD",
+    "test_login_username": "[email protected]"
+  },
   "test_server_group": 1,
   "test_server_credentials": [
     {
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
index 6be2bb2..18c5981 100644
--- a/web/regression/test_utils.py
+++ b/web/regression/test_utils.py
@@ -19,6 +19,20 @@ SERVER_URL = '/browser/server/obj/'
 SERVER_CONNECT_URL = 'browser/server/connect/'
 DATABASE_URL = '/browser/database/obj/'
 DATABASE_CONNECT_URL = 'browser/database/connect/'
+ROLE_URL = '/browser/role/obj/'
+TABLE_SPACE_URL = '/browser/tablespace/obj/'
+
+
+def get_pickle_id_dict():
+    """This function returns the empty dict of server config data"""
+
+    pickle_id_dict = {
+        "sid": [],  # server
+        "did": [],  # database
+        "lrid": [],  # role
+        "table_space_id": []  # tablespace
+    }
+    return pickle_id_dict
 
 
 def get_ids(url=pickle_path):
@@ -34,10 +48,22 @@ def get_ids(url=pickle_path):
     output = open(url, 'rb')
     ids = pickle.load(output)
     output.close()
-
     return ids
 
 
+def verify_server(tester, server_group, server_id):
+    """This function verifies that server is connecting or not"""
+
+    response = tester.post(
+        '{0}{1}/{2}'.format(SERVER_CONNECT_URL, server_group, server_id),
+        data=dict(password=config_data
+        ['test_server_credentials'][0]
+        ['test_db_password']),
+        follow_redirects=True)
+    srv_connect = json.loads(response.data.decode('utf-8'))
+    return srv_connect
+
+
 def verify_database(tester, server_group, server_id, db_id):
     """
     This function verifies that database is exists and whether it connect
@@ -158,6 +184,7 @@ def logout_tester_account(tester):
     response = tester.get('/logout')
 
 
+# Config data for parent_id.pkl
 def get_config_data():
     """
     This function get the data related to server group and database
@@ -168,12 +195,7 @@ def get_config_data():
     """
 
     db_data = []
-
-    pickle_id_dict = {
-        "sid": [],  # server
-        "did": []  # database
-    }
-
+    pickle_id_dict = get_pickle_id_dict()
     server_group = config_data['test_server_group']
 
     for srv in config_data['test_server_credentials']:
@@ -205,7 +227,7 @@ def write_parent_id(response_data, pickle_id_dict):
         existed_server_id = open(pickle_path, 'rb')
         pickle_id_dict = pickle.load(existed_server_id)
 
-    pickle_id_dict["sid"].append(server_id)
+    pickle_id_dict["sid"].append(str(server_id))
     output = open(pickle_path, 'wb')
     pickle.dump(pickle_id_dict, output)
     output.close()
@@ -223,20 +245,22 @@ def write_db_parent_id(response_data):
 
     db_id = response_data['node']['_id']
     server_id = response_data['node']['_pid']
+    # TODO: modify logic to write in file / file exists or create new
+    pickle_id_dict = get_pickle_id_dict()
     if os.path.isfile(pickle_path):
         existing_server_id = open(pickle_path, 'rb')
         tol_server_id = pickle.load(existing_server_id)
         pickle_id_dict = tol_server_id
-        if 'did' in pickle_id_dict:
-            if pickle_id_dict['did']:
-                # Add the db_id as value in dict
-                pickle_id_dict["did"][0].update({server_id: db_id})
-            else:
-                # Create new dict with server_id and db_id
-                pickle_id_dict["did"].append({server_id: db_id})
-        db_output = open(pickle_path, 'wb')
-        pickle.dump(pickle_id_dict, db_output)
-        db_output.close()
+    if 'did' in pickle_id_dict:
+        if pickle_id_dict['did']:
+            # Add the db_id as value in dict
+            pickle_id_dict["did"][0].update({server_id: db_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["did"].append({server_id: db_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
 
 
 def delete_parent_id_file():
@@ -265,7 +289,7 @@ def add_server(tester):
     for db_detail in db_data:
         response = tester.post(url, data=json.dumps(db_detail),
                                content_type='html/json')
-        response_data = json.loads(response.data.decode())
+        response_data = json.loads(response.data.decode('utf-8'))
         write_parent_id(response_data, pickle_id_dict)
 
 
@@ -289,12 +313,14 @@ def get_server(tester):
         response_data = json.loads(response.data.decode())
 
 
-def connect_server(tester):
+def connect_server(tester, add_db_flag=False):
     """
     This function used to connect added server
 
     :param tester:test client object
     :type tester: flask test object
+    :param add_db_flag: flag for db add test case
+    :type add_db_flag: bool
     :return: server_connect, server_group, server_id
     :rtype: server_connect:dict, server_group:dict, server_id:str
     """
@@ -315,9 +341,10 @@ def connect_server(tester):
                                    ['test_server_credentials'][0]
                                    ['test_db_password']),
                                follow_redirects=True)
-        server_connect_detail = json.loads(response.data.decode())
-        connect_database(tester, server_connect_detail, server_id,
-                         server_group)
+        server_connect_detail = json.loads(response.data.decode('utf-8'))
+        if not add_db_flag:
+            connect_database(tester, server_connect_detail, server_id,
+                             server_group)
         server_connect.append(server_connect_detail)
         servers.append(server_id)
     return server_connect, server_group, servers
@@ -345,7 +372,7 @@ def connect_database(tester, server_connect, server_id, server_group):
             DATABASE_URL + str(server_group) + "/" + server_id + "/",
             data=json.dumps(db_data),
             content_type='html/json')
-        response_data = json.loads(db_response.data.decode())
+        response_data = json.loads(db_response.data.decode('utf-8'))
         write_db_parent_id(response_data)
 
 
@@ -366,7 +393,7 @@ def delete_server(tester):
     for server_id in server_ids:
         response = tester.delete(url + str(server_id))
         assert response.status_code == 200
-        response_data = json.loads(response.data.decode())
+        response_data = json.loads(response.data.decode('utf-8'))
         assert response_data['success'] == 1
 
 
@@ -395,3 +422,309 @@ def delete_database(tester):
         assert response.status_code == 200
         response_data = json.loads(response.data.decode('utf-8'))
         assert response_data['success'] == 1
+
+
+# Roles utility
+def verify_role(tester, server_group, server_id, role_id):
+    """
+    This function calls the GET API for role to verify
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param role_id: role id
+    :type role_id: int
+    :return: dict/None
+    """
+
+    response = tester.post(
+        '{0}{1}/{2}'.format(SERVER_CONNECT_URL, server_group, server_id),
+        data=dict(password=config_data
+        ['test_server_credentials'][0]
+        ['test_db_password']),
+        follow_redirects=True)
+    srv_connect = json.loads(response.data.decode('utf-8'))
+    if srv_connect['data']['connected']:
+        response = tester.get(
+            '{0}{1}/{2}/{3}'.format(ROLE_URL, server_group, server_id,
+                                    role_id),
+            content_type='html/json')
+        temp_response = json.loads(response.data.decode('utf-8'))
+        return temp_response
+    else:
+        return None
+
+
+def test_getrole(tester):
+    if not tester:
+        return None
+
+    all_id = get_ids()
+
+    server_ids = all_id["sid"]
+    role_ids_dict = all_id["lrid"][0]
+    server_group = config_data['test_server_group']
+
+    role_response_data = []
+    for server_id in server_ids:
+        role_id = role_ids_dict[int(server_id)]
+        role_response_data.append(
+            verify_role(tester, server_group, server_id, role_id))
+    return role_response_data
+
+
+def get_role_data():
+    """This function returns the role data from config file"""
+
+    data = {
+        "rolcanlogin": advanced_config_data['test_lr_credentials']
+        ['test_can_login'],
+        "rolconnlimit": advanced_config_data['test_lr_credentials']
+        ['test_conn_limit'],
+        "rolcreaterole": advanced_config_data['test_lr_credentials']
+        ['test_create_role'],
+        "rolinherit": advanced_config_data['test_lr_credentials']
+        ['test_role_inherit'],
+        "rolmembership": advanced_config_data['test_lr_credentials']
+        ['test_role_membership'],
+        "rolname": str(uuid.uuid4())[1:8],
+        "rolpassword": advanced_config_data['test_lr_credentials']
+        ['test_lr_password'],
+        "rolvaliduntil": advanced_config_data['test_lr_credentials']
+        ['test_lr_validity'],
+        "seclabels": advanced_config_data['test_lr_credentials']
+        ['test_sec_lable'],
+        "variables": advanced_config_data['test_lr_credentials']
+        ['test_variable']
+    }
+    return data
+
+
+def add_role(tester, server_connect_response, server_group, server_ids):
+    """
+    This function is used to add the roles to server
+
+    :param tester: flask test client
+    :type tester: flask test client object
+    :param server_connect_response: server connect API response
+    :type server_connect_response: dict
+    :param server_group: server group
+    :type server_group: int
+    :param server_ids: list of server id
+    :type server_ids: list
+    :return: None
+    """
+
+    for server_connect, server_id in zip(server_connect_response,
+                                         server_ids):
+        if server_connect['data']['connected']:
+            data = get_role_data()
+            response = tester.post(ROLE_URL + str(server_group) + '/'
+                                   + server_id + '/', data=json.dumps(data),
+                                   content_type='html/json')
+            assert response.status_code == 200
+            response_data = json.loads(response.data.decode('utf-8'))
+            write_role_id(response_data)
+
+
+def write_role_id(response_data):
+    """
+
+    :param response_data:
+    :return:
+    """
+
+    lr_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = get_pickle_id_dict()
+    # TODO: modify logic to write in file / file exists or create new check
+    # old file
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'lrid' in pickle_id_dict:
+        if pickle_id_dict['lrid']:
+            # Add the db_id as value in dict
+            pickle_id_dict["lrid"][0].update({server_id: lr_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["lrid"].append({server_id: lr_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def delete_role(tester):
+    """
+    This function use to delete the existing roles in the servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :return: None
+    """
+
+    srv_grp = config_data['test_server_group']
+    all_id = get_ids()
+    server_ids = all_id["sid"]
+    role_ids_dict = all_id["lrid"][0]
+
+    for server_id in server_ids:
+        role_id = role_ids_dict[int(server_id)]
+        role_response = verify_role(tester, srv_grp, server_id,
+                                    role_id)
+        if len(role_response) == 0:
+            raise Exception("No roles(s) to delete!!!")
+        response = tester.delete(ROLE_URL + str(srv_grp) + '/' +
+                                 str(server_id) + '/' + str(role_id),
+                                 follow_redirects=True)
+        assert response.status_code == 200
+        delete_response_data = json.loads(response.data.decode('utf-8'))
+        assert delete_response_data['success'] == 1
+
+
+# Tablespace utility
+def get_tablespace_data(server_connect):
+    """This function returns the tablespace data from config file"""
+
+    adv_config_data = None
+    data = None
+    db_user = server_connect['data']['user']['name']
+
+    # Get the config data of appropriate db user
+    for config_test_data in advanced_config_data['test_tablespc_credentials']:
+        if db_user == config_test_data['test_spc_user']:
+            adv_config_data = config_test_data
+
+    if adv_config_data is not None:
+        data = {
+            "name": str(uuid.uuid4())[1:8],
+            "seclabels": adv_config_data["test_spc_seclable"],
+            "spcacl": adv_config_data["test_spc_acl"],
+            "spclocation": adv_config_data["test_spc_location"],
+            "spcoptions": adv_config_data["test_spc_opts"],
+            "spcuser": adv_config_data["test_spc_user"]
+        }
+    return data
+
+
+def write_tablespace_id(response_data):
+    """
+    This function write the table space id to parent_id.pkl
+
+    :param response_data: create table space API response data
+    :type response_data: dict
+    :return: None
+    """
+
+    table_space_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = get_pickle_id_dict()
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'table_space_id' in pickle_id_dict:
+        if pickle_id_dict['table_space_id']:
+            # Add the db_id as value in dict
+            pickle_id_dict["table_space_id"][0].update(
+                {server_id: table_space_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["table_space_id"].append(
+                {server_id: table_space_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def add_table_space(tester, server_connect_response, server_group, server_ids):
+    """
+    This function is used to add the roles to server
+
+    :param tester: flask test client
+    :type tester: flask test client object
+    :param server_connect_response: server connect API response
+    :type server_connect_response: dict
+    :param server_group: server group
+    :type server_group: int
+    :param server_ids: list of server id
+    :type server_ids: list
+    :return: None
+    """
+
+    for server_connect, server_id in zip(server_connect_response,
+                                         server_ids):
+        if server_connect['data']['connected']:
+            data = get_tablespace_data(server_connect)
+            response = tester.post(TABLE_SPACE_URL + str(server_group) + '/'
+                                   + server_id + '/',
+                                   data=json.dumps(data),
+                                   content_type='html/json')
+            assert response.status_code == 200
+            response_data = json.loads(response.data.decode('utf-8'))
+            write_tablespace_id(response_data)
+
+
+def verify_table_space(tester, server_group, server_id, tablespace_id):
+    """
+    This function calls the GET API for role to verify
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param tablespace_id: table space id
+    :type tablespace_id: int
+    :return: dict/None
+    """
+
+    response = tester.post(
+        '{0}{1}/{2}'.format(SERVER_CONNECT_URL, server_group, server_id),
+        data=dict(password=config_data
+        ['test_server_credentials'][0]
+        ['test_db_password']),
+        follow_redirects=True)
+    srv_connect = json.loads(response.data.decode('utf-8'))
+    if srv_connect['data']['connected']:
+        response = tester.get(
+            '{0}{1}/{2}/{3}'.format(TABLE_SPACE_URL, server_group, server_id,
+                                    tablespace_id),
+            content_type='html/json')
+        temp_response = json.loads(response.data.decode('utf-8'))
+        return temp_response
+    else:
+        return None
+
+
+def delete_table_space(tester):
+    """
+    This function use to delete the existing tablespace in the servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :return: None
+    """
+
+    srv_grp = config_data['test_server_group']
+    all_id = get_ids()
+    server_ids = all_id["sid"]
+    tablespace_ids_dict = all_id["table_space_id"][0]
+
+    for server_id in server_ids:
+        tablespace_id = tablespace_ids_dict[int(server_id)]
+        role_response = verify_table_space(tester, srv_grp, server_id,
+                                           tablespace_id)
+        if len(role_response) == 0:
+            raise Exception("No tablespace(s) to delete!!!")
+        response = tester.delete(TABLE_SPACE_URL + str(srv_grp) + '/' +
+                                 str(server_id) + '/' + str(tablespace_id),
+                                 follow_redirects=True)
+        assert response.status_code == 200
+        delete_response_data = json.loads(response.data.decode('utf-8'))
+        assert delete_response_data['success'] == 1


view thread (29+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected]
  Subject: Re: pgAdmin IV : Unittest modular patch
  In-Reply-To: <CAOAJCYq94E=zhaVWWUORP62nSD-PJ2y2crJeL41Mmv-50i-VbQ@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox