From 4c84a1103a7e87e1e39b98b51af99dd4a98db627 Mon Sep 17 00:00:00 2001 From: Roberto Alves Date: Wed, 18 Oct 2023 16:41:49 +0100 Subject: [PATCH] Refactor the NamingConventionService so that it works for both Server and WASM modes. Add new test fixtures for WASM mode. Add two loading types (file loading and via http request). --- .../NamingConventionServiceTestFixture.cs | 9 +- .../NamingConventionServiceTestFixture.cs | 115 ++++++++++++++++++ .../NamingConventionService.cs | 68 +++++++++++ .../BaseNamingConventionService.cs | 101 +++++++++++++++ .../INamingConventionService.cs | 4 +- .../NamingConventionService.cs | 110 ----------------- .../NamingConventionService.cs | 93 ++++++++++++++ 7 files changed, 385 insertions(+), 115 deletions(-) create mode 100644 COMET.Web.Common.Tests/WebAssembly/Services/NamingConventionService/NamingConventionServiceTestFixture.cs create mode 100644 COMET.Web.Common/Server/Services/NamingConventionService/NamingConventionService.cs create mode 100644 COMET.Web.Common/Services/NamingConventionService/BaseNamingConventionService.cs delete mode 100644 COMET.Web.Common/Services/NamingConventionService/NamingConventionService.cs create mode 100644 COMET.Web.Common/WebAssembly/Services/NamingConventionService/NamingConventionService.cs diff --git a/COMET.Web.Common.Tests/Services/NamingConventionService/NamingConventionServiceTestFixture.cs b/COMET.Web.Common.Tests/Services/NamingConventionService/NamingConventionServiceTestFixture.cs index 8fe89d61..772f1b48 100644 --- a/COMET.Web.Common.Tests/Services/NamingConventionService/NamingConventionServiceTestFixture.cs +++ b/COMET.Web.Common.Tests/Services/NamingConventionService/NamingConventionServiceTestFixture.cs @@ -26,6 +26,7 @@ namespace COMET.Web.Common.Tests.Services.NamingConventionService { + using COMET.Web.Common.Server.Services.NamingConventionService; using COMET.Web.Common.Services.NamingConventionService; using Microsoft.Extensions.Logging; @@ -53,13 +54,13 @@ public async Task VerifyInitializationAndGetNamingConvention() await this.service.InitializeService(); var enumValues = Enum.GetValues(); - foreach (var namingConventionKind in enumValues) + Assert.Multiple(() => { - Assert.Multiple(() => + foreach (var namingConventionKind in enumValues) { Assert.That(this.service.GetNamingConventionValue(namingConventionKind), Is.Not.Empty); - }); - } + } + }); } /// To be used for testing purposes only diff --git a/COMET.Web.Common.Tests/WebAssembly/Services/NamingConventionService/NamingConventionServiceTestFixture.cs b/COMET.Web.Common.Tests/WebAssembly/Services/NamingConventionService/NamingConventionServiceTestFixture.cs new file mode 100644 index 00000000..ed59625c --- /dev/null +++ b/COMET.Web.Common.Tests/WebAssembly/Services/NamingConventionService/NamingConventionServiceTestFixture.cs @@ -0,0 +1,115 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Tests.WebAssembly.Services.NamingConventionService; + +using System.Net; + +using COMET.Web.Common.Services.NamingConventionService; +using COMET.Web.Common.Test.Helpers; +using COMET.Web.Common.WebAssembly.Services.NamingConventionService; + +using Microsoft.Extensions.Logging; + +using Moq; + +using NUnit.Framework; + +using RichardSzalay.MockHttp; + +[TestFixture] +public class NamingConventionServiceTestFixture +{ + private NamingConventionService service; + private MockHttpMessageHandler mockHttpMessageHandler; + private Mock>> logger; + + [SetUp] + public void Setup() + { + this.mockHttpMessageHandler = new MockHttpMessageHandler(); + var httpClient = this.mockHttpMessageHandler.ToHttpClient(); + httpClient.BaseAddress = new Uri("http://localhost/"); + this.logger = new Mock>>(); + this.service = new NamingConventionService(this.logger.Object, httpClient); + } + + [Test] + public async Task VerifyService() + { + this.mockHttpMessageHandler.When(HttpMethod.Get, "/_content/CDP4.WEB.Common/naming_convention.json") + .Throw(new Exception()); + + await this.service.InitializeService(); + this.logger.Verify(LogLevel.Critical, o => o!.ToString()!.Contains("Exception has been raised"), Times.Once()); + + this.mockHttpMessageHandler.ResetBackendDefinitions(); + + var httpResponse = new HttpResponseMessage() + { + StatusCode = HttpStatusCode.InternalServerError + }; + + this.mockHttpMessageHandler.When(HttpMethod.Get, "/_content/CDP4.WEB.Common/naming_convention.json") + .Respond(_ => httpResponse); + + await this.service.InitializeService(); + this.logger.Verify(LogLevel.Error, o => o!.ToString()!.Contains("Error fetching naming conventions. Status code:"), Times.Once()); + + httpResponse.StatusCode = HttpStatusCode.NotFound; + + await this.service.InitializeService(); + this.logger.Verify(LogLevel.Error, o => o!.ToString()!.Contains("Naming conventions file not found at "), Times.Once()); + + httpResponse.StatusCode = HttpStatusCode.OK; + + var json = """ + { + "TestValue1": "TestValue1", + "TestValue2": "TestValue2" + } + """; + + httpResponse.Content = new StringContent(json); + await this.service.InitializeService(); + + var enumValues = Enum.GetValues(); + + Assert.Multiple(() => + { + foreach (var namingConventionKind in enumValues) + { + Assert.That(this.service.GetNamingConventionValue(namingConventionKind), Is.Not.Empty); + } + }); + } + + /// To be used for testing purposes only + public enum NamingConventionKindTestEnum + { + TestValue1, + TestValue2 + } +} diff --git a/COMET.Web.Common/Server/Services/NamingConventionService/NamingConventionService.cs b/COMET.Web.Common/Server/Services/NamingConventionService/NamingConventionService.cs new file mode 100644 index 00000000..f0f347b3 --- /dev/null +++ b/COMET.Web.Common/Server/Services/NamingConventionService/NamingConventionService.cs @@ -0,0 +1,68 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Server.Services.NamingConventionService +{ + using System.Text.Json; + + using COMET.Web.Common.Services.NamingConventionService; + + using Microsoft.Extensions.Logging; + + /// + /// The provides static information based on defined naming convention, like for names of + /// to use for example + /// + public class NamingConventionService : BaseNamingConventionService where TEnum : Enum + { + /// + /// The + /// + private readonly ILogger> logger; + + public NamingConventionService(ILogger> logger) : base(logger) + { + this.logger = logger; + } + + /// + /// Gets the naming convention configuration + /// + /// A of the naming convention configuration + public override async Task> GetNamingConventionConfiguration() + { + try + { + var namingConvention = JsonSerializer.Deserialize>(await File.ReadAllTextAsync(Path.Combine("Resources", "configuration", "naming_convention.json")))!; + return new Dictionary(namingConvention, StringComparer.OrdinalIgnoreCase); + } + catch (Exception e) + { + this.logger.LogError(e, "Error while getting the naming convention configuration file."); + throw; + } + } + } +} diff --git a/COMET.Web.Common/Services/NamingConventionService/BaseNamingConventionService.cs b/COMET.Web.Common/Services/NamingConventionService/BaseNamingConventionService.cs new file mode 100644 index 00000000..c473432c --- /dev/null +++ b/COMET.Web.Common/Services/NamingConventionService/BaseNamingConventionService.cs @@ -0,0 +1,101 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Services.NamingConventionService; + +using Microsoft.Extensions.Logging; + +public class BaseNamingConventionService : INamingConventionService where TEnum : Enum +{ + /// + /// that holds the defined naming convention + /// + private readonly Dictionary definedNaming = new(StringComparer.OrdinalIgnoreCase); + + /// + /// The + /// + private readonly ILogger> logger; + + /// + /// Initializes a new instance of the class. + /// + /// The + protected BaseNamingConventionService(ILogger> logger) + { + this.logger = logger; + } + + /// + /// Initializes this service + /// + /// A + public async Task InitializeService() + { + var namingConvention = await this.GetNamingConventionConfiguration(); + + foreach (var namingConventionKind in Enum.GetValues(typeof(TEnum))) + { + if (namingConvention.TryGetValue(namingConventionKind.ToString(), out var namingConventionValue)) + { + this.definedNaming[namingConventionKind.ToString()] = namingConventionValue; + } + else + { + this.logger.LogWarning("{namingConventionKind} is missing from the Naming Convention configuration file", namingConventionKind.ToString()); + } + } + } + + /// + /// Gets the value for naming convention + /// + /// The naming convention key + /// The defined naming convention, if exists + public string GetNamingConventionValue(string namingConventionKey) + { + return this.definedNaming.TryGetValue(namingConventionKey, out var namingConventionValue) ? namingConventionValue : string.Empty; + } + + /// + /// Gets the value for naming convention + /// + /// The + /// The defined naming convention, if exists + public string GetNamingConventionValue(TEnum namingConventionKind) + { + return this.GetNamingConventionValue(namingConventionKind.ToString()); + } + + /// + /// Gets the naming convention configuration + /// + /// A of the naming convention configuration + /// + public virtual Task> GetNamingConventionConfiguration() + { + throw new NotImplementedException(); + } +} diff --git a/COMET.Web.Common/Services/NamingConventionService/INamingConventionService.cs b/COMET.Web.Common/Services/NamingConventionService/INamingConventionService.cs index f6bbb81c..a44c69f6 100644 --- a/COMET.Web.Common/Services/NamingConventionService/INamingConventionService.cs +++ b/COMET.Web.Common/Services/NamingConventionService/INamingConventionService.cs @@ -28,7 +28,7 @@ namespace COMET.Web.Common.Services.NamingConventionService /// /// The provides static information based on defined naming convention, like for names of to use for example /// - public interface INamingConventionService where TEnum : Enum + public interface INamingConventionService where TEnum : Enum { /// /// Initializes this service @@ -49,5 +49,7 @@ public interface INamingConventionService where TEnum : Enum /// The /// The defined naming convention, if exists string GetNamingConventionValue(TEnum namingConventionKind); + + Task> GetNamingConventionConfiguration(); } } diff --git a/COMET.Web.Common/Services/NamingConventionService/NamingConventionService.cs b/COMET.Web.Common/Services/NamingConventionService/NamingConventionService.cs deleted file mode 100644 index bfa7258b..00000000 --- a/COMET.Web.Common/Services/NamingConventionService/NamingConventionService.cs +++ /dev/null @@ -1,110 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2023 RHEA System S.A. -// -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar -// -// This file is part of COMET WEB Community Edition -// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 -// Annex A and Annex C. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace COMET.Web.Common.Services.NamingConventionService -{ - using System.Text.Json; - - using Microsoft.Extensions.Logging; - - /// - /// The provides static information based on defined naming convention, like for names of - /// to use for example - /// - public class NamingConventionService : INamingConventionService where TEnum : Enum - { - /// - /// that holds the defined naming convention - /// - private readonly Dictionary definedNaming = new(StringComparer.OrdinalIgnoreCase); - - /// - /// The - /// - private readonly ILogger> logger; - - /// - /// Initializes a new instance of the class. - /// - /// The - public NamingConventionService(ILogger> logger) - { - this.logger = logger; - } - - /// - /// Initializes this service - /// - /// A - public async Task InitializeService() - { - Dictionary namingConvention; - - try - { - namingConvention = JsonSerializer.Deserialize>(await File.ReadAllTextAsync(Path.Combine("Resources", "configuration", "naming_convention.json")))!; - } - catch (Exception e) - { - this.logger.LogError(e, "Error while getting the naming convention configuration file."); - return; - } - - namingConvention = new Dictionary(namingConvention, StringComparer.OrdinalIgnoreCase); - - foreach (var namingConventionKind in Enum.GetValues(typeof(TEnum))) - { - if (namingConvention.TryGetValue(namingConventionKind.ToString(), out var namingConventionValue)) - { - this.definedNaming[namingConventionKind.ToString()] = namingConventionValue; - } - else - { - this.logger.LogWarning("{namingConventionKind} is missing from the Naming Convention configuration file", namingConventionKind.ToString()); - } - } - } - - /// - /// Gets the value for naming convention - /// - /// The naming convention key - /// The defined naming convention, if exists - public string GetNamingConventionValue(string namingConventionKey) - { - return this.definedNaming.TryGetValue(namingConventionKey, out var namingConventionValue) ? namingConventionValue : string.Empty; - } - - /// - /// Gets the value for naming convention - /// - /// The - /// The defined naming convention, if exists - public string GetNamingConventionValue(TEnum namingConventionKind) - { - return this.GetNamingConventionValue(namingConventionKind.ToString()); - } - } -} diff --git a/COMET.Web.Common/WebAssembly/Services/NamingConventionService/NamingConventionService.cs b/COMET.Web.Common/WebAssembly/Services/NamingConventionService/NamingConventionService.cs new file mode 100644 index 00000000..cb728b2e --- /dev/null +++ b/COMET.Web.Common/WebAssembly/Services/NamingConventionService/NamingConventionService.cs @@ -0,0 +1,93 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.WebAssembly.Services.NamingConventionService +{ + using System.Collections.Immutable; + using System.Net; + using System.Text.Json; + + using COMET.Web.Common.Services.NamingConventionService; + using COMET.Web.Common.Utilities; + + using Microsoft.Extensions.Logging; + + /// + /// The provides static information based on defined naming convention, like for names of + /// to use for example + /// + public class NamingConventionService : BaseNamingConventionService where TEnum : Enum + { + /// + /// The + /// + private readonly ILogger> logger; + + /// + /// The + /// + private readonly HttpClient httpClient; + + public NamingConventionService(ILogger> logger, HttpClient httpClient) : base(logger) + { + this.logger = logger; + this.httpClient = httpClient; + } + + /// + /// Gets the naming convention configuration + /// + /// A of the naming convention configuration + public override async Task> GetNamingConventionConfiguration() + { + try + { + var path = ContentPathBuilder.BuildPath("naming_convention.json"); + var response = await this.httpClient.GetAsync(path); + + if (response.IsSuccessStatusCode) + { + var jsonContent = await response.Content.ReadAsStreamAsync(); + var namingConvention = JsonSerializer.Deserialize>(jsonContent); + return new Dictionary(namingConvention, StringComparer.OrdinalIgnoreCase); + } + + if (response.StatusCode == HttpStatusCode.NotFound) + { + this.logger.LogError("Naming conventions file not found at {path}", path); + return ImmutableDictionary.Empty; + } + + this.logger.LogError("Error fetching naming conventions. Status code: {response}", response.StatusCode); + return ImmutableDictionary.Empty; + } + catch (Exception e) + { + this.logger.LogCritical("Exception has been raised : {message}", e.Message); + return ImmutableDictionary.Empty; + } + } + } +}