Added: API v4.0

This commit is contained in:
TheJoKlLa 2024-03-11 22:38:56 +01:00
parent 6c60dc5dcf
commit dbf19566db
29 changed files with 2379 additions and 0 deletions

54
API.sln Normal file
View 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
View 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
}
}

View 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;
}
}
}

View 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
}
}

View 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)
{
}
}
}

View 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)
{
}
}
}

View 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)
{
}
}
}

View 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)
{
}
}
}

View File

@ -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
}
}

View 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)
{
}
}
}

View 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)
{
}
}
}

View 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)
{
}
}
}

View 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)
{
}
}
}

View 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
View 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
}
}

View 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.");
}
}
}
}

View 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;
}
}

View 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");
});
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View 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);
});
}
}
}

View File

@ -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);
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View 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));
}
});
}
}
}

View 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");
}
}
}
}
}

View 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>

View 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;
}
}
}

4
README.md Normal file
View File

@ -0,0 +1,4 @@
FabAccess API
===
FabAccess API in C# with Tests