Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fc08735
Update sonarcloud.yml
Yegres546 Nov 25, 2025
1bb5602
Move 'UdpTimedSender' into a named namespace.Program.cs
Yegres546 Nov 25, 2025
165f3ac
static handle Program.cs
Yegres546 Nov 25, 2025
3b5c4e4
coverlet.msbuild sonarcloud.yml
Yegres546 Nov 25, 2025
0b1b87b
coverage sonarcloud.yml
Yegres546 Nov 25, 2025
6e8bc31
coverage sonarcloud.yml
Yegres546 Nov 25, 2025
2f7289c
coverage sonarcloud.yml
Yegres546 Nov 25, 2025
6d9f4d8
Merge pull request #2 from Yegres546/lab3-coverage
Yegres546 Nov 25, 2025
9d333e2
Update NetSdrClientAppTests.csproj
Yegres546 Nov 25, 2025
a8c55e8
Update NetSdrClientAppTests.csproj
Yegres546 Nov 25, 2025
77a217e
Update sonarcloud.yml
Yegres546 Nov 25, 2025
0574e66
Update sonarcloud.yml
Yegres546 Nov 26, 2025
5f61227
Merge branch 'master' into lab3-coverage
Yegres546 Nov 26, 2025
c520b33
Merge pull request #3 from Yegres546/lab3-coverage
Yegres546 Nov 26, 2025
a9464dc
ref sonarcloud.yml
Yegres546 Nov 26, 2025
49bdb5c
Create coverlet.msbuild
Yegres546 Nov 26, 2025
d5c6a8c
Merge pull request #4 from Yegres546/patch-5
Yegres546 Nov 26, 2025
9d4bea6
Create SDRDeviceTests.cs
Yegres546 Nov 26, 2025
d0da030
Create SDRClientTests.cs
Yegres546 Nov 26, 2025
e9bfced
Create ProtocolHandlerTests.cs
Yegres546 Nov 26, 2025
e4531ee
Create NetworkServiceTests.cs
Yegres546 Nov 26, 2025
ba9bcee
Create NetSdrClient.Tests.csproj
Yegres546 Nov 26, 2025
84c9c42
Create coverlet.msbuild
Yegres546 Nov 26, 2025
b542287
Merge pull request #5 from Yegres546/lab3-coverage
Yegres546 Nov 26, 2025
64e97d4
Update sonarcloud.yml
Yegres546 Nov 26, 2025
71b909b
Create coverlet.runsettings
Yegres546 Nov 26, 2025
d799a08
Create ArchitectureTests.cs
Yegres546 Nov 26, 2025
d01b555
Update NetSdrClient.Tests.csproj
Yegres546 Nov 26, 2025
8e1e35e
Create BadService.cs
Yegres546 Nov 26, 2025
178b8ea
Create UIComponent.cs
Yegres546 Nov 26, 2025
cd16e6d
Create DatabaseService.cs
Yegres546 Nov 26, 2025
1031a89
Create IDeviceService.cs
Yegres546 Nov 26, 2025
1d6ed29
Update NetSdrClient.cs
Yegres546 Nov 26, 2025
0eac29f
Update sonarcloud.yml
Yegres546 Nov 26, 2025
b2165fd
Merge pull request #6 from Yegres546/Lab_5
Yegres546 Nov 26, 2025
7318e61
Merge branch 'master' into patch-1
Yegres546 Nov 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/coverlet.msbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dotnet add NetSdrClientAppTests package coverlet.msbuild
dotnet add NetSdrClientAppTests package Microsoft.NET.Test.Sdk
dotnet test NetSdrClientAppTests -c Release /p:CollectCoverage=true /p:CoverletOutput=TestResults/coverage.xml /p:CoverletOutputFormat=opencover
151 changes: 80 additions & 71 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
@@ -1,83 +1,92 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# This workflow helps you trigger a SonarCloud analysis of your code and populates
# GitHub Code Scanning alerts with the vulnerabilities found.
# Free for open source project.

# 1. Login to SonarCloud.io using your GitHub account

# 2. Import your project on SonarCloud
# * Add your GitHub organization first, then add your repository as a new project.
# * Please note that many languages are eligible for automatic analysis,
# which means that the analysis will start automatically without the need to set up GitHub Actions.
# * This behavior can be changed in Administration > Analysis Method.
#
# 3. Follow the SonarCloud in-product tutorial
# * a. Copy/paste the Project Key and the Organization Key into the args parameter below
# (You'll find this information in SonarCloud. Click on "Information" at the bottom left)
#
# * b. Generate a new token and add it to your Github repository's secrets using the name SONAR_TOKEN
# (On SonarCloud, click on your avatar on top-right > My account > Security
# or go directly to https://sonarcloud.io/account/security/)

