add test Test_HTMLBinding_Basic_TwoWay_Collection_string

--- Tests/Test_HTMLBinding.cs
+++ Tests/Test_HTMLBinding.cs
@@ -1971,42 +1971,71 @@
             await RunAsync(test);
         }

-        //[Fact]
-        //public void Test_HTMLBinding_Basic_TwoWay_Long_ShouldOK()
-        //{
-        //    using (Tester())
-        //    {
-
-        //        bool isValidSynchronizationContext = (_SynchronizationContext != null) && (_SynchronizationContext.GetType() != typeof(SynchronizationContext));
-        //        isValidSynchronizationContext.Should().BeTrue();
-
-        //        var datacontext = new VMwithlong() { longValue = 45 };
-
-        //        using (var mb = AwesomeBinding.Bind(_WebView, datacontext, JavascriptBindingMode.TwoWay).Result)
-        //        {
-        //            var js = mb.JSRootObject;
-
-        //            JSValue res = GetSafe(() => Get(js, "longValue"));
-        //            res.Should().NotBeNull();
-        //            res.IsNumber.Should().BeTrue();
-        //            var doublev = (long)res;
-        //            doublev.Should().Be(45);
-
-        //            this.DoSafe(() => js.Invoke("longValue", 24524));
-        //            Thread.Sleep(100);
-
-        //            datacontext.longValue.Should().Be(24524);
-
-        //            res = GetSafe(() => Get(js, "longValue"));
-        //            res.Should().NotBeNull();
-        //            res.IsNumber.Should().BeTrue();
-        //            doublev = (long)res;
-        //            long half = 24524;
-        //            doublev.Should().Be(half);
-        //        }
-        //    }
-        //}
-
+
+
+        [Fact]
+        public async Task Test_HTMLBinding_Basic_TwoWay_Collection_string()
+        {
+            var datacontext = new VMWithList<string>();
+
+            var test = new TestInContext()
+            {
+                Bind = (win) => HTML_Binding.Bind(win, datacontext, JavascriptBindingMode.TwoWay),
+                Test = (mb) =>
+                {
+                    var js = mb.JSRootObject;
+
+                    CefV8Value col = GetSafe(() => UnWrapCollection(js, "List"));
+                    col.GetArrayLength().Should().Be(0);
+
+                    Checkstring(col, datacontext.List);
+
+                    datacontext.List.Add("titi");
+
+                    Thread.Sleep(100);
+                    col = GetSafe(() => UnWrapCollection(js, "List"));
+
+                    Checkstring(col, datacontext.List);
+
+                    datacontext.List.Add("kiki");
+                    datacontext.List.Add("toto");
+
+                    Thread.Sleep(100);
+                    col = GetSafe(() => UnWrapCollection(js, "List"));
+
+                    Checkstring(col, datacontext.List);
+
+                    Thread.Sleep(100);
+                    col = GetSafe(() => UnWrapCollection(js, "List"));
+
+                    Checkstring(col, datacontext.List);
+
+                    var comp = new List<string>(datacontext.List);
+                    comp.Add("newvalue");
+
+                    col = GetSafe(() => UnWrapCollection(js, "List"));
+                    var chcol = GetAttribute(js, "List");
+                    Call(chcol, "push", CefV8Value.CreateString("newvalue"));
+
+                    Thread.Sleep(350);
+
+                    col = GetSafe(() => UnWrapCollection(js, "List"));
+
+                    datacontext.List.Should().Equal(comp);
+                    Checkstring(col, datacontext.List);
+
+                    datacontext.List.Clear();
+                    Thread.Sleep(100);
+                    col = GetSafe(() => UnWrapCollection(js, "List"));
+
+                    Checkstring(col, datacontext.List);
+                }
+            };
+
+            await RunAsync(test);
+        }
+
+
         //[Fact]
         //public void Test_HTMLBinding_Basic_TwoWay_Collection_string()
         //{


Tweaked badge order, badge state no longer saved


Started setting up VLQ tests.

Started setting up VLQ tests.

--- Tests/UnsignedVlqTests.cs
+++ Tests/UnsignedVlqTests.cs
@@ -1,11 +1,166 @@
 using System;
