示例#1
0
        public void ProcessChangeSet_update_dirty_invokes_successful_resolver_and_successful_retry()
        {
            var repo = A.Fake<IRepository<Asset, int>>();
            var context = A.Fake<IDataContext>();
            var resolver = A.Fake<IConflictResolver>();
            var bfim = A.Dummy<Models.Asset>();
            var afim = A.Dummy<Models.Asset>();

            var cs = new ChangeSet()
            {
                Assets = new List<ChangeItem<Models.Asset>>{
                     new ChangeItem<Models.Asset>{
                         Action = ChangeAction.Update,
                         BFIM = bfim,
                         AFIM = afim
                     }
                 }
            };

            A.CallTo(() => repo.KeySelector).Returns((Asset a) => a.Id);
            A.CallTo(() => context.Assets).Returns(repo);
            A.CallTo(() => context.AcceptChanges()).Throws(new ConcurrencyException()).Once();
            A.CallTo(() => resolver.Resolve(repo, A<ChangeItem<Asset>>.Ignored, A<IDictionary<int,Asset>>.Ignored)).Returns(true);

            var processor = new ChangeSetProcessor(context, resolver);
            var result = processor.Process(1, false, cs);

            Assert.IsTrue(result.IsEmpty);
            Assert.AreEqual(ChangeSet.Empty, result);
            A.CallTo(() => context.Assets.Update(afim)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => context.AcceptChanges()).MustHaveHappened(Repeated.Exactly.Twice);
        }
示例#2
0
        public void ProcessChangeSet_update_cleanly_completes_without_error()
        {
            var context = A.Fake<IDataContext>();
            var resolver = A.Fake<IConflictResolver>();
            var bfim = A.Dummy<Models.Asset>();
            var afim = A.Dummy<Models.Asset>();

            var cs = new ChangeSet()
            {
                Assets = new List<ChangeItem<Models.Asset>>{
                     new ChangeItem<Models.Asset>{
                         Action = ChangeAction.Update,
                         BFIM = bfim,
                         AFIM = afim
                     }
                 }
            };

            var processor = new ChangeSetProcessor(context, resolver);
            var result = processor.Process(1, false, cs);

            ExceptionAssert.Throws<ArgumentNullException>(() => processor.Process(1, false, null));
            Assert.IsTrue(result.IsEmpty);
            Assert.AreEqual(ChangeSet.Empty, result);
            A.CallTo(() => context.Assets.Update(A<Models.Asset>.Ignored)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => context.Assets.Update(afim)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => context.AcceptChanges()).MustHaveHappened(Repeated.Exactly.Once);
        }
示例#3
0
 private IHttpActionResult Conflict(ChangeSet changeSet)
 {
     if (changeSet == null || changeSet.IsEmpty)
         return Conflict();
     else
         return ResponseMessage(
             Request.CreateResponse(
             HttpStatusCode.Conflict, changeSet));
 }
示例#4
0
        public void ProcessChangeSet_update_dirty_invokes_unsuccessful_merge_and_no_retry()
        {
            var repo = A.Fake<IRepository<Asset, int>>();
            var context = A.Fake<IDataContext>();
            var resolver = new RejectConcurrentEditsConflictResolver();
            var afim = A.Dummy<Models.Asset>();

            var cs = new ChangeSet()
            {
                Assets = new List<ChangeItem<Models.Asset>>{
                     new ChangeItem<Models.Asset>{
                         Action = ChangeAction.Update,
                         BFIM = A.Dummy<Models.Asset>(),
                         AFIM = afim
                     }
                 }
            };
            A.CallTo(() => repo.KeySelector).Returns((Asset a) => a.Id);
            A.CallTo(() => context.Assets).Returns(repo);
            A.CallTo(() => context.AcceptChanges()).Throws(new ConcurrencyException()).Once();

            var processor = new ChangeSetProcessor(context, resolver);
            var result = processor.Process(1, false, cs);

            Assert.IsFalse(result.IsEmpty);
            Assert.AreNotEqual(ChangeSet.Empty, result);
            A.CallTo(() => context.Assets.Update(afim)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => context.AcceptChanges()).MustHaveHappened(Repeated.Exactly.Once);
        }
