Update Common package patches and tests

This commit is contained in:
Andy Howard
2026-09-14 11:16:48 +01:00
parent c2660bd5b3
commit 72b96d292b
7 changed files with 349 additions and 6 deletions
@@ -0,0 +1,110 @@
using Microsoft.Data.SqlClient;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Dbas.Base;
using Sarand.Net.Standard.Dbas.Data;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Odbc;
namespace Sacs.UnitTests.Net.Standard.Base.Dbas
{
[TestClass]
public class DatabaseProvider_Tester
{
private class ParameterTestItem : DbDataItem
{
public ParameterTestItem() : base() { }
public override string SchemaName => "dbo";
public override string TableName => "TestItem";
public override void PopulateFrom(DbCommand dbCommand, string tableAlias, string filter) { }
public override void PopulateFrom(DbDataReader dbDataReader) { }
public override bool ExecuteInsertCommand(DbCommand dbCommand) => false;
public void AddParameter<T>(DbCommand command, string name, T value) => AddCommandParameter(command, name, value);
}
// --- Provider Selection ---
[TestMethod]
public void OpenOdbcDatabase_CreatesSqlClientAndForcedOdbcConnections()
{
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig
{
Dbms = DbmsType.MsSql,
DatabaseName = "TestDb",
Location = "MsSql:localhost\\TestDb",
ConnectionString = "Driver={SQL Server};Server=localhost;Database=TestDb;Trusted_Connection=Yes;"
};
SacsDatabase database = SacsDatabaseConsole.OpenOdbcDatabase(config);
using DbConnection sqlConnection = database.CreateConnection();
using DbConnection odbcConnection = database.CreateConnection(true);
Assert.IsInstanceOfType(sqlConnection, typeof(SqlConnection));
StringAssert.Contains(sqlConnection.ConnectionString, "Server=localhost");
StringAssert.Contains(sqlConnection.ConnectionString, "Database=TestDb");
Assert.IsInstanceOfType(odbcConnection, typeof(OdbcConnection));
Assert.AreEqual(config.ConnectionString, odbcConnection.ConnectionString);
}
// --- Command Parameters ---
[TestMethod]
public void AddCommandParameter_AssignsValuesNullsAndExplicitTypes()
{
ParameterTestItem item = new ParameterTestItem();
using SqlCommand command = new SqlCommand();
item.AddParameter(command, "@Count", 12);
item.AddParameter<int?>(command, "@MissingCount", null);
item.AddParameter<byte[]>(command, "@Data", null);
Assert.AreEqual("@Count", command.Parameters[0].ParameterName);
Assert.AreEqual(12, command.Parameters[0].Value);
Assert.AreEqual(DbType.Int32, command.Parameters[0].DbType);
Assert.AreEqual(DBNull.Value, command.Parameters[1].Value);
Assert.AreEqual(DbType.Int32, command.Parameters[1].DbType);
Assert.AreEqual(DBNull.Value, command.Parameters[2].Value);
Assert.AreEqual(DbType.Binary, command.Parameters[2].DbType);
}
[TestMethod]
public void AddCommandParameter_NormalisesSqlAndOdbcDates()
{
ParameterTestItem item = new ParameterTestItem();
DateTime value = new DateTime(2026, 9, 14, 10, 20, 30, 456, DateTimeKind.Utc);
using SqlCommand sqlCommand = new SqlCommand();
using OdbcCommand odbcCommand = new OdbcCommand();
item.AddParameter(sqlCommand, "@When", value);
item.AddParameter(odbcCommand, "When", value);
Assert.AreEqual(DbType.DateTime2, sqlCommand.Parameters[0].DbType);
Assert.AreEqual(DbType.DateTime, odbcCommand.Parameters[0].DbType);
Assert.AreEqual(value.AddMilliseconds(-456), sqlCommand.Parameters[0].Value);
Assert.AreEqual(value.AddMilliseconds(-456), odbcCommand.Parameters[0].Value);
}
[TestMethod]
public void AddCommandParameter_MapsSentinelDatesToDatabaseNull()
{
ParameterTestItem item = new ParameterTestItem();
using SqlCommand command = new SqlCommand();
item.AddParameter(command, "@Minimum", DateTime.MinValue);
item.AddParameter<DateTime?>(command, "@Maximum", DateTime.MaxValue);
item.AddParameter<DateTime?>(command, "@Missing", null);
Assert.AreEqual(DBNull.Value, command.Parameters[0].Value);
Assert.AreEqual(DBNull.Value, command.Parameters[1].Value);
Assert.AreEqual(DBNull.Value, command.Parameters[2].Value);
Assert.AreEqual(DbType.DateTime2, command.Parameters[0].DbType);
Assert.AreEqual(DbType.DateTime2, command.Parameters[1].DbType);
Assert.AreEqual(DbType.DateTime2, command.Parameters[2].DbType);
}
// --- The End ---
}
}
@@ -0,0 +1,113 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sarand.Net.Standard.Base.Utils;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using System;
using System.IO;
using System.Text;
namespace Sacs.UnitTests.Net.Standard.Base.Utils
{
[TestClass]
public class ImageUtils_Tester
{
// --- Image Recognition ---
[TestMethod]
public void VerifyImageData_RecognisesPngAndJpegDimensions()
{
byte[] pngData = CreateImageData(7, 5, new PngEncoder());
byte[] jpegData = CreateImageData(9, 4, new JpegEncoder());
ImageUtils.ImageConfig pngConfig = ImageUtils.VerifyImageData(pngData);
ImageUtils.ImageConfig jpegConfig = ImageUtils.VerifyImageData(jpegData);
Assert.IsTrue(pngConfig.ValidImage);
Assert.AreEqual("PNG", pngConfig.ImageFormatName);
Assert.AreEqual("image/png", pngConfig.DefaultMimeType);
Assert.AreEqual(7, pngConfig.Width);
Assert.AreEqual(5, pngConfig.Height);
Assert.IsTrue(jpegConfig.ValidImage);
Assert.AreEqual("JPEG", jpegConfig.ImageFormatName);
Assert.AreEqual("image/jpeg", jpegConfig.DefaultMimeType);
Assert.AreEqual(9, jpegConfig.Width);
Assert.AreEqual(4, jpegConfig.Height);
}
[TestMethod]
public void VerifyImageData_RejectsInvalidAndTruncatedData()
{
byte[] pngData = CreateImageData(3, 2, new PngEncoder());
byte[] truncatedData = new byte[Math.Min(12, pngData.Length)];
Array.Copy(pngData, truncatedData, truncatedData.Length);
Assert.IsFalse(ImageUtils.VerifyImageData(Array.Empty<byte>()).ValidImage);
Assert.IsFalse(ImageUtils.VerifyImageData(Encoding.UTF8.GetBytes("not an image")).ValidImage);
Assert.IsFalse(ImageUtils.VerifyImageData(truncatedData).ValidImage);
}
[TestMethod]
public void IsSvg_RecognisesSvgAndRejectsFalsePositives()
{
byte[] svgData = Encoding.UTF8.GetBytes("<SVG xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 10 10\"></SVG>");
byte[] missingNamespace = Encoding.UTF8.GetBytes("<svg viewBox=\"0 0 10 10\"></svg>");
Assert.IsTrue(ImageUtils.IsSvg(svgData));
Assert.IsFalse(ImageUtils.IsSvg(missingNamespace));
Assert.IsFalse(ImageUtils.IsSvg(Encoding.UTF8.GetBytes("svg xmlns=\"http://www.w3.org/2000/svg\"")));
Assert.IsFalse(ImageUtils.IsSvg(null));
}
// --- Encoding and Resizing ---
[TestMethod]
public void LoadAndEncodeImage_PreservesFormatAndDimensions()
{
byte[] originalData = CreateImageData(8, 6, new PngEncoder());
using Image image = ImageUtils.LoadImage(originalData, out IImageFormat format);
byte[] encodedData = image.GetImageData(format);
ImageUtils.ImageConfig encodedConfig = ImageUtils.VerifyImageData(encodedData);
Assert.AreEqual("PNG", format.Name);
Assert.IsTrue(encodedConfig.ValidImage);
Assert.AreEqual(8, encodedConfig.Width);
Assert.AreEqual(6, encodedConfig.Height);
}
[TestMethod]
public void ConstrainImage_ResizesLandscapeAndPortraitWithoutUpscaling()
{
ImageUtils.ImageConfig landscape = ImageUtils.VerifyImageData(CreateImageData(20, 10, new PngEncoder()));
ImageUtils.ImageConfig portrait = ImageUtils.VerifyImageData(CreateImageData(10, 20, new PngEncoder()));
ImageUtils.ImageConfig withinLimits = ImageUtils.VerifyImageData(CreateImageData(4, 3, new PngEncoder()));
byte[] originalData = withinLimits.ImageData;
Assert.IsTrue(ImageUtils.ConstrainImage(landscape, 8, 8));
Assert.AreEqual(8, landscape.Width);
Assert.AreEqual(4, landscape.Height);
Assert.IsTrue(ImageUtils.ConstrainImage(portrait, 8, 8));
Assert.AreEqual(4, portrait.Width);
Assert.AreEqual(8, portrait.Height);
Assert.IsTrue(ImageUtils.ConstrainImage(withinLimits, 8, 8));
Assert.AreSame(originalData, withinLimits.ImageData);
Assert.IsFalse(ImageUtils.ConstrainImage(landscape, 0, 8));
Assert.IsFalse(ImageUtils.ConstrainImage(portrait, 8, 0));
}
// --- Utilities ---
private static byte[] CreateImageData(int width, int height, IImageEncoder encoder)
{
using Image<Rgba32> image = new Image<Rgba32>(width, height, new Rgba32(32, 96, 160, 255));
using MemoryStream stream = new MemoryStream();
image.Save(stream, encoder);
return stream.ToArray();
}
// --- The End ---
}
}
@@ -0,0 +1,116 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sacs.UnitTests.Net.Standard.Base.Utils
{
[TestClass]
public class NewtonsoftJsonUtil_Tester
{
private class JsonData
{
public string Name { get; set; }
public int Count { get; set; }
public string Optional { get; set; }
public List<string> Values { get; set; } = new List<string> { "constructor value" };
}
// --- Serialization ---
[TestMethod]
public void SerializeObject_HandlesObjectsArraysNullsAndSettings()
{
JsonData data = new JsonData { Name = "alpha", Count = 3, Optional = null };
JsonSerializerSettings settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
string objectJson = NewtonsoftJsonUtil.SerializeObject(data, settings);
string arrayJson = NewtonsoftJsonUtil.SerializeObject(new[] { 1, 2, 3 });
StringAssert.Contains(objectJson, "\"Name\":\"alpha\"");
Assert.IsFalse(objectJson.Contains("Optional"));
Assert.AreEqual("[1,2,3]", arrayJson);
Assert.AreEqual("null", NewtonsoftJsonUtil.SerializeObject(null));
}
[TestMethod]
public void SysIdJsonConverter_RoundTripsValidAndInvalidValues()
{
string validJson = JsonConvert.SerializeObject(new SysId(42));
string invalidJson = JsonConvert.SerializeObject(new SysId());
SysId validId = JsonConvert.DeserializeObject<SysId>(validJson);
SysId invalidId = JsonConvert.DeserializeObject<SysId>(invalidJson);
Assert.AreEqual("42", validJson);
Assert.AreEqual("0", invalidJson);
Assert.AreEqual(42, validId.ToInt());
Assert.IsFalse(SysId.IsValid(invalidId));
Assert.IsFalse(SysId.IsValid(JsonConvert.DeserializeObject<SysId>("null")));
}
// --- Parsing ---
[TestMethod]
public void ParseJsonMethods_ParseTokensObjectsAndArrays()
{
JToken token = NewtonsoftJsonUtil.ParseJsonToken("123");
JObject jsonObject = NewtonsoftJsonUtil.ParseJsonObject("{\"name\":\"alpha\",\"nested\":{\"enabled\":true}}");
JArray jsonArray = NewtonsoftJsonUtil.ParseJsonArray("[1,2,3]");
Assert.AreEqual(123, token.Value<int>());
Assert.AreEqual("alpha", jsonObject["name"].Value<string>());
Assert.IsTrue(jsonObject["nested"]["enabled"].Value<bool>());
CollectionAssert.AreEqual(new[] { 1, 2, 3 }, jsonArray.ToObject<int[]>());
}
[TestMethod]
public void ParseJsonMethods_ReportInvalidInputWithoutThrowing()
{
Assert.IsNull(NewtonsoftJsonUtil.ParseJsonToken("{", out Exception tokenException));
Assert.IsNotNull(tokenException);
Assert.IsNull(NewtonsoftJsonUtil.ParseJsonObject("[]", out Exception objectException));
Assert.IsNotNull(objectException);
Assert.IsNull(NewtonsoftJsonUtil.ParseJsonArray("{}", out Exception arrayException));
Assert.IsNotNull(arrayException);
Assert.ThrowsException<JsonReaderException>(() => NewtonsoftJsonUtil.ParseJsonToken("{"));
}
[TestMethod]
public void DeserializeJsonObject_ProvidesDynamicPropertyAccess()
{
dynamic data = SacsJsonHelper.DeserializeJsonObject("{\"name\":\"alpha\",\"count\":3,\"items\":[\"a\",\"b\"]}");
Assert.AreEqual("alpha", (string)data.name);
Assert.AreEqual(3, (int)data.count);
Assert.AreEqual("b", (string)data.items[1]);
Assert.IsNull(SacsJsonHelper.DeserializeJsonObject("null"));
}
// --- Deep Copy ---
[TestMethod]
public void DeepCopy_CreatesIndependentNestedCollectionsAndReplacesConstructorValues()
{
JsonData source = new JsonData { Name = "source", Count = 2 };
source.Values.Clear();
source.Values.AddRange(new[] { "one", "two" });
JsonData copy = SerializableUtil.DeepCopy(source);
copy.Values.Add("copy only");
Assert.AreNotSame(source, copy);
Assert.AreNotSame(source.Values, copy.Values);
CollectionAssert.AreEqual(new[] { "one", "two" }, source.Values);
CollectionAssert.AreEqual(new[] { "one", "two", "copy only" }, copy.Values);
Assert.IsNull(SerializableUtil.DeepCopy<JsonData>(null));
Assert.AreEqual(String.Empty, SerializableUtil.ToJson<JsonData>(null));
}
// --- The End ---
}
}