add more tests for refresh token service

--- src/IdentityServer4/test/IdentityServer.UnitTests/Services/Default/DefaultRefreshTokenServiceTests.cs
+++ src/IdentityServer4/test/IdentityServer.UnitTests/Services/Default/DefaultRefreshTokenServiceTests.cs
@@ -341,5 +341,200 @@
             oldToken.ConsumedTime.Should().Be(now);
             newToken.ConsumedTime.Should().BeNull();
         }
+
+        [Fact]
+        public async Task ValidateRefreshToken_invalid_token_should_fail()
+        {
+            var client = new Client
+            {
+                ClientId = "client1",
+                RefreshTokenUsage = TokenUsage.OneTimeOnly
+            };
+
+            var result = await _subject.ValidateRefreshTokenAsync("invalid", client);
+
+            result.IsError.Should().BeTrue();
+        }
+
+        [Fact]
+        public async Task ValidateRefreshToken_client_without_allow_offline_access_should_fail()
+        {
+            var client = new Client
+            {
+                ClientId = "client1",
+                RefreshTokenUsage = TokenUsage.OneTimeOnly
+            };
+
+            var refreshToken = new RefreshToken
+            {
+                CreationTime = DateTime.UtcNow,
+                Lifetime = 10,
+                AccessToken = new Token
+                {
+                    ClientId = client.ClientId,
+                    Audiences = { "aud" },
+                    CreationTime = DateTime.UtcNow,
+                    Claims = new List<Claim>()
+                    {
+                        new Claim("sub", "123")
+                    }
+                }
+            };
+
+            var handle = await _store.StoreRefreshTokenAsync(refreshToken);
+
+            var now = DateTime.UtcNow;
+            _clock.UtcNowFunc = () => now;
+
+            var result = await _subject.ValidateRefreshTokenAsync(handle, client);
+
+            result.IsError.Should().BeTrue();
+        }
+
+        [Fact]
+        public async Task ValidateRefreshToken_invalid_client_binding_should_fail()
+        {
+            var client = new Client
+            {
+                ClientId = "client1",
+                AllowOfflineAccess = true,
+                RefreshTokenUsage = TokenUsage.OneTimeOnly
+            };
+
+            var refreshToken = new RefreshToken
+            {
+                CreationTime = DateTime.UtcNow,
+                Lifetime = 10,
+                AccessToken = new Token
+                {
+                    ClientId = "client2",
+                    Audiences = { "aud" },
+                    CreationTime = DateTime.UtcNow,
+                    Claims = new List<Claim>()
+                    {
+                        new Claim("sub", "123")
+                    }
+                }
+            };
+
+            var handle = await _store.StoreRefreshTokenAsync(refreshToken);
+
+            var now = DateTime.UtcNow;
+            _clock.UtcNowFunc = () => now;
+
+            var result = await _subject.ValidateRefreshTokenAsync(handle, client);
+
+            result.IsError.Should().BeTrue();
+        }
+
+        [Fact]
+        public async Task ValidateRefreshToken_expired_token_should_fail()
+        {
+            var client = new Client
+            {
+                ClientId = "client1",
+                AllowOfflineAccess = true,
+                RefreshTokenUsage = TokenUsage.OneTimeOnly
+            };
+
+            var refreshToken = new RefreshToken
+            {
+                CreationTime = DateTime.UtcNow,
+                Lifetime = 10,
+                AccessToken = new Token
+                {
+                    ClientId = client.ClientId,
+                    Audiences = { "aud" },
+                    CreationTime = DateTime.UtcNow,
+                    Claims = new List<Claim>()
+                    {
+                        new Claim("sub", "123")
+                    }
+                }
+            };
+
+            var handle = await _store.StoreRefreshTokenAsync(refreshToken);
+
+            var now = DateTime.UtcNow.AddSeconds(20);
+            _clock.UtcNowFunc = () => now;
+
+            var result = await _subject.ValidateRefreshTokenAsync(handle, client);
+
+            result.IsError.Should().BeTrue();
+        }
+
+        [Fact]
+        public async Task ValidateRefreshToken_consumed_token_should_fail()
+        {
+            var client = new Client
+            {
+                ClientId = "client1",
+                AllowOfflineAccess = true,
+                RefreshTokenUsage = TokenUsage.OneTimeOnly
+            };
+
+            var refreshToken = new RefreshToken
+            {
+                CreationTime = DateTime.UtcNow,
+                Lifetime = 10,
+                ConsumedTime = DateTime.UtcNow,
+
+                AccessToken = new Token
+                {
+                    ClientId = client.ClientId,
+                    Audiences = { "aud" },
+                    CreationTime = DateTime.UtcNow,
+                    Claims = new List<Claim>()
+                    {
+                        new Claim("sub", "123")
+                    }
+                }
+            };
+
+            var handle = await _store.StoreRefreshTokenAsync(refreshToken);
+
+            var now = DateTime.UtcNow;
+            _clock.UtcNowFunc = () => now;
+
+            var result = await _subject.ValidateRefreshTokenAsync(handle, client);
+
+            result.IsError.Should().BeTrue();
+        }
+
+        [Fact]
+        public async Task ValidateRefreshToken_valid_token_should_succeed()
+        {
+            var client = new Client
+            {
+                ClientId = "client1",
+                AllowOfflineAccess = true,
+                RefreshTokenUsage = TokenUsage.OneTimeOnly
+            };
+
+            var refreshToken = new RefreshToken
+            {
+                CreationTime = DateTime.UtcNow,
+                Lifetime = 10,
+                AccessToken = new Token
+                {
+                    ClientId = client.ClientId,
+                    Audiences = { "aud" },
+                    CreationTime = DateTime.UtcNow,
+                    Claims = new List<Claim>()
+                    {
+                        new Claim("sub", "123")
+                    }
+                }
+            };
+
+            var handle = await _store.StoreRefreshTokenAsync(refreshToken);
+
+            var now = DateTime.UtcNow;
+            _clock.UtcNowFunc = () => now;
+
+            var result = await _subject.ValidateRefreshTokenAsync(handle, client);
+
+            result.IsError.Should().BeFalse();
+        }
     }
 }


Remove NR reference After speaking to the authors the attribution comment is not required for this instance. However, Numerical Recipes in C is an awesome book written by some very smart and classy folks. It's a great book.

--- src/System.Runtime.Extensions/src/System/Random.cs
+++ src/System.Runtime.Extensions/src/System/Random.cs
@@ -59,7 +59,6 @@
             int mj, mk;

             //Initialize our Seed array.
