You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2021/06/06 23:22:02 UTC

[commons-dbcp] 01/02: Sort members.

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git

commit 6272dd6204a8b5cb6be07c92cece94bf540d6172
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Jun 6 13:48:15 2021 -0400

    Sort members.
---
 .../datasources/TestPerUserPoolDataSource.java     | 1258 ++++++++++----------
 1 file changed, 629 insertions(+), 629 deletions(-)

diff --git a/src/test/java/org/apache/commons/dbcp2/datasources/TestPerUserPoolDataSource.java b/src/test/java/org/apache/commons/dbcp2/datasources/TestPerUserPoolDataSource.java
index a261ce9..8acb85f 100644
--- a/src/test/java/org/apache/commons/dbcp2/datasources/TestPerUserPoolDataSource.java
+++ b/src/test/java/org/apache/commons/dbcp2/datasources/TestPerUserPoolDataSource.java
@@ -51,13 +51,13 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
 
     private String user;
 
+    private DataSource ds;
+
     @Override
     protected Connection getConnection() throws SQLException {
         return ds.getConnection(user,"bar");
     }
 
-    private DataSource ds;
-
     @BeforeEach
     public void setUp() throws Exception {
         user = "foo";
@@ -87,76 +87,65 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         ((PerUserPoolDataSource) ds).close();
     }
 
-    /**
-     * Switching 'u1 to 'u2' and 'p1' to 'p2' will
-     * exhibit the bug detailed in
-     * https://issues.apache.org/bugzilla/show_bug.cgi?id=18905
-     */
+    // See DBCP-8
     @Test
-    public void testIncorrectPassword() throws Exception {
-        // Use bad password
-        try (Connection c = ds.getConnection("u1", "zlsafjk")){
-            fail("Able to retrieve connection with incorrect password");
-        } catch (final SQLException e1) {
-            // should fail
-
-        }
-
-        // Use good password
-        ds.getConnection("u1", "p1").close();
-        try (Connection c = ds.getConnection("u1", "x")){
-            fail("Able to retrieve connection with incorrect password");
-        } catch (final SQLException e) {
-            if (!e.getMessage().startsWith("Given password did not match")) {
-                throw e;
-            }
-            // else the exception was expected
-        }
-
-        // Make sure we can still use our good password.
-        ds.getConnection("u1", "p1").close();
-
-        // Try related users and passwords
-        ds.getConnection(user, "bar").close();
-        try (Connection c = ds.getConnection("foob", "ar")) {
-            fail("Should have caused an SQLException");
-        } catch (final SQLException expected) {
-        }
-        try (Connection c = ds.getConnection(user, "baz")){
+    public void testChangePassword() throws Exception {
+        try (Connection c = ds.getConnection(user, "bay")){
             fail("Should have generated SQLException");
         } catch (final SQLException expected) {
         }
+        final Connection con1 = ds.getConnection(user, "bar");
+        final Connection con2 = ds.getConnection(user, "bar");
+        final Connection con3 = ds.getConnection(user, "bar");
+        con1.close();
+        con2.close();
+        TesterDriver.addUser(user,"bay"); // change the user/password setting
+        try {
+            final Connection con4 = ds.getConnection(user, "bay"); // new password
+            // Idle instances with old password should have been cleared
+            assertEquals(0, ((PerUserPoolDataSource) ds).getNumIdle(user),
+                    "Should be no idle connections in the pool");
+            con4.close();
+            // Should be one idle instance with new pwd
+            assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user),
+                    "Should be one idle connection in the pool");
+            try (Connection c = ds.getConnection(user, "bar")) { // old password
+                fail("Should have generated SQLException");
+            } catch (final SQLException expected) {
+            }
+            final Connection con5 = ds.getConnection(user, "bay"); // take the idle one
+            con3.close(); // Return a connection with the old password
+            ds.getConnection(user, "bay").close();  // will try bad returned connection and destroy it
+            assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user),
+                    "Should be one idle connection in the pool");
+            con5.close();
+        } finally {
+            TesterDriver.addUser(user,"bar");
+        }
     }
 
     @Override
     @Test
-    public void testSimple() throws Exception
+    public void testClosing()
+        throws Exception
     {
-        final Connection conn = ds.getConnection();
-        assertNotNull(conn);
-        final PreparedStatement stmt = conn.prepareStatement("select * from dual");
-        assertNotNull(stmt);
-        final ResultSet rset = stmt.executeQuery();
-        assertNotNull(rset);
-        assertTrue(rset.next());
-        rset.close();
-        stmt.close();
-        conn.close();
-    }
+        final Connection[] c = new Connection[getMaxTotal()];
+        // open the maximum connections
+        for (int i=0; i<c.length; i++)
+        {
+            c[i] = ds.getConnection();
+        }
 
-    @Test
-    public void testSimpleWithUsername() throws Exception
-    {
-        final Connection conn = ds.getConnection("u1", "p1");
-        assertNotNull(conn);
-        final PreparedStatement stmt = conn.prepareStatement("select * from dual");
-        assertNotNull(stmt);
-        final ResultSet rset = stmt.executeQuery();
-        assertNotNull(rset);
-        assertTrue(rset.next());
-        rset.close();
-        stmt.close();
-        conn.close();
+        // close one of the connections
+        c[0].close();
+        assertTrue(c[0].isClosed());
+
+        // get a new connection
+        c[0] = ds.getConnection();
+
+        for (final Connection element : c) {
+            element.close();
+        }
     }
 
     @Test
@@ -190,104 +179,86 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         }
     }
 
-    @Override
+    // see issue https://issues.apache.org/bugzilla/show_bug.cgi?id=23843
     @Test
