Repository: qpid-dispatch
Updated Branches:
  refs/heads/crolke-DISPATCH-188-1 dfb8cfda4 -> 1036c0efc


Squashed commit of the following:

commit cb6f40ffbeae3dda38de785d35bd4969cfa5fc7f
Author: Chuck Rolke <[email protected]>
Date:   Fri Jan 29 12:27:45 2016 -0500

    Adjust agent to new schema. Fix example ruleset.

commit 6bd202413dec306d3814d1fee5e400708352aa85
Author: Chuck Rolke <[email protected]>
Date:   Fri Jan 29 12:19:01 2016 -0500

    collapse settings into ruleset map; fix up test rulesets to match new schema

commit db1d89a0f142a704adcb83489008c81f97a307a2
Author: Chuck Rolke <[email protected]>
Date:   Fri Jan 29 11:49:03 2016 -0500

    Tidy up the self tests.

commit 85b958e67db35708b81478d2a08b63dfa32af198
Author: Chuck Rolke <[email protected]>
Date:   Fri Jan 29 09:23:01 2016 -0500

    cwip

commit 455bc738c3a012c2b081efb16e49823ca7da1c0b
Author: Chuck Rolke <[email protected]>
Date:   Thu Jan 28 14:10:51 2016 -0500

    Split unit tests out of system test


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/1036c0ef
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/1036c0ef
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/1036c0ef

Branch: refs/heads/crolke-DISPATCH-188-1
Commit: 1036c0efcd75d9d674708fed65b6c51fd888bc79
Parents: dfb8cfd
Author: Chuck Rolke <[email protected]>
Authored: Fri Jan 29 12:29:39 2016 -0500
Committer: Chuck Rolke <[email protected]>
Committed: Fri Jan 29 12:29:39 2016 -0500

----------------------------------------------------------------------
 python/qpid_dispatch/management/qdrouter.json   | 106 +-----
 .../qpid_dispatch_internal/management/agent.py  |   9 +-
 .../policy/policy_local.py                      | 377 +++++++++----------
 tests/CMakeLists.txt                            |   3 +
 tests/policy-1/policy-photoserver.json          |   1 -
 tests/policy-1/test-router-with-policy.json     | 196 +++++-----
 tests/router_policy_test.py                     | 243 ++++++++++++
 tests/system_tests_policy.py                    | 259 +------------
 8 files changed, 522 insertions(+), 672 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/1036c0ef/python/qpid_dispatch/management/qdrouter.json
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch/management/qdrouter.json 
b/python/qpid_dispatch/management/qdrouter.json
index 9565ba7..0944b3d 100644
--- a/python/qpid_dispatch/management/qdrouter.json
+++ b/python/qpid_dispatch/management/qdrouter.json
@@ -1018,7 +1018,7 @@
             }
         },
 
-        "policyAccessRuleset": {
+        "policyRuleset": {
             "description": "Per application definition of the locations from 
which users may connect and the groups to which users belong.",
             "extends": "configurationEntity",
             "attributes": {
@@ -1072,11 +1072,17 @@
                     "default": false,
                     "required": false,
                     "create": true
+                },
+                "settings": {
+                    "type": "map",
+                    "description": "A map where each key is a connection group 
name and the corresponding settings for that group.",
+                    "required": false,
+                    "create": true
                 }
             }
         },
 
