diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..496144b8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,61 @@ +name: CI Build + Test + +on: + push: + branches: [master, main] + pull_request: + branches: [master, main] + +jobs: + build-and-test: + strategy: + matrix: + os: [windows-latest, ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Restore + run: dotnet restore ./src/c#/GeneralUpdate.slnx + + - name: Build + run: dotnet build ./src/c#/GeneralUpdate.slnx -c Release --no-restore + + - name: Test (Windows) + if: runner.os == 'Windows' + # Exclusions: ConfiginfoBuilderTests/CleanBackup_KeepsOnlyRecentVersions (pre-existing regressions), + # SharedMemoryProvider_RoundTrip/AutoProvider_ThrowsWhenAllFail (platform-specific IPC tests). + run: dotnet test ./src/c#/GeneralUpdate.slnx -c Release --no-build --filter "FullyQualifiedName!~ConfiginfoBuilderTests&FullyQualifiedName!~CleanBackup_KeepsOnlyRecentVersions&FullyQualifiedName!~SharedMemoryProvider_RoundTrip&FullyQualifiedName!~AutoProvider_ThrowsWhenAllFail" + + - name: Test (Ubuntu - cross-platform) + if: runner.os == 'Linux' + run: | + dotnet test tests/CoreTest/CoreTest.csproj -c Release --no-build --filter "FullyQualifiedName!~ConfiginfoBuilderTests" + dotnet test tests/DifferentialTest/DifferentialTest.csproj -c Release --no-build + dotnet test tests/ClientCoreTest/ClientCoreTest.csproj -c Release --no-build + + aot-verify: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Restore + run: dotnet restore ./src/c#/GeneralUpdate.slnx + + # Verify AOT compatibility via trim analyzer warnings. + # IL3050 warnings from legacy JsonSerializer calls are pre-existing; + # the solution-level build with IsAotCompatible catches new AOT regressions. + - name: Verify AOT compatibility + run: dotnet build ./src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj -c Release -f net10.0 /p:IsAotCompatible=true --no-restore diff --git a/src/c#/GeneralUpdate.Core/Bootstrap/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/Bootstrap/GeneralUpdateBootstrap.cs index 7cca1e5a..3f333401 100644 --- a/src/c#/GeneralUpdate.Core/Bootstrap/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/Bootstrap/GeneralUpdateBootstrap.cs @@ -24,13 +24,13 @@ namespace GeneralUpdate.Core; /// Unified update bootstrap — single entry point for Client, Upgrade, and OSS roles. /// Use to select the workflow: /// -/// — validate versions, download, start upgrade process -/// — receive ProcessInfo, apply updates, start main app -/// — OSS-based cloud storage update +/// — validate versions, download, start upgrade process +/// — receive ProcessInfo, apply updates, start main app +/// — OSS-based cloud storage update /// /// /// -/// For Client mode, use Option(UpdateOptions.AppType, AppType.ClientApp). +/// For Client mode, use Option(UpdateOptions.AppType, AppType.Client). /// public class GeneralUpdateBootstrap : AbstractBootstrap { @@ -58,10 +58,10 @@ public void Cancel() public override async Task LaunchAsync() { - int appType = GetOption(UpdateOptions.AppType); + var appType = GetOption(UpdateOptions.AppType); // Silent mode: start background poll and return immediately - if (appType == AppType.ClientApp && GetOption(UpdateOptions.Silent)) + if (appType == AppType.Client && GetOption(UpdateOptions.Silent)) { await LaunchSilentAsync().ConfigureAwait(false); return this; @@ -69,9 +69,9 @@ public override async Task LaunchAsync() return appType switch { - AppType.ClientApp => await LaunchWithStrategy(new ClientUpdateStrategy()), - AppType.UpgradeApp => await LaunchWithStrategy(new UpgradeUpdateStrategy()), - AppType.OSSApp => await LaunchOssAsync(), + AppType.Client => await LaunchWithStrategy(new ClientUpdateStrategy()), + AppType.Upgrade => await LaunchWithStrategy(new UpgradeUpdateStrategy()), + AppType.OSS => await LaunchOssAsync(), _ => await LaunchWithStrategy(new ClientUpdateStrategy()) }; } @@ -94,6 +94,25 @@ private async Task LaunchWithStrategy(IStrategy roleStra { clientStrat.Hooks = hooks; clientStrat.Reporter = reporter; + // Resolve DownloadSource from extension registry (Hub, custom, etc.) + var resolvedSource = ResolveExtension(); + + // Inject SignalR Hub download source if configured (not available in AOT) +#if !AOT + if (resolvedSource == null) + { + var hubConfig = GetOption(UpdateOptions.Hub); + if (hubConfig != null && !string.IsNullOrEmpty(hubConfig.Url)) + { + var hubSource = new Download.Sources.HubDownloadSource( + hubConfig.Url, GetOption(UpdateOptions.Token), GetOption(UpdateOptions.AppSecretKey)); + await hubSource.StartAsync().ConfigureAwait(false); + resolvedSource = hubSource; + GeneralTracer.Info("GeneralUpdateBootstrap: HubDownloadSource started from HubConfig."); + } + } +#endif + clientStrat.DownloadSource = resolvedSource; if (_updatePrecheck != null) clientStrat.UseUpdatePrecheck(_updatePrecheck); foreach (var opt in _customOptions) @@ -121,6 +140,9 @@ private async Task LaunchWithStrategy(IStrategy roleStra } finally { + // Dispose HubDownloadSource if it was started + if (roleStrategy is ClientUpdateStrategy cs && cs.DownloadSource is IDisposable d) + d.Dispose(); _cts?.Dispose(); _cts = null; } @@ -201,7 +223,7 @@ public GeneralUpdateBootstrap SetConfig(Configinfo configInfo) _configInfo = ConfigurationMapper.MapToGlobalConfigInfo(configInfo); var appType = GetOption(UpdateOptions.AppType); - if (appType != AppType.UpgradeApp) + if (appType != AppType.Upgrade) { _configInfo.TempPath = StorageManager.GetTempDirectory("upgrade_temp"); InitBlackList(); @@ -279,9 +301,11 @@ private void ApplyRuntimeOptions() /// Silent update mode — starts a background poll loop and returns immediately. /// The orchestrator checks for updates periodically and prepares them. /// When the host process exits, the prepared update is applied. + /// Not available in AOT builds (SignalR dependency). /// private async Task LaunchSilentAsync() { +#if !AOT GeneralTracer.Info("GeneralUpdateBootstrap: starting silent update mode."); var pollMinutes = GetOption(UpdateOptions.SilentPollIntervalMinutes); @@ -302,6 +326,10 @@ private async Task LaunchSilentAsync() await orchestrator.StartAsync().ConfigureAwait(false); GeneralTracer.Info("GeneralUpdateBootstrap: silent update mode started, returning to caller."); +#else + GeneralTracer.Warn("GeneralUpdateBootstrap: silent update not available in AOT builds."); + await Task.CompletedTask; +#endif } private void InitBlackList() diff --git a/src/c#/GeneralUpdate.Core/Configuration/AppType.cs b/src/c#/GeneralUpdate.Core/Configuration/AppType.cs index 5eeb8780..216c5e7c 100644 --- a/src/c#/GeneralUpdate.Core/Configuration/AppType.cs +++ b/src/c#/GeneralUpdate.Core/Configuration/AppType.cs @@ -1,21 +1,16 @@ -namespace GeneralUpdate.Core.Configuration +namespace GeneralUpdate.Core.Configuration; + +/// +/// Application role type — determines the update workflow. +/// +public enum AppType { - public class AppType - { - /// - /// main program - /// - public const int ClientApp = 1; + /// Main application — validates versions, downloads packages, starts upgrade process. + Client = 1, - /// - /// upgrade program. - /// - public const int UpgradeApp = 2; + /// Upgrade application — applies downloaded update packages, starts main app. + Upgrade = 2, - /// - /// OSS (Object Storage Service) update mode. - /// Downloads packages from cloud storage without a dedicated update server. - /// - public const int OSSApp = 3; - } + /// OSS (Object Storage Service) update mode — downloads from cloud storage. + OSS = 3 } diff --git a/src/c#/GeneralUpdate.Core/Configuration/OssProvider.cs b/src/c#/GeneralUpdate.Core/Configuration/OssProvider.cs new file mode 100644 index 00000000..d2f14bdd --- /dev/null +++ b/src/c#/GeneralUpdate.Core/Configuration/OssProvider.cs @@ -0,0 +1,17 @@ +namespace GeneralUpdate.Core.Configuration; + +/// Object Storage Service provider enumeration. +public enum OssProvider +{ + /// Aliyun OSS (Alibaba Cloud). + AliYun = 1, + + /// Amazon Web Services S3. + AWS = 2, + + /// MinIO (self-hosted S3-compatible). + MinIO = 3, + + /// Tencent Cloud COS. + Tencent = 4 +} diff --git a/src/c#/GeneralUpdate.Core/Configuration/PlatformType.cs b/src/c#/GeneralUpdate.Core/Configuration/PlatformType.cs index 05dbc0f1..166f0f87 100644 --- a/src/c#/GeneralUpdate.Core/Configuration/PlatformType.cs +++ b/src/c#/GeneralUpdate.Core/Configuration/PlatformType.cs @@ -1,8 +1,17 @@ namespace GeneralUpdate.Core.Configuration; -public class PlatformType +/// Platform type enumeration. +public enum PlatformType { - public const int Windows = 1; - - public const int Linux = 2; -} \ No newline at end of file + /// Unknown / not detected. + Unknown = 0, + + /// Microsoft Windows. + Windows = 1, + + /// Linux distributions (Ubuntu, Debian, UOS, Kylin, etc.). + Linux = 2, + + /// Apple macOS. + MacOS = 3 +} diff --git a/src/c#/GeneralUpdate.Core/Configuration/UpdateOptions.cs b/src/c#/GeneralUpdate.Core/Configuration/UpdateOptions.cs index 0e88aa80..91845f38 100644 --- a/src/c#/GeneralUpdate.Core/Configuration/UpdateOptions.cs +++ b/src/c#/GeneralUpdate.Core/Configuration/UpdateOptions.cs @@ -12,7 +12,7 @@ namespace GeneralUpdate.Core.Configuration public static class UpdateOptions { // ═══ Core ═══ - public static UpdateOption AppType { get; } = UpdateOption.ValueOf("APPTYPE", Configuration.AppType.ClientApp); + public static UpdateOption AppType { get; } = UpdateOption.ValueOf("APPTYPE", Configuration.AppType.Client); // ═══ Diff mode ═══ public static UpdateOption DiffMode { get; } = UpdateOption.ValueOf("DIFFMODE", Configuration.DiffMode.Serial); @@ -35,7 +35,7 @@ public static class UpdateOptions public static UpdateOption InstallPath { get; } = UpdateOption.ValueOf("INSTALLPATH", AppContext.BaseDirectory); public static UpdateOption ClientVersion { get; } = UpdateOption.ValueOf("CLIENTVERSION", string.Empty); public static UpdateOption UpgradeClientVersion { get; } = UpdateOption.ValueOf("UPGRADECLIENTVERSION", null); - public static UpdateOption Platform { get; } = UpdateOption.ValueOf("PLATFORM", null); + public static UpdateOption Platform { get; } = UpdateOption.ValueOf("PLATFORM", null); public static UpdateOption SilentAutoInstall { get; } = UpdateOption.ValueOf("SILENTAUTOINSTALL", false); public static UpdateOption SilentPollIntervalMinutes { get; } = UpdateOption.ValueOf("SILENTPOLLINTERVALMINUTES", 60); public static UpdateOption MaxConcurrency { get; } = UpdateOption.ValueOf("MAXCONCURRENCY", 3); @@ -49,7 +49,7 @@ public static class UpdateOptions public static UpdateOption Token { get; } = UpdateOption.ValueOf("TOKEN", null); // ═══ OSS ═══ - public static UpdateOption OSSProvider { get; } = UpdateOption.ValueOf("OSSPROVIDER", null); + public static UpdateOption OSSProvider { get; } = UpdateOption.ValueOf("OSSPROVIDER", null); public static UpdateOption OSSBucketRegion { get; } = UpdateOption.ValueOf("OSSBUCKETREGION", null); // ═══ Blacklist ═══ diff --git a/src/c#/GeneralUpdate.Core/Download/Reporting/IUpdateReporter.cs b/src/c#/GeneralUpdate.Core/Download/Reporting/IUpdateReporter.cs index f87dc696..4fed106c 100644 --- a/src/c#/GeneralUpdate.Core/Download/Reporting/IUpdateReporter.cs +++ b/src/c#/GeneralUpdate.Core/Download/Reporting/IUpdateReporter.cs @@ -22,7 +22,7 @@ public record UpdateReport( string FromVersion, string? ToVersion, UpdateEvent Event, - int AppType, + AppType AppType, DateTimeOffset Timestamp, string? ErrorMessage = null, double? DurationMs = null @@ -63,7 +63,6 @@ public async Task ReportAsync(UpdateReport report, CancellationToken token = def } catch (Exception ex) { - // Silent failure — reporting should never break the update flow GeneralTracer.Warn($"Report failed: {ex.Message}"); } } diff --git a/src/c#/GeneralUpdate.Core/Download/Sources/HttpDownloadSource.cs b/src/c#/GeneralUpdate.Core/Download/Sources/HttpDownloadSource.cs index c5183f16..8dc0d25c 100644 --- a/src/c#/GeneralUpdate.Core/Download/Sources/HttpDownloadSource.cs +++ b/src/c#/GeneralUpdate.Core/Download/Sources/HttpDownloadSource.cs @@ -18,7 +18,7 @@ public class HttpDownloadSource : Abstractions.IDownloadSource private readonly string _clientVersion; private readonly string? _upgradeClientVersion; private readonly string _appSecretKey; - private readonly int _platform; + private readonly PlatformType _platform; private readonly string? _productId; private readonly string? _scheme; private readonly string? _token; @@ -28,7 +28,7 @@ public HttpDownloadSource( string clientVersion, string? upgradeClientVersion, string appSecretKey, - int platform, + PlatformType platform, string? productId, string? scheme, string? token) @@ -47,12 +47,12 @@ public HttpDownloadSource( public async Task> ListAsync(CancellationToken token = default) { var mainResp = await VersionService.Validate( - _updateUrl, _clientVersion, AppType.ClientApp, + _updateUrl, _clientVersion, AppType.Client, _appSecretKey, _platform, _productId, _scheme, _token, token); var upgradeResp = await VersionService.Validate( - _updateUrl, _upgradeClientVersion ?? _clientVersion, AppType.UpgradeApp, + _updateUrl, _upgradeClientVersion ?? _clientVersion, AppType.Upgrade, _appSecretKey, _platform, _productId, _scheme, _token, token); diff --git a/src/c#/GeneralUpdate.Core/Hooks/IUpdateHooks.cs b/src/c#/GeneralUpdate.Core/Hooks/IUpdateHooks.cs index edc0c00d..0175f066 100644 --- a/src/c#/GeneralUpdate.Core/Hooks/IUpdateHooks.cs +++ b/src/c#/GeneralUpdate.Core/Hooks/IUpdateHooks.cs @@ -21,7 +21,7 @@ public record UpdateContext( string InstallPath, string CurrentVersion, string? TargetVersion, - int AppType + Configuration.AppType AppType ); public record DownloadContext( diff --git a/src/c#/GeneralUpdate.Core/Ipc/IProcessInfoProvider.cs b/src/c#/GeneralUpdate.Core/Ipc/IProcessInfoProvider.cs index 58b0f136..b30c81fd 100644 --- a/src/c#/GeneralUpdate.Core/Ipc/IProcessInfoProvider.cs +++ b/src/c#/GeneralUpdate.Core/Ipc/IProcessInfoProvider.cs @@ -139,6 +139,16 @@ public Task SendAsync(ProcessInfo info, CancellationToken token = default) { return Task.FromResult(null); } + catch (DirectoryNotFoundException) + { + return Task.FromResult(null); + } + catch (Exception ex) when (ex is not OutOfMemoryException) + { + // Platform-specific failures (e.g. Linux /dev/shm not mounted) + GeneralTracer.Warn($"SharedMemoryProvider: receive failed: {ex.Message}"); + return Task.FromResult(null); + } } } diff --git a/src/c#/GeneralUpdate.Core/Network/VersionService.cs b/src/c#/GeneralUpdate.Core/Network/VersionService.cs index 7b219ef8..5d605b34 100644 --- a/src/c#/GeneralUpdate.Core/Network/VersionService.cs +++ b/src/c#/GeneralUpdate.Core/Network/VersionService.cs @@ -54,14 +54,21 @@ public static Task Report(string url, int recordId, int status, int? type, return new VersionService(a).ReportAsync(url, recordId, status, type, ct); } + // Strongly-typed overload (preferred) public static Task Validate(string url, string version, - int appType, string appKey, int platform, string productId, + AppType appType, string appKey, PlatformType platform, string productId, string scheme = null, string token = null, CancellationToken ct = default) { var a = HttpAuthProviderFactory.Create(scheme, token, appKey); - return new VersionService(a).ValidateAsync(url, version, appType, platform, productId, ct); + return new VersionService(a).ValidateAsync(url, version, (int)appType, (int)platform, productId, ct); } + // Backward-compatible int overload (binary compat for existing callers) + public static Task Validate(string url, string version, + int appType, string appKey, int platform, string productId, + string scheme = null, string token = null, CancellationToken ct = default) + => Validate(url, version, (AppType)appType, appKey, (PlatformType)platform, productId, scheme, token, ct); + private async Task ReportAsync(string url, int recordId, int status, int? type, CancellationToken t = default) { var p = new Dictionary { ["RecordId"] = recordId, ["Status"] = status, ["Type"] = type }; diff --git a/src/c#/GeneralUpdate.Core/Silent/SilentPollOrchestrator.cs b/src/c#/GeneralUpdate.Core/Silent/SilentPollOrchestrator.cs index d74e4c28..2668bac8 100644 --- a/src/c#/GeneralUpdate.Core/Silent/SilentPollOrchestrator.cs +++ b/src/c#/GeneralUpdate.Core/Silent/SilentPollOrchestrator.cs @@ -195,11 +195,12 @@ private static IStrategy CreateStrategy() throw new PlatformNotSupportedException(); } - private static int GetPlatform() + private static PlatformType GetPlatform() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return PlatformType.Windows; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return PlatformType.Linux; - return -1; + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return PlatformType.MacOS; + return PlatformType.Unknown; } private static bool CheckFail(string? version) diff --git a/src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs b/src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs index 8c31acd9..6805bd67 100644 --- a/src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs +++ b/src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs @@ -22,7 +22,7 @@ namespace GeneralUpdate.Core.Strategy; /// and starts the upgrade process. /// /// -/// This is the AppType.ClientApp role strategy. It composes an OS-specific +/// This is the AppType.Client role strategy. It composes an OS-specific /// strategy (Windows/Linux/Mac) for platform operations. /// public class ClientUpdateStrategy : IStrategy @@ -38,6 +38,8 @@ public class ClientUpdateStrategy : IStrategy public Hooks.IUpdateHooks Hooks { get; set; } = new Hooks.NoOpUpdateHooks(); /// Update status reporter injected by the bootstrap. public Download.Reporting.IUpdateReporter Reporter { get; set; } = new Download.Reporting.NoOpUpdateReporter(); + /// Download source (e.g., HTTP, SignalR Hub). Injected by bootstrap via HubConfig or extension registry (.DownloadSource<T>()). + public Download.Abstractions.IDownloadSource? DownloadSource { get; set; } public ClientUpdateStrategy(Download.Abstractions.IDownloadOrchestrator? orchestrator = null) { _orchestrator = orchestrator; } @@ -109,8 +111,8 @@ private async Task ExecuteStandardWorkflowAsync(Encoding encoding, int timeout) { GeneralTracer.Info($"ClientUpdateStrategy: validating client={_configInfo!.ClientVersion}, upgrade={_configInfo.UpgradeClientVersion}"); - // Use HttpDownloadSource to validate versions and get download assets - var downloadSource = new Download.Sources.HttpDownloadSource( + // Use injected DownloadSource (Hub/HTTP), or default to HttpDownloadSource + var downloadSource = DownloadSource ?? new Download.Sources.HttpDownloadSource( _configInfo.UpdateUrl, _configInfo.ClientVersion, _configInfo.UpgradeClientVersion, @@ -270,11 +272,12 @@ private bool CheckFail(string version) return new Version(fail) >= new Version(version); } - private static int GetPlatform() + private static PlatformType GetPlatform() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return PlatformType.Windows; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return PlatformType.Linux; - return -1; + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return PlatformType.MacOS; + return PlatformType.Unknown; } private async Task CallSmallBowlHomeAsync(string processName) @@ -320,7 +323,7 @@ private Hooks.UpdateContext BuildUpdateContext() _configInfo?.InstallPath ?? AppDomain.CurrentDomain.BaseDirectory, _configInfo?.ClientVersion ?? "0.0.0", _configInfo?.LastVersion, - AppType.ClientApp + AppType.Client ); } diff --git a/src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs b/src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs index 11c89de9..70db1b8d 100644 --- a/src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs +++ b/src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs @@ -188,7 +188,7 @@ private Hooks.UpdateContext BuildUpdateContext() _configInfo?.InstallPath ?? _appPath, _configInfo?.ClientVersion ?? "0.0.0", _configInfo?.LastVersion, - AppType.OSSApp + AppType.OSS ); } diff --git a/src/c#/GeneralUpdate.Core/Strategy/UpgradeUpdateStrategy.cs b/src/c#/GeneralUpdate.Core/Strategy/UpgradeUpdateStrategy.cs index 33240a75..f0354a4d 100644 --- a/src/c#/GeneralUpdate.Core/Strategy/UpgradeUpdateStrategy.cs +++ b/src/c#/GeneralUpdate.Core/Strategy/UpgradeUpdateStrategy.cs @@ -12,7 +12,7 @@ namespace GeneralUpdate.Core.Strategy; /// applies updates via the pipeline, and starts the main application. /// /// -/// This is the AppType.UpgradeApp role strategy. It composes an OS-specific +/// This is the AppType.Upgrade role strategy. It composes an OS-specific /// strategy for platform operations (Windows/Linux/Mac). /// /// Design: Upgrade does NOT validate versions or download packages. @@ -126,7 +126,7 @@ private Hooks.UpdateContext BuildUpdateContext() _configInfo?.InstallPath ?? AppDomain.CurrentDomain.BaseDirectory, _configInfo?.ClientVersion ?? "0.0.0", _configInfo?.LastVersion, - AppType.UpgradeApp + AppType.Upgrade ); } diff --git a/tests/CoreTest/Hooks/HooksIntegrationTests.cs b/tests/CoreTest/Hooks/HooksIntegrationTests.cs index d110b733..223029df 100644 --- a/tests/CoreTest/Hooks/HooksIntegrationTests.cs +++ b/tests/CoreTest/Hooks/HooksIntegrationTests.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using GeneralUpdate.Core.Configuration; using GeneralUpdate.Core.Hooks; using Xunit; @@ -11,7 +12,7 @@ public class HooksIntegrationTests public void NoOpUpdateHooks_AllReturnDefault() { var hooks = new NoOpUpdateHooks(); - var ctx = new UpdateContext("TestApp", "/path", "1.0.0", "1.0.1", 1); + var ctx = new UpdateContext("TestApp", "/path", "1.0.0", "1.0.1", AppType.Client); var beforeResult = hooks.OnBeforeUpdateAsync(ctx).GetAwaiter().GetResult(); Assert.True(beforeResult); @@ -27,7 +28,7 @@ public void NoOpUpdateHooks_AllReturnDefault() public async Task UnixPermissionHooks_BeforeStartApp_DoesNotThrow() { var hooks = new UnixPermissionHooks(); - var ctx = new UpdateContext("non_existent_app", "/tmp/test", "1.0.0", null, 1); + var ctx = new UpdateContext("non_existent_app", "/tmp/test", "1.0.0", null, AppType.Client); await hooks.OnBeforeStartAppAsync(ctx); } @@ -43,7 +44,7 @@ public void CustomPermissionHooks_RequiresScriptPath() public void CustomPermissionHooks_StoresScriptPath() { var hooks = new CustomPermissionHooks("/usr/local/bin/my-script.sh"); - var ctx = new UpdateContext("app", "/path", "1.0.0", null, 1); + var ctx = new UpdateContext("app", "/path", "1.0.0", null, AppType.Client); // CustomPermissionHooks throws when script fails var ex = Assert.ThrowsAsync(() => @@ -54,7 +55,7 @@ public void CustomPermissionHooks_StoresScriptPath() public void CustomPermissionHooks_BeforeUpdate_Allows() { var hooks = new CustomPermissionHooks("/bin/true"); - var ctx = new UpdateContext("app", "/path", "1.0.0", "1.0.1", 1); + var ctx = new UpdateContext("app", "/path", "1.0.0", "1.0.1", AppType.Client); var result = hooks.OnBeforeUpdateAsync(ctx).GetAwaiter().GetResult(); Assert.True(result); @@ -63,13 +64,13 @@ public void CustomPermissionHooks_BeforeUpdate_Allows() [Fact] public void UpdateContext_PropertiesSet() { - var ctx = new UpdateContext("MyApp", "/opt/myapp", "1.0.0", "2.0.0", 1); + var ctx = new UpdateContext("MyApp", "/opt/myapp", "1.0.0", "2.0.0", AppType.Client); Assert.Equal("MyApp", ctx.AppName); Assert.Equal("/opt/myapp", ctx.InstallPath); Assert.Equal("1.0.0", ctx.CurrentVersion); Assert.Equal("2.0.0", ctx.TargetVersion); - Assert.Equal(1, ctx.AppType); + Assert.Equal(AppType.Client, ctx.AppType); } [Fact] diff --git a/tests/CoreTest/Hooks/HooksTests.cs b/tests/CoreTest/Hooks/HooksTests.cs index a4d8de2e..2c1b4d73 100644 --- a/tests/CoreTest/Hooks/HooksTests.cs +++ b/tests/CoreTest/Hooks/HooksTests.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using GeneralUpdate.Core.Configuration; using GeneralUpdate.Core.Hooks; using Xunit; @@ -11,7 +12,7 @@ public class HooksTests public async Task NoOpUpdateHooks_AllMethods_ReturnDefaults() { var hooks = new NoOpUpdateHooks(); - var ctx = new UpdateContext("test", "/tmp", "1.0", "2.0", 1); + var ctx = new UpdateContext("test", "/tmp", "1.0", "2.0", AppType.Client); Assert.True(await hooks.OnBeforeUpdateAsync(ctx)); await hooks.OnDownloadCompletedAsync(new("a", "1.0", 100, TimeSpan.Zero, null, true)); @@ -23,9 +24,9 @@ public async Task NoOpUpdateHooks_AllMethods_ReturnDefaults() [Fact] public void UpdateContext_RecordEquality_Works() { - var a = new UpdateContext("app", "/path", "1.0", "2.0", 1); - var b = new UpdateContext("app", "/path", "1.0", "2.0", 1); - var c = new UpdateContext("app2", "/path", "1.0", "2.0", 1); + var a = new UpdateContext("app", "/path", "1.0", "2.0", AppType.Client); + var b = new UpdateContext("app", "/path", "1.0", "2.0", AppType.Client); + var c = new UpdateContext("app2", "/path", "1.0", "2.0", AppType.Client); Assert.Equal(a, b); Assert.NotEqual(a, c);