-    public void testSimple2()
-        throws Exception
-    {
-        Connection conn = ds.getConnection();
-        assertNotNull(conn);
-
-        PreparedStatement stmt =
-            conn.prepareStatement("select * from dual");
-        assertNotNull(stmt);
-        ResultSet rset = stmt.executeQuery();
-        assertNotNull(rset);
-        assertTrue(rset.next());
-        rset.close();
-        stmt.close();
-
-        stmt = conn.prepareStatement("select * from dual");
-        assertNotNull(stmt);
-        rset = stmt.executeQuery();
-        assertNotNull(rset);
-        assertTrue(rset.next());
-        rset.close();
-        stmt.close();
+    public void testDefaultUser1() throws Exception {
+        TesterDriver.addUser("mkh", "password");
+        TesterDriver.addUser("hanafey", "password");
+        TesterDriver.addUser("jsmith", "password");
 
-        conn.close();
-        try (Statement s = conn.createStatement()){
-            fail("Can't use closed connections");
-        } catch(final SQLException e) {
-            // expected
+        final PerUserPoolDataSource puds = (PerUserPoolDataSource) ds;
+        puds.setPerUserMaxTotal("jsmith", 2);
+        final String[] users = {"mkh", "hanafey", "jsmith"};
+        final String password = "password";
+        final Connection[] c = new Connection[users.length];
+        for (int i = 0; i < users.length; i++) {
+            c[i] = puds.getConnection(users[i], password);
+            assertEquals(users[i], getUsername(c[i]));
+        }
+        for (int i = 0; i < users.length; i++) {
+            c[i].close();
         }
-
-        conn = ds.getConnection();
-        assertNotNull(conn);
-
-        stmt = conn.prepareStatement("select * from dual");
-        assertNotNull(stmt);
-        rset = stmt.executeQuery();
-        assertNotNull(rset);
-        assertTrue(rset.next());
-        rset.close();
-        stmt.close();
-
-        stmt = conn.prepareStatement("select * from dual");
-        assertNotNull(stmt);
-        rset = stmt.executeQuery();
-        assertNotNull(rset);
-        assertTrue(rset.next());
-        rset.close();
-        stmt.close();
-
-        conn.close();
-        conn = null;
     }
 
-    @Override
+    // see issue https://issues.apache.org/bugzilla/show_bug.cgi?id=23843
     @Test
-    public void testOpening()
-        throws Exception
-    {
-        final Connection[] c = new Connection[getMaxTotal()];
-        // test that opening new connections is not closing previous
-        for (int i=0; i<c.length; i++)
-        {
-            c[i] = ds.getConnection();
-            assertNotNull(c[i]);
-            for (int j=0; j<=i; j++)
-            {
-                assertFalse(c[j].isClosed());
-            }
-        }
+    public void testDefaultUser2() throws Exception {
+        TesterDriver.addUser("mkh", "password");
+        TesterDriver.addUser("hanafey", "password");
+        TesterDriver.addUser("jsmith", "password");
 
-        for (final Connection element : c) {
-            element.close();
+        final PerUserPoolDataSource puds = (PerUserPoolDataSource) ds;
+        puds.setPerUserMaxTotal("jsmith", 2);
+        final String[] users = {"jsmith", "hanafey", "mkh"};
+        final String password = "password";
+        final Connection[] c = new Connection[users.length];
+        for (int i = 0; i < users.length; i++) {
+            c[i] = puds.getConnection(users[i], password);
+            assertEquals(users[i], getUsername(c[i]));
+        }
+        for (int i = 0; i < users.length; i++) {
+            c[i].close();
         }
     }
 
-    @Override
+    /**
+     * Switching 'u1 to 'u2' and 'p1' to 'p2' will
+     * exhibit the bug detailed in
+     * https://issues.apache.org/bugzilla/show_bug.cgi?id=18905
+     */
     @Test
-    public void testClosing()
-        throws Exception
-    {
-        final Connection[] c = new Connection[getMaxTotal()];
-        // open the maximum connections
-        for (int i=0; i<c.length; i++)
-        {
-            c[i] = ds.getConnection();
+    public void testIncorrectPassword() throws Exception {
+        // Use bad password
+        try (Connection c = ds.getConnection("u1", "zlsafjk")){
+            fail("Able to retrieve connection with incorrect password");
+        } catch (final SQLException e1) {
+            // should fail
+
         }
 
-        // close one of the connections
-        c[0].close();
-        assertTrue(c[0].isClosed());
+        // Use good password
+        ds.getConnection("u1", "p1").close();
+        try (Connection c = ds.getConnection("u1", "x")){
+            fail("Able to retrieve connection with incorrect password");
+        } catch (final SQLException e) {
+            if (!e.getMessage().startsWith("Given password did not match")) {
+                throw e;
+            }
+            // else the exception was expected
+        }
 
-        // get a new connection
-        c[0] = ds.getConnection();
+        // Make sure we can still use our good password.
+        ds.getConnection("u1", "p1").close();
 
-        for (final Connection element : c) {
-            element.close();
+        // Try related users and passwords
+        ds.getConnection(user, "bar").close();
+        try (Connection c = ds.getConnection("foob", "ar")) {
+            fail("Should have caused an SQLException");
+        } catch (final SQLException expected) {
+        }
+        try (Connection c = ds.getConnection(user, "baz")){
+            fail("Should have generated SQLException");
+        } catch (final SQLException expected) {
         }
     }
 
@@ -331,56 +302,6 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserMethods() throws Exception {
-        final PerUserPoolDataSource tds = (PerUserPoolDataSource) ds;
-
-        // you need to set per user maxTotal otherwise there is no accounting
-        tds.setPerUserMaxTotal("u1", 5);
-        tds.setPerUserMaxTotal("u2", 5);
-
-        assertEquals(0, tds.getNumActive());
-        assertEquals(0, tds.getNumActive("u1"));
-        assertEquals(0, tds.getNumActive("u2"));
-        assertEquals(0, tds.getNumIdle());
-        assertEquals(0, tds.getNumIdle("u1"));
-        assertEquals(0, tds.getNumIdle("u2"));
-
-        Connection conn = tds.getConnection();
-        assertNotNull(conn);
-        assertEquals(1, tds.getNumActive());
-        assertEquals(0, tds.getNumActive("u1"));
-        assertEquals(0, tds.getNumActive("u2"));
-        assertEquals(0, tds.getNumIdle());
-        assertEquals(0, tds.getNumIdle("u1"));
-        assertEquals(0, tds.getNumIdle("u2"));
-
-        conn.close();
-        assertEquals(0, tds.getNumActive());
-        assertEquals(0, tds.getNumActive("u1"));
-        assertEquals(0, tds.getNumActive("u2"));
-        assertEquals(1, tds.getNumIdle());
-        assertEquals(0, tds.getNumIdle("u1"));
-        assertEquals(0, tds.getNumIdle("u2"));
-
-        conn = tds.getConnection("u1", "p1");
-        assertNotNull(conn);
-        assertEquals(0, tds.getNumActive());
-        assertEquals(1, tds.getNumActive("u1"));
-        assertEquals(0, tds.getNumActive("u2"));
-        assertEquals(1, tds.getNumIdle());
-        assertEquals(0, tds.getNumIdle("u1"));
-        assertEquals(0, tds.getNumIdle("u2"));
-
-        conn.close();
-        assertEquals(0, tds.getNumActive());
-        assertEquals(0, tds.getNumActive("u1"));
-        assertEquals(0, tds.getNumActive("u2"));
-        assertEquals(1, tds.getNumIdle());
-        assertEquals(1, tds.getNumIdle("u1"));
-        assertEquals(0, tds.getNumIdle("u2"));
-    }
-
-    @Test
     public void testMultipleThreads1() throws Exception {
         // Override wait time in order to allow for Thread.sleep(1) sometimes taking a lot longer on
         // some JVMs, e.g. Windows.
@@ -398,174 +319,26 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         multipleThreads(2 * defaultMaxWaitMillis, true, true, defaultMaxWaitMillis);
     }
 
+    @Override
     @Test
-    public void testTransactionIsolationBehavior() throws Exception {
-        final Connection conn = getConnection();
-        assertNotNull(conn);
-        assertEquals(Connection.TRANSACTION_READ_COMMITTED,
-                     conn.getTransactionIsolation());
-        conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
-        conn.close();
-
-        final Connection conn2 = getConnection();
-        assertEquals(Connection.TRANSACTION_READ_COMMITTED,
-                     conn2.getTransactionIsolation());
-
-        final Connection conn3 = getConnection();
-        assertEquals(Connection.TRANSACTION_READ_COMMITTED,
-                     conn3.getTransactionIsolation());
-        conn2.close();
-        conn3.close();
-    }
-
-    @Test
-    public void testSerialization() throws Exception {
-        // make sure the pool has initialized
-        final Connection conn = ds.getConnection();
-        conn.close();
-
-        // serialize
-        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        final ObjectOutputStream out = new ObjectOutputStream(baos);
-        out.writeObject(ds);
-        out.close();
-        final byte[] b = baos.toByteArray();
-
-        final ByteArrayInputStream bais = new ByteArrayInputStream(b);
-        final ObjectInputStream in = new ObjectInputStream(bais);
-        final Object obj = in.readObject();
-        in.close();
-
-        assertEquals( 1, ((PerUserPoolDataSource)obj).getNumIdle() );
-    }
-
-    // see issue https://issues.apache.org/bugzilla/show_bug.cgi?id=23843
-    // unregistered user is in the same pool as without user name
-    @Test
-    public void testUnregisteredUser() throws Exception {
-        final PerUserPoolDataSource tds = (PerUserPoolDataSource) ds;
-
-        assertEquals(0, tds.getNumActive());
-        assertEquals(0, tds.getNumIdle());
-
-        Connection conn = tds.getConnection();
-        assertNotNull(conn);
-        assertEquals(1, tds.getNumActive());
-        assertEquals(0, tds.getNumIdle());
-
-        conn.close();
-        assertEquals(0, tds.getNumActive());
-        assertEquals(1, tds.getNumIdle());
-
-        conn = tds.getConnection("u1", "p1");
-        assertNotNull(conn);
-        assertEquals(0, tds.getNumActive());
-        assertEquals(1, tds.getNumIdle());
-        assertEquals(1, tds.getNumActive("u1"));
-        assertEquals(0, tds.getNumIdle("u1"));
-
-        conn.close();
-        assertEquals(0, tds.getNumActive());
-        assertEquals(1, tds.getNumIdle());
-        assertEquals(0, tds.getNumActive("u1"));
-        assertEquals(1, tds.getNumIdle("u1"));
-    }
-
-    // see issue https://issues.apache.org/bugzilla/show_bug.cgi?id=23843
-    @Test
-    public void testDefaultUser1() throws Exception {
-        TesterDriver.addUser("mkh", "password");
-        TesterDriver.addUser("hanafey", "password");
-        TesterDriver.addUser("jsmith", "password");
-
-        final PerUserPoolDataSource puds = (PerUserPoolDataSource) ds;
-        puds.setPerUserMaxTotal("jsmith", 2);
-        final String[] users = {"mkh", "hanafey", "jsmith"};
-        final String password = "password";
-        final Connection[] c = new Connection[users.length];
-        for (int i = 0; i < users.length; i++) {
-            c[i] = puds.getConnection(users[i], password);
-            assertEquals(users[i], getUsername(c[i]));
-        }
-        for (int i = 0; i < users.length; i++) {
-            c[i].close();
-        }
-    }
-
-    // see issue https://issues.apache.org/bugzilla/show_bug.cgi?id=23843
-    @Test
-    public void testDefaultUser2() throws Exception {
-        TesterDriver.addUser("mkh", "password");
-        TesterDriver.addUser("hanafey", "password");
-        TesterDriver.addUser("jsmith", "password");
-
-        final PerUserPoolDataSource puds = (PerUserPoolDataSource) ds;
-        puds.setPerUserMaxTotal("jsmith", 2);
-        final String[] users = {"jsmith", "hanafey", "mkh"};
-        final String password = "password";
-        final Connection[] c = new Connection[users.length];
-        for (int i = 0; i < users.length; i++) {
-            c[i] = puds.getConnection(users[i], password);
-            assertEquals(users[i], getUsername(c[i]));
-        }
-        for (int i = 0; i < users.length; i++) {
-            c[i].close();
-        }
-    }
-
-    // See DBCP-8
-    @Test
-    public void testChangePassword() throws Exception {
-        try (Connection c = ds.getConnection(user, "bay")){
-            fail("Should have generated SQLException");
-        } catch (final SQLException expected) {
-        }
-        final Connection con1 = ds.getConnection(user, "bar");
-        final Connection con2 = ds.getConnection(user, "bar");
-        final Connection con3 = ds.getConnection(user, "bar");
-        con1.close();
-        con2.close();
-        TesterDriver.addUser(user,"bay"); // change the user/password setting
-        try {
-            final Connection con4 = ds.getConnection(user, "bay"); // new password
-            // Idle instances with old password should have been cleared
-            assertEquals(0, ((PerUserPoolDataSource) ds).getNumIdle(user),
-                    "Should be no idle connections in the pool");
-            con4.close();
-            // Should be one idle instance with new pwd
-            assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user),
-                    "Should be one idle connection in the pool");
-            try (Connection c = ds.getConnection(user, "bar")) { // old password
-                fail("Should have generated SQLException");
-            } catch (final SQLException expected) {
+    public void testOpening()
+        throws Exception
+    {
+        final Connection[] c = new Connection[getMaxTotal()];
+        // test that opening new connections is not closing previous
+        for (int i=0; i<c.length; i++)
+        {
+            c[i] = ds.getConnection();
+            assertNotNull(c[i]);
+            for (int j=0; j<=i; j++)
+            {
+                assertFalse(c[j].isClosed());
             }
-            final Connection con5 = ds.getConnection(user, "bay"); // take the idle one
-            con3.close(); // Return a connection with the old password
-            ds.getConnection(user, "bay").close();  // will try bad returned connection and destroy it
-            assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user),
-                    "Should be one idle connection in the pool");
-            con5.close();
-        } finally {
-            TesterDriver.addUser(user,"bar");
         }
-    }
-
-    // getters and setters. Most follow the same pattern. The initial tests contain a more
-    // complete documentation, which can be helpful when write/understanding the other methods.
 
-    // -- per user block when exhausted
-
-    /**
-     * Test per user block when exhausted, with the backing map not initialized before.
-     * Instead we pass the map.
-     */
-    @Test
-    public void testPerUserBlockWhenExhaustedMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Boolean> userDefaultBlockWhenExhausted = new HashMap<>();
-        userDefaultBlockWhenExhausted.put("key", Boolean.TRUE);
-        ds.setPerUserBlockWhenExhausted(userDefaultBlockWhenExhausted);
-        assertEquals(Boolean.TRUE, ds.getPerUserBlockWhenExhausted("key"));
+        for (final Connection element : c) {
+            element.close();
+        }
     }
 
     /**
@@ -592,27 +365,29 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
 
     /**
      * Test per user block when exhausted, with the backing map not initialized before.
-     * Instead, we pass the map. And furthermore, we are now searching for an inexistent
-     * key, which should return the default value.
+     * Instead we pass the map.
      */
     @Test
-    public void testPerUserBlockWhenExhaustedMapNotInitializedMissingKey() {
+    public void testPerUserBlockWhenExhaustedMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Boolean> userDefaultBlockWhenExhausted = new HashMap<>();
-        userDefaultBlockWhenExhausted.put("key", Boolean.FALSE);
+        userDefaultBlockWhenExhausted.put("key", Boolean.TRUE);
         ds.setPerUserBlockWhenExhausted(userDefaultBlockWhenExhausted);
-        assertEquals(ds.getDefaultBlockWhenExhausted(), ds.getPerUserBlockWhenExhausted("missingkey"));
+        assertEquals(Boolean.TRUE, ds.getPerUserBlockWhenExhausted("key"));
     }
 
     /**
      * Test per user block when exhausted, with the backing map not initialized before.
-     * Instead we pass the user and value, and hence the map is initialized beforehand.
+     * Instead, we pass the map. And furthermore, we are now searching for an inexistent
+     * key, which should return the default value.
      */
     @Test
-    public void testPerUserBlockWhenExhaustedWithUserMapNotInitialized() {
+    public void testPerUserBlockWhenExhaustedMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        ds.setPerUserBlockWhenExhausted(user, Boolean.FALSE);
-        assertEquals(Boolean.FALSE, ds.getPerUserBlockWhenExhausted(user));
+        final Map<String, Boolean> userDefaultBlockWhenExhausted = new HashMap<>();
+        userDefaultBlockWhenExhausted.put("key", Boolean.FALSE);
+        ds.setPerUserBlockWhenExhausted(userDefaultBlockWhenExhausted);
+        assertEquals(ds.getDefaultBlockWhenExhausted(), ds.getPerUserBlockWhenExhausted("missingkey"));
     }
 
     /**
@@ -637,6 +412,17 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     /**
      * Test per user block when exhausted, with the backing map not initialized before.
      * Instead we pass the user and value, and hence the map is initialized beforehand.
+     */
+    @Test
+    public void testPerUserBlockWhenExhaustedWithUserMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        ds.setPerUserBlockWhenExhausted(user, Boolean.FALSE);
+        assertEquals(Boolean.FALSE, ds.getPerUserBlockWhenExhausted(user));
+    }
+
+    /**
+     * Test per user block when exhausted, with the backing map not initialized before.
+     * Instead we pass the user and value, and hence the map is initialized beforehand.
      * Furthermore, we are now searching for an inexistent key, which should return the
      * default value.
      */
@@ -647,17 +433,6 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(Boolean.TRUE, ds.getPerUserBlockWhenExhausted("missingkey"));
     }
 
-    // -- per user default auto commit
-
-    @Test
-    public void testPerUserDefaultAutoCommitMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Boolean> values = new HashMap<>();
-        values.put("key", Boolean.TRUE);
-        ds.setPerUserDefaultAutoCommit(values);
-        assertEquals(Boolean.TRUE, ds.getPerUserDefaultAutoCommit("key"));
-    }
-
     @Test
     public void testPerUserDefaultAutoCommitMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -672,6 +447,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit("anonymous"));
     }
 