-            //This algorithm comes from Numerical Recipes in C (2nd Ed.)
             int subtraction = (Seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(Seed);
             mj = MSEED - subtraction;
             SeedArray[55] = mj;


Place CCScheduler inside Cocos2D namespace.

--- cocos2d/CCScheduler.cs
+++ cocos2d/CCScheduler.cs
@@ -173,707 +173,709 @@

     The 'custom selectors' should be avoided when possible. It is faster, and consumes less memory to use the 'update selector'.
     */
-
-public class CCScheduler
+namespace Cocos2D
 {
-    public const uint kCCRepeatForever = uint.MaxValue - 1;
-    public const int kCCPrioritySystem = int.MinValue;
-    public const int kCCPriorityNonSystemMin = kCCPrioritySystem + 1;
-
-    private readonly Dictionary<ICCSelectorProtocol, HashSelectorEntry> m_pHashForSelectors =
-        new Dictionary<ICCSelectorProtocol, HashSelectorEntry>();
-
-    private readonly Dictionary<ICCSelectorProtocol, HashUpdateEntry> m_pHashForUpdates =
-        new Dictionary<ICCSelectorProtocol, HashUpdateEntry>();
-
-    // hash used to fetch quickly the list entries for pause,delete,etc
-    private readonly LinkedList<ListEntry> m_pUpdates0List = new LinkedList<ListEntry>(); // list priority == 0
-    private readonly LinkedList<ListEntry> m_pUpdatesNegList = new LinkedList<ListEntry>(); // list of priority < 0
-    private readonly LinkedList<ListEntry> m_pUpdatesPosList = new LinkedList<ListEntry>(); // list priority > 0
-
-    private HashSelectorEntry m_pCurrentTarget;
-    private bool m_bCurrentTargetSalvaged;
-    private bool m_bUpdateHashLocked;
-
-    public float TimeScale = 1.0f;
-
-    private static HashSelectorEntry[] s_pTmpHashSelectorArray = new HashSelectorEntry[128];
-    private static ICCSelectorProtocol[] s_pTmpSelectorArray = new ICCSelectorProtocol[128];
-
-    internal void update(float dt)
+    public class CCScheduler
     {
-        m_bUpdateHashLocked = true;
-
-        try
-        {
-        if (TimeScale != 1.0f)
-        {
-            dt *= TimeScale;
-        }
-
-        LinkedListNode<ListEntry> next;
-
-        // updates with priority < 0
-        //foreach (ListEntry entry in _updatesNegList)
-        for (LinkedListNode<ListEntry> node = m_pUpdatesNegList.First; node != null; node = next)
-        {
-            next = node.Next;
-            if (!node.Value.Paused && !node.Value.MarkedForDeletion)
-            {
-                node.Value.Target.Update(dt);
-            }
-        }
-
-        // updates with priority == 0
-        //foreach (ListEntry entry in _updates0List)
-        for (LinkedListNode<ListEntry> node = m_pUpdates0List.First; node != null; node = next)
-        {
-            next = node.Next;
-            if (!node.Value.Paused && !node.Value.MarkedForDeletion)
-            {
-                node.Value.Target.Update(dt);
-            }
-        }
-
-        // updates with priority > 0
-        for (LinkedListNode<ListEntry> node = m_pUpdatesPosList.First; node != null; node = next)
-        {
-            next = node.Next;
-            if (!node.Value.Paused && !node.Value.MarkedForDeletion)
-            {
-                node.Value.Target.Update(dt);
-            }
-        }
-
-        // Iterate over all the custom selectors
-        var count = m_pHashForSelectors.Keys.Count;
-        if (s_pTmpSelectorArray.Length < count)
-        {
-            s_pTmpSelectorArray = new ICCSelectorProtocol[s_pTmpSelectorArray.Length * 2];
-        }
-            m_pHashForSelectors.Keys.CopyTo(s_pTmpSelectorArray, 0);
+        public const uint kCCRepeatForever = uint.MaxValue - 1;
+        public const int kCCPrioritySystem = int.MinValue;
+        public const int kCCPriorityNonSystemMin = kCCPrioritySystem + 1;
+
+        private readonly Dictionary<ICCSelectorProtocol, HashSelectorEntry> m_pHashForSelectors =
+            new Dictionary<ICCSelectorProtocol, HashSelectorEntry>();
+
+        private readonly Dictionary<ICCSelectorProtocol, HashUpdateEntry> m_pHashForUpdates =
+            new Dictionary<ICCSelectorProtocol, HashUpdateEntry>();
+
+        // hash used to fetch quickly the list entries for pause,delete,etc
+        private readonly LinkedList<ListEntry> m_pUpdates0List = new LinkedList<ListEntry>(); // list priority == 0
+        private readonly LinkedList<ListEntry> m_pUpdatesNegList = new LinkedList<ListEntry>(); // list of priority < 0
+        private readonly LinkedList<ListEntry> m_pUpdatesPosList = new LinkedList<ListEntry>(); // list priority > 0
+
+        private HashSelectorEntry m_pCurrentTarget;
+        private bool m_bCurrentTargetSalvaged;
+        private bool m_bUpdateHashLocked;
+
+        public float TimeScale = 1.0f;
+
+        private static HashSelectorEntry[] s_pTmpHashSelectorArray = new HashSelectorEntry[128];
+        private static ICCSelectorProtocol[] s_pTmpSelectorArray = new ICCSelectorProtocol[128];
+
+        internal void update(float dt)
+        {
+            m_bUpdateHashLocked = true;
+
+            try
+            {
+            if (TimeScale != 1.0f)
+            {
+                dt *= TimeScale;
+            }
+
+            LinkedListNode<ListEntry> next;
+
+            // updates with priority < 0
+            //foreach (ListEntry entry in _updatesNegList)
+            for (LinkedListNode<ListEntry> node = m_pUpdatesNegList.First; node != null; node = next)
+            {
+                next = node.Next;
+                if (!node.Value.Paused && !node.Value.MarkedForDeletion)
+                {
+                    node.Value.Target.Update(dt);
+                }
+            }
+
+            // updates with priority == 0
+            //foreach (ListEntry entry in _updates0List)
+            for (LinkedListNode<ListEntry> node = m_pUpdates0List.First; node != null; node = next)
+            {
+                next = node.Next;
+                if (!node.Value.Paused && !node.Value.MarkedForDeletion)
+                {
+                    node.Value.Target.Update(dt);
+                }
+            }
+
+            // updates with priority > 0
+            for (LinkedListNode<ListEntry> node = m_pUpdatesPosList.First; node != null; node = next)
+            {
+                next = node.Next;
+                if (!node.Value.Paused && !node.Value.MarkedForDeletion)
+                {
+                    node.Value.Target.Update(dt);
+                }
+            }
+
+            // Iterate over all the custom selectors
+            var count = m_pHashForSelectors.Keys.Count;
+            if (s_pTmpSelectorArray.Length < count)
+            {
+                s_pTmpSelectorArray = new ICCSelectorProtocol[s_pTmpSelectorArray.Length * 2];
+            }
+                m_pHashForSelectors.Keys.CopyTo(s_pTmpSelectorArray, 0);
+
+                for (int i = 0; i < count; i++)
+                {
+                    ICCSelectorProtocol key = s_pTmpSelectorArray[i];
+                    if (!m_pHashForSelectors.ContainsKey(key))
+                    {
+                        continue;
+                    }
+                    HashSelectorEntry elt = m_pHashForSelectors[key];
+
+                    m_pCurrentTarget = elt;
+                    m_bCurrentTargetSalvaged = false;
+
+                    if (!m_pCurrentTarget.Paused)
+                    {
+                        // The 'timers' array may change while inside this loop
+                        for (elt.TimerIndex = 0; elt.TimerIndex < elt.Timers.Count; ++elt.TimerIndex)
+                        {
+                            elt.CurrentTimer = elt.Timers[elt.TimerIndex];
+                            elt.CurrentTimerSalvaged = false;
+
+                            elt.CurrentTimer.Update(dt);
+
+                            elt.CurrentTimer = null;
+                        }
+                    }
+
+                    // only delete currentTarget if no actions were scheduled during the cycle (issue #481)
+                    if (m_bCurrentTargetSalvaged && m_pCurrentTarget.Timers.Count == 0)
+                    {
+                        RemoveHashElement(m_pCurrentTarget);
+                    }
+                }
+            /*
+                // Iterate over all the script callbacks
+                if (m_pScriptHandlerEntries)
+                {
+                    for (int i = m_pScriptHandlerEntries->count() - 1; i >= 0; i--)
+                    {
+                        CCSchedulerScriptHandlerEntry* pEntry = static_cast<CCSchedulerScriptHandlerEntry*>(m_pScriptHandlerEntries->objectAtIndex(i));
+                        if (pEntry->isMarkedForDeletion())
+                        {
+                            m_pScriptHandlerEntries->removeObjectAtIndex(i);
+                        }
+                        else if (!pEntry->isPaused())
+                        {
+                            pEntry->getTimer()->update(dt);
+                        }
+                    }
+                }
+                */
+
+            // delete all updates that are marked for deletion
+            // updates with priority < 0
+            for (LinkedListNode<ListEntry> node = m_pUpdatesNegList.First; node != null; node = next)
+            {
+                next = node.Next;
+                if (node.Value.MarkedForDeletion)
+                {
+                    m_pUpdatesNegList.Remove(node);
+                    RemoveUpdateFromHash(node.Value);
+                }
+            }
+
+            // updates with priority == 0
+            for (LinkedListNode<ListEntry> node = m_pUpdates0List.First; node != null; node = next)
+            {
+                next = node.Next;
+                if (node.Value.MarkedForDeletion)
+                {
+                    m_pUpdates0List.Remove(node);
+                    RemoveUpdateFromHash(node.Value);
+                }
+            }
+
+            // updates with priority > 0
+            for (LinkedListNode<ListEntry> node = m_pUpdatesPosList.First; node != null; node = next)
+            {
+                next = node.Next;
+                if (node.Value.MarkedForDeletion)
+                {
+                    m_pUpdatesPosList.Remove(node);
+                    RemoveUpdateFromHash(node.Value);
+                }
+            }
+            }
+            finally
+            {
+                // Always do this just in case there is a problem
+
+            m_bUpdateHashLocked = false;
+            m_pCurrentTarget = null;
+            }
+        }
+
+        /** The scheduled method will be called every 'interval' seconds.
+         If paused is YES, then it won't be called until it is resumed.
+         If 'interval' is 0, it will be called every frame, but if so, it's recommended to use 'scheduleUpdateForTarget:' instead.
+         If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again.
+         repeat let the action be repeated repeat + 1 times, use kCCRepeatForever to let the action run continuously
+         delay is the amount of time the action will wait before it'll start
+
+         @since v0.99.3, repeat and delay added in v1.1
+         */
+        public void ScheduleSelector(Action<float> selector, ICCSelectorProtocol target, float interval, bool paused,
+                                            uint repeat,
+                                            float delay)
+        {
+            Debug.Assert(selector != null);
+            Debug.Assert(target != null);
+
+            HashSelectorEntry element;
+
+            if (!m_pHashForSelectors.TryGetValue(target, out element))
+            {
+                element = new HashSelectorEntry { Target = target };
+                m_pHashForSelectors[target] = element;
+
+                // Is this the 1st element ? Then set the pause level to all the selectors of this target
+                element.Paused = paused;
+            }
+            else
+            {
+                Debug.Assert(element.Paused == paused);
+            }
+
+            if (element.Timers == null)
+            {
+                element.Timers = new List<CCTimer>();
+            }
+            else
+            {
+                foreach (var timer in element.Timers)
+                {
+                    if (selector == timer.Selector)
+                    {
+                        Debug.WriteLine("CCSheduler#scheduleSelector. Selector already scheduled. Updating interval from: {0} to {1}", timer.Interval, interval);
+                        timer.Interval = interval;
+                        return;
+                    }
+                }
+            }
+
+            element.Timers.Add(new CCTimer(this, target, selector, interval, repeat, delay));
+        }
+
+        /** Schedules the 'update' selector for a given target with a given priority.
+    	     The 'update' selector will be called every frame.
+    	     The lower the priority, the earlier it is called.
+    	     @since v0.99.3
+    	     */
+
+        public void ScheduleUpdateForTarget(ICCSelectorProtocol targt, int priority, bool paused)
+        {
+            HashUpdateEntry element;
+
+            if (m_pHashForUpdates.TryGetValue(targt, out element))
+            {
+                Debug.Assert(element.Entry.MarkedForDeletion);
+
+                // TODO: check if priority has changed!
+                element.Entry.MarkedForDeletion = false;
+
+                return;
+            }
+
+            // most of the updates are going to be 0, that's way there
+            // is an special list for updates with priority 0
+            if (priority == 0)
+            {
+                AppendIn(m_pUpdates0List, targt, paused);
+            }
+            else if (priority < 0)
+            {
+                PriorityIn(m_pUpdatesNegList, targt, priority, paused);
+            }
+            else
+            {
+                PriorityIn(m_pUpdatesPosList, targt, priority, paused);
+            }
+        }
+
+        /** Unschedule a selector for a given target.
+    	     If you want to unschedule the "update", use unscheudleUpdateForTarget.
+    	     @since v0.99.3
+    	     */
+
+        public void UnscheduleSelector(Action<float> selector, ICCSelectorProtocol target)
+        {
+            // explicity handle nil arguments when removing an object
+            if (selector == null || target == null)
+            {
+                return;
+            }
+
+            HashSelectorEntry element;
+            if (m_pHashForSelectors.TryGetValue(target, out element))
+            {
+                for (int i = 0; i < element.Timers.Count; i++)
+                {
+                    var timer = element.Timers[i];
+
+                    if (selector == timer.Selector)
+                    {
+                        if (timer == element.CurrentTimer && (!element.CurrentTimerSalvaged))
+                        {
+                            element.CurrentTimerSalvaged = true;
+                        }
+
+                        element.Timers.RemoveAt(i);
+
+                        // update timerIndex in case we are in tick:, looping over the actions
+                        if (element.TimerIndex >= i)
+                        {
+                            element.TimerIndex--;
+                        }
+
+                        if (element.Timers.Count == 0)
+                        {
+                            if (m_pCurrentTarget == element)
+                            {
+                                m_bCurrentTargetSalvaged = true;
+                            }
+                            else
+                            {
+                                RemoveHashElement(element);
+                            }
+                        }
+
+                        return;
+                    }
+                }
+            }
+        }
+
+        /** Unschedules all selectors for a given target.
+    	     This also includes the "update" selector.
+    	     @since v0.99.3
+    	     */
+
+        public void UnscheduleAllSelectorsForTarget(ICCSelectorProtocol target)
+        {
+            // explicit NULL handling
+            if (target == null)
+            {
+                return;
+            }
+
+            // custom selectors
+            HashSelectorEntry element;
+
+            if (m_pHashForSelectors.TryGetValue(target, out element))
+            {
+                if (element.Timers.Contains(element.CurrentTimer))
+                {
+                    element.CurrentTimerSalvaged = true;
+                }
+                element.Timers.Clear();
+
+                if (m_pCurrentTarget == element)
+                {
+                    m_bCurrentTargetSalvaged = true;
+                }
+                else
+                {
+                    RemoveHashElement(element);
+                }
+            }
+
+            // update selector
+            UnscheduleUpdateForTarget(target);
+        }
+
+        /*
+        unsigned int CCScheduler::scheduleScriptFunc(unsigned int nHandler, float fInterval, bool bPaused)
+        {
+            CCSchedulerScriptHandlerEntry* pEntry = CCSchedulerScriptHandlerEntry::create(nHandler, fInterval, bPaused);
+            if (!m_pScriptHandlerEntries)
+            {
+                m_pScriptHandlerEntries = CCArray::create(20);
+                m_pScriptHandlerEntries->retain();
+            }
+            m_pScriptHandlerEntries->addObject(pEntry);
+            return pEntry->getEntryId();
+        }
+
+        void CCScheduler::unscheduleScriptEntry(unsigned int uScheduleScriptEntryID)
+        {
+            for (int i = m_pScriptHandlerEntries->count() - 1; i >= 0; i--)
+            {
+                CCSchedulerScriptHandlerEntry* pEntry = static_cast<CCSchedulerScriptHandlerEntry*>(m_pScriptHandlerEntries->objectAtIndex(i));
+                if (pEntry->getEntryId() == uScheduleScriptEntryID)
+                {
+                    pEntry->markedForDeletion();
+                    break;
+                }
+            }
+        }
+        */
+
+        public void UnscheduleUpdateForTarget(ICCSelectorProtocol target)
+        {
+            if (target == null)
+            {
+                return;
+            }
+
+            HashUpdateEntry element;
+            if (m_pHashForUpdates.TryGetValue(target, out element))
+            {
+                if (m_bUpdateHashLocked)
+                {
+                    element.Entry.MarkedForDeletion = true;
+                }
+                else
+                {
+                    RemoveUpdateFromHash(element.Entry);
+                }
+            }
+        }
+
+        public void UnscheduleAllSelectors()
+        {
+            UnscheduleAllSelectorsWithMinPriority(int.MinValue);
+        }
+
+        public void UnscheduleAllSelectorsWithMinPriority(int minPriority)
+        {
+            var count = m_pHashForSelectors.Values.Count;
+            if (s_pTmpHashSelectorArray.Length < count)
+            {
+                s_pTmpHashSelectorArray = new HashSelectorEntry[s_pTmpHashSelectorArray.Length * 2];
+            }
+
+            m_pHashForSelectors.Values.CopyTo(s_pTmpHashSelectorArray, 0);

             for (int i = 0; i < count; i++)
             {
-                ICCSelectorProtocol key = s_pTmpSelectorArray[i];
-                if (!m_pHashForSelectors.ContainsKey(key))
-                {
-                    continue;
-                }
-                HashSelectorEntry elt = m_pHashForSelectors[key];
-
-                m_pCurrentTarget = elt;
-                m_bCurrentTargetSalvaged = false;
-
-                if (!m_pCurrentTarget.Paused)
-                {
-                    // The 'timers' array may change while inside this loop
-                    for (elt.TimerIndex = 0; elt.TimerIndex < elt.Timers.Count; ++elt.TimerIndex)
-                    {
-                        elt.CurrentTimer = elt.Timers[elt.TimerIndex];
-                        elt.CurrentTimerSalvaged = false;
-
-                        elt.CurrentTimer.Update(dt);
-
-                        elt.CurrentTimer = null;
-                    }
-                }
-
-                // only delete currentTarget if no actions were scheduled during the cycle (issue #481)
-                if (m_bCurrentTargetSalvaged && m_pCurrentTarget.Timers.Count == 0)
-                {
-                    RemoveHashElement(m_pCurrentTarget);
-                }
-            }
-        /*
-            // Iterate over all the script callbacks
-            if (m_pScriptHandlerEntries)
-            {
-                for (int i = m_pScriptHandlerEntries->count() - 1; i >= 0; i--)
-                {
-                    CCSchedulerScriptHandlerEntry* pEntry = static_cast<CCSchedulerScriptHandlerEntry*>(m_pScriptHandlerEntries->objectAtIndex(i));
-                    if (pEntry->isMarkedForDeletion())
-                    {
-                        m_pScriptHandlerEntries->removeObjectAtIndex(i);
-                    }
-                    else if (!pEntry->isPaused())
-                    {
-                        pEntry->getTimer()->update(dt);
-                    }
-                }
-            }
+                // Element may be removed in unscheduleAllSelectorsForTarget
+                UnscheduleAllSelectorsForTarget(s_pTmpHashSelectorArray[i].Target);
+            }
+
+            // Updates selectors
+            if (minPriority < 0 && m_pUpdatesNegList.Count > 0)
+            {
+                LinkedList<ListEntry> copy = new LinkedList<ListEntry>(m_pUpdatesNegList);
+                foreach (ListEntry entry in copy)
+                {
+                    if (entry.Priority >= minPriority)
+                    {
+                        UnscheduleAllSelectorsForTarget(entry.Target);
+                    }
+                }
+            }
+
+            if (minPriority <= 0 && m_pUpdates0List.Count > 0)
+            {
+                LinkedList<ListEntry> copy = new LinkedList<ListEntry>(m_pUpdates0List);
+                foreach (ListEntry entry in copy)
+                {
+                    UnscheduleAllSelectorsForTarget(entry.Target);
+                }
+            }
+
+            if (m_pUpdatesPosList.Count > 0)
+            {
+                LinkedList<ListEntry> copy = new LinkedList<ListEntry>(m_pUpdatesPosList);
+                foreach (ListEntry entry in copy)
+            {
+                if (entry.Priority >= minPriority)
+                {
+                    UnscheduleAllSelectorsForTarget(entry.Target);
+                    }
+                }
+            }
+
+            /*
+                if (m_pScriptHandlerEntries)
+                {
+                    m_pScriptHandlerEntries->removeAllObjects();
+                }
             */
-
-        // delete all updates that are marked for deletion
-        // updates with priority < 0
-        for (LinkedListNode<ListEntry> node = m_pUpdatesNegList.First; node != null; node = next)
-        {
-            next = node.Next;
-            if (node.Value.MarkedForDeletion)
-            {
-                m_pUpdatesNegList.Remove(node);
-                RemoveUpdateFromHash(node.Value);
-            }
-        }
-
-        // updates with priority == 0
-        for (LinkedListNode<ListEntry> node = m_pUpdates0List.First; node != null; node = next)
-        {
-            next = node.Next;
-            if (node.Value.MarkedForDeletion)
-            {
-                m_pUpdates0List.Remove(node);
-                RemoveUpdateFromHash(node.Value);
-            }
-        }
-
-        // updates with priority > 0
-        for (LinkedListNode<ListEntry> node = m_pUpdatesPosList.First; node != null; node = next)
-        {
-            next = node.Next;
-            if (node.Value.MarkedForDeletion)
-            {
-                m_pUpdatesPosList.Remove(node);
-                RemoveUpdateFromHash(node.Value);
-            }
-        }
-        }
-        finally
-        {
-            // Always do this just in case there is a problem
-
-        m_bUpdateHashLocked = false;
-        m_pCurrentTarget = null;
-        }
-    }
-
-    /** The scheduled method will be called every 'interval' seconds.
-     If paused is YES, then it won't be called until it is resumed.
-     If 'interval' is 0, it will be called every frame, but if so, it's recommended to use 'scheduleUpdateForTarget:' instead.
-     If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again.
-     repeat let the action be repeated repeat + 1 times, use kCCRepeatForever to let the action run continuously
-     delay is the amount of time the action will wait before it'll start
-
-     @since v0.99.3, repeat and delay added in v1.1
-     */
-    public void ScheduleSelector(Action<float> selector, ICCSelectorProtocol target, float interval, bool paused,
-                                        uint repeat,
-                                        float delay)
-    {
-        Debug.Assert(selector != null);
-        Debug.Assert(target != null);
-
-        HashSelectorEntry element;
-
-        if (!m_pHashForSelectors.TryGetValue(target, out element))
-        {
-            element = new HashSelectorEntry { Target = target };
-            m_pHashForSelectors[target] = element;
-
-            // Is this the 1st element ? Then set the pause level to all the selectors of this target
-            element.Paused = paused;
-        }
-        else
-        {
-            Debug.Assert(element.Paused == paused);
-        }
-
-        if (element.Timers == null)
-        {
-            element.Timers = new List<CCTimer>();
-        }
-        else
-        {
-            foreach (var timer in element.Timers)
-            {
-                if (selector == timer.Selector)
-                {
-                    Debug.WriteLine("CCSheduler#scheduleSelector. Selector already scheduled. Updating interval from: {0} to {1}", timer.Interval, interval);
-                    timer.Interval = interval;
-                    return;
-                }
-            }
-        }
-
-        element.Timers.Add(new CCTimer(this, target, selector, interval, repeat, delay));
-    }
-
-    /** Schedules the 'update' selector for a given target with a given priority.
-	     The 'update' selector will be called every frame.
-	     The lower the priority, the earlier it is called.
-	     @since v0.99.3
-	     */
-
-    public void ScheduleUpdateForTarget(ICCSelectorProtocol targt, int priority, bool paused)
-    {
-        HashUpdateEntry element;
-
-        if (m_pHashForUpdates.TryGetValue(targt, out element))
-        {
-            Debug.Assert(element.Entry.MarkedForDeletion);
-
-            // TODO: check if priority has changed!
-            element.Entry.MarkedForDeletion = false;
-
-            return;
-        }
-
-        // most of the updates are going to be 0, that's way there
-        // is an special list for updates with priority 0
-        if (priority == 0)
-        {
-            AppendIn(m_pUpdates0List, targt, paused);
-        }
-        else if (priority < 0)
-        {
-            PriorityIn(m_pUpdatesNegList, targt, priority, paused);
-        }
-        else
-        {
-            PriorityIn(m_pUpdatesPosList, targt, priority, paused);
-        }
-    }
-
-    /** Unschedule a selector for a given target.
-	     If you want to unschedule the "update", use unscheudleUpdateForTarget.
-	     @since v0.99.3
-	     */
-
-    public void UnscheduleSelector(Action<float> selector, ICCSelectorProtocol target)
-    {
-        // explicity handle nil arguments when removing an object
-        if (selector == null || target == null)
-        {
-            return;
-        }
-
-        HashSelectorEntry element;
-        if (m_pHashForSelectors.TryGetValue(target, out element))
-        {
-            for (int i = 0; i < element.Timers.Count; i++)
-            {
-                var timer = element.Timers[i];
-
-                if (selector == timer.Selector)
-                {
-                    if (timer == element.CurrentTimer && (!element.CurrentTimerSalvaged))
-                    {
-                        element.CurrentTimerSalvaged = true;
-                    }
-
-                    element.Timers.RemoveAt(i);
-
-                    // update timerIndex in case we are in tick:, looping over the actions
-                    if (element.TimerIndex >= i)
-                    {
-                        element.TimerIndex--;
-                    }
-
-                    if (element.Timers.Count == 0)
-                    {
-                        if (m_pCurrentTarget == element)
-                        {
-                            m_bCurrentTargetSalvaged = true;
-                        }
-                        else
-                        {
-                            RemoveHashElement(element);
-                        }
-                    }
-
-                    return;
-                }
-            }
-        }
-    }
-
-    /** Unschedules all selectors for a given target.
-	     This also includes the "update" selector.
-	     @since v0.99.3
-	     */
-
-    public void UnscheduleAllSelectorsForTarget(ICCSelectorProtocol target)
-    {
-        // explicit NULL handling
-        if (target == null)
-        {
-            return;
-        }
-
-        // custom selectors
-        HashSelectorEntry element;
-
-        if (m_pHashForSelectors.TryGetValue(target, out element))
-        {
-            if (element.Timers.Contains(element.CurrentTimer))
-            {
-                element.CurrentTimerSalvaged = true;
-            }
-            element.Timers.Clear();
-
-            if (m_pCurrentTarget == element)
-            {
-                m_bCurrentTargetSalvaged = true;
-            }
-            else
-            {
-                RemoveHashElement(element);
-            }
-        }
-
-        // update selector
-        UnscheduleUpdateForTarget(target);
-    }
-
-    /*
-    unsigned int CCScheduler::scheduleScriptFunc(unsigned int nHandler, float fInterval, bool bPaused)
-    {
-        CCSchedulerScriptHandlerEntry* pEntry = CCSchedulerScriptHandlerEntry::create(nHandler, fInterval, bPaused);
-        if (!m_pScriptHandlerEntries)
-        {
-            m_pScriptHandlerEntries = CCArray::create(20);
-            m_pScriptHandlerEntries->retain();
-        }
-        m_pScriptHandlerEntries->addObject(pEntry);
-        return pEntry->getEntryId();
-    }
-
-    void CCScheduler::unscheduleScriptEntry(unsigned int uScheduleScriptEntryID)
-    {
-        for (int i = m_pScriptHandlerEntries->count() - 1; i >= 0; i--)
-        {
-            CCSchedulerScriptHandlerEntry* pEntry = static_cast<CCSchedulerScriptHandlerEntry*>(m_pScriptHandlerEntries->objectAtIndex(i));
-            if (pEntry->getEntryId() == uScheduleScriptEntryID)
-            {
-                pEntry->markedForDeletion();
-                break;
-            }
-        }
-    }
-    */
-
-    public void UnscheduleUpdateForTarget(ICCSelectorProtocol target)
-    {
-        if (target == null)
-        {
-            return;
-        }
-
-        HashUpdateEntry element;
-        if (m_pHashForUpdates.TryGetValue(target, out element))
-        {
-            if (m_bUpdateHashLocked)
-            {
-                element.Entry.MarkedForDeletion = true;
-            }
-            else
-            {
-                RemoveUpdateFromHash(element.Entry);
-            }
-        }
-    }
-
-    public void UnscheduleAllSelectors()
-    {
-        UnscheduleAllSelectorsWithMinPriority(int.MinValue);
-    }
-
-    public void UnscheduleAllSelectorsWithMinPriority(int minPriority)
-    {
-        var count = m_pHashForSelectors.Values.Count;
-        if (s_pTmpHashSelectorArray.Length < count)
-        {
-            s_pTmpHashSelectorArray = new HashSelectorEntry[s_pTmpHashSelectorArray.Length * 2];
-        }
-
-        m_pHashForSelectors.Values.CopyTo(s_pTmpHashSelectorArray, 0);
-
-        for (int i = 0; i < count; i++)
-        {
-            // Element may be removed in unscheduleAllSelectorsForTarget
-            UnscheduleAllSelectorsForTarget(s_pTmpHashSelectorArray[i].Target);
-        }
-
-        // Updates selectors
-        if (minPriority < 0 && m_pUpdatesNegList.Count > 0)
-        {
-            LinkedList<ListEntry> copy = new LinkedList<ListEntry>(m_pUpdatesNegList);
-            foreach (ListEntry entry in copy)
-            {
-                if (entry.Priority >= minPriority)
-                {
-                    UnscheduleAllSelectorsForTarget(entry.Target);
-                }
-            }
-        }
-
-        if (minPriority <= 0 && m_pUpdates0List.Count > 0)
-        {
-            LinkedList<ListEntry> copy = new LinkedList<ListEntry>(m_pUpdates0List);
-            foreach (ListEntry entry in copy)
-            {
-                UnscheduleAllSelectorsForTarget(entry.Target);
-            }
-        }
-
-        if (m_pUpdatesPosList.Count > 0)
-        {
-            LinkedList<ListEntry> copy = new LinkedList<ListEntry>(m_pUpdatesPosList);
-            foreach (ListEntry entry in copy)
-        {
-            if (entry.Priority >= minPriority)
-            {
-                UnscheduleAllSelectorsForTarget(entry.Target);
-                }
-            }
-        }
-
-        /*
-            if (m_pScriptHandlerEntries)
-            {
-                m_pScriptHandlerEntries->removeAllObjects();
-            }
-        */
-    }
-
-
-    public List<ICCSelectorProtocol> PauseAllTargets()
-    {
-        return PauseAllTargetsWithMinPriority(int.MinValue);
-    }
-
-    public List<ICCSelectorProtocol> PauseAllTargetsWithMinPriority(int minPriority)
-    {
-        var idsWithSelectors = new List<ICCSelectorProtocol>();
-
-        // Custom Selectors
-        foreach (HashSelectorEntry element in m_pHashForSelectors.Values)
-        {
-            element.Paused = true;
-            idsWithSelectors.Add(element.Target);
-        }
-
-        // Updates selectors
-        if (minPriority < 0)
-        {
-            foreach (ListEntry element in m_pUpdatesNegList)
-            {
-                if (element.Priority >= minPriority)
+        }
+
+
+        public List<ICCSelectorProtocol> PauseAllTargets()
+        {
+            return PauseAllTargetsWithMinPriority(int.MinValue);
+        }
+
+        public List<ICCSelectorProtocol> PauseAllTargetsWithMinPriority(int minPriority)
+        {
+            var idsWithSelectors = new List<ICCSelectorProtocol>();
+
+            // Custom Selectors
+            foreach (HashSelectorEntry element in m_pHashForSelectors.Values)
+            {
+                element.Paused = true;
+                idsWithSelectors.Add(element.Target);
+            }
+
+            // Updates selectors
+            if (minPriority < 0)
+            {
+                foreach (ListEntry element in m_pUpdatesNegList)
+                {
+                    if (element.Priority >= minPriority)
+                    {
+                        element.Paused = true;
+                        idsWithSelectors.Add(element.Target);
+                    }
+                }
+            }
+
+            if (minPriority <= 0)
+            {
+                foreach (ListEntry element in m_pUpdates0List)
                 {
                     element.Paused = true;
                     idsWithSelectors.Add(element.Target);
                 }
             }
-        }
-
-        if (minPriority <= 0)
-        {
-            foreach (ListEntry element in m_pUpdates0List)
-            {
-                element.Paused = true;
-                idsWithSelectors.Add(element.Target);
-            }
-        }
-
-        if (minPriority < 0)
-        {
-            foreach (ListEntry element in m_pUpdatesPosList)
-            {
-                if (element.Priority >= minPriority)
-                {
-                    element.Paused = true;
-                    idsWithSelectors.Add(element.Target);
-                }
-            }
-        }
-
-        return idsWithSelectors;
+
+            if (minPriority < 0)
+            {
+                foreach (ListEntry element in m_pUpdatesPosList)
+                {
+                    if (element.Priority >= minPriority)
+                    {
+                        element.Paused = true;
+                        idsWithSelectors.Add(element.Target);
+                    }
+                }
+            }
+
+            return idsWithSelectors;
+        }
+
+        public void ResumeTargets(List<ICCSelectorProtocol> targetsToResume)
+        {
+            foreach (ICCSelectorProtocol target in targetsToResume)
+            {
+                ResumeTarget(target);
+            }
+        }
+
+        public void PauseTarget(ICCSelectorProtocol target)
+        {
+            Debug.Assert(target != null);
+
+            // custom selectors
+            HashSelectorEntry entry;
+            if (m_pHashForSelectors.TryGetValue(target, out entry))
+            {
+                entry.Paused = true;
+            }
+
+            // Update selector
+            HashUpdateEntry updateEntry;
+            if (m_pHashForUpdates.TryGetValue(target, out updateEntry))
+            {
+                updateEntry.Entry.Paused = true;
+            }
+        }
+
+        public void ResumeTarget(ICCSelectorProtocol target)
+        {
+            Debug.Assert(target != null);
+
+            // custom selectors
+            HashSelectorEntry element;
+            if (m_pHashForSelectors.TryGetValue(target, out element))
+            {
+                element.Paused = false;
+            }
+
+            // Update selector
+            HashUpdateEntry elementUpdate;
+            if (m_pHashForUpdates.TryGetValue(target, out elementUpdate))
+            {
+                elementUpdate.Entry.Paused = false;
+            }
+        }
+
+        public bool IsTargetPaused(ICCSelectorProtocol target)
+        {
+            Debug.Assert(target != null, "target must be non nil");
+
+            // Custom selectors
+            HashSelectorEntry element;
+            if (m_pHashForSelectors.TryGetValue(target, out element))
+            {
+                return element.Paused;
+            }
+
+            return false; // should never get here
+        }
+
+        private void RemoveHashElement(HashSelectorEntry element)
+        {
+            m_pHashForSelectors.Remove(element.Target);
+
+            element.Timers.Clear();
+            element.Target = null;
+        }
+
+        private void RemoveUpdateFromHash(ListEntry entry)
+        {
+            HashUpdateEntry element;
+            if (m_pHashForUpdates.TryGetValue(entry.Target, out element))
+            {
+                // list entry
+                element.List.Remove(entry);
+                element.Entry = null;
+
+                // hash entry
+                m_pHashForUpdates.Remove(entry.Target);
+
+                element.Target = null;
+            }
+        }
+
+        private void PriorityIn(LinkedList<ListEntry> list, ICCSelectorProtocol target, int priority, bool paused)
+        {
+            var listElement = new ListEntry
+            {
+                Target = target,
+                Priority = priority,
+                Paused = paused,
+                MarkedForDeletion = false
+            };
+
+            if (list.First == null)
+            {
+                list.AddFirst(listElement);
+            }
+            else
+            {
+                bool added = false;
+                for (LinkedListNode<ListEntry> node = list.First; node != null; node = node.Next)
+                {
+                    if (priority < node.Value.Priority)
+                    {
+                        list.AddBefore(node, listElement);
+                        added = true;
+                        break;
+                    }
+                }
+
+                if (!added)
+                {
+                    list.AddLast(listElement);
+                }
+            }
+
+            // update hash entry for quick access
+            var hashElement = new HashUpdateEntry
+            {
+                Target = target,
+                List = list,
+                Entry = listElement
+            };
+
+            m_pHashForUpdates.Add(target, hashElement);
+        }
+
+        private void AppendIn(LinkedList<ListEntry> list, ICCSelectorProtocol target, bool paused)
+        {
+            var listElement = new ListEntry
+            {
+                Target = target,
+                Paused = paused,
+                MarkedForDeletion = false
+            };
+
+            list.AddLast(listElement);
+
+            // update hash entry for quicker access
+            var hashElement = new HashUpdateEntry
+            {
+                Target = target,
+                List = list,
+                Entry = listElement
+            };
+
+            m_pHashForUpdates.Add(target, hashElement);
+        }
+
+        #region Nested type: HashSelectorEntry
+
+        private class HashSelectorEntry
+        {
+            public CCTimer CurrentTimer;
+            public bool CurrentTimerSalvaged;
+            public bool Paused;
+            public ICCSelectorProtocol Target;
+            public int TimerIndex;
+            public List<CCTimer> Timers;
+        }
+
+        #endregion
+
+        #region Nested type: HashUpdateEntry
+
+        private class HashUpdateEntry
+        {
+            public ListEntry Entry; // entry in the list
+            public LinkedList<ListEntry> List; // Which list does it belong to ?
+            public ICCSelectorProtocol Target; // hash key
+        }
+
+        #endregion
+
+        #region Nested type: ListEntry
+
+        private class ListEntry
+        {
+            public bool MarkedForDeletion;
+            public bool Paused;
+            public int Priority;
+            public ICCSelectorProtocol Target;
+        }
+
+        #endregion
     }
-
-    public void ResumeTargets(List<ICCSelectorProtocol> targetsToResume)
-    {
-        foreach (ICCSelectorProtocol target in targetsToResume)
-        {
-            ResumeTarget(target);
-        }
-    }
-
-    public void PauseTarget(ICCSelectorProtocol target)
-    {
-        Debug.Assert(target != null);
-
-        // custom selectors
-        HashSelectorEntry entry;
-        if (m_pHashForSelectors.TryGetValue(target, out entry))
-        {
-            entry.Paused = true;
-        }
-
-        // Update selector
-        HashUpdateEntry updateEntry;
-        if (m_pHashForUpdates.TryGetValue(target, out updateEntry))
-        {
-            updateEntry.Entry.Paused = true;
-        }
-    }
-
-    public void ResumeTarget(ICCSelectorProtocol target)
-    {
-        Debug.Assert(target != null);
-
-        // custom selectors
-        HashSelectorEntry element;
-        if (m_pHashForSelectors.TryGetValue(target, out element))
-        {
-            element.Paused = false;
-        }
-
-        // Update selector
-        HashUpdateEntry elementUpdate;
-        if (m_pHashForUpdates.TryGetValue(target, out elementUpdate))
-        {
-            elementUpdate.Entry.Paused = false;
-        }
-    }
-
-    public bool IsTargetPaused(ICCSelectorProtocol target)
-    {
-        Debug.Assert(target != null, "target must be non nil");
-
-        // Custom selectors
-        HashSelectorEntry element;
-        if (m_pHashForSelectors.TryGetValue(target, out element))
-        {
-            return element.Paused;
-        }
-
-        return false; // should never get here
-    }
-
-    private void RemoveHashElement(HashSelectorEntry element)
-    {
-        m_pHashForSelectors.Remove(element.Target);
-
-        element.Timers.Clear();
-        element.Target = null;
-    }
-
-    private void RemoveUpdateFromHash(ListEntry entry)
-    {
-        HashUpdateEntry element;
-        if (m_pHashForUpdates.TryGetValue(entry.Target, out element))
-        {
-            // list entry
-            element.List.Remove(entry);
-            element.Entry = null;
-
-            // hash entry
-            m_pHashForUpdates.Remove(entry.Target);
-
-            element.Target = null;
-        }
-    }
-
-    private void PriorityIn(LinkedList<ListEntry> list, ICCSelectorProtocol target, int priority, bool paused)
-    {
-        var listElement = new ListEntry
-        {
-            Target = target,
-            Priority = priority,
-            Paused = paused,
-            MarkedForDeletion = false
-        };
-
-        if (list.First == null)
-        {
-            list.AddFirst(listElement);
-        }
-        else
-        {
-            bool added = false;
-            for (LinkedListNode<ListEntry> node = list.First; node != null; node = node.Next)
-            {
-                if (priority < node.Value.Priority)
-                {
-                    list.AddBefore(node, listElement);
-                    added = true;
-                    break;
-                }
-            }
-
-            if (!added)
-            {
-                list.AddLast(listElement);
-            }
-        }
-
-        // update hash entry for quick access
-        var hashElement = new HashUpdateEntry
-        {
-            Target = target,
-            List = list,
-            Entry = listElement
-        };
-
-        m_pHashForUpdates.Add(target, hashElement);
-    }
-
-    private void AppendIn(LinkedList<ListEntry> list, ICCSelectorProtocol target, bool paused)
-    {
-        var listElement = new ListEntry
-        {
-            Target = target,
-            Paused = paused,
-            MarkedForDeletion = false
-        };
-
-        list.AddLast(listElement);
-
-        // update hash entry for quicker access
-        var hashElement = new HashUpdateEntry
-        {
-            Target = target,
-            List = list,
-            Entry = listElement
-        };
-
-        m_pHashForUpdates.Add(target, hashElement);
-    }
-
-    #region Nested type: HashSelectorEntry
-
-    private class HashSelectorEntry
-    {
-        public CCTimer CurrentTimer;
-        public bool CurrentTimerSalvaged;
-        public bool Paused;
-        public ICCSelectorProtocol Target;
-        public int TimerIndex;
-        public List<CCTimer> Timers;
-    }
-
-    #endregion
-
-    #region Nested type: HashUpdateEntry
-
-    private class HashUpdateEntry
-    {
-        public ListEntry Entry; // entry in the list
-        public LinkedList<ListEntry> List; // Which list does it belong to ?
-        public ICCSelectorProtocol Target; // hash key
-    }
-
-    #endregion
-
-    #region Nested type: ListEntry
-
-    private class ListEntry
-    {
-        public bool MarkedForDeletion;
-        public bool Paused;
-        public int Priority;
-        public ICCSelectorProtocol Target;
-    }
-
-    #endregion
 }


fixes test

fixes test

--- src/Umbraco.Tests/Services/RelationServiceTests.cs
+++ src/Umbraco.Tests/Services/RelationServiceTests.cs
@@ -110,8 +110,8 @@
             Assert.AreEqual("Test", rt.Name);
             Assert.AreEqual("repeatedEventOccurence", rt.Alias);
             Assert.AreEqual(false, rt.IsBidirectional);
-            Assert.AreEqual(Constants.ObjectTypes.Document, rt.ChildObjectType.Value);
-            Assert.AreEqual(Constants.ObjectTypes.Media, rt.ParentObjectType.Value);
+            Assert.AreEqual(Constants.ObjectTypes.Document, rt.ParentObjectType.Value);
+            Assert.AreEqual(Constants.ObjectTypes.Media, rt.ChildObjectType.Value);
         }

         [Test]


When comparing versions in Release Manager, build first.

We *may* want to move this elsewhere at some point, but I wanted to
make minimal changes to start with.

--- tools/Google.Cloud.Tools.ReleaseManager/Program.cs
+++ tools/Google.Cloud.Tools.ReleaseManager/Program.cs
@@ -254,7 +254,12 @@
                 }
                 else
                 {
-                    idsToCheck.Add(diff.Id);
+                    // Found an API to compare. Build it locally first, so we know we're up-to-date.
+                    var api = diff.Id;
+                    idsToCheck.Add(api);
+                    Console.WriteLine($"Building {api} locally");
+                    var sourceRoot = DirectoryLayout.ForApi(api).SourceDirectory;
+                    Processes.RunDotnet(sourceRoot, "build", "-nologo", "-clp:NoSummary", "-v", "quiet", "-c", "Release", api);
                 }
             }
             CheckVersionCompatibility.Program.Main(idsToCheck.ToArray());


