PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Sources/CsvReader.Azure.Tests/Tests.cs

https://github.com/tpwalke2/DataTable
C# | 337 lines | 238 code | 74 blank | 25 comment | 4 complexity | dcd2f826811fc5968374bf14ed30bd67 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Xunit;
  6. using Microsoft.WindowsAzure;
  7. using DataAccess;
  8. using Microsoft.WindowsAzure.StorageClient;
  9. using System.IO;
  10. using System.Diagnostics;
  11. namespace CsvReader.Azure.Tests
  12. {
  13. public class Tests
  14. {
  15. static private CloudStorageAccount GetStorage()
  16. {
  17. return CloudStorageAccount.DevelopmentStorageAccount;
  18. }
  19. [Fact]
  20. public void DownloadNonExistentBlob()
  21. {
  22. var account = GetStorage();
  23. var client = account.CreateCloudBlobClient();
  24. string containerName = "csvtestcontainer";
  25. string blobName = "csvtestblobnoexist";
  26. // Test when container doesn't exist.
  27. DeleteContainer(account, containerName);
  28. Assert.Throws<FileNotFoundException>(() => DataTable.New.ReadAzureBlob(account, containerName, blobName));
  29. // Container exists, blob name doesn't.
  30. CloudBlobContainer container = client.GetContainerReference(containerName);
  31. container.CreateIfNotExist();
  32. Assert.Throws<FileNotFoundException>(() => DataTable.New.ReadAzureBlob(account, containerName, blobName));
  33. }
  34. [Fact]
  35. public void UploadUnsupportedTypeFails()
  36. {
  37. // Save a table to azure, and then use traditional techniques to query it back.
  38. var account = GetStorage();
  39. var source = from x in Enumerable.Range(1, 10) select new { N = x, N2 = x * x };
  40. DataTable dtSource = DataTable.New.FromEnumerable(source);
  41. Assert.Throws<InvalidOperationException>(() => dtSource.SaveToAzureTable(account, "table", new Type[] { typeof(object), typeof(object) }));
  42. }
  43. [Fact]
  44. public void UploadCsvToBlob()
  45. {
  46. // Save a table to azure, and then use traditional techniques to query it back.
  47. var account = GetStorage();
  48. var client = account.CreateCloudBlobClient();
  49. var source = from x in Enumerable.Range(1, 10) select new { N = x, N2 = x * x };
  50. DataTable dtSource = DataTable.New.FromEnumerable(source);
  51. string originalContent = TableToString(dtSource);
  52. string containerName = "csvtestcontainer";
  53. string blobName = "csvtestblob";
  54. // Will create container if it doesn't exist. So delete
  55. DeleteContainer(account, containerName);
  56. dtSource.SaveToAzureBlob(account, containerName, blobName);
  57. // Verify existence.
  58. {
  59. CloudBlobContainer container = client.GetContainerReference(containerName);
  60. CloudBlob blob = container.GetBlobReference(blobName);
  61. string contents = blob.DownloadText();
  62. Assert.Equal(originalContent, contents);
  63. }
  64. // Now download with helpers.
  65. DataTable dtDownload = DataTable.New.ReadAzureBlob(account, containerName, blobName);
  66. string downloadContent = TableToString(dtDownload);
  67. Assert.Equal(containerName + "." + blobName, dtDownload.Name); // verify name
  68. Assert.Equal(originalContent, downloadContent); // verify contents
  69. }
  70. private static string TableToString(DataTable dt)
  71. {
  72. StringWriter sw = new StringWriter();
  73. dt.SaveToStream(sw);
  74. return sw.ToString();
  75. }
  76. [DebuggerNonUserCode]
  77. private static void DeleteContainer(CloudStorageAccount account, string containerName)
  78. {
  79. var client = account.CreateCloudBlobClient();
  80. CloudBlobContainer container = client.GetContainerReference(containerName);
  81. try
  82. {
  83. container.Delete();
  84. }
  85. catch
  86. {
  87. // Throws if container doesn't exist. That's ok.
  88. }
  89. }
  90. [Fact]
  91. public void UploadInvalidTableName()
  92. {
  93. var account = GetStorage();
  94. var source = from x in Enumerable.Range(1, 10) select new { N = x, N2 = x * x };
  95. DataTable dtSource = DataTable.New.FromEnumerable(source);
  96. string tableName = "csvtesttable%%"; // illegal name
  97. // Illegal name should get graceful error.
  98. Assert.Throws < InvalidOperationException>(() => dtSource.SaveToAzureTable(account, tableName));
  99. }
  100. [Fact]
  101. public void SaveToTableCausesDelete()
  102. {
  103. // Save a table to azure, and then use traditional techniques to query it back.
  104. var account = GetStorage();
  105. var source = from x in Enumerable.Range(1, 10) select new { N = x, N2 = x * x };
  106. DataTable dtSource = DataTable.New.FromEnumerable(source);
  107. string tableName = "csvtesttable";
  108. dtSource.SaveToAzureTable(account, tableName);
  109. // Now save a different table.
  110. var source2 = from x in Enumerable.Range(1, 5) select new { abc = x };
  111. DataTable dtSource2 = DataTable.New.FromEnumerable(source2);
  112. dtSource2.SaveToAzureTable(account, tableName);
  113. // Now look at table, and make sure it's the latest one.
  114. DataTable dtFromAzure = DataTable.New.ReadAzureTableLazy(account, tableName);
  115. Assert.False(dtFromAzure.HasColumnName("N"));
  116. Assert.False(dtFromAzure.HasColumnName("N2"));
  117. Assert.True(dtFromAzure.HasColumnName("abc"));
  118. int totalRows = dtFromAzure.Rows.Count();
  119. Assert.Equal(source2.Count(), totalRows);
  120. }
  121. [Fact]
  122. public void UploadWithRowKeyNoPartition()
  123. {
  124. var account = GetStorage();
  125. var source = from x in Enumerable.Range(1, 3) select new { RowKey = x * 10, N2 = x * x };
  126. DataTable dtSource = DataTable.New.FromEnumerable(source);
  127. string tableName = "csvtesttable";
  128. dtSource.SaveToAzureTable(account, tableName);
  129. DataTable dtFromAzure = DataTable.New.ReadAzureTableLazy(account, tableName);
  130. TestRecord[] result = Utility.ReadTable<TestRecord>(account, tableName);
  131. Assert.Equal(3, result.Length);
  132. int idx = 0;
  133. for (int i = 1; i <= result.Length; i++)
  134. {
  135. Assert.Equal((i * 10).ToString(), result[idx].RowKey);
  136. Assert.Equal("1", result[idx].PartitionKey);
  137. Assert.Equal(i * i, result[idx].N2);
  138. idx++;
  139. }
  140. }
  141. [Fact]
  142. public void UploadWithRowKeyAndPartition()
  143. {
  144. var account = GetStorage();
  145. // This is also a good test of each row having a different partition key
  146. var source = from x in Enumerable.Range(1, 3) select new { RowKey = x * 10, PartitionKey = x * 100, N2 = x * x };
  147. DataTable dtSource = DataTable.New.FromEnumerable(source);
  148. string tableName = "csvtesttable";
  149. dtSource.SaveToAzureTable(account, tableName);
  150. DataTable dtFromAzure = DataTable.New.ReadAzureTableLazy(account, tableName);
  151. TestRecord[] result = Utility.ReadTable<TestRecord>(account, tableName);
  152. Assert.Equal(3, result.Length);
  153. int idx = 0;
  154. for (int i = 1; i <= result.Length; i++)
  155. {
  156. Assert.Equal((i * 10).ToString(), result[idx].RowKey);
  157. Assert.Equal((i*100).ToString(), result[idx].PartitionKey);
  158. Assert.Equal(i * i, result[idx].N2);
  159. idx++;
  160. }
  161. }
  162. [Fact]
  163. public void UploadWithNoRowKeyAndPartition()
  164. {
  165. var account = GetStorage();
  166. // This is also a good test of each row having a different partition key
  167. var source = from x in Enumerable.Range(1, 3) select new { PartitionKey = x * 100, N2 = x * x };
  168. DataTable dtSource = DataTable.New.FromEnumerable(source);
  169. string tableName = "csvtesttable";
  170. dtSource.SaveToAzureTable(account, tableName);
  171. DataTable dtFromAzure = DataTable.New.ReadAzureTableLazy(account, tableName);
  172. TestRecord[] result = Utility.ReadTable<TestRecord>(account, tableName);
  173. Assert.Equal(3, result.Length);
  174. int idx = 0;
  175. for (int i = 1; i <= result.Length; i++)
  176. {
  177. Assert.Equal((i * 100).ToString(), result[idx].PartitionKey);
  178. Assert.Equal(i * i, result[idx].N2);
  179. idx++;
  180. }
  181. }
  182. [Fact]
  183. public void UploadWithExplicitRowAndPartitionFunc()
  184. {
  185. var account = GetStorage();
  186. // This is also a good test of each row having a different partition key
  187. var source = from x in Enumerable.Range(1, 3) select new { N = x * 10 };
  188. DataTable dtSource = DataTable.New.FromEnumerable(source);
  189. string tableName = "csvtesttable";
  190. Func<int, Row, ParitionRowKey> explicitFunc = (rowIdx, row) => new ParitionRowKey((rowIdx * 10).ToString(), rowIdx);
  191. dtSource.SaveToAzureTable(account, tableName, new Type[] { typeof(int) }, explicitFunc);
  192. DataTable dtFromAzure = DataTable.New.ReadAzureTableLazy(account, tableName);
  193. Assert.Equal(tableName, dtFromAzure.Name); // names should match.
  194. TestRecord[] result = Utility.ReadTable<TestRecord>(account, tableName);
  195. Assert.Equal(3, result.Length);
  196. int idx = 0;
  197. for (int i = 1; i <= result.Length; i++)
  198. {
  199. Assert.Equal(idx, int.Parse(result[idx].RowKey));
  200. Assert.Equal((idx*10).ToString(), result[idx].PartitionKey);
  201. Assert.Equal(i*10, result[idx].N);
  202. idx++;
  203. }
  204. }
  205. [Fact]
  206. public void RoundtripTable()
  207. {
  208. // Test that if we download and then reupload, it's ok.
  209. var account = GetStorage();
  210. var source = from x in Enumerable.Range(1, 200) select new { N = x, N2 = x * x };
  211. DataTable dtSource = DataTable.New.FromEnumerable(source);
  212. string tableName = "csvtesttable";
  213. dtSource.SaveToAzureTable(account, tableName); // original upload
  214. DataTable dtDownload1 = DataTable.New.ReadAzureTableLazy(account, tableName);
  215. MutableDataTable dtA = DataTable.New.GetMutableCopy(dtDownload1);
  216. // this writes back to the source that dtDownload1 was streaming from.
  217. // But we already copied to dtA, so safe to overwrite.
  218. dtA.SaveToAzureTable(account, tableName); // 2nd upload
  219. DataTable dtDownload2 = DataTable.New.ReadAzureTableLazy(account, tableName);
  220. MutableDataTable dtB = DataTable.New.GetMutableCopy(dtDownload2);
  221. // Everything except timestamps should match.
  222. dtA.DeleteColumns("TimeStamp");
  223. dtB.DeleteColumns("TimeStamp");
  224. Utility.AssertEquals(dtA, dtB);
  225. }
  226. [Fact]
  227. public void UploadCsvToAzureTables()
  228. {
  229. // Save a table to azure, and then use traditional techniques to query it back.
  230. // Use a large enough value to forcve batching and spilling.
  231. var account = GetStorage();
  232. var source = from x in Enumerable.Range(1, 200) select new { N = x, N2 = x * x };
  233. DataTable dtSource = DataTable.New.FromEnumerable(source);
  234. string tableName = "csvtesttable";
  235. dtSource.SaveToAzureTable(account, tableName);
  236. // Use traditional Azure table read to verify the newly uploaded table matches source.
  237. TestRecord[] result = Utility.ReadTable<TestRecord>(account, tableName);
  238. int i = 0;
  239. foreach(var item in source)
  240. {
  241. Assert.Equal(item.N, result[i].N);
  242. Assert.Equal(item.N2, result[i].N2);
  243. i++;
  244. }
  245. Assert.Equal(i, result.Length);
  246. // Read back as datatable
  247. DataTable dtFromAzure = DataTable.New.ReadAzureTableLazy(account, tableName);
  248. // When reading from Azure, we should get back row, parition, and timestamp keys.
  249. Assert.True(dtFromAzure.HasColumnName("RowKey"));
  250. Assert.True(dtFromAzure.HasColumnName("PartitionKey"));
  251. Assert.True(dtFromAzure.HasColumnName("TimeStamp"));
  252. // Compare contents with original table that was uploaded. Easy way to do this is to just keep the original columns.
  253. MutableDataTable dt5 = DataTable.New.GetMutableCopy(dtFromAzure);
  254. dt5.KeepColumns("N", "N2");
  255. Utility.AssertEquals(dtSource, dt5);
  256. }
  257. }
  258. class TestRecord : TableServiceEntity
  259. {
  260. public int N { get; set; }
  261. public int N2 { get; set; }
  262. }
  263. }