+using InvertedTomato.Serialization.LightWeightSerialization;
 using Xunit;

 namespace Tests {
 	public class UnsignedVlqTests {
 		[Fact]
-		public void Test() {
-			throw new NotImplementedException();
+		public void Encode0() {
+			Assert.Equal(new Byte[] {0b00000000}, UnsignedVlq.Encode(0));
+		}
+
+		[Fact]
+		public void Encode1() {
+			Assert.Equal(new Byte[] {0b00000001}, UnsignedVlq.Encode(1));
+		}
+
+		[Fact]
+		public void Encode2() {
+			Assert.Equal(new Byte[] {0b00000010}, UnsignedVlq.Encode(2));
+		}
+
+		[Fact]
+		public void Encode3() {
+			Assert.Equal(new Byte[] {0b00000011}, UnsignedVlq.Encode(3));
+		}
+
+		[Fact]
+		public void Encode127() {
+			Assert.Equal(new Byte[] {0b01111111}, UnsignedVlq.Encode(127));
+		}
+
+		[Fact]
+		public void Encode128() {
+			Assert.Equal(new Byte[] {0b10000000, 0b00000000}, UnsignedVlq.Encode(128));
+		}
+
+		[Fact]
+		public void Encode129() {
+			Assert.Equal(new Byte[] {0b10000001, 0b00000000}, UnsignedVlq.Encode(129));
+		}
+
+		[Fact]
+		public void Encode16511() {
+			Assert.Equal(new Byte[] {0b10000000, 0b01111111}, UnsignedVlq.Encode(16511));
+		}
+
+		[Fact]
+		public void Encode16512() {
+			Assert.Equal(new Byte[] {0b10000000, 0b10000000, 0b00000000}, UnsignedVlq.Encode(16512));
+		}
+
+		[Fact]
+		public void Encode2113663() {
+			Assert.Equal(new Byte[] {0b11111111, 0b11111111, 0b01111111}, UnsignedVlq.Encode(2113663));
+		}
+
+		[Fact]
+		public void Encode2113664() {
+			Assert.Equal(new Byte[] {0b10000000, 0b10000000, 0b10000000, 0b00000000}, UnsignedVlq.Encode(2113664));
+		}
+
+		[Fact]
+		public void EncodeMax() {
+			Assert.Equal(new Byte[] {0b11111110, 0b11111110, 0b11111110, 0b11111110,0b11111110, 0b11111110, 0b11111110, 0b11111110, 0b11111110, 0b00000000,}, UnsignedVlq.Encode(UnsignedVlq.MaxValue));
+		}
+
+		[Fact]
+		public void EncodeOverflow() {
+			Assert.Throws<OverflowException>(() => { UnsignedVlq.Encode(UInt64.MaxValue); });
+		}
+
+
+		[Fact]
+		public void Decode0() {
+			Assert.Equal((UInt64) 0, DecompressOne("10000000", 1));
+		}
+
+		[Fact]
+		public void Decode1() {
+			Assert.Equal((UInt64) 1, DecompressOne("10000001", 1));
+		}
+
+		[Fact]
+		public void Decode2() {
+			Assert.Equal((UInt64) 2, DecompressOne("10000010", 1));
+		}
+
+		[Fact]
+		public void Decode3() {
+			Assert.Equal((UInt64) 3, DecompressOne("10000011", 1));
+		}
+
+		[Fact]
+		public void Decode127() {
+			Assert.Equal((UInt64) 127, DecompressOne("11111111", 1));
+		}
+
+		[Fact]
+		public void Decode128() {
+			Assert.Equal((UInt64) 128, DecompressOne("00000000 10000000", 2));
+		}
+
+		[Fact]
+		public void Decode129() {
+			Assert.Equal((UInt64) 129, DecompressOne("00000001 10000000", 2));
+		}
+
+		[Fact]
+		public void Decode16511() {
+			Assert.Equal((UInt64) 16511, DecompressOne("01111111 11111111", 2));
+		}
+
+		[Fact]
+		public void Decode16512() {
+			Assert.Equal((UInt64) 16512, DecompressOne("00000000 00000000 10000000", 3));
+		}
+
+		[Fact]
+		public void Decode16513() {
+			Assert.Equal((UInt64) 16513, DecompressOne("00000001 00000000 10000000", 3));
+		}
+
+		[Fact]
+		public void Decode2113663() {
+			Assert.Equal((UInt64) 2113663, DecompressOne("01111111 01111111 11111111", 3));
+		}
+
+		[Fact]
+		public void Decode2113664() {
+			Assert.Equal((UInt64) 2113664, DecompressOne("00000000 00000000 00000000 10000000", 4));
+		}
+
+		[Fact]
+		public void DecodeMax() {
+			Assert.Equal(VLQCodec.MaxValue, DecompressOne("01111110 01111110 01111110 01111110 01111110 01111110 01111110 01111110 01111110 10000000", 10));
+		}
+
+		[Fact]
+		public void Decode1_1_1() {
+			var set = DecompressMany("10000001 10000001 10000001", 3, 3);
+			Assert.Equal(3, set.Length);
+			Assert.Equal((UInt64) 1, set[0]);
+			Assert.Equal((UInt64) 1, set[1]);
+			Assert.Equal((UInt64) 1, set[2]);
+		}
+
+		[Fact]
+		public void DecodeInputClipped() {
+			Assert.Throws<EndOfStreamException>(() => {
+				var input = new MemoryStream(BitOperation.ParseToBytes("00000000"));
+				var output = Codec.DecompressUnsigned(input, 1).ToArray();
+			});
+		}
+
+		[Fact]
+		public void DecodeOverflow() {
+			Assert.Throws<OverflowException>(() => { DecompressOne("01111111 01111110 01111110 01111110 01111110 01111110 01111110 01111110 01111110 01111110 10000000", 11); });
+		}
+
+		[Fact]
+		public void Decode1_X() {
+			var input = new MemoryStream(BitOperation.ParseToBytes("10000001 00000011"));
+			Assert.Equal((UInt64) 1, Codec.DecompressUnsigned(input, 1).Single());
 		}
 	}
 }


WIP #258 - Add test coverage for cloning elements

--- ZptSharp.Tests/Dom/HapElementTests.cs
+++ ZptSharp.Tests/Dom/HapElementTests.cs
@@ -10,6 +10,8 @@
     [TestFixture,Parallelizable]
     public class HapElementTests
     {
+        #region ToString
+
         [Test]
         public void ToString_returns_HTML_open_tag()
         {
@@ -17,7 +19,11 @@
             Assert.That(() => HapDocumentUtil.GetNode(html).ToString(), Is.EqualTo(html));
         }

-        [Test,AutoMoqData]
+        #endregion
+
+        #region IsInNamespace
+
+        [Test, AutoMoqData]
         public void IsInNamespace_returns_false_when_element_has_no_namespace_prefix(WellKnownNamespaceProvider namespaces)
         {
             var html = @"
";
@@ -37,6 +43,10 @@
             var html = @"<metal:div class=""foo"" tal:repeat=""item items"">";
             Assert.That(() => HapDocumentUtil.GetNode(html).IsInNamespace(namespaces.TalNamespace), Is.False);
         }
+
+        #endregion
+
+        #region ChildNodes

         [Test]
         public void Adding_a_child_node_modifies_native_document()
@@ -61,6 +71,10 @@
             Assert.That(element.NativeElement.OuterHtml, Is.EqualTo("

"));
         }

+        #endregion
+
+        #region Attributes
+
         [Test]
         public void Adding_an_attribute_modifies_native_document()
         {
@@ -82,5 +96,41 @@
             Assert.That(element.NativeElement.OuterHtml, Is.EqualTo("

"));
         }

+        #endregion
+
+        #region GetCopy
+
+        [Test, AutoMoqData]
+        public void GetCopy_returns_deep_copy_of_selected_node()
+        {
+            var html = @"

Hello there

Another paragraph

";
+            var htmlElement = HapDocumentUtil.GetNode(html);
+            var bodyElement = htmlElement.ChildNodes.First();
+            var result = (HapElement) bodyElement.GetCopy();
+
+            Assert.That(result.NativeElement.OuterHtml, Is.EqualTo(@"

Hello there

Another paragraph

"));
+        }
+
+        [Test, AutoMoqData]
+        public void GetCopy_deep_copies_source_info_line_numbers()
+        {
+            var html = @"
+
+

+
Hello there

+
Another paragraph

+

+
+";
+            var htmlElement = HapDocumentUtil.GetNode(html);
+            var bodyElement = htmlElement.ChildNodes.Skip(1).First();
+
+            var result = bodyElement.GetCopy();
+
+            var testElement = result.ChildNodes.Skip(1).First().ChildNodes.Skip(1).First();
+            Assert.That(testElement.SourceInfo?.LineNumber, Is.EqualTo(4));
+        }
+
+        #endregion
     }
 }


Removed a debug thing that I'd forgotten to remove once I was done with that thing.

--- UIconEdit/IconFileBase.cs
+++ UIconEdit/IconFileBase.cs
@@ -188,7 +188,7 @@
                             #endregion
                             isPng = true;
                         }
-                        else
+                        else if (dibSize == MinDibSize)
                         {
                             #region Load Bmp
                             using (OffsetStream ms = new OffsetStream(input, entry.ResourceLength - 4, true))
@@ -261,21 +261,17 @@
                             }
                             #endregion
                         }
+                        else throw new InvalidDataException();

                         Debug.WriteLine("Reading type {0}, width:{1}, height:{2}, bit depth:{3}",
                             isPng ? "PNG" : "BMP", loadedImage.Width, loadedImage.Height, bitDepth);

-                        IconFrame frame; try
-                        {
-                            if (id == IconTypeCode.Cursor)
-                                frame = new CursorFrame(bitDepth, loadedImage, entry.XPlanes, entry.YBitsPerpixel);
-                            else
-                                frame = new IconFrame(bitDepth, loadedImage);
-                        }
-                        catch (InvalidDataException) { throw; }
-                        catch (ObjectDisposedException) { throw; }
-                        catch (IOException) { throw; }
-                        catch { throw new InvalidDataException(); }
+                        IconFrame frame;
+
+                        if (id == IconTypeCode.Cursor)
+                            frame = new CursorFrame(bitDepth, loadedImage, entry.XPlanes, entry.YBitsPerpixel);
+                        else
+                            frame = new IconFrame(bitDepth, loadedImage);

                         if (!returner.FrameCollection.Add(frame))
                         {
@@ -285,7 +281,10 @@
                         offset += entry.ResourceLength;
                     }
                 }
-                finally { }
+                catch (InvalidDataException) { throw; }
+                catch (ObjectDisposedException) { throw; }
+                catch (IOException) { throw; }
+                catch { throw new InvalidDataException(); }

                 return returner;
             }


Whoops! I got an exception-throw in IconFileBase backwards.

--- UIconEdit/IconFileBase.cs
+++ UIconEdit/IconFileBase.cs
@@ -223,7 +223,7 @@
                                     default:
                                         throw new InvalidDataException();
                                 }