示例#5
0
        public void ProcessChangeSet_which_locks_retains_lock_on_failed_merge()
        {
            var job = new Job() { Id = 42 };
            var context = A.Fake<IDataContext>();
            var resolver = A.Fake<IConflictResolver>();
            var bfim = A.Dummy<Models.Asset>();
            var afim = A.Dummy<Models.Asset>();

            var cs = new ChangeSet()
            {
                Assets = new List<ChangeItem<Models.Asset>>{
                    new ChangeItem<Models.Asset>(ChangeAction.Update,bfim,afim),
                    new ChangeItem<Models.Asset>(ChangeAction.Delete,A.Dummy<Asset>(),null),
                    new ChangeItem<Models.Asset>(ChangeAction.Create,null, A.Dummy<Asset>())
                }
            };

            A.CallTo(() => resolver.Resolve(A<IRepository<Asset, int>>.Ignored, A<ChangeItem<Asset>>.Ignored, A<IDictionary<int, Asset>>.Ignored)).Returns(false);
            A.CallTo(() => context.Jobs.GetById(A<int>.Ignored)).Returns(job);
            A.CallTo(() => context.Assets.KeySelector).Returns((Asset a) => a.Id);
            A.CallTo(() => context.AcceptChanges()).Throws(new ConcurrencyException());
            A.CallTo(() => context.AcceptChanges()).DoesNothing().Once();

            var processor = new ChangeSetProcessor(context, resolver);
            var result = processor.Process(1, true, cs);

            Assert.IsFalse(result.IsEmpty);
            Assert.AreNotEqual(ChangeSet.Empty, result);
            A.CallTo(() => context.Assets.Update(afim)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => context.AcceptChanges()).MustHaveHappened(Repeated.Exactly.Twice);
            A.CallTo(() => resolver.Resolve(A<IRepository<Asset, int>>.Ignored, A<ChangeItem<Asset>>.Ignored, A<IDictionary<int, Asset>>.Ignored)).MustHaveHappened(Repeated.Exactly.Once);
            //Assert.IsNotNull(job.LockedBy); // disabling this check temporarily this functionality was designed around EF and transaction rollbacks
        }
示例#6
0
 private void Touch(int jobid, ChangeSet cs)
 {
     var im = cs.Assets.First(_ => _.BFIM != null).BFIM;
     s_rng.NextBytes(im.RowVersion);
 }
示例#7
0
        private ChangeSet BuildChangeSet(int jobId)
        {
            var dc = new Rel.Data.Ef6.TpContext();
            IList<Asset> assets;
            int count;
            using (var scope = new TransactionScope())
            {
                int take = s_rng.Next(s_minCsSize, s_maxCsSize);
                assets = dc.Database.SqlQuery<Asset>(
@"SELECT
Id
,JobId
,Name
,RowVersion
,ServiceArea
,PercentTolerance
,StaticTolerance
,MonotonicTolerance
,MaximumAndMinimumDecay
,MaxMinDecayWithStepAndTol
,MinimumDecay
FROM ( SELECT * FROM dbo.Asset WITH(NOLOCK) WHERE JobId=@p0 ) a
ORDER BY PercentTolerance ASC OFFSET 0 ROWS
FETCH NEXT @p1 ROWS ONLY", jobId, take).ToList();

                count = dc.Database.SqlQuery<int>(@"SELECT COUNT(Id) FROM dbo.Asset WITH(NOLOCK) WHERE JobId=@p0", jobId).Single();
                scope.Complete();
            }

            var cs = new ChangeSet()
            {
                Assets = assets
                    .Select(ModifyAsset)
                    .Union(NewAssets(jobId, s_rng.Next(1, (int)Math.Ceiling(assets.Count * 0.3)))).ToList()
            };

            s_assetCount[jobId - 1].IncrementBy(count);
            s_assetCountBase[jobId - 1].Increment();
            return cs;
        }