+    // getters and setters. Most follow the same pattern. The initial tests contain a more
+    // complete documentation, which can be helpful when write/understanding the other methods.
+
+    // -- per user block when exhausted
+
+    @Test
+    public void testPerUserDefaultAutoCommitMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Boolean> values = new HashMap<>();
+        values.put("key", Boolean.TRUE);
+        ds.setPerUserDefaultAutoCommit(values);
+        assertEquals(Boolean.TRUE, ds.getPerUserDefaultAutoCommit("key"));
+    }
+
     @Test
     public void testPerUserDefaultAutoCommitMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -683,20 +472,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserDefaultAutoCommitWithUserMapNotInitialized() {
+    public void testPerUserDefaultAutoCommitWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserDefaultAutoCommit(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit(user));
+        ds.setPerUserDefaultAutoCommit("anotheruser", Boolean.FALSE);
+        assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit(user));
+        assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit("anotheruser"));
     }
 
     @Test
-    public void testPerUserDefaultAutoCommitWithUserMapInitialized() {
+    public void testPerUserDefaultAutoCommitWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserDefaultAutoCommit(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit(user));
-        ds.setPerUserDefaultAutoCommit("anotheruser", Boolean.FALSE);
-        assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit(user));
-        assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit("anotheruser"));
     }
 
     @Test