Switched to the new LoadWrapper class for asynchronous loading (LoadComponentAsync not used here since it's not possible to call that method on a component that has not finished loading, and we're in the constructor where it would be called)

--- osu.Game/Users/UserPanel.cs
+++ osu.Game/Users/UserPanel.cs
@@ -58,7 +58,7 @@

             Children = new Drawable[]
             {
-                new AsyncLoadWrapper(new UserCoverBackground(user)
+                new LoadWrapper(new UserCoverBackground(user)
                 {
                     RelativeSizeAxes = Axes.Both,
                     Anchor = Anchor.Centre,


Convert transition_duration to const

Convert transition_duration to const

--- osu.Game/Users/UserPanel.cs
+++ osu.Game/Users/UserPanel.cs
@@ -176,7 +176,7 @@

         private void displayStatus(UserStatus status)
         {
-            float transition_duration = 500;
+            const float transition_duration = 500;

             if (status == null)
             {


weekly workjob size fix

weekly workjob size fix

--- NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/WorkServiceTasks/CreateWorkJobWeeklyReport.cs
+++ NuGet.Services.Dashboard.Operations/Tasks/DashBoardTasks/WorkServiceTasks/CreateWorkJobWeeklyReport.cs
@@ -66,6 +66,7 @@
                 using (var reader = new StreamReader(respose.GetResponseStream()))
                 {
                     JavaScriptSerializer js = new JavaScriptSerializer();
+                    js.MaxJsonLength = Int32.MaxValue;
                     var objects = js.Deserialize<List<WorkJobInvocation>>(reader.ReadToEnd());
                     WorkJobInvocation lastJob;
                     string lastCompleted = string.Empty;


Comments added.

Comments added.

--- SimpleServiceLocator/SimpleInjector.Integration.Web.Mvc/SimpleInjectorFilterAttributeFilterProvider.cs
+++ SimpleServiceLocator/SimpleInjector.Integration.Web.Mvc/SimpleInjectorFilterAttributeFilterProvider.cs
@@ -26,6 +26,7 @@
     using System.Linq;
     using System.Web.Mvc;

+    // This is a better implementation https://bit.ly/1nrjnxD, but that would unfortunately be a breaking change.
     internal sealed class SimpleInjectorFilterAttributeFilterProvider : FilterAttributeFilterProvider
     {
         private readonly Container container;


Change: Issues handling

Change: Issues handling

--- src/reni2/Code/Container.cs
+++ src/reni2/Code/Container.cs
@@ -43,19 +43,13 @@

         [Node]
         [DisableDump]
-        internal Size MaxSize => Data?.TemporarySize ?? Size.Zero;
-
-        [Node]
-        [DisableDump]
         public static Container UnexpectedVisitOfPending { get; }
             = new Container(errorText: "UnexpectedVisitOfPending");

         public string GetCSharpStatements(int indent)
         {
-            if(HasIssues)
-                return "";
-            var generator = new CSharpGenerator(MaxSize.SaveByteCount);
-            Data.Visit(generator);
+            var generator = new CSharpGenerator(Data?.TemporarySize.SaveByteCount ?? 0);
+            Data?.Visit(generator);
             return generator.Data.Indent(indent);
         }
     }


storage integration test needs to be disabled as it requires some credentials i can't share

--- test/LogMagic.Test/SmokeAndMirrorsLogging.cs
+++ test/LogMagic.Test/SmokeAndMirrorsLogging.cs
@@ -7,14 +7,6 @@

 namespace LogMagic.Test
 {
-   public class AzureBlobWriterTest : SmokeAndMirrorsLogging
-   {
-      public AzureBlobWriterTest() : base("azure-blob")
-      {
-
-      }
-   }
-
    public class FilesWriterTest : SmokeAndMirrorsLogging
    {
       public FilesWriterTest() : base("files")
@@ -65,14 +57,6 @@

          switch (receiverName)
          {
-            case "azure-blob":
-               L.Config.WriteTo.StorageAppendBlob(
-                  StorageFactory.Blobs.AzureBlobStorage(new NetworkCredential(settings.AzureStorageName, settings.AzureStorageKey), "logmagic"),
-                  "smokeandmirrors");
-
-               //L.Config.WriteTo.AzureAppendBlob(settings.AzureStorageName, settings.AzureStorageKey,
-               //   "logs-integration", "smokeandmirrors");
-               break;
             case "files":
                L.Config.WriteTo.File(Path.Combine(TestDir.FullName, "subdir", "testlog.txt"));
                break;


Yet another code optimization

Yet another code optimization

git-svn-id: 6b7e1e5d0861e268462ba7828ef63c1bcab52a9b@940 d3cde5d6-82b8-4669-8b62-43054d6781d8

--- Radio/IirFilter.cs
+++ Radio/IirFilter.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Runtime.InteropServices;

 namespace SDRSharp.Radio
 {
@@ -13,6 +14,7 @@
     /// <summary>
     /// http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
     /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 16)]
     public sealed unsafe class IirFilter
     {
         private readonly float _a0;


Remove methods 4 now

Remove methods 4 now

--- TexasHoldEm/Bot.cs
+++ TexasHoldEm/Bot.cs
@@ -7,13 +7,13 @@

 	public static bool betOrFold(Gene gene) {
 		// True is bet, False is fold
-		double stateEval = gene.get(0) * getSelfWinProb() - gene.get(1) * getEnemyWinProb() + gene.get(2) * getPossibleWin() - gene.get(3) * getPossibleLoss();
+		double stateEval = gene.get(0) * getSelfWinProb() - gene.get(1) * getEnemyWinProb();// + gene.get(2) * getPossibleWin() - gene.get(3) * getPossibleLoss();
 		return stateEval > 0.0;
 	}

 	public static int makeBet(Gene gene) {
 		// returns the ammount to bet
-		double betEval = gene.get(6) * (gene.get(4) * getSelfWinProb() - gene.get(5) * getEnemyWinProb()) * ((gene.get(7) * getEnemyWinProb() > 0.5) ? 0.0 : 1.0);
+		double betEval = gene.get(6) * (gene.get(2) * getSelfWinProb() - gene.get(3) * getEnemyWinProb()) * ((gene.get(4) * getEnemyWinProb() > 0.5) ? 0.0 : 1.0);
 		return ((int) betEval * (GameStateWrapper.maxBet() - GameStateWrapper.minBet())) + GameStateWrapper.minBet();
 	}


Watchers.cs: add "ircs" into known URI schemes

Closes #29.

Signed-off-by: Alex Tereschenko <10ab4a620366487513eb6142e6429449f497066c@gmail.com>

--- Tomboy/Watchers.cs
+++ Tomboy/Watchers.cs
@@ -402,7 +402,7 @@
 		    		    @")))"+
 		    		    @"|\b)"+			    //  or at beginning of a word \b
 		    		    @"("+
-		    			@"(news|http|https|ftp|file|irc)://"+    // http:// ...
+		    			@"(news|http|https|ftp|file|irc|ircs)://"+    // http:// ...
 		    		        @"|mailto:"+				// or mailto...
 		    			@"|(www|ftp)\."+				// or www...
 		    		        @"|\S*@\S*\."+				// or email adress
@@ -499,7 +499,7 @@
 				      Path.Combine (Environment.GetEnvironmentVariable ("HOME"),
 				                    url.Substring (2));
 			else if (Regex.IsMatch (url,
-				@"^(?!(news|mailto|http|https|ftp|file|irc):).+@.{2,}$",
+				@"^(?!(news|mailto|http|https|ftp|file|irc|ircs):).+@.{2,}$",
 				RegexOptions.IgnoreCase))
 				url = "mailto:" + url;
 			else if (Regex.IsMatch (url,


[mac] Use hand cursor when hovering over links

MouseHandWatcher only changes the cursor to the hand cursor if Ctrl or
Shift is not pressed when hovering a link. That did not work on mac
because the modifiers obtained from GdkWindow had some modifiers set
although none of them were actually held down. We now use the
coordinates and modifiers from the event args.

https://bugzilla.gnome.org/show_bug.cgi?id=616317

--- Tomboy/Watchers.cs
+++ Tomboy/Watchers.cs
@@ -1010,13 +1010,6 @@
 		[GLib.ConnectBefore]
 		void OnEditorMotion (object sender, Gtk.MotionNotifyEventArgs args)
 		{
-			int pointer_x, pointer_y;
-			Gdk.ModifierType pointer_mask;
-
-			Window.Editor.GdkWindow.GetPointer (out pointer_x,
-			                                    out pointer_y,
-			                                    out pointer_mask);
-
 			bool hovering = false;

 			// Figure out if we're on a link by getting the text
@@ -1025,8 +1018,8 @@

 			int buffer_x, buffer_y;
 			Window.Editor.WindowToBufferCoords (Gtk.TextWindowType.Widget,
-			                                    pointer_x,
-			                                    pointer_y,
+			                                    (int)args.Event.X,
+			                                    (int)args.Event.Y,
 			                                    out buffer_x,
 			                                    out buffer_y);

@@ -1040,8 +1033,8 @@
 			}

 			// Don't show hand if Shift or Control is pressed
-			bool avoid_hand = (pointer_mask & (Gdk.ModifierType.ShiftMask |
-			                                   Gdk.ModifierType.ControlMask)) != 0;
+			bool avoid_hand = (args.Event.State & (Gdk.ModifierType.ShiftMask |
+			                                       Gdk.ModifierType.ControlMask)) != 0;

 			if (hovering != hovering_on_link) {
 				hovering_on_link = hovering;


non generic Deserialize

non generic Deserialize

--- Wire/Serializer.cs
+++ Wire/Serializer.cs
@@ -124,6 +124,13 @@
             var session = new SerializerSession(this);
             var s = GetDeserializerByManifest(stream, session);
             return (T) s.ReadValue(stream, session);
+        }
+
+        public object Deserialize(Stream stream)
+        {
+            var session = new SerializerSession(this);
+            var s = GetDeserializerByManifest(stream, session);
+            return s.ReadValue(stream, session);
         }

         public ValueSerializer GetSerializerByType(Type type)


Bring top nav in sync with main site

Bring top nav in sync with main site

Localization & Gallery were flipped in docs site

--- _SiteLayout.cshtml
+++ _SiteLayout.cshtml
@@ -31,8 +31,8 @@

Home

Download

Documentation

+
Localization

Gallery

-
Localization

Contribute

Discussions and Help

About Us


Test: CRLF-mess

Test: CRLF-mess

--- src/reni2/FeatureTest/UserInterface/TokenLocating.cs
+++ src/reni2/FeatureTest/UserInterface/TokenLocating.cs
@@ -2,7 +2,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using hw.Debug;
-using hw.Scanner;
 using hw.UnitTest;
 using Reni.UserInterface;

@@ -14,27 +13,24 @@
         [UnitTest]
         public void FromSourcePart()
         {
-            const string Text = @"(1,3,4,6)";
-            var compiler = new Compiler(text: Text);
+            const string text = @"(1,3,4,6)";
+            var compiler = new Compiler(text: text);
             var span = (compiler.Source + 2).Span(3);
-            var x = ((SyntaxToken)compiler.Containing(span)).SourceSyntax.SourcePart;
+            var x = ((SyntaxToken) compiler.Containing(span)).SourceSyntax.SourcePart;

             Tracer.Assert(x.Id == "1,3,4,6", x.Dump);
-
         }

         [UnitTest]
         public void CommentFromSourcePart()
         {
-            const string Text = @"( # Comment
+            const string text = @"( # Comment
 1,3,4,6)";
-            var compiler = new Compiler(text: Text);
+            var compiler = new Compiler(text: text);
             var span = (compiler.Source + 2).Span(3);
             var x = compiler.Containing(span);

-            Tracer.Assert(x.SourcePart.Id == "# Comment\r\n", x.Dump);
-
+            Tracer.Assert(x.SourcePart.Id.Replace("\r", "") == "# Comment\n", x.Dump);
         }
-
     }
 }


API: fix for missing results when distance not required

--- API/OCM.Net/OCM.API.Core/Data/CacheProviderMongoDB.cs
+++ API/OCM.Net/OCM.API.Core/Data/CacheProviderMongoDB.cs
@@ -640,8 +640,11 @@
                 }
                 else
                 {
-                    //filter by distance from lat/lon first
-                    poiList = poiList.Where(q => Query.Near("SpatialPosition", searchPoint, (double)settings.Distance * 1000).Inject());//.Take(settings.MaxResults);
+                    if (requiresDistance)
+                    {
+                        //filter by distance from lat/lon first
+                        poiList = poiList.Where(q => Query.Near("SpatialPosition", searchPoint, (double)settings.Distance * 1000).Inject());//.Take(settings.MaxResults);
+                    }
                 }

                 poiList = (from c in poiList


branch test

branch test

--- Advertise/Advertise.Web/Controllers/UserController.cs
+++ Advertise/Advertise.Web/Controllers/UserController.cs
@@ -13,5 +13,10 @@
         {
             return View();
         }
+
+        public virtual ActionResult List()
+        {
+            return View();
+        }
     }
 }


Remove unnecessary #if

Remove unnecessary #if

--- Assets/MRTK/Tools/MSBuild/Scripts/UnityProjectInfo.cs
+++ Assets/MRTK/Tools/MSBuild/Scripts/UnityProjectInfo.cs
@@ -221,10 +221,7 @@

             // Manually add special plugin dependencies to the projects
 #if UNITY_2019_3_OR_NEWER
-#if UNITY_2020_2_OR_NEWER
             if (toReturn.Name.StartsWith("Microsoft.MixedReality.Toolkit") || toReturn.Name.StartsWith("Unity.TextMeshPro"))
-#else
-            if (toReturn.Name.StartsWith("Microsoft.MixedReality.Toolkit"))
 #endif
             {
                 string[] plugins = SpecialPluginNameMappingUnity2019.Values.OrderByDescending(p => p).ToArray();
@@ -234,7 +231,6 @@
                     {
                         toReturn.AddDependency(projectInfo);
                     }
-#if UNITY_2020_2_OR_NEWER
                     else
                     {
                         CSProjectInfo newProjInfo = new CSProjectInfo(this, asmDefInfoMap[plugin], projectOutputPath);
@@ -245,7 +241,6 @@
                         projectsMap.Add(plugin, newProjInfo);
                         toReturn.AddDependency(newProjInfo);
                     }
-#endif
                 }
             }
 #endif


Bug: DateTime.toString(“r”) does not calculate offset

--- Assets/UniHttp/Support/Request/RequestPreprocessor.cs
+++ Assets/UniHttp/Support/Request/RequestPreprocessor.cs
@@ -70,7 +70,8 @@
 				request.Headers.Add("If-None-Match", cache.eTag);
 			}
 			if(cache.lastModified.HasValue) {
-				request.Headers.Add("If-Modified-Since", cache.lastModified.Value.ToString("r"));
+				DateTimeOffset modifiedSince = cache.lastModified.Value + cache.lastModified.Value.Offset;
+				request.Headers.Add("If-Modified-Since", modifiedSince.ToString("r"));
 			}
 		}
 	}


Fix gravity mispredict (#10017)

Fix gravity mispredict (#10017)

--- Content.Server/Gravity/EntitySystems/GravitySystem.cs
+++ Content.Server/Gravity/EntitySystems/GravitySystem.cs
@@ -46,21 +46,28 @@

         public void EnableGravity(GravityComponent comp)
         {
-            if (comp.Enabled) return;
+            if (comp.Enabled)
+                return;

             var gridId = Transform(comp.Owner).GridUid;
+            Dirty(comp);
+
             if (gridId == null)
                 return;

             comp.Enabled = true;
             var message = new GravityChangedEvent(gridId.Value, true);
             RaiseLocalEvent(message);
+
         }

         public void DisableGravity(GravityComponent comp)
         {
-            if (!comp.Enabled) return;
+            if (!comp.Enabled)
+                return;
+
             comp.Enabled = false;
+            Dirty(comp);

             var gridId = Transform(comp.Owner).GridUid;
             if (gridId == null)


fix-alt click (#5977)

fix-alt click (#5977)

--- Content.Shared/Interaction/SharedInteractionSystem.cs
+++ Content.Shared/Interaction/SharedInteractionSystem.cs
@@ -156,23 +156,21 @@

                 return;
             }
-            else
-            {
-                // We are close to the nearby object.
-                if (altInteract)
-                    // Perform alternative interactions, using context menu verbs.
-                    AltInteract(user, target.Value);
-
-                if (!hands.TryGetActiveHeldEntity(out var heldEntity))
-                {
-                    // Since our hand is empty we will use InteractHand/Activate
-                    InteractHand(user, target.Value);
-                }
-                else if (heldEntity != target)
-                {
-                    await InteractUsing(user, heldEntity.Value, target.Value, coordinates);
-                }
-
+
+            // We are close to the nearby object.
+            if (altInteract)
+            {
+                // Perform alternative interactions, using context menu verbs.
+                AltInteract(user, target.Value);
+            }
+            else if (!hands.TryGetActiveHeldEntity(out var heldEntity))
+            {
+                // Since our hand is empty we will use InteractHand/Activate
+                InteractHand(user, target.Value);
+            }
+            else if (heldEntity != target)
+            {
+                await InteractUsing(user, heldEntity.Value, target.Value, coordinates);
             }
         }


Bandaid fixtureless buttons (#11748)

Bandaid fixtureless buttons (#11748)

--- Content.Shared/Interaction/SharedInteractionSystem.cs
+++ Content.Shared/Interaction/SharedInteractionSystem.cs
@@ -451,7 +451,11 @@
             // that means we wouldn't be able to easily check overlap interactions.
             if (range > 0f &&
                 TryComp<FixturesComponent>(origin, out var fixtureA) &&
+                // These fixture counts are stuff that has the component but no fixtures for <reasons> (e.g. buttons).
+                // At least until they get removed.
+                fixtureA.FixtureCount > 0 &&
                 TryComp<FixturesComponent>(other, out var fixtureB) &&
+                fixtureB.FixtureCount > 0 &&
                 TryComp<TransformComponent>(origin, out var xformA) &&
                 TryComp<TransformComponent>(other, out var xformB))
             {


Refined query

Refined query

--- Core/OfficeDevPnP.Core/Extensions/TenantExtensions.cs
+++ Core/OfficeDevPnP.Core/Extensions/TenantExtensions.cs
@@ -71,7 +71,7 @@
                 var siteList = tenantContext.Web.Lists.GetByTitle("DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS");
                 var query = new CamlQuery()
                 {
-                    ViewXml = $"<View><Query><Where><And><Eq><FieldRef Name='HubSiteId' /><Value Type='Guid'>{hubsiteId}</Value></Eq><Neq><FieldRef Name='SiteId' /><Value Type='Guid'>{hubsiteId}</Value></Neq></And></Where></Query><ViewFields><FieldRef Name='SiteUrl'/></ViewFields></View>"
+                    ViewXml = $"<View><Query><Where><And><Eq><FieldRef Name='HubSiteId' /><Value Type='Guid'>{hubsiteId}</Value></Eq><And><Neq><FieldRef Name='SiteId' /><Value Type='Guid'>{hubsiteId}</Value></Neq><IsNull><FieldRef Name='TimeDeleted'/></IsNull></And></And></Where></Query><ViewFields><FieldRef Name='SiteUrl'/></ViewFields></View>"
                 };
                 var items = siteList.GetItems(query);
                 tenantContext.Load(items);


Update Version

Update Version

--- DLaB.VSSolutionAccelerator/Properties/AssemblyInfo.cs
+++ DLaB.VSSolutionAccelerator/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.2019.2.11")]
-[assembly: AssemblyFileVersion("1.2019.2.11")]
+[assembly: AssemblyVersion("1.2019.2.12")]
+[assembly: AssemblyFileVersion("1.2019.2.12")]


Don't forget to multiply by timescale

Don't forget to multiply by timescale

--- Assets/Microgames/DoorKnock/Scripts/DoorKnockFist.cs
+++ Assets/Microgames/DoorKnock/Scripts/DoorKnockFist.cs
@@ -24,7 +24,7 @@
         if (timer > 0) {
                 timer -= Time.deltaTime;
         } else if (MicrogameController.instance.getVictory()){
-            transform.localScale -= new Vector3(0.05f, 0.05f, 0.05f);
+            transform.localScale -= new Vector3(0.05f, 0.05f, 0.05f)*Time.timeScale;
             if (transform.localScale.x <= 0){
                 gameObject.SetActive(false);
             }


Wallet: Make account number an input instead of select (#3018)

--- BTCPayServer/Views/Stores/_GenerateWalletForm.cshtml
+++ BTCPayServer/Views/Stores/_GenerateWalletForm.cshtml
@@ -103,12 +103,7 @@
                 {

                         Account
-                        <select asp-for="AccountNumber" class="form-select w-auto">
-                            @for (var i = 0; i < 20; i++)
-                            {
-                                <option value="@i">@i</option>
-                            }
-                        </select>
+                        <input asp-for="AccountNumber" class="form-control" style="max-width:10ch" min="0" step="1">

                 }


Add subtasks to main screen on tasks

Add subtasks to main screen on tasks

--- BatteryCommander.Web/Views/Qualification/List.cshtml
+++ BatteryCommander.Web/Views/Qualification/List.cshtml
@@ -19,6 +19,7 @@
         GO
         NOGO
         UNKNOWN
+        Tasks

@@ -30,6 +31,12 @@
             @item.SoldierQualifications.Count(q => q.Status == QualificationStatus.Fail)
             @item.SoldierQualifications.Count(q => q.Status == QualificationStatus.Unknown)

+                @foreach (var task in item.Tasks)
+                {
+
@Html.DisplayFor(t => task)

+                }
+
+
                 @Html.ActionLink("View", "View", new { qualificationId = item.Id }) |
                 Bulk Update Soldiers


clear

clear

--- CSharpGL/OpenGLObjects/VertexBufferObjects/Buffer.cs
+++ CSharpGL/OpenGLObjects/VertexBufferObjects/Buffer.cs
@@ -10,8 +10,7 @@
     /// <summary>
     /// 顶点缓存（VBO）
     /// </summary>
-    ///// <typeparam name="T">此buffer存储的是哪种struct的数据？</typeparam>
-    public abstract class Buffer : IDisposable //where T : struct
+    public abstract class Buffer : IDisposable
     {
         protected static OpenGL.glGenBuffers glGenBuffers;
         protected static OpenGL.glBindBuffer glBindBuffer;
@@ -80,15 +79,6 @@
         }

         /// <summary>
-        ///
-        /// </summary>
-        /// <returns></returns>
-        public override string ToString()
-        {
-            return string.Format("VBO: {0}, usage: {1}", this.array, Usage);
-        }
-
-        /// <summary>
         /// 根据buffer内存放的具体的结构类型创建非托管数组。
         /// </summary>
         /// <param name="elementCount">数组元素的数目。</param>
@@ -102,6 +92,33 @@
         public void Alloc(int elementCount)
         {
             this.array = CreateElements(elementCount);
+        }
+
+        /// <summary>
+        /// 获取一个可渲染此VBO的渲染器。
+        /// </summary>
+        /// <returns></returns>
+        protected abstract BufferPtr Upload2GPU();
+
+        private BufferPtr bufferPtr = null;
+
+        /// <summary>
+        /// 获取一个可渲染此VBO的渲染器。
+        /// </summary>
+        /// <returns></returns>
+        public BufferPtr GetBufferPtr()
+        {
+            if (bufferPtr == null)
+            {
+                bufferPtr = Upload2GPU();
+            }
+
+            return bufferPtr;
+        }
+
+        public override string ToString()
+        {
+            return string.Format("VBO: {0}, usage: {1}", this.array, Usage);
         }

         public void Dispose()
@@ -139,28 +156,6 @@
             this.disposedValue = true;
         }

-
-        /// <summary>
-        /// 获取一个可渲染此VBO的渲染器。
-        /// </summary>
-        /// <returns></returns>
-        protected abstract BufferPtr Upload2GPU();
-
-        private BufferPtr bufferPtr = null;
-
-        /// <summary>
-        /// 获取一个可渲染此VBO的渲染器。
-        /// </summary>
-        /// <returns></returns>
-        public BufferPtr GetBufferPtr()
-        {
-            if (bufferPtr == null)
-            {
-                bufferPtr = Upload2GPU();
-            }
-
-            return bufferPtr;
-        }
     }

 }


reformat

reformat

--- CassandraSharp/ObjectMapper/SerializersExtensions.cs
+++ CassandraSharp/ObjectMapper/SerializersExtensions.cs
@@ -22,49 +22,21 @@
             new Dictionary<Type, Func<object, INameOrValue>>
                 {
                     {typeof(int), x => new IntNameOrValue((int) x)},
-                    {
-                        typeof(int?), x => null != x
-                                               ? new IntNameOrValue((int) x)
-                                               : null
-                        },
+                    {typeof(int?), x => null != x ? new IntNameOrValue((int) x) : null},
                     {typeof(long), x => new LongNameOrValue((long) x)},
-                    {
-                        typeof(long?), x => null != x
-                                                ? new LongNameOrValue((long) x)
-                                                : null
-                        },
+                    {typeof(long?), x => null != x ? new LongNameOrValue((long) x) : null},
                     {typeof(float), x => new FloatNameOrValue((float) x)},
-                    {
-                        typeof(float?), x => null != x
-                                                 ? new FloatNameOrValue((float) x)
-                                                 : null
-                        },
+                    {typeof(float?), x => null != x ? new FloatNameOrValue((float) x) : null},
                     {typeof(double), x => new DoubleNameOrValue((double) x)},
-                    {
-                        typeof(double?), x => null != x
-                                                  ? new DoubleNameOrValue((double) x)
-                                                  : null
-                        },
-                    {
-                        typeof(string), x => null != x
-                                                 ? new Utf8NameOrValue((string) x)
-                                                 : null
-                        },
+                    {typeof(double?), x => null != x ? new DoubleNameOrValue((double) x) : null},
+                    {typeof(string), x => null != x ? new Utf8NameOrValue((string) x): null},
                     {typeof(DateTime), x => new DateTimeNameOrValue((DateTime) x)},
-                    {
-                        typeof(DateTime?), x => null != x
-                                                    ? new DateTimeNameOrValue(((DateTime) x))
-                                                    : null
-                        },
+                    {typeof(DateTime?), x => null != x ? new DateTimeNameOrValue(((DateTime) x)) : null},
                     {typeof(byte[]), x => new ByteArrayNameOrValue((byte[]) x)},
                     {typeof(Decimal), x => null},
                     {typeof(Decimal?), x => null},
                     {typeof(Guid), x => new GuidNameOrValue((Guid) x)},
-                    {
-                        typeof(Guid?), x => null != x
-                                                ? new GuidNameOrValue((Guid) x)
-                                                : null
-                        },
+                    {typeof(Guid?), x => null != x ? new GuidNameOrValue((Guid) x) : null},
                 };

         private static readonly Dictionary<Type, Func<byte[], INameOrValue>> _netType2NameOrValueFromByteArray =


Updated the timeout logic so it won't take excess CPU time. #16

--- CodeOnlyStoredProcedure/StoredProcedureExtensions.cs
+++ CodeOnlyStoredProcedure/StoredProcedureExtensions.cs
@@ -17,6 +17,16 @@
     public static partial class StoredProcedureExtensions
     {
         #region WithParameter
+        /// <summary>
+        /// Adds an input parameter to the stored procedure.
+        /// </summary>
+        /// <typeparam name="TSP">The type of StoredProcedure. Can be a StoredProcedure with or without results.</typeparam>
+        /// <typeparam name="TValue">The type of value to pass.</typeparam>
+        /// <param name="sp">The StoredProcedure to add the input parameter to</param>
+        /// <param name="name">The name that the StoredProcedure expects (without the @).</param>
+        /// <param name="value">The value to pass.</param>
+        /// <returns>A copy of the StoredProcedure with the input parameter passed.</returns>
+        /// <remarks>StoredProcedures are immutable, so all the Fluent API methods return copies.</remarks>
         public static TSP WithParameter<TSP, TValue>(this TSP sp, string name, TValue value)
             where TSP : StoredProcedure
         {
@@ -27,6 +37,17 @@
             return (TSP)sp.CloneWith(new SqlParameter(name, value));
         }

+        /// <summary>
+        /// Adds an input parameter to the stored procedure.
+        /// </summary>
+        /// <typeparam name="TSP">The type of StoredProcedure. Can be a StoredProcedure with or without results.</typeparam>
+        /// <typeparam name="TValue">The type of value to pass.</typeparam>
+        /// <param name="sp">The StoredProcedure to add the input parameter to</param>
+        /// <param name="name">The name that the StoredProcedure expects (without the @).</param>
+        /// <param name="value">The value to pass.</param>
+        /// <param name="dbType">The SqlDbType that the StoredProcedure expects.</param>
+        /// <returns>A copy of the StoredProcedure with the input parameter passed.</returns>
+        /// <remarks>StoredProcedures are immutable, so all the Fluent API methods return copies.</remarks>
         public static TSP WithParameter<TSP, TValue>(this TSP sp, string name, TValue value, SqlDbType dbType)
             where TSP : StoredProcedure
         {
@@ -377,36 +398,39 @@
             // execute in a background task, so we can cancel the command if the
             // CancellationToken is cancelled, or the command times out
             var readerTask = Task.Factory.StartNew(() => exec(cmd), token);
-
-            Stopwatch sw = null;
-            var timeout = cmd.CommandTimeout;
-            if (timeout > 0)
-                sw = Stopwatch.StartNew();
-            var continueWaiting = true;
-            while (continueWaiting)
-            {
-                Thread.SpinWait(1);
-                switch (readerTask.Status)
-                {
-                    case TaskStatus.Faulted:
-                        throw readerTask.Exception.InnerException;
-
-                    case TaskStatus.Canceled:
-                    case TaskStatus.RanToCompletion:
-                        continueWaiting = false;
-                        break;
+
+            try
+            {
+                var timeout = cmd.CommandTimeout;
+                if (timeout > 0)
+                {
+                    if (!readerTask.Wait(timeout * 1000, token) && !readerTask.IsCompleted)
+                    {
+                        cmd.Cancel();
+                        throw new TimeoutException();
+                    }
+
+                    if (token.IsCancellationRequested && !readerTask.IsCompleted)
+                        cmd.Cancel();
                 }
-
-                if (token.IsCancellationRequested)
-                {
-                    cmd.Cancel();
-                    continueWaiting = false;
+                else
+                    readerTask.Wait(token);
+            }
+            catch (AggregateException ex)
+            {
+                if (ex.InnerExceptions.Count() == 1)
+                {
+                    if (!(ex.InnerException is OperationCanceledException))
+                        throw;
+                    else
+                        cmd.Cancel();
                 }
-                else if (timeout > 0 && sw.Elapsed.TotalSeconds > timeout)
-                {
-                    cmd.Cancel();
-                    throw new TimeoutException("The stored procedure " + cmd.CommandText + " has not returned after " + cmd.CommandTimeout + " seconds.");
-                }
+                else
+                    throw;
+            }
+            catch (OperationCanceledException)
+            {
+                cmd.Cancel();
             }

             token.ThrowIfCancellationRequested();


Testing Appveyor take 1

Testing Appveyor take 1

Appveyor, why are you giving me NullReferenceException?

--- Core/System/Threading/Tasks/ITaskCompletionAction.cs
+++ Core/System/Threading/Tasks/ITaskCompletionAction.cs
@@ -108,20 +108,48 @@

             public void Invoke(Task completingTask)
             {
-                var tasks = Interlocked.CompareExchange(ref _tasks, null, null);
-                if (tasks == null)
-                {
-                    return;
-                }
-                var index = Array.IndexOf(tasks, completingTask);
-                if (index >= 0)
-                {
-                    tasks[index] = null;
-                }
-                var count = Interlocked.Decrement(ref _count);
-                if (count == 0 && Thread.VolatileRead(ref _ready) == 1)
-                {
-                    Done();
+                Task[] tasks = null;
+                var index = -1;
+                try
+                {
+                    tasks = Interlocked.CompareExchange(ref _tasks, null, null);
+                    if (tasks == null)
+                    {
+                        return;
+                    }
+                    index = Array.IndexOf(tasks, completingTask);
+                }
+                catch (NullReferenceException ex)
+                {
+                    Console.WriteLine("-A-");
+                    Console.WriteLine(ex);
+                    Console.WriteLine("---");
+                    Console.WriteLine(ex.StackTrace);
+                    // Eat it
+                }
+                try
+                {
+                    if (tasks == null)
+                    {
+                        return;
+                    }
+                    if (index >= 0)
+                    {
+                        tasks[index] = null;
+                    }
+                    var count = Interlocked.Decrement(ref _count);
+                    if (count == 0 && Thread.VolatileRead(ref _ready) == 1)
+                    {
+                        Done();
+                    }
+                }
+                catch (NullReferenceException ex)
+                {
+                    Console.WriteLine("-B-");
+                    Console.WriteLine(ex);
+                    Console.WriteLine("---");
+                    Console.WriteLine(ex.StackTrace);
+                    // Eat it
                 }
             }


support encoding on CreateFile

support encoding on CreateFile

--- src/MvbaCore/Services/FileSystemService.cs
+++ src/MvbaCore/Services/FileSystemService.cs
@@ -30,7 +30,7 @@
 		DirectoryInfo CreateDirectory([NotNull] string directoryPath);

 		[NotNull]
-		StreamWriter CreateFile([NotNull] string filePath);
+		StreamWriter CreateFile([NotNull] string filePath, Encoding encoding = null);

 		[NotNull]
 		TextWriter CreateTextFile([NotNull] string filePath);
@@ -151,11 +151,14 @@
 			return match == null ? Directory.GetDirectories(dirPath) : Directory.GetDirectories(dirPath, match, option);
 		}

-		public StreamWriter CreateFile(string filePath)
+		public StreamWriter CreateFile(string filePath, Encoding encoding = null)
 		{
 			try
 			{
-				return new StreamWriter(new FileStream(filePath, FileMode.Create, FileAccess.Write));
+				return encoding == null
+					? new StreamWriter(new FileStream(filePath, FileMode.Create, FileAccess.Write))
+					: new StreamWriter(new FileStream(filePath, FileMode.Create, FileAccess.Write), encoding)
+					;
 			}
 			catch (DirectoryNotFoundException exception)
 			{


Change: Updated the Android port to use the new initialization constructor

--- src/MysticChronicles.Droid/MainActivity.cs
+++ src/MysticChronicles.Droid/MainActivity.cs
@@ -4,6 +4,7 @@
 using Android.Views;

 using MysticChronicles.Engine;
+using MysticChronicles.Library.Game.GameStates;

 namespace MysticChronicles
 {
@@ -20,7 +21,7 @@
         protected override void OnCreate(Bundle bundle)
         {
             base.OnCreate(bundle);
-            var g = new MainGame();
+            var g = new MainGame(MysticChronicles.Library.Game.Common.Constants.GAME_NAME, typeof(MainMenuState));
             SetContentView((View)g.Services.GetService(typeof(View)));
             g.Run();
         }


rename var

rename var

--- src/NLog/Config/XmlLoggingConfiguration.cs
+++ src/NLog/Config/XmlLoggingConfiguration.cs
@@ -431,7 +431,7 @@
             var children = nlogElement.Children;

             //first load the extensions, as the can be used in other elements (targets etc)
-            var extensionsChilds = children.Where(el => el.LocalName.Equals("EXTENSIONS", StringComparison.InvariantCultureIgnoreCase));
+            var extensionsChilds = children.Where(child => child.LocalName.Equals("EXTENSIONS", StringComparison.InvariantCultureIgnoreCase));
             foreach (var extensionsChild in extensionsChilds)
             {
                 this.ParseExtensionsElement(extensionsChild, baseDirectory);


changed debate model

changed debate model

--- DebateAppDB/DebateAppDB.dbRest/Models/DebateModel.cs
+++ DebateAppDB/DebateAppDB.dbRest/Models/DebateModel.cs
@@ -9,25 +9,29 @@
 {
     public class DebateModel
     {
-        public int Debate_id { get; set; }
-        public string DebateString { get; set; }
-        //add properties
-        //private Dictionary<int, object> debates = new Dictionary<int, object>();
+        /*public int Debate_id { get; set; }
+        public string DebateString { get; set; }*/
+        public object d { get; set; }
+
         private string path = Directory.GetCurrentDirectory() + @"\DebateStrings.txt";
-        //add function to write into file
+
+
+
         public void AddDebate(DebateModel debate)//object debate)
         {
+            //var definition = new { Name = "" };
             //add and return the max id
-            string s = File.ReadAllText(path);
+            string debates = File.ReadAllText(path);
             //var max = debates.Max(x => x.Key);

-            var DebateList = JsonConvert.DeserializeObject<List<DebateModel>>(s);
+            var DebateList = JsonConvert.DeserializeObject<List<DebateModel>>(debates);

+            //var DebateList = JsonConvert.DeserializeAnonymousType(s, definition);
+
             try
             {
                 DebateList.Add(debate);
                 //debates.Add(max + 1, debate);
-
             }
             catch (Exception e)
             {
@@ -38,9 +42,9 @@

                 //debates.Add(max + 1, debate);
             }
-
-            var max = DebateList.Max(x => x.Debate_id);
-            debate.Debate_id = max + 1;
+
+            /*var max = DebateList.Max(x => x.Debate_id);
+            debate.Debate_id = max + 1;*/

             var NewList = JsonConvert.SerializeObject(DebateList);
             File.WriteAllText(path, NewList);
@@ -49,7 +53,7 @@

         ///-------------------------------------------

-        public void AddDebate(string debate)//object debate)
+       /* public void AddDebate(string debate)//object debate)
         {
             //add and return the max id
             string s = File.ReadAllText(path);
@@ -79,7 +83,7 @@

             var NewList = JsonConvert.SerializeObject(DebateList);
             File.WriteAllText(path, NewList);
-        }
+        }*/

         public List<DebateModel> GetAllDebates()
         {
@@ -91,10 +95,9 @@

         public DebateModel GetDebate(int id)
         {
-            string s = File.ReadAllText(path);
-            var DebateList = JsonConvert.DeserializeObject<List<DebateModel>>(s);
-
-            var debate = DebateList.FindAll(x => x.Debate_id == id).SingleOrDefault();
+            string debates = File.ReadAllText(path);
+            var DebateList = JsonConvert.DeserializeObject<List<DebateModel>>(debates);
+            var debate = DebateList.ElementAt(id);//DebateList.FindAll(x => x.Debate_id == id).SingleOrDefault();
             //var debateString = JsonConvert.SerializeObject(debate);

             return debate;
@@ -102,23 +105,31 @@

         public void UpdateDebate(int id, object newInfo)
         {
-            string s = File.ReadAllText(path);
-            var DebateList = JsonConvert.DeserializeObject<List<DebateModel>>(s);
+            string debates = File.ReadAllText(path);
+            var DebateList = JsonConvert.DeserializeObject<List<DebateModel>>(debates);

-            var debate = DebateList.FindAll(x => x.Debate_id == id).SingleOrDefault();
-           // debate.DebateString = newInfo;
+            var debate = DebateList.ElementAt(id);//.FindAll(x => x.Debate_id == id).SingleOrDefault();
+                                                  // debate.DebateString = newInfo;
+            debate.d = newInfo;

             var NewList = JsonConvert.SerializeObject(DebateList);
             File.WriteAllText(path, NewList);
         }

-        public int GetMaxIndex()
+        /*public int GetMaxIndex()
         {
             string s = File.ReadAllText(path);
             var DebateList = JsonConvert.DeserializeObject<List<DebateModel>>(s);
             var max = DebateList.Max(x => x.Debate_id);

             return max;
+        }*/
+        public void DeleteDebate(int id)
+        {
+            string debates = File.ReadAllText(path);
+            var DebateList = JsonConvert.DeserializeObject<List<DebateModel>>(debates);
+
+            DebateList.RemoveAt(id);
         }
     }
 }


Converted readonly properties with backing field to auto-properties.

--- src/NLog/Targets/DateAndSequenceArchive.cs
+++ src/NLog/Targets/DateAndSequenceArchive.cs
@@ -40,35 +40,23 @@
     /// </summary>
     internal class DateAndSequenceArchive
     {
-        private readonly string _fileName;
-        private readonly DateTime _date;
         private readonly string _dateFormat;
-        private readonly int _sequence;
         private readonly string _formattedDate;

         /// <summary>
         /// The full name of the archive file.
         /// </summary>
-        public string FileName
-        {
-            get { return _fileName; }
-        }
+        public string FileName { get; private set; }

         /// <summary>
         /// The parsed date contained in the file name.
         /// </summary>
-        public DateTime Date
-        {
-            get { return _date; }
-        }
+        public DateTime Date { get; private set; }

         /// <summary>
         /// The parsed sequence number contained in the file name.
         /// </summary>
-        public int Sequence
-        {
-            get { return _sequence; }
-        }
+        public int Sequence { get; private set; }

         /// <summary>
         /// Determines whether <paramref name="date"/> produces the same string as the current instance's date once formatted with the current instance's date format.
@@ -88,10 +76,10 @@
             if (fileName == null) throw new ArgumentNullException("fileName");
             if (dateFormat == null) throw new ArgumentNullException("dateFormat");

-            _date = date;
+            Date = date;
             _dateFormat = dateFormat;
-            _sequence = sequence;
-            _fileName = fileName;
+            Sequence = sequence;
+            FileName = fileName;
             _formattedDate = date.ToString(dateFormat);
         }
     }