-        "policyAccessStats": {
+        "policyStats": {
             "description": "Per application connection and access statistics.",
             "extends": "operationalEntity",
             "attributes": {
@@ -1094,104 +1100,8 @@
                 "perHostState": {
                     "type": "map",
                     "description": "A map where the key is the host name and 
the value is a list of the host's connections."
-                }
-
-            }
-
-        },
-
-        "policyAppSettings": {
-            "description": "For a given application and user group define the 
policy settings applied to the user's AMQP connection.",
-            "extends": "configurationEntity",
-            "attributes": {
-                "applicationName": {
-                    "type": "string",
-                    "description": "The application to which these settings 
apply.",
-                    "required": true
-                },
-                "userGroupName": {
-                    "type": "string",
-                    "description": "The user group to which these settings 
apply.",
-                    "required": true
                 },
-                "maxFrameSize": {
-                    "type": "integer",
-                    "description": "Largest frame that may be sent on this 
connection. Zero implies system default. (AMQP Open, max-frame-size)",
-                    "default": 65536,
-                    "required": false,
-                    "create": true
-                },
-                "maxMessageSize": {
-                    "type": "integer",
-                    "description": "Largest message size supported by links 
created on this connection. Zero implies system default. (AMQP Attach, 
max-message-size)",
-                    "default": 0,
-                    "required": false,
-                    "create": true
-                },
-                "maxSessionWindow": {
-                    "type": "integer",
-                    "description": "Largest incoming and outgoing window for 
sessions created on this connection. Zero implies system default. (AMQP Begin, 
incoming-window, outgoing-window)",
-                    "default": 2147483647,
-                    "required": false,
-                    "create": true
-                },
-                "maxSessions": {
-                    "type": "integer",
-                    "description": "Maximum number of sessions that may be 
created on this connection. Zero implies system default. (AMQP Open, 
channel-max)",
-                    "default": 10,
-                    "required": false,
-                    "create": true
-                },
-                "maxSenders": {
-                    "type": "integer",
-                    "description": "Maximum number of sending links that may 
be created on this connection. Zero implies system default.",
-                    "default": 10,
-                    "required": false,
-                    "create": true
-                },
-                "maxReceivers": {
-                    "type": "integer",
-                    "description": "Maximum number of receiving links that may 
be created on this connection. Zero implies system default.",
-                    "required": false,
-                    "create": true
-                },
-                "allowDynamicSrc": {
-                    "type": "boolean",
-                    "description": "This connection is allowed to use the 
dynamic link source feature.",
-                    "default": false,
-                    "required": false,
-                    "create": true
-                },
-                "allowAnonymousSender": {
-                    "type": "boolean",
-                    "description": "This connection is allowed to use the 
Anonymous Sender feature.",
-                    "default": false,
-                    "required": false,
-                    "create": true
-                },
-                "sources": {
-                    "type": "string",
-                    "description": "List of Source addresses allowed when 
creating receiving links.",
-                    "required": false,
-                    "create": true
-                },
-                "targets": {
-                    "type": "string",
-                    "description": "List of Target addresses allowed when 
creating sending links.",
-                    "required": false,
-                    "create": true
-                }
-            }
-        },
 
-        "policyAppStats": {
-            "description": "Per application policy enforcement statistics.",
-            "extends": "operationalEntity",
-            "attributes": {
-                "name": {
-                    "type": "string",
-                    "description": "The application name."
-                },
                 "maxSendersDenied": {"type": "integer", "graph": true},
                 "maxReceiversDenied": {"type": "integer", "graph": true},
                 "dynamicSrcDenied": {"type": "integer", "graph": true},

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/1036c0ef/python/qpid_dispatch_internal/management/agent.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/management/agent.py 
b/python/qpid_dispatch_internal/management/agent.py
index 013eddb..994b0dd 100644
--- a/python/qpid_dispatch_internal/management/agent.py
+++ b/python/qpid_dispatch_internal/management/agent.py
@@ -285,20 +285,13 @@ class PolicyEntity(EntityAdapter):
     def _identifier(self):
         return self.attributes.get('module')
 
-class PolicyAccessRulesetEntity(EntityAdapter):
+class PolicyRulesetEntity(EntityAdapter):
     def create(self):
         self._policy.create_ruleset(self.attributes)
 
     def _identifier(self):
         return self.attributes.get('applicationName')
 
-class PolicyAppSettingsEntity(EntityAdapter):
-    def create(self):
-        self._policy.create_settings(self.attributes)
-
-    def _identifier(self):
-        return self.attributes.get('applicationName') + "_" + 
self.attributes.get('userGroupName')
-
 def _addr_port_identifier(entity):
     for attr in ['addr', 'port']: # Set default values if need be
         entity.attributes.setdefault(

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/1036c0ef/python/qpid_dispatch_internal/policy/policy_local.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/policy/policy_local.py 
b/python/qpid_dispatch_internal/policy/policy_local.py
index 7cc17de..d3b5e72 100644
--- a/python/qpid_dispatch_internal/policy/policy_local.py
+++ b/python/qpid_dispatch_internal/policy/policy_local.py
@@ -27,8 +27,6 @@ import optparse
 from policy_util import PolicyError, HostStruct, HostAddr, 
PolicyAppConnectionMgr
 import pdb #; pdb.set_trace()
 
-
-
 """
 Entity implementing the business logic of user connection/access policy.
 """
@@ -43,13 +41,14 @@ class PolicyKeys(object):
     KW_APPLICATION_NAME         = "applicationName"
 
     # Policy ruleset key words
-    KW_MAXCONN                  = "maxConnections"
-    KW_MAXCONNPERHOST           = "maxConnPerHost"
-    KW_MAXCONNPERUSER           = "maxConnPerUser"
-    KW_USER_GROUPS              = "userGroups"
-    KW_CONNECTION_GROUPS        = "connectionGroups"
-    KW_CONNECTION_POLICY        = "connectionIngressPolicies"
-    KW_CONNECTION_ALLOW_DEFAULT = "connectionAllowDefault"
+    KW_MAXCONN                     = "maxConnections"
+    KW_MAXCONNPERHOST              = "maxConnPerHost"
+    KW_MAXCONNPERUSER              = "maxConnPerUser"
+    KW_USER_GROUPS                 = "userGroups"
+    KW_CONNECTION_GROUPS           = "connectionGroups"
+    KW_CONNECTION_INGRESS_POLICIES = "connectionIngressPolicies"
+    KW_CONNECTION_ALLOW_DEFAULT    = "connectionAllowDefault"
+    KW_SETTINGS                    = "settings"
 
     # Policy settings key words
     KW_USER_GROUP_NAME          = "userGroupName"
@@ -73,6 +72,9 @@ class PolicyKeys(object):
 
     # Config file separator character for names in a list
     KC_CONFIG_LIST_SEP          = ","
+
+    # user-to-group computed map in compiled ruleset
+    RULESET_U2G_MAP             = "U2G"
 #
 #
 class PolicyCompiler(object):
@@ -93,16 +95,12 @@ class PolicyCompiler(object):
         PolicyKeys.KW_MAXCONNPERUSER,
         PolicyKeys.KW_USER_GROUPS,
         PolicyKeys.KW_CONNECTION_GROUPS,
-        PolicyKeys.KW_CONNECTION_POLICY,
-        PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT
+        PolicyKeys.KW_CONNECTION_INGRESS_POLICIES,
+        PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT,
+        PolicyKeys.KW_SETTINGS
         ]
 
     allowed_settings_options = [
-        PolicyKeys.KW_IGNORED_NAME,
-        PolicyKeys.KW_IGNORED_IDENTITY,
-        PolicyKeys.KW_IGNORED_TYPE,
-        PolicyKeys.KW_APPLICATION_NAME,
-        PolicyKeys.KW_USER_GROUP_NAME,
         PolicyKeys.KW_MAX_FRAME_SIZE,
         PolicyKeys.KW_MAX_MESSAGE_SIZE,
         PolicyKeys.KW_MAX_SESSION_WINDOW,
@@ -192,6 +190,18 @@ class PolicyCompiler(object):
                   warnings[] may contain info and errors[0] will hold the
                   description of why the policy was rejected.
         """
+        # rulesets may not come through standard config so make nice defaults
+        policy_out[PolicyKeys.KW_MAX_FRAME_SIZE] = 65536
+        policy_out[PolicyKeys.KW_MAX_MESSAGE_SIZE] = 0
+        policy_out[PolicyKeys.KW_MAX_SESSION_WINDOW] = 2147483647
+        policy_out[PolicyKeys.KW_MAX_SESSIONS] = 10
+        policy_out[PolicyKeys.KW_MAX_SENDERS] = 10
+        policy_out[PolicyKeys.KW_MAX_RECEIVERS] = 10
+        policy_out[PolicyKeys.KW_ALLOW_DYNAMIC_SRC] = False
+        policy_out[PolicyKeys.KW_ALLOW_ANONYMOUS_SENDER] = False
+        policy_out[PolicyKeys.KW_SOURCES] = []
+        policy_out[PolicyKeys.KW_TARGETS] = []
+
         cerror = []
         for key, val in policy_in.iteritems():
             if key not in self.allowed_settings_options:
@@ -241,6 +251,16 @@ class PolicyCompiler(object):
                   description of why the policy was rejected.
         """
         cerror = []
+        # rulesets may not come through standard config so make nice defaults
+        policy_out[PolicyKeys.KW_MAXCONN] = 0
+        policy_out[PolicyKeys.KW_MAXCONNPERHOST] = 0
+        policy_out[PolicyKeys.KW_MAXCONNPERUSER] = 0
+        policy_out[PolicyKeys.KW_USER_GROUPS] = {}
+        policy_out[PolicyKeys.KW_CONNECTION_GROUPS] = {}
+        policy_out[PolicyKeys.KW_CONNECTION_INGRESS_POLICIES] = {}
+        policy_out[PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT] = False
+        policy_out[PolicyKeys.KW_SETTINGS] = {}
+
         # validate the options
         for key, val in policy_in.iteritems():
             if key not in self.allowed_ruleset_options:
@@ -258,7 +278,7 @@ class PolicyCompiler(object):
                 policy_out[key] = val
             elif key in [PolicyKeys.KW_USER_GROUPS,
                          PolicyKeys.KW_CONNECTION_GROUPS,
-                         PolicyKeys.KW_CONNECTION_POLICY
+                         PolicyKeys.KW_CONNECTION_INGRESS_POLICIES
                          ]:
                 try:
                     if not type(val) is dict:
@@ -266,6 +286,8 @@ class PolicyCompiler(object):
                                       (name, key, type(val)))
                         return False
                     if key == PolicyKeys.KW_CONNECTION_GROUPS:
+                        # Conection groups are lists of IP addresses that need 
to be
+                        # converted into binary structures for comparisons.
                         if not self.compile_connection_groups(name, val, 
warnings, errors):
                             return False
                     else:
@@ -279,6 +301,57 @@ class PolicyCompiler(object):
                     errors.append("Application '%s' option '%s' error 
processing map: %s" %
                                   (name, key, e))
                     return False
+            elif key in [PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT]:
+                if not type(val) is bool:
+                    errors.append("Application '%s' option '%s' must be of 
type 'bool' but is '%s'" %
+                                  (name, key, type(val)))
+                    return False
+                policy_out[key] = val
+            elif key in [PolicyKeys.KW_SETTINGS]:
+                if not type(val) is dict:
+                    errors.append("Application '%s' option '%s' must be of 
type 'dict' but is '%s'" %
+                                  (name, key, type(val)))
+                    return False
+                for skey, sval in val.iteritems():
+                    newsettings = {}
+                    if not self.compile_app_settings(name, skey, sval, 
newsettings, warnings, errors):
+                        return False
+                    policy_out[key][skey] = {}
+                    policy_out[key][skey].update(newsettings)
+
+        # Verify that each user is in only one group.
+        # Verify that each user group has defined settings
+        # Create user-to-group map for looling up user's group
+        policy_out[PolicyKeys.RULESET_U2G_MAP] = {}
+        if PolicyKeys.KW_USER_GROUPS in policy_out:
+            for group, userlist in 
policy_out[PolicyKeys.KW_USER_GROUPS].iteritems():
+                for user in userlist:
+                    if user in policy_out[PolicyKeys.RULESET_U2G_MAP]:
+                        errors.append("Application '%s' user '%s' is in 
multiple user groups '%s' and '%s'" %
+                                      (name, user, 
policy_out[PolicyKeys.RULESET_U2G_MAP][user], group))
+                        return False
+                    else:
+                        policy_out[PolicyKeys.RULESET_U2G_MAP][user] = group
+                if not group in policy_out[PolicyKeys.KW_SETTINGS]:
+                    errors.append("Application '%s' user group '%s' has no 
defined settings" %
+                                  (name, group))
+                    return False
+
+        # Default connections require a default settings
+        if policy_out[PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT]:
+            if not PolicyKeys.KW_DEFAULT_SETTINGS in 
policy_out[PolicyKeys.KW_SETTINGS]:
+                errors.append("Application '%s' allows connections by default 
but default settings are not defined" %
+                              (name))
+                return False
+
+        # Each ingress policy name references must exist in connection_groups
+        for cipname, cip in 
policy_out[PolicyKeys.KW_CONNECTION_INGRESS_POLICIES].iteritems():
+            for co in cip:
+                if not co in policy_out[PolicyKeys.KW_CONNECTION_GROUPS]:
+                    errors.append("Application '%s' connection ingress policy 
'%s' references connection group '%s' but that group does not exist"
+                                  (name, cipname, co))
+                    return False
+
         return True
 
 class PolicyLocal(object):
@@ -291,13 +364,24 @@ class PolicyLocal(object):
         Create instance
         @params folder: relative path from __file__ to conf file folder
         """
-        self.policydb = {}
+        # rulesetdb is a map
+        #  key : application name
+        #  val : ruleset for this app
+        # created by configuration
+        # augmented by policy compiler
+        self.rulesetdb = {}
+
+        # settingsdb is a map
+        #  key : <application name>
+        #  val : a map
+        #   key : <user group name>
+        #   val : settings to use for user's connection
+        # created by configuration
         self.settingsdb = {}
-        self.lookup_cache = {}
-        self.stats = {}
-        self.policy_compiler = PolicyCompiler()
-        self.name_lookup_cache = {}
-        self.blob_lookup_cache = {}
+
+        # _policy_compiler is a function
+        #  validates incoming policy and readies it for internal use
+        self._policy_compiler = PolicyCompiler()
 
     #
     # Service interfaces
@@ -311,13 +395,13 @@ class PolicyLocal(object):
         diag = []
         candidate = {}
         name = attributes[PolicyKeys.KW_APPLICATION_NAME]
-        result = self.policy_compiler.compile_access_ruleset(name, attributes, 
candidate, warnings, diag)
+        result = self._policy_compiler.compile_access_ruleset(name, 
attributes, candidate, warnings, diag)
         if not result:
             raise PolicyError( "Policy '%s' is invalid: %s" % (name, diag[0]) )
         if len(warnings) > 0:
             print ("LogMe: Application '%s' has warnings: %s" %
                    (name, warnings))
-        self.policydb[name] = candidate
+        self.rulesetdb[name] = candidate
         # TODO: Create stats
 
     def create_settings(self, attributes):
@@ -330,7 +414,7 @@ class PolicyLocal(object):
         candidate = {}
         app_name = attributes[PolicyKeys.KW_APPLICATION_NAME]
         usergroup = attributes[PolicyKeys.KW_USER_GROUP_NAME]
-        result = self.policy_compiler.compile_app_settings(app_name, 
usergroup, attributes, candidate, warnings, diag)
+        result = self._policy_compiler.compile_app_settings(app_name, 
usergroup, attributes, candidate, warnings, diag)
         if not result:
             raise PolicyError( "Policy '%s' is invalid: %s" % (app_name, 
diag[0]) )
         if len(warnings) > 0:
@@ -346,7 +430,7 @@ class PolicyLocal(object):
         @param[in] name application name
         @return policy data in raw user format
         """
-        return self.policydb[name]
+        return self.rulesetdb[name]
 
     def policy_update(self, name, policy):
         """
@@ -354,7 +438,7 @@ class PolicyLocal(object):
         @param[in] name application name
         @param[in] policy data in raw user input
         """
-        if not name in self.policydb:
+        if not name in self.rulesetdb:
             raise PolicyError("Policy '%s' does not exist" % name)
         self.policy_create(name, policy)
 
@@ -363,9 +447,9 @@ class PolicyLocal(object):
         Delete named policy
         @param[in] name application name
         """
-        if not name in self.policydb:
+        if not name in self.rulesetdb:
             raise PolicyError("Policy '%s' does not exist" % name)
-        del self.policydb[name]
+        del self.rulesetdb[name]
 
     #
     # db enumerator
@@ -374,101 +458,13 @@ class PolicyLocal(object):
         """
         Return a list of application names in this policy
         """
-        return self.policydb.keys()
+        return self.rulesetdb.keys()
 
 
     #
     # Runtime query interface
     #
-    def policy_aggregate_limits(self, upolicy, policy, settingname):
-        """
-        Force a max count value into user policy
-        param[in,out] upolicy user policy receiving aggregations
-        param[in] policy Internal policy holding settings to be aggregated
-        param[in] settingname setting of interest
-        """
-        if settingname in policy:
-            upolicy[settingname] = policy[settingname]
-
-    def policy_aggregate_policy_int(self, upolicy, appsettings, groups, 
settingname):
-        """
-        Pull int out of policy.policies[group] and install into upolicy.
-        Integers are set to max(new, existing)
-        param[in,out] upolicy user policy receiving aggregations
-        param[in] policy Internal policy holding settings to be aggregated
-        param[in] settingname setting of interest
-        """
-        for group in groups:
-            if group in appsettings:
-                rpol = appsettings[group]
-                if settingname in rpol:
-                    sp = rpol[settingname]
-                    if settingname in upolicy:
-                        up = upolicy[settingname]
-                        if sp > up:
-                            # policy bumps up user setting
-                            upolicy[settingname] = sp
-                        else:
-                            # user policy is already better
-                            pass
-                    else:
-                        # user policy doesn't have setting so force it
-                        upolicy[settingname] = sp
-                else:
-                    # no setting of this name in the group's policy
-                    pass
-            else:
-                # no policy for this group
-                pass
-
-    def policy_aggregate_policy_bool(self, upolicy, appsettings, groups, 
settingname):
-        """
-        Pull bool out of policy and install into upolicy if true
-        param[in,out] upolicy user policy receiving aggregations
-        param[in] policy Internal policy holding settings to be aggregated
-        param[in] settingname setting of interest
-        """
-        for group in groups:
-            if group in appsettings:
-                rpol = appsettings[group]
-                if settingname in rpol:
-                    if rpol[settingname]:
-                        upolicy[settingname] = True
-                else:
-                    # no setting of this name in the group's policy
-                    pass
-            else:
-                # no policy for this group
-                pass
-
-    def policy_aggregate_policy_list(self, upolicy, appsettings, groups, 
settingname):
-        """
-        Pull list out of policy and append into upolicy
-        param[in,out] upolicy user policy receiving aggregations
-        param[in] policy Internal policy holding settings to be aggregated
-        param[in] settingname setting of interest
-        """
-        for group in groups:
-            if group in appsettings:
-                rpol = appsettings[group]
-                if settingname in rpol:
-                    sp = rpol[settingname]
-                    if settingname in upolicy:
-                        upolicy[settingname].extend( sp )
-                        upolicy[settingname] = list(set(upolicy[settingname]))
-                    else:
-                        # user policy doesn't have setting so force it
-                        upolicy[settingname] = sp
-                else:
-                    # no setting of this name in the group's policy
-                    pass
-            else:
-                # no policy for this group
-                pass
-
-    #
-    #
-    def lookup_user(self, user, host, app, conn_name, policyname):
+    def lookup_user(self, user, host, app, conn_name):
         """
         Lookup function called from C.
         Determine if a user on host accessing app through AMQP Open is allowed
@@ -477,117 +473,96 @@ class PolicyLocal(object):
         @param[in] user connection authId
         @param[in] host connection remote host numeric IP address as string
         @param[in] app application user is accessing
-        @param[out] policyname name of the policy settings blob for this user
-        @return if allowed by policy
+        @return settings user-group name if allowed; "" if not allowed
         # Note: the upolicy[0] output is list of group names joined with '|'.
         TODO: handle the AccessStats
         """
         try:
-            lookup_id = user + "|" + host + "|" + app
-            if lookup_id in self.name_lookup_cache:
-                policyname.append( self.name_lookup_cache[lookup_id] )
-                return True
-
-            if not app in self.policydb:
+            if not app in self.rulesetdb:
                 # TODO: ("LogMe: no policy defined for application %s" % app)
-                policyname.append("")
-                return False
+                return ""
 
-            settings = self.policydb[app]
-            # User allowed to connect from host?
-            allowed = False
-            restricted = False
-            uhs = HostStruct(host)
-            ugroups = []
-            if PolicyKeys.KW_USER_GROUPS in settings:
-                for r in settings[PolicyKeys.KW_USER_GROUPS]:
-                    if user in settings[PolicyKeys.KW_USER_GROUPS][r]:
-                        restricted = True
-                        ugroups.append(r)
-            uorigins = []
-            if PolicyKeys.KW_CONNECTION_POLICY in settings:
-                for ur in ugroups:
-                    if ur in settings[PolicyKeys.KW_CONNECTION_POLICY]:
-                        
uorigins.extend(settings[PolicyKeys.KW_CONNECTION_POLICY][ur])
-            if PolicyKeys.KW_CONNECTION_GROUPS in settings:
-                for co in settings[PolicyKeys.KW_CONNECTION_GROUPS]:
-                    if co in uorigins:
-                        for cohost in 
settings[PolicyKeys.KW_CONNECTION_GROUPS][co]:
-                            if cohost.match_bin(uhs):
-                                allowed = True
-                                break
+            ruleset = self.rulesetdb[app]
+            # User in a group or default?
+            if user in ruleset[PolicyKeys.RULESET_U2G_MAP]:
+                usergroup = ruleset[PolicyKeys.RULESET_U2G_MAP][user]
+            else:
+                if ruleset[PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT]:
+                    usergroup = PolicyKeys.KW_DEFAULT_SETTINGS
+                else:
+                    # User is not in a group and default is disallowed. So no 
go.
+                    return ""
+            # User in usergroup allowed to connect from host?
+            if usergroup in ruleset[PolicyKeys.KW_CONNECTION_INGRESS_POLICIES]:
+                # User's usergroup is restricted to connecting from a host
+                # defined by the group's ingress policy
+                allowed = False
+                uhs = HostStruct(host)
+                cglist = 
ruleset[PolicyKeys.KW_CONNECTION_INGRESS_POLICIES][usergroup]
+                for cg in cglist:
+                    for cohost in ruleset[PolicyKeys.KW_CONNECTION_GROUPS][cg]:
+                        if cohost.match_bin(uhs):
+                            allowed = True
+                            break
                     if allowed:
                         break
-            if not allowed and not restricted:
-                if PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT in settings:
-                    allowed = settings[PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT]
+            else:
+                # User's usergroup has no ingress policy so allow
+                allowed = True
             if not allowed:
-                return False
-            if not restricted:
-                ugroups.append(PolicyKeys.KW_DEFAULT_SETTINGS)
-            #
-            ugroups.sort()
-            result = "|".join(ugroups)
-            self.name_lookup_cache[lookup_id] = result
-            policyname.append(result)
-            return True
+                return ""
+
+            # This user passes administrative approval.
+            # TODO: Count connection limits and possibly deny
+
+            # Return success
+            return usergroup
 
         except Exception, e:
             #print str(e)
             #pdb.set_trace()
-            return False
+            return ""
 
     def lookup_settings(self, appname, name, upolicy):
         """
         Given a settings name, return the aggregated policy blob.
         @param[in] appname: application user is accessing
-        @param[in] name: user group name or concatenation of names of the 
policy settings blob
+        @param[in] name: user group name
         @param[out] upolicy: dict holding policy values - the settings blob
+                    TODO: make this a c struct
         @return if allowed by policy
         # Note: the upolicy output is a non-nested dict with settings of 
interest
         # TODO: figure out decent defaults for upolicy settings that are 
undefined
         """
         try:
-            cachekey = appname + "|" + name
-            if cachekey in self.blob_lookup_cache:
-                upolicy.update( self.blob_lookup_cache[cachekey] )
-                return True
-            settings = self.settingsdb[appname]
-            ugroups = name.split("|")
-            self.policy_aggregate_policy_int (upolicy, settings, ugroups, 
PolicyKeys.KW_MAX_FRAME_SIZE)
-            self.policy_aggregate_policy_int (upolicy, settings, ugroups, 
PolicyKeys.KW_MAX_MESSAGE_SIZE)
-            self.policy_aggregate_policy_int (upolicy, settings, ugroups, 
PolicyKeys.KW_MAX_SESSION_WINDOW)
-            self.policy_aggregate_policy_int (upolicy, settings, ugroups, 
PolicyKeys.KW_MAX_SESSIONS)
-            self.policy_aggregate_policy_int (upolicy, settings, ugroups, 
PolicyKeys.KW_MAX_SENDERS)
-            self.policy_aggregate_policy_int (upolicy, settings, ugroups, 
PolicyKeys.KW_MAX_RECEIVERS)
-            self.policy_aggregate_policy_bool(upolicy, settings, ugroups, 
PolicyKeys.KW_ALLOW_DYNAMIC_SRC)
-            self.policy_aggregate_policy_bool(upolicy, settings, ugroups, 
PolicyKeys.KW_ALLOW_ANONYMOUS_SENDER)
-            self.policy_aggregate_policy_list(upolicy, settings, ugroups, 
PolicyKeys.KW_SOURCES)
-            self.policy_aggregate_policy_list(upolicy, settings, ugroups, 
PolicyKeys.KW_TARGETS)
-            c_upolicy = {}
-            c_upolicy.update(upolicy)
-            self.blob_lookup_cache[cachekey] = c_upolicy
+            if not appname in self.rulesetdb:
+                # TODO: ("LogMe: no policy defined for application %s" % app)
+                return ""
+
+            ruleset = self.rulesetdb[appname]
+
+            if not name in ruleset[PolicyKeys.KW_SETTINGS]:
+                # TODO: ("LogMe: no user group settings for application %s 
group %s" % (app, name))
+                return ""
+
+            upolicy.update(ruleset[PolicyKeys.KW_SETTINGS][name])
             return True
         except Exception, e:
             #print str(e)
             #pdb.set_trace()
-            return False
+            return ""
 
     def test_load_config(self):
-        ruleset_str = '["policyAccessRuleset", {"applicationName": 
"photoserver","maxConnections": 50,"maxConnPerUser": 5,"maxConnPerHost": 
20,"userGroups": {"anonymous":       "anonymous","users":           "u1, 
u2","paidsubscribers": "p1, p2","test":            "zeke, ynot","admin":        
   "alice, bob, ellen","superuser":       "ellen"},"connectionGroups": 
{"Ten18":     "10.18.0.0-10.18.255.255","EllensWS":  "72.135.2.9","TheLabs":   
"10.48.0.0-10.48.255.255, 192.168.100.0-192.168.100.255","localhost": 
"127.0.0.1, ::1","TheWorld":  "*"},"connectionIngressPolicies": {"anonymous":   
    "TheWorld","users":           "TheWorld","paidsubscribers": 
"TheWorld","test":            "TheLabs","admin":           "Ten18, TheLabs, 
localhost","superuser":       "EllensWS, localhost"},"connectionAllowDefault": 
true}]'
+        ruleset_str = '["policyAccessRuleset", {"applicationName": 
"photoserver","maxConnections": 50,"maxConnPerUser": 5,"maxConnPerHost": 
20,"userGroups": {"anonymous":       "anonymous","users":           "u1, 
u2","paidsubscribers": "p1, p2","test":            "zeke, ynot","admin":        
   "alice, bob","superuser":       "ellen"},"connectionGroups": {"Ten18":     
"10.18.0.0-10.18.255.255","EllensWS":  "72.135.2.9","TheLabs":   
"10.48.0.0-10.48.255.255, 192.168.100.0-192.168.100.255","localhost": 
"127.0.0.1, ::1","TheWorld":  "*"},"connectionIngressPolicies": {"anonymous":   
    "TheWorld","users":           "TheWorld","paidsubscribers": 
"TheWorld","test":            "TheLabs","admin":           "Ten18, TheLabs, 
localhost","superuser":       "EllensWS, localhost"},"connectionAllowDefault": 
true,'
+        ruleset_str += '"settings": {'
+        ruleset_str += '"anonymous":      {"maxFrameSize": 
111111,"maxMessageSize":   111111,"maxSessionWindow": 111111,"maxSessions":     
      1,"maxSenders":           11,"maxReceivers":         
11,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": 
"public",                           "targets": ""},'
+        ruleset_str += '"users":          {"maxFrameSize": 
222222,"maxMessageSize":   222222,"maxSessionWindow": 222222,"maxSessions":     
      2,"maxSenders":           22,"maxReceivers":         
22,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": 
"public, private",                  "targets": "public"},'
+        ruleset_str += '"paidsubscribers":{"maxFrameSize": 
333333,"maxMessageSize":   333333,"maxSessionWindow": 333333,"maxSessions":     
      3,"maxSenders":           33,"maxReceivers":         
33,"allowDynamicSrc":      true, "allowAnonymousSender": false,"sources": 
"public, private",                  "targets": "public, private"},'
+        ruleset_str += '"test":           {"maxFrameSize": 
444444,"maxMessageSize":   444444,"maxSessionWindow": 444444,"maxSessions":     
      4,"maxSenders":           44,"maxReceivers":         
44,"allowDynamicSrc":      true, "allowAnonymousSender": true, "sources": 
"private",                          "targets": "private"},'
+        ruleset_str += '"admin":          {"maxFrameSize": 
555555,"maxMessageSize":   555555,"maxSessionWindow": 555555,"maxSessions":     
      5,"maxSenders":           55,"maxReceivers":         
55,"allowDynamicSrc":      true, "allowAnonymousSender": true, "sources": 
"public, private, management",      "targets": "public, private, management"},'
+        ruleset_str += '"superuser":      {"maxFrameSize": 
666666,"maxMessageSize":   666666,"maxSessionWindow": 666666,"maxSessions":     
      6,"maxSenders":           66,"maxReceivers":         
66,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": 
"public, private, management, root","targets": "public, private, management, 
root"},'
+        ruleset_str += '"default":        {"maxFrameSize": 
222222,"maxMessageSize":   222222,"maxSessionWindow": 222222,"maxSessions":     
      2,"maxSenders":           22,"maxReceivers":         
22,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": 
"public, private",                  "targets": "public"}'
+        ruleset_str += '}}]'
         ruleset = json.loads(ruleset_str)
 
         self.create_ruleset(ruleset[1])
-
-        settings_strs = []
-        settings_strs.append('["policyAppSettings", {"applicationName": 
"photoserver","userGroupName":"anonymous",      "maxFrameSize": 
111111,"maxMessageSize":   111111,"maxSessionWindow": 111111,"maxSessions":     
      1,"maxSenders":           11,"maxReceivers":         
11,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": 
"public",                           "targets": ""}]')
-        settings_strs.append('["policyAppSettings", {"applicationName": 
"photoserver","userGroupName":"users",          "maxFrameSize": 
222222,"maxMessageSize":   222222,"maxSessionWindow": 222222,"maxSessions":     
      2,"maxSenders":           22,"maxReceivers":         
22,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": 
"public, private",                  "targets": "public"}]')
-        settings_strs.append('["policyAppSettings", {"applicationName": 
"photoserver","userGroupName":"paidsubscribers","maxFrameSize": 
333333,"maxMessageSize":   333333,"maxSessionWindow": 333333,"maxSessions":     
      3,"maxSenders":           33,"maxReceivers":         
33,"allowDynamicSrc":      true, "allowAnonymousSender": false,"sources": 
"public, private",                  "targets": "public, private"}]')
-        settings_strs.append('["policyAppSettings", {"applicationName": 
"photoserver","userGroupName":"test",           "maxFrameSize": 
444444,"maxMessageSize":   444444,"maxSessionWindow": 444444,"maxSessions":     
      4,"maxSenders":           44,"maxReceivers":         
44,"allowDynamicSrc":      true, "allowAnonymousSender": true, "sources": 
"private",                          "targets": "private"}]')
-        settings_strs.append('["policyAppSettings", {"applicationName": 
"photoserver","userGroupName":"admin",          "maxFrameSize": 
555555,"maxMessageSize":   555555,"maxSessionWindow": 555555,"maxSessions":     
      5,"maxSenders":           55,"maxReceivers":         
55,"allowDynamicSrc":      true, "allowAnonymousSender": true, "sources": 
"public, private, management",      "targets": "public, private, management"}]')
-        settings_strs.append('["policyAppSettings", {"applicationName": 
"photoserver","userGroupName":"superuser",      "maxFrameSize": 
666666,"maxMessageSize":   666666,"maxSessionWindow": 666666,"maxSessions":     
      6,"maxSenders":           66,"maxReceivers":         
66,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": 
"public, private, management, root","targets": "public, private, management, 
root"}]')
-        settings_strs.append('["policyAppSettings", {"applicationName": 
"photoserver","userGroupName":"default",        "maxFrameSize": 
222222,"maxMessageSize":   222222,"maxSessionWindow": 222222,"maxSessions":     
      2,"maxSenders":           22,"maxReceivers":         
22,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": 
"public, private",                  "targets": "public"}]')
-
-        for sstr in settings_strs:
-            settings = json.loads(sstr)
-            self.create_settings(settings[1])

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/1036c0ef/tests/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index d2d5e29..b43903a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -54,6 +54,7 @@ target_link_libraries(unit_tests_size qpid-dispatch)
 # While moving the files make sure that configure_file() is called on any 
.py.in files resulting in .py file
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/system_tests_sasl_plain.py.in 
${CMAKE_CURRENT_BINARY_DIR}/system_tests_sasl_plain.py)
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/router_engine_test.py DESTINATION 
${CMAKE_CURRENT_BINARY_DIR})
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/router_policy_test.py DESTINATION 
${CMAKE_CURRENT_BINARY_DIR})
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/system_tests_broker.py DESTINATION 
${CMAKE_CURRENT_BINARY_DIR})
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/system_tests_management.py DESTINATION 
${CMAKE_CURRENT_BINARY_DIR})
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/system_tests_one_router.py DESTINATION 
${CMAKE_CURRENT_BINARY_DIR})
@@ -80,6 +81,7 @@ add_test(unit_tests            ${TEST_WRAP} --vg unit_tests 
${CMAKE_CURRENT_SOUR
 
 # Add all sytem_tests* using add_test
 add_test(router_tests             ${TEST_WRAP} -s 
${CMAKE_CURRENT_BINARY_DIR}/router_engine_test.py -v)
+add_test(router_tests_policy      ${TEST_WRAP} -s 
${CMAKE_CURRENT_BINARY_DIR}/router_policy_test.py -v)
 add_test(system_tests_broker      ${TEST_WRAP} -s 
${CMAKE_CURRENT_BINARY_DIR}/system_tests_broker.py -v)
 add_test(system_tests_management  ${TEST_WRAP} -s 
${CMAKE_CURRENT_BINARY_DIR}/system_tests_management.py -v)
 add_test(system_tests_one_router  ${TEST_WRAP} -s 
${CMAKE_CURRENT_BINARY_DIR}/system_tests_one_router.py -v)
@@ -100,6 +102,7 @@ add_test(management_tests         ${TEST_WRAP} -m unittest 
-v management)
 #
 set(SYSTEM_TEST_FILES
   ${CMAKE_CURRENT_BINARY_DIR}/router_engine_test.py
+  ${CMAKE_CURRENT_BINARY_DIR}/router_policy_test.py
   ${CMAKE_CURRENT_BINARY_DIR}/run_system_tests.py
   ${CMAKE_CURRENT_BINARY_DIR}/system_test.py
   ${CMAKE_CURRENT_BINARY_DIR}/system_tests_one_router.py

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/1036c0ef/tests/policy-1/policy-photoserver.json
----------------------------------------------------------------------
diff --git a/tests/policy-1/policy-photoserver.json 
b/tests/policy-1/policy-photoserver.json
index 56b804a..6e13689 100644
--- a/tests/policy-1/policy-photoserver.json
+++ b/tests/policy-1/policy-photoserver.json
@@ -1,6 +1,5 @@
 {
     "photoserver": {
-        "policyVersion": 1,
         "maxConnections": 10,
         "maxConnPerUser": 5,
         "maxConnPerHost": 5,

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/1036c0ef/tests/policy-1/test-router-with-policy.json
----------------------------------------------------------------------
diff --git a/tests/policy-1/test-router-with-policy.json 
b/tests/policy-1/test-router-with-policy.json
index 4988093..dcf2de0 100644
--- a/tests/policy-1/test-router-with-policy.json
+++ b/tests/policy-1/test-router-with-policy.json
@@ -54,7 +54,7 @@
     ["policy", {
        "maximumConnections": 2
     }],
-  ["policyAccessRuleset", {
+  ["policyRuleset", {
       "applicationName": "photoserver",
       "maxConnections": 50,
       "maxConnPerUser": 5,
@@ -64,7 +64,7 @@
         "users":           "u1, u2",
         "paidsubscribers": "p1, p2",
         "test":            "zeke, ynot",
-        "admin":           "alice, bob, ellen",
+        "admin":           "alice, bob",
         "superuser":       "ellen"
       },
       "connectionGroups": {
@@ -82,111 +82,93 @@
         "admin":           "Ten18, TheLabs, localhost",
         "superuser":       "EllensWS, localhost"
       },
-      "connectionAllowDefault": true
-    }
-  ],
-  ["policyAppSettings", {
-      "applicationName": "photoserver",
-      "userGroupName":   "anonymous",
-      "maxFrameSize":     111111,
-      "maxMessageSize":   111111,
-      "maxSessionWindow": 111111,
-      "maxSessions":           1,
-      "maxSenders":           11,
-      "maxReceivers":         11,
-      "allowDynamicSrc":      false,
-      "allowAnonymousSender": false,
-      "sources": "public",
-      "targets": ""
-    }
-  ],
-  ["policyAppSettings", {
-      "applicationName": "photoserver",
-      "userGroupName":   "users",
-      "maxFrameSize":     222222,
-      "maxMessageSize":   222222,
-      "maxSessionWindow": 222222,
-      "maxSessions":           2,
-      "maxSenders":           22,
-      "maxReceivers":         22,
-      "allowDynamicSrc":      false,
-      "allowAnonymousSender": false,
-      "sources": "public, private",
-      "targets": "public"
-    }
-  ],
-  ["policyAppSettings", {
-      "applicationName": "photoserver",
-      "userGroupName":   "paidsubscribers",
-      "maxFrameSize":     333333,
-      "maxMessageSize":   333333,
-      "maxSessionWindow": 333333,
-      "maxSessions":           3,
-      "maxSenders":           33,
-      "maxReceivers":         33,
-      "allowDynamicSrc":      true,
-      "allowAnonymousSender": false,
-      "sources": "public, private",
-      "targets": "public, private"
-    }
-  ],
-  ["policyAppSettings", {
-      "applicationName": "photoserver",
-      "userGroupName":   "test",
-      "maxFrameSize":     444444,
-      "maxMessageSize":   444444,
-      "maxSessionWindow": 444444,
-      "maxSessions":           4,
-      "maxSenders":           44,
-      "maxReceivers":         44,
-      "allowDynamicSrc":      true,
-      "allowAnonymousSender": true,
-      "sources": "private",
-      "targets": "private"
-    }
-  ],
-  ["policyAppSettings", {
-      "applicationName": "photoserver",
-      "userGroupName":   "admin",
-      "maxFrameSize":     555555,
-      "maxMessageSize":   555555,
-      "maxSessionWindow": 555555,
-      "maxSessions":           5,
-      "maxSenders":           55,
-      "maxReceivers":         55,
-      "allowDynamicSrc":      true,
-      "allowAnonymousSender": true,
-      "sources": "public, private, management",
-      "targets": "public, private, management"
-    }
-  ],
-  ["policyAppSettings", {
-      "applicationName": "photoserver",
-      "userGroupName":   "superuser",
-      "maxFrameSize":     666666,
-      "maxMessageSize":   666666,
-      "maxSessionWindow": 666666,
-      "maxSessions":           6,
-      "maxSenders":           66,
-      "maxReceivers":         66,
-      "allowDynamicSrc":      false,
-      "allowAnonymousSender": false,
-      "sources": "public, private, management, root",
-      "targets": "public, private, management, root"
-    }
-  ],  ["policyAppSettings", {
-      "applicationName": "photoserver",
-      "userGroupName":   "default",
-      "maxFrameSize":     222222,
-      "maxMessageSize":   222222,
-      "maxSessionWindow": 222222,
-      "maxSessions":           2,
-      "maxSenders":           22,
-      "maxReceivers":         22,
-      "allowDynamicSrc":      false,
-      "allowAnonymousSender": false,
-      "sources": "public, private",
-      "targets": "public"
+      "connectionAllowDefault": true,
+      "settings": {
+        "anonymous" : {
+          "maxFrameSize":     111111,
+          "maxMessageSize":   111111,
+          "maxSessionWindow": 111111,
+          "maxSessions":           1,
+          "maxSenders":           11,
+          "maxReceivers":         11,
+          "allowDynamicSrc":      false,
+          "allowAnonymousSender": false,
+          "sources": "public",
+          "targets": ""
+        },
+        "users" : {
+          "maxFrameSize":     222222,
+          "maxMessageSize":   222222,
+          "maxSessionWindow": 222222,
+          "maxSessions":           2,
+          "maxSenders":           22,
+          "maxReceivers":         22,
+          "allowDynamicSrc":      false,
+          "allowAnonymousSender": false,
+          "sources": "public, private",
+          "targets": "public"
+        },
+        "paidsubscribers" : {
+          "maxFrameSize":     333333,
+          "maxMessageSize":   333333,
+          "maxSessionWindow": 333333,
+          "maxSessions":           3,
+          "maxSenders":           33,
+          "maxReceivers":         33,
+          "allowDynamicSrc":      true,
+          "allowAnonymousSender": false,
+          "sources": "public, private",
+          "targets": "public, private"
+        },
+        "test" : {
+          "maxFrameSize":     444444,
+          "maxMessageSize":   444444,
+          "maxSessionWindow": 444444,
+          "maxSessions":           4,
+          "maxSenders":           44,
+          "maxReceivers":         44,
+          "allowDynamicSrc":      true,
+          "allowAnonymousSender": true,
+          "sources": "private",
+          "targets": "private"
+        },
+        "admin" : {
+          "maxFrameSize":     555555,
+          "maxMessageSize":   555555,
+          "maxSessionWindow": 555555,
+          "maxSessions":           5,
+          "maxSenders":           55,
+          "maxReceivers":         55,
+          "allowDynamicSrc":      true,
+          "allowAnonymousSender": true,
+          "sources": "public, private, management",
+          "targets": "public, private, management"
+        },
+        "superuser" : {
+          "maxFrameSize":     666666,
+          "maxMessageSize":   666666,
+          "maxSessionWindow": 666666,
+          "maxSessions":           6,
+          "maxSenders":           66,
+          "maxReceivers":         66,
+          "allowDynamicSrc":      false,
+          "allowAnonymousSender": false,
+          "sources": "public, private, management, root",
+          "targets": "public, private, management, root"
+        },
+        "default" : {
+          "maxFrameSize":     222222,
+          "maxMessageSize":   222222,
+          "maxSessionWindow": 222222,
+          "maxSessions":           2,
+          "maxSenders":           22,
+          "maxReceivers":         22,
+          "allowDynamicSrc":      false,
+          "allowAnonymousSender": false,
+          "sources": "public, private",
+          "targets": "public"
+        }
+      }
     }
   ]
 ]

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/1036c0ef/tests/router_policy_test.py
----------------------------------------------------------------------
diff --git a/tests/router_policy_test.py b/tests/router_policy_test.py
new file mode 100644
index 0000000..5d2505d
--- /dev/null
+++ b/tests/router_policy_test.py
@@ -0,0 +1,243 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+import unittest
+
+from qpid_dispatch_internal.policy.policy_util import HostAddr
+from qpid_dispatch_internal.policy.policy_util import HostStruct
+from qpid_dispatch_internal.policy.policy_util import PolicyError
+from qpid_dispatch_internal.policy.policy_util import PolicyAppConnectionMgr
+from qpid_dispatch_internal.policy.policy_local import PolicyLocal
+from system_test import TestCase, main_module
+
+class PolicyHostAddrTest(TestCase):
+
+    def expect_deny(self, badhostname, msg):
+        denied = False
+        try:
+            xxx = HostStruct(badhostname)
+        except PolicyError:
+            denied = True
+        self.assertTrue(denied, ("%s" % msg))
+
+    def check_hostaddr_match(self, tHostAddr, tString, expectOk=True):
+        # check that the string is a match for the addr
+        # check that the internal struct version matches, too
+        ha = HostStruct(tString)
+        if expectOk:
+            self.assertTrue( tHostAddr.match_str(tString) )
+            self.assertTrue( tHostAddr.match_bin(ha) )
+        else:
+            self.assertFalse( tHostAddr.match_str(tString) )
+            self.assertFalse( tHostAddr.match_bin(ha) )
+
+    def test_policy_hostaddr_ipv4(self):
+        # Create simple host and range
+        aaa = HostAddr("192.168.1.1")
+        bbb = HostAddr("1.1.1.1,1.1.1.255")
+        # Verify host and range
+        self.check_hostaddr_match(aaa, "192.168.1.1")
+        self.check_hostaddr_match(aaa, "1.1.1.1", False)
+        self.check_hostaddr_match(aaa, "192.168.1.2", False)
+        self.check_hostaddr_match(bbb, "1.1.1.1")
+        self.check_hostaddr_match(bbb, "1.1.1.254")
+        self.check_hostaddr_match(bbb, "1.1.1.0", False)
+        self.check_hostaddr_match(bbb, "1.1.2.0", False)
+
+    def test_policy_hostaddr_ipv6(self):
+        if not HostAddr.has_ipv6:
+            self.skipTest("System IPv6 support is not available")
+        # Create simple host and range
+        aaa = HostAddr("::1")
+        bbb = HostAddr("::1,::ffff")
+        ccc = HostAddr("ffff::0,ffff:ffff::0")
+        # Verify host and range
+        self.check_hostaddr_match(aaa, "::1")
+        self.check_hostaddr_match(aaa, "::2", False)
+        self.check_hostaddr_match(aaa, "ffff:ffff::0", False)
+        self.check_hostaddr_match(bbb, "::1")
+        self.check_hostaddr_match(bbb, "::fffe")
+        self.check_hostaddr_match(bbb, "::1:0", False)
+        self.check_hostaddr_match(bbb, "ffff::0", False)
+        self.check_hostaddr_match(ccc, "ffff::1")
+        self.check_hostaddr_match(ccc, "ffff:fffe:ffff:ffff::ffff")
+        self.check_hostaddr_match(ccc, "ffff:ffff::1", False)
+        self.check_hostaddr_match(ccc, "ffff:ffff:ffff:ffff::ffff", False)
+
+    def test_policy_hostaddr_ipv4_wildcard(self):
+        aaa = HostAddr("*")
+        self.check_hostaddr_match(aaa,"0.0.0.0")
+        self.check_hostaddr_match(aaa,"127.0.0.1")
+        self.check_hostaddr_match(aaa,"255.254.253.252")
+
+
+    def test_policy_hostaddr_ipv6_wildcard(self):
+        if not HostAddr.has_ipv6:
+            self.skipTest("System IPv6 support is not available")
+        aaa = HostAddr("*")
+        self.check_hostaddr_match(aaa,"::0")
+        self.check_hostaddr_match(aaa,"::1")
+        
self.check_hostaddr_match(aaa,"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
+
+    def test_policy_malformed_hostaddr_ipv4(self):
+        self.expect_deny( "0.0.0.0.0", "Name or service not known")
+        self.expect_deny( "1.1.1.1,2.2.2.2,3.3.3.3", "arg count")
+        self.expect_deny( "9.9.9.9,8.8.8.8", "a > b")
+
+    def test_policy_malformed_hostaddr_ipv6(self):
+        if not HostAddr.has_ipv6:
+            self.skipTest("System IPv6 support is not available")
+        self.expect_deny( "1::2::3", "Name or service not known")
+        self.expect_deny( "::1,::2,::3", "arg count")
+        self.expect_deny( "0:ff:0,0:fe:ffff:ffff::0", "a > b")
+
+class PolicyFile(TestCase):
+
+    policy = PolicyLocal()
+    policy.test_load_config()
+
+    def dict_compare(self, d1, d2):
+        d1_keys = set(d1.keys())
+        d2_keys = set(d2.keys())
+        intersect_keys = d1_keys.intersection(d2_keys)
+        added = d1_keys - d2_keys
+        removed = d2_keys - d1_keys
+        modified = {o : (d1[o], d2[o]) for o in intersect_keys if d1[o] != 
d2[o]}
+        same = set(o for o in intersect_keys if d1[o] == d2[o])
+        return len(added) == 0 and len(removed) == 0 and len(modified) == 0
+
+    def test_policy1_test_zeke_ok(self):
+        p1 = PolicyFile.policy.lookup_user('zeke', '192.168.100.5', 
'photoserver', '192.168.100.5:33333')
+        self.assertTrue(p1 == 'test')
+        upolicy = {}
+        self.assertTrue(
+            PolicyFile.policy.lookup_settings('photoserver', p1, upolicy)
+        )
+        self.assertTrue(upolicy['maxFrameSize']            == 444444)
+        self.assertTrue(upolicy['maxMessageSize']          == 444444)
+        self.assertTrue(upolicy['maxSessionWindow']        == 444444)
+        self.assertTrue(upolicy['maxSessions']              == 4)
+        self.assertTrue(upolicy['maxSenders']               == 44)
+        self.assertTrue(upolicy['maxReceivers']             == 44)
+        self.assertTrue(upolicy['allowAnonymousSender'])
+        self.assertTrue(upolicy['allowDynamicSrc'])
+        self.assertTrue(len(upolicy['targets']) == 1)
+        self.assertTrue('private' in upolicy['targets'])
+        self.assertTrue(len(upolicy['sources']) == 1)
+        self.assertTrue('private' in upolicy['sources'])
+
+    def test_policy1_test_zeke_bad_IP(self):
+        self.assertTrue(
+            PolicyFile.policy.lookup_user('zeke', '10.18.0.1',    
'photoserver', "connid") == '')
+        self.assertTrue(
+            PolicyFile.policy.lookup_user('zeke', '72.135.2.9',   
'photoserver', "connid") == '')
+        self.assertTrue(
+            PolicyFile.policy.lookup_user('zeke', '127.0.0.1',    
'photoserver', "connid") == '')
+
+    def test_policy1_test_zeke_bad_app(self):
+        self.assertTrue(
+            PolicyFile.policy.lookup_user('zeke', '192.168.100.5','galleria', 
"connid") == '')
+
+    def test_policy1_test_users_same_permissions(self):
+        zname = PolicyFile.policy.lookup_user('zeke', '192.168.100.5', 
'photoserver', '192.168.100.5:33333')
+        yname = PolicyFile.policy.lookup_user('ynot', '10.48.255.254', 
'photoserver', '192.168.100.5:33334')
+        self.assertTrue( zname == yname )
+
+
+class PolicyAppConnectionMgrTests(TestCase):
+
+    def test_policy_app_conn_mgr_fail_by_total(self):
+        stats = PolicyAppConnectionMgr(1, 2, 2)
+        diags = []
+        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
+        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
+        self.assertTrue(len(diags) == 1)
+        self.assertTrue('by total' in diags[0])
+
+    def test_policy_app_conn_mgr_fail_by_user(self):
+        stats = PolicyAppConnectionMgr(3, 1, 2)
+        diags = []
+        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
+        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
+        self.assertTrue(len(diags) == 1)
+        self.assertTrue('per user' in diags[0])
+
+    def test_policy_app_conn_mgr_fail_by_hosts(self):
+        stats = PolicyAppConnectionMgr(3, 2, 1)
+        diags = []
+        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
+        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
+        self.assertTrue(len(diags) == 1)
+        self.assertTrue('per host' in diags[0])
+
+    def test_policy_app_conn_mgr_fail_by_user_hosts(self):
+        stats = PolicyAppConnectionMgr(3, 1, 1)
+        diags = []
+        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
+        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
+        self.assertTrue(len(diags) == 2)
+        self.assertTrue('per user' in diags[0] or 'per user' in diags[1])
+        self.assertTrue('per host' in diags[0] or 'per host' in diags[1])
+
+    def test_policy_app_conn_mgr_update(self):
+        stats = PolicyAppConnectionMgr(3, 1, 2)
+        diags = []
+        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
+        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
+        self.assertTrue(len(diags) == 1)
+        self.assertTrue('per user' in diags[0])
+        diags = []
+        stats.update(3, 2, 2)
+        self.assertTrue(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
+
+    def test_policy_app_conn_mgr_create_bad_settings(self):
+        denied = False
+        try:
+            stats = PolicyAppConnectionMgr(-3, 1, 2)
+        except PolicyError:
+            denied = True
+        self.assertTrue(denied, "Failed to detect negative setting value.")
+
+    def test_policy_app_conn_mgr_update_bad_settings(self):
+        denied = False
+        try:
+            stats = PolicyAppConnectionMgr(0, 0, 0)
+        except PolicyError:
+            denied = True
+        self.assertFalse(denied, "Should allow all zeros.")
+        try:
+            stats.update(0, -1, 0)
+        except PolicyError:
+            denied = True
+        self.assertTrue(denied, "Failed to detect negative setting value.")
+
+    def test_policy_app_conn_mgr_larger_counts(self):
+        stats = PolicyAppConnectionMgr(10000, 10000, 10000)
+        diags = []
+        for i in range(0, 10000):
+            self.assertTrue(stats.can_connect('1.1.1.1:' + str(i), 'chuck', 
'1.1.1.1', diags))
+            self.assertTrue(len(diags) == 0)
+        self.assertFalse(stats.can_connect('1.1.1.1:10000', 'chuck', 
'1.1.1.1', diags))
+        self.assertTrue(len(diags) == 3)
+        self.assertTrue(stats.connections_active == 10000)
+        self.assertTrue(stats.connections_approved == 10000)
+        self.assertTrue(stats.connections_denied == 1)
+
+if __name__ == '__main__':
+    unittest.main(main_module())

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/1036c0ef/tests/system_tests_policy.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_policy.py b/tests/system_tests_policy.py
index 14dfbf0..74f93c4 100644
--- a/tests/system_tests_policy.py
+++ b/tests/system_tests_policy.py
@@ -17,23 +17,11 @@
 # under the License.
 #
 
-import sys
 import unittest
-from time import sleep
 from system_test import TestCase, Qdrouterd, main_module
-
-from proton import Message
 from proton import ConnectionException
-from proton.reactor import AtMostOnce
 from proton.utils import BlockingConnection, LinkDetached
 
-from qpid_dispatch.management.client import Node
-from system_test import TIMEOUT
-
-from qpid_dispatch_internal.policy.policy_util import \
-    HostAddr, PolicyError, HostStruct, PolicyAppConnectionMgr
-from qpid_dispatch_internal.policy.policy_local import PolicyLocal
-
 class AbsoluteConnectionCountLimit(TestCase):
     """
     Verify that connections beyond the absolute limit are denied
@@ -65,7 +53,7 @@ class AbsoluteConnectionCountLimit(TestCase):
         except ConnectionException:
             denied = True
 
-        self.assertFalse(denied) # connections that should open did not open
+        self.assertFalse(denied) # assert if connections that should open did 
not open
 
         # third connection should be denied
         denied = False
@@ -74,253 +62,10 @@ class AbsoluteConnectionCountLimit(TestCase):
         except ConnectionException:
             denied = True
 
-        self.assertTrue(denied) # connection that should not open did open
+        self.assertTrue(denied) # assert if connection that should not open 
did open
 
         bc1.close()
         bc2.close()
 
-class PolicyHostAddrTest(TestCase):
-
-    def expect_deny(self, badhostname, msg):
-        denied = False
-        try:
-            xxx = HostStruct(badhostname)
-        except PolicyError:
-            denied = True
-        self.assertTrue(denied, ("%s" % msg))
-
-    def check_hostaddr_match(self, tHostAddr, tString, expectOk=True):
-        # check that the string is a match for the addr
-        # check that the internal struct version matches, too
-        ha = HostStruct(tString)
-        if expectOk:
-            self.assertTrue( tHostAddr.match_str(tString) )
-            self.assertTrue( tHostAddr.match_bin(ha) )
-        else:
-            self.assertFalse( tHostAddr.match_str(tString) )
-            self.assertFalse( tHostAddr.match_bin(ha) )
-
-    def test_policy_hostaddr_ipv4(self):
-        # Create simple host and range
-        aaa = HostAddr("192.168.1.1")
-        bbb = HostAddr("1.1.1.1,1.1.1.255")
-        # Verify host and range
-        self.check_hostaddr_match(aaa, "192.168.1.1")
-        self.check_hostaddr_match(aaa, "1.1.1.1", False)
-        self.check_hostaddr_match(aaa, "192.168.1.2", False)
-        self.check_hostaddr_match(bbb, "1.1.1.1")
-        self.check_hostaddr_match(bbb, "1.1.1.254")
-        self.check_hostaddr_match(bbb, "1.1.1.0", False)
-        self.check_hostaddr_match(bbb, "1.1.2.0", False)
-
-    def test_policy_hostaddr_ipv6(self):
-        if not HostAddr.has_ipv6:
-            self.skipTest("System IPv6 support is not available")
-        # Create simple host and range
-        aaa = HostAddr("::1")
-        bbb = HostAddr("::1,::ffff")
-        ccc = HostAddr("ffff::0,ffff:ffff::0")
-        # Verify host and range
-        self.check_hostaddr_match(aaa, "::1")
-        self.check_hostaddr_match(aaa, "::2", False)
-        self.check_hostaddr_match(aaa, "ffff:ffff::0", False)
-        self.check_hostaddr_match(bbb, "::1")
-        self.check_hostaddr_match(bbb, "::fffe")
-        self.check_hostaddr_match(bbb, "::1:0", False)
-        self.check_hostaddr_match(bbb, "ffff::0", False)
-        self.check_hostaddr_match(ccc, "ffff::1")
-        self.check_hostaddr_match(ccc, "ffff:fffe:ffff:ffff::ffff")
-        self.check_hostaddr_match(ccc, "ffff:ffff::1", False)
-        self.check_hostaddr_match(ccc, "ffff:ffff:ffff:ffff::ffff", False)
-
-    def test_policy_hostaddr_ipv4_wildcard(self):
-        aaa = HostAddr("*")
-        self.check_hostaddr_match(aaa,"0.0.0.0")
-        self.check_hostaddr_match(aaa,"127.0.0.1")
-        self.check_hostaddr_match(aaa,"255.254.253.252")
-
-
-    def test_policy_hostaddr_ipv6_wildcard(self):
-        if not HostAddr.has_ipv6:
-            self.skipTest("System IPv6 support is not available")
-        aaa = HostAddr("*")
-        self.check_hostaddr_match(aaa,"::0")
-        self.check_hostaddr_match(aaa,"::1")
-        
self.check_hostaddr_match(aaa,"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
-
-    def test_policy_malformed_hostaddr_ipv4(self):
-        self.expect_deny( "0.0.0.0.0", "Name or service not known")
-        self.expect_deny( "1.1.1.1,2.2.2.2,3.3.3.3", "arg count")
-        self.expect_deny( "9.9.9.9,8.8.8.8", "a > b")
-
-    def test_policy_malformed_hostaddr_ipv6(self):
-        if not HostAddr.has_ipv6:
-            self.skipTest("System IPv6 support is not available")
-        self.expect_deny( "1::2::3", "Name or service not known")
-        self.expect_deny( "::1,::2,::3", "arg count")
-        self.expect_deny( "0:ff:0,0:fe:ffff:ffff::0", "a > b")
-
-class PolicyFile(TestCase):
-
-    policy = PolicyLocal()
-    policy.test_load_config()
-
-    def dict_compare(self, d1, d2):
-        d1_keys = set(d1.keys())
-        d2_keys = set(d2.keys())
-        intersect_keys = d1_keys.intersection(d2_keys)
-        added = d1_keys - d2_keys
-        removed = d2_keys - d1_keys
-        modified = {o : (d1[o], d2[o]) for o in intersect_keys if d1[o] != 
d2[o]}
-        same = set(o for o in intersect_keys if d1[o] == d2[o])
-        return len(added) == 0 and len(removed) == 0 and len(modified) == 0
-
-    def test_policy1_test_zeke_ok(self):
-        unames = []
-        self.assertTrue(
-            PolicyFile.policy.lookup_user('zeke', '192.168.100.5', 
'photoserver', '192.168.100.5:33333', unames)
-        )
-        upolicy = {}
-        self.assertTrue(
-            PolicyFile.policy.lookup_settings('photoserver', unames[0], 
upolicy)
-        )
-        self.assertTrue(upolicy['maxFrameSize']            == 444444)
-        self.assertTrue(upolicy['maxMessageSize']          == 444444)
-        self.assertTrue(upolicy['maxSessionWindow']        == 444444)
-        self.assertTrue(upolicy['maxSessions']              == 4)
-        self.assertTrue(upolicy['maxSenders']               == 44)
-        self.assertTrue(upolicy['maxReceivers']             == 44)
-        self.assertTrue(upolicy['allowAnonymousSender'])
-        self.assertTrue(upolicy['allowDynamicSrc'])
-        self.assertTrue(len(upolicy['targets']) == 1)
-        self.assertTrue('private' in upolicy['targets'])
-        self.assertTrue(len(upolicy['sources']) == 1)
-        self.assertTrue('private' in upolicy['sources'])
-
-    def test_policy1_test_zeke_bad_IP(self):
-        unames = []
-        self.assertFalse(
-            PolicyFile.policy.lookup_user('zeke', '10.18.0.1',    
'photoserver', "connid", unames) )
-        self.assertFalse(
-            PolicyFile.policy.lookup_user('zeke', '72.135.2.9',   
'photoserver', "connid", unames) )
-        self.assertFalse(
-            PolicyFile.policy.lookup_user('zeke', '127.0.0.1',    
'photoserver', "connid", unames) )
-
-    def test_policy1_test_zeke_bad_app(self):
-        unames = []
-        self.assertFalse(
-            PolicyFile.policy.lookup_user('zeke', '192.168.100.5','galleria', 
"connid", unames) )
-
-    def test_policy1_test_users_same_permissions(self):
-        znames = []
-        self.assertTrue(
-            PolicyFile.policy.lookup_user('zeke', '192.168.100.5', 
'photoserver', '192.168.100.5:33333', znames) )
-        ynames = []
-        self.assertTrue(
-            PolicyFile.policy.lookup_user('ynot', '10.48.255.254', 
'photoserver', '192.168.100.5:33334', ynames) )
-        self.assertTrue( znames[0] == ynames[0] )
-
-    def test_policy1_superuser_aggregation(self):
-        unames = []
-        self.assertTrue(
-            PolicyFile.policy.lookup_user('ellen', '72.135.2.9', 
'photoserver', '75.135.2.9:33333', unames)
-        )
-        upolicy = {}
-        self.assertTrue(
-            PolicyFile.policy.lookup_settings('photoserver', unames[0], 
upolicy)
-        )
-        self.assertTrue(upolicy['maxFrameSize']            == 666666)
-        self.assertTrue(upolicy['maxMessageSize']          == 666666)
-        self.assertTrue(upolicy['maxSessionWindow']        == 666666)
-        self.assertTrue(upolicy['maxSessions']              == 6)
-        self.assertTrue(upolicy['maxSenders']               == 66)
-        self.assertTrue(upolicy['maxReceivers']             == 66)
-        self.assertTrue(upolicy['allowAnonymousSender'])
-        self.assertTrue(upolicy['allowDynamicSrc'])
-        addrs = ['public', 'private','management', 'root']
-        self.assertTrue(len(upolicy['targets']) == 4)
-        self.assertTrue(len(upolicy['sources']) == 4)
-        for s in addrs: self.assertTrue(s in upolicy['targets'])
-        for s in addrs: self.assertTrue(s in upolicy['sources'])
-
-class PolicyAppConnectionMgrTests(TestCase):
-
-    def test_policy_app_conn_mgr_fail_by_total(self):
-        stats = PolicyAppConnectionMgr(1, 2, 2)
-        diags = []
-        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
-        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
-        self.assertTrue(len(diags) == 1)
-        self.assertTrue('by total' in diags[0])
-
-    def test_policy_app_conn_mgr_fail_by_user(self):
-        stats = PolicyAppConnectionMgr(3, 1, 2)
-        diags = []
-        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
-        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
-        self.assertTrue(len(diags) == 1)
-        self.assertTrue('per user' in diags[0])
-
-    def test_policy_app_conn_mgr_fail_by_hosts(self):
-        stats = PolicyAppConnectionMgr(3, 2, 1)
-        diags = []
-        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
-        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
-        self.assertTrue(len(diags) == 1)
-        self.assertTrue('per host' in diags[0])
-
-    def test_policy_app_conn_mgr_fail_by_user_hosts(self):
-        stats = PolicyAppConnectionMgr(3, 1, 1)
-        diags = []
-        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
-        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
-        self.assertTrue(len(diags) == 2)
-        self.assertTrue('per user' in diags[0] or 'per user' in diags[1])
-        self.assertTrue('per host' in diags[0] or 'per host' in diags[1])
-
-    def test_policy_app_conn_mgr_update(self):
-        stats = PolicyAppConnectionMgr(3, 1, 2)
-        diags = []
-        self.assertTrue(stats.can_connect('10.10.10.10:10000', 'chuck', 
'10.10.10.10', diags))
-        self.assertFalse(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
-        self.assertTrue(len(diags) == 1)
-        self.assertTrue('per user' in diags[0])
-        diags = []
-        stats.update(3, 2, 2)
-        self.assertTrue(stats.can_connect('10.10.10.10:10001', 'chuck', 
'10.10.10.10', diags))
-
-    def test_policy_app_conn_mgr_create_bad_settings(self):
-        denied = False
-        try:
-            stats = PolicyAppConnectionMgr(-3, 1, 2)
-        except PolicyError:
-            denied = True
-        self.assertTrue(denied, "Failed to detect negative setting value.")
-
-    def test_policy_app_conn_mgr_update_bad_settings(self):
-        denied = False
-        try:
-            stats = PolicyAppConnectionMgr(0, 0, 0)
-        except PolicyError:
-            denied = True
-        self.assertFalse(denied, "Should allow all zeros.")
-        try:
-            stats.update(0, -1, 0)
-        except PolicyError:
-            denied = True
-        self.assertTrue(denied, "Failed to detect negative setting value.")
-
-    def test_policy_app_conn_mgr_larger_counts(self):
-        stats = PolicyAppConnectionMgr(10000, 10000, 10000)
-        diags = []
-        for i in range(0, 10000):
-            self.assertTrue(stats.can_connect('1.1.1.1:' + str(i), 'chuck', 
'1.1.1.1', diags))
-            self.assertTrue(len(diags) == 0)
-        self.assertFalse(stats.can_connect('1.1.1.1:10000', 'chuck', 
'1.1.1.1', diags))
-        self.assertTrue(len(diags) == 3)
-        self.assertTrue(stats.connections_active == 10000)
-        self.assertTrue(stats.connections_approved == 10000)
-        self.assertTrue(stats.connections_denied == 1)
-
 if __name__ == '__main__':
     unittest.main(main_module())


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to