Skip to content

Commit

Permalink
Merge pull request #94 from mikecarr/master
Browse files Browse the repository at this point in the history
Merge latest
  • Loading branch information
mikecarr authored Feb 26, 2025
2 parents 4e80307 + ddd1f7f commit b7a7ad0
Show file tree
Hide file tree
Showing 13 changed files with 308 additions and 82 deletions.
1 change: 1 addition & 0 deletions OpenIPC_Config.Android/OpenIPC_Config.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<PackageReference Include="Avalonia.Android" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Svg.Skia" Version="11.2.0.2"/>
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/>
Expand Down
1 change: 1 addition & 0 deletions OpenIPC_Config.Browser/OpenIPC_Config.Browser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<PackageReference Include="Avalonia.Browser" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Svg.Skia" Version="11.2.0.2"/>
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
Expand Down
1 change: 1 addition & 0 deletions OpenIPC_Config.Desktop/OpenIPC_Config.Desktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Svg.Skia" Version="11.2.0.2"/>
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/>
Expand Down
1 change: 1 addition & 0 deletions OpenIPC_Config.Tests/OpenIPC_Config.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<PackageReference Include="Avalonia.Desktop" Version="0.10.13"/>
<PackageReference Include="Avalonia.Svg.Skia" Version="11.2.0.2"/>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="Moq" Version="4.20.72"/>
Expand Down
97 changes: 97 additions & 0 deletions OpenIPC_Config.Tests/Services/GitHubServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using Microsoft.Extensions.Caching.Memory;
using Moq;
using NUnit.Framework;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Moq.Protected;
using OpenIPC_Config.Services;
using Xunit;
using Assert = NUnit.Framework.Assert;

public class GitHubServiceTests
{
private readonly Mock<HttpMessageHandler> _httpMessageHandlerMock;
private readonly HttpClient _httpClient;
private readonly IMemoryCache _memoryCache;
private readonly GitHubService _gitHubService;

public GitHubServiceTests()
{
_httpMessageHandlerMock = new Mock<HttpMessageHandler>();
_httpClient = new HttpClient(_httpMessageHandlerMock.Object);
_memoryCache = new MemoryCache(new MemoryCacheOptions());
_gitHubService = new GitHubService(_memoryCache, _httpClient);
}

[Fact]
public async Task GetGitHubDataAsync_ReturnsDataFromCache_WhenAvailable()
{
// Arrange
string url = "https://api.github.com/repos/example/repo";
string cachedData = "cached response";
_memoryCache.Set("GitHubData", cachedData, TimeSpan.FromMinutes(60));

// Act
string result = await _gitHubService.GetGitHubDataAsync(url);

// Assert
Assert.That(cachedData, Is.EqualTo(result));
}

[Fact]
public async Task GetGitHubDataAsync_FetchesFromGitHub_WhenNotCached()
{
// Arrange
string url = "https://api.github.com/repos/example/repo";
string apiResponse = "api response";
// string cachedData = "cached response";
// _memoryCache.Set("GitHubData", cachedData, TimeSpan.FromMinutes(60));

_httpMessageHandlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(apiResponse)
});

// Act
string result = await _gitHubService.GetGitHubDataAsync(url);

// Assert
Assert.That(apiResponse, Is.EqualTo(result));
_memoryCache.TryGetValue("GitHubData", out string cachedResult);

// Assert.True(_memoryCache.TryGetValue("GitHubData", out string cachedResult));
Assert.That(apiResponse, Is.EqualTo(cachedResult)); // Assert that the cached data matches the API response cachedResult);
}

[Fact]
public async Task GetGitHubDataAsync_ReturnsNull_OnHttpRequestException()
{
// Arrange
string url = "https://api.github.com/repos/example/repo";

_httpMessageHandlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.ThrowsAsync(new HttpRequestException("Network error"));

// Act
string result = await _gitHubService.GetGitHubDataAsync(url);

// Assert
Assert.Null(result);
}
}
5 changes: 3 additions & 2 deletions OpenIPC_Config.Tests/ViewModels/FirmwareTabViewModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class FirmwareTabViewModelTests
private Mock<ILogger> _mockLogger;
private Mock<ISshClientService> _mockSshClientService;
private Mock<IEventSubscriptionService> _mockEventSubscriptionService;
private Mock<GitHubService> _mockGithubService;

[SetUp]
public void Setup()
Expand All @@ -24,10 +25,10 @@ public void Setup()
_viewModel = new FirmwareTabViewModel(
_mockLogger.Object,
_mockSshClientService.Object,
_mockEventSubscriptionService.Object);
_mockEventSubscriptionService.Object,
_mockGithubService.Object);
}



[Test]
public void LoadDevices_ValidManufacturer_PopulatesDevices()
Expand Down
1 change: 1 addition & 0 deletions OpenIPC_Config.iOS/OpenIPC_Config.iOS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<PackageReference Include="Avalonia.iOS" Version="$(AvaloniaVersion)"/>
<PackageReference Include="Avalonia.Svg.Skia" Version="11.2.0.2"/>
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/>
Expand Down
6 changes: 6 additions & 0 deletions OpenIPC_Config/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,12 @@ private void ConfigureServices(IServiceCollection services, IConfiguration confi
// Register IConfiguration
services.AddTransient<DeviceConfigValidator>();

services.AddSingleton<HttpClient>();
services.AddTransient<GitHubService>();

// add memory cache
services.AddMemoryCache();

// Register ViewModels
RegisterViewModels(services);

Expand Down
2 changes: 2 additions & 0 deletions OpenIPC_Config/Models/OpenIPC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ public enum FileType
Sensors
}


public const string AppName = "OpenIPC_Config";

public const string OpenIPCBuilderGitHubApiUrl = "https://api.github.com/repos/OpenIPC/builder/releases/latest";
public const string MajesticFileLoc = "/etc/majestic.yaml";
public const string WfbConfFileLoc = "/etc/wfb.conf";
public const string TelemetryConfFileLoc = "/etc/telemetry.conf";
Expand Down
1 change: 1 addition & 0 deletions OpenIPC_Config/OpenIPC_Config.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)"/>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1"/>
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0"/>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0-rc.2.24473.5"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/>
Expand Down
55 changes: 55 additions & 0 deletions OpenIPC_Config/Services/GitHubService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Serilog;

namespace OpenIPC_Config.Services;

public class GitHubService
{
private readonly IMemoryCache _cache;
private readonly HttpClient _httpClient;
private readonly string _cacheKey = "GitHubData"; // Unique key for your data
private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(60); // Cache for 1 hour


public GitHubService(IMemoryCache cache, HttpClient httpClient)
{
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
}

public async Task<string> GetGitHubDataAsync(string url)
{
if (_cache.TryGetValue(_cacheKey, out string cachedData))
{
// Data found in cache
Log.Information("Github API data retrieved from cache.");
return cachedData;
}

// Data not in cache, fetch from GitHub API
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (compatible; OpenIPC-Config/1.0)");

try
{
var response = await _httpClient.GetStringAsync(url);

// Store the data in the cache
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(_cacheDuration) // Data expires after this time
.SetPriority(CacheItemPriority.Normal); // Low priority for eviction

_cache.Set(_cacheKey, response, cacheEntryOptions);
Log.Information("Data retrieved from GitHub API and cached.");
return response;
}
catch (HttpRequestException ex)
{
// Handle API errors gracefully (log, throw, etc.)
Log.Error($"Error calling GitHub API: {ex.Message}");
return null; // Or throw the exception, depending on your needs
}
}
}
Loading

0 comments on commit b7a7ad0

Please sign in to comment.