@Test
public final void testIsValid_failures() throws Exception {

	for (Action action : cu) {
		// passing in a null policy should fail with appropriate failure reason
		_policy = null;
		checkFailure_isValid(action, "missing", "policy");
		
		// policy must have a name on it
		_policy = mock(RangerPolicy.class);
		for (String name : new String[] { null, "  " }) {
			when(_policy.getName()).thenReturn(name);
			when(_policy.getResources()).thenReturn(null);
			checkFailure_isValid(action, "missing", "name");
		}
		
		// for update id is required!
		if (action == Action.UPDATE) {
			when(_policy.getId()).thenReturn(null);
			checkFailure_isValid(action, "missing", "id");
		}
	}
	RangerService service = mock(RangerService.class);
	/*
	 * Id is ignored for Create but name should not belong to an existing policy.  For update, policy should exist for its id and should match its name.
	 */
	when(_policy.getName()).thenReturn("policy-name");
	when(_policy.getService()).thenReturn("service-name");
	when(_store.getServiceByName("service-name")).thenReturn(service);
	when(service.getId()).thenReturn(2L);
	RangerPolicy existingPolicy = mock(RangerPolicy.class);
	when(existingPolicy.getId()).thenReturn(7L);
	when(existingPolicy.getService()).thenReturn("service-name");
	List<RangerPolicy> existingPolicies = new ArrayList<>();
	when(_store.getPolicyId(service.getId(), "policy-name", _zoneId)).thenReturn(7L);
	checkFailure_isValid(Action.CREATE, "semantic", "policy name");
	
	// update : does not exist for id
	when(_policy.getId()).thenReturn(7L);
	when(_store.getPolicy(7L)).thenReturn(null);
	checkFailure_isValid(Action.UPDATE, "semantic", "id");
	// Update: name should not point to an existing different policy, i.e. with a different id
	when(_store.getPolicy(7L)).thenReturn(existingPolicy);
	RangerPolicy anotherExistingPolicy = mock(RangerPolicy.class);
	when(anotherExistingPolicy.getId()).thenReturn(8L);
	when(anotherExistingPolicy.getService()).thenReturn("service-name");
	existingPolicies.add(anotherExistingPolicy);
	when(_store.getPolicyId(service.getId(), "policy-name", _zoneId)).thenReturn(8L);
	checkFailure_isValid(Action.UPDATE, "semantic", "id/name");
	
	// policy must have service name on it and it should be valid
	when(_policy.getName()).thenReturn("policy-name");
	for (Action action : cu) {
		for (boolean isAdmin : new boolean[] { true, false }) {
			when(_policy.getService()).thenReturn(null);
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForMissingValue(_failures, "service name");

			when(_policy.getService()).thenReturn("");
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForMissingValue(_failures, "service name");
		}
	}
	
	// service name should be valid
	when(_store.getServiceByName("service-name")).thenReturn(null);
	when(_store.getServiceByName("another-service-name")).thenThrow(new Exception());
	for (Action action : cu) {
		for (boolean isAdmin : new boolean[] { true, false }) {
			when(_policy.getService()).thenReturn(null);
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForMissingValue(_failures, "service name");

			when(_policy.getService()).thenReturn(null);
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForMissingValue(_failures, "service name");

			when(_policy.getService()).thenReturn("service-name");
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForSemanticError(_failures, "service name");

			when(_policy.getService()).thenReturn("another-service-name");
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForSemanticError(_failures, "service name");
		}
	}
	
	// policy must contain at least one policy item
	List<RangerPolicyItem> policyItems = new ArrayList<>();
	for (Action action : cu) {
		for (boolean isAdmin : new boolean[] { true, false }) {
			// when it is null
			when(_policy.getPolicyItems()).thenReturn(null);
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForMissingValue(_failures, "policy items");
			// or when it is not null but empty.
			when(_policy.getPolicyItems()).thenReturn(policyItems);
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForMissingValue(_failures, "policy items");
		}
	}
	
	// these are known good policy items -- same as used above in happypath
	policyItems = _utils.createPolicyItems(policyItemsData);
	when(_policy.getPolicyItems()).thenReturn(policyItems);
	// policy item check requires that service def should exist
	when(service.getType()).thenReturn("service-type");
	when(_store.getServiceDefByName("service-type")).thenReturn(null);
	for (Action action : cu) {
		for (boolean isAdmin : new boolean[] { true, false }) {
			when(_policy.getService()).thenReturn("service-name");
			when(_store.getServiceByName("service-name")).thenReturn(service);
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForInternalError(_failures, "policy service def");
		}
	}
	
	// service-def should contain the right access types on it.
	_serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes_bad, "service-type");
	when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
	for (Action action : cu) {
		for (boolean isAdmin : new boolean[] { true, false }) {
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForSemanticError(_failures, "policy item access type");
		}
	}
	
	// create the right service def with right resource defs - this is the same as in the happypath test above.
	_serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes, "service-type");
	when(_store.getPolicyId(service.getId(), "policy-name", _zoneId)).thenReturn(null);
	List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
	when(_serviceDef.getResources()).thenReturn(resourceDefs);
	when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
	// one mandatory is missing (tbl) and one unknown resource is specified (extra), and values of option resource don't conform to validation pattern (col)
	Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
	when(_policy.getResources()).thenReturn(policyResources);
	// ensure thta policy is kosher when it comes to resource signature
	RangerPolicyResourceSignature signature = mock(RangerPolicyResourceSignature.class);
	when(_factory.createPolicyResourceSignature(_policy)).thenReturn(signature);
	when(signature.getSignature()).thenReturn("hash-1");
	when(_store.getPoliciesByResourceSignature("service-name", "hash-1", true)).thenReturn(null); // store does not have any policies for that signature hash
	for (Action action : cu) {
		for (boolean isAdmin : new boolean[] { true, false }) {
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForSemanticError(_failures, "resource-values", "col"); // for spurious resource: "extra"
			_utils.checkFailureForSemanticError(_failures, "isRecursive", "db"); // for specifying it as true when def did not allow it
			_utils.checkFailureForSemanticError(_failures, "isExcludes", "col"); // for specifying it as true when def did not allow it
		}
	}
	
	// Check if error around resource signature clash are reported.  have Store return policies for same signature
	when(_store.getPoliciesByResourceSignature("service-name", "hash-1", true)).thenReturn(existingPolicies);
	for (Action action : cu) {
		for (boolean isAdmin : new boolean[] { true, false }) {
			_failures.clear(); Assert.assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
			_utils.checkFailureForSemanticError(_failures, "policy resources");
		}
	}
}