-                                if (bitDepth != BitDepth.Bit32 && (height & 1) != 1)
+                                if (bitDepth != BitDepth.Bit32 && (height & 1) == 1)
                                     throw new InvalidDataException();

                                 if (loadedId != IconTypeCode.Cursor && bitsPerPixel != entry.YBitsPerpixel)


Add request  exception details to log.

Add request  exception details to log.

--- src/Certify.Core/Management/CertifyManager.cs
+++ src/Certify.Core/Management/CertifyManager.cs
@@ -50,7 +50,7 @@
         }

         /// <summary>
-        /// Check if we have one or more managed sites setup
+        /// Check if we have one or more managed sites setup
         /// </summary>
         public bool HasManagedSites
         {
@@ -104,7 +104,7 @@
         }

         /// <summary>
-        /// Test dummy method for async UI testing etc
+        /// Test dummy method for async UI testing etc
         /// </summary>
         /// <param name="vaultManager"></param>
         /// <param name="managedSite"></param>
@@ -142,7 +142,7 @@
         }

         /// <summary>
-        /// Remove other contacts which don't match the email address given
+        /// Remove other contacts which don't match the email address given
         /// </summary>
         /// <param name="email"></param>
         /// <returns></returns>
@@ -454,7 +454,7 @@
                 catch (Exception exp)
                 {
                     result.IsSuccess = false;
-                    result.Message = managedSite.Name + ": Request failed - " + exp.Message;
+                    result.Message = managedSite.Name + ": Request failed - " + exp.Message + " " + exp.ToString();
                     LogMessage(managedSite.Id, result.Message, LogItemType.CertficateRequestFailed);

                     System.Diagnostics.Debug.WriteLine(exp.ToString());
@@ -652,6 +652,8 @@
             //in debug mode we renew every time instead of skipping based on days old
             renewalIntervalDays = 0;
 #endif
+            int numRenewalTasks = 0;
+            int maxRenewalTasks = Properties.Settings.Default.MaxRenewalRequests;

             var renewalTasks = new List<Task<CertificateRequestResult>>();
             foreach (var s in sites.Where(s => s.IncludeInAutoRenew == true))
@@ -677,15 +679,20 @@
                         tracker = progressTrackers[s.Id];
                     }

