Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ApiPlcProgramBlockType enum #44

Merged
merged 1 commit into from
Dec 4, 2023
Merged
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
add ApiPlcProgramBlockType enum
KircMax committed Dec 4, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 50b668949428f65fff830187a00676d1b06bce46
5 changes: 1 addition & 4 deletions src/Webserver.API/Enums/ApiErrorCode.cs
Original file line number Diff line number Diff line change
@@ -235,8 +235,5 @@ public enum ApiErrorCode
/// Invalid Parameters provided (null/empty string that is forbidden?, invalid ticket length?, wrong datetime string format (rfc3339)? ...)
/// </summary>
InvalidParams = -32602



}
}
}
47 changes: 47 additions & 0 deletions src/Webserver.API/Enums/ApiPlcProgramBlockType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) 2023, Siemens AG
//
// SPDX-License-Identifier: MIT

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Serialization;

namespace Siemens.Simatic.S7.Webserver.API.Enums
{
/// <summary>
/// Block type enumeration.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum ApiPlcProgramBlockType
{
/// <summary>
/// OB block.
/// </summary>
[EnumMember(Value = "ob")]
Ob,

/// <summary>
/// FB block.
/// </summary>
[EnumMember(Value = "fc")]
Fc,

/// <summary>
/// FC block.
/// </summary>
[EnumMember(Value = "fb")]
Fb,

/// <summary>
/// SFB block.
/// </summary>
[EnumMember(Value = "sfc")]
Sfc,

/// <summary>
/// SFC block.
/// </summary>
[EnumMember(Value = "sfb")]
Sfb,
}
}
7 changes: 4 additions & 3 deletions src/Webserver.API/Models/ApiPlcProgramBrowseCodeBlocksData.cs
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Siemens.Simatic.S7.Webserver.API.Enums;
using System;

namespace Siemens.Simatic.S7.Webserver.API.Models
@@ -18,7 +19,7 @@ public class ApiPlcProgramBrowseCodeBlocksData : IEquatable<ApiPlcProgramBrowseC
/// <returns></returns>
public ApiPlcProgramBrowseCodeBlocksData ShallowCopy()
{
return (ApiPlcProgramBrowseCodeBlocksData) this.MemberwiseClone();
return (ApiPlcProgramBrowseCodeBlocksData)this.MemberwiseClone();
}

/// <summary>
@@ -37,13 +38,13 @@ public ApiPlcProgramBrowseCodeBlocksData ShallowCopy()
/// Type of the code block.
/// </summary>
[JsonProperty("block_type")]
public string BlockType { get; set; }
public ApiPlcProgramBlockType BlockType { get; set; }

/// <summary>
/// Constructor.
/// </summary>
[JsonConstructor]
public ApiPlcProgramBrowseCodeBlocksData(string name, ushort blockNumber, string blockType)
public ApiPlcProgramBrowseCodeBlocksData(string name, ushort blockNumber, ApiPlcProgramBlockType blockType)
{
Name = name;
BlockNumber = blockNumber;
206 changes: 205 additions & 1 deletion tests/Webserver.API.UnitTests/ApiRequestTests.cs
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@
using Siemens.Simatic.S7.Webserver.API.Enums;
using Siemens.Simatic.S7.Webserver.API.Exceptions;
using Siemens.Simatic.S7.Webserver.API.Models;
using Siemens.Simatic.S7.Webserver.API.Models.ApiDiagnosticBuffer;
using Siemens.Simatic.S7.Webserver.API.Models.FailsafeParameters;
using Siemens.Simatic.S7.Webserver.API.Models.Requests;
using Siemens.Simatic.S7.Webserver.API.Models.Responses;
@@ -1075,6 +1074,69 @@ public void T013_06_ApiPlcProgramBrowse_InvalidArrayIndex_ExcThrown()
Assert.ThrowsAsync<ApiInvalidArrayIndexException>(async () => await TestHandler.PlcProgramBrowseAsync(ApiPlcProgramBrowseMode.Children, "\"DataTypes\".\"Bool\"a"));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public async Task T014_01_PlcProgramDownloadProfilingData_Success()
{
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramDownloadProfilingDataSuccess); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

ApiSingleStringResponse response = await TestHandler.PlcProgramDownloadProfilingDataAsync();

Assert.That(response.Result.Equals("jgxikeMgLryvP0YoHc.eqt8BY787"));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public void T014_02_PlcProgramDownloadProfilingData_NoResources()
{
// This case could happen if the user downloads the profiling
// data twice without clearing the ticket or downloading the actual data.

var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramDownloadProfilingDataNoResources); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

Assert.ThrowsAsync<ApiNoResourcesException>(async () => await TestHandler.PlcProgramDownloadProfilingDataAsync());
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public void T014_03_PlcProgramDownloadProfilingData_PermissionDenied()
{

var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramDownloadProfilingDataPermissionDenied); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

Assert.ThrowsAsync<System.UnauthorizedAccessException>(async () => await TestHandler.PlcProgramDownloadProfilingDataAsync());
}