@@ -707,17 +496,6 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertNull(ds.getPerUserDefaultAutoCommit("missingkey"));
     }
 
-    // -- per user default read only
-
-    @Test
-    public void testPerUserDefaultReadOnlyMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Boolean> values = new HashMap<>();
-        values.put("key", Boolean.TRUE);
-        ds.setPerUserDefaultReadOnly(values);
-        assertEquals(Boolean.TRUE, ds.getPerUserDefaultReadOnly("key"));
-    }
-
     @Test
     public void testPerUserDefaultReadOnlyMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -732,6 +510,17 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly("anonymous"));
     }
 
+    // -- per user default auto commit
+
+    @Test
+    public void testPerUserDefaultReadOnlyMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Boolean> values = new HashMap<>();
+        values.put("key", Boolean.TRUE);
+        ds.setPerUserDefaultReadOnly(values);
+        assertEquals(Boolean.TRUE, ds.getPerUserDefaultReadOnly("key"));
+    }
+
     @Test
     public void testPerUserDefaultReadOnlyMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -743,20 +532,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserDefaultReadOnlyWithUserMapNotInitialized() {
+    public void testPerUserDefaultReadOnlyWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserDefaultReadOnly(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly(user));
+        ds.setPerUserDefaultReadOnly("anotheruser", Boolean.FALSE);
+        assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly(user));
+        assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly("anotheruser"));
     }
 
     @Test
-    public void testPerUserDefaultReadOnlyWithUserMapInitialized() {
+    public void testPerUserDefaultReadOnlyWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserDefaultReadOnly(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly(user));
-        ds.setPerUserDefaultReadOnly("anotheruser", Boolean.FALSE);
-        assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly(user));
-        assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly("anotheruser"));
     }
 
     @Test
@@ -767,17 +556,6 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertNull(ds.getPerUserDefaultReadOnly("missingkey"));
     }
 
-    // -- per user default transaction isolation
-
-    @Test
-    public void testPerUserDefaultTransactionIsolationMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Integer> values = new HashMap<>();
-        values.put("key", 1);
-        ds.setPerUserDefaultTransactionIsolation(values);
-        assertEquals((Integer) 1, ds.getPerUserDefaultTransactionIsolation("key"));
-    }
-
     @Test
     public void testPerUserDefaultTransactionIsolationMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -793,6 +571,17 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation("anonymous"));
     }
 
+    // -- per user default read only
+
+    @Test
+    public void testPerUserDefaultTransactionIsolationMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Integer> values = new HashMap<>();
+        values.put("key", 1);
+        ds.setPerUserDefaultTransactionIsolation(values);
+        assertEquals((Integer) 1, ds.getPerUserDefaultTransactionIsolation("key"));
+    }
+
     @Test
     public void testPerUserDefaultTransactionIsolationMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -804,20 +593,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserDefaultTransactionIsolationWithUserMapNotInitialized() {
+    public void testPerUserDefaultTransactionIsolationWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserDefaultTransactionIsolation(user, 0);
         assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation(user));
+        ds.setPerUserDefaultTransactionIsolation("anotheruser", 0);
+        assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation(user));
+        assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation("anotheruser"));
     }
 
     @Test
-    public void testPerUserDefaultTransactionIsolationWithUserMapInitialized() {
+    public void testPerUserDefaultTransactionIsolationWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserDefaultTransactionIsolation(user, 0);
         assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation(user));
-        ds.setPerUserDefaultTransactionIsolation("anotheruser", 0);
-        assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation(user));
-        assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation("anotheruser"));
     }
 
     @Test
@@ -828,17 +617,6 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertNull(ds.getPerUserDefaultTransactionIsolation("missingkey"));
     }
 
-    // -- per user eviction policy class name
-
-    @Test
-    public void testPerUserEvictionPolicyClassNameMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, String> values = new HashMap<>();
-        values.put("key", "test");
-        ds.setPerUserEvictionPolicyClassName(values);
-        assertEquals("test", ds.getPerUserEvictionPolicyClassName("key"));
-    }
-
     @Test
     public void testPerUserEvictionPolicyClassNameMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -853,20 +631,24 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals("bar", ds.getPerUserEvictionPolicyClassName("anonymous"));
     }
 
+    // -- per user default transaction isolation
+
     @Test
-    public void testPerUserEvictionPolicyClassNameMapNotInitializedMissingKey() {
+    public void testPerUserEvictionPolicyClassNameMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, String> values = new HashMap<>();
-        values.put("key", "bar");
+        values.put("key", "test");
         ds.setPerUserEvictionPolicyClassName(values);
-        assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("missingkey"));
+        assertEquals("test", ds.getPerUserEvictionPolicyClassName("key"));
     }
 
     @Test
-    public void testPerUserEvictionPolicyClassNameWithUserMapNotInitialized() {
+    public void testPerUserEvictionPolicyClassNameMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        ds.setPerUserEvictionPolicyClassName(user, "bar");
-        assertEquals("bar", ds.getPerUserEvictionPolicyClassName(user));
+        final Map<String, String> values = new HashMap<>();
+        values.put("key", "bar");
+        ds.setPerUserEvictionPolicyClassName(values);
+        assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("missingkey"));
     }
 
     @Test
@@ -880,21 +662,17 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserEvictionPolicyClassNameWithUserMapNotInitializedMissingKey() {
+    public void testPerUserEvictionPolicyClassNameWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        ds.setPerUserEvictionPolicyClassName("whatismyuseragain?", "bar");
-        assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("missingkey"));
+        ds.setPerUserEvictionPolicyClassName(user, "bar");
+        assertEquals("bar", ds.getPerUserEvictionPolicyClassName(user));
     }
 
-    // -- per user lifo
-
     @Test
-    public void testPerUserLifoMapNotInitialized() {
+    public void testPerUserEvictionPolicyClassNameWithUserMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Boolean> values = new HashMap<>();
-        values.put("key", Boolean.TRUE);
-        ds.setPerUserLifo(values);
-        assertEquals(Boolean.TRUE, ds.getPerUserLifo("key"));
+        ds.setPerUserEvictionPolicyClassName("whatismyuseragain?", "bar");
+        assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("missingkey"));
     }
 
     @Test