-                    if (testModeOnly)
-                    {
-                        //simulated request for UI testing
-                        renewalTasks.Add(this.PerformDummyCertificateRequest(s, tracker));
-                    }
-                    else
-                    {
-                        renewalTasks.Add(this.PerformCertificateRequest(s, tracker));
-                    }
+                    // optionally limit the number of renewal tasks to attempt in this pass
+                    if (maxRenewalTasks == 0 || maxRenewalTasks > 0 && numRenewalTasks < maxRenewalTasks)
+                    {
+                        if (testModeOnly)
+                        {
+                            //simulated request for UI testing
+                            renewalTasks.Add(this.PerformDummyCertificateRequest(s, tracker));
+                        }
+                        else
+                        {
+                            renewalTasks.Add(this.PerformCertificateRequest(s, tracker));
+                        }
+                    }
+                    numRenewalTasks++;
                 }
                 else
                 {


Updated alarm summary to use FirstOrDefault

--- Source/Libraries/Adapters/openHistorian.Adapters/OscEventLogger.cs
+++ Source/Libraries/Adapters/openHistorian.Adapters/OscEventLogger.cs
@@ -123,7 +123,7 @@
                 m_parent = parent ?? throw new ArgumentNullException(nameof(parent));
             }

-            private AlarmDetails FirstAlarm => m_alarms.Values.First();
+            private AlarmDetails FirstAlarm => m_alarms.Values.FirstOrDefault();

             private bool AllAlarmsStopped => m_alarms.Values.All(alarm => alarm.IsStopped);