Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
129 changes: 58 additions & 71 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
@@ -1,83 +1,70 @@
# 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: SonarQube
on:
push:
branches: [ "master" ]
branches:
- master
pull_request:
branches: [ "master" ]
workflow_dispatch:

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

types: [opened, synchronize, reopened]
jobs:
sonar-check:
name: Sonar Check
runs-on: windows-latest # безпечно для будь-яких .NET проектів
build:
name: Build and analyze
runs-on: windows-latest
steps:
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'zulu' # Alternative distribution options are available.
- 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
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Cache SonarQube Cloud packages
uses: actions/cache@v4
with:
path: ~\sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache SonarQube Cloud scanner
id: cache-sonar-scanner
uses: actions/cache@v4
with:
path: ${{ runner.temp }}\scanner
key: ${{ runner.os }}-sonar-scanner
restore-keys: ${{ runner.os }}-sonar-scanner
- name: Install SonarQube Cloud scanner
if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
shell: powershell
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" `
/d:sonar.cpd.cs.minimumTokens=40 `
/d:sonar.cpd.cs.minimumLines=5 `
/d:sonar.exclusions=**/bin/**,**/obj/**,**/sonarcloud.yml `
/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
New-Item -Path ${{ runner.temp }}\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path ${{ runner.temp }}\scanner
- name: Build and analyze
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: |
${{ runner.temp }}\scanner\dotnet-sonarscanner begin /k:"Yegres546_NetSdrClient" /o:"yegres546-1" /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
dotnet build
${{ runner.temp }}\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"

- name: Test with coverage
run: |
dotnet test NetSdrClient.Tests/NetSdrClient.Tests.csproj -c Release \
--logger "trx;LogFileName=test-results.trx" \
/p:CollectCoverage=true \
/p:CoverletOutput=TestResults/ \
/p:CoverletOutputFormat=opencover \
/p:Exclude="[nunit.*]*%2c[*.Tests]*%2c[Moq]*%2c[NUnit.*]*"

- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: test-coverage-results
path: NetSdrClient.Tests/TestResults/
retention-days: 30
shell: pwsh
# 3) END: SonarScanner
- name: SonarScanner End
run: dotnet sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
shell: pwsh


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();
}
}
}
22 changes: 22 additions & 0 deletions NetSdrClient.Tests/NetSdrClient.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NetSdrClient\NetSdrClient.csproj" />
</ItemGroup>

</Project>
75 changes: 75 additions & 0 deletions NetSdrClient.Tests/NetworkServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NetSdrClient.Services;

namespace NetSdrClient.Tests
{
[TestClass]
public class NetworkServiceTests
{
[TestMethod]
public void NetworkService_Constructor_ShouldInitialize()
{
// Arrange & Act
var service = new NetworkService();

// Assert
Assert.IsNotNull(service);
}

[TestMethod]
public void IsValidIpAddress_WithValidIp_ShouldReturnTrue()
{
// Arrange
var service = new NetworkService();
var validIp = "192.168.1.1";

// Act
var result = service.IsValidIpAddress(validIp);

// Assert
Assert.IsTrue(result);
}

[TestMethod]
public void IsValidIpAddress_WithInvalidIp_ShouldReturnFalse()
{
// Arrange
var service = new NetworkService();
var invalidIp = "999.999.999.999";

// Act
var result = service.IsValidIpAddress(invalidIp);

// Assert
Assert.IsFalse(result);
}

[TestMethod]
public void IsValidPort_WithValidPort_ShouldReturnTrue()
{
// Arrange
var service = new NetworkService();
var validPort = 8080;

// Act
var result = service.IsValidPort(validPort);

// Assert
Assert.IsTrue(result);
}

[TestMethod]
public void IsValidPort_WithInvalidPort_ShouldReturnFalse()
{
// Arrange
var service = new NetworkService();
var invalidPort = 99999;

// Act
var result = service.IsValidPort(invalidPort);

// Assert
Assert.IsFalse(result);
}
}
}
63 changes: 63 additions & 0 deletions NetSdrClient.Tests/ProtocolHandlerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NetSdrClient.Services;

namespace NetSdrClient.Tests
{
[TestClass]
public class ProtocolHandlerTests
{
[TestMethod]
public void ProtocolHandler_Constructor_ShouldInitialize()
{
// Arrange & Act
var handler = new ProtocolHandler();

// Assert
Assert.IsNotNull(handler);
}

[TestMethod]
public void CreateCommand_ShouldReturnValidCommand()
{
// Arrange
var handler = new ProtocolHandler();
var expectedCommand = "CONNECT";

// Act
var result = handler.CreateCommand(expectedCommand);

// Assert
Assert.IsNotNull(result);
Assert.IsTrue(result.Contains(expectedCommand));
}

[TestMethod]
public void ParseResponse_WithValidData_ShouldReturnParsedResponse()
{
// Arrange
var handler = new ProtocolHandler();
var testData = "OK:CONNECTED";

// Act
var result = handler.ParseResponse(testData);

// Assert
Assert.IsNotNull(result);
Assert.IsTrue(result.Contains("CONNECTED"));
}

[TestMethod]
public void ParseResponse_WithNullData_ShouldReturnErrorMessage()
{
// Arrange
var handler = new ProtocolHandler();

// Act
var result = handler.ParseResponse(null);

// Assert
Assert.IsNotNull(result);
Assert.IsTrue(result.Contains("ERROR"));
}
}
}
Loading