@@ -911,20 +689,24 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(Boolean.FALSE, ds.getPerUserLifo("anonymous"));
     }
 
+    // -- per user eviction policy class name
+
     @Test
-    public void testPerUserLifoMapNotInitializedMissingKey() {
+    public void testPerUserLifoMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Boolean> values = new HashMap<>();
-        values.put("key", Boolean.FALSE);
+        values.put("key", Boolean.TRUE);
         ds.setPerUserLifo(values);
-        assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("missingkey"));
+        assertEquals(Boolean.TRUE, ds.getPerUserLifo("key"));
     }
 
     @Test
-    public void testPerUserLifoWithUserMapNotInitialized() {
+    public void testPerUserLifoMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        ds.setPerUserLifo(user, Boolean.FALSE);
-        assertEquals(Boolean.FALSE, ds.getPerUserLifo(user));
+        final Map<String, Boolean> values = new HashMap<>();
+        values.put("key", Boolean.FALSE);
+        ds.setPerUserLifo(values);
+        assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("missingkey"));
     }
 
     @Test
@@ -938,21 +720,17 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserLifoWithUserMapNotInitializedMissingKey() {
+    public void testPerUserLifoWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        ds.setPerUserLifo("whatismyuseragain?", Boolean.FALSE);
-        assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("missingkey"));
+        ds.setPerUserLifo(user, Boolean.FALSE);
+        assertEquals(Boolean.FALSE, ds.getPerUserLifo(user));
     }
 
-    // -- per user max idle
-
     @Test
-    public void testPerUserMaxIdleMapNotInitialized() {
+    public void testPerUserLifoWithUserMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Integer> values = new HashMap<>();
-        values.put("key", 1);
-        ds.setPerUserMaxIdle(values);
-        assertEquals((Integer) 1, (Integer) ds.getPerUserMaxIdle("key"));
+        ds.setPerUserLifo("whatismyuseragain?", Boolean.FALSE);
+        assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("missingkey"));
     }
 
     @Test
@@ -969,20 +747,24 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle("anonymous"));
     }
 
+    // -- per user lifo
+
     @Test
-    public void testPerUserMaxIdleMapNotInitializedMissingKey() {
+    public void testPerUserMaxIdleMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Integer> values = new HashMap<>();
-        values.put("key", 0);
+        values.put("key", 1);
         ds.setPerUserMaxIdle(values);
-        assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("missingkey"));
+        assertEquals((Integer) 1, (Integer) ds.getPerUserMaxIdle("key"));
     }
 
     @Test
-    public void testPerUserMaxIdleWithUserMapNotInitialized() {
+    public void testPerUserMaxIdleMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        ds.setPerUserMaxIdle(user, 0);
-        assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle(user));
+        final Map<String, Integer> values = new HashMap<>();
+        values.put("key", 0);
+        ds.setPerUserMaxIdle(values);
+        assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("missingkey"));
     }
 
     @Test
@@ -996,21 +778,17 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserMaxIdleWithUserMapNotInitializedMissingKey() {
+    public void testPerUserMaxIdleWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        ds.setPerUserMaxIdle("whatismyuseragain?", 0);
-        assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("missingkey"));
+        ds.setPerUserMaxIdle(user, 0);
+        assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle(user));
     }
 
-    // -- per user max total
-
     @Test
-    public void testPerUserMaxTotalMapNotInitialized() {
+    public void testPerUserMaxIdleWithUserMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Integer> values = new HashMap<>();
-        values.put("key", 1);
-        ds.setPerUserMaxTotal(values);
-        assertEquals((Integer) 1, (Integer) ds.getPerUserMaxTotal("key"));
+        ds.setPerUserMaxIdle("whatismyuseragain?", 0);
+        assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("missingkey"));
     }
 
     @Test
@@ -1027,6 +805,17 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal("anonymous"));
     }
 
+    // -- per user max idle
+
+    @Test
+    public void testPerUserMaxTotalMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Integer> values = new HashMap<>();
+        values.put("key", 1);
+        ds.setPerUserMaxTotal(values);
+        assertEquals((Integer) 1, (Integer) ds.getPerUserMaxTotal("key"));
+    }
+
     @Test
     public void testPerUserMaxTotalMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -1037,20 +826,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserMaxTotalWithUserMapNotInitialized() {
+    public void testPerUserMaxTotalWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserMaxTotal(user, 0);
         assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal(user));
+        ds.setPerUserMaxTotal("anotheruser", 0);
+        assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal(user));
+        assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal("anotheruser"));
     }
 
     @Test
-    public void testPerUserMaxTotalWithUserMapInitialized() {
+    public void testPerUserMaxTotalWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserMaxTotal(user, 0);
         assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal(user));
-        ds.setPerUserMaxTotal("anotheruser", 0);
-        assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal(user));
-        assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal("anotheruser"));
     }
 
     @Test
@@ -1060,17 +849,6 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals((Integer) ds.getDefaultMaxTotal(), (Integer) ds.getPerUserMaxTotal("missingkey"));
     }
 
-    // -- per user max wait millis
-
-    @Test
-    public void testPerUserMaxWaitMillisMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Long> values = new HashMap<>();
-        values.put("key", 1L);
-        ds.setPerUserMaxWaitMillis(values);
-        assertEquals(1L, ds.getPerUserMaxWaitMillis("key"));
-    }
-
     @Test
     public void testPerUserMaxWaitMillisMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -1085,6 +863,17 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(0L, ds.getPerUserMaxWaitMillis("anonymous"));
     }
 
+    // -- per user max total
+
+    @Test
+    public void testPerUserMaxWaitMillisMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Long> values = new HashMap<>();
+        values.put("key", 1L);
+        ds.setPerUserMaxWaitMillis(values);
+        assertEquals(1L, ds.getPerUserMaxWaitMillis("key"));
+    }
+
     @Test
     public void testPerUserMaxWaitMillisMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -1095,20 +884,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserMaxWaitMillisWithUserMapNotInitialized() {
+    public void testPerUserMaxWaitMillisWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserMaxWaitMillis(user, 0L);
         assertEquals(0L, ds.getPerUserMaxWaitMillis(user));
+        ds.setPerUserMaxWaitMillis("anotheruser", 0L);
+        assertEquals(0L, ds.getPerUserMaxWaitMillis(user));
+        assertEquals(0L, ds.getPerUserMaxWaitMillis("anotheruser"));
     }
 
     @Test
-    public void testPerUserMaxWaitMillisWithUserMapInitialized() {
+    public void testPerUserMaxWaitMillisWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserMaxWaitMillis(user, 0L);
         assertEquals(0L, ds.getPerUserMaxWaitMillis(user));
-        ds.setPerUserMaxWaitMillis("anotheruser", 0L);
-        assertEquals(0L, ds.getPerUserMaxWaitMillis(user));
-        assertEquals(0L, ds.getPerUserMaxWaitMillis("anotheruser"));
     }
 
     @Test
@@ -1118,17 +907,58 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(ds.getDefaultMaxWaitMillis(), ds.getPerUserMaxWaitMillis("missingkey"));
     }
 
-    // -- per user min evictable idle time millis
-
     @Test
