mirror of
https://gitlab.com/fabinfra/fabaccess/fabaccess-api-cs.git
synced 2025-03-11 14:21:44 +01:00
Added: API v4.0
This commit is contained in:
parent
6c60dc5dcf
commit
dbf19566db
54
API.sln
Normal file
54
API.sln
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34607.119
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FabAccessAPI", "FabAccessAPI\FabAccessAPI.csproj", "{1349C60B-AEDC-4D87-BDE3-68A9E040C6B6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FabAccessAPI_Test", "FabAccessAPI_Test\FabAccessAPI_Test.csproj", "{784C376D-6F28-46F5-AFA7-71DC7F764609}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime", "external\capnproto-dotnetcore_Runtime\Capnp.Net.Runtime\Capnp.Net.Runtime.csproj", "{CA36D5C1-A477-469D-82F7-E70977708FE9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "S22.Sasl", "external\S22.Sasl\S22.Sasl.csproj", "{63DF5EBE-236A-4586-A2DE-95A0A40D1E87}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "external", "external", "{F74FFCEE-898F-4C38-BC49-395475147DED}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2F3CE8F3-459B-44FD-A52B-76A55B1EB028}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
..\borepin_tmp\.editorconfig = ..\borepin_tmp\.editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1349C60B-AEDC-4D87-BDE3-68A9E040C6B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1349C60B-AEDC-4D87-BDE3-68A9E040C6B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1349C60B-AEDC-4D87-BDE3-68A9E040C6B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1349C60B-AEDC-4D87-BDE3-68A9E040C6B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{784C376D-6F28-46F5-AFA7-71DC7F764609}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{784C376D-6F28-46F5-AFA7-71DC7F764609}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{784C376D-6F28-46F5-AFA7-71DC7F764609}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{784C376D-6F28-46F5-AFA7-71DC7F764609}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA36D5C1-A477-469D-82F7-E70977708FE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA36D5C1-A477-469D-82F7-E70977708FE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA36D5C1-A477-469D-82F7-E70977708FE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA36D5C1-A477-469D-82F7-E70977708FE9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{63DF5EBE-236A-4586-A2DE-95A0A40D1E87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{63DF5EBE-236A-4586-A2DE-95A0A40D1E87}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{63DF5EBE-236A-4586-A2DE-95A0A40D1E87}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{63DF5EBE-236A-4586-A2DE-95A0A40D1E87}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{CA36D5C1-A477-469D-82F7-E70977708FE9} = {F74FFCEE-898F-4C38-BC49-395475147DED}
|
||||
{63DF5EBE-236A-4586-A2DE-95A0A40D1E87} = {F74FFCEE-898F-4C38-BC49-395475147DED}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C60AAC74-8D10-421C-B051-908A1D5553BC}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
506
FabAccessAPI/API.cs
Normal file
506
FabAccessAPI/API.cs
Normal file
@ -0,0 +1,506 @@
|
||||
using Capnp.Rpc;
|
||||
using FabAccessAPI.Exceptions;
|
||||
using FabAccessAPI.Exceptions.SASL;
|
||||
using FabAccessAPI.Schema;
|
||||
using NLog;
|
||||
using S22.Sasl;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI
|
||||
{
|
||||
public class API : IAPI
|
||||
{
|
||||
#region Logger
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
/// <summary>
|
||||
/// Internal client to connect to a server with TCP and RPC
|
||||
/// </summary>
|
||||
private TcpRpcClient _TcpRpcClient;
|
||||
|
||||
/// <summary>
|
||||
/// Private ConnectionData
|
||||
/// </summary>
|
||||
private ConnectionData _ConnectionData;
|
||||
|
||||
/// <summary>
|
||||
/// Private ServerData
|
||||
/// </summary>
|
||||
private ServerData _ServerData;
|
||||
|
||||
/// <summary>
|
||||
/// Private Session
|
||||
/// </summary>
|
||||
private Session _Session;
|
||||
|
||||
/// <summary>
|
||||
/// Private Bootstrap
|
||||
/// </summary>
|
||||
private IBootstrap _Bootstrap;
|
||||
|
||||
/// <summary>
|
||||
/// Timer to check connection status
|
||||
/// </summary>
|
||||
private readonly Timer _ConnectionHeatbeat;
|
||||
|
||||
/// <summary>
|
||||
/// Semaphore to connect only once
|
||||
/// </summary>
|
||||
private static readonly SemaphoreSlim _ConnectSemaphore = new SemaphoreSlim(1, 1);
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public API()
|
||||
{
|
||||
_ConnectionHeatbeat = new Timer(Heartbeat, null, 1000, 1000);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Members
|
||||
/// <summary>
|
||||
/// State of the conneciton, can the API-Service connect to a server
|
||||
/// </summary>
|
||||
public bool CanConnect
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ConnectionData != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// State of the conneciton, is the API-Service connecting to a server
|
||||
/// </summary>
|
||||
public bool IsConnecting
|
||||
{
|
||||
get
|
||||
{
|
||||
return _TcpRpcClient != null && _ConnectionData != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// State of the conneciton, is the API-Service connected to a server
|
||||
/// </summary>
|
||||
public bool IsConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
return _TcpRpcClient != null && _TcpRpcClient.State == ConnectionState.Active;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about the connection
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is not connected or trying to connected to a server </exception>
|
||||
public ConnectionData ConnectionData
|
||||
{
|
||||
get
|
||||
{
|
||||
if(_ConnectionData == null || !IsConnecting)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
else
|
||||
{
|
||||
return _ConnectionData;
|
||||
}
|
||||
}
|
||||
private set
|
||||
{
|
||||
_ConnectionData = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about the server
|
||||
/// Is only avalible if the API-Service is connected
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is not connected </exception>
|
||||
public ServerData ServerData
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_ServerData == null || !IsConnected)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
else
|
||||
{
|
||||
return _ServerData;
|
||||
}
|
||||
}
|
||||
private set
|
||||
{
|
||||
_ServerData = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Event on changes in connection status
|
||||
/// </summary>
|
||||
public event EventHandler<ConnectionStatusChanged> ConnectionStatusChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Unbind all handlers from EventHandler<ConnectionStatusChanged>
|
||||
/// </summary>
|
||||
public void UnbindEventHandler()
|
||||
{
|
||||
if (ConnectionStatusChanged != null)
|
||||
{
|
||||
Log.Trace("Eventhandlers unbinded");
|
||||
foreach (Delegate d in ConnectionStatusChanged.GetInvocationList())
|
||||
{
|
||||
ConnectionStatusChanged -= (EventHandler<ConnectionStatusChanged>)d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Eventhandler for TcpRpcConnectionChanged
|
||||
/// Track connection loss and publish i in ConnectionStatusChanged
|
||||
/// </summary>
|
||||
public void OnTcpRpcConnectionChanged(object sender, ConnectionStateChange args)
|
||||
{
|
||||
if (args.LastState == ConnectionState.Active && args.NewState == ConnectionState.Down)
|
||||
{
|
||||
Log.Trace("TcpRpcClient Event ConnectionLoss");
|
||||
ConnectionStatusChanged?.Invoke(this, FabAccessAPI.ConnectionStatusChanged.ConnectionLoss);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Session
|
||||
/// <summary>
|
||||
/// Get session after connection
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is not connected </exception>
|
||||
public Session Session
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Session == null || !IsConnected)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
else
|
||||
{
|
||||
return _Session;
|
||||
}
|
||||
}
|
||||
private set
|
||||
{
|
||||
_Session = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// Connect to server with ConnectionData
|
||||
/// If connection lost, the API-Server will try to reconnect
|
||||
/// </summary>
|
||||
/// <param name="connectionData"> Data to establish a connection to a server </param>
|
||||
/// <exception cref="ConnectionException"> When API-Service can not connect to a server </exception>
|
||||
/// <exception cref="AuthenticationException"> When API-Service can connect to a server but can not authenticate </exception>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is allready connected </exception>
|
||||
public async Task Connect(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null)
|
||||
{
|
||||
await _ConnectSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (IsConnected)
|
||||
{
|
||||
Log.Warn("API already connected");
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
if (tcpRpcClient == null)
|
||||
{
|
||||
tcpRpcClient = new TcpRpcClient();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _ConnectAsync(tcpRpcClient, connectionData).ConfigureAwait(false);
|
||||
|
||||
_Bootstrap = tcpRpcClient.GetMain<IBootstrap>();
|
||||
ServerData = await _GetServerData(_Bootstrap);
|
||||
|
||||
Session = await _Authenticate(connectionData).ConfigureAwait(false);
|
||||
ConnectionData = connectionData;
|
||||
|
||||
_TcpRpcClient = tcpRpcClient;
|
||||
tcpRpcClient.ConnectionStateChanged += OnTcpRpcConnectionChanged;
|
||||
ConnectionStatusChanged?.Invoke(this, FabAccessAPI.ConnectionStatusChanged.Connected);
|
||||
Log.Info("API connected");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warn(ex, "API connect failed");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ConnectSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect from a server
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is not connected or trying to connect </exception>
|
||||
public Task Disconnect()
|
||||
{
|
||||
if (IsConnected)
|
||||
{
|
||||
_TcpRpcClient.Dispose();
|
||||
}
|
||||
|
||||
_Bootstrap = null;
|
||||
_TcpRpcClient = null;
|
||||
|
||||
Session = null;
|
||||
ConnectionData = null;
|
||||
ServerData = null;
|
||||
|
||||
ConnectionStatusChanged?.Invoke(this, FabAccessAPI.ConnectionStatusChanged.Disconnected);
|
||||
|
||||
Log.Info("API disconnected");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to connect to a server and get ServerData
|
||||
/// The connection is not maintained
|
||||
/// </summary>
|
||||
/// <exception cref="ConnectionException"> When API-Service can not connect to a server </exception>
|
||||
public async Task<ServerData> TryToConnect(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null)
|
||||
{
|
||||
if (tcpRpcClient == null)
|
||||
{
|
||||
tcpRpcClient = new TcpRpcClient();
|
||||
}
|
||||
|
||||
await _ConnectAsync(tcpRpcClient, connectionData).ConfigureAwait(false);
|
||||
IBootstrap bootstrap = tcpRpcClient.GetMain<IBootstrap>();
|
||||
|
||||
ServerData serverData = await _GetServerData(bootstrap).ConfigureAwait(false);
|
||||
|
||||
tcpRpcClient.Dispose();
|
||||
|
||||
return serverData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public Wrapper to run HeartbeatAsync
|
||||
/// </summary>
|
||||
public void Heartbeat(object state)
|
||||
{
|
||||
_ = _HeartbeatAsync();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
|
||||
private async Task _HeartbeatAsync()
|
||||
{
|
||||
if(!IsConnected && CanConnect)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Connect(ConnectionData).ConfigureAwait(false);
|
||||
}
|
||||
catch(AuthenticationException)
|
||||
{
|
||||
await Disconnect().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate Certificate
|
||||
/// TODO: Do some validation
|
||||
/// </summary>
|
||||
private bool _RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
// TODO Cert Check
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Injects SSL as Midlayer in TCPRPCConnection
|
||||
/// </summary>
|
||||
/// <exception cref="ConnectionException"></exception>
|
||||
private Stream _InjectSSL(Stream tcpstream)
|
||||
{
|
||||
SslStream sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(_RemoteCertificateValidationCallback));
|
||||
try
|
||||
{
|
||||
sslStream.ReadTimeout = 5000;
|
||||
sslStream.AuthenticateAsClient("bffhd");
|
||||
sslStream.ReadTimeout = -1;
|
||||
|
||||
return sslStream;
|
||||
}
|
||||
catch (System.Security.Authentication.AuthenticationException exception)
|
||||
{
|
||||
sslStream.Close();
|
||||
Log.Warn(exception);
|
||||
throw new ConnectionException("TLS failed", exception);
|
||||
}
|
||||
catch(IOException exception)
|
||||
{
|
||||
sslStream.Close();
|
||||
Log.Warn(exception);
|
||||
throw new ConnectionException("TLS failed", new Exceptions.TimeoutException("TLS timeout", exception));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connect async to a server with ConnectionData
|
||||
/// </summary>
|
||||
/// <exception cref="ConnectionException">Based on RPC Exception</exception>
|
||||
private async Task _ConnectAsync(TcpRpcClient tcprpcClient, ConnectionData connectionData)
|
||||
{
|
||||
tcprpcClient.InjectMidlayer(_InjectSSL);
|
||||
|
||||
try
|
||||
{
|
||||
Task timeoutTask = Task.Delay(5000);
|
||||
tcprpcClient.Connect(connectionData.Host.Host, connectionData.Host.Port);
|
||||
await await Task.WhenAny(tcprpcClient.WhenConnected, timeoutTask);
|
||||
|
||||
if (timeoutTask.IsCompleted)
|
||||
{
|
||||
Exceptions.TimeoutException timeoutException = new Exceptions.TimeoutException();
|
||||
Log.Warn(timeoutException);
|
||||
throw new ConnectionException("Connection timeout", timeoutException);
|
||||
}
|
||||
}
|
||||
catch (RpcException exception) when (string.Equals(exception.Message, "TcpRpcClient is unable to connect", StringComparison.Ordinal))
|
||||
{
|
||||
Log.Warn(exception);
|
||||
throw new ConnectionException("RPC Connecting failed", exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate connection with ConnectionData
|
||||
/// </summary>
|
||||
/// <param name="connectionData"> Data to establish a connection to a server </param>
|
||||
/// <exception cref="AuthenticationException"></exception>
|
||||
private async Task<Session> _Authenticate(ConnectionData connectionData)
|
||||
{
|
||||
IAuthentication? authentication = await _Bootstrap.CreateSession(SASLMechanism.ToString(connectionData.Mechanism)).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
return await _SASLAuthenticate(authentication, SASLMechanism.ToString(connectionData.Mechanism), connectionData.Properties).ConfigureAwait(false);
|
||||
}
|
||||
catch (System.Exception exception)
|
||||
{
|
||||
Log.Warn(exception, "API authenticating failed");
|
||||
AuthenticationException authenticationException = new AuthenticationException("Authentication failed", exception);
|
||||
|
||||
throw authenticationException;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate with SASL
|
||||
/// </summary>
|
||||
/// <exception cref="BadMechanismException"></exception>
|
||||
/// <exception cref="InvalidCredentialsException"></exception>
|
||||
/// <exception cref="AuthenticationFailedException"></exception>
|
||||
private async Task<Session> _SASLAuthenticate(IAuthentication authentication, string mech, Dictionary<string, object> properties)
|
||||
{
|
||||
SaslMechanism? saslMechanism = SaslFactory.Create(mech);
|
||||
foreach (KeyValuePair<string, object> entry in properties)
|
||||
{
|
||||
saslMechanism.Properties.Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
byte[] data = new byte[0];
|
||||
|
||||
if (saslMechanism.HasInitial)
|
||||
{
|
||||
data = saslMechanism.GetResponse(new byte[0]);
|
||||
}
|
||||
|
||||
Response? response = await authentication.Step(data);
|
||||
while (!saslMechanism.IsCompleted)
|
||||
{
|
||||
if (response.Failed != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (response.Challenge != null)
|
||||
{
|
||||
byte[]? additional = saslMechanism.GetResponse(response.Challenge.ToArray());
|
||||
response = await authentication.Step(additional);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AuthenticationFailedException();
|
||||
}
|
||||
}
|
||||
|
||||
if (response.Successful != null)
|
||||
{
|
||||
return response.Successful.Session;
|
||||
}
|
||||
else if (response.Failed != null)
|
||||
{
|
||||
switch (response.Failed.Code)
|
||||
{
|
||||
case Response.Error.badMechanism:
|
||||
throw new BadMechanismException();
|
||||
case Response.Error.invalidCredentials:
|
||||
throw new InvalidCredentialsException();
|
||||
case Response.Error.aborted:
|
||||
case Response.Error.failed:
|
||||
default:
|
||||
throw new AuthenticationFailedException(response.Failed.AdditionalData.ToArray());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AuthenticationFailedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get ServerData from server with tcprpcconnection
|
||||
/// </summary>
|
||||
private async Task<ServerData> _GetServerData(IBootstrap bootstrap)
|
||||
{
|
||||
ServerData serverData = new ServerData()
|
||||
{
|
||||
APIVersion = await bootstrap.GetAPIVersion().ConfigureAwait(false),
|
||||
Mechanisms = new List<string>(await bootstrap.Mechanisms().ConfigureAwait(false)),
|
||||
ServerName = (await bootstrap.GetServerRelease().ConfigureAwait(false)).Item1,
|
||||
ServerRelease = (await bootstrap.GetServerRelease().ConfigureAwait(false)).Item2,
|
||||
};
|
||||
|
||||
return serverData;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
45
FabAccessAPI/ConnectionData.cs
Normal file
45
FabAccessAPI/ConnectionData.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FabAccessAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// Data to establish a connection to a server
|
||||
/// With Data for Authentication
|
||||
/// </summary>
|
||||
public class ConnectionData
|
||||
{
|
||||
public Uri Host;
|
||||
public string Username;
|
||||
|
||||
public SASLMechanismEnum Mechanism;
|
||||
public Dictionary<string, object> Properties;
|
||||
|
||||
public DateTime LastTime;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if(obj is ConnectionData && obj != null)
|
||||
{
|
||||
ConnectionData? data = obj as ConnectionData;
|
||||
|
||||
return data.Host.Host == Host.Host &&
|
||||
data.Host.Port == Host.Port &&
|
||||
data.Mechanism == Mechanism &&
|
||||
data.Username == Username;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hashCode = -1151110446;
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<Uri>.Default.GetHashCode(Host);
|
||||
hashCode = hashCode * -1521134295 + Mechanism.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Username);
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<Dictionary<string, object>>.Default.GetHashCode(Properties);
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
20
FabAccessAPI/ConnectionStatusChanged.cs
Normal file
20
FabAccessAPI/ConnectionStatusChanged.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace FabAccessAPI
|
||||
{
|
||||
public enum ConnectionStatusChanged
|
||||
{
|
||||
/// <summary>
|
||||
/// API-Service has established connection to server
|
||||
/// </summary>
|
||||
Connected,
|
||||
|
||||
/// <summary>
|
||||
/// API-Service has closed the connection to a server
|
||||
/// </summary>
|
||||
Disconnected,
|
||||
|
||||
/// <summary>
|
||||
/// Connection was lost and the API-Service will try to reconnect automatically
|
||||
/// </summary>
|
||||
ConnectionLoss
|
||||
}
|
||||
}
|
22
FabAccessAPI/Exceptions/APIIncompatibleException.cs
Normal file
22
FabAccessAPI/Exceptions/APIIncompatibleException.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions
|
||||
{
|
||||
public class APIIncompatibleException : Exception
|
||||
{
|
||||
public APIIncompatibleException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public APIIncompatibleException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public APIIncompatibleException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
26
FabAccessAPI/Exceptions/AuthenticationException.cs
Normal file
26
FabAccessAPI/Exceptions/AuthenticationException.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Authenticating to a server has failed
|
||||
/// InnerException will provide more information
|
||||
/// </summary>
|
||||
public class AuthenticationException : Exception
|
||||
{
|
||||
public AuthenticationException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AuthenticationException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AuthenticationException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
26
FabAccessAPI/Exceptions/ConnectionException.cs
Normal file
26
FabAccessAPI/Exceptions/ConnectionException.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Connecting to a server has failed
|
||||
/// InnerException will provide more information
|
||||
/// </summary>
|
||||
public class ConnectionException : Exception
|
||||
{
|
||||
public ConnectionException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ConnectionException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ConnectionException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
22
FabAccessAPI/Exceptions/ReconnectingFailedException.cs
Normal file
22
FabAccessAPI/Exceptions/ReconnectingFailedException.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions
|
||||
{
|
||||
public class ReconnectingFailedException : Exception
|
||||
{
|
||||
public ReconnectingFailedException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ReconnectingFailedException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ReconnectingFailedException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions.SASL
|
||||
{
|
||||
public class AuthenticationFailedException : Exception
|
||||
{
|
||||
#region Constructors
|
||||
public AuthenticationFailedException(byte[] additionalData = null)
|
||||
{
|
||||
AdditionalData = additionalData;
|
||||
}
|
||||
|
||||
public AuthenticationFailedException(byte[] additionalData, string message) : base(message)
|
||||
{
|
||||
AdditionalData = additionalData;
|
||||
}
|
||||
|
||||
public AuthenticationFailedException(byte[] additionalData, string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
AdditionalData = additionalData;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
public byte[]? AdditionalData { get; }
|
||||
#endregion
|
||||
}
|
||||
}
|
22
FabAccessAPI/Exceptions/SASL/BadMechanismException.cs
Normal file
22
FabAccessAPI/Exceptions/SASL/BadMechanismException.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions.SASL
|
||||
{
|
||||
public class BadMechanismException : Exception
|
||||
{
|
||||
public BadMechanismException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BadMechanismException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BadMechanismException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
22
FabAccessAPI/Exceptions/SASL/InvalidCredentialsException.cs
Normal file
22
FabAccessAPI/Exceptions/SASL/InvalidCredentialsException.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions.SASL
|
||||
{
|
||||
public class InvalidCredentialsException : Exception
|
||||
{
|
||||
public InvalidCredentialsException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public InvalidCredentialsException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public InvalidCredentialsException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
25
FabAccessAPI/Exceptions/TimeoutException.cs
Normal file
25
FabAccessAPI/Exceptions/TimeoutException.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Timeout on Connection
|
||||
/// </summary>
|
||||
public class TimeoutException : Exception
|
||||
{
|
||||
public TimeoutException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TimeoutException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TimeoutException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
22
FabAccessAPI/Exceptions/UnsupportedMechanismException.cs
Normal file
22
FabAccessAPI/Exceptions/UnsupportedMechanismException.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI.Exceptions
|
||||
{
|
||||
public class UnsupportedMechanismException : Exception
|
||||
{
|
||||
public UnsupportedMechanismException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public UnsupportedMechanismException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public UnsupportedMechanismException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
19
FabAccessAPI/FabAccessAPI.csproj
Normal file
19
FabAccessAPI/FabAccessAPI.csproj
Normal file
@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CapnpC.CSharp.MsBuild.Generation" Version="1.3.118" />
|
||||
<PackageReference Include="NLog" Version="5.2.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\external\capnproto-dotnetcore_Runtime\Capnp.Net.Runtime\Capnp.Net.Runtime.csproj" />
|
||||
<ProjectReference Include="..\external\S22.Sasl\S22.Sasl.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
84
FabAccessAPI/IAPI.cs
Normal file
84
FabAccessAPI/IAPI.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Capnp.Rpc;
|
||||
using FabAccessAPI.Exceptions;
|
||||
using FabAccessAPI.Schema;
|
||||
|
||||
namespace FabAccessAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to connect to a server and maintain the connection
|
||||
/// </summary>
|
||||
public interface IAPI
|
||||
{
|
||||
#region Information about a connection and the server
|
||||
/// <summary>
|
||||
/// State of the conneciton, is the API-Service connecting to a server
|
||||
/// </summary>
|
||||
bool IsConnecting { get; }
|
||||
|
||||
/// <summary>
|
||||
/// State of the conneciton, is the API-Service connected to a server
|
||||
/// </summary>
|
||||
bool IsConnected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Information about the connection
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is not connected or trying to connected to a server </exception>
|
||||
ConnectionData ConnectionData { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Information about the server
|
||||
/// Is only avalible if the API-Service is connected
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is not connected </exception>
|
||||
ServerData ServerData { get; }
|
||||
#endregion
|
||||
|
||||
#region Methods to connect to server
|
||||
/// <summary>
|
||||
/// Connect to server with ConnectionData
|
||||
/// If connection lost, the API-Server will try to reconnect
|
||||
/// </summary>
|
||||
/// <param name="connectionData"> Data to establish a connection to a server </param>
|
||||
/// <exception cref="ConnectionException"> When API-Service can not connect to a server </exception>
|
||||
/// <exception cref="AuthenticationException"> When API-Service can connect to a server but can not authenticate </exception>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is allready connected </exception>
|
||||
Task Connect(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null);
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect from a server
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is not connected or trying to connect </exception>
|
||||
Task Disconnect();
|
||||
|
||||
/// <summary>
|
||||
/// Try to connect to a server and get ServerData
|
||||
/// The connection is not maintained
|
||||
/// </summary>
|
||||
/// <exception cref="ConnectionException"> When API-Service can not connect to a server </exception>
|
||||
Task<ServerData> TryToConnect(ConnectionData connectionData, TcpRpcClient tcpRpcClient = null);
|
||||
#endregion
|
||||
|
||||
#region Session
|
||||
/// <summary>
|
||||
/// Get session after connection
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"> When API-Service is not connected </exception>
|
||||
Session Session { get; }
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Event on changes in connection status
|
||||
/// </summary>
|
||||
event EventHandler<ConnectionStatusChanged> ConnectionStatusChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Unbind all handlers from EventHandler<ConnectionStatusChanged>
|
||||
/// </summary>
|
||||
void UnbindEventHandler();
|
||||
#endregion
|
||||
}
|
||||
}
|
24
FabAccessAPI/SASLMechanismEnum.cs
Normal file
24
FabAccessAPI/SASLMechanismEnum.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace FabAccessAPI
|
||||
{
|
||||
public enum SASLMechanismEnum
|
||||
{
|
||||
PLAIN,
|
||||
}
|
||||
|
||||
public static class SASLMechanism
|
||||
{
|
||||
public static string ToString(SASLMechanismEnum mechanism)
|
||||
{
|
||||
switch(mechanism)
|
||||
{
|
||||
case SASLMechanismEnum.PLAIN:
|
||||
return "PLAIN";
|
||||
default:
|
||||
throw new ArgumentException("Mechanism unknown.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
13
FabAccessAPI/ServerData.cs
Normal file
13
FabAccessAPI/ServerData.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FabAccessAPI
|
||||
{
|
||||
public class ServerData
|
||||
{
|
||||
public Schema.Version APIVersion;
|
||||
public string ServerName;
|
||||
public string ServerRelease;
|
||||
public List<string> Mechanisms;
|
||||
}
|
||||
}
|
174
FabAccessAPI_Test/API_Test.cs
Normal file
174
FabAccessAPI_Test/API_Test.cs
Normal file
@ -0,0 +1,174 @@
|
||||
using Capnp.Rpc;
|
||||
using FabAccessAPI;
|
||||
using FabAccessAPI.Exceptions;
|
||||
using FabAccessAPI.Exceptions.SASL;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI_Test
|
||||
{
|
||||
public class API_Test
|
||||
{
|
||||
[Test]
|
||||
public async Task Connect_HostUnreachable()
|
||||
{
|
||||
API api = new API();
|
||||
|
||||
ConnectionData connectionData = new ConnectionData()
|
||||
{
|
||||
Host = new UriBuilder(TestEnv.SCHEMA, "UnkownHost" + TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri,
|
||||
Mechanism = SASLMechanismEnum.PLAIN,
|
||||
Username = "UnkownUser",
|
||||
Properties = new Dictionary<string, object>()
|
||||
{
|
||||
{ "Username", "UnkownUser" },
|
||||
{ "Password", TestEnv.PASSWORD }
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await api.Connect(connectionData);
|
||||
}
|
||||
catch (ConnectionException)
|
||||
{
|
||||
ClassicAssert.Pass();
|
||||
}
|
||||
ClassicAssert.Fail();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Connect_InvalidCredentials()
|
||||
{
|
||||
API api = new API();
|
||||
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData("UnkownUser");
|
||||
|
||||
try
|
||||
{
|
||||
await api.Connect(connectionData);
|
||||
}
|
||||
catch(AuthenticationException exception) when (exception.InnerException is InvalidCredentialsException)
|
||||
{
|
||||
ClassicAssert.Pass();
|
||||
}
|
||||
ClassicAssert.Fail();
|
||||
}
|
||||
|
||||
[TestCase("Admin1")]
|
||||
public async Task ConnectDisconnect(string username)
|
||||
{
|
||||
API api = new API();
|
||||
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
|
||||
bool event_Connected = false;
|
||||
bool event_Disconnected = false;
|
||||
api.ConnectionStatusChanged += (sender, eventArgs) =>
|
||||
{
|
||||
if (eventArgs == ConnectionStatusChanged.Connected)
|
||||
{
|
||||
event_Connected = true;
|
||||
}
|
||||
if(eventArgs == ConnectionStatusChanged.Disconnected)
|
||||
{
|
||||
event_Disconnected = true;
|
||||
}
|
||||
};
|
||||
|
||||
await api.Connect(connectionData);
|
||||
|
||||
bool HasSesion = api.Session != null;
|
||||
bool HasConnectionData = api.ConnectionData != null;
|
||||
bool HasServerData = api.ServerData != null;
|
||||
bool IsConnected = api.IsConnected;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
Thread.Sleep(3000);
|
||||
ClassicAssert.Multiple(() =>
|
||||
{
|
||||
ClassicAssert.IsTrue(event_Connected, "event_Connected");
|
||||
ClassicAssert.IsTrue(event_Disconnected, "event_Disconnected");
|
||||
|
||||
ClassicAssert.IsTrue(HasSesion, "HasSesion");
|
||||
ClassicAssert.IsTrue(HasConnectionData, "HasConnectionData");
|
||||
ClassicAssert.IsTrue(HasServerData, "HasServerData");
|
||||
ClassicAssert.IsTrue(IsConnected, "IsConnected");
|
||||
|
||||
ClassicAssert.IsFalse(api.IsConnected, "api.IsConnected");
|
||||
});
|
||||
}
|
||||
|
||||
[TestCase("Admin1")]
|
||||
public async Task TestConnectíon(string username)
|
||||
{
|
||||
API api = new API();
|
||||
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
|
||||
ServerData serverData = await api.TryToConnect(connectionData);
|
||||
|
||||
ClassicAssert.IsNotNull(serverData);
|
||||
}
|
||||
|
||||
[TestCase("Admin1"), Explicit]
|
||||
public async Task Reconnect(string username)
|
||||
{
|
||||
API api = new API();
|
||||
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
|
||||
int event_Connected = 0;
|
||||
int event_ConnectionLoss = 0;
|
||||
int event_Disconnected = 0;
|
||||
|
||||
api.ConnectionStatusChanged += (sender, eventArgs) =>
|
||||
{
|
||||
if (eventArgs == ConnectionStatusChanged.Connected)
|
||||
{
|
||||
event_Connected++;
|
||||
}
|
||||
if (eventArgs == ConnectionStatusChanged.ConnectionLoss)
|
||||
{
|
||||
event_ConnectionLoss++;
|
||||
}
|
||||
if (eventArgs == ConnectionStatusChanged.Disconnected)
|
||||
{
|
||||
event_Disconnected++;
|
||||
}
|
||||
};
|
||||
|
||||
TcpRpcClient tcpRpcClient = new TcpRpcClient();
|
||||
await api.Connect(connectionData, tcpRpcClient);
|
||||
|
||||
try
|
||||
{
|
||||
// Stop here and cut internet connection
|
||||
await api.Session.MachineSystem.Info.GetMachineList().ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
Thread.Sleep(3000);
|
||||
|
||||
// Stop here and connect with internet again
|
||||
await api.Disconnect();
|
||||
|
||||
Thread.Sleep(1000);
|
||||
ClassicAssert.Multiple(() =>
|
||||
{
|
||||
ClassicAssert.AreEqual(2, event_Connected, "event_Connected");
|
||||
ClassicAssert.AreEqual(1, event_ConnectionLoss, "event_ConnectionLoss");
|
||||
ClassicAssert.AreEqual(1, event_Disconnected, "event_Disconnected");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
199
FabAccessAPI_Test/API_TestEnv/MachineSystem_Test_Stateless.cs
Normal file
199
FabAccessAPI_Test/API_TestEnv/MachineSystem_Test_Stateless.cs
Normal file
@ -0,0 +1,199 @@
|
||||
using FabAccessAPI;
|
||||
using FabAccessAPI.Schema;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI_Test.API_TestEnv
|
||||
{
|
||||
[TestFixture, Parallelizable(ParallelScope.Children)]
|
||||
[Order(1)]
|
||||
public class MachineSystem_Test_Stateless
|
||||
{
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("Admin2", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("ManagerA2", true)]
|
||||
[TestCase("ManagerB1", true)]
|
||||
[TestCase("ManagerB2", true)]
|
||||
[TestCase("ManagerC1", true)]
|
||||
[TestCase("ManagerC2", true)]
|
||||
[TestCase("ManagerABC1", true)]
|
||||
[TestCase("ManagerABC2", true)]
|
||||
[TestCase("MakerA1", true)]
|
||||
[TestCase("MakerA2", true)]
|
||||
[TestCase("MakerB1", true)]
|
||||
[TestCase("MakerB2", true)]
|
||||
[TestCase("MakerC1", true)]
|
||||
[TestCase("MakerC2", true)]
|
||||
[TestCase("MakerABC1", true)]
|
||||
[TestCase("MakerABC2", true)]
|
||||
[TestCase("GuestA1", true)]
|
||||
[TestCase("GuestA2", true)]
|
||||
[TestCase("GuestB1", true)]
|
||||
[TestCase("GuestB2", true)]
|
||||
[TestCase("GuestC1", true)]
|
||||
[TestCase("GuestC2", true)]
|
||||
[TestCase("GuestABC1", true)]
|
||||
[TestCase("GuestABC2", true)]
|
||||
[TestCase("MakerQRA", true)]
|
||||
[TestCase("MakerQRB", true)]
|
||||
[TestCase("MakerQRC", true)]
|
||||
[Order(2)]
|
||||
public async Task AccessMachineSystem_Info(string username, bool expectAllow)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
ClassicAssert.AreEqual(expectAllow, !((MachineSystem.InfoInterface_Proxy)api.Session.MachineSystem.Info).IsNull);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", 15)]
|
||||
[TestCase("ManagerA1", 5)]
|
||||
[TestCase("ManagerB1", 5)]
|
||||
[TestCase("ManagerC1", 5)]
|
||||
[TestCase("ManagerABC1", 15)]
|
||||
[TestCase("MakerA1", 5)]
|
||||
[TestCase("MakerB1", 5)]
|
||||
[TestCase("MakerC1", 5)]
|
||||
[TestCase("MakerABC1", 15)]
|
||||
[TestCase("GuestA1", 5)]
|
||||
[TestCase("GuestB1", 5)]
|
||||
[TestCase("GuestC1", 5)]
|
||||
[TestCase("GuestABC1", 15)]
|
||||
[TestCase("MakerQRA", 0)]
|
||||
[TestCase("MakerQRB", 0)]
|
||||
[TestCase("MakerQRC", 0)]
|
||||
[Order(3)]
|
||||
public async Task ListMachines(string username, int expectedMachineCount)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
IReadOnlyList<Machine> machine_list = await api.Session.MachineSystem.Info.GetMachineList().ConfigureAwait(false);
|
||||
|
||||
int result = machine_list.Count;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectedMachineCount, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "MachineA1", true)]
|
||||
[TestCase("Admin1", "MachineB1", true)]
|
||||
[TestCase("Admin1", "MachineC1", true)]
|
||||
[TestCase("ManagerA1", "MachineA1", true)]
|
||||
[TestCase("ManagerA1", "MachineB1", false)]
|
||||
[TestCase("ManagerA1", "MachineC1", false)]
|
||||
[TestCase("ManagerB1", "MachineA1", false)]
|
||||
[TestCase("ManagerB1", "MachineB1", true)]
|
||||
[TestCase("ManagerB1", "MachineC1", false)]
|
||||
[TestCase("ManagerC1", "MachineA1", false)]
|
||||
[TestCase("ManagerC1", "MachineB1", false)]
|
||||
[TestCase("ManagerC1", "MachineC1", true)]
|
||||
[TestCase("ManagerABC1", "MachineA1", true)]
|
||||
[TestCase("ManagerABC1", "MachineB1", true)]
|
||||
[TestCase("ManagerABC1", "MachineC1", true)]
|
||||
[TestCase("MakerA1", "MachineA1", true)]
|
||||
[TestCase("MakerB1", "MachineB1", true)]
|
||||
[TestCase("MakerC1", "MachineC1", true)]
|
||||
[TestCase("GuestA1", "MachineA1", true)]
|
||||
[TestCase("GuestB1", "MachineB1", true)]
|
||||
[TestCase("GuestC1", "MachineC1", true)]
|
||||
[TestCase("MakerQRA", "MachineA1", true)]
|
||||
[TestCase("MakerQRB", "MachineB1", true)]
|
||||
[TestCase("MakerQRC", "MachineC1", true)]
|
||||
[Order(4)]
|
||||
public async Task GetMachineByName(string username, string machineName, bool expectedAllow)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Optional<Machine> optional = await api.Session.MachineSystem.Info.GetMachine(machineName).ConfigureAwait(false);
|
||||
|
||||
bool result = optional.Just != null;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectedAllow, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "MachineX")]
|
||||
[TestCase("Admin1", "urn:fabaccess:resource:MachineA1")]
|
||||
[Order(5)]
|
||||
public async Task GetMachineByName_WrongName(string username, string machineName)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Optional<Machine> optional = await api.Session.MachineSystem.Info.GetMachine(machineName).ConfigureAwait(false);
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsNull(optional.Just);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "urn:fabaccess:resource:MachineA1", true)]
|
||||
[TestCase("Admin1", "urn:fabaccess:resource:MachineB1", true)]
|
||||
[TestCase("Admin1", "urn:fabaccess:resource:MachineC1", true)]
|
||||
[TestCase("ManagerA1", "urn:fabaccess:resource:MachineA1", true)]
|
||||
[TestCase("ManagerA1", "urn:fabaccess:resource:MachineB1", false)]
|
||||
[TestCase("ManagerA1", "urn:fabaccess:resource:MachineC1", false)]
|
||||
[TestCase("ManagerB1", "urn:fabaccess:resource:MachineA1", false)]
|
||||
[TestCase("ManagerB1", "urn:fabaccess:resource:MachineB1", true)]
|
||||
[TestCase("ManagerB1", "urn:fabaccess:resource:MachineC1", false)]
|
||||
[TestCase("ManagerC1", "urn:fabaccess:resource:MachineA1", false)]
|
||||
[TestCase("ManagerC1", "urn:fabaccess:resource:MachineB1", false)]
|
||||
[TestCase("ManagerC1", "urn:fabaccess:resource:MachineC1", true)]
|
||||
[TestCase("ManagerABC1", "urn:fabaccess:resource:MachineA1", true)]
|
||||
[TestCase("ManagerABC1", "urn:fabaccess:resource:MachineB1", true)]
|
||||
[TestCase("ManagerABC1", "urn:fabaccess:resource:MachineC1", true)]
|
||||
[TestCase("MakerA1", "urn:fabaccess:resource:MachineA1", true)]
|
||||
[TestCase("MakerB1", "urn:fabaccess:resource:MachineB1", true)]
|
||||
[TestCase("MakerC1", "urn:fabaccess:resource:MachineC1", true)]
|
||||
[TestCase("GuestA1", "urn:fabaccess:resource:MachineA1", true)]
|
||||
[TestCase("GuestB1", "urn:fabaccess:resource:MachineB1", true)]
|
||||
[TestCase("GuestC1", "urn:fabaccess:resource:MachineC1", true)]
|
||||
[TestCase("MakerQRA", "urn:fabaccess:resource:MachineA1", true)]
|
||||
[TestCase("MakerQRB", "urn:fabaccess:resource:MachineB1", true)]
|
||||
[TestCase("MakerQRC", "urn:fabaccess:resource:MachineC1", true)]
|
||||
|
||||
[Order(6)]
|
||||
public async Task GetMachineByURN(string username, string urn, bool expectedAllow)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Optional<Machine> optional = await api.Session.MachineSystem.Info.GetMachineURN(urn).ConfigureAwait(false);
|
||||
bool result = optional.Just != null;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectedAllow, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "urn:fabaccess:resource:MachineX")]
|
||||
[TestCase("Admin1", "MachineA1")]
|
||||
[TestCase("Admin1", "something")]
|
||||
[Order(7)]
|
||||
public async Task GetMachineByURN_WrongURN(string username, string urn)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Optional<Machine> optional = await api.Session.MachineSystem.Info.GetMachineURN(urn).ConfigureAwait(false);
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsNull(optional.Just);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
301
FabAccessAPI_Test/API_TestEnv/Machine_Test.cs
Normal file
301
FabAccessAPI_Test/API_TestEnv/Machine_Test.cs
Normal file
@ -0,0 +1,301 @@
|
||||
using FabAccessAPI;
|
||||
using FabAccessAPI.Schema;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI_Test.API_TestEnv
|
||||
{
|
||||
[TestFixture]
|
||||
public class Machine_Test
|
||||
{
|
||||
#region SetUp
|
||||
[SetUp]
|
||||
public async Task SetUp()
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData("Admin1");
|
||||
await api.Connect(connectionData);
|
||||
|
||||
IReadOnlyList<Machine> machine_list = await api.Session.MachineSystem.Info.GetMachineList().ConfigureAwait(false);
|
||||
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (Machine m in machine_list)
|
||||
{
|
||||
tasks.Add(m.Manage.ForceFree());
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
#endregion
|
||||
|
||||
[TestCase("Admin1", "MachineA1")]
|
||||
[TestCase("ManagerA1", "MachineA1")]
|
||||
[TestCase("MakerA1", "MachineA1")]
|
||||
[Order(1)]
|
||||
public async Task UseGiveBack(string username, string machineID)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
// Check State before run Test
|
||||
if (machine.State != Machine.MachineState.free)
|
||||
{
|
||||
await api.Disconnect();
|
||||
ClassicAssert.Inconclusive("State is not 'free'");
|
||||
}
|
||||
|
||||
await machine.Use.Use().ConfigureAwait(false);
|
||||
|
||||
machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine.Inuse.GiveBack().ConfigureAwait(false);
|
||||
|
||||
machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(Machine.MachineState.free, machine.State);
|
||||
}
|
||||
|
||||
[TestCase("ManagerA1", "MakerA1", "MachineA1")]
|
||||
[TestCase("MakerA1", "Admin1", "MachineA1")]
|
||||
[TestCase("ManagerA1", "GuestA1", "MachineA1")]
|
||||
[Order(2), Ignore("Not Implemented")]
|
||||
public async Task TransferMachine(string username1, string username2, string machineID)
|
||||
{
|
||||
API api1 = new API();
|
||||
ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1);
|
||||
await api1.Connect(connectionData1);
|
||||
|
||||
API api2 = new API();
|
||||
ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2);
|
||||
await api2.Connect(connectionData2);
|
||||
|
||||
Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
// Check State before run Test
|
||||
if (machine1.State != Machine.MachineState.free)
|
||||
{
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
ClassicAssert.Inconclusive("State is not 'free'");
|
||||
}
|
||||
|
||||
await machine1.Use.Use().ConfigureAwait(false);
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine1.Inuse.Releasefortakeover().ConfigureAwait(false);
|
||||
|
||||
Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine2.Takeover.Accept().ConfigureAwait(false);
|
||||
|
||||
machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine2.Inuse.GiveBack().ConfigureAwait(false);
|
||||
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(Machine.MachineState.free, machine1.State);
|
||||
}
|
||||
|
||||
[TestCase("ManagerA1", "MakerA1", "MachineA1")]
|
||||
[TestCase("MakerA1", "Admin1", "MachineA1")]
|
||||
[TestCase("ManagerA1", "GuestA1", "MachineA1")]
|
||||
[Order(3), Ignore("Not Implemented")]
|
||||
public async Task TransferMachine_Reject(string username1, string username2, string machineID)
|
||||
{
|
||||
API api1 = new API();
|
||||
ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1);
|
||||
await api1.Connect(connectionData1);
|
||||
|
||||
API api2 = new API();
|
||||
ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2);
|
||||
await api2.Connect(connectionData2);
|
||||
|
||||
Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
// Check State before run Test
|
||||
if (machine1.State != Machine.MachineState.free)
|
||||
{
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
ClassicAssert.Inconclusive("State is not 'free'");
|
||||
}
|
||||
|
||||
await machine1.Use.Use().ConfigureAwait(false);
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine1.Inuse.Releasefortakeover().ConfigureAwait(false);
|
||||
|
||||
Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine2.Takeover.Reject().ConfigureAwait(false);
|
||||
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine1.Inuse.GiveBack().ConfigureAwait(false);
|
||||
|
||||
machine2 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(Machine.MachineState.free, machine2.State);
|
||||
}
|
||||
|
||||
[TestCase("ManagerA1", "ManagerA1", "MachineA1")]
|
||||
[TestCase("ManagerA1", "Admin1", "MachineA1")]
|
||||
[TestCase("MakerA1", "Admin1", "MachineA1")]
|
||||
[Order(4), Ignore("Not Implemented")]
|
||||
public async Task CheckMachine(string username1, string username2, string machineID)
|
||||
{
|
||||
API api1 = new API();
|
||||
ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1);
|
||||
await api1.Connect(connectionData1);
|
||||
|
||||
API api2 = new API();
|
||||
ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2);
|
||||
await api2.Connect(connectionData2);
|
||||
|
||||
Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
// Check State before run Test
|
||||
if (machine1.State != Machine.MachineState.free)
|
||||
{
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
ClassicAssert.Inconclusive("State is not 'free'");
|
||||
}
|
||||
|
||||
await machine1.Use.Use().ConfigureAwait(false);
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine1.Inuse.GiveBack().ConfigureAwait(false);
|
||||
|
||||
Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine2.Check.Check().ConfigureAwait(false);
|
||||
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(Machine.MachineState.free, machine1.State);
|
||||
}
|
||||
|
||||
[TestCase("ManagerA1", "ManagerA1", "MachineA1")]
|
||||
[TestCase("ManagerA1", "Admin1", "MachineA1")]
|
||||
[TestCase("MakerA1", "Admin1", "MachineA1")]
|
||||
[Order(5), Ignore("Not Implemented")]
|
||||
public async Task CheckMachine_Reject(string username1, string username2, string machineID)
|
||||
{
|
||||
API api1 = new API();
|
||||
ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1);
|
||||
await api1.Connect(connectionData1);
|
||||
|
||||
API api2 = new API();
|
||||
ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2);
|
||||
await api2.Connect(connectionData2);
|
||||
|
||||
|
||||
Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
// Check State before run Test
|
||||
if (machine1.State != Machine.MachineState.free)
|
||||
{
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
ClassicAssert.Inconclusive("State is not 'free'");
|
||||
}
|
||||
|
||||
await machine1.Use.Use().ConfigureAwait(false);
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine1.Inuse.GiveBack().ConfigureAwait(false);
|
||||
|
||||
Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine2.Check.Reject().ConfigureAwait(false);
|
||||
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine1.Inuse.GiveBack().ConfigureAwait(false);
|
||||
|
||||
machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine2.Check.Check().ConfigureAwait(false);
|
||||
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(Machine.MachineState.free, machine1.State);
|
||||
}
|
||||
|
||||
[TestCase("MakerA1", "GuestA1", "ManagerA1", "MachineA1")]
|
||||
[Order(4), Ignore("Not Implemented")]
|
||||
public async Task CheckMachine_NoPermission(string username1, string username2, string username3, string machineID)
|
||||
{
|
||||
API api1 = new API();
|
||||
ConnectionData connectionData1 = TestEnv.CreateConnetionData(username1);
|
||||
await api1.Connect(connectionData1);
|
||||
|
||||
API api2 = new API();
|
||||
ConnectionData connectionData2 = TestEnv.CreateConnetionData(username2);
|
||||
await api2.Connect(connectionData2);
|
||||
|
||||
API api3 = new API();
|
||||
ConnectionData connectionData3 = TestEnv.CreateConnetionData(username3);
|
||||
await api3.Connect(connectionData3);
|
||||
|
||||
Machine machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
// Check State before run Test
|
||||
if (machine1.State != Machine.MachineState.free)
|
||||
{
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
await api3.Disconnect();
|
||||
ClassicAssert.Inconclusive("State is not 'free'");
|
||||
}
|
||||
|
||||
await machine1.Use.Use().ConfigureAwait(false);
|
||||
machine1 = (await api1.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine1.Inuse.GiveBack().ConfigureAwait(false);
|
||||
|
||||
Machine machine2 = (await api2.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
bool result = ((Machine.CheckInterface_Proxy)machine2.Check).IsNull;
|
||||
|
||||
Machine machine3 = (await api3.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
await machine3.Check.Check().ConfigureAwait(false);
|
||||
|
||||
await api1.Disconnect();
|
||||
await api2.Disconnect();
|
||||
await api3.Disconnect();
|
||||
|
||||
ClassicAssert.IsTrue(result);
|
||||
}
|
||||
|
||||
[TestCase("ManagerA1", "MachineA1")]
|
||||
[Order(5)]
|
||||
public async Task CurrentUser(string username, string machineID)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
// Check State before run Test
|
||||
if (machine.State != Machine.MachineState.free)
|
||||
{
|
||||
await api.Disconnect();
|
||||
ClassicAssert.Inconclusive("State is not 'free'");
|
||||
}
|
||||
|
||||
Machine.MachineInfoExtended machineInfoExtended = await machine.Manage.GetMachineInfoExtended().ConfigureAwait(false);
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsNull(machineInfoExtended.CurrentUser.Just);
|
||||
}
|
||||
}
|
||||
}
|
139
FabAccessAPI_Test/API_TestEnv/Machine_Test_Stateless.cs
Normal file
139
FabAccessAPI_Test/API_TestEnv/Machine_Test_Stateless.cs
Normal file
@ -0,0 +1,139 @@
|
||||
using FabAccessAPI;
|
||||
using NUnit.Framework;
|
||||
using System.Threading.Tasks;
|
||||
using FabAccessAPI.Schema;
|
||||
using NUnit.Framework.Legacy;
|
||||
|
||||
namespace FabAccessAPI_Test.API_TestEnv
|
||||
{
|
||||
[TestFixture, Parallelizable(ParallelScope.Children)]
|
||||
[Order(2)]
|
||||
public class Machine_Test_Stateless
|
||||
{
|
||||
[TestCase("Admin1", "MachineA1", true)]
|
||||
[TestCase("Admin1", "MachineB1", true)]
|
||||
[TestCase("Admin1", "MachineC1", true)]
|
||||
[TestCase("ManagerA1", "MachineA1", true)]
|
||||
[TestCase("ManagerB1", "MachineB1", true)]
|
||||
[TestCase("ManagerC1", "MachineC1", true)]
|
||||
[TestCase("ManagerABC1", "MachineA1", true)]
|
||||
[TestCase("ManagerABC1", "MachineB1", true)]
|
||||
[TestCase("ManagerABC1", "MachineC1", true)]
|
||||
[TestCase("MakerA1", "MachineA1", true)]
|
||||
[TestCase("MakerB1", "MachineB1", true)]
|
||||
[TestCase("MakerC1", "MachineC1", true)]
|
||||
[TestCase("GuestA1", "MachineA1", true)]
|
||||
[TestCase("GuestB1", "MachineB1", true)]
|
||||
[TestCase("GuestC1", "MachineC1", true)]
|
||||
[TestCase("MakerQRA", "MachineA1", true)]
|
||||
[TestCase("MakerQRB", "MachineB1", true)]
|
||||
[TestCase("MakerQRC", "MachineC1", true)]
|
||||
[Order(1)]
|
||||
public async Task InfoInterface(string username, string machineID, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
bool result = !((Machine.InfoInterface_Proxy)machine.Info).IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "MachineA1", true)]
|
||||
[TestCase("Admin1", "MachineB1", true)]
|
||||
[TestCase("Admin1", "MachineC1", true)]
|
||||
[TestCase("ManagerA1", "MachineA1", true)]
|
||||
[TestCase("ManagerB1", "MachineB1", true)]
|
||||
[TestCase("ManagerC1", "MachineC1", true)]
|
||||
[TestCase("ManagerABC1", "MachineA1", true)]
|
||||
[TestCase("ManagerABC1", "MachineB1", true)]
|
||||
[TestCase("ManagerABC1", "MachineC1", true)]
|
||||
[TestCase("MakerA1", "MachineA1", false)]
|
||||
[TestCase("MakerB1", "MachineB1", false)]
|
||||
[TestCase("MakerC1", "MachineC1", false)]
|
||||
[TestCase("GuestA1", "MachineA1", false)]
|
||||
[TestCase("GuestB1", "MachineB1", false)]
|
||||
[TestCase("GuestC1", "MachineC1", false)]
|
||||
[TestCase("MakerQRA", "MachineA1", false)]
|
||||
[TestCase("MakerQRB", "MachineB1", false)]
|
||||
[TestCase("MakerQRC", "MachineC1", false)]
|
||||
[Order(2)]
|
||||
public async Task ManageInterface(string username, string machineID, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
bool result = !((Machine.ManageInterface_Proxy)machine.Manage).IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "MachineA1", true)]
|
||||
[TestCase("Admin1", "MachineB1", true)]
|
||||
[TestCase("Admin1", "MachineC1", true)]
|
||||
[TestCase("ManagerA1", "MachineA1", false)]
|
||||
[TestCase("ManagerB1", "MachineB1", false)]
|
||||
[TestCase("ManagerC1", "MachineC1", false)]
|
||||
[TestCase("ManagerABC1", "MachineA1", false)]
|
||||
[TestCase("ManagerABC1", "MachineB1", false)]
|
||||
[TestCase("ManagerABC1", "MachineC1", false)]
|
||||
[TestCase("MakerA1", "MachineA1", false)]
|
||||
[TestCase("MakerB1", "MachineB1", false)]
|
||||
[TestCase("MakerC1", "MachineC1", false)]
|
||||
[TestCase("GuestA1", "MachineA1", false)]
|
||||
[TestCase("GuestB1", "MachineB1", false)]
|
||||
[TestCase("GuestC1", "MachineC1", false)]
|
||||
[TestCase("MakerQRA", "MachineA1", false)]
|
||||
[TestCase("MakerQRB", "MachineB1", false)]
|
||||
[TestCase("MakerQRC", "MachineC1", false)]
|
||||
[Order(3), Ignore("Not Implemented")]
|
||||
public async Task AdminInterface(string username, string machineID, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
bool result = !((Machine.AdminInterface_Proxy)machine.Admin).IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "MachineA1", "Description of MachineA1", @"https://fab-access.readthedocs.io", "CategoryA")]
|
||||
[TestCase("Admin1", "MachineB2", "Description of MachineB2", @"https://fab-access.readthedocs.io", "CategoryB")]
|
||||
[TestCase("Admin1", "MachineC3", "Description of MachineC3", @"https://fab-access.readthedocs.io", "CategoryC")]
|
||||
[Order(4)]
|
||||
public async Task ReadMachineData(string username, string machineID, string description, string wiki, string category)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.Multiple(() =>
|
||||
{
|
||||
ClassicAssert.AreEqual(machineID, machine.Id);
|
||||
ClassicAssert.AreEqual(description, machine.Description);
|
||||
ClassicAssert.AreEqual(wiki, machine.Wiki);
|
||||
ClassicAssert.AreEqual(category, machine.Category);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
using FabAccessAPI;
|
||||
using FabAccessAPI.Schema;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI_Test.API_TestEnv
|
||||
{
|
||||
[TestFixture, Parallelizable(ParallelScope.Children)]
|
||||
[Order(1)]
|
||||
public class PermissionSystem_Test_Stateless
|
||||
{
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("MakerA1", true)]
|
||||
[TestCase("GuestA1", true)]
|
||||
[Order(1)]
|
||||
public async Task AccessPermissionSystem(string username, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
bool result = api.Session.PermissionSystem != null;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("MakerA1", true)]
|
||||
[TestCase("GuestA1", true)]
|
||||
[Order(2)]
|
||||
public async Task InfoInterface(string username, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
PermissionSystem.InfoInterface_Proxy infoInterface = (PermissionSystem.InfoInterface_Proxy)api.Session.PermissionSystem.Info;
|
||||
|
||||
bool result = !infoInterface.IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", 13)]
|
||||
[TestCase("ManagerA1", 13)]
|
||||
[TestCase("MakerA1", 13)]
|
||||
[TestCase("GuestA1", 13)]
|
||||
[Order(3), Ignore("Not implemented")]
|
||||
public async Task ListRoles(string username, int expectRolesCount)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
IReadOnlyList<Role> roles_list = await api.Session.PermissionSystem.Info.GetRoleList().ConfigureAwait(false);
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectRolesCount, roles_list.Count);
|
||||
}
|
||||
}
|
||||
}
|
143
FabAccessAPI_Test/API_TestEnv/UserSystem_Test.cs
Normal file
143
FabAccessAPI_Test/API_TestEnv/UserSystem_Test.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using Capnp.Rpc;
|
||||
using FabAccessAPI;
|
||||
using FabAccessAPI.Schema;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI_Test.API_TestEnv
|
||||
{
|
||||
[TestFixture]
|
||||
public class UserSystem_Test
|
||||
{
|
||||
#region SetUp
|
||||
[SetUp]
|
||||
public async Task SetUp()
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData("Admin1");
|
||||
await api.Connect(connectionData);
|
||||
|
||||
IReadOnlyList<User> user_list = await api.Session.UserSystem.Manage.GetUserList().ConfigureAwait(false);
|
||||
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (User u in user_list)
|
||||
{
|
||||
if(u.Username.StartsWith("New"))
|
||||
{
|
||||
tasks.Add(api.Session.UserSystem.Manage.RemoveUser(u));
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
#endregion
|
||||
|
||||
[TestCase("Admin1", "NewUserA1")]
|
||||
[Order(1)]
|
||||
public async Task AddUser_DEPRECATED(string username, string username2)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
bool methodNotImplemented = false;
|
||||
|
||||
try
|
||||
{
|
||||
User user = (await api.Session.UserSystem.Manage.AddUser(username2, TestEnv.PASSWORD).ConfigureAwait(false));
|
||||
}
|
||||
catch (RpcException exception) when (string.Equals(exception.Message, "method not implemented", StringComparison.Ordinal))
|
||||
{
|
||||
methodNotImplemented = true;
|
||||
}
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsTrue(methodNotImplemented);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "NewUserA1")]
|
||||
[TestCase("Admin1", "NewUserB1")]
|
||||
[TestCase("Admin1", "NewUserC1")]
|
||||
[Order(1)]
|
||||
public async Task AddUser(string username, string username2)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = (await api.Session.UserSystem.Manage.AddUserFallible(username2, TestEnv.PASSWORD).ConfigureAwait(false)).Successful;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsNotNull(user);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "Admin1")]
|
||||
[TestCase("Admin1", "ManagerA1")]
|
||||
[TestCase("Admin1", "MakerA1")]
|
||||
[TestCase("Admin1", "GuestA1")]
|
||||
[Order(2)]
|
||||
public async Task AddUser_AllreadyExists(string username, string username2)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
UserSystem.ManageInterface.AddUserError.AddUserErrorEnum error = (await api.Session.UserSystem.Manage.AddUserFallible(username2, TestEnv.PASSWORD).ConfigureAwait(false)).Failed.Error;
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(UserSystem.ManageInterface.AddUserError.AddUserErrorEnum.alreadyExists, error);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "")]
|
||||
[Order(2)]
|
||||
public async Task AddUser_InvalidUsername(string username, string username2)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
UserSystem.ManageInterface.AddUserError.AddUserErrorEnum error = (await api.Session.UserSystem.Manage.AddUserFallible(username2, TestEnv.PASSWORD).ConfigureAwait(false)).Failed.Error;
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(UserSystem.ManageInterface.AddUserError.AddUserErrorEnum.usernameInvalid, error);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "NewUserC1", "")]
|
||||
[Order(2)]
|
||||
public async Task AddUser_InvalidPassword(string username, string username2, string password)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
UserSystem.ManageInterface.AddUserError.AddUserErrorEnum error = (await api.Session.UserSystem.Manage.AddUserFallible(username2, password).ConfigureAwait(false)).Failed.Error;
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(UserSystem.ManageInterface.AddUserError.AddUserErrorEnum.passwordInvalid, error);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "NewUserA1")]
|
||||
[TestCase("Admin1", "NewUserB1")]
|
||||
[TestCase("Admin1", "NewUserC1")]
|
||||
[Order(3)]
|
||||
public async Task AddRemoveUser(string username, string username2)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = (await api.Session.UserSystem.Manage.AddUserFallible(username2, TestEnv.PASSWORD).ConfigureAwait(false)).Successful;
|
||||
|
||||
await api.Session.UserSystem.Manage.RemoveUser(user);
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsNotNull(user);
|
||||
}
|
||||
}
|
||||
}
|
123
FabAccessAPI_Test/API_TestEnv/UserSystem_Test_Stateless.cs
Normal file
123
FabAccessAPI_Test/API_TestEnv/UserSystem_Test_Stateless.cs
Normal file
@ -0,0 +1,123 @@
|
||||
using FabAccessAPI;
|
||||
using FabAccessAPI.Schema;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI_Test.API_TestEnv
|
||||
{
|
||||
[TestFixture, Parallelizable(ParallelScope.Children)]
|
||||
[Order(1)]
|
||||
public class UserSystem_Test_Stateless
|
||||
{
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("MakerA1", true)]
|
||||
[TestCase("GuestA1", true)]
|
||||
[Order(2)]
|
||||
public async Task InfoInterface(string username, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
UserSystem.InfoInterface_Proxy infoInterface = (UserSystem.InfoInterface_Proxy)api.Session.UserSystem.Info;
|
||||
|
||||
bool result = !infoInterface.IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("MakerA1", false)]
|
||||
[TestCase("GuestA1", false)]
|
||||
[Order(3)]
|
||||
public async Task ManageInterface(string username, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
UserSystem.ManageInterface_Proxy manageInterface = (UserSystem.ManageInterface_Proxy)api.Session.UserSystem.Manage;
|
||||
|
||||
bool result = !manageInterface.IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("MakerA1", false)]
|
||||
[TestCase("GuestA1", false)]
|
||||
[Order(3)]
|
||||
public async Task SearchInterface(string username, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
UserSystem.SearchInterface_Proxy searchInterface = (UserSystem.SearchInterface_Proxy)api.Session.UserSystem.Search;
|
||||
|
||||
bool result = !searchInterface.IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1")]
|
||||
[TestCase("ManagerA1")]
|
||||
[TestCase("MakerA1")]
|
||||
[TestCase("GuestA1")]
|
||||
[Order(4)]
|
||||
public async Task GetUserSelf(string username)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsNotNull(user);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "Admin1")]
|
||||
[TestCase("Admin1", "MakerA1")]
|
||||
[TestCase("Admin1", "GuestA1")]
|
||||
[Order(4)]
|
||||
public async Task GetUserByUsername(string username, string username2)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = (await api.Session.UserSystem.Search.GetUserByName(username2).ConfigureAwait(false)).Just;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsNotNull(user);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "UnknownUser")]
|
||||
[Order(5)]
|
||||
public async Task GetUserByUsername_NotExist(string username, string username2)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = (await api.Session.UserSystem.Search.GetUserByName(username2).ConfigureAwait(false)).Just;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.IsNull(user);
|
||||
}
|
||||
}
|
||||
}
|
69
FabAccessAPI_Test/API_TestEnv/User_Test.cs
Normal file
69
FabAccessAPI_Test/API_TestEnv/User_Test.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using FabAccessAPI;
|
||||
using FabAccessAPI.Schema;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI_Test.API_TestEnv
|
||||
{
|
||||
[TestFixture]
|
||||
public class User_Test
|
||||
{
|
||||
#region SetUp
|
||||
[SetUp]
|
||||
public async Task SetUp()
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData("Admin1");
|
||||
await api.Connect(connectionData);
|
||||
|
||||
IReadOnlyList<User> user_list = await api.Session.UserSystem.Manage.GetUserList().ConfigureAwait(false);
|
||||
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (User u in user_list)
|
||||
{
|
||||
if (u.Username.StartsWith("New"))
|
||||
{
|
||||
tasks.Add(api.Session.UserSystem.Manage.RemoveUser(u));
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
#endregion
|
||||
|
||||
[TestCase("Admin1", "NewMakerA1", "UseA", "ReadA", "DiscloseA")]
|
||||
[Order(1)]
|
||||
[Ignore("Deprecated")]
|
||||
public async Task AddRoles(string username, string username2, params string[] roles)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
await api.Session.UserSystem.Manage.AddUser(username2, TestEnv.PASSWORD);
|
||||
|
||||
User user = (await api.Session.UserSystem.Search.GetUserByName(username2).ConfigureAwait(false)).Just;
|
||||
|
||||
foreach(string s in roles)
|
||||
{
|
||||
await user.Admin.AddRole(new Role() { Name = s }).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
user = (await api.Session.UserSystem.Search.GetUserByName(username2).ConfigureAwait(false)).Just;
|
||||
List<Role> user_roles = new List<Role>(await user.Info.ListRoles().ConfigureAwait(false));
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.Multiple(() =>
|
||||
{
|
||||
ClassicAssert.AreEqual(3, user_roles.Count);
|
||||
foreach (string s in roles)
|
||||
{
|
||||
ClassicAssert.IsTrue(user_roles.Exists(x => x.Name == s));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
127
FabAccessAPI_Test/API_TestEnv/User_Test_Stateless.cs
Normal file
127
FabAccessAPI_Test/API_TestEnv/User_Test_Stateless.cs
Normal file
@ -0,0 +1,127 @@
|
||||
using FabAccessAPI;
|
||||
using FabAccessAPI.Schema;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI_Test.API_TestEnv
|
||||
{
|
||||
[TestFixture, Parallelizable(ParallelScope.Children)]
|
||||
[Order(2)]
|
||||
public class User_Test_Stateless
|
||||
{
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("MakerA1", true)]
|
||||
[TestCase("GuestA1", true)]
|
||||
[Order(1)]
|
||||
public async Task InfoInterface(string username, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);
|
||||
|
||||
bool result = !((User.InfoInterface_Proxy)user.Info).IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("MakerA1", true)]
|
||||
[TestCase("GuestA1", true)]
|
||||
[Order(2)]
|
||||
public async Task ManageInterface(string username, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);
|
||||
|
||||
bool result = !((User.ManageInterface_Proxy)user.Manage).IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1", true)]
|
||||
[TestCase("ManagerA1", true)]
|
||||
[TestCase("MakerA1", false)]
|
||||
[TestCase("GuestA1", false)]
|
||||
[Order(3)]
|
||||
public async Task AdminInterface(string username, bool expectInterface)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);
|
||||
|
||||
bool result = !((User.AdminInterface_Proxy)user.Admin).IsNull;
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.AreEqual(expectInterface, result);
|
||||
}
|
||||
|
||||
[TestCase("Admin1")]
|
||||
[TestCase("ManagerA1")]
|
||||
[TestCase("MakerA1")]
|
||||
[TestCase("GuestA1")]
|
||||
[Order(4)]
|
||||
public async Task ReadUserData(string username)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
ClassicAssert.Multiple(() =>
|
||||
{
|
||||
ClassicAssert.AreEqual(username, user.Username);
|
||||
});
|
||||
}
|
||||
|
||||
[TestCase("Admin1", "Admin", "ManageUsers")]
|
||||
[TestCase("ManagerA1", "ManageA", "UseA", "ReadA", "DiscloseA", "ManageUsers")]
|
||||
[TestCase("MakerA1", "UseA", "ReadA", "DiscloseA")]
|
||||
[TestCase("GuestA1", "ReadA", "DiscloseA")]
|
||||
[Order(5)]
|
||||
public async Task ListUserRoles(string username, params string[] expect_roles)
|
||||
{
|
||||
API api = new API();
|
||||
ConnectionData connectionData = TestEnv.CreateConnetionData(username);
|
||||
await api.Connect(connectionData);
|
||||
|
||||
User user = await api.Session.UserSystem.Info.GetUserSelf().ConfigureAwait(false);
|
||||
|
||||
List<Role> roles_user = new List<Role>(await user.Info.ListRoles().ConfigureAwait(false));
|
||||
List<string> expect_roles_list = new List<string>(expect_roles);
|
||||
|
||||
await api.Disconnect();
|
||||
|
||||
if (roles_user.Count != expect_roles_list.Count)
|
||||
{
|
||||
ClassicAssert.Fail("Roles Count is different");
|
||||
}
|
||||
|
||||
foreach (Role role_user in roles_user)
|
||||
{
|
||||
if (!expect_roles_list.Exists(x => x == role_user.Name))
|
||||
{
|
||||
ClassicAssert.Fail("Roles are different");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
FabAccessAPI_Test/FabAccessAPI_Test.csproj
Normal file
17
FabAccessAPI_Test/FabAccessAPI_Test.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FabAccessAPI\FabAccessAPI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
33
FabAccessAPI_Test/TestEnv.cs
Normal file
33
FabAccessAPI_Test/TestEnv.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using FabAccessAPI;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FabAccessAPI_Test
|
||||
{
|
||||
public static class TestEnv
|
||||
{
|
||||
public const string SCHEMA = "fabaccess";
|
||||
public const string TESTSERVER = "127.0.0.1";//"test.fab-access.org";
|
||||
public const int TESTSERVER_PORT = 59661;
|
||||
public const string PASSWORD = "secret";
|
||||
|
||||
[TestCase("Testuser")]
|
||||
public static ConnectionData CreateConnetionData(string username)
|
||||
{
|
||||
ConnectionData connectionData = new ConnectionData()
|
||||
{
|
||||
Host = new UriBuilder(TestEnv.SCHEMA, TestEnv.TESTSERVER, TestEnv.TESTSERVER_PORT).Uri,
|
||||
Mechanism = SASLMechanismEnum.PLAIN,
|
||||
Username = username,
|
||||
Properties = new Dictionary<string, object>()
|
||||
{
|
||||
{ "Username", username },
|
||||
{ "Password", TestEnv.PASSWORD },
|
||||
},
|
||||
};
|
||||
|
||||
return connectionData;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user