# Feel free to take a look at our documentation (https://docs.sonarcloud.io/getting-started/github/)
# or reach out to our community forum if you need some help (https://community.sonarsource.com/c/help/sc/9)

name: SonarCloud analysis
name: SonarCloud Analysis

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
workflow_dispatch:

permissions:
pull-requests: read # allows SonarCloud to decorate PRs with analysis results

jobs:
sonar-check:
name: Sonar Check
runs-on: windows-latest # безпечно для будь-яких .NET проектів
build-and-analyze:
name: Build and Analyze
runs-on: windows-latest

steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }

- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'

# 1) BEGIN: SonarScanner for .NET
- name: SonarScanner Begin
run: |
dotnet tool install --global dotnet-sonarscanner
echo "$env:USERPROFILE\.dotnet\tools" >> $env:GITHUB_PATH
dotnet sonarscanner begin `
/k:"ppanchen_NetSdrClient" `
/o:"ppanchen" `
/d:sonar.token="${{ secrets.SONAR_TOKEN }}" `
/d:sonar.cs.opencover.reportsPaths="**/coverage.xml" `
- name: Checkout code
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'

- name: Install SonarScanner
run: |
dotnet tool install --global dotnet-sonarscanner
echo "$env:USERPROFILE\.dotnet\tools" >> $env:GITHUB_PATH

- name: Install Coverlet
run: dotnet tool install --global coverlet.console

- name: Build and test with SonarCloud
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
# Start SonarScanner
dotnet sonarscanner begin `
/k:"Yegres546_NetSdrClient" `
/o:"yegres546" `
/d:sonar.token="$env:SONAR_TOKEN" `
/d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" `
/d:sonar.cpd.cs.minimumTokens=40 `
/d:sonar.cpd.cs.minimumLines=5 `
/d:sonar.exclusions=**/bin/**,**/obj/**,**/sonarcloud.yml `
/d:sonar.exclusions="**/bin/**,**/obj/**,**/TestResults/**,**/*.Tests.cs" `
/d:sonar.coverage.exclusions="**Test*.cs" `
/d:sonar.qualitygate.wait=true
shell: pwsh
# 2) BUILD & TEST
- name: Restore
run: dotnet restore NetSdrClient.sln
- name: Build
run: dotnet build NetSdrClient.sln -c Release --no-restore
#- name: Tests with coverage (OpenCover)
# run: |
# dotnet test NetSdrClientAppTests/NetSdrClientAppTests.csproj -c Release --no-build `
# /p:CollectCoverage=true `
# /p:CoverletOutput=TestResults/coverage.xml `
# /p:CoverletOutputFormat=opencover
# shell: pwsh
# 3) END: SonarScanner
- name: SonarScanner End
run: dotnet sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
shell: pwsh

# Build the solution
dotnet build --configuration Release