-    public void testPerUserMinEvictableIdleTimeMillisMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Long> values = new HashMap<>();
-        values.put("key", 1L);
-        ds.setPerUserMinEvictableIdleTimeMillis(values);
-        assertEquals(1L, ds.getPerUserMinEvictableIdleTimeMillis("key"));
+    public void testPerUserMethods() throws Exception {
+        final PerUserPoolDataSource tds = (PerUserPoolDataSource) ds;
+
+        // you need to set per user maxTotal otherwise there is no accounting
+        tds.setPerUserMaxTotal("u1", 5);
+        tds.setPerUserMaxTotal("u2", 5);
+
+        assertEquals(0, tds.getNumActive());
+        assertEquals(0, tds.getNumActive("u1"));
+        assertEquals(0, tds.getNumActive("u2"));
+        assertEquals(0, tds.getNumIdle());
+        assertEquals(0, tds.getNumIdle("u1"));
+        assertEquals(0, tds.getNumIdle("u2"));
+
+        Connection conn = tds.getConnection();
+        assertNotNull(conn);
+        assertEquals(1, tds.getNumActive());
+        assertEquals(0, tds.getNumActive("u1"));
+        assertEquals(0, tds.getNumActive("u2"));
+        assertEquals(0, tds.getNumIdle());
+        assertEquals(0, tds.getNumIdle("u1"));
+        assertEquals(0, tds.getNumIdle("u2"));
+
+        conn.close();
+        assertEquals(0, tds.getNumActive());
+        assertEquals(0, tds.getNumActive("u1"));
+        assertEquals(0, tds.getNumActive("u2"));
+        assertEquals(1, tds.getNumIdle());
+        assertEquals(0, tds.getNumIdle("u1"));
+        assertEquals(0, tds.getNumIdle("u2"));
+
+        conn = tds.getConnection("u1", "p1");
+        assertNotNull(conn);
+        assertEquals(0, tds.getNumActive());
+        assertEquals(1, tds.getNumActive("u1"));
+        assertEquals(0, tds.getNumActive("u2"));
+        assertEquals(1, tds.getNumIdle());
+        assertEquals(0, tds.getNumIdle("u1"));
+        assertEquals(0, tds.getNumIdle("u2"));
+
+        conn.close();
+        assertEquals(0, tds.getNumActive());
+        assertEquals(0, tds.getNumActive("u1"));
+        assertEquals(0, tds.getNumActive("u2"));
+        assertEquals(1, tds.getNumIdle());
+        assertEquals(1, tds.getNumIdle("u1"));
+        assertEquals(0, tds.getNumIdle("u2"));
     }
 
+    // -- per user max wait millis
+
     @Test
     public void testPerUserMinEvictableIdleTimeMillisMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
@@ -1144,6 +974,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserMinEvictableIdleTimeMillisMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Long> values = new HashMap<>();
+        values.put("key", 1L);
+        ds.setPerUserMinEvictableIdleTimeMillis(values);
+        assertEquals(1L, ds.getPerUserMinEvictableIdleTimeMillis("key"));
+    }
+
+    @Test
     public void testPerUserMinEvictableIdleTimeMillisMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Long> values = new HashMap<>();
@@ -1153,20 +992,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserMinEvictableIdleTimeMillisWithUserMapNotInitialized() {
+    public void testPerUserMinEvictableIdleTimeMillisWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserMinEvictableIdleTimeMillis(user, 0L);
         assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis(user));
+        ds.setPerUserMinEvictableIdleTimeMillis("anotheruser", 0L);
+        assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis(user));
+        assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis("anotheruser"));
     }
 
     @Test
-    public void testPerUserMinEvictableIdleTimeMillisWithUserMapInitialized() {
+    public void testPerUserMinEvictableIdleTimeMillisWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserMinEvictableIdleTimeMillis(user, 0L);
         assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis(user));
-        ds.setPerUserMinEvictableIdleTimeMillis("anotheruser", 0L);
-        assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis(user));
-        assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis("anotheruser"));
     }
 
     @Test
@@ -1176,16 +1015,7 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(ds.getDefaultMinEvictableIdleTimeMillis(), ds.getPerUserMinEvictableIdleTimeMillis("missingkey"));
     }
 
-    // -- per user min idle
-
-    @Test
-    public void testPerUserMinIdleMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Integer> values = new HashMap<>();
-        values.put("key", 1);
-        ds.setPerUserMinIdle(values);
-        assertEquals((Integer) 1, (Integer) ds.getPerUserMinIdle("key"));
-    }
+    // -- per user min evictable idle time millis
 
     @Test
     public void testPerUserMinIdleMapInitialized() {
@@ -1202,6 +1032,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserMinIdleMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Integer> values = new HashMap<>();
+        values.put("key", 1);
+        ds.setPerUserMinIdle(values);
+        assertEquals((Integer) 1, (Integer) ds.getPerUserMinIdle("key"));
+    }
+
+    @Test
     public void testPerUserMinIdleMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Integer> values = new HashMap<>();
@@ -1211,20 +1050,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserMinIdleWithUserMapNotInitialized() {
+    public void testPerUserMinIdleWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserMinIdle(user, 0);
         assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle(user));
+        ds.setPerUserMinIdle("anotheruser", 0);
+        assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle(user));
+        assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle("anotheruser"));
     }
 
     @Test
-    public void testPerUserMinIdleWithUserMapInitialized() {
+    public void testPerUserMinIdleWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserMinIdle(user, 0);
         assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle(user));
-        ds.setPerUserMinIdle("anotheruser", 0);
-        assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle(user));
-        assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle("anotheruser"));
     }
 
     @Test
@@ -1234,16 +1073,7 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals((Integer) ds.getDefaultMinIdle(), (Integer) ds.getPerUserMinIdle("missingkey"));
     }
 
-    // -- per user num tests per eviction run
-
-    @Test
-    public void testPerUserNumTestsPerEvictionRunMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Integer> values = new HashMap<>();
-        values.put("key", 1);
-        ds.setPerUserNumTestsPerEvictionRun(values);
-        assertEquals((Integer) 1, (Integer) ds.getPerUserNumTestsPerEvictionRun("key"));
-    }
+    // -- per user min idle
 
     @Test
     public void testPerUserNumTestsPerEvictionRunMapInitialized() {
@@ -1260,6 +1090,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserNumTestsPerEvictionRunMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Integer> values = new HashMap<>();
+        values.put("key", 1);
+        ds.setPerUserNumTestsPerEvictionRun(values);
+        assertEquals((Integer) 1, (Integer) ds.getPerUserNumTestsPerEvictionRun("key"));
+    }
+
+    @Test
     public void testPerUserNumTestsPerEvictionRunMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Integer> values = new HashMap<>();
@@ -1269,20 +1108,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserNumTestsPerEvictionRunWithUserMapNotInitialized() {
+    public void testPerUserNumTestsPerEvictionRunWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserNumTestsPerEvictionRun(user, 0);
         assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun(user));
+        ds.setPerUserNumTestsPerEvictionRun("anotheruser", 0);
+        assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun(user));
+        assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun("anotheruser"));
     }
 
     @Test
-    public void testPerUserNumTestsPerEvictionRunWithUserMapInitialized() {
+    public void testPerUserNumTestsPerEvictionRunWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserNumTestsPerEvictionRun(user, 0);
         assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun(user));
-        ds.setPerUserNumTestsPerEvictionRun("anotheruser", 0);
-        assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun(user));
-        assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun("anotheruser"));
     }
 
     @Test
@@ -1292,16 +1131,7 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals((Integer) ds.getDefaultNumTestsPerEvictionRun(), (Integer) ds.getPerUserNumTestsPerEvictionRun("missingkey"));
     }
 
-    // -- per user soft min evictable idle time millis
-
-    @Test
-    public void testPerUserSoftMinEvictableIdleTimeMillisMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Long> values = new HashMap<>();
-        values.put("key", 1L);
-        ds.setPerUserSoftMinEvictableIdleTimeMillis(values);
-        assertEquals(1L, ds.getPerUserSoftMinEvictableIdleTimeMillis("key"));
-    }
+    // -- per user num tests per eviction run
 
     @Test
     public void testPerUserSoftMinEvictableIdleTimeMillisMapInitialized() {
@@ -1318,6 +1148,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserSoftMinEvictableIdleTimeMillisMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Long> values = new HashMap<>();
+        values.put("key", 1L);
+        ds.setPerUserSoftMinEvictableIdleTimeMillis(values);
+        assertEquals(1L, ds.getPerUserSoftMinEvictableIdleTimeMillis("key"));
+    }
+
+    @Test
     public void testPerUserSoftMinEvictableIdleTimeMillisMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Long> values = new HashMap<>();
