public static void MyClassInitialize(TestContext testContext)
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            currentTable = tableClient.GetTableReference(GenerateRandomTableName());
            currentTable.CreateIfNotExists();

            // Populate Entities (This will add 1500 entities to a new table, enough to test continuations 
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            
            for (int l = 0; l < totalTestEntities / 100; l++)
            {
                for (int m = 0; m < 100; m++)
                {
                    BaseEntity ent = new BaseEntity("partition" + l, m.ToString());
                    ent.Randomize();
                    ent.A = ent.RowKey;
                    ctx.AddObject(currentTable.Name, ent);
                }

                ctx.SaveChangesWithRetries(SaveChangesOptions.Batch);
            }
        }
        private void DoSingleEntityReplaceFail(TablePayloadFormat format)
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext secondContext = tableClient.GetTableServiceContext();
            SetPayloadFormatOnDataServiceContext(ctx, format, tableClient);
            SetPayloadFormatOnDataServiceContext(secondContext, format, tableClient);

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo" + format.ToString());
            baseEntity.Randomize();
            ctx.AddObject(currentTable.Name, baseEntity);
            ctx.SaveChangesWithRetries();
            string etag = ctx.Entities.First().ETag;
            baseEntity.A = "updated";
            ctx.UpdateObject(baseEntity);
            ctx.SaveChangesWithRetries();

            MergeEntity replaceEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            replaceEntity.Randomize();
            secondContext.AttachTo(currentTable.Name, replaceEntity, etag);
            secondContext.UpdateObject(replaceEntity);
            OperationContext opContext = new OperationContext();

            try
            {
                secondContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate, null, opContext);
                Assert.Fail();
            }
            catch (StorageException)
            {
                TestHelper.ValidateResponse(opContext,
                       1,
                       (int)HttpStatusCode.PreconditionFailed,
                       new string[] { "UpdateConditionNotSatisfied", "ConditionNotMet" },
                       new string[] { "The update condition specified in the request was not satisfied.", "The condition specified using HTTP conditional header(s) is not met." });
            }

            ctx.DeleteObject(baseEntity);
            ctx.SaveChangesWithRetries();

            opContext = new OperationContext();

            // try merging with deleted entity
            try
            {
                secondContext.SaveChangesWithRetries(SaveChangesOptions.None, null, opContext);
                Assert.Fail();
            }
            catch (StorageException)
            {
                TestHelper.ValidateResponse(opContext, 1, (int)HttpStatusCode.NotFound, new string[] { "ResourceNotFound" }, "The specified resource does not exist.");
            }
        }
        private void DoSingleEntityReplace(TablePayloadFormat format)
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext queryContext = tableClient.GetTableServiceContext();
            SetPayloadFormatOnDataServiceContext(ctx, format, tableClient);
            SetPayloadFormatOnDataServiceContext(queryContext, format, tableClient);

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo" + format.ToString());
            baseEntity.Randomize();
            ctx.AddObject(currentTable.Name, baseEntity);
            ctx.SaveChangesWithRetries();
            string etag = ctx.Entities.First().ETag;
            ctx.Detach(baseEntity);

            MergeEntity replaceEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            replaceEntity.Randomize();
            ctx.AttachTo(currentTable.Name, replaceEntity, etag);
            ctx.UpdateObject(replaceEntity);
            ctx.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);

            // Retrieve Entity
            UnionEnitity retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                                            where ent.PartitionKey == baseEntity.PartitionKey
                                            && ent.RowKey == baseEntity.RowKey
                                            select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(null, retrievedEntity.A);
            Assert.AreEqual(null, retrievedEntity.B);
            Assert.AreEqual(null, retrievedEntity.C);
            Assert.AreEqual(replaceEntity.D, retrievedEntity.D);
            Assert.AreEqual(replaceEntity.E, retrievedEntity.E);
            Assert.AreEqual(replaceEntity.F, retrievedEntity.F);
        }
        public void SingleEntityInsertOrReplaceTask()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext queryContext = tableClient.GetTableServiceContext();
            queryContext.MergeOption = MergeOption.NoTracking;

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo");

            // Insert Or Merge with no pre-existing entity
            MergeEntity insertOrReplaceEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            insertOrReplaceEntity.Randomize();
            ctx.AttachTo(currentTable.Name, insertOrReplaceEntity, null);
            ctx.UpdateObject(insertOrReplaceEntity);
            ctx.SaveChangesWithRetriesAsync(SaveChangesOptions.ReplaceOnUpdate).Wait();
            ctx.Detach(insertOrReplaceEntity);

            // Retrieve Entity & Verify Contents
            UnionEnitity retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                                            where ent.PartitionKey == baseEntity.PartitionKey
                                            && ent.RowKey == baseEntity.RowKey
                                            select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(null, retrievedEntity.A);
            Assert.AreEqual(null, retrievedEntity.B);
            Assert.AreEqual(null, retrievedEntity.C);
            Assert.AreEqual(insertOrReplaceEntity.D, retrievedEntity.D);
            Assert.AreEqual(insertOrReplaceEntity.E, retrievedEntity.E);
            Assert.AreEqual(insertOrReplaceEntity.F, retrievedEntity.F);

            BaseEntity replacedEntity = new BaseEntity("insert test", "foo");
            replacedEntity.Randomize();

            ctx.AttachTo(currentTable.Name, replacedEntity, null);
            ctx.UpdateObject(replacedEntity);
            ctx.SaveChangesWithRetriesAsync(SaveChangesOptions.ReplaceOnUpdate).Wait();

            // Retrieve Entity & Verify
            retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                               where ent.PartitionKey == baseEntity.PartitionKey
                               && ent.RowKey == baseEntity.RowKey
                               select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(replacedEntity.A, retrievedEntity.A);
            Assert.AreEqual(replacedEntity.B, retrievedEntity.B);
            Assert.AreEqual(replacedEntity.C, retrievedEntity.C);
            Assert.AreEqual(null, retrievedEntity.D);
            Assert.AreEqual(null, retrievedEntity.E);
            Assert.AreEqual(null, retrievedEntity.F);
        }
        public void TableServiceContextTimeoutDuringSaveChangesNonBatchAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            for (int m = 0; m < 100; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }

            OperationContext opContext = new OperationContext();
            TableRequestOptions requestOptions = new TableRequestOptions() { MaximumExecutionTime = TimeSpan.FromSeconds(5) };

            using (HttpMangler proxy = new HttpMangler(false,
                new[] { DelayBehaviors.DelayAllRequestsIf(2000, XStoreSelectors.TableTraffic().IfHostNameContains(tableClient.Credentials.AccountName).SkipNSessions(10)) }))
            {
                try
                {
                    using (ManualResetEvent evt = new ManualResetEvent(false))
                    {
                        IAsyncResult result = ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, requestOptions, opContext,
                            (res) =>
                            {
                                result = res;
                                evt.Set();
                            }, null);

                        evt.WaitOne();

                        ctx.EndSaveChangesWithRetries(result);
                    }

                    ctx.SaveChangesWithRetries(SaveChangesOptions.None, requestOptions, opContext);
                }
                catch (StorageException ex)
                {
                    Assert.AreEqual(ex.RequestInformation.HttpStatusCode, (int)HttpStatusCode.RequestTimeout);
                    Assert.AreEqual("The client could not finish the operation within specified timeout.", ex.Message);
                    Assert.IsTrue(ex.InnerException is TimeoutException);
                }
            }
        }
        public void TableServiceContextConcurrencyAllowsOnlySingleOperationAtOnce()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext tableContext = tableClient.GetTableServiceContext();

            // insert entities to query against
            for (int i = 0; i < 5; i++)
            {
                for (int m = 0; m < 100; m++)
                {
                    BaseEntity ent = new BaseEntity("testpartition" + i, m.ToString());
                    ent.Randomize();
                    ent.A = ent.RowKey;
                    tableContext.AddObject(currentTable.Name, ent);
                }

                tableContext.SaveChangesWithRetries(SaveChangesOptions.Batch);
            }

            List<OperationContext> opContexts = new List<OperationContext>();
            object lockerObj = new object();
            DateTime start = DateTime.Now;

            int threadsRunning = 0;

            Exception lastEx = null;

            // Start 10 simultaneous threads to query entities associated with same context.
            for (int j = 0; j < 10; j++)
            {
                opContexts.Add(new OperationContext());
                Thread newThread = new Thread((arg) =>
                {
                    Interlocked.Increment(ref threadsRunning);
                    try
                    {
                        lock (lockerObj)
                        {
                            Monitor.Wait(lockerObj);
                        }

                        TableServiceQuery<BaseEntity> query = (from ent in tableContext.CreateQuery<BaseEntity>(currentTable.Name)
                                                               select ent).AsTableServiceQuery(tableContext);

                        Debug.WriteLine(String.Format("Thread {0} start operation @ {1}", Thread.CurrentThread.ManagedThreadId, (DateTime.Now - start).TotalMilliseconds));

                        try
                        {
                            query.Execute(null, arg as OperationContext).ToList();
                        }
                        catch (Exception)
                        {
                            // no op, expected to have some exceptions
                        }

                        Debug.WriteLine(String.Format("Thread {0} end operation @ {1}", Thread.CurrentThread.ManagedThreadId, (DateTime.Now - start).TotalMilliseconds));
                    }
                    catch (Exception ex)
                    {
                        lastEx = ex;
                    }
                    finally
                    {
                        Interlocked.Decrement(ref threadsRunning);
                    }
                });

                newThread.Start(opContexts[j]);
            }

            // Wait for all threads to start
            while (Interlocked.CompareExchange(ref threadsRunning, 10, 10) < 10)
            {
                Thread.Sleep(200);
            }

            // pulse all threads
            lock (lockerObj)
            {
                Monitor.PulseAll(lockerObj);
            }

            // Wait for all threads to complete
            while (Interlocked.CompareExchange(ref threadsRunning, -1, 0) > -1)
            {
                Thread.Sleep(200);
            }

            if (lastEx != null)
            {
                throw lastEx;
            }

            foreach (OperationContext opContext in opContexts)
            {
                if (opContext.LastResult == null || opContext.LastResult.StartTime == null || opContext.LastResult.EndTime == null)
                    continue;

                TestHelper.AssertNAttempts(opContext, 1);

                RequestResult currRes = opContext.LastResult;

                // Make sure this results start time does not occur in between any other results start & end time
                var overlappingResults = (from ctx in opContexts
                                          where ctx.LastResult != null && ctx.LastResult != currRes &&
                                          ctx.LastResult.StartTime != null && ctx.LastResult.EndTime != null &&
                                          ctx.LastResult.StartTime.Ticks < currRes.StartTime.Ticks &&
                                          ctx.LastResult.EndTime.Ticks > currRes.StartTime.Ticks
                                          select ctx.LastResult);

                Assert.AreEqual(overlappingResults.Count(), 0, "Detected overlapping query");
            }
        }
        public void TableServiceContextOperationContextEventsAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            for (int m = 0; m < 10; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }

            List<string> sends = new List<string>();
            List<string> receives = new List<string>();

            OperationContext opContext = new OperationContext();
            opContext.SendingRequest += (sender, args) => sends.Add(args.RequestInformation.StartTime.Ticks.ToString());
            opContext.ResponseReceived += (sender, args) => receives.Add(args.RequestInformation.ServiceRequestID);

            using (ManualResetEvent evt = new ManualResetEvent(false))
            {
                ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, null, opContext,
                    (res) =>
                    {
                        ctx.EndSaveChangesWithRetries(res);
                        evt.Set();
                    }, null);
                evt.WaitOne();
            }

            TestHelper.AssertNAttempts(opContext, 10);

            Assert.AreEqual(sends.Count(), 10);
            Assert.AreEqual(receives.Count(), 10);
        }
        public void TableServiceContextRequestResultsAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            for (int m = 0; m < 10; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }

            OperationContext opContext = new OperationContext();

            using (ManualResetEvent evt = new ManualResetEvent(false))
            {
                ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, null, opContext,
                    (res) =>
                    {
                        ctx.EndSaveChangesWithRetries(res);
                        evt.Set();
                    }, null);
                evt.WaitOne();
            }

            TestHelper.AssertNAttempts(opContext, 10);
        }
        public void TableServiceContextRequestResultsSync()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            for (int m = 0; m < 10; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }

            OperationContext opContext = new OperationContext();

            ctx.SaveChangesWithRetries(SaveChangesOptions.None, null, opContext);

            TestHelper.AssertNAttempts(opContext, 10);
        }
        public void TableServiceContextOperationContextStartEndTimeAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            DateTime start = DateTime.Now;
            for (int m = 0; m < 10; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }


            OperationContext opContext = new OperationContext();
            using (ManualResetEvent evt = new ManualResetEvent(false))
            {
                ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, null, opContext,
                    (res) =>
                    {
                        ctx.EndSaveChangesWithRetries(res);
                        evt.Set();
                    }, null);
                evt.WaitOne();
            }

            Assert.IsNotNull(opContext.StartTime, "StartTime not set");
            Assert.IsTrue(opContext.StartTime >= start, "StartTime not set correctly");
            Assert.IsNotNull(opContext.EndTime, "EndTime not set");
            Assert.IsTrue(opContext.EndTime <= DateTime.Now, "EndTime not set correctly");
        }
        public void SingleEntityMerge()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext queryContext = tableClient.GetTableServiceContext();

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo");
            baseEntity.Randomize();
            ctx.AddObject(currentTable.Name, baseEntity);
            ctx.SaveChangesWithRetries();
            string etag = ctx.Entities.First().ETag;
            ctx.Detach(baseEntity);

            MergeEntity mergeEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            mergeEntity.Randomize();
            ctx.AttachTo(currentTable.Name, mergeEntity, etag);
            ctx.UpdateObject(mergeEntity);
            ctx.SaveChangesWithRetries();

            // Retrieve Entity
            UnionEnitity retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                                            where ent.PartitionKey == baseEntity.PartitionKey
                                            && ent.RowKey == baseEntity.RowKey
                                            select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(baseEntity.A, retrievedEntity.A);
            Assert.AreEqual(baseEntity.B, retrievedEntity.B);
            Assert.AreEqual(baseEntity.C, retrievedEntity.C);
            Assert.AreEqual(mergeEntity.D, retrievedEntity.D);
            Assert.AreEqual(mergeEntity.E, retrievedEntity.E);
            Assert.AreEqual(mergeEntity.F, retrievedEntity.F);
        }