public void GetCityBytes_WhenPlayersInRegionArentInOrder_ShouldSucceed( [Frozen] DefaultMultiObjectLock.Factory lockerFactory, IMultiObjectLock locker, IMiniMapRegionObject obj1, IMiniMapRegionObject obj2, MiniMapRegion miniMapRegion) { obj1.Hash.Returns(1); obj2.Hash.Returns(2); lockerFactory().Lock(Arg.Is <ILockable[]>(p => p.SequenceEqual(new[] { obj2, obj1 }))) .Returns(locker); locker.When(p => p.SortLocks(Arg.Is <ILockable[]>(a => a.SequenceEqual(new[] { obj2, obj1 })))) .Do(args => Array.Sort((ILockable[])args[0], DefaultMultiObjectLock.CompareObject)); locker.Do(Arg.Any <Func <bool> >()).Returns(callInfo => { var action = callInfo.Arg <Func <bool> >(); return(action()); }); miniMapRegion.Add(obj2); miniMapRegion.Add(obj1); miniMapRegion.GetCityBytes().Should().NotBeNull(); }
public IMultiObjectLock Lock(CallbackLockHandler lockHandler, object[] lockHandlerParams, params ILockable[] baseLocks) { int attempts = 0; while (currentLock == null) { if ((++attempts) % 10 == 0) { logger.Warn(string.Format("CallbackLock has iterated {0} times {1}", attempts, Environment.StackTrace)); } if (attempts > 300) { throw new LockException("Callback lock exceeded maximum count"); } var toBeLocked = new List <ILockable>(baseLocks); // Lock the base objects multiObjectLockFactory().Lock(baseLocks) .Do(() => toBeLocked.AddRange(lockHandler(lockHandlerParams))); // Lock all of the objects we believe should be locked currentLock = multiObjectLockFactory(); currentLock.Lock(toBeLocked.ToArray()); // Grab the current list of objects we need to lock from the callback var newToBeLocked = new List <ILockable>(baseLocks); newToBeLocked.AddRange(lockHandler(lockHandlerParams)); // Make sure they are still all the same if (newToBeLocked.Count != toBeLocked.Count) { currentLock.UnlockAll(); currentLock = null; Thread.Sleep(GetWaitRetrySleep(attempts)); continue; } if (!newToBeLocked.Where((t, i) => t.Hash != toBeLocked[i].Hash).Any()) { continue; } currentLock.UnlockAll(); currentLock = null; Thread.Sleep(GetWaitRetrySleep(attempts)); } return(currentLock); }
public void Lock_CityIdTroopId_WhenTroopIsNotFound_ShouldReturnEmptyLockAndNullCity( [Frozen] IGameObjectLocator locator, [FrozenMock] DefaultMultiObjectLock.Factory lockFactory, IMultiObjectLock cityLock, IMultiObjectLock emptyLock, ICity city, ITroopObject troop, DefaultLocker locker) { lockFactory().Returns(cityLock, emptyLock); ICity outCity; locator.TryGetObjects(1, out outCity).Returns(call => { call[1] = city; return(true); }); ITroopObject outTroop; city.TryGetTroop(2, out outTroop).Returns(false); ICity lockedCity; ITroopObject lockedTroop; var multiObjLock = locker.Lock(1, 2, out lockedCity, out lockedTroop); ((object)lockedCity).Should().BeNull(); lockedTroop.Should().BeNull(); multiObjLock.Should().Be(emptyLock); emptyLock.Received(1) .Lock(Arg.Is <ILockable[]>(itemsLocked => !itemsLocked.Any())); cityLock.Received(1) .Lock(Arg.Is <ILockable[]>(itemsLocked => itemsLocked.SequenceEqual(new[] { city }))); cityLock.Received(1).UnlockAll(); }