using System.Globalization; using System.IO; using System.Windows; using Newtonsoft.Json; using Store.Management.Framework.Controls; using Store.Management.Framework.Converters; using Store.Management.Framework.Services; using Store.Management.Framework.Utilities; using Store.Management.Framework.Configs; internal static class Program { [STAThread] private static void Main() { int count = 0; var cleanup = new DisposeAction(() => Interlocked.Increment(ref count)); Parallel.For(0, 100, _ => cleanup.Dispose()); Check(count == 1, "Concurrent cleanup"); VerifyEvents().GetAwaiter().GetResult(); string? crashPath = ApplicationLogService.WriteFatal(new InvalidOperationException("smoke-crash-marker"), "SmokeTest"); Check(crashPath != null && File.ReadAllText(crashPath).Contains("smoke-crash-marker"), "Crash report without logger initialization"); File.Delete(crashPath!); Check(Path.IsPathFullyQualified(FolderConfig.ConfigFolder), "Absolute config directory"); Check(FolderConfig.AppSettingsFilePath == Path.Combine(FolderConfig.ConfigFolder, "AppSettings.json"), "Settings location"); Check(new DefaultPathSettings().FilePath == Path.Combine(FolderConfig.ConfigFolder, "SettingsModel.json"), "Default model location"); foreach (string invalid in new[] { "../escape.json", "D:\\escape.json", "..", "config.json." }) { try { FolderConfig.GetSettingsFilePath(invalid); throw new Exception("Expected invalid filename error"); } catch (ArgumentException) { } } string directory = Path.Combine(Path.GetTempPath(), "StoreFramework-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(directory); try { string file = Path.Combine(directory, "settings.JSON"); var settings = new TestSettings(file); settings.LoadSettings(); Check(settings.Model.Value == 7, "Missing settings defaults"); settings.Model.Value = 42; settings.SaveSettings(); var reloaded = new TestSettings(file); reloaded.LoadSettingsAsync().GetAwaiter().GetResult(); Check(reloaded.Model.Value == 42, "Settings roundtrip"); Task.WhenAll(Enumerable.Range(0, 10).Select(_ => settings.SaveSettingsAsync())).GetAwaiter().GetResult(); Check(Directory.GetFiles(directory, "*.tmp").Length == 0, "Temporary file cleanup"); File.WriteAllText(file, "{broken"); try { reloaded.LoadSettings(); throw new Exception("Expected JSON error"); } catch (JsonException) { } Check(reloaded.Model.Value == 42, "Corrupt settings preserve model"); File.WriteAllText(file, "null"); try { reloaded.LoadSettings(); throw new Exception("Expected null error"); } catch (JsonException) { } string[] args = [file]; AppArgsService.Initialize(args); args[0] = "changed"; Check(AppArgsService.GetArgs()[0] == file, "Arguments snapshot"); Check(AppArgsService.GetFilePaths("json").Single() == file, "Extension case"); Check(AppArgsService.GetFilePaths(".JSON").Single() == file, "Dotted extension"); try { AppArgsService.GetFilePaths("."); throw new Exception("Expected invalid extension error"); } catch (ArgumentException) { } } finally { Directory.Delete(directory, recursive: true); } var grid = new AutoColumnsUniformGrid { CellMinWidth = 200, MinColumns = 2, MaxColumns = 4 }; grid.Measure(new Size(1000, 500)); Check(grid.Columns == 4, "Maximum columns"); grid.Measure(new Size(100, 500)); Check(grid.Columns == 2, "Minimum columns"); grid.MaxColumns = 1; grid.Measure(new Size(1000, 500)); Check(grid.Columns == 2, "Conflicting bounds"); try { grid.CellMinWidth = double.NaN; throw new Exception("Expected invalid width error"); } catch (ArgumentException) { } var converter = new StringNullOrEmpty2VisibilityConverter(); Check(Equals(converter.Convert(null!, typeof(Visibility), null!, CultureInfo.InvariantCulture), Visibility.Visible), "Null placeholder"); Check(Equals(converter.Convert("value", typeof(Visibility), null!, CultureInfo.InvariantCulture), Visibility.Collapsed), "Nonempty placeholder"); Console.WriteLine("PASS: cleanup, async events, settings, arguments, WPF layout and converter boundaries."); } private static async Task VerifyEvents() { var events = new AsyncEvent(); var calls = new List(); Func second = (_, _) => { calls.Add(2); return Task.CompletedTask; }; events.Subscribe(async (_, _) => { await Task.Yield(); calls.Add(1); events.Unsubscribe(second); }); events.Subscribe(second); await events.InvokeAsync(null, EventArgs.Empty); Check(calls.SequenceEqual([1, 2]), "Event snapshot and order"); calls.Clear(); await events.InvokeAsync(null, EventArgs.Empty); Check(calls.SequenceEqual([1]), "Event unsubscribe"); } private static void Check(bool result, string message) { if (!result) throw new Exception(message); } } public sealed class SettingsModel { public int Value { get; set; } = 7; } internal sealed class TestSettings(string path) : JsonSettingsServiceBase { public override string FilePath => path; public override SettingsModel GetDefaultModel() => new(); } internal sealed class DefaultPathSettings : JsonSettingsServiceBase { public override SettingsModel GetDefaultModel() => new(); }