/// <summary>
///
/// </summary>
@@ -1093,6 +1155,148 @@ public void T015_ApiPlcProgramBrowse_PermissionDenied_ExcThrown()
Assert.ThrowsAsync<UnauthorizedAccessException>(async () => await TestHandler.PlcProgramBrowseAsync(ApiPlcProgramBrowseMode.Children, "\"DataTypes\".\"Bool\""));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public async Task T015_02_ApiPlcProgramBrowseCodeBlocks_EmptyResult()
{
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramBrowseCodeBlocksEmptyResult); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

ApiPlcProgramBrowseCodeBlocksResponse response = await TestHandler.PlcProgramBrowseCodeBlocksAsync();
Assert.That(response.Result.Count == 0);
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public void T015_03_ApiPlcProgramBrowseCodeBlocks_InvalidParams()
{
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramBrowseCodeBlocksInvalidParams); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

Assert.ThrowsAsync<ApiInvalidParametersException>(async () => await TestHandler.PlcProgramBrowseCodeBlocksAsync());
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public async Task T015_04_ApiPlcProgramBrowseCodeBlocks_Success()
{
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramBrowseCodeBlocksSuccess); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

ApiPlcProgramBrowseCodeBlocksResponse response = await TestHandler.PlcProgramBrowseCodeBlocksAsync();

Assert.That(response.Result.Count == 5);

Assert.That(response.Result[0].Name == "Main");
Assert.That(response.Result[0].BlockType == ApiPlcProgramBlockType.Ob);
Assert.That(response.Result[0].BlockNumber == 1);

Assert.That(response.Result[1].Name == "USEND");
Assert.That(response.Result[1].BlockType == ApiPlcProgramBlockType.Sfb);
Assert.That(response.Result[1].BlockNumber == 8);

Assert.That(response.Result[2].Name == "COPY_HW");
Assert.That(response.Result[2].BlockType == ApiPlcProgramBlockType.Sfc);
Assert.That(response.Result[2].BlockNumber == 65509);

Assert.That(response.Result[3].Name == "PRODTEST");
Assert.That(response.Result[3].BlockType == ApiPlcProgramBlockType.Fb);
Assert.That(response.Result[3].BlockNumber == 65522);

Assert.That(response.Result[4].Name == "FC_14325");
Assert.That(response.Result[4].BlockType == ApiPlcProgramBlockType.Fc);
Assert.That(response.Result[4].BlockNumber == 14325);
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public async Task T015_05_ApiPlcProgramBrowseCodeBlocks_EmptyBlockName()
{
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramBrowseCodeBlocksEmptyBlockName); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

ApiPlcProgramBrowseCodeBlocksResponse response = await TestHandler.PlcProgramBrowseCodeBlocksAsync();

Assert.That(response.Result.Count == 1);
Assert.That(response.Result[0].Name == String.Empty);
Assert.That(response.Result[0].BlockType == ApiPlcProgramBlockType.Ob);
Assert.That(response.Result[0].BlockNumber == 1);
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public void T015_06_ApiPlcProgramBrowseCodeBlocks_StringAsBlockNumber()
{
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramBrowseCodeBlocksStringAsNumber); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

Assert.ThrowsAsync<Newtonsoft.Json.JsonSerializationException>(async () => await TestHandler.PlcProgramBrowseCodeBlocksAsync());
}

/// <summary>
///
/// </summary>
/// <returns></returns>
[Test]
public void T015_07_ApiPlcProgramBrowseCodeBlocks_PermissionDenied()
{
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When(HttpMethod.Post, $"https://{Ip.ToString()}/api/jsonrpc")
.Respond("application/json", ResponseStrings.PlcProgramBrowseCodeBlocksPermissionDenied); // Respond with JSON
// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);

Assert.ThrowsAsync<System.UnauthorizedAccessException>(async () => await TestHandler.PlcProgramBrowseCodeBlocksAsync());
}

