Permalink
Browse files

Merge pull request #172 from WindowsAzure/dev

Windows Azure Storage Client 2.0.4
  • Loading branch information...
2 parents 62783cb + 101f586 commit db922d4ac2cad5049eb94f61634f42657644be9f Abdelrahman Elogeel committed Jan 31, 2013
Showing with 304 additions and 26 deletions.
  1. +4 −0 microsoft-azure-api/Services/Storage/Lib/Common/Blob/Protocol/ListContainersResponse.cs
  2. +2 −2 microsoft-azure-api/Services/Storage/Lib/Common/Core/Executor/ExecutionState.cs
  3. +1 −1 microsoft-azure-api/Services/Storage/Lib/Common/Shared/Protocol/Constants.cs
  4. +6 −0 microsoft-azure-api/Services/Storage/Lib/Common/Table/Protocol/TableConstants.cs
  5. +2 −2 microsoft-azure-api/Services/Storage/Lib/Common/Table/TableQueryBase.cs
  6. +2 −2 microsoft-azure-api/Services/Storage/Lib/Common/Table/TableQueryGenericBase.cs
  7. +1 −1 microsoft-azure-api/Services/Storage/Lib/DotNet40/Properties/AssemblyInfo.cs
  8. +1 −1 microsoft-azure-api/Services/Storage/Lib/DotNet40/Table/TableQuery.cs
  9. +1 −1 microsoft-azure-api/Services/Storage/Lib/DotNet40/Table/TableQueryNonGeneric.cs
  10. +2 −2 microsoft-azure-api/Services/Storage/Lib/DotNet40/WindowsAzure.Storage.nuspec
  11. +15 −0 microsoft-azure-api/Services/Storage/Lib/DotNetCommon/Core/Executor/Executor.cs
  12. +1 −1 microsoft-azure-api/Services/Storage/Lib/RT/Properties/AssemblyInfo.cs
  13. +1 −1 microsoft-azure-api/Services/Storage/Lib/RT/Queue/CloudQueue.cs
  14. +1 −1 microsoft-azure-api/Services/Storage/Lib/RTTable/Properties/AssemblyInfo.cs
  15. +1 −1 microsoft-azure-api/Services/Storage/Lib/RTTable/TableQuery.cs
  16. +1 −1 microsoft-azure-api/Services/Storage/Test/Unit/DotNet40/Properties/AssemblyInfo.cs
  17. +58 −5 microsoft-azure-api/Services/Storage/Test/Unit/DotNet40/Table/TableQueryGenericTests.cs
  18. +55 −1 microsoft-azure-api/Services/Storage/Test/Unit/DotNet40/Table/TableQueryTests.cs
  19. +43 −0 microsoft-azure-api/Services/Storage/Test/Unit/DotNetCommon/Core/RetryPoliciesTests.cs
  20. +43 −0 microsoft-azure-api/Services/Storage/Test/Unit/RT/Core/RetryPoliciesTests.cs
  21. +1 −1 microsoft-azure-api/Services/Storage/Test/Unit/RT/Properties/AssemblyInfo.cs
  22. +23 −0 microsoft-azure-api/Services/Storage/Test/Unit/RT/Queue/CloudQueueMessageTest.cs
  23. +3 −2 microsoft-azure-api/Services/Storage/Test/Unit/RT/RT.csproj
  24. +28 −0 microsoft-azure-api/Services/Storage/Test/Unit/RT/Table/TableQueryTests.cs
  25. +8 −0 microsoft-azure-api/Services/Storage/changelog.txt