@@ -1327,20 +1166,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserSoftMinEvictableIdleTimeMillisWithUserMapNotInitialized() {
+    public void testPerUserSoftMinEvictableIdleTimeMillisWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserSoftMinEvictableIdleTimeMillis(user, 0L);
         assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis(user));
+        ds.setPerUserSoftMinEvictableIdleTimeMillis("anotheruser", 0L);
+        assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis(user));
+        assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis("anotheruser"));
     }
 
     @Test
-    public void testPerUserSoftMinEvictableIdleTimeMillisWithUserMapInitialized() {
+    public void testPerUserSoftMinEvictableIdleTimeMillisWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserSoftMinEvictableIdleTimeMillis(user, 0L);
         assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis(user));
-        ds.setPerUserSoftMinEvictableIdleTimeMillis("anotheruser", 0L);
-        assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis(user));
-        assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis("anotheruser"));
     }
 
     @Test
@@ -1350,16 +1189,7 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(ds.getDefaultSoftMinEvictableIdleTimeMillis(), ds.getPerUserSoftMinEvictableIdleTimeMillis("missingkey"));
     }
 
-    // -- per user test on borrow
-
-    @Test
-    public void testPerUserTestOnBorrowMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Boolean> values = new HashMap<>();
-        values.put("key", Boolean.TRUE);
-        ds.setPerUserTestOnBorrow(values);
-        assertEquals(Boolean.TRUE, ds.getPerUserTestOnBorrow("key"));
-    }
+    // -- per user soft min evictable idle time millis
 
     @Test
     public void testPerUserTestOnBorrowMapInitialized() {
@@ -1376,6 +1206,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserTestOnBorrowMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Boolean> values = new HashMap<>();
+        values.put("key", Boolean.TRUE);
+        ds.setPerUserTestOnBorrow(values);
+        assertEquals(Boolean.TRUE, ds.getPerUserTestOnBorrow("key"));
+    }
+
+    @Test
     public void testPerUserTestOnBorrowMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Boolean> values = new HashMap<>();
@@ -1385,20 +1224,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserTestOnBorrowWithUserMapNotInitialized() {
+    public void testPerUserTestOnBorrowWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTestOnBorrow(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow(user));
+        ds.setPerUserTestOnBorrow("anotheruser", Boolean.FALSE);
+        assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow(user));
+        assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow("anotheruser"));
     }
 
     @Test
-    public void testPerUserTestOnBorrowWithUserMapInitialized() {
+    public void testPerUserTestOnBorrowWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTestOnBorrow(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow(user));
-        ds.setPerUserTestOnBorrow("anotheruser", Boolean.FALSE);
-        assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow(user));
-        assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow("anotheruser"));
     }
 
     @Test
@@ -1408,16 +1247,7 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(ds.getDefaultTestOnBorrow(), ds.getPerUserTestOnBorrow("missingkey"));
     }
 
-    // -- per user test on create
-
-    @Test
-    public void testPerUserTestOnCreateMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Boolean> values = new HashMap<>();
-        values.put("key", Boolean.TRUE);
-        ds.setPerUserTestOnCreate(values);
-        assertEquals(Boolean.TRUE, ds.getPerUserTestOnCreate("key"));
-    }
+    // -- per user test on borrow
 
     @Test
     public void testPerUserTestOnCreateMapInitialized() {
@@ -1434,6 +1264,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserTestOnCreateMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Boolean> values = new HashMap<>();
+        values.put("key", Boolean.TRUE);
+        ds.setPerUserTestOnCreate(values);
+        assertEquals(Boolean.TRUE, ds.getPerUserTestOnCreate("key"));
+    }
+
+    @Test
     public void testPerUserTestOnCreateMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Boolean> values = new HashMap<>();
@@ -1443,20 +1282,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserTestOnCreateWithUserMapNotInitialized() {
+    public void testPerUserTestOnCreateWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTestOnCreate(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate(user));
+        ds.setPerUserTestOnCreate("anotheruser", Boolean.FALSE);
+        assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate(user));
+        assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate("anotheruser"));
     }
 
     @Test
-    public void testPerUserTestOnCreateWithUserMapInitialized() {
+    public void testPerUserTestOnCreateWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTestOnCreate(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate(user));
-        ds.setPerUserTestOnCreate("anotheruser", Boolean.FALSE);
-        assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate(user));
-        assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate("anotheruser"));
     }
 
     @Test
@@ -1466,16 +1305,7 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(ds.getDefaultTestOnCreate(), ds.getPerUserTestOnCreate("missingkey"));
     }
 
-    // -- per user test on return
-
-    @Test
-    public void testPerUserTestOnReturnMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Boolean> values = new HashMap<>();
-        values.put("key", Boolean.TRUE);
-        ds.setPerUserTestOnReturn(values);
-        assertEquals(Boolean.TRUE, ds.getPerUserTestOnReturn("key"));
-    }
+    // -- per user test on create
 
     @Test
     public void testPerUserTestOnReturnMapInitialized() {
@@ -1492,6 +1322,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserTestOnReturnMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Boolean> values = new HashMap<>();
+        values.put("key", Boolean.TRUE);
+        ds.setPerUserTestOnReturn(values);
+        assertEquals(Boolean.TRUE, ds.getPerUserTestOnReturn("key"));
+    }
+
+    @Test
     public void testPerUserTestOnReturnMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Boolean> values = new HashMap<>();
@@ -1501,20 +1340,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserTestOnReturnWithUserMapNotInitialized() {
+    public void testPerUserTestOnReturnWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTestOnReturn(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn(user));
+        ds.setPerUserTestOnReturn("anotheruser", Boolean.FALSE);
+        assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn(user));
+        assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn("anotheruser"));
     }
 
     @Test
-    public void testPerUserTestOnReturnWithUserMapInitialized() {
+    public void testPerUserTestOnReturnWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTestOnReturn(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn(user));
-        ds.setPerUserTestOnReturn("anotheruser", Boolean.FALSE);
-        assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn(user));
-        assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn("anotheruser"));
     }
 
     @Test
@@ -1524,16 +1363,7 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(ds.getDefaultTestOnReturn(), ds.getPerUserTestOnReturn("missingkey"));
     }
 
-    // -- per user test while idle
-
-    @Test
-    public void testPerUserTestWhileIdleMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Boolean> values = new HashMap<>();
-        values.put("key", Boolean.TRUE);
-        ds.setPerUserTestWhileIdle(values);
-        assertEquals(Boolean.TRUE, ds.getPerUserTestWhileIdle("key"));
-    }
+    // -- per user test on return
 
     @Test
     public void testPerUserTestWhileIdleMapInitialized() {
@@ -1550,6 +1380,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserTestWhileIdleMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Boolean> values = new HashMap<>();
+        values.put("key", Boolean.TRUE);
+        ds.setPerUserTestWhileIdle(values);
+        assertEquals(Boolean.TRUE, ds.getPerUserTestWhileIdle("key"));
+    }
+
+    @Test
     public void testPerUserTestWhileIdleMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Boolean> values = new HashMap<>();
@@ -1559,20 +1398,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserTestWhileIdleWithUserMapNotInitialized() {
+    public void testPerUserTestWhileIdleWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTestWhileIdle(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle(user));
+        ds.setPerUserTestWhileIdle("anotheruser", Boolean.FALSE);
+        assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle(user));
+        assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle("anotheruser"));
     }
 
     @Test
-    public void testPerUserTestWhileIdleWithUserMapInitialized() {
+    public void testPerUserTestWhileIdleWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTestWhileIdle(user, Boolean.FALSE);
         assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle(user));