/// <summary>
///
/// </summary>
11 changes: 11 additions & 0 deletions tests/Webserver.API.UnitTests/ResponseStrings.cs
Original file line number Diff line number Diff line change
@@ -48,10 +48,21 @@ public static class ResponseStrings
public const string PlcProgramBrowseErrorStruct = "{\"jsonrpc\":\"2.0\",\"id\":\"ibf8wom\",\"result\":[{\"name\":\"ERROR_ID\",\"db_number\":1,\"datatype\":\"word\"},{\"name\":\"FLAGS\",\"db_number\":1,\"datatype\":\"byte\"},{\"name\":\"REACTION\",\"db_number\":1,\"datatype\":\"byte\"},{\"name\":\"CODE_ADDRESS\",\"has_children\":true,\"db_number\":1,\"datatype\":\"cref\"},{\"name\":\"MODE\",\"db_number\":1,\"datatype\":\"byte\"},{\"name\":\"OPERAND_NUMBER\",\"db_number\":1,\"datatype\":\"uint\"},{\"name\":\"POINTER_NUMBER_LOCATION\",\"db_number\":1,\"datatype\":\"uint\"},{\"name\":\"SLOT_NUMBER_SCOPE\",\"db_number\":1,\"datatype\":\"uint\"},{\"name\":\"DATA_ADDRESS\",\"has_children\":true,\"db_number\":1,\"datatype\":\"nref\"}]}";
public const string PlcProgramBrowseVarIsNotAStructure = "{\"jsonrpc\":\"2.0\",\"id\":\"5q27h2n\",\"error\":{\"code\":202,\"message\":\"Variable is not a structure\"}}";

public const string PlcProgramBrowseCodeBlocksEmptyResult = "{\"jsonrpc\":\"2.0\",\"id\":\"y9vedkb9\",\"result\":[]}";
public const string PlcProgramBrowseCodeBlocksInvalidParams = "{\"jsonrpc\":\"2.0\",\"id\":55,\"error\":{\"code\":-32602,\"message\":\"Invalid Params\"}}";
public const string PlcProgramBrowseCodeBlocksSuccess = "{\"jsonrpc\":\"2.0\",\"id\":96,\"result\":[{\"name\":\"Main\",\"block_number\":1,\"block_type\":\"ob\"},{\"name\":\"USEND\",\"block_number\":8,\"block_type\":\"sfb\"},{\"name\":\"COPY_HW\",\"block_number\":65509,\"block_type\":\"sfc\"},{\"name\":\"PRODTEST\",\"block_number\":65522,\"block_type\":\"fb\"},{\"name\":\"FC_14325\",\"block_number\":14325,\"block_type\":\"fc\"}]}";
public const string PlcProgramBrowseCodeBlocksEmptyBlockName = "{\"jsonrpc\":\"2.0\",\"id\":96,\"result\":[{\"name\":\"\",\"block_number\":1,\"block_type\":\"ob\"}]}";
public const string PlcProgramBrowseCodeBlocksStringAsNumber = "{\"jsonrpc\":\"2.0\",\"id\":96,\"result\":[{\"name\":\"Main\",\"block_number\":\"abcdefg\",\"block_type\":\"ob\"},{\"name\":\"USEND\",\"block_number\":8,\"block_type\":\"sfb\"},{\"name\":\"COPY_HW\",\"block_number\":65509,\"block_type\":\"sfc\"},{\"name\":\"PRODTEST\",\"block_number\":65522,\"block_type\":\"sfc\"}]}";
public const string PlcProgramBrowseCodeBlocksPermissionDenied = "{\"jsonrpc\":\"2.0\",\"id\":50,\"error\":{\"code\":2,\"message\":\"Permission denied\"}}";

public const string PlcProgramInvalidAddress = "{\"jsonrpc\":\"2.0\",\"id\":\"5uxrl166\",\"error\":{\"code\":201,\"message\":\"Invalid address\"}}";
public const string PlcProgramAddressDoesNotExist = "{\"jsonrpc\":\"2.0\",\"id\":\"8buk8ryn\",\"error\":{\"code\":200,\"message\":\"Address does not exist\"}}";
public const string PlcProgramnInvalidArrayIndex = "{\"jsonrpc\":\"2.0\",\"id\":\"f5eqwla\",\"error\":{\"code\":203,\"message\":\"Invalid array index\"}}";

public const string PlcProgramDownloadProfilingDataSuccess = "{\"jsonrpc\":\"2.0\",\"id\": 6,\"result\":\"jgxikeMgLryvP0YoHc.eqt8BY787\"}";
public const string PlcProgramDownloadProfilingDataPermissionDenied = "{\"jsonrpc\":\"2.0\",\"id\": 18,\"error\":{\"code\": 2,\"message\":\"Permission denied\"}}";
public const string PlcProgramDownloadProfilingDataNoResources = "{\"jsonrpc\":\"2.0\",\"id\":28,\"error\":{\"code\":4,\"message\":\"No Resources\"}}";

public const string PlcProgramUnsupportedAddress = "{\"jsonrpc\":\"2.0\",\"id\":\"1wwe2z8j\",\"error\":{\"code\":204,\"message\":\"Unsupported address\"}}";

public const string PlcProgramReadFalseBool = "{\"jsonrpc\":\"2.0\",\"id\":\"aax109lc\",\"result\":false}";