# Run tests with coverage
dotnet test --configuration Release `
--no-build `
--verbosity normal `
--collect:"XPlat Code Coverage" `
--results-directory ./TestResults `
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover

# End SonarScanner
dotnet sonarscanner end /d:sonar.token="$env:SONAR_TOKEN"
name: Architecture Rules Validation

on:
push:
branches: [ "lab5" ]
pull_request:
branches: [ "lab5" ]

jobs:
architecture-tests:
name: Architecture Rules Validation
runs-on: windows-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'

- name: Install dependencies
run: dotnet restore

- name: Build
run: dotnet build --no-restore --configuration Release

- name: Run Architecture Tests
run: dotnet test --configuration Release --no-build --verbosity normal --filter "Category=Architecture"

- name: Run All Tests
run: dotnet test --configuration Release --no-build --verbosity normal
29 changes: 15 additions & 14 deletions EchoTcpServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task StartAsync()
Console.WriteLine("Server shutdown.");
}

private async Task HandleClientAsync(TcpClient client, CancellationToken token)
private static async Task HandleClientAsync(TcpClient client, CancellationToken token)
{
using (NetworkStream stream = client.GetStream())
{
Expand Down Expand Up @@ -112,21 +112,22 @@ public static async Task Main(string[] args)
}
}


public class UdpTimedSender : IDisposable
namespace EchoServerNamespace
{
private readonly string _host;
private readonly int _port;
private readonly UdpClient _udpClient;
private Timer _timer;

public UdpTimedSender(string host, int port)
public class UdpTimedSender : IDisposable
{
_host = host;
_port = port;
_udpClient = new UdpClient();
}
private readonly string _host;
private readonly int _port;
private readonly UdpClient _udpClient;
private Timer _timer;

public UdpTimedSender(string host, int port)
{
_host = host;
_port = port;
_udpClient = new UdpClient();
}
}
public void StartSending(int intervalMilliseconds)
{
if (_timer != null)
Expand Down Expand Up @@ -170,4 +171,4 @@ public void Dispose()
StopSending();
_udpClient.Dispose();
}
}
}
10 changes: 10 additions & 0 deletions Infrastructure/DatabaseService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace NetSdrClient.Infrastructure
{
public class DatabaseService
{
public void SaveData(object data)
{
// Database operations
}
}
}
8 changes: 8 additions & 0 deletions Interfaces/IDeviceService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace NetSdrClient.Interfaces
{
public interface IDeviceService
{
void Connect();
void Disconnect();
}
}
148 changes: 148 additions & 0 deletions NetSdrClient.Tests/ArchitectureTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
using NetArchTest.Rules;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace NetSdrClient.Tests
{
[TestClass]
public class ArchitectureTests
{
private const string ApplicationNamespace = "NetSdrClient";
private const string ModelsNamespace = "NetSdrClient.Models";
private const string ServicesNamespace = "NetSdrClient.Services";
private const string InterfacesNamespace = "NetSdrClient.Interfaces";
private const string InfrastructureNamespace = "NetSdrClient.Infrastructure";
private const string UINamespace = "NetSdrClient.UI";

[TestMethod]
public void ServicesLayer_ShouldNotDependOnUI()
{
// Arrange
var assembly = typeof(Services.SDRClient).Assembly;

// Act
var result = Types
.InAssembly(assembly)
.That()
.ResideInNamespace(ServicesNamespace)
.ShouldNot()
.HaveDependencyOn(UINamespace)
.GetResult();

// Assert
Assert.IsTrue(result.IsSuccessful,
$"Services layer should not depend on UI: {string.Join(", ", result.FailingTypes)}");
}

[TestMethod]
public void Models_ShouldNotReferenceServices()
{
// Arrange
var assembly = typeof(Models.SDRDevice).Assembly;

// Act
var result = Types
.InAssembly(assembly)
.That()
.ResideInNamespace(ModelsNamespace)
.ShouldNot()
.HaveDependencyOn(ServicesNamespace)
.GetResult();

// Assert
Assert.IsTrue(result.IsSuccessful,
$"Models should not depend on Services: {string.Join(", ", result.FailingTypes)}");
}

[TestMethod]
public void Interfaces_ShouldNotHaveDependencies()
{
// Arrange
var assembly = typeof(Services.SDRClient).Assembly;

// Act
var result = Types
.InAssembly(assembly)
.That()
.ResideInNamespace(InterfacesNamespace)
.Should()
.NotHaveDependencyOnAny(
ServicesNamespace,
ModelsNamespace,
InfrastructureNamespace,
UINamespace)
.GetResult();

// Assert
Assert.IsTrue(result.IsSuccessful,
$"Interfaces should not have dependencies: {string.Join(", ", result.FailingTypes)}");
}

[TestMethod]
public void AllClasses_ShouldHaveNamesEndingWithService_IfInServicesNamespace()
{
// Arrange
var assembly = typeof(Services.SDRClient).Assembly;

// Act
var result = Types
.InAssembly(assembly)
.That()
.ResideInNamespace(ServicesNamespace)
.And()
.AreClasses()
.Should()
.HaveNameEndingWith("Service")
.Or()
.HaveNameEndingWith("Client")
.Or()
.HaveNameEndingWith("Handler")
.GetResult();

// Assert
Assert.IsTrue(result.IsSuccessful,
$"Services should have proper naming: {string.Join(", ", result.FailingTypes)}");
}

[TestMethod]
public void Models_ShouldBeSealed()
{
// Arrange
var assembly = typeof(Models.SDRDevice).Assembly;

// Act
var result = Types
.InAssembly(assembly)
.That()
.ResideInNamespace(ModelsNamespace)
.And()
.AreClasses()
.Should()
.BeSealed()
.GetResult();

// Assert
Assert.IsTrue(result.IsSuccessful,
$"Models should be sealed: {string.Join(", ", result.FailingTypes)}");
}

[TestMethod]
public void Services_ShouldNotDependOnInfrastructureDirectly()
{
// Arrange
var assembly = typeof(Services.SDRClient).Assembly;

// Act
var result = Types
.InAssembly(assembly)
.That()
.ResideInNamespace(ServicesNamespace)
.ShouldNot()
.HaveDependencyOn(InfrastructureNamespace)
.GetResult();

// Assert
Assert.IsTrue(result.IsSuccessful,
$"Services should not depend directly on Infrastructure: {string.Join(", ", result.FailingTypes)}");
}
}
}
Loading