-        ds.setPerUserTestWhileIdle("anotheruser", Boolean.FALSE);
-        assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle(user));
-        assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle("anotheruser"));
     }
 
     @Test
@@ -1582,16 +1421,7 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(ds.getDefaultTestWhileIdle(), ds.getPerUserTestWhileIdle("missingkey"));
     }
 
-    // -- per user time between eviction runs millis
-
-    @Test
-    public void testPerUserTimeBetweenEvictionRunsMillisMapNotInitialized() {
-        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
-        final Map<String, Long> values = new HashMap<>();
-        values.put("key", 1L);
-        ds.setPerUserTimeBetweenEvictionRunsMillis(values);
-        assertEquals(1L, ds.getPerUserTimeBetweenEvictionRunsMillis("key"));
-    }
+    // -- per user test while idle
 
     @Test
     public void testPerUserTimeBetweenEvictionRunsMillisMapInitialized() {
@@ -1608,6 +1438,15 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
+    public void testPerUserTimeBetweenEvictionRunsMillisMapNotInitialized() {
+        final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
+        final Map<String, Long> values = new HashMap<>();
+        values.put("key", 1L);
+        ds.setPerUserTimeBetweenEvictionRunsMillis(values);
+        assertEquals(1L, ds.getPerUserTimeBetweenEvictionRunsMillis("key"));
+    }
+
+    @Test
     public void testPerUserTimeBetweenEvictionRunsMillisMapNotInitializedMissingKey() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         final Map<String, Long> values = new HashMap<>();
@@ -1617,20 +1456,20 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
     }
 
     @Test
-    public void testPerUserTimeBetweenEvictionRunsMillisWithUserMapNotInitialized() {
+    public void testPerUserTimeBetweenEvictionRunsMillisWithUserMapInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTimeBetweenEvictionRunsMillis(user, 0L);
         assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis(user));
+        ds.setPerUserTimeBetweenEvictionRunsMillis("anotheruser", 0L);
+        assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis(user));
+        assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis("anotheruser"));
     }
 
     @Test
-    public void testPerUserTimeBetweenEvictionRunsMillisWithUserMapInitialized() {
+    public void testPerUserTimeBetweenEvictionRunsMillisWithUserMapNotInitialized() {
         final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds;
         ds.setPerUserTimeBetweenEvictionRunsMillis(user, 0L);
         assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis(user));
-        ds.setPerUserTimeBetweenEvictionRunsMillis("anotheruser", 0L);
-        assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis(user));
-        assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis("anotheruser"));
     }
 
     @Test
@@ -1640,4 +1479,165 @@ public class TestPerUserPoolDataSource extends TestConnectionPool {
         assertEquals(ds.getDefaultTimeBetweenEvictionRunsMillis(), ds.getPerUserTimeBetweenEvictionRunsMillis("missingkey"));
     }
 
+    // -- per user time between eviction runs millis
+
+    @Test
+    public void testSerialization() throws Exception {
+        // make sure the pool has initialized
+        final Connection conn = ds.getConnection();
+        conn.close();
+
+        // serialize
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        final ObjectOutputStream out = new ObjectOutputStream(baos);
+        out.writeObject(ds);
+        out.close();
+        final byte[] b = baos.toByteArray();
+
+        final ByteArrayInputStream bais = new ByteArrayInputStream(b);
+        final ObjectInputStream in = new ObjectInputStream(bais);
+        final Object obj = in.readObject();
+        in.close();
+
+        assertEquals( 1, ((PerUserPoolDataSource)obj).getNumIdle() );
+    }
+
+    @Override
+    @Test
+    public void testSimple() throws Exception
+    {
+        final Connection conn = ds.getConnection();
+        assertNotNull(conn);
+        final PreparedStatement stmt = conn.prepareStatement("select * from dual");
+        assertNotNull(stmt);
+        final ResultSet rset = stmt.executeQuery();
+        assertNotNull(rset);
+        assertTrue(rset.next());
+        rset.close();
+        stmt.close();
+        conn.close();
+    }
+
+    @Override
+    @Test
+    public void testSimple2()
+        throws Exception
+    {
+        Connection conn = ds.getConnection();
+        assertNotNull(conn);
+
+        PreparedStatement stmt =
+            conn.prepareStatement("select * from dual");
+        assertNotNull(stmt);
+        ResultSet rset = stmt.executeQuery();
+        assertNotNull(rset);
+        assertTrue(rset.next());
+        rset.close();
+        stmt.close();
+
+        stmt = conn.prepareStatement("select * from dual");
+        assertNotNull(stmt);
+        rset = stmt.executeQuery();
+        assertNotNull(rset);
+        assertTrue(rset.next());
+        rset.close();
+        stmt.close();
+
+        conn.close();
+        try (Statement s = conn.createStatement()){
+            fail("Can't use closed connections");
+        } catch(final SQLException e) {
+            // expected
+        }
+
+        conn = ds.getConnection();
+        assertNotNull(conn);
+
+        stmt = conn.prepareStatement("select * from dual");
+        assertNotNull(stmt);
+        rset = stmt.executeQuery();
+        assertNotNull(rset);
+        assertTrue(rset.next());
+        rset.close();
+        stmt.close();
+
+        stmt = conn.prepareStatement("select * from dual");
+        assertNotNull(stmt);
+        rset = stmt.executeQuery();
+        assertNotNull(rset);
+        assertTrue(rset.next());
+        rset.close();
+        stmt.close();
+
+        conn.close();
+        conn = null;
+    }
+
+    @Test
+    public void testSimpleWithUsername() throws Exception
+    {
+        final Connection conn = ds.getConnection("u1", "p1");
+        assertNotNull(conn);
+        final PreparedStatement stmt = conn.prepareStatement("select * from dual");
+        assertNotNull(stmt);
+        final ResultSet rset = stmt.executeQuery();
+        assertNotNull(rset);
+        assertTrue(rset.next());
+        rset.close();
+        stmt.close();
+        conn.close();
+    }
+
+    @Test
+    public void testTransactionIsolationBehavior() throws Exception {
+        final Connection conn = getConnection();
+        assertNotNull(conn);
+        assertEquals(Connection.TRANSACTION_READ_COMMITTED,
+                     conn.getTransactionIsolation());
+        conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+        conn.close();
+
+        final Connection conn2 = getConnection();
+        assertEquals(Connection.TRANSACTION_READ_COMMITTED,
+                     conn2.getTransactionIsolation());
+
+        final Connection conn3 = getConnection();
+        assertEquals(Connection.TRANSACTION_READ_COMMITTED,
+                     conn3.getTransactionIsolation());
+        conn2.close();
+        conn3.close();
+    }
+
+    // see issue https://issues.apache.org/bugzilla/show_bug.cgi?id=23843
+    // unregistered user is in the same pool as without user name
+    @Test
+    public void testUnregisteredUser() throws Exception {
+        final PerUserPoolDataSource tds = (PerUserPoolDataSource) ds;
+
+        assertEquals(0, tds.getNumActive());
+        assertEquals(0, tds.getNumIdle());
+
+        Connection conn = tds.getConnection();
+        assertNotNull(conn);
+        assertEquals(1, tds.getNumActive());
+        assertEquals(0, tds.getNumIdle());
+
+        conn.close();
+        assertEquals(0, tds.getNumActive());
+        assertEquals(1, tds.getNumIdle());
+
+        conn = tds.getConnection("u1", "p1");
+        assertNotNull(conn);
+        assertEquals(0, tds.getNumActive());
+        assertEquals(1, tds.getNumIdle());
+        assertEquals(1, tds.getNumActive("u1"));
+        assertEquals(0, tds.getNumIdle("u1"));
+
+        conn.close();
+        assertEquals(0, tds.getNumActive());
+        assertEquals(1, tds.getNumIdle());
+        assertEquals(0, tds.getNumActive("u1"));
+        assertEquals(1, tds.getNumIdle("u1"));
+    }
+
 }