PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/sdk/test/CrossPlatformTests/CommonTests/IntegrationTests/DynamoDB/DynamoDBTestsBase.cs

https://gitlab.com/CORP-RESELLER/aws-sdk-net
C# | 340 lines | 280 code | 43 blank | 17 comment | 23 complexity | c1f988c8e65bc38a0fc8aedca8eb2eff MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Amazon.DynamoDBv2;
  5. using Amazon.DynamoDBv2.Model;
  6. using Amazon;
  7. using Amazon.DynamoDBv2.DataModel;
  8. using Amazon.DynamoDBv2.DocumentModel;
  9. using Amazon.Runtime;
  10. using Amazon.Runtime.Internal.Util;
  11. using CommonTests.Framework;
  12. using NUnit.Framework;
  13. using System.Threading.Tasks;
  14. namespace CommonTests.IntegrationTests.DynamoDB
  15. {
  16. [TestFixture]
  17. public partial class DynamoDBTests : TestBase<AmazonDynamoDBClient>
  18. {
  19. public static string TableCacheIdentifier = typeof(Table).FullName;
  20. private ICache<string, TableDescription> _tableCache = null;
  21. public ICache<string, TableDescription> TableCache
  22. {
  23. get
  24. {
  25. if (_tableCache == null)
  26. _tableCache = SdkCache.GetCache<string, TableDescription>(
  27. Client, TableCacheIdentifier, StringComparer.Ordinal);
  28. return _tableCache;
  29. }
  30. }
  31. [OneTimeSetUp]
  32. public void ClassInitialize()
  33. {
  34. ConfigureContext();
  35. RunAsSync(async () =>
  36. {
  37. await CreateTestTables();
  38. Client.BeforeRequestEvent += ClientBeforeRequestEvent;
  39. // Since tables have a variable prefix, configure the prefix for the process
  40. AWSConfigsDynamoDB.Context.TableNamePrefix = TableNamePrefix;
  41. // Construct single context object to use for all operations
  42. CreateContext(DynamoDBEntryConversion.V1);
  43. });
  44. }
  45. [OneTimeTearDown]
  46. public void ClassCleanup()
  47. {
  48. #pragma warning disable 162
  49. if (!ReuseTables)
  50. RemoveCreatedTables();
  51. #pragma warning restore 162
  52. //BaseClean();
  53. if (Context != null)
  54. Context.Dispose();
  55. Client.BeforeRequestEvent -= ClientBeforeRequestEvent;
  56. }
  57. private void ClientBeforeRequestEvent(object sender, Amazon.Runtime.RequestEventArgs e)
  58. {
  59. var client = sender as AmazonServiceClient;
  60. if (client == null)
  61. throw new InvalidOperationException();
  62. var wsrea = e as WebServiceRequestEventArgs;
  63. if (wsrea == null)
  64. throw new InvalidOperationException();
  65. var request = wsrea.Request;
  66. var describeTableRequest = request as DescribeTableRequest;
  67. if (describeTableRequest != null)
  68. {
  69. var keys = TableCache.Keys;
  70. if (keys.Contains(describeTableRequest.TableName))
  71. Assert.Fail("Attempting to describe table that has already been described");
  72. }
  73. }
  74. [TearDown]
  75. public void CleanupTables()
  76. {
  77. RunAsSync(async () =>
  78. {
  79. await ClearTable(hashTableName);
  80. await ClearTable(hashRangeTableName);
  81. });
  82. }
  83. public void CreateContext(DynamoDBEntryConversion conversion)
  84. {
  85. var config = new DynamoDBContextConfig
  86. {
  87. //IgnoreNullValues = true
  88. Conversion = conversion
  89. };
  90. Context = new DynamoDBContext(Client, config);
  91. }
  92. public static string hashTableName;
  93. public static string hashRangeTableName;
  94. public static DynamoDBContext Context = null;
  95. public static int OneMB = 1024 * 1024;
  96. public static int MaxItemSize = 65 * 1024;
  97. public static int MaxBatchSize = 25;
  98. /// <summary>
  99. /// Setting this value to true will configure the tests to not
  100. /// delete the tables after the test has finished.
  101. /// </summary>
  102. public const bool ReuseTables = true;
  103. public const int DefaultReadCapacity = 50;
  104. public const int DefaultWriteCapacity = 50;
  105. public const int ScanLimit = 1;
  106. public static readonly string BaseTableNamePrefix = "DotNetTests";
  107. #pragma warning disable 429
  108. public static readonly string TableNamePrefix =
  109. BaseTableNamePrefix + "-" +
  110. (ReuseTables ? string.Empty : +DateTime.Now.ToFileTime() + "-");
  111. #pragma warning restore 429
  112. public static List<string> CreatedTables = new List<string>();
  113. public async Task ClearTable(string tableName)
  114. {
  115. var table = Table.LoadTable(Client, tableName, DynamoDBEntryConversion.V1);
  116. var keyNames = table.Keys.Keys.ToList();
  117. // Retrieve all keys
  118. var keys = await table.Scan(new ScanOperationConfig
  119. {
  120. AttributesToGet = keyNames,
  121. Select = SelectValues.SpecificAttributes
  122. }).GetRemainingAsync();
  123. // Populate BatchWrite to delete all keys
  124. var batchWrite = table.CreateBatchWrite();
  125. foreach (var key in keys)
  126. batchWrite.AddKeyToDelete(key);
  127. // Execute batch write
  128. await batchWrite.ExecuteAsync();
  129. }
  130. public async Task CreateTestTables()
  131. {
  132. hashTableName = TableNamePrefix + "HashTable";
  133. hashRangeTableName = TableNamePrefix + "HashRangeTable";
  134. bool createHashTable = true;
  135. bool createHashRangeTable = true;
  136. if (ReuseTables)
  137. {
  138. if (await GetStatus(Client, hashTableName) != null)
  139. {
  140. WaitForTableStatus(Client, hashTableName, TableStatus.ACTIVE);
  141. createHashTable = false;
  142. }
  143. if (await GetStatus(Client, hashRangeTableName) != null)
  144. {
  145. WaitForTableStatus(Client, hashRangeTableName, TableStatus.ACTIVE);
  146. createHashRangeTable = false;
  147. }
  148. }
  149. if (createHashTable)
  150. {
  151. // Create hash-key table with global index
  152. await Client.CreateTableAsync(new CreateTableRequest
  153. {
  154. TableName = hashTableName,
  155. AttributeDefinitions = new List<AttributeDefinition>
  156. {
  157. new AttributeDefinition { AttributeName = "Id", AttributeType = ScalarAttributeType.N },
  158. new AttributeDefinition { AttributeName = "Company", AttributeType = ScalarAttributeType.S },
  159. new AttributeDefinition { AttributeName = "Price", AttributeType = ScalarAttributeType.N }
  160. },
  161. KeySchema = new List<KeySchemaElement>
  162. {
  163. new KeySchemaElement { KeyType = KeyType.HASH, AttributeName = "Id" }
  164. },
  165. GlobalSecondaryIndexes = new List<GlobalSecondaryIndex>
  166. {
  167. new GlobalSecondaryIndex
  168. {
  169. IndexName = "GlobalIndex",
  170. KeySchema = new List<KeySchemaElement>
  171. {
  172. new KeySchemaElement { AttributeName = "Company", KeyType = KeyType.HASH },
  173. new KeySchemaElement { AttributeName = "Price", KeyType = KeyType.RANGE }
  174. },
  175. ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 },
  176. Projection = new Projection { ProjectionType = ProjectionType.ALL }
  177. }
  178. },
  179. ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = DefaultReadCapacity, WriteCapacityUnits = DefaultWriteCapacity },
  180. });
  181. CreatedTables.Add(hashTableName);
  182. // Wait for table to be ready
  183. WaitForTableStatus(Client, hashTableName, TableStatus.ACTIVE);
  184. }
  185. if (createHashRangeTable)
  186. {
  187. // Create hash-and-range-key table with local and global indexes
  188. await Client.CreateTableAsync(new CreateTableRequest
  189. {
  190. TableName = hashRangeTableName,
  191. AttributeDefinitions = new List<AttributeDefinition>
  192. {
  193. new AttributeDefinition { AttributeName = "Name", AttributeType = ScalarAttributeType.S },
  194. new AttributeDefinition { AttributeName = "Age", AttributeType = ScalarAttributeType.N },
  195. new AttributeDefinition { AttributeName = "Company", AttributeType = ScalarAttributeType.S },
  196. new AttributeDefinition { AttributeName = "Score", AttributeType = ScalarAttributeType.N },
  197. new AttributeDefinition { AttributeName = "Manager", AttributeType = ScalarAttributeType.S }
  198. },
  199. KeySchema = new List<KeySchemaElement>
  200. {
  201. new KeySchemaElement { AttributeName = "Name", KeyType = KeyType.HASH },
  202. new KeySchemaElement { AttributeName = "Age", KeyType = KeyType.RANGE }
  203. },
  204. GlobalSecondaryIndexes = new List<GlobalSecondaryIndex>
  205. {
  206. new GlobalSecondaryIndex
  207. {
  208. IndexName = "GlobalIndex",
  209. KeySchema = new List<KeySchemaElement>
  210. {
  211. new KeySchemaElement { AttributeName = "Company", KeyType = KeyType.HASH },
  212. new KeySchemaElement { AttributeName = "Score", KeyType = KeyType.RANGE }
  213. },
  214. ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 },
  215. Projection = new Projection { ProjectionType = ProjectionType.ALL }
  216. }
  217. },
  218. LocalSecondaryIndexes = new List<LocalSecondaryIndex>
  219. {
  220. new LocalSecondaryIndex
  221. {
  222. IndexName = "LocalIndex",
  223. KeySchema = new List<KeySchemaElement>
  224. {
  225. new KeySchemaElement { AttributeName = "Name", KeyType = KeyType.HASH },
  226. new KeySchemaElement { AttributeName = "Manager", KeyType = KeyType.RANGE }
  227. },
  228. Projection = new Projection
  229. {
  230. ProjectionType = ProjectionType.INCLUDE,
  231. NonKeyAttributes = new List<string> { "Company", "Score" }
  232. }
  233. }
  234. },
  235. ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = DefaultReadCapacity, WriteCapacityUnits = DefaultWriteCapacity },
  236. });
  237. CreatedTables.Add(hashRangeTableName);
  238. // Wait for table to be ready
  239. WaitForTableStatus(Client, hashRangeTableName, TableStatus.ACTIVE);
  240. }
  241. }
  242. public void RemoveCreatedTables()
  243. {
  244. if (CreatedTables.Count > 0)
  245. {
  246. // Wait for all tables to be active first
  247. WaitForTableStatus(Client, CreatedTables, TableStatus.ACTIVE);
  248. foreach (var table in CreatedTables)
  249. {
  250. Client.DeleteTableAsync(table);
  251. }
  252. // Wait for tables to be deleted
  253. WaitForTableStatus(Client, CreatedTables, null);
  254. CreatedTables.Clear();
  255. }
  256. }
  257. public static void WaitForTableStatus(IAmazonDynamoDB client, string tableName, TableStatus status)
  258. {
  259. WaitForTableStatus(client, new string[] { tableName }, status);
  260. }
  261. public static void WaitForTableStatus(IAmazonDynamoDB client, IEnumerable<string> tableNames, TableStatus status)
  262. {
  263. Console.WriteLine("Waiting for tables [{0}] to reach status {1}",
  264. string.Join(", ", tableNames.ToArray()), status);
  265. var tablesList = new List<string>(tableNames);
  266. Func<bool> testFunction = () =>
  267. {
  268. bool allReady = true;
  269. foreach(var tableName in tablesList.ToArray())
  270. {
  271. var tableStatus = GetStatus(client, tableName).Result;
  272. allReady &= (tableStatus == status);
  273. if (allReady)
  274. tablesList.Remove(tableName);
  275. if (!allReady)
  276. break;
  277. }
  278. return allReady;
  279. };
  280. UtilityMethods.WaitUntil(testFunction);
  281. Console.WriteLine("All tables ready");
  282. }
  283. public static async Task<TableStatus> GetStatus(IAmazonDynamoDB client, string tableName)
  284. {
  285. TableStatus status = null;
  286. try
  287. {
  288. status = (await client.DescribeTableAsync(tableName)).Table.TableStatus;
  289. }
  290. catch(ResourceNotFoundException)
  291. {
  292. status = null;
  293. }
  294. return status;
  295. }
  296. }
  297. }