Initial commit: SWP.Core enterprise framework with multi-tenant architecture, configuration management, security, telemetry and comprehensive test suite
This commit is contained in:
commit
5275a75502
87 changed files with 6140 additions and 0 deletions
145
Tests/ConfigurationTests/JsonConfigurationProviderTests.cs
Normal file
145
Tests/ConfigurationTests/JsonConfigurationProviderTests.cs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
using Newtonsoft.Json.Linq;
|
||||
using SWP.Core.Configurations;
|
||||
using SWP.Core.Configurations.JsonConfigProvider;
|
||||
using SWP.Core.Configurations.SmartConfigProvider;
|
||||
using Shouldly;
|
||||
using SWP.Core.X.TDD;
|
||||
|
||||
namespace SWP.Core.X.TDD.ConfigurationTests;
|
||||
|
||||
[TestClass]
|
||||
public class JsonConfigurationProviderTests : TestFixture
|
||||
{
|
||||
private const string _testFolder = "ConfigurationTests/";
|
||||
|
||||
public JsonConfigurationProviderTests() : base(_testFolder)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void GetSection_ShouldReturnCorrectFeatureSection()
|
||||
{
|
||||
// Arrange
|
||||
var expectedJObject = JObject.Parse(@"{
|
||||
'Enabled': true,
|
||||
'RolloutPercentage': 25,
|
||||
'AllowedUserGroups': ['beta']
|
||||
}") as JToken;
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var section = builder.GetSection("Feature");
|
||||
|
||||
// Assert
|
||||
section.ShouldNotBeNull();
|
||||
section.Value.ShouldBeEquivalentTo(expectedJObject);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Get_ShouldReturnCorrectFeatureObject()
|
||||
{
|
||||
// Arrange
|
||||
var expectedFeature = new Feature
|
||||
{
|
||||
Enabled = true,
|
||||
RolloutPercentage = 25,
|
||||
AllowedUserGroups = new List<string> { "beta" }
|
||||
};
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var actualFeature = builder.GetSection("Feature").ToObject<Feature>();
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var actualFeatureObsoleted = builder.GetSection("Feature").Get<Feature>();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
// Assert
|
||||
actualFeature.ShouldBeEquivalentTo(expectedFeature);
|
||||
actualFeatureObsoleted.ShouldBeEquivalentTo(expectedFeature);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Get_ShouldReturnCorrectValueAsString()
|
||||
{
|
||||
// Arrange
|
||||
var expectedFeature = "123";
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var actualFeature = builder.GetSection("AnotherSetting").Get<string>("Thresholds:High");
|
||||
|
||||
// Assert
|
||||
actualFeature.ShouldBeEquivalentTo(expectedFeature);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Testing a stupid indexer for compability with Microsoft ConfigurationBuilder
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void Indexer_ShouldReturnValueAsString()
|
||||
{
|
||||
// Arrange
|
||||
var expected = "SHA256";
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var actual = builder["Authentication"];
|
||||
|
||||
// Assert
|
||||
actual.ShouldBeEquivalentTo(expected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Get_ShouldReturnCorrectValueAsInt()
|
||||
{
|
||||
// Arrange
|
||||
var expectedFeature = 22;
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var actualFeature = builder.GetSection("AnotherSetting:Temperature").Get<int>("Indoor:Max:Limit");
|
||||
|
||||
// Assert
|
||||
actualFeature.ShouldBe(expectedFeature);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Get_ShouldReturnCorrectValueAsBool()
|
||||
{
|
||||
// Arrange
|
||||
var expectedFeature = true;
|
||||
|
||||
var configRoot = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.AddSmartConfig()
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var actualFeature = configRoot.Get<bool>("Database:UseSSL");
|
||||
|
||||
// Assert
|
||||
actualFeature.ShouldBe(expectedFeature);
|
||||
}
|
||||
}
|
||||
|
||||
internal class Feature
|
||||
{
|
||||
public bool Enabled { get; set; }
|
||||
public int RolloutPercentage { get; set; }
|
||||
public List<string> AllowedUserGroups { get; set; }
|
||||
}
|
||||
75
Tests/ConfigurationTests/KeyValueJsonHandlingTests.cs
Normal file
75
Tests/ConfigurationTests/KeyValueJsonHandlingTests.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
using Newtonsoft.Json.Linq;
|
||||
using SWP.Core.Configurations.Common;
|
||||
|
||||
namespace SWP.Core.X.TDD.ConfigurationTests;
|
||||
|
||||
[TestClass]
|
||||
public class ConfigurationTests : TestFixture
|
||||
{
|
||||
[TestInitialize]
|
||||
public void Init()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void ConfigurationSettingsTest()
|
||||
{
|
||||
var pairs = new List<KeyValuePair<string, JToken>>
|
||||
{
|
||||
new("Debug", true),
|
||||
// Database konfiguration
|
||||
new("Database:ConnectionString", "Server=db.example.com;Port=5432"),
|
||||
new("Database:Timeout", 30),
|
||||
new("Database:UseSSL", true),
|
||||
|
||||
// Logging konfiguration med JObject
|
||||
new("Logging:FileOptions", JObject.Parse(@"{
|
||||
'Path': '/var/logs/app.log',
|
||||
'MaxSizeMB': 100,
|
||||
'RetentionDays': 7
|
||||
}")),
|
||||
|
||||
// Feature flags med kompleks konfiguration
|
||||
new("Features:Experimental", JObject.Parse(@"{
|
||||
'Enabled': true,
|
||||
'RolloutPercentage': 25,
|
||||
'AllowedUserGroups': ['beta']
|
||||
}")),
|
||||
|
||||
// API endpoints med array
|
||||
new("API:Endpoints", "/api/users"),
|
||||
new("API:Endpoints", "/api/products")
|
||||
};
|
||||
|
||||
var result = KeyValueToJson.Convert(pairs);
|
||||
|
||||
var expected = JObject.Parse(@"{
|
||||
'Debug' : true,
|
||||
'Database': {
|
||||
'ConnectionString': 'Server=db.example.com;Port=5432',
|
||||
'Timeout': 30,
|
||||
'UseSSL': true
|
||||
},
|
||||
'Logging': {
|
||||
'FileOptions': {
|
||||
'Path': '/var/logs/app.log',
|
||||
'MaxSizeMB': 100,
|
||||
'RetentionDays': 7
|
||||
}
|
||||
},
|
||||
'Features': {
|
||||
'Experimental': {
|
||||
'Enabled': true,
|
||||
'RolloutPercentage': 25,
|
||||
'AllowedUserGroups': ['beta']
|
||||
}
|
||||
},
|
||||
'API': {
|
||||
'Endpoints': ['/api/users', '/api/products']
|
||||
}
|
||||
}");
|
||||
|
||||
Assert.IsTrue(JToken.DeepEquals(expected, result));
|
||||
}
|
||||
}
|
||||
82
Tests/ConfigurationTests/SmartConfigProviderTests.cs
Normal file
82
Tests/ConfigurationTests/SmartConfigProviderTests.cs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
using Autofac;
|
||||
using Insight.Database;
|
||||
using SWP.Core.Configurations;
|
||||
using SWP.Core.Configurations.JsonConfigProvider;
|
||||
using SWP.Core.Configurations.SmartConfigProvider;
|
||||
using SWP.Core.Database.ConnectionFactory;
|
||||
using Shouldly;
|
||||
|
||||
namespace SWP.Core.X.TDD.ConfigurationTests;
|
||||
|
||||
[TestClass]
|
||||
public class SmartConfigProviderTests : TestFixture
|
||||
{
|
||||
private const string _testFolder = "ConfigurationTests/";
|
||||
|
||||
[TestMethod]
|
||||
public void TrySmartConfigWithOptionsForPostgres()
|
||||
{
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.AddSmartConfig(options => options.UsePostgres("DefaultConnection"))
|
||||
.Build();
|
||||
|
||||
var actualFeature = config.Get<bool>("Database:UseSSL");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Get_ShouldReturnCorrectValueAsBool()
|
||||
{
|
||||
// Arrange
|
||||
var expectedFeature = true;
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.AddSmartConfig(options => options.UsePostgres("DefaultConnection"))
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var actualFeature = config.Get<bool>("Database:UseSSL");
|
||||
|
||||
// Assert
|
||||
actualFeature.ShouldBe(expectedFeature);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Get_ShouldReturnCorrectValueWhenSelectingIntoValueRowInConfigTable()
|
||||
{
|
||||
// Arrange
|
||||
var expectedFeature = 100;
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.AddSmartConfig(options => options.UsePostgres("DefaultConnection"))
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var actualFeature = builder.GetSection("Logging:FileOptions").Get<int>("MaxSizeMB");
|
||||
var withoutSectionThisAlsoWorks = builder.Get<int>("Logging:FileOptions:MaxSizeMB");
|
||||
|
||||
// Assert
|
||||
actualFeature.ShouldBe(expectedFeature);
|
||||
actualFeature.ShouldBe(withoutSectionThisAlsoWorks);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TryGetActiveConfigurations()
|
||||
{
|
||||
var connFactory = Container.Resolve<IDbConnectionFactory>();
|
||||
|
||||
const string sql = @"
|
||||
SELECT id, ""key"", value, label, content_type,
|
||||
valid_from, expires_at, created_at, modified_at, etag
|
||||
FROM app_configuration
|
||||
WHERE CURRENT_TIMESTAMP BETWEEN valid_from AND expires_at
|
||||
OR (valid_from IS NULL AND expires_at IS NULL)";
|
||||
|
||||
using (var conn = connFactory.Create())
|
||||
{
|
||||
var result = conn.QuerySql(sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
74
Tests/ConfigurationTests/appconfiguration.dev.json
Normal file
74
Tests/ConfigurationTests/appconfiguration.dev.json
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=192.168.1.57;Port=5432;Database=sandbox;User Id=sathumper;Password=3911;"
|
||||
},
|
||||
"ApplicationInsights": {
|
||||
"ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548",
|
||||
"UseSeqLoggingTelemetryChannel": true
|
||||
},
|
||||
"SeqConfiguration": {
|
||||
"IngestionEndpoint": "http://localhost:5341",
|
||||
"ApiKey": null,
|
||||
"Environment": "MSTEST"
|
||||
},
|
||||
"Authentication": "SHA256",
|
||||
"Feature": {
|
||||
"Enabled": true,
|
||||
"RolloutPercentage": 25,
|
||||
"AllowedUserGroups": [
|
||||
"beta"
|
||||
]
|
||||
},
|
||||
"AnotherSetting": {
|
||||
"Thresholds": {
|
||||
"High": "123",
|
||||
"Low": "-1"
|
||||
},
|
||||
"Temperature": {
|
||||
"Indoor": {
|
||||
"Max": {
|
||||
"Limit": 22
|
||||
},
|
||||
"Min": {
|
||||
"Limit": 18
|
||||
}
|
||||
},
|
||||
"Outdoor": {
|
||||
"Max": {
|
||||
"Limit": 12
|
||||
},
|
||||
"Min": {
|
||||
"Limit": 9
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning",
|
||||
"System": "Warning"
|
||||
}
|
||||
},
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "Seq",
|
||||
"Args": {
|
||||
"serverUrl": "http://localhost:5341",
|
||||
"apiKey": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"Enrich": [
|
||||
"WithMachineName",
|
||||
"WithThreadId",
|
||||
"WithProcessId",
|
||||
"WithEnvironmentName"
|
||||
],
|
||||
"Properties": {
|
||||
"Application": "PlanTempus"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue