refactor ui boilerplate for brevity and DRY

--- UI/GameForm.cs
+++ UI/GameForm.cs
@@ -73,32 +73,28 @@

         private void btnRun_Click(object sender, EventArgs e)
         {
-            GameState = GameStates.Run;
-            SetUiForGameState();
+            SetUiForGameState(GameStates.Run);
             RaiseGaeaOnDemand();
             _gaea.Run(UpdateGameVisualization);
         }

         private void btnPause_Click(object sender, EventArgs e)
         {
-            GameState = GameStates.Pause;
-            SetUiForGameState();
+            SetUiForGameState(GameStates.Pause);
             RaiseGaeaOnDemand();
             _gaea.Pause();
         }

         private void btnStep_Click(object sender, EventArgs e)
         {
-            GameState = GameStates.Step;
-            SetUiForGameState();
+            SetUiForGameState(GameStates.Step);
             RaiseGaeaOnDemand();
             _gaea.Step(UpdateGameVisualization);
         }

         private void btnClear_Click(object sender, EventArgs e)
         {
-            GameState = GameStates.Idle;
-            SetUiForGameState();
+            SetUiForGameState(GameStates.Idle);
             _gaea?.Clear(UpdateGameVisualization);
             _gaea = null;
         }
@@ -133,7 +129,6 @@

         private void TrackRows_ValueChanged(object sender, EventArgs e)
         {
-            SetUiForGameState();
             if (CheckboxLockRowAndCols.Checked)
             {
                 TrackCols.Value = TrackRows.Value;
@@ -145,7 +140,6 @@

         private void TrackCols_ValueChanged(object sender, EventArgs e)
         {
-            SetUiForGameState();
             if (CheckboxLockRowAndCols.Checked)
             {
                 TrackRows.Value = TrackCols.Value;
@@ -157,17 +151,16 @@

         private void CheckboxLockRowAndCols_CheckedChanged(object sender, EventArgs e)
         {
-            SetUiForGameState();
-            if (CheckboxLockRowAndCols.Checked)
-            {
-                var lower = new List<int> { TrackRows.Value, TrackCols.Value }.Min();
-                TrackRows.Value = lower;
-                TrackCols.Value = lower;
-            }
-        }
-
-        private void SetUiForGameState()
-        {
+            if (!CheckboxLockRowAndCols.Checked) return;
+
+            var lower = Math.Min(TrackRows.Value, TrackCols.Value);
+            TrackRows.Value = lower;
+            TrackCols.Value = lower;
+        }
+
+        private void SetUiForGameState(GameStates state)
+        {
+            GameState = state;
             switch (GameState)
             {
                 case GameStates.Idle:
@@ -210,8 +203,6 @@
                     TrackRows.Enabled = false;
                     TrackCols.Enabled = false;
                     break;
-                default:
-                    break;
             }
         }
     }


Added SafeAnysizeStructMarshaler which is a IVanaraMarshaler implementation for SafeAnysizeStruct<T>

--- PInvoke/Shared/InteropServices/SafeAnysizeStruct.cs
+++ PInvoke/Shared/InteropServices/SafeAnysizeStruct.cs
@@ -34,8 +34,8 @@
 		/// Initializes a new instance of the <see cref="SafeAnysizeStruct{T}"/> class.
 		/// <param name="value">The initial value of the structure, if provided.</param>
 		/// <param name="sizeFieldName">
-		/// The name of the field in <typeparamref name="T"/> that holds the length of the array. If <see langword="null"/>, the first public
-		/// field will be selected.
+		/// The name of the field in <typeparamref name="T"/> that holds the length of the array. If <see langword="null"/>, the first
+		/// public field will be selected.
 		/// </param>
 		/// <exception cref="InvalidOperationException">This class can only manange sequential layout structures.</exception>
 		public SafeAnysizeStruct(in T value, string sizeFieldName = null) : base(baseSz)
@@ -48,8 +48,8 @@
 		/// <param name="allocatedMemory">A pointer to memory that holds the value of an instance of <typeparamref name="T"/>.</param>
 		/// <param name="size">The size of the allocated memory in <paramref name="allocatedMemory"/> in bytes.</param>
 		/// <param name="sizeFieldName">
-		/// The name of the field in <typeparamref name="T"/> that holds the length of the array. If <see langword="null"/>, the first public
-		/// field will be selected.
+		/// The name of the field in <typeparamref name="T"/> that holds the length of the array. If <see langword="null"/>, the first
+		/// public field will be selected.
 		/// </param>
 		public SafeAnysizeStruct(IntPtr allocatedMemory, int size, string sizeFieldName = null) : base(size)
 		{
@@ -62,8 +62,8 @@
 		/// Initializes a new instance of the <see cref="SafeAnysizeStruct{T}"/> class with an initial empty memory allocation.
 		/// <param name="size">The size of the reserved memory in bytes.</param>
 		/// <param name="sizeFieldName">
-		/// The name of the field in <typeparamref name="T"/> that holds the length of the array. If <see langword="null"/>, the first public
-		/// field will be selected.
+		/// The name of the field in <typeparamref name="T"/> that holds the length of the array. If <see langword="null"/>, the first
+		/// public field will be selected.
 		/// </param>
 		public SafeAnysizeStruct(SizeT size, string sizeFieldName = null) : base(size) => InitCountField(sizeFieldName);

@@ -129,4 +129,35 @@
 				Marshal.StructureToPtr(((Array)arrVal).GetValue(i), handle.Offset(baseSz - arrElemSz * (i - 1)), false);
 		}
 	}
+
+	///
+	/// A marshaler implementation of <see cref="IVanaraMarshaler"/> to set the marshaler as an attribute using
+	/// <see cref="SafeAnysizeStruct{T}"/>. Use the cookie paramter of
+	/// <see cref="SafeAnysizeStructMarshaler{T}.SafeAnysizeStructMarshaler(string)"/> to specify the name of the field in
+	/// <typeparamref name="T"/> that specifies the number of elements in the last field of <typeparamref name="T"/>.
+	///
+	/// <typeparam name="T">The structure type to be marshaled.</typeparam>
+	/// <seealso cref="Vanara.InteropServices.IVanaraMarshaler"/>
+	public class SafeAnysizeStructMarshaler<T> : IVanaraMarshaler where T : struct
+	{
+		private string sizeFieldName;
+
+		/// Initializes a new instance of the <see cref="SafeAnysizeStructMarshaler{T}"/> class.
+		/// <param name="cookie">
+		/// The name of the field in <typeparamref name="T"/> that specifies the number of elements in the last field of <typeparamref name="T"/>.
+		/// </param>
+		public SafeAnysizeStructMarshaler(string cookie) => sizeFieldName = cookie;
+
+		SizeT IVanaraMarshaler.GetNativeSize() => Marshal.SizeOf(typeof(T));
+
+		SafeAllocatedMemoryHandle IVanaraMarshaler.MarshalManagedToNative(object managedObject) =>
+			managedObject is null ? SafeCoTaskMemHandle.Null : (SafeAllocatedMemoryHandle)new SafeAnysizeStruct<T>((T)managedObject, sizeFieldName);
+
+		object IVanaraMarshaler.MarshalNativeToManaged(IntPtr pNativeData, SizeT allocatedBytes)
+		{
+			if (pNativeData == IntPtr.Zero) return null;
+			using var s = new SafeAnysizeStruct<T>(pNativeData, allocatedBytes, sizeFieldName);
+			return s.Value;
+		}
+	}
 }


Deal with carriage returns differently

Deal with carriage returns differently

--- ExpressionToCodeTest/StringInterpolationTest.cs
+++ ExpressionToCodeTest/StringInterpolationTest.cs
@@ -109,7 +109,7 @@
 2
 3
 4
-"", J = 1 }} Z"")".Replace("\r",""),
+"", J = 1 }} Z"")",
                 ExpressionToCode.ToCode(
                     () => Interpolation($@"abc {new { I = @"1
 2


purchase/order context now stored in backend, returned on purchase/token verify

--- Vingd/Vingd.cs
+++ Vingd/Vingd.cs
@@ -268,12 +268,14 @@
 		/**
 		 * Contacts Vingd Broker and generates a new order for selling the object (oid)
      	 * under the defined terms (price). Order shall be valid until expiresLocal.
+     	 * Context shall be stored with order and returned upon purchase verification.
      	 *
 		 */
-		public VingdOrder CreateOrder (long oid, double price, DateTime expiresLocal) {
+		public VingdOrder CreateOrder (long oid, double price, string context, DateTime expiresLocal) {
 			DateTimeOffset expiresWithTimezone = new DateTimeOffset(expiresLocal, TimeZone.CurrentTimeZone.GetUtcOffset(expiresLocal));
 			var parameters = new Dictionary<string, object>();
 			parameters.Add("price", (int)(price * 100));
+			parameters.Add("context", context);
 			parameters.Add("order_expires", expiresWithTimezone.ToString("o"));

 			object responseRaw = Request("POST", "/objects/" + oid + "/orders", parameters);
@@ -290,15 +292,23 @@
 			}
 			long orderid = Convert.ToInt64(id);

-			return new VingdOrder(orderid, oid, price, expiresWithTimezone, frontendURL);
-		}
-
+			return new VingdOrder(orderid, oid, price, context, expiresWithTimezone, frontendURL);
+		}
+
+		public VingdOrder CreateOrder(long oid, double price, string context, TimeSpan expiry) {
+			return CreateOrder(oid, price, context, DateTime.Now.Add(expiry));
+		}
+
+		public VingdOrder CreateOrder(long oid, double price, string context) {
+			return CreateOrder(oid, price, context, DateTime.Now.Add(defaultOrderExpiry));
+		}
+
 		public VingdOrder CreateOrder(long oid, double price, TimeSpan expiry) {
-			return CreateOrder(oid, price, DateTime.Now.Add(expiry));
+			return CreateOrder(oid, price, null, DateTime.Now.Add(expiry));
 		}

 		public VingdOrder CreateOrder(long oid, double price) {
-			return CreateOrder(oid, price, DateTime.Now.Add(defaultOrderExpiry));
+			return CreateOrder(oid, price, null, DateTime.Now.Add(defaultOrderExpiry));
 		}

 		/**
@@ -324,6 +334,7 @@
 				huid = (string)response["huid"],
 				oid = Convert.ToInt64(oid),
 				orderid = Convert.ToInt64(response["orderid"]),
+				context = (string)response["context"],
 				purchaseid = Convert.ToInt64(response["purchaseid"]),
 				transferid = Convert.ToInt64(response["transferid"]),
 				reclaimed = Convert.ToBoolean(response["reclaimed"])
@@ -416,32 +427,26 @@
 		public long id;
 		public long oid;
 		public double price;
+		public string context;
 		public DateTimeOffset expires;

 		private string frontendURL;

-		public VingdOrder(long id, long oid, double price, DateTimeOffset expires, string frontendURL) {
+		public VingdOrder(long id, long oid, double price, string context, DateTimeOffset expires, string frontendURL) {
 			this.id = id;
 			this.oid = oid;
 			this.price = price;
+			this.context = context;
 			this.expires = expires;
 			this.frontendURL = frontendURL;
 		}

 		public string GetRedirectURL() {
-			return GetRedirectURL(null);
-		}
-		public string GetRedirectURL(string context) {
-			if (context != null) context = "?context=" + Uri.EscapeUriString(context);
-			return frontendURL + "/orders/" + id + "/add/" + context;
-		}
-
+			return frontendURL + "/orders/" + id + "/add/";
+		}
+
 		public string GetPopupURL() {
-			return GetPopupURL(null);
-		}
-		public string GetPopupURL(string context) {
-			if (context != null) context = "?context=" + Uri.EscapeUriString(context);
-			return frontendURL + "/popup/orders/" + id + "/add/" + context;
+			return frontendURL + "/popup/orders/" + id + "/add/";
 		}
 	}

@@ -452,6 +457,7 @@
 		public long orderid;
 		public long purchaseid;
 		public long transferid;
+		public string context;
 		public bool reclaimed;
 	}

@@ -475,6 +481,7 @@
 		public string GetRedirectURL() {
 			return frontendURL + "/vouchers/" + code;
 		}
+
 		public string GetPopupURL() {
 			return frontendURL + "/popup/vouchers/" + code;
 		}


Code Coverage 96.14%

Code Coverage 96.14%

--- PcapDotNet/src/PcapDotNet.Packets.Test/IpV6Tests.cs
+++ PcapDotNet/src/PcapDotNet.Packets.Test/IpV6Tests.cs
@@ -2373,5 +2373,13 @@
             Packet invalidPacket = new Packet(packet.Buffer, DateTime.Now, DataLinkKind.Ethernet);
             Assert.IsFalse(invalidPacket.IsValid);
         }
+
+        [TestMethod]
+        [ExpectedException(typeof(ArgumentException), AllowDerivedTypes = false)]
+        public void IpV6ExtensionHeaderMobilityExperimentalConstructorMessageDataBadLength()
+        {
+            Assert.IsNull(new IpV6ExtensionHeaderMobilityExperimental(IpV4Protocol.Pin, 0, new DataSegment(new byte[5])));
+            Assert.Fail();
+        }
     }
 }


[Samples] Display Frametime at bottom of window. Useful for checking VSync.

--- Samples/Toolkit/Common/MonitorInfo/MonitorInfoGame.cs
+++ Samples/Toolkit/Common/MonitorInfo/MonitorInfoGame.cs
@@ -212,6 +212,9 @@

             spriteBatch.Begin(SpriteSortMode.Immediate, null);
             spriteBatch.DrawString(font, text, new Vector2(20, 20), Color.Black);
+
+            var textMillis = "Frametime in Milliseconds: " + gameTime.ElapsedGameTime.TotalMilliseconds;
+            spriteBatch.DrawString(font, textMillis, new Vector2(20, Window.ClientBounds.Height - 40), Color.Black);
             spriteBatch.End();

             base.Draw(gameTime);


- Don't show tables if there are no rows in the statistics page. Show a message instead; - Show the time when the server last started in the statistics page

--- Fos/Logging/StatsLogging/StatsPageMiddleware.cs
+++ Fos/Logging/StatsLogging/StatsPageMiddleware.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Linq;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using System.IO;
@@ -50,6 +51,7 @@
         {
             var builder = new System.Text.StringBuilder();
             builder.AppendLine("
Overall
");
+            builder.AppendFormat("Server last started {0}
", Logger.ServerStarted.Last());
             builder.AppendFormat("Total connections received: {0}
", Logger.TotalConnectionsReceived);

             builder.AppendLine("
Request Times
");
@@ -67,35 +69,51 @@
             }
             builder.Append("
\n");

+            var applicationErrors = Logger.GetAllApplicationErrors();
             builder.Append("
Application Errors
");
-            builder.AppendLine("

Path	Method	Error
");
-            i = 0;
-            foreach (var error in Logger.GetAllApplicationErrors())
+            if (!applicationErrors.Any())
             {
-                string row_class = (i % 2 == 0) ? "even_row" : "odd_row";
-                builder.AppendFormat("
{1}	{2}	{3}	details
\n", row_class, HtmlEncode(error.RelativePath), HtmlEncode(error.HttpMethod), HtmlEncode(error.Error.Message));
-
-                // Now the line with more data
-                builder.AppendFormat("

{0}

\n", error.Error.ToString());
-
-                i++;
+                builder.AppendLine("
No application errors
");
             }
-            builder.Append("
\n");
+            else
+            {
+                builder.AppendLine("

Path	Method	Error
");
+                i = 0;
+                foreach (var error in applicationErrors)
+                {
+                    string row_class = (i % 2 == 0) ? "even_row" : "odd_row";
+                    builder.AppendFormat("
{1}	{2}	{3}	details
\n", row_class, HtmlEncode(error.RelativePath), HtmlEncode(error.HttpMethod), HtmlEncode(error.Error.Message));
+
+                    // Now the line with more data
+                    builder.AppendFormat("

{0}

\n", error.Error.ToString());
+
+                    i++;
+                }
+                builder.Append("
\n");
+            }

+            var serverErrors = Logger.GetAllServerErrors();
             builder.Append("
Server Errors
");
-            builder.AppendLine("

Type
");
-            i = 0;
-            foreach (var error in Logger.GetAllServerErrors())
+            if (!serverErrors.Any())
             {
-                string row_class = (i % 2 == 0) ? "even_row" : "odd_row";
-                builder.AppendFormat("
{1}	details
\n", row_class, HtmlEncode(error.GetType().ToString()));
-
-                // Now the line with more data
-                builder.AppendFormat("

{0}

\n", HtmlEncode(error.ToString()));
-
-                i++;
+                builder.AppendLine("
No server errors
");
             }
-            builder.Append("
\n");
+            else
+            {
+                builder.AppendLine("

Type
");
+                i = 0;
+                foreach (var error in serverErrors)
+                {
+                    string row_class = (i % 2 == 0) ? "even_row" : "odd_row";
+                    builder.AppendFormat("
{1}	details
\n", row_class, HtmlEncode(error.GetType().ToString()));
+
+                    // Now the line with more data
+                    builder.AppendFormat("

{0}

\n", HtmlEncode(error.ToString()));
+
+                    i++;
+                }
+                builder.Append("
\n");
+            }

             return builder.ToString();
         }


MigrationLogic.ExecuteLoadProcess optionally with log

--- Signum.Engine.Extensions/Migrations/MigrationLogic.cs
+++ Signum.Engine.Extensions/Migrations/MigrationLogic.cs
@@ -88,7 +88,7 @@
             string showDescription = description ?? action.Method.Name.SpacePascal(true);
             Console.WriteLine("------- Executing {0} ".FormatWith(showDescription).PadRight(Console.WindowWidth - 2, '-'));

-            var log = new ExecutedLoadProcessEntity
+            var log = !Schema.Current.Tables.ContainsKey(typeof(ExecutedLoadProcessEntity)) ? null : new ExecutedLoadProcessEntity
             {
                 Start = TimeZoneManager.Now,
                 ClassName = action.Method.DeclaringType.FullName,
@@ -99,8 +99,11 @@
             try
             {
                 action();
-                log.End = TimeZoneManager.Now;
-                log.Save();
+                if (log != null)
+                {
+                    log.End = TimeZoneManager.Now;
+                    log.Save();
+                }
                 Console.WriteLine("------- Executed {0} (took {1})".FormatWith(showDescription, (log.End.Value - log.Start).NiceToString()).PadRight(Console.WindowWidth - 2, '-'));

                 return null;
@@ -112,11 +115,13 @@
                 SafeConsole.WriteColor(ConsoleColor.Red, e.GetType() + ": ");
                 SafeConsole.WriteLineColor(ConsoleColor.DarkRed, e.Message);
                 SafeConsole.WriteSameLineColor(ConsoleColor.DarkRed, e.StackTrace);
-
-                var exLog = e.LogException();
-                log.Exception = exLog.ToLite();
-                log.End = TimeZoneManager.Now;
-                log.Save();
+                if (log != null)
+                {
+                    var exLog = e.LogException();
+                    log.Exception = exLog.ToLite();
+                    log.End = TimeZoneManager.Now;
+                    log.Save();
+                }

                 return e;
             }


Loader con Panel de Control Proveedores (reservas bajo demanda)

--- Signum.Entities.Extensions/UserQueries/UserQueryDN.cs
+++ Signum.Entities.Extensions/UserQueries/UserQueryDN.cs
@@ -177,6 +177,14 @@
     [Serializable]
     public class QueryOrderDN : QueryTokenDN
     {
+        public QueryOrderDN() {}
+
+        public QueryOrderDN(string columnName, OrderType type)
+        {
+            this.TokenString = columnName;
+            orderType = type;
+        }
+
         int index;
         public int Index
         {
@@ -204,10 +212,15 @@
     {
         public QueryColumnDN(){}

+        public QueryColumnDN(string columnName)
+        {
+            this.TokenString = columnName;
+        }
+
         public QueryColumnDN(Column col)
         {
             Token = col.Token;
-            if(col.DisplayName != col.Token.NiceName())
+            if (col.DisplayName != col.Token.NiceName())
                 DisplayName = col.DisplayName;
         }


Sync with ReClass.NET code changes.

Sync with ReClass.NET code changes.

--- WeakPtrNode.cs
+++ WeakPtrNode.cs
@@ -48,9 +48,9 @@
 			var tx = x;
 			x = AddAddressOffset(view, x, y);

-			x = AddText(view, x, y, FrostbitePluginExt.Settings.TypeColor, HotSpot.NoneId, "WeakPtr") + view.Font.Width;
-			x = AddText(view, x, y, FrostbitePluginExt.Settings.NameColor, HotSpot.NameId, Name) + view.Font.Width;
-			x = AddText(view, x, y, FrostbitePluginExt.Settings.ValueColor, HotSpot.NoneId, $"<{InnerNode.Name}>");
+			x = AddText(view, x, y, view.Settings.TypeColor, HotSpot.NoneId, "WeakPtr") + view.Font.Width;
+			x = AddText(view, x, y, view.Settings.NameColor, HotSpot.NameId, Name) + view.Font.Width;
+			x = AddText(view, x, y, view.Settings.ValueColor, HotSpot.NoneId, $"<{InnerNode.Name}>");
 			x = AddIcon(view, x, y, Icons.Change, 4, HotSpotType.ChangeType);

 			x += view.Font.Width;


Trial

Trial

--- ProjectFood/ProjectFood/App_Start/IdentityConfig.cs
+++ ProjectFood/ProjectFood/App_Start/IdentityConfig.cs
@@ -54,10 +54,10 @@
             manager.PasswordValidator = new PasswordValidator
             {
                 RequiredLength = 6,
-                RequireNonLetterOrDigit = true,
-                RequireDigit = true,
-                RequireLowercase = true,
-                RequireUppercase = true,
+                RequireNonLetterOrDigit = false,
+                RequireDigit = false,
+                RequireLowercase = false,
+                RequireUppercase = false,
             };

             // Configure user lockout defaults


Update for latest ReClass.NET changes.

Update for latest ReClass.NET changes.

--- WeakPtrNode.cs
+++ WeakPtrNode.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Drawing;
 using ReClassNET;
 using ReClassNET.Memory;
 using ReClassNET.Nodes;
@@ -30,17 +31,20 @@
 		/// <param name="view">The view information.</param>
 		/// <param name="x">The x coordinate.</param>
 		/// <param name="y">The y coordinate.</param>
-		/// <returns>The height the node occupies.</returns>
-		public override int Draw(ViewInfo view, int x, int y)
+		/// <returns>The pixel size the node occupies.</returns>
+		public override Size Draw(ViewInfo view, int x, int y)
 		{
 			if (IsHidden)
 			{
 				return DrawHidden(view, x, y);
 			}

+			var origX = x;
+			var origY = y;
+
 			AddSelection(view, x, y, view.Font.Height);
-			AddDelete(view, x, y);
-			AddTypeDrop(view, x, y);
+			AddDelete(view, y);
+			AddTypeDrop(view, y);

 			x = AddOpenClose(view, x, y);
 			x = AddIcon(view, x, y, Icons.Pointer, -1, HotSpotType.None);
@@ -57,6 +61,8 @@
 			AddComment(view, x, y);

 			y += view.Font.Height;
+
+			var size = new Size(x - origX, y - origY);

 			if (levelsOpen[view.Level])
 			{
@@ -78,16 +84,19 @@
 				v.Address = ptr;
 				v.Memory = memory;

-				y = InnerNode.Draw(v, tx, y);
+				var innerSize = InnerNode.Draw(v, tx, y);
+
+				size.Width = Math.Max(size.Width, innerSize.Width + tx - origX);
+				size.Height += innerSize.Height;
 			}

-			return y;
+			return size;
 		}

 		/// <summary>Calculates the height of the node.</summary>
 		/// <param name="view">The view information.</param>
 		/// <returns>The calculated height.</returns>
-		public override int CalculateHeight(ViewInfo view)
+		public override int CalculateDrawnHeight(ViewInfo view)
 		{
 			if (IsHidden)
 			{
@@ -97,7 +106,7 @@
 			var h = view.Font.Height;
 			if (levelsOpen[view.Level])
 			{
-				h += InnerNode.CalculateHeight(view);
+				h += InnerNode.CalculateDrawnHeight(view);
 			}
 			return h;
 		}


- Fix from NedRyerson to fix Merge( Vector3 )

git-svn-id: ad71a101fa69fb252e58119732bf51384d5dbd95@1285 bb9bf1cf-960d-0410-9a3a-baeba60cf407

--- Projects/Axiom/Source/Engine/Math/AxisAlignedBox.cs
+++ Projects/Axiom/Source/Engine/Math/AxisAlignedBox.cs
@@ -529,8 +529,8 @@
 			}
 			else
 			{
-				Maximum.Ceil( point );
-				Minimum.Floor( point );
+				maxVector.Ceil( point );
+				minVector.Floor( point );
 				UpdateCorners();
 			}
 		}


Web: Changed comment

Web: Changed comment

--- Web/Startup.cs
+++ Web/Startup.cs
@@ -32,9 +32,9 @@
             services.AddOptions();
             services.Configure<DataLoaderOptions>(Configuration.GetSection("DataLoader"));

-            // Requests through Chrome Data Saver cause "Parameter count mismatch between X-Forwarded-For and X-Forwarded-Proto" otherwise
             services.Configure<ForwardedHeadersOptions>(options =>
             {
+                // Requests through Chrome Data Saver cause "Parameter count mismatch between X-Forwarded-For and X-Forwarded-Proto" if true
                 options.RequireHeaderSymmetry = false;
             });


Brining more inline with cpp version (pointer fixes so actual values are modified)

--- SourceFiles/Box2DX/Dynamics/Contacts/ContactSolver.cs
+++ SourceFiles/Box2DX/Dynamics/Contacts/ContactSolver.cs
@@ -109,67 +109,65 @@
                 worldManifold.Initialize(manifold, bodyA.GetXForm(), radiusA, bodyB.GetXForm(), radiusB);

                 Constraints[i] = new ContactConstraint();
-                ContactConstraint cc = Constraints[i];
-                cc.BodyA = bodyA;
-                cc.BodyB = bodyB;
-                cc.Manifold = manifold;
-                cc.Normal = worldManifold.Normal;
-                cc.PointCount = manifold.PointCount;
-                cc.Friction = friction;
-                cc.Restitution = restitution;
-
-                cc.LocalPlaneNormal = manifold.LocalPlaneNormal;
-                cc.LocalPoint = manifold.LocalPoint;
-                cc.Radius = radiusA + radiusB;
-                cc.Type = manifold.Type;
+                Constraints[i].BodyA = bodyA;
+                Constraints[i].BodyB = bodyB;
+                Constraints[i].Manifold = manifold;
+                Constraints[i].Normal = worldManifold.Normal;
+                Constraints[i].PointCount = manifold.PointCount;
+                Constraints[i].Friction = friction;
+                Constraints[i].Restitution = restitution;
+
+                Constraints[i].LocalPlaneNormal = manifold.LocalPlaneNormal;
+                Constraints[i].LocalPoint = manifold.LocalPoint;
+                Constraints[i].Radius = radiusA + radiusB;
+                Constraints[i].Type = manifold.Type;

                 for (int j = 0; j < Constraints[i].PointCount; ++j)
                 {
                     ManifoldPoint cp = manifold.Points[j];
-                    ContactConstraintPoint ccp = Constraints[i].Points[j];
-
-                    ccp.NormalImpulse = cp.NormalImpulse;
-                    ccp.TangentImpulse = cp.TangentImpulse;
-
-                    ccp.LocalPoint = cp.LocalPoint;
-
-                    ccp.RA = WorldManifold.Points[j] - bodyA._sweep.C;
-                    ccp.RB = WorldManifold.Points[j] - bodyB._sweep.C;
-
-                    float rnA = Vec2.Cross(ccp.RA, Constraints[i].Normal);
-                    float rnB = Vec2.Cross(ccp.RB, Constraints[i].Normal);
+
+                    Constraints[i].Points[j].NormalImpulse = cp.NormalImpulse;
+                    Constraints[i].Points[j].TangentImpulse = cp.TangentImpulse;
+
+                    Constraints[i].Points[j].LocalPoint = cp.LocalPoint;
+
+                    Constraints[i].Points[j].RA = WorldManifold.Points[j] - bodyA._sweep.C;
+                    Constraints[i].Points[j].RB = WorldManifold.Points[j] - bodyB._sweep.C;
+
+                    float rnA = Vec2.Cross(Constraints[i].Points[j].RA, Constraints[i].Normal);
+                    float rnB = Vec2.Cross(Constraints[i].Points[j].RB, Constraints[i].Normal);
                     rnA *= rnA;
                     rnB *= rnB;

                     float kNormal = bodyA._invMass + bodyB._invMass + bodyA._invI * rnA + bodyB._invI * rnB;

                     Box2DXDebug.Assert(kNormal > Settings.FLT_EPSILON);
-                    ccp.NormalMass = 1.0f / kNormal;
+                    Constraints[i].Points[j].NormalMass = 1.0f / kNormal;

                     float kEqualized = bodyA._mass * bodyA._invMass + bodyB._mass * bodyB._invMass;
                     kEqualized += bodyA._mass * bodyA._invI * rnA + bodyB._mass * bodyB._invI * rnB;

                     Box2DXDebug.Assert(kEqualized > Settings.FLT_EPSILON);
-                    ccp.EqualizedMass = 1.0f / kEqualized;
-
-                    Vec2 tangent = Vec2.Cross(cc.Normal, 1.0f);
-
-                    float rtA = Vec2.Cross(ccp.RA, tangent);
-                    float rtB = Vec2.Cross(ccp.RB, tangent);
+                    Constraints[i].Points[j].EqualizedMass = 1.0f / kEqualized;
+
+                    Vec2 tangent = Vec2.Cross(Constraints[i].Normal, 1.0f);
+
+                    float rtA = Vec2.Cross(Constraints[i].Points[j].RA, tangent);
+                    float rtB = Vec2.Cross(Constraints[i].Points[j].RB, tangent);
                     rtA *= rtA;
                     rtB *= rtB;

                     float kTangent = bodyA._invMass + bodyB._invMass + bodyA._invI * rtA + bodyB._invI * rtB;

                     Box2DXDebug.Assert(kTangent > Settings.FLT_EPSILON);
-                    ccp.TangentMass = 1.0f / kTangent;
+                    Constraints[i].Points[j].TangentMass = 1.0f / kTangent;

                     // Setup a velocity bias for restitution.
-                    ccp.VelocityBias = 0.0f;
-                    float vRel = Vec2.Dot(cc.Normal, vB + Vec2.Cross(wB, ccp.RB) - vA - Vec2.Cross(wA, ccp.RA));
+                    Constraints[i].Points[j].VelocityBias = 0.0f;
+                    float vRel = Vec2.Dot(Constraints[i].Normal, vB + Vec2.Cross(wB, Constraints[i].Points[j].RB) - vA - Vec2.Cross(wA, Constraints[i].Points[j].RA));
                     if (vRel < -Settings.VelocityThreshold)
                     {
-                        ccp.VelocityBias = -cc.Restitution * vRel;
+                        Constraints[i].Points[j].VelocityBias = -Constraints[i].Restitution * vRel;
                     }
                 }

@@ -184,10 +182,10 @@
                     float invMassB = bodyB._invMass;
                     float invIB = bodyB._invI;

-                    float rn1A = Vec2.Cross(ccp1.RA, cc.Normal);
-                    float rn1B = Vec2.Cross(ccp1.RB, cc.Normal);
-                    float rn2A = Vec2.Cross(ccp2.RA, cc.Normal);
-                    float rn2B = Vec2.Cross(ccp2.RB, cc.Normal);
+                    float rn1A = Vec2.Cross(ccp1.RA, Constraints[i].Normal);
+                    float rn1B = Vec2.Cross(ccp1.RB, Constraints[i].Normal);
+                    float rn2A = Vec2.Cross(ccp2.RA, Constraints[i].Normal);
+                    float rn2B = Vec2.Cross(ccp2.RB, Constraints[i].Normal);

                     float k11 = invMassA + invMassB + invIA * rn1A * rn1A + invIB * rn1B * rn1B;
                     float k22 = invMassA + invMassB + invIA * rn2A * rn2A + invIB * rn2B * rn2B;
@@ -198,15 +196,15 @@
                     if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12))
                     {
                         // K is safe to invert.
-                        cc.K.Col1.Set(k11, k12);
-                        cc.K.Col2.Set(k12, k22);
-                        cc.NormalMass = Constraints[i].K.Invert();
+                        Constraints[i].K.Col1.Set(k11, k12);
+                        Constraints[i].K.Col2.Set(k12, k22);
+                        Constraints[i].NormalMass = Constraints[i].K.Invert();
                     }
                     else
                     {
                         // The constraints are redundant, just use one.
                         // TODO_ERIN use deepest?
-                        cc.PointCount = 1;
+                        Constraints[i].PointCount = 1;
                     }
                 }
             }
@@ -222,38 +220,32 @@
 			// Warm start.
 			for (int i = 0; i < ConstraintCount; ++i)
 			{
-				ContactConstraint c = Constraints[i];
-
-				Body bodyA = c.BodyA;
-				Body bodyB = c.BodyB;
-				float invMassA = bodyA._invMass;
-				float invIA = bodyA._invI;
-				float invMassB = bodyB._invMass;
-				float invIB = bodyB._invI;
-				Vec2 normal = c.Normal;
+                float invMassA = Constraints[i].BodyA._invMass;
+                float invIA = Constraints[i].BodyA._invI;
+                float invMassB = Constraints[i].BodyB._invMass;
+                float invIB = Constraints[i].BodyB._invI;
+                Vec2 normal = Constraints[i].Normal;
 				Vec2 tangent = Vec2.Cross(normal, 1.0f);

 				if (step.WarmStarting)
 				{
-					for (int j = 0; j < c.PointCount; ++j)
+                    for (int j = 0; j < Constraints[i].PointCount; ++j)
 					{
-						ContactConstraintPoint ccp = c.Points[j];
-						ccp.NormalImpulse *= step.DtRatio;
-						ccp.TangentImpulse *= step.DtRatio;
-						Vec2 P = ccp.NormalImpulse * normal + ccp.TangentImpulse * tangent;
-						bodyA._angularVelocity -= invIA * Vec2.Cross(ccp.RA, P);
-						bodyA._linearVelocity -= invMassA * P;
-						bodyB._angularVelocity += invIB * Vec2.Cross(ccp.RB, P);
-						bodyB._linearVelocity += invMassB * P;
+                        Constraints[i].Points[j].NormalImpulse *= step.DtRatio;
+                        Constraints[i].Points[j].TangentImpulse *= step.DtRatio;
+                        Vec2 P = Constraints[i].Points[j].NormalImpulse * normal + Constraints[i].Points[j].TangentImpulse * tangent;
+                        Constraints[i].BodyA._angularVelocity -= invIA * Vec2.Cross(Constraints[i].Points[j].RA, P);
+                        Constraints[i].BodyA._linearVelocity -= invMassA * P;
+                        Constraints[i].BodyB._angularVelocity += invIB * Vec2.Cross(Constraints[i].Points[j].RB, P);
+                        Constraints[i].BodyB._linearVelocity += invMassB * P;
 					}
 				}
 				else
 				{
-					for (int j = 0; j < c.PointCount; ++j)
+                    for (int j = 0; j < Constraints[i].PointCount; ++j)
 					{
-						ContactConstraintPoint ccp = c.Points[j];
-						ccp.NormalImpulse = 0.0f;
-						ccp.TangentImpulse = 0.0f;
+                        Constraints[i].Points[j].NormalImpulse = 0.0f;
+                        Constraints[i].Points[j].TangentImpulse = 0.0f;
 					}
 				}
 			}
@@ -551,10 +543,10 @@
                     }
                 }

-				bodyA._linearVelocity = vA;
-				bodyA._angularVelocity = wA;
-				bodyB._linearVelocity = vB;
-				bodyB._angularVelocity = wB;
+                Constraints[i].BodyA._linearVelocity = vA;
+                Constraints[i].BodyA._angularVelocity = wA;
+                Constraints[i].BodyB._linearVelocity = vB;
+                Constraints[i].BodyB._angularVelocity = wB;
 			}
 		}

@@ -563,12 +555,11 @@
 			for (int i = 0; i < ConstraintCount; ++i)
 			{
 				ContactConstraint c = Constraints[i];
-				Manifold m = c.Manifold;

 				for (int j = 0; j < c.PointCount; ++j)
 				{
-					m.Points[j].NormalImpulse = c.Points[j].NormalImpulse;
-					m.Points[j].TangentImpulse = c.Points[j].TangentImpulse;
+                    c.Manifold.Points[j].NormalImpulse = c.Points[j].NormalImpulse;
+                    c.Manifold.Points[j].TangentImpulse = c.Points[j].TangentImpulse;
 				}
 			}
 		}
@@ -615,13 +606,13 @@

 			        Vec2 P = impulse * normal;

-			        bodyA._sweep.C -= invMassA * P;
-			        bodyA._sweep.A -= invIA * Vec2.Cross(rA, P);
-			        bodyA.SynchronizeTransform();
-
-			        bodyB._sweep.C += invMassB * P;
-			        bodyB._sweep.A += invIB * Vec2.Cross(rB, P);
-			        bodyB.SynchronizeTransform();
+                    Constraints[i].BodyA._sweep.C -= invMassA * P;
+                    Constraints[i].BodyA._sweep.A -= invIA * Vec2.Cross(rA, P);
+                    Constraints[i].BodyA.SynchronizeTransform();
+
+                    Constraints[i].BodyB._sweep.C += invMassB * P;
+                    Constraints[i].BodyB._sweep.A += invIB * Vec2.Cross(rB, P);
+                    Constraints[i].BodyB.SynchronizeTransform();
 		        }
 	        }


showing existing attachments on order edit page

--- Purchasing.Web/Views/Order/_OrderPreferences.cshtml
+++ Purchasing.Web/Views/Order/_OrderPreferences.cshtml
@@ -36,25 +36,41 @@

-

-				    Comments and/or special instructions:
-

-

+

+                    Comments and/or special instructions:
+

+

                     <textarea name="comments"></textarea>
-

-

+

+

+            @if (Model.Order.Attachments.Count > 0)
+            {
+

+

+                        Existing Attachments:
+

+

+

+                            @foreach (var file in Model.Order.Attachments)
+                            {
+
@Html.ActionLink(@file.FileName, "ViewFile", new {fileId = file.Id})

+                            }
+

+

+

+            }

-				    Attachments:
+				    Add Attachments:

-

-

-
+

+

+

Please enable JavaScript to use file uploader.

-
+

-

+


Bumped version

Bumped version

--- Src/ManageMessageNamespace/Properties/AssemblyInfo.cs
+++ Src/ManageMessageNamespace/Properties/AssemblyInfo.cs
@@ -34,4 +34,4 @@
 // [assembly: AssemblyVersion("1.0.*")]
 [assembly: AssemblyVersion("2.1.0.0")]
 [assembly: AssemblyFileVersion("2.1.0.0")]
-[assembly: AssemblyInformationalVersion("1.5.0.3")]
+[assembly: AssemblyInformationalVersion("1.6.0.0")]


Fix handling of foreign functions in ControlFlowChecker

--- Src/Pc/CompilerCore/TypeChecker/ControlFlowChecker.cs
+++ Src/Pc/CompilerCore/TypeChecker/ControlFlowChecker.cs
@@ -3,6 +3,7 @@
 using Plang.Compiler.TypeChecker.AST.Statements;
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;

 namespace Plang.Compiler.TypeChecker
 {
@@ -23,7 +24,16 @@

         private void CheckFunction(Function function)
         {
-            CheckStmt(function.Body);
+            if (function.IsForeign)
+            {
+                Debug.Assert(function.Body == null);
+                // Skip this function; nothing to check
+            }
+            else
+            {
+                Debug.Assert(function.Body != null);
+                CheckStmt(function.Body);
+            }
         }

         private void CheckStmt(IPStmt stmt)


Getting used to C#

Getting used to C#

--- WordGuesser.cs
+++ WordGuesser.cs
@@ -2,8 +2,22 @@

 public class WordGuesser
 {
-	public WordGuesser()
+
+    public string test = "Test";
+
+    public WordGuesser(string wordLen, string numLives)
 	{
         //Kier do your thing
-	}
+
+
+    }
+
 }
+
+class MainClass
+{
+    public static void Main()
+    {
+        myClass myObject = new myClass();
+    }
+}


Clamp turntableAzimuth value

Clamp turntableAzimuth value

--- view/CameraManipulator.cs
+++ view/CameraManipulator.cs
@@ -101,6 +101,7 @@
                 turntableAzimuth -= deltaAzimuth;
                 turntableAltitude += deltaAltitude;
             }
+            turntableAzimuth = (float)MathUtil.ClampAngleDeg(Convert.ToDouble(turntableAzimuth), -360d, 360d);
             turntableAltitude = Mathf.Clamp(turntableAltitude, -89.9f, 89.9f);

             scene.RootGameObject.RotateAroundD(rotTarget, up, turntableAzimuth);


Pointless string capitalization change

Pointless string capitalization change


Fixed the test.

Fixed the test.

svn path=/trunk/bitsharp/; revision=95702


fixed a few dependency resolution issues


Updated with loggeing and better error handling

--- ITSWebMgmt/DefendpointChallengeResponse.aspx.cs
+++ ITSWebMgmt/DefendpointChallengeResponse.aspx.cs
@@ -1,8 +1,10 @@
-using System;
+using NLog;
+using System;
 using System.Collections.Generic;
 using System.Configuration;
 using System.Diagnostics;
 using System.Linq;
+using System.Text.RegularExpressions;
 using System.Web;
 using System.Web.UI;
 using System.Web.UI.WebControls;
@@ -11,11 +13,14 @@
 {
     public partial class DefendpointChallengeResponse : System.Web.UI.Page
     {
+        private static Logger logger = LogManager.GetCurrentClassLogger();
+
         protected void Page_Load(object sender, EventArgs e)
         {

             if (IsPostBack)
             {
+

                 Process si = new Process();
                 si.StartInfo.FileName = "C:\\webmgmtlog\\PGChallengeResponse.exe";
@@ -23,24 +28,36 @@

                 string key = ConfigurationManager.AppSettings["other:defendpoint:crkey"];

-                string argument = string.Format(@"""{0}"" ""{1}"" ""{2}""", challanageInput.Value, "once", "key");
+                string challange = challanageInput.Value.Replace("\"", "");

-                si.StartInfo.Arguments = argument;
-                si.StartInfo.RedirectStandardOutput = true;
-                si.Start();
-                string output = si.StandardOutput.ReadToEnd();
-                si.Close();
+                //XXX: Allow spaces sperators and rember X version for persistent response
+                Regex regex = new Regex("[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]");

-                //Check if valid response
-                if (output.Contains("Generated Response:"))
-                {
+                if (regex.IsMatch(challange)) {
+                    string argument = string.Format(@"""{0}"" ""{1}"" ""{2}""", challange, "once".Replace("\"", ""), "key".Replace("\"", ""));

-                    resultLbl2.Text = "
Response Code: "+ output.Replace("Generated Response: ", "");
+                    si.StartInfo.Arguments = argument;
+                    si.StartInfo.RedirectStandardOutput = true;
+                    si.Start();
+                    string output = si.StandardOutput.ReadToEnd();
+                    si.Close();
+
+                    //Check if valid response
+                    if (output.Contains("Generated Response:"))
+                    {
+                        logger.Info("User {0} generated challange with reason {1}", System.Web.HttpContext.Current.User.Identity.Name, reasonInput.Value);
+                        resultLbl2.Text = "
Response Code: " + output.Replace("Generated Response: ", "");
+
+                    }
+                    else
+                    {
+                        resultLbl2.Text = "
Error generating code - Error in command line values";
+                    }

                 }
                 else
                 {
-                    resultLbl2.Text = "
Error generating code";
+                    resultLbl2.Text = "
Error generating code - Invalid challange code";
                 }

@@ -53,10 +70,8 @@

-

-
             }

         }


updates Login.cs to support an id0 required to keep bots operating when empty mac addresses are banned.

git-svn-id: baf6e02d125cf6f9bfcfe153b2eb83d6e1f5ace6@1653 52acb1d6-8a22-11de-b505-999d5b087335

--- libsecondlife/Login.cs
+++ libsecondlife/Login.cs
@@ -94,6 +94,8 @@
         public string ViewerDigest;
         ///
         public List<string> Options;
+        ///
+        public string id0;
     }

     public struct LoginResponseData
@@ -410,6 +412,7 @@
             loginParams.MAC = String.Empty;
             loginParams.ViewerDigest = String.Empty;
             loginParams.Options = options;
+            loginParams.id0 = "00000000000000000000000000000000";

             return loginParams;
         }
@@ -554,6 +557,7 @@
             loginLLSD["agree_to_tos"] = LLSD.FromBoolean(true);
             loginLLSD["read_critical"] = LLSD.FromBoolean(true);
             loginLLSD["viewer_digest"] = LLSD.FromString(loginParams.ViewerDigest);
+            loginLLSD["id0"] = LLSD.FromString(loginParams.id0);

             // Create the options LLSD array
             LLSDArray optionsLLSD = new LLSDArray();


RemoteProcedureCall events still need work.  Need to make sure comms handlers are removed once they are unnecessary.  Will probably have to do this using IL in the add and remove methods


Adding more blocks to main chain provider


fix cs message

fix cs message

--- conf/messages.cs
+++ conf/messages.cs
@@ -382,7 +382,7 @@
 premovesPlayingDuringOpponentTurn=Předtahy (hraní během protivníkova tahu)
 takebacksWithOpponentApproval=Vrácení tahu (s protivníkovým souhlasem)
 promoteToQueenAutomatically=Povýšit na královnu automaticky
-claimDrawOnThreefoldRepetitionAutomatically=Vyžádat remízu při %trojím opakování pozic%s automaticky
+claimDrawOnThreefoldRepetitionAutomatically=Vyžádat remízu při %strojím opakování pozic%s automaticky
 privacy=Soukromí
 letOtherPlayersFollowYou=Umožnit ostatním hráčům následovat Tě
 letOtherPlayersChallengeYou=Umožnit ostatním hráčům vyzvat Tě


Change the name of files to use test functions.

--- tests/ImageExtensionsTest.cs
+++ tests/ImageExtensionsTest.cs
@@ -41,7 +41,7 @@
         [Fact]
         public void DoComplexCrop()
         {
-            var image = GetImage("penguins.jpg");
+            var image = GetImage("Penguins.jpg");
             var croppedImage = image.Crop(70, 130, 150, 50);
             // New size is:
             // 1024 - (70 + 30) = 824 width
@@ -56,7 +56,7 @@
         [Fact]
         public void DoHeightResize()
         {
-            var image = GetImage("desert.jpg");
+            var image = GetImage("Desert.jpg");
             var resizedImage = image.HeightResize(499);
             // New width is:
             // (1024 * 499) / 768 = 665
@@ -70,7 +70,7 @@
         [Fact]
         public void DoResize()
         {
-            var image = GetImage("tulips.jpg");
+            var image = GetImage("Tulips.jpg");
             var resizedImage = image.Resize(800, 450);
             resizedImage.Width.Should().Be(800, "Is the width for the resized image.");
             resizedImage.Height.Should().Be(450, "Is the height for the resized image.");
@@ -82,7 +82,7 @@
         [Fact]
         public void DoSimpleCrop()
         {
-            var image = GetImage("hydrangeas.jpg");
+            var image = GetImage("Hydrangeas.jpg");
             var croppedImage = image.Crop(120, 50);
             // New size is:
             // 1024 - 120 * 2 = 784 width
@@ -97,7 +97,7 @@
         [Fact]
         public void DoWidthResize()
         {
-            var image = GetImage("koala.jpg");
+            var image = GetImage("Koala.jpg");
             var resizedImage = image.WidthResize(665);
             // New heigth is:
             // (768 * 665) / 1024 = 498


Fixed running .net core tests.

Fixed running .net core tests.

--- test/ExcelDataReader.Tests/NetCoreTestsConfiguration.cs
+++ test/ExcelDataReader.Tests/NetCoreTestsConfiguration.cs
@@ -21,7 +21,7 @@

 		public static string GetTestWorkbookPath(string key)
         {
-			var fileName = Path.Combine("../Resources", GetKey(key));
+			var fileName = Path.Combine("../../../Resources", GetKey(key));
             //string fileName = Path.Combine(GetKey("basePath"), GetKey(key));
             fileName = Path.GetFullPath(fileName);
             Assert.IsTrue(File.Exists(fileName), string.Format("By the key '{0}' the file '{1}' could not be found. Inside the Excel.Tests App.config file, edit the key basePath to be the folder where the test workbooks are located. If this is fine, check the filename that is related to the key.", key, fileName));


Improve test coverage for the SqliteStorageEngine class

--- test/Openchain.Sqlite.Tests/SqliteStorageEngineTests.cs
+++ test/Openchain.Sqlite.Tests/SqliteStorageEngineTests.cs
@@ -78,6 +78,46 @@
         }

         [Fact]
+        public async Task AddTransaction_Multiple()
+        {
+            IList<Record> records1 = new Record[]
+            {
+                new Record(binaryData[0], binaryData[1], ByteString.Empty),
+                new Record(binaryData[2], binaryData[3], ByteString.Empty),
+            };
+
+            ByteString mutation1 = new ByteString(MessageSerializer.SerializeMutation(new Mutation(ByteString.Empty, records1, ByteString.Empty)));
+            ByteString mutationHash1 = new ByteString(MessageSerializer.ComputeHash(mutation1.ToByteArray()));
+
+            IList<Record> records2 = new Record[]
+            {
+                new Record(binaryData[2], binaryData[5], mutationHash1),
+                new Record(binaryData[6], binaryData[7], ByteString.Empty),
+            };
+
+            ByteString mutation2 = new ByteString(MessageSerializer.SerializeMutation(new Mutation(ByteString.Empty, records2, ByteString.Empty)));
+            ByteString mutationHash2 = new ByteString(MessageSerializer.ComputeHash(mutation2.ToByteArray()));
+
+            // Submit both transactions at once
+            await this.store.AddTransactions(new[]
+            {
+                new ByteString(MessageSerializer.SerializeTransaction(new Transaction(mutation1, new DateTime(), ByteString.Empty))),
+                new ByteString(MessageSerializer.SerializeTransaction(new Transaction(mutation2, new DateTime(), ByteString.Empty)))
+            });
+
+            IList<Record> result1 = await this.store.GetRecords(new[] { binaryData[0] });
+            IList<Record> result2 = await this.store.GetRecords(new[] { binaryData[2] });
+            IList<Record> result3 = await this.store.GetRecords(new[] { binaryData[6] });
+
+            Assert.Equal(1, result1.Count);
+            AssertRecord(result1[0], binaryData[0], binaryData[1], mutationHash1);
+            Assert.Equal(1, result2.Count);
+            AssertRecord(result2[0], binaryData[2], binaryData[5], mutationHash2);
+            Assert.Equal(1, result3.Count);
+            AssertRecord(result3[0], binaryData[6], binaryData[7], mutationHash2);
+        }
+
+        [Fact]
         public async Task AddTransaction_InsertError()
         {
             ByteString mutationHash = await AddTransaction(


--- test/Openchain.Sqlite.Tests/SqliteStorageEngineTests.cs
+++ test/Openchain.Sqlite.Tests/SqliteStorageEngineTests.cs
@@ -22,7 +22,7 @@
 {
     public class SqliteStorageEngineTests
     {
-        private readonly SqliteStorageEngine store;
+        private SqliteStorageEngine store;
         private readonly ByteString[] binaryData =
             Enumerable.Range(0, 10).Select(index => new ByteString(Enumerable.Range(0, 32).Select(i => (byte)index))).ToArray();

@@ -181,6 +181,23 @@
             Assert.False(observer.Fail);
             Assert.Equal(1, observer.Values.Count);
             Assert.Equal(mutation2, GetMutationHash(observer.Values[0]));
+        }
+
+        [Fact]
+        public async Task GetTransactionStream_Error()
+        {
+            // Create a new storage engine with no table so that any query will throw an exception
+            this.store = new SqliteStorageEngine(":memory:");
+            TestObserver observer = new TestObserver() { ExpectedValueCount = 1 };
+
+            IObservable<ByteString> stream = this.store.GetTransactionStream(null);
+            using (stream.Subscribe(observer))
+                await observer.Completed.Task;
+
+            await observer.Disposed.Task;
+
+            Assert.True(observer.Fail);
+            Assert.Equal(0, observer.Values.Count);
         }

         private async Task<ByteString> AddTransaction(params Record[] records)
@@ -224,7 +241,12 @@

             public void OnCompleted() => Disposed.SetResult(0);

-            public void OnError(Exception error) => Fail = true;
+            public void OnError(Exception error)
+            {
+                Fail = true;
+                this.Completed.SetResult(0);
+                Disposed.SetResult(0);
+            }

             public void OnNext(ByteString value)
             {