| /* |
| * 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. |
| */ |
| |
| using System; |
| using System.Collections.Generic; |
| using System.Threading; |
| |
| namespace Apache.Geode.Client.UnitTests |
| { |
| using NUnit.Framework; |
| using Apache.Geode.DUnitFramework; |
| using Apache.Geode.Client.Tests; |
| using Apache.Geode.Client; |
| //using Region = Apache.Geode.Client.IRegion<Object, Object>; |
| using AssertionException = Apache.Geode.Client.AssertionException; |
| public abstract class ThinClientSecurityAuthzTestBase : ThinClientRegionSteps |
| { |
| #region Protected members |
| |
| protected const string SubregionName = "AuthSubregion"; |
| protected const string CacheXml1 = "cacheserver_notify_subscription.xml"; |
| protected const string CacheXml2 = "cacheserver_notify_subscription2.xml"; |
| |
| #endregion |
| |
| #region Private methods |
| |
| private static string IndicesToString(int[] indices) |
| { |
| string str = string.Empty; |
| if (indices != null && indices.Length > 0) |
| { |
| str += indices[0]; |
| for (int index = 1; index < indices.Length; ++index) |
| { |
| str += ','; |
| str += indices[index]; |
| } |
| } |
| return str; |
| } |
| |
| private IRegion<TKey, TValue> CreateSubregion<TKey, TValue>(IRegion<TKey, TValue> region) |
| { |
| Util.Log("CreateSubregion " + SubregionName); |
| IRegion<TKey, TValue> subregion = region.GetSubRegion(SubregionName); |
| if (subregion == null) |
| { |
| //subregion = region.CreateSubRegion(SubregionName, region.Attributes); |
| subregion = CacheHelper.GetRegion<TKey, TValue>(region.FullPath).CreateSubRegion(SubregionName, region.Attributes); |
| } |
| return subregion; |
| } |
| |
| private bool CheckFlags(OpFlags flags, OpFlags checkFlag) |
| { |
| return ((flags & checkFlag) == checkFlag); |
| } |
| |
| protected void DoOp(OperationCode op, int[] indices, |
| OpFlags flags, ExpectedResult expectedResult) |
| { |
| DoOp(op, indices, flags, expectedResult, null, false); |
| } |
| |
| protected void DoOp(OperationCode op, int[] indices, |
| OpFlags flags, ExpectedResult expectedResult, Properties<string, string> creds, bool isMultiuser) |
| { |
| IRegion<object, object> region; |
| if(isMultiuser) |
| region = CacheHelper.GetRegion<object, object>(RegionName, creds); |
| else |
| region = CacheHelper.GetRegion<object, object>(RegionName); |
| |
| if (CheckFlags(flags, OpFlags.UseSubRegion)) |
| { |
| IRegion<object, object> subregion = null; |
| if (CheckFlags(flags, OpFlags.NoCreateSubRegion)) |
| { |
| subregion = region.GetSubRegion(SubregionName); |
| if (CheckFlags(flags, OpFlags.CheckNoRegion)) |
| { |
| Assert.IsNull(subregion); |
| return; |
| } |
| else |
| { |
| Assert.IsNotNull(subregion); |
| } |
| } |
| else |
| { |
| subregion = CreateSubregion(region); |
| if (isMultiuser) |
| subregion = region.GetSubRegion(SubregionName); |
| } |
| Assert.IsNotNull(subregion); |
| region = subregion; |
| } |
| else if (CheckFlags(flags, OpFlags.CheckNoRegion)) |
| { |
| Assert.IsNull(region); |
| return; |
| } |
| else |
| { |
| Assert.IsNotNull(region); |
| } |
| string valPrefix; |
| if (CheckFlags(flags, OpFlags.UseNewVal)) |
| { |
| valPrefix = NValuePrefix; |
| } |
| else |
| { |
| valPrefix = ValuePrefix; |
| } |
| int numOps = indices.Length; |
| Util.Log("Got DoOp for op: " + op + ", numOps: " + numOps |
| + ", indices: " + IndicesToString(indices)); |
| bool exceptionOccured = false; |
| bool breakLoop = false; |
| for (int indexIndex = 0; indexIndex < indices.Length; ++indexIndex) |
| { |
| if (breakLoop) |
| { |
| break; |
| } |
| int index = indices[indexIndex]; |
| string key = KeyPrefix + index; |
| string expectedValue = (valPrefix + index); |
| try |
| { |
| switch (op) |
| { |
| case OperationCode.Get: |
| Object value = null; |
| if (CheckFlags(flags, OpFlags.LocalOp)) |
| { |
| int sleepMillis = 100; |
| int numTries = 30; |
| bool success = false; |
| while (!success && numTries-- > 0) |
| { |
| if (!isMultiuser && region.ContainsValueForKey(key)) |
| { |
| value = region[key]; |
| success = expectedValue.Equals(value.ToString()); |
| if (CheckFlags(flags, OpFlags.CheckFail)) |
| { |
| success = !success; |
| } |
| } |
| else |
| { |
| value = null; |
| success = CheckFlags(flags, OpFlags.CheckFail); |
| } |
| if (!success) |
| { |
| Thread.Sleep(sleepMillis); |
| } |
| } |
| } |
| else |
| { |
| if (!isMultiuser) |
| { |
| if (CheckFlags(flags, OpFlags.CheckNoKey)) |
| { |
| Assert.IsFalse(region.GetLocalView().ContainsKey(key)); |
| } |
| else |
| { |
| Assert.IsTrue(region.GetLocalView().ContainsKey(key)); |
| region.GetLocalView().Invalidate(key); |
| } |
| } |
| try |
| { |
| value = region[key]; |
| } |
| catch (Client.KeyNotFoundException ) |
| { |
| Util.Log("KeyNotFoundException while getting key. should be ok as we are just testing auth"); |
| } |
| } |
| if (!isMultiuser && value != null) |
| { |
| if (CheckFlags(flags, OpFlags.CheckFail)) |
| { |
| Assert.AreNotEqual(expectedValue, value.ToString()); |
| } |
| else |
| { |
| Assert.AreEqual(expectedValue, value.ToString()); |
| } |
| } |
| break; |
| case OperationCode.Put: |
| region[key] = expectedValue; |
| break; |
| case OperationCode.Destroy: |
| if (!isMultiuser && !region.GetLocalView().ContainsKey(key)) |
| { |
| // Since DESTROY will fail unless the value is present |
| // in the local cache, this is a workaround for two cases: |
| // 1. When the operation is supposed to succeed then in |
| // the current AuthzCredentialGenerators the clients having |
| // DESTROY permission also has CREATE/UPDATE permission |
| // so that calling region.Put() will work for that case. |
| // 2. When the operation is supposed to fail with |
| // NotAuthorizedException then in the current |
| // AuthzCredentialGenerators the clients not |
| // having DESTROY permission are those with reader role that have |
| // GET permission. |
| // |
| // If either of these assumptions fails, then this has to be |
| // adjusted or reworked accordingly. |
| if (CheckFlags(flags, OpFlags.CheckNotAuthz)) |
| { |
| value = region[key]; |
| Assert.AreEqual(expectedValue, value.ToString()); |
| } |
| else |
| { |
| region[key] = expectedValue; |
| } |
| } |
| if ( !isMultiuser && CheckFlags(flags, OpFlags.LocalOp)) |
| { |
| region.GetLocalView().Remove(key); //Destroyed replaced by Remove() API |
| } |
| else |
| { |
| region.Remove(key); //Destroyed replaced by Remove API |
| } |
| break; |
| //TODO: Need to fix Stack overflow exception.. |
| case OperationCode.RegisterInterest: |
| if (CheckFlags(flags, OpFlags.UseList)) |
| { |
| breakLoop = true; |
| // Register interest list in this case |
| List<CacheableKey> keyList = new List<CacheableKey>(numOps); |
| for (int keyNumIndex = 0; keyNumIndex < numOps; ++keyNumIndex) |
| { |
| int keyNum = indices[keyNumIndex]; |
| keyList.Add(KeyPrefix + keyNum); |
| } |
| region.GetSubscriptionService().RegisterKeys(keyList.ToArray()); |
| } |
| else if (CheckFlags(flags, OpFlags.UseRegex)) |
| { |
| breakLoop = true; |
| region.GetSubscriptionService().RegisterRegex(KeyPrefix + "[0-" + (numOps - 1) + ']'); |
| } |
| else if (CheckFlags(flags, OpFlags.UseAllKeys)) |
| { |
| breakLoop = true; |
| region.GetSubscriptionService().RegisterAllKeys(); |
| } |
| break; |
| //TODO: Need to fix Stack overflow exception.. |
| case OperationCode.UnregisterInterest: |
| if (CheckFlags(flags, OpFlags.UseList)) |
| { |
| breakLoop = true; |
| // Register interest list in this case |
| List<CacheableKey> keyList = new List<CacheableKey>(numOps); |
| for (int keyNumIndex = 0; keyNumIndex < numOps; ++keyNumIndex) |
| { |
| int keyNum = indices[keyNumIndex]; |
| keyList.Add(KeyPrefix + keyNum); |
| } |
| region.GetSubscriptionService().UnregisterKeys(keyList.ToArray()); |
| } |
| else if (CheckFlags(flags, OpFlags.UseRegex)) |
| { |
| breakLoop = true; |
| region.GetSubscriptionService().UnregisterRegex(KeyPrefix + "[0-" + (numOps - 1) + ']'); |
| } |
| else if (CheckFlags(flags, OpFlags.UseAllKeys)) |
| { |
| breakLoop = true; |
| region.GetSubscriptionService().UnregisterAllKeys(); |
| } |
| break; |
| case OperationCode.Query: |
| breakLoop = true; |
| ISelectResults<object> queryResults; |
| |
| if (!isMultiuser) |
| { |
| queryResults = (ResultSet<object>)region.Query<object>( |
| "SELECT DISTINCT * FROM " + region.FullPath); |
| } |
| else |
| { |
| queryResults = CacheHelper.getMultiuserCache(creds).GetQueryService().NewQuery<object>("SELECT DISTINCT * FROM " + region.FullPath).Execute(); |
| } |
| Assert.IsNotNull(queryResults); |
| if (!CheckFlags(flags, OpFlags.CheckFail)) |
| { |
| Assert.AreEqual(numOps, queryResults.Size); |
| } |
| |
| var querySet = new List<string>((int) queryResults.Size); |
| ResultSet<object> rs = queryResults as ResultSet<object>; |
| foreach ( object result in rs) |
| { |
| querySet.Add(result.ToString()); |
| } |
| for (int keyNumIndex = 0; keyNumIndex < numOps; ++keyNumIndex) |
| { |
| int keyNum = indices[keyNumIndex]; |
| string expectedVal = valPrefix + keyNumIndex; |
| if (CheckFlags(flags, OpFlags.CheckFail)) |
| { |
| Assert.IsFalse(querySet.Contains(expectedVal)); |
| } |
| else |
| { |
| Assert.IsTrue(querySet.Contains(expectedVal)); |
| } |
| } |
| break; |
| case OperationCode.RegionDestroy: |
| breakLoop = true; |
| if ( !isMultiuser && CheckFlags(flags, OpFlags.LocalOp)) |
| { |
| region.GetLocalView().DestroyRegion(); |
| } |
| else |
| { |
| region.DestroyRegion(); |
| } |
| break; |
| |
| case OperationCode.GetServerKeys: |
| breakLoop = true; |
| ICollection<object> serverKeys = region.Keys; |
| break; |
| |
| //TODO: Need to fix System.ArgumentOutOfRangeException: Index was out of range. Know issue with GetAll() |
| case OperationCode.GetAll: |
| //ICacheableKey[] keymap = new ICacheableKey[5]; |
| List<object> keymap = new List<object>(); |
| for (int i = 0; i < 5; i++) |
| { |
| keymap.Add(i); |
| //CacheableInt32 item = CacheableInt32.Create(i); |
| //Int32 item = i; |
| // NOTE: GetAll should operate right after PutAll |
| //keymap[i] = item; |
| } |
| Dictionary<Object, Object> entrymap = new Dictionary<Object, Object>(); |
| //CacheableHashMap entrymap = CacheableHashMap.Create(); |
| region.GetAll(keymap, entrymap, null, false); |
| if (entrymap.Count < 5) |
| { |
| Assert.Fail("DoOp: Got fewer entries for op " + op); |
| } |
| break; |
| case OperationCode.PutAll: |
| // NOTE: PutAll should operate right before GetAll |
| //CacheableHashMap entrymap2 = CacheableHashMap.Create(); |
| Dictionary<Object, Object> entrymap2 = new Dictionary<object, object>(); |
| for (int i = 0; i < 5; i++) |
| { |
| //CacheableInt32 item = CacheableInt32.Create(i); |
| Int32 item = i; |
| entrymap2.Add(item, item); |
| } |
| region.PutAll(entrymap2); |
| break; |
| case OperationCode.RemoveAll: |
| Dictionary<Object, Object> entrymap3 = new Dictionary<object, object>(); |
| for (int i = 0; i < 5; i++) |
| { |
| //CacheableInt32 item = CacheableInt32.Create(i); |
| Int32 item = i; |
| entrymap3.Add(item, item); |
| } |
| region.PutAll(entrymap3); |
| ICollection<object> keys = new LinkedList<object>(); |
| for (int i = 0; i < 5; i++) |
| { |
| Int32 item = i; |
| keys.Add(item); |
| } |
| region.RemoveAll(keys); |
| break; |
| case OperationCode.ExecuteCQ: |
| Pool/*<object, object>*/ pool = CacheHelper.DCache.GetPoolManager().Find("__TESTPOOL1_"); |
| QueryService qs; |
| if (pool != null) |
| { |
| qs = pool.GetQueryService(); |
| } |
| else |
| { |
| //qs = CacheHelper.DCache.GetQueryService(); |
| qs = null; |
| |
| } |
| CqAttributesFactory<object, object> cqattrsfact = new CqAttributesFactory<object, object>(); |
| CqAttributes<object, object> cqattrs = cqattrsfact.Create(); |
| CqQuery<object, object> cq = qs.NewCq("cq_security", "SELECT * FROM /" + region.Name, cqattrs, false); |
| qs.ExecuteCqs(); |
| qs.StopCqs(); |
| qs.CloseCqs(); |
| break; |
| |
| case OperationCode.ExecuteFunction: |
| if (!isMultiuser) |
| { |
| Pool/*<object, object>*/ pool2 = CacheHelper.DCache.GetPoolManager().Find("__TESTPOOL1_"); |
| if (pool2 != null) |
| { |
| Client.FunctionService<object>.OnServer(pool2).Execute("securityTest"); |
| Client.FunctionService<object>.OnRegion<object, object>(region).Execute("FireNForget"); |
| } |
| else |
| { |
| expectedResult = ExpectedResult.Success; |
| } |
| } |
| else |
| { |
| //FunctionService fs = CacheHelper.getMultiuserCache(creds).GetFunctionService(); |
| //Execution exe = fs.OnServer(); |
| IRegionService userCache = CacheHelper.getMultiuserCache(creds); |
| Apache.Geode.Client.Execution<object> exe = Client.FunctionService<object>.OnServer(userCache); |
| exe.Execute("securityTest"); |
| exe = Client.FunctionService<object>.OnServers(userCache); |
| Client.FunctionService<object>.OnRegion<object, object>(region); |
| Client.FunctionService<object>.OnRegion<object, object>(userCache.GetRegion<object, object>(region.Name)).Execute("FireNForget"); |
| } |
| break; |
| default: |
| Assert.Fail("DoOp: Unhandled operation " + op); |
| break; |
| } |
| |
| if (expectedResult != ExpectedResult.Success) |
| { |
| Assert.Fail("Expected an exception while performing operation"); |
| } |
| } |
| catch (AssertionException ex) |
| { |
| Util.Log("DoOp: failed assertion: {0}", ex); |
| throw; |
| } |
| catch (NotAuthorizedException ex) |
| { |
| exceptionOccured = true; |
| if (expectedResult == ExpectedResult.NotAuthorizedException) |
| { |
| Util.Log( |
| "DoOp: Got expected NotAuthorizedException when doing operation [" |
| + op + "] with flags [" + flags + "]: " + ex.Message); |
| continue; |
| } |
| else |
| { |
| Assert.Fail("DoOp: Got unexpected NotAuthorizedException when " + |
| "doing operation: " + ex.Message); |
| } |
| } |
| catch (Exception ex) |
| { |
| exceptionOccured = true; |
| if (expectedResult == ExpectedResult.OtherException) |
| { |
| Util.Log("DoOp: Got expected exception when doing operation: " + |
| ex.GetType() + "::" + ex.Message); |
| continue; |
| } |
| else |
| { |
| Assert.Fail("DoOp: Got unexpected exception when doing operation: " + ex); |
| } |
| } |
| } |
| |
| if (!exceptionOccured |
| && expectedResult != ExpectedResult.Success) |
| { |
| Assert.Fail("Expected an exception while performing operation"); |
| } |
| Util.Log(" doop done"); |
| } |
| |
| protected void ExecuteOpBlock(List<OperationWithAction> opBlock, |
| string authInit, Properties<string, string> extraAuthProps, Properties<string, string> extraAuthzProps, |
| TestCredentialGenerator gen, Random rnd, bool isMultiuser, bool ssl,bool withPassword) |
| { |
| foreach (OperationWithAction currentOp in opBlock) |
| { |
| // Start client with valid credentials as specified in |
| // OperationWithAction |
| OperationCode opCode = currentOp.OpCode; |
| OpFlags opFlags = currentOp.Flags; |
| int clientNum = currentOp.ClientNum; |
| if (clientNum > m_clients.Length) |
| { |
| Assert.Fail("ExecuteOpBlock: Unknown client number " + clientNum); |
| } |
| ClientBase client = m_clients[clientNum - 1]; |
| Util.Log("ExecuteOpBlock: performing operation number [" + |
| currentOp.OpNum + "]: " + currentOp); |
| Properties<string, string> clientProps = null; |
| if (!CheckFlags(opFlags, OpFlags.UseOldConn)) |
| { |
| Properties<string, string> opCredentials; |
| int newRnd = rnd.Next(100) + 1; |
| string currentRegionName = '/' + RegionName; |
| if (CheckFlags(opFlags, OpFlags.UseSubRegion)) |
| { |
| currentRegionName += ('/' + SubregionName); |
| } |
| string credentialsTypeStr; |
| OperationCode authOpCode = currentOp.AuthzOperationCode; |
| int[] indices = currentOp.Indices; |
| CredentialGenerator cGen = gen.GetCredentialGenerator(); |
| Properties<string, string> javaProps = null; |
| if (CheckFlags(opFlags, OpFlags.CheckNotAuthz) || |
| CheckFlags(opFlags, OpFlags.UseNotAuthz)) |
| { |
| opCredentials = gen.GetDisallowedCredentials( |
| new OperationCode[] { authOpCode }, |
| new string[] { currentRegionName }, indices, newRnd); |
| credentialsTypeStr = " unauthorized " + authOpCode; |
| } |
| else |
| { |
| opCredentials = gen.GetAllowedCredentials(new OperationCode[] { |
| opCode, authOpCode }, new string[] { currentRegionName }, |
| indices, newRnd); |
| credentialsTypeStr = " authorized " + authOpCode; |
| } |
| if (cGen != null) |
| { |
| javaProps = cGen.JavaProperties; |
| } |
| clientProps = SecurityTestUtil.ConcatProperties( |
| opCredentials, extraAuthProps, extraAuthzProps); |
| // Start the client with valid credentials but allowed or disallowed to |
| // perform an operation |
| Util.Log("ExecuteOpBlock: For client" + clientNum + |
| credentialsTypeStr + " credentials: " + opCredentials); |
| |
| if(!isMultiuser) |
| client.Call(SecurityTestUtil.CreateClientSSL, RegionName, |
| CacheHelper.Locators, authInit, clientProps, ssl, withPassword); |
| else |
| client.Call(SecurityTestUtil.CreateClientMU, RegionName, |
| CacheHelper.Locators, authInit, (Properties<string, string>)null, true); |
| } |
| ExpectedResult expectedResult; |
| if (CheckFlags(opFlags, OpFlags.CheckNotAuthz)) |
| { |
| expectedResult = ExpectedResult.NotAuthorizedException; |
| } |
| else if (CheckFlags(opFlags, OpFlags.CheckException)) |
| { |
| expectedResult = ExpectedResult.OtherException; |
| } |
| else |
| { |
| expectedResult = ExpectedResult.Success; |
| } |
| |
| // Perform the operation from selected client |
| if (!isMultiuser) |
| client.Call(DoOp, opCode, currentOp.Indices, opFlags, expectedResult); |
| else |
| client.Call(DoOp, opCode, currentOp.Indices, opFlags, expectedResult, clientProps, true); |
| } |
| } |
| |
| protected List<AuthzCredentialGenerator> GetAllGeneratorCombos(bool isMultiUser) |
| { |
| List<AuthzCredentialGenerator> generators = |
| new List<AuthzCredentialGenerator>(); |
| foreach (AuthzCredentialGenerator.ClassCode authzClassCode in |
| Enum.GetValues(typeof(AuthzCredentialGenerator.ClassCode))) |
| { |
| List<CredentialGenerator> cGenerators = |
| SecurityTestUtil.getAllGenerators(isMultiUser); |
| foreach (CredentialGenerator cGen in cGenerators) |
| { |
| AuthzCredentialGenerator authzGen = AuthzCredentialGenerator |
| .Create(authzClassCode); |
| if (authzGen != null) |
| { |
| if (authzGen.Init(cGen)) |
| { |
| generators.Add(authzGen); |
| } |
| } |
| } |
| } |
| return generators; |
| } |
| |
| protected void RunOpsWithFailoverSSL(OperationWithAction[] opCodes, |
| string testName, bool withPassword) |
| { |
| RunOpsWithFailover(opCodes, testName, false, true,withPassword); |
| } |
| |
| protected void RunOpsWithFailover(OperationWithAction[] opCodes, |
| string testName) |
| { |
| RunOpsWithFailover(opCodes, testName, false); |
| } |
| |
| protected void RunOpsWithFailover(OperationWithAction[] opCodes, |
| string testName, bool isMultiUser) |
| { |
| RunOpsWithFailover(opCodes, testName, isMultiUser, false, false); |
| } |
| |
| protected void RunOpsWithFailover(OperationWithAction[] opCodes, |
| string testName, bool isMultiUser, bool ssl, bool withPassword) |
| { |
| CacheHelper.SetupJavaServers(true, CacheXml1, CacheXml2); |
| CacheHelper.StartJavaLocator(1, "GFELOC", null, ssl); |
| Util.Log("Locator started"); |
| |
| foreach (AuthzCredentialGenerator authzGen in GetAllGeneratorCombos(isMultiUser)) |
| { |
| CredentialGenerator cGen = authzGen.GetCredentialGenerator(); |
| Properties<string, string> extraAuthProps = cGen.SystemProperties; |
| Properties<string, string> javaProps = cGen.JavaProperties; |
| Properties<string, string> extraAuthzProps = authzGen.SystemProperties; |
| string authenticator = cGen.Authenticator; |
| string authInit = cGen.AuthInit; |
| string accessor = authzGen.AccessControl; |
| TestAuthzCredentialGenerator tgen = new TestAuthzCredentialGenerator(authzGen); |
| |
| Util.Log(testName + ": Using authinit: " + authInit); |
| Util.Log(testName + ": Using authenticator: " + authenticator); |
| Util.Log(testName + ": Using accessor: " + accessor); |
| |
| // Start servers with all required properties |
| string serverArgs = SecurityTestUtil.GetServerArgs(authenticator, |
| accessor, null, SecurityTestUtil.ConcatProperties(extraAuthProps, |
| extraAuthzProps), javaProps); |
| |
| // Perform all the ops on the clients |
| List<OperationWithAction> opBlock = new List<OperationWithAction>(); |
| Random rnd = new Random(); |
| for (int opNum = 0; opNum < opCodes.Length; ++opNum) |
| { |
| // Start client with valid credentials as specified in |
| // OperationWithAction |
| OperationWithAction currentOp = opCodes[opNum]; |
| if (currentOp == OperationWithAction.OpBlockEnd || |
| currentOp == OperationWithAction.OpBlockNoFailover) |
| { |
| // End of current operation block; execute all the operations |
| // on the servers with/without failover |
| if (opBlock.Count > 0) |
| { |
| // Start the first server and execute the operation block |
| CacheHelper.StartJavaServerWithLocators(1, "GFECS1", 1, serverArgs, ssl); |
| Util.Log("Cacheserver 1 started."); |
| CacheHelper.StopJavaServer(2, false); |
| ExecuteOpBlock(opBlock, authInit, extraAuthProps, |
| extraAuthzProps, tgen, rnd, isMultiUser, ssl, withPassword); |
| if (currentOp == OperationWithAction.OpBlockNoFailover) |
| { |
| CacheHelper.StopJavaServer(1); |
| } |
| else |
| { |
| // Failover to the second server and run the block again |
| CacheHelper.StartJavaServerWithLocators(2, "GFECS2", 1, serverArgs, ssl); |
| Util.Log("Cacheserver 2 started."); |
| CacheHelper.StopJavaServer(1); |
| ExecuteOpBlock(opBlock, authInit, extraAuthProps, |
| extraAuthzProps, tgen, rnd, isMultiUser, ssl, withPassword); |
| } |
| opBlock.Clear(); |
| } |
| } |
| else |
| { |
| currentOp.OpNum = opNum; |
| opBlock.Add(currentOp); |
| } |
| } |
| // Close all clients here since we run multiple iterations for pool and non pool configs |
| foreach (ClientBase client in m_clients) |
| { |
| client.Call(Close); |
| } |
| } |
| CacheHelper.StopJavaLocator(1, true, ssl); |
| CacheHelper.ClearEndpoints(); |
| CacheHelper.ClearLocators(); |
| } |
| |
| #endregion |
| |
| /// <summary> |
| /// This class specifies flags that can be used to alter the behaviour of |
| /// operations being performed by the <see cref="DoOp"/> method. |
| /// </summary> |
| [Flags] |
| public enum OpFlags |
| { |
| /// <summary> |
| /// Default behaviour. |
| /// </summary> |
| None = 0x0, |
| |
| /// <summary> |
| /// Check that the operation should fail. |
| /// </summary> |
| CheckFail = 0x1, |
| |
| /// <summary> |
| /// Check that the operation should throw <c>NotAuthorizedException</c>. |
| /// </summary> |
| CheckNotAuthz = 0x2, |
| |
| /// <summary> |
| /// Do the connection with unauthorized credentials but do not check that the |
| /// operation throws <c>NotAuthorizedException</c>. |
| /// </summary> |
| UseNotAuthz = 0x4, |
| |
| /// <summary> |
| /// Check that the region should not be available. |
| /// </summary> |
| CheckNoRegion = 0x8, |
| |
| /// <summary> |
| /// Check that the operation should throw an exception other than the |
| /// <c>NotAuthorizedException</c>. |
| /// </summary> |
| CheckException = 0x10, |
| |
| /// <summary> |
| /// Check for values starting with <c>NValuePrefix</c> instead of |
| /// <c>ValuePrefix</c>. |
| /// </summary> |
| UseNewVal = 0x20, |
| |
| /// <summary> |
| /// Register a regular expression. |
| /// </summary> |
| UseRegex = 0x40, |
| |
| /// <summary> |
| /// Register a list of keys. |
| /// </summary> |
| UseList = 0x80, |
| |
| /// <summary> |
| /// Register all keys. |
| /// </summary> |
| UseAllKeys = 0x100, |
| |
| /// <summary> |
| /// Perform the local version of the operation (if applicable). |
| /// </summary> |
| LocalOp = 0x200, |
| |
| /// <summary> |
| /// Check that the key for the operation should not be present. |
| /// </summary> |
| CheckNoKey = 0x400, |
| |
| /// <summary> |
| /// Use the sub-region for performing the operation. |
| /// </summary> |
| UseSubRegion = 0x800, |
| |
| /// <summary> |
| /// Do not try to create the sub-region. |
| /// </summary> |
| NoCreateSubRegion = 0x1000, |
| |
| /// <summary> |
| /// Do not re-connect using new credentials rather use the previous |
| /// connection. |
| /// </summary> |
| UseOldConn = 0x2000, |
| } |
| |
| /// <summary> |
| /// This class encapsulates an <see cref="OperationCode"/> with associated flags, the |
| /// client to perform the operation, and the number of operations to perform. |
| /// </summary> |
| public class OperationWithAction |
| { |
| /// <summary> |
| /// The operation to be performed. |
| /// </summary> |
| private OperationCode m_opCode; |
| |
| /// <summary> |
| /// The operation for which authorized or unauthorized credentials have to be |
| /// generated. This is the same as {@link #opCode} when not specified. |
| /// </summary> |
| private OperationCode m_authzOpCode; |
| |
| /// <summary> |
| /// The client number on which the operation has to be performed. |
| /// </summary> |
| private int m_clientNum; |
| |
| /// <summary> |
| /// Bitwise or'd <see cref="OpFlags"/> to change/specify the behaviour of |
| /// the operations. |
| /// </summary> |
| private OpFlags m_flags; |
| |
| /// <summary> |
| /// Indices of the keys array to be used for operations. The keys used |
| /// will be concatenation of <c>KeyPrefix</c> and <c>index</c> integer. |
| /// </summary> |
| private int[] m_indices; |
| |
| /// <summary> |
| /// An index for the operation used for logging. |
| /// </summary> |
| private int m_opNum; |
| |
| /// <summary> |
| /// Indicates end of an operation block which can be used for testing with |
| /// failover. |
| /// </summary> |
| public static readonly OperationWithAction OpBlockEnd = new OperationWithAction( |
| OperationCode.Get, 4); |
| |
| /// <summary> |
| /// Indicates end of an operation block which should not be used for testing |
| /// with failover. |
| /// </summary> |
| public static readonly OperationWithAction OpBlockNoFailover = |
| new OperationWithAction(OperationCode.Get, 5); |
| |
| private void SetIndices(int numOps) |
| { |
| this.m_indices = new int[numOps]; |
| for (int index = 0; index < numOps; ++index) |
| { |
| this.m_indices[index] = index; |
| } |
| } |
| |
| public OperationWithAction(OperationCode opCode) |
| { |
| this.m_opCode = opCode; |
| this.m_authzOpCode = opCode; |
| this.m_clientNum = 1; |
| this.m_flags = OpFlags.None; |
| SetIndices(4); |
| this.m_opNum = 0; |
| } |
| |
| public OperationWithAction(OperationCode opCode, int clientNum) |
| { |
| this.m_opCode = opCode; |
| this.m_authzOpCode = opCode; |
| this.m_clientNum = clientNum; |
| this.m_flags = OpFlags.None; |
| SetIndices(4); |
| this.m_opNum = 0; |
| } |
| |
| public OperationWithAction(OperationCode opCode, int clientNum, OpFlags flags, |
| int numOps) |
| { |
| this.m_opCode = opCode; |
| this.m_authzOpCode = opCode; |
| this.m_clientNum = clientNum; |
| this.m_flags = flags; |
| SetIndices(numOps); |
| this.m_opNum = 0; |
| } |
| |
| public OperationWithAction(OperationCode opCode, |
| OperationCode deniedOpCode, int clientNum, OpFlags flags, int numOps) |
| { |
| this.m_opCode = opCode; |
| this.m_authzOpCode = deniedOpCode; |
| this.m_clientNum = clientNum; |
| this.m_flags = flags; |
| SetIndices(numOps); |
| this.m_opNum = 0; |
| } |
| |
| public OperationWithAction(OperationCode opCode, int clientNum, |
| OpFlags flags, int[] indices) |
| { |
| this.m_opCode = opCode; |
| this.m_authzOpCode = opCode; |
| this.m_clientNum = clientNum; |
| this.m_flags = flags; |
| this.m_indices = indices; |
| this.m_opNum = 0; |
| } |
| |
| public OperationWithAction(OperationCode opCode, OperationCode authzOpCode, |
| int clientNum, OpFlags flags, int[] indices) |
| { |
| this.m_opCode = opCode; |
| this.m_authzOpCode = authzOpCode; |
| this.m_clientNum = clientNum; |
| this.m_flags = flags; |
| this.m_indices = indices; |
| this.m_opNum = 0; |
| } |
| |
| public OperationCode OpCode |
| { |
| get |
| { |
| return this.m_opCode; |
| } |
| } |
| |
| public OperationCode AuthzOperationCode |
| { |
| get |
| { |
| return this.m_authzOpCode; |
| } |
| } |
| |
| public int ClientNum |
| { |
| get |
| { |
| return this.m_clientNum; |
| } |
| } |
| |
| public OpFlags Flags |
| { |
| get |
| { |
| return this.m_flags; |
| } |
| } |
| |
| public int[] Indices |
| { |
| get |
| { |
| return this.m_indices; |
| } |
| } |
| |
| public int OpNum |
| { |
| get |
| { |
| return this.m_opNum; |
| } |
| set |
| { |
| this.m_opNum = value; |
| } |
| } |
| |
| public override string ToString() |
| { |
| return "opCode:" + this.m_opCode + ",authOpCode:" + this.m_authzOpCode |
| + ",clientNum:" + this.m_clientNum + ",flags:" + this.m_flags |
| + ",numOps:" + this.m_indices.Length + ",indices:" |
| + IndicesToString(this.m_indices); |
| } |
| } |
| |
| /// <summary> |
| /// Simple interface to generate credentials with authorization based on key |
| /// indices also. This is utilized by the post-operation authorization tests |
| /// <c>ThinClientAuthzObjectModTests</c> where authorization depends on |
| /// the actual keys being used for the operation. |
| /// </summary> |
| public interface TestCredentialGenerator |
| { |
| /// <summary> |
| /// Get allowed credentials for the given set of operations in the given |
| /// regions and indices of keys. |
| /// </summary> |
| Properties<string, string> GetAllowedCredentials(OperationCode[] opCodes, |
| string[] regionNames, int[] keyIndices, int num); |
| |
| /// <summary> |
| /// Get disallowed credentials for the given set of operations in the given |
| /// regions and indices of keys. |
| /// </summary> |
| Properties<string, string> GetDisallowedCredentials(OperationCode[] opCodes, |
| string[] regionNames, int[] keyIndices, int num); |
| |
| /// <summary> |
| /// Get the <see cref="CredentialGenerator"/> if any. |
| /// </summary> |
| /// <returns></returns> |
| CredentialGenerator GetCredentialGenerator(); |
| } |
| |
| /// <summary> |
| /// Contains a <c>AuthzCredentialGenerator</c> and implements the |
| /// <c>TestCredentialGenerator</c> interface. |
| /// </summary> |
| protected class TestAuthzCredentialGenerator : TestCredentialGenerator |
| { |
| private AuthzCredentialGenerator authzGen; |
| |
| public TestAuthzCredentialGenerator(AuthzCredentialGenerator authzGen) |
| { |
| this.authzGen = authzGen; |
| } |
| |
| public Properties<string, string> GetAllowedCredentials(OperationCode[] opCodes, |
| string[] regionNames, int[] keyIndices, int num) |
| { |
| |
| return this.authzGen.GetAllowedCredentials(opCodes, regionNames, num); |
| } |
| |
| public Properties<string, string> GetDisallowedCredentials(OperationCode[] opCodes, |
| string[] regionNames, int[] keyIndices, int num) |
| { |
| |
| return this.authzGen.GetDisallowedCredentials(opCodes, regionNames, num); |
| } |
| |
| public CredentialGenerator GetCredentialGenerator() |
| { |
| |
| return authzGen.GetCredentialGenerator(); |
| } |
| } |
| } |
| } |