@@ -226,6 +226,10 @@ private BlobContainerEntry ParseContainerEntry()
case Constants.LeaseDurationElement:
containerProperties.LeaseDuration = BlobHttpResponseParsers.GetLeaseDuration(reader.ReadElementContentAsString());
break;
+
+ default:
+ reader.Skip();
+ break;
}
}
}
@@ -46,7 +46,7 @@ internal class ExecutionState<T>
public ExecutionState(StorageCommandBase<T> cmd, IRetryPolicy policy, OperationContext operationContext)
{
this.Cmd = cmd;
- this.RetryPolicy = policy.CreateInstance();
+ this.RetryPolicy = policy != null ? policy.CreateInstance() : new NoRetry();
this.OperationContext = operationContext ?? new OperationContext();
if (!this.OperationContext.OperationExpiryTime.HasValue && cmd != null && cmd.ClientMaxTimeout.HasValue)
@@ -69,7 +69,7 @@ public ExecutionState(StorageCommandBase<T> cmd, IRetryPolicy policy, OperationC
: base(callback, asyncState)
{
this.Cmd = cmd;
- this.RetryPolicy = policy.CreateInstance();
+ this.RetryPolicy = policy != null ? policy.CreateInstance() : new NoRetry();
this.OperationContext = operationContext ?? new OperationContext();
if (!this.OperationContext.OperationExpiryTime.HasValue && cmd != null && cmd.ClientMaxTimeout.HasValue)
@@ -605,7 +605,7 @@ internal class HeaderConstants
/// <summary>
/// Specifies the value to use for UserAgent header.
/// </summary>
- public const string UserAgentProductVersion = "2.0.3";
+ public const string UserAgentProductVersion = "2.0.4";
/// <summary>
/// Master Windows Azure Storage header prefix.
@@ -17,6 +17,7 @@
namespace Microsoft.WindowsAzure.Storage.Table.Protocol
{
+ using System;
using Microsoft.WindowsAzure.Storage.Shared.Protocol;
#if DNCP
@@ -120,5 +121,10 @@ class TableConstants
/// The query select clause name.
/// </summary>
internal const string Select = "$select";
+
+ /// <summary>
+ /// The minimum DateTime supported.
+ /// </summary>
+ public static readonly DateTimeOffset MinDateTime = new DateTimeOffset(1601, 1, 1, 0, 0, 0, TimeSpan.Zero);
}
}
@@ -47,7 +47,7 @@ public sealed partial class TableQuery
/// <returns>A string containing the formatted filter condition.</returns>
public static string GenerateFilterCondition(string propertyName, string operation, string givenValue)
{
- CommonUtils.AssertNotNullOrEmpty("givenValue", givenValue);
+ givenValue = givenValue ?? string.Empty;
return GenerateFilterCondition(propertyName, operation, givenValue, EdmType.String);
}
@@ -295,7 +295,7 @@ internal UriQueryBuilder GenerateQueryBuilder()
// take
if (this.takeCount.HasValue)
{
- builder.Add(TableConstants.Top, Convert.ToString(this.takeCount.Value));
+ builder.Add(TableConstants.Top, Convert.ToString(Math.Min(this.takeCount.Value, TableConstants.TableServiceMaxResults)));
}
// select
@@ -45,7 +45,7 @@ public sealed partial class TableQuery<TElement> where TElement : ITableEntity,
/// <returns>A string containing the formatted filter condition.</returns>
public static string GenerateFilterCondition(string propertyName, string operation, string value)
{
- CommonUtils.AssertNotNullOrEmpty("value", value);
+ value = value ?? string.Empty;
return GenerateFilterCondition(propertyName, operation, value, EdmType.String);
}
@@ -293,7 +293,7 @@ internal UriQueryBuilder GenerateQueryBuilder()
// take
if (this.takeCount.HasValue)
{
- builder.Add(TableConstants.Top, Convert.ToString(this.takeCount.Value));
+ builder.Add(TableConstants.Top, Convert.ToString(Math.Min(this.takeCount.Value, TableConstants.TableServiceMaxResults)));
}
// select
@@ -36,7 +36,7 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0.0")]
-[assembly: AssemblyFileVersion("2.0.3.0")]
+[assembly: AssemblyFileVersion("2.0.4.0")]
#if SIGN
[assembly: InternalsVisibleTo(
@@ -55,7 +55,7 @@ internal IEnumerable<TElement> Execute(CloudTableClient client, string tableName
return new ResultSegment<TElement>(seg.Results) { ContinuationToken = seg.ContinuationToken };
},
- long.MaxValue,
+ this.takeCount.HasValue ? this.takeCount.Value : long.MaxValue,
operationContext);
return enumerable;
@@ -53,7 +53,7 @@ internal IEnumerable<DynamicTableEntity> Execute(CloudTableClient client, string
return new ResultSegment<DynamicTableEntity>(seg.Results) { ContinuationToken = seg.ContinuationToken };
},
- long.MaxValue,
+ this.takeCount.HasValue ? this.takeCount.Value : long.MaxValue,
operationContext);
return enumerable;
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>WindowsAzure.Storage</id>
- <version>2.0.3.0</version>
+ <version>2.0.4.0</version>
<title>Windows Azure Storage</title>
<authors>Microsoft</authors>
<owners>Microsoft</owners>
@@ -16,7 +16,7 @@ Windows Azure Storage team's blog - http://blogs.msdn.com/b/windowsazurestorage/
<summary>A client library for working with Windows Azure storage services including blobs, tables, and queues.</summary>
<tags>Microsoft, Azure, Storage, Table, Blob, Queue, Scalable, windowsazureofficial</tags>
<dependencies>
- <dependency id="Microsoft.Data.OData" version="5.0.2" />
+ <dependency id="Microsoft.Data.OData" version="[5.0.2]" />
<dependency id="Microsoft.WindowsAzure.ConfigurationManager" version="1.8.0.0" />
</dependencies>
<frameworkAssemblies>
@@ -192,6 +192,18 @@ private static void EndSendStreamCopy<T>(ExecutionState<T> executionState)
}
else
{
+ try
+ {
+ executionState.ReqStream.Flush();
+ executionState.ReqStream.Dispose();
+ executionState.ReqStream = null;
+ }
+ catch (Exception)
+ {
+ // If we could not flush/dispose the request stream properly,
+ // BeginGetResponse will fail with a more meaningful error anyway.
+ }
+
BeginGetResponse(executionState);
}
}
@@ -442,6 +454,9 @@ public static T ExecuteSync<T>(StorageCommandBase<T> cmd, IRetryPolicy policy, O
executionState.Req.Timeout = executionState.RemainingTimeout;
executionState.ReqStream = executionState.Req.GetRequestStream();
executionState.RestCMD.SendStream.WriteToSync(executionState.ReqStream, null /* maxLength */, executionState.OperationExpiryTime, false, true, executionState.OperationContext, null /* streamCopyState */); // don't calculate md5 here as we should have already set this for auth purposes
+ executionState.ReqStream.Flush();
+ executionState.ReqStream.Dispose();
+ executionState.ReqStream = null;
}
// 6. Get response
@@ -26,7 +26,7 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0.0")]
-[assembly: AssemblyFileVersion("2.0.3.0")]
+[assembly: AssemblyFileVersion("2.0.4.0")]
[assembly: ComVisible(false)]
#if SIGN
[assembly: InternalsVisibleTo(
@@ -441,7 +441,7 @@ public IAsyncAction DeleteMessageAsync(CloudQueueMessage message, QueueRequestOp
/// <returns>An <see cref="IAsyncAction"/> that represents an asynchronous action.</returns>
public IAsyncAction DeleteMessageAsync(string messageId, string popReceipt)
{
- return this.DeleteMessageAsync(null, null, null, null);
+ return this.DeleteMessageAsync(messageId, popReceipt, null, null);
}
/// <summary>
@@ -25,5 +25,5 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0.0")]
-[assembly: AssemblyFileVersion("2.0.3.0")]
+[assembly: AssemblyFileVersion("2.0.4.0")]
[assembly: ComVisible(false)]
@@ -62,7 +62,7 @@ internal IEnumerable<TElement> Execute(CloudTableClient client, string tableName
return new ResultSegment<TElement>((List<TElement>)seg.Results) { ContinuationToken = seg.ContinuationToken };
},
- long.MaxValue,
+ this.takeCount.HasValue ? this.takeCount.Value : long.MaxValue,
operationContext);
return enumerable;
@@ -33,4 +33,4 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0.0")]
-[assembly: AssemblyFileVersion("2.0.3.0")]
+[assembly: AssemblyFileVersion("2.0.4.0")]
@@ -102,7 +102,7 @@ public static void MyClassCleanup()
#region Unit Tests
#region Query Segmented
-
+
#region Sync
[TestMethod]
@@ -186,7 +186,7 @@ public void TableEmptyHeaderSigningTest()
}
#endregion
-
+
#region APM
[TestMethod]
@@ -277,9 +277,9 @@ public void TableGenericQueryWithContinuationAPM()
Assert.AreEqual(1500, count);
TestHelper.AssertNAttempts(opContext, 2);
- }
+ }
#endregion
-
+
#endregion
[TestMethod]
@@ -432,7 +432,8 @@ public void TableGenericWithResolverAPM()
List<BaseEntity> list1 = new List<BaseEntity>();
do
{
- IAsyncResult result = currentTable.BeginExecuteQuerySegmented(query, (pk, rk, ts, prop, etag) => new BaseEntity() {
+ IAsyncResult result = currentTable.BeginExecuteQuerySegmented(query, (pk, rk, ts, prop, etag) => new BaseEntity()
+ {
PartitionKey = pk,
RowKey = rk,
Timestamp = ts,
@@ -588,6 +589,58 @@ public void TableGenericQueryOnSupportedTypes()
}
}
+ [TestMethod]
+ [Description("A test to validate basic take Count with and without continuations")]
+ [TestCategory(ComponentCategory.Table)]
+ [TestCategory(TestTypeCategory.UnitTest)]
+ [TestCategory(SmokeTestCategory.NonSmoke)]
+ [TestCategory(TenantTypeCategory.DevStore), TestCategory(TenantTypeCategory.DevFabric), TestCategory(TenantTypeCategory.Cloud)]
+ public void TableQueryGenericWithTakeCount()
+ {
+ // No continuation
+ TableQuery<BaseEntity> query = new TableQuery<BaseEntity>().Take(100);
+
+ OperationContext opContext = new OperationContext();
+ IEnumerable<BaseEntity> enumerable = currentTable.ExecuteQuery(query, null, opContext);
+
+ Assert.AreEqual(query.TakeCount, enumerable.Count());
+ TestHelper.AssertNAttempts(opContext, 1);
+
+
+ // With continuations
+ query.TakeCount = 1200;
+ opContext = new OperationContext();
+ enumerable = currentTable.ExecuteQuery(query, null, opContext);
+
+ Assert.AreEqual(query.TakeCount, enumerable.Count());
+ TestHelper.AssertNAttempts(opContext, 2);
+ }
+
+ [TestMethod]
+ [Description("A test to validate basic take Count with a resolver, with and without continuations")]
+ [TestCategory(ComponentCategory.Table)]
+ [TestCategory(TestTypeCategory.UnitTest)]
+ [TestCategory(SmokeTestCategory.NonSmoke)]
+ [TestCategory(TenantTypeCategory.DevStore), TestCategory(TenantTypeCategory.DevFabric), TestCategory(TenantTypeCategory.Cloud)]
+ public void TableQueryGenericWithTakeCountAndResolver()
+ {
+ // No continuation
+ TableQuery<BaseEntity> query = new TableQuery<BaseEntity>().Take(100);
+
+ OperationContext opContext = new OperationContext();
+ IEnumerable<string> enumerable = currentTable.ExecuteQuery(query, (pk, rk, ts, prop, etag) => pk + rk, null, opContext);
+
+ Assert.AreEqual(query.TakeCount, enumerable.Count());
+ TestHelper.AssertNAttempts(opContext, 1);
+
+ // With continuations
+ query.TakeCount = 1200;
+ opContext = new OperationContext();
+ enumerable = currentTable.ExecuteQuery(query, (pk, rk, ts, prop, etag) => pk + rk, null, opContext);
+
+ Assert.AreEqual(query.TakeCount, enumerable.Count());
+ TestHelper.AssertNAttempts(opContext, 2);
+ }
#endregion
#region Negative Tests
@@ -257,7 +257,7 @@ public void TableGenericQueryWithContinuationAPM()
#endregion
#endregion
-
+
[TestMethod]
[Description("A test to validate basic table filtering")]
[TestCategory(ComponentCategory.Table)]
@@ -478,6 +478,60 @@ public void TableQueryOnSupportedTypes()
}
}
+ [TestMethod]
+ [Description("A test to validate querying with an empty value")]
+ [TestCategory(ComponentCategory.Table)]
+ [TestCategory(TestTypeCategory.UnitTest)]
+ [TestCategory(SmokeTestCategory.NonSmoke)]
+ [TestCategory(TenantTypeCategory.DevStore), TestCategory(TenantTypeCategory.DevFabric), TestCategory(TenantTypeCategory.Cloud)]
+ public void TableQueryEmptyValue()
+ {
+ CloudTableClient client = GenerateCloudTableClient();
+
+ CloudTable table = client.GetTableReference(GenerateRandomTableName());
+ table.Create();
+
+ // Setup
+ string pk = Guid.NewGuid().ToString();
+
+ DynamicTableEntity dynEnt = new DynamicTableEntity(pk, string.Format("{0:0000}", "rowkey"));
+ dynEnt.Properties.Add("A", new EntityProperty(string.Empty));
+ table.Execute(TableOperation.Insert(dynEnt));
+
+ // 1. Filter on String
+ List<DynamicTableEntity> results = table.ExecuteQuery(new TableQuery().Where(TableQuery.GenerateFilterCondition("A", QueryComparisons.Equal, string.Empty))).ToList();
+ Assert.AreEqual(1, results.Count);
+
+ List<BaseEntity> pocoresults = table.ExecuteQuery(new TableQuery<BaseEntity>().Where(TableQuery.GenerateFilterCondition("A", QueryComparisons.Equal, string.Empty))).ToList();
+ Assert.AreEqual(1, pocoresults.Count);
+ }
+
+ [TestMethod]
+ [Description("A test to validate basic take Count with and without continuations")]
+ [TestCategory(ComponentCategory.Table)]
+ [TestCategory(TestTypeCategory.UnitTest)]
+ [TestCategory(SmokeTestCategory.NonSmoke)]
+ [TestCategory(TenantTypeCategory.DevStore), TestCategory(TenantTypeCategory.DevFabric), TestCategory(TenantTypeCategory.Cloud)]
+ public void TableQueryWithTakeCount()
+ {
+ // No continuation
+ TableQuery query = new TableQuery().Take(100);
+
+ OperationContext opContext = new OperationContext();
+ IEnumerable<DynamicTableEntity> enumerable = currentTable.ExecuteQuery(query, null, opContext);
+
+ Assert.AreEqual(query.TakeCount, enumerable.Count());
+ TestHelper.AssertNAttempts(opContext, 1);
+
+ // With continuations
+ query.TakeCount = 1200;
+ opContext = new OperationContext();
+ enumerable = currentTable.ExecuteQuery(query, null, opContext);
+
+ Assert.AreEqual(query.TakeCount, enumerable.Count());
+ TestHelper.AssertNAttempts(opContext, 2);
+ }
+
#endregion
#region Negative Tests
Oops, something went wrong.

0 comments on commit db922d4

Please sign in to comment.