test ALL the things, all green lights now

This commit is contained in:
Michael Becker 2024-12-17 00:49:22 -05:00
parent 601caf1651
commit 3a3e681a90
18 changed files with 645 additions and 219 deletions

View File

@ -54,6 +54,16 @@ public class Program : WebApplication
protected override void OnStartup(EventArgs e)
{
string pidfile = "/var/run/mocha/mocha-oms.pid";
try
{
System.IO.File.WriteAllText(pidfile, System.Environment.ProcessId.ToString());
}
catch (Exception ex)
{
Console.Error.WriteLine("oms: error: failed to write PID file; graceful control will be unavailable");
}
// this all has to be done before the Web server is started...
oms.Initialize();
@ -93,6 +103,9 @@ public class Program : WebApplication
if (e.SystemRoutine.GlobalIdentifier == KnownInstanceGuids.SystemUpdateRoutines.LoginUser)
{
string token = e.Context.GetWorkData<string>(e.OMS.GetInstance(KnownAttributeGuids.Text.Token));
if (token == null)
return;
_Sessions[token] = new OmsSession();
}
}

View File

@ -36,7 +36,7 @@ public class ElementCommand : InstanceCommand
{
// what we should do, is build a transaction with all updated ECs and fields and values
// if any update fails, the entire transaction should be rolled back
Response resp = ProcessElement(oms, ctx, ProcessingInstance, InstanceHandle.Empty, e.Context.Request.Form);
Response resp = oms.ProcessElement(ctx, ProcessingInstance, e.Context.Request.Form);
if (resp != null)
{
JsonObject obj2 = resp.GetResponse(oms, ctx);
@ -85,7 +85,7 @@ public class ElementCommand : InstanceCommand
InstanceHandle elem = oms.GetRelatedInstance(ProcessingInstance, oms.GetInstance(KnownRelationshipGuids.Task__has_initiating__Element));
// fill out the initiating element and execute the task
Response r = oms.ProcessElement(ctx, elem, InstanceHandle.Empty);
Response r = oms.ProcessElement(ctx, elem, null);
JsonObject obj = r.GetResponse(oms, ctx);
/*
@ -105,7 +105,7 @@ public class ElementCommand : InstanceCommand
InstanceHandle elem = oms.GetRelatedInstance(defaultTask, oms.GetInstance(KnownRelationshipGuids.Task__has_initiating__Element));
// fill out the initiating element and execute the task
Response r = oms.ProcessElement(ctx, elem, ProcessingInstance);
Response r = oms.ProcessElement(ctx, elem, null);
JsonObject obj = r.GetResponse(oms, ctx);
/*
@ -117,105 +117,4 @@ public class ElementCommand : InstanceCommand
}
}
}
private Response ProcessElement(Core.Oms oms, OmsContext ctx, InstanceHandle element, InstanceHandle elementContent, ReadOnlyDictionary<string, string> form, string fqecidPrefix = "")
{
// first we process the related updates
InstanceHandle processedByPru = oms.GetRelatedInstance(element, oms.GetInstance(KnownRelationshipGuids.Element__processed_by__Process_Related_Updates_Method));
if (processedByPru != InstanceHandle.Empty)
{
// this works... so far
oms.UpdateElementContents(ctx, element, form);
oms.Execute(ctx, processedByPru);
/*
$executesMethod = $oms->getRelatedInstance($usesBRMB, KnownRelationshipGuids::Method_Binding__executes__Method);
if ($executesMethod === null)
{
trigger_error("task_step: 1; uses BRMB " . $usesBRMB . "; executes method is null");
}
$usesElement = $oms->getRelatedInstance($executesMethod, KnownRelationshipGuids::Build_UI_Response_Method__uses__Executable_returning_Element);
$this->updateWorkDataWithElementContents($parentElementContents, $element);
$usesElementContents = $oms->getRelatedInstances($usesElement, KnownRelationshipGuids::Element__has__Element_Content);
if (count($usesElementContents) > 0)
{
$ecInst0 = $oms->getRelatedInstance($usesElementContents[0], KnownRelationshipGuids::Element_Content__has__Instance);
$this->TargetInstance = $this->Context->getWorkData($ecInst0);
$this->renderTaskStep2($parentElementContents, $usesElement);
}
exit();
*/
}
// ... then we process the element contents...
IEnumerable<InstanceHandle> elementContents = oms.GetRelatedInstances(element, oms.GetInstance(KnownRelationshipGuids.Element__has__Element_Content));
foreach (InstanceHandle elementContent2 in elementContents)
{
Response? resp = ProcessElementContent(oms, ctx, elementContent2, form, fqecidPrefix);
if (resp != null)
{
return resp;
}
}
// ... finally we run the CT - Control Transaction Method to return the response
InstanceHandle processedByCt = oms.GetRelatedInstance(element, oms.GetInstance(KnownRelationshipGuids.Element__processed_by__Control_Transaction_Method));
if (processedByCt != InstanceHandle.Empty)
{
string destinationURL = oms.GetAttributeValue<string>(processedByCt, oms.GetInstance(KnownAttributeGuids.Text.TargetURL));
InstanceHandle usesBuildResponseMethodBinding = oms.GetRelatedInstance(processedByCt, oms.GetInstance(KnownRelationshipGuids.Control_Transaction_Method__uses__Build_Response_Method_Binding));
if (usesBuildResponseMethodBinding != InstanceHandle.Empty)
{
}
else if (destinationURL != null)
{
return new RedirectResponse(destinationURL);
}
/*
$executesMethod = $oms->getRelatedInstance($usesBRMB, KnownRelationshipGuids::Method_Binding__executes__Method);
if ($executesMethod === null)
{
trigger_error("task_step: 1; uses BRMB " . $usesBRMB . "; executes method is null");
}
$usesElement = $oms->getRelatedInstance($executesMethod, KnownRelationshipGuids::Build_UI_Response_Method__uses__Executable_returning_Element);
$this->updateWorkDataWithElementContents($parentElementContents, $element);
$usesElementContents = $oms->getRelatedInstances($usesElement, KnownRelationshipGuids::Element__has__Element_Content);
if (count($usesElementContents) > 0)
{
$ecInst0 = $oms->getRelatedInstance($usesElementContents[0], KnownRelationshipGuids::Element_Content__has__Instance);
$this->TargetInstance = $this->Context->getWorkData($ecInst0);
$this->renderTaskStep2($parentElementContents, $usesElement);
}
exit();
*/
return FailureResponse.NotImplemented;
}
return FailureResponse.UnexpectedFailure;
}
private Response? ProcessElementContent(Core.Oms oms, OmsContext context, InstanceHandle elementContent, ReadOnlyDictionary<string, string> form, string fqecidPrefix)
{
InstanceHandle elementContentInstance = oms.GetRelatedInstance(elementContent, oms.GetInstance(KnownRelationshipGuids.Element_Content__has__Instance));
if (oms.IsInstanceOf(elementContentInstance, oms.GetInstance(KnownInstanceGuids.Classes.Element)))
{
return ProcessElement(oms, context, elementContentInstance, elementContent, form, fqecidPrefix + oms.GetInstanceKey(elementContentInstance).ToString() + ":");
}
else if (oms.IsInstanceOf(elementContentInstance, oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute)))
{
string key = fqecidPrefix + oms.GetInstanceKey(elementContent);
string text = oms.GetInstanceText(elementContentInstance);
if (form.ContainsKey(key))
{
string value = form[key];
}
}
return null;
}
}

View File

@ -61,7 +61,7 @@ public abstract class InstanceCommand : TenantedCommand
if (context.Session.ContainsKey("OmsContext"))
{
OmsContext ctx = (OmsContext)context.Session["OmsContext"];
object? loginToken = ctx.GetWorkData(oms.GetInstance(KnownAttributeGuids.Text.Token));
string? loginToken = ctx.GetGlobal<string?>(oms.GetInstance(KnownAttributeGuids.Text.Token));
if (loginToken != null)
{
obj.Add("sessionSecureToken", loginToken.ToString());

View File

@ -218,6 +218,7 @@ public class OmsServer
// obj.Add("message", String.Format("unknown cmd '{0}'", command));
RespondWithJson(oms, sw, e.Context, 404, "Not Found", obj);
}
e.Handled = true;
}
public void RespondWithJson(Oms oms, StreamWriter sw, WebContext context, int responseCode, string responseText, JsonObject obj)
{
@ -228,7 +229,7 @@ public class OmsServer
if (context.Session.ContainsKey("OmsContext"))
{
OmsContext ctx = (OmsContext)context.Session["OmsContext"];
object? loginToken = ctx.GetWorkData(oms.GetInstance(KnownAttributeGuids.Text.Token));
string? loginToken = ctx.GetGlobal<string?>(oms.GetInstance(KnownAttributeGuids.Text.Token));
if (loginToken != null)
{
obj.Add("sessionSecureToken", loginToken.ToString());

View File

@ -481,5 +481,12 @@ namespace Mocha.Core
public static Guid Far { get; } = new Guid("{f19d16c7-99ff-48a3-b86a-7db8f400d869}");
public static Guid Center { get; } = new Guid("{63179b92-9a6a-495b-a823-f45e353be9d8}");
}
public static class Modules
{
public static Guid MochaBaseSystem { get; } = new Guid("{3ffd3a31-208c-49c9-905d-2a69362902ca}");
public static Guid OOP { get; } = new Guid("{818dfe8d-96ea-4339-8d18-a0e9a5f50908}");
public static Guid OOPMethodExamples { get; } = new Guid("{5017c102-c154-4ef0-b117-e42bd1c756c1}");
}
}
}

View File

@ -34,32 +34,8 @@ public class ConditionalSelectAttributeMethodImplementation : MethodImplementati
IEnumerable<InstanceHandle> trueConditions = oms.GetRelatedInstances(cas, oms.GetInstance(KnownRelationshipGuids.Condition_Group__has_true_condition__Executable_returning_Work_Data));
IEnumerable<InstanceHandle> falseConditions = oms.GetRelatedInstances(cas, oms.GetInstance(KnownRelationshipGuids.Condition_Group__has_false_condition__Executable_returning_Work_Data));
bool useAnyCondition = oms.GetAttributeValue<bool>(cas, oms.GetInstance(KnownAttributeGuids.Boolean.UseAnyCondition));
if (trueConditions != null)
{
foreach (InstanceHandle trueCondition in trueConditions)
{
InstanceHandle ret = oms.Execute(context, trueCondition);
object? retval = context.GetWorkData(ret);
if (retval is bool && ((bool)retval))
{
value = true;
break;
}
}
}
if (falseConditions != null)
{
foreach (InstanceHandle falseCondition in falseConditions)
{
InstanceHandle ret = oms.Execute(context, falseCondition);
object? retval = context.GetWorkData(ret);
if (retval is bool && (!(bool)retval))
{
value = true;
break;
}
}
}
value = oms.EvaluateConditions(context, trueConditions, falseConditions, useAnyCondition);
if (value)
{

View File

@ -45,80 +45,120 @@ public class EvaluateBooleanExpressionMethodImplementation : MethodImplementatio
InstanceHandle source = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Evaluate_Boolean_Expression_Method__has_source__Executable_returning_Work_Data));
InstanceHandle comparison = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Evaluate_Boolean_Expression_Method__uses__Boolean_Operator));
InstanceHandle target = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Evaluate_Boolean_Expression_Method__has_target__Executable_returning_Work_Data));
InstanceHandle[] rtarget_value = new InstanceHandle[0];
Console.Error.WriteLine("EBE - source {0}", oms.GetGlobalIdentifier(source));
InstanceHandle rsource = oms.Execute(context, source);
object? rsource_valueraw = context.GetWorkData(rsource);
InstanceHandle[] rsource_value = new InstanceHandle[0];
if (rsource_valueraw is InstanceHandle[])
{
rsource_value = (InstanceHandle[])rsource_valueraw;
}
else if (rsource_valueraw is InstanceHandle)
{
rsource_value = new InstanceHandle[] { (InstanceHandle)rsource_valueraw };
}
if (oms.IsInstanceOf(target, oms.GetInstance(KnownInstanceGuids.Classes.Attribute)))
{
rtarget_value = new InstanceHandle[] { target };
}
else if (oms.IsInstanceOf(target, oms.GetInstance(KnownInstanceGuids.Classes.Executable)))
{
InstanceHandle rtarget = oms.Execute(context, target);
object? rtarget_valueraw = context.GetWorkData(rtarget);
}
else
{
rtarget_value = new InstanceHandle[] { target };
}
bool value = false;
if (comparison == oms.GetInstance(KnownInstanceGuids.RelationalOperators.InSelectionList))
if (comparison == oms.GetInstance(KnownInstanceGuids.RelationalOperators.IsNotEmpty))
{
if (rtarget_value.ContainsAny(rsource_value))
if (rsource_valueraw is InstanceHandle)
{
value = true;
Console.Error.WriteLine("EBE - is not empty - {0} ?", oms.GetGlobalIdentifier((InstanceHandle)rsource_valueraw));
value = ((InstanceHandle)rsource_valueraw) != InstanceHandle.Empty;
}
}
else if (comparison == oms.GetInstance(KnownInstanceGuids.RelationalOperators.ExactMatchWithSelectionList))
{
if (rtarget_value.Length == rsource_value.Length)
else if (rsource_valueraw is IEnumerable<InstanceHandle>)
{
List<InstanceHandle> l1 = new List<InstanceHandle>(rsource_value);
List<InstanceHandle> l2 = new List<InstanceHandle>(rtarget_value);
l1.Sort();
l2.Sort();
value = true;
for (int i = 0; i < l1.Count; i++)
{
if (!l1[i].Equals(l2[i]))
{
value = false;
break;
}
}
Console.Error.WriteLine("EBE - is not empty - count = {0} ?", ((IEnumerable<InstanceHandle>)rsource_valueraw).Count());
value = ((IEnumerable<InstanceHandle>)rsource_valueraw).Any();
}
else
{
value = false;
Console.Error.WriteLine("EBE - is not empty - {0} ?", rsource_valueraw);
value = rsource_valueraw != null;
}
}
else if (comparison == oms.GetInstance(KnownInstanceGuids.LogicalOperators.EqualTo))
else if (comparison == oms.GetInstance(KnownInstanceGuids.RelationalOperators.IsEmpty))
{
// ! FIXME ! Implement This !
value = false;
if (rsource_valueraw is InstanceHandle)
{
value = ((InstanceHandle)rsource_valueraw) == InstanceHandle.Empty;
}
else if (rsource_valueraw is IEnumerable<InstanceHandle>)
{
value = !((IEnumerable<InstanceHandle>)rsource_valueraw).Any();
}
else
{
value = rsource_valueraw == null;
}
}
else
{
throw new NotImplementedException(String.Format("relational operator '{0}' not implemented @@ {1}, {2}", comparison, oms.GetGlobalIdentifier(method).ToString("B"), context.StackTrace.ToString()));
InstanceHandle target = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Evaluate_Boolean_Expression_Method__has_target__Executable_returning_Work_Data));
InstanceHandle[] rtarget_value = new InstanceHandle[0];
InstanceHandle[] rsource_value = new InstanceHandle[0];
if (rsource_valueraw is InstanceHandle[])
{
rsource_value = (InstanceHandle[])rsource_valueraw;
}
else if (rsource_valueraw is InstanceHandle)
{
rsource_value = new InstanceHandle[] { (InstanceHandle)rsource_valueraw };
}
if (oms.IsInstanceOf(target, oms.GetInstance(KnownInstanceGuids.Classes.Attribute)))
{
rtarget_value = new InstanceHandle[] { target };
}
else if (oms.IsInstanceOf(target, oms.GetInstance(KnownInstanceGuids.Classes.Executable)))
{
InstanceHandle rtarget = oms.Execute(context, target);
object? rtarget_valueraw = context.GetWorkData(rtarget);
}
else
{
rtarget_value = new InstanceHandle[] { target };
}
if (comparison == oms.GetInstance(KnownInstanceGuids.RelationalOperators.InSelectionList))
{
if (rtarget_value.ContainsAny(rsource_value))
{
value = true;
}
}
else if (comparison == oms.GetInstance(KnownInstanceGuids.RelationalOperators.ExactMatchWithSelectionList))
{
if (rtarget_value.Length == rsource_value.Length)
{
List<InstanceHandle> l1 = new List<InstanceHandle>(rsource_value);
List<InstanceHandle> l2 = new List<InstanceHandle>(rtarget_value);
l1.Sort();
l2.Sort();
value = true;
for (int i = 0; i < l1.Count; i++)
{
if (!l1[i].Equals(l2[i]))
{
value = false;
break;
}
}
}
else
{
value = false;
}
}
else if (comparison == oms.GetInstance(KnownInstanceGuids.LogicalOperators.EqualTo))
{
// ! FIXME ! Implement This !
value = false;
}
else
{
throw new NotImplementedException(String.Format("relational operator '{0}' not implemented @@ {1}, {2}", comparison, oms.GetGlobalIdentifier(method).ToString("B"), context.StackTrace.ToString()));
}
}
context.SetWorkData(returnsAttribute, value);
return returnsAttribute;
}

View File

@ -40,9 +40,16 @@ public class GetAttributeMethodImplementation : MethodImplementation
{
forInstance = (InstanceHandle?) context.GetWorkData(forInstance.Value);
}
object? value = oms.UnsafeGetAttributeValue((InstanceHandle) forInstance, returnsAttribute);
context.SetWorkData(returnsAttribute, value);
if (forInstance is InstanceHandle forInstanceHandle)
{
object? value = oms.UnsafeGetAttributeValue((InstanceHandle)forInstanceHandle, returnsAttribute);
context.SetWorkData(returnsAttribute, value);
}
else
{
Console.Error.WriteLine("no for instance IS");
}
return returnsAttribute;
}
}

View File

@ -0,0 +1,38 @@
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
//
// This file is part of Mocha.NET.
//
// Mocha.NET is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Mocha.NET is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Mocha.NET. If not, see <https://www.gnu.org/licenses/>.
namespace Mocha.Core.MethodImplementations;
public class GetInstanceSetBySystemRoutineMethodImplementation : MethodImplementation
{
public override Guid MethodClassGuid => KnownInstanceGuids.MethodClasses.GetInstanceSetBySystemRoutineMethod;
protected override InstanceHandle ExecuteInternal(Oms oms, OmsContext context, InstanceHandle method)
{
InstanceHandle irForClass = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Method__for__Class));
InstanceHandle returnsWorkSet = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Get_Instance_Set_by_System_Routine_Method__returns__Work_Set));
InstanceHandle usesSystemInstanceSetRoutine = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Get_Instance_Set_by_System_Routine_Method__uses__System_Instance_Set_Routine));
if (returnsWorkSet == InstanceHandle.Empty)
{
throw new InvalidOperationException("no return Attribute specified for method");
}
object? value = oms.ExecuteSystemRoutine(context, usesSystemInstanceSetRoutine);
context.SetWorkData(returnsWorkSet, value);
return returnsWorkSet;
}
}

View File

@ -25,9 +25,12 @@ public class ProcessRelatedUpdatesMethodImplementation : MethodImplementation
InstanceHandle forClass = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Method__for__Class));
IEnumerable<InstanceHandle> usesExecutableForPUMB = oms.GetRelatedInstances(method, oms.GetInstance(KnownRelationshipGuids.Process_Related_Updates_Method__uses__Executable_for_PUMB));
Console.Error.WriteLine("---> has {0} PUMBs", usesExecutableForPUMB.Count());
foreach (InstanceHandle pumb in usesExecutableForPUMB)
{
oms.Execute(context, pumb);
Console.Error.WriteLine("---> executing PUMB {0}", pumb.GlobalIdentifier);
oms.Execute(context, pumb) ;
}
return InstanceHandle.Empty;
}

View File

@ -21,6 +21,7 @@ using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Net;
using System.Numerics;
@ -72,6 +73,37 @@ public abstract class Oms
UpdateSyntacticSugar();
RegisterSystemInstanceSetRoutine(KnownInstanceGuids.SystemInstanceSetRoutines.GetCurrentUser, delegate (Oms oms, OmsContext context)
{
Console.Error.WriteLine("oms: executing system instance set routine {0}", KnownInstanceGuids.SystemUpdateRoutines.LoginUser);
InstanceHandle a_Token = oms.GetInstance(KnownAttributeGuids.Text.Token);
string token = context.GetGlobal<string>(a_Token);
if (token != null)
{
IEnumerable<InstanceHandle> userLogins = oms.GetInstancesOf(oms.GetInstance(KnownInstanceGuids.Classes.UserLogin));
InstanceHandle r_User_Login__has__User = oms.GetInstance(KnownRelationshipGuids.User_Login__has__User);
foreach (InstanceHandle userLogin in userLogins)
{
string compareToken = oms.GetAttributeValue<string>(userLogin, a_Token);
Console.Error.WriteLine("oms: token {0} == {1} ???", token, compareToken);
if (compareToken.Equals(token))
{
InstanceHandle user = oms.GetRelatedInstance(userLogin, r_User_Login__has__User);
Console.Error.WriteLine("yes, returning {0}", user.GlobalIdentifier);
return new InstanceHandle[] { user };
}
}
}
else
{
Console.Error.WriteLine("oms: error: login token not set");
}
return new InstanceHandle[0];
});
RegisterSystemAttributeRoutine(KnownInstanceGuids.SystemAttributeRoutines.GetInstanceText, delegate (Oms oms, OmsContext context)
{
object? val = context.GetWorkData(oms.GetInstance(KnownInstanceGuids.Classes.Instance));
@ -103,6 +135,8 @@ public abstract class Oms
});
RegisterSystemUpdateRoutine(KnownInstanceGuids.SystemUpdateRoutines.LoginUser, delegate (Oms oms, OmsContext context)
{
Console.Error.WriteLine("oms: executing system update routine {0}", KnownInstanceGuids.SystemUpdateRoutines.LoginUser);
// FIXME: these are ECs for now, they should probably be Text Attributes (or parms?) passed into the US method
Guid userNameGuid = new Guid("{c67f305e-bd4d-4628-816b-55fb85ea1b67}");
Guid passwordGuid = new Guid("{51b51be3-44fd-48f1-971f-682aee0a6132}");
@ -120,10 +154,14 @@ public abstract class Oms
foreach (InstanceHandle user in users)
{
Console.Error.WriteLine("looking at user {0}", user.GlobalIdentifier);
string expectedUserName = oms.GetAttributeValue<string>(user, oms.GetInstance(KnownAttributeGuids.Text.UserName));
if (expectedUserName == null)
continue;
Console.Error.WriteLine("... expected user name '{0}', actual user name '{1}'", expectedUserName, userName);
if (expectedUserName != userName)
continue;
@ -137,6 +175,8 @@ public abstract class Oms
byte[] hash = hashAlgorithm.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password + passwordSalt));
string actualPasswordHash = Convert.ToHexString(hash).ToLowerInvariant();
Console.Error.WriteLine("... expected password hash '{0}'\n... actual password hash '{1}'", expectedPasswordHash, actualPasswordHash);
if (actualPasswordHash.Equals(expectedPasswordHash))
{
actualSystemUser = user;
@ -147,8 +187,12 @@ public abstract class Oms
if (sessionSecureToken != null)
{
Console.Error.WriteLine("!! success !! set secure token {0}", sessionSecureToken);
Console.Error.WriteLine("!! success !! current system user is {0}", actualSystemUser.GlobalIdentifier);
context.SetWorkData(oms.GetInstance(KnownInstanceGuids.Classes.User), actualSystemUser);
context.SetWorkData(oms.GetInstance(KnownAttributeGuids.Text.Token), sessionSecureToken);
context.SetGlobal(oms.GetInstance(KnownAttributeGuids.Text.Token), sessionSecureToken);
// FIXME: this should be processed in the PRU
InstanceHandle clsSystemAccountSignon = GetInstance(KnownInstanceGuids.Classes.UserLogin);
@ -905,7 +949,8 @@ public abstract class Oms
InstanceHandle parentClass = GetParentClass(methodOrMethodBinding);
Guid parentClassId = GetGlobalIdentifier(parentClass);
context.StackTrace.Push(methodOrMethodBinding);
context.Push(methodOrMethodBinding);
// context.StackTrace.Push(methodOrMethodBinding);
InstanceHandle? retval = null;
@ -949,7 +994,14 @@ public abstract class Oms
}
else
{
context.StackTrace.Pop();
// context.StackTrace.Pop();
IDictionary<InstanceHandle, object?> dict = context.GetAllWorkData();
context.Pop();
if (dict.ContainsKey(retval.Value))
{
context.SetWorkData(retval.Value, dict[retval.Value]);
}
return retval.Value;
}
}
@ -965,7 +1017,7 @@ public abstract class Oms
return new OmsContext(this);
}
public IReadOnlyCollection<InstanceHandle> ExecuteStaticMethodReturningInstanceSet(OmsContext context, ReturnInstanceSetMethodBinding methodBinding)
public IEnumerable<InstanceHandle> ExecuteStaticMethodReturningInstanceSet(OmsContext context, ReturnInstanceSetMethodBinding methodBinding)
{
InstanceHandle method = GetRelatedInstance(methodBinding.Handle, GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method));
if (TryGetAttributeValue<bool>(method, GetInstance(KnownAttributeGuids.Boolean.Static), out bool is_static))
@ -975,10 +1027,14 @@ public abstract class Oms
InstanceHandle result = Execute(context, methodBinding);
object? value = context.GetWorkData(result);
if (value is IReadOnlyCollection<InstanceHandle> res)
if (value is IEnumerable<InstanceHandle> res)
{
return res;
}
else if (value is InstanceHandle res_singular)
{
return new InstanceHandle[] { res_singular };
}
}
}
throw new InvalidOperationException("cannot call a non-static Method in a static context");
@ -1607,7 +1663,7 @@ public abstract class Oms
return false;
}
public void UpdateElementContents(OmsContext context, InstanceHandle element, ReadOnlyDictionary<string, string> values)
private void UpdateElementContents(OmsContext context, InstanceHandle element, IDictionary<string, string> values)
{
IEnumerable<InstanceHandle> elementContents = GetRelatedInstances(element, GetInstance(KnownRelationshipGuids.Element__has__Element_Content));
foreach (InstanceHandle elementContent in elementContents)
@ -1664,24 +1720,139 @@ public abstract class Oms
}
}
public Response ProcessElement(OmsContext context, InstanceHandle initiatingElement, InstanceHandle parmInstance)
public string GetLabelForUIElement(InstanceHandle parentElementContent)
{
if (parmInstance != InstanceHandle.Empty)
InstanceHandle parentInstance = GetRelatedInstance(parentElementContent, GetInstance(KnownRelationshipGuids.Element_Content__has__Instance));
string label = GetAttributeValue<string>(parentElementContent, GetInstance(KnownAttributeGuids.Text.LabelOverride));
if (label == null)
{
InstanceHandle processedByCt = GetRelatedInstance(initiatingElement, GetInstance(KnownRelationshipGuids.Element__processed_by__Control_Transaction_Method));
InstanceHandle forClassId = GetRelatedInstance(processedByCt, GetInstance(KnownRelationshipGuids.Method__for__Class));
label = GetAttributeValue<string>(parentElementContent, GetInstance(KnownAttributeGuids.Text.Label));
if (label == null)
{
label = GetInstanceText(parentInstance);
}
}
return label;
}
InstanceHandle buildsResponseWithMB = GetRelatedInstance(processedByCt, GetInstance(KnownRelationshipGuids.Control_Transaction_Method__uses__Build_Response_Method_Binding));
public Response ProcessElement(OmsContext ctx, InstanceHandle element, IDictionary<string, string>? form = null, string fqecidPrefix = "")
{
if (form != null)
{
/*
InstanceHandle processedByCt2 = GetRelatedInstance(element, GetInstance(KnownRelationshipGuids.Element__processed_by__Control_Transaction_Method));
InstanceHandle forClassId = GetRelatedInstance(processedByCt2, GetInstance(KnownRelationshipGuids.Method__for__Class));
InstanceHandle buildsResponseWithMB = GetRelatedInstance(processedByCt2, GetInstance(KnownRelationshipGuids.Control_Transaction_Method__uses__Build_Response_Method_Binding));
InstanceHandle executesMethod = GetRelatedInstance(buildsResponseWithMB, GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method));
InstanceHandle usesExecutableReturningElement = GetRelatedInstance(executesMethod, GetInstance(KnownRelationshipGuids.Build_UI_Response_Method__uses__Executable_returning_Element));
context.SetWorkData(forClassId, parmInstance);
return ProcessElement(context, usesExecutableReturningElement, InstanceHandle.Empty);
ctx.SetWorkData(forClassId, processingInstance);
return ProcessElement(ctx, usesExecutableReturningElement, InstanceHandle.Empty, form);
*/
// first we process the related updates
InstanceHandle processedByPru = GetRelatedInstance(element, GetInstance(KnownRelationshipGuids.Element__processed_by__Process_Related_Updates_Method));
if (processedByPru != InstanceHandle.Empty)
{
// this works... so far
Console.Error.WriteLine("oms: processing element with PRU {0}", processedByPru.GlobalIdentifier);
// hack
UpdateElementContents(ctx, element, form);
Execute(ctx, processedByPru);
/*
$executesMethod = $oms->getRelatedInstance($usesBRMB, KnownRelationshipGuids::Method_Binding__executes__Method);
if ($executesMethod === null)
{
trigger_error("task_step: 1; uses BRMB " . $usesBRMB . "; executes method is null");
}
$usesElement = $oms->getRelatedInstance($executesMethod, KnownRelationshipGuids::Build_UI_Response_Method__uses__Executable_returning_Element);
$this->updateWorkDataWithElementContents($parentElementContents, $element);
$usesElementContents = $oms->getRelatedInstances($usesElement, KnownRelationshipGuids::Element__has__Element_Content);
if (count($usesElementContents) > 0)
{
$ecInst0 = $oms->getRelatedInstance($usesElementContents[0], KnownRelationshipGuids::Element_Content__has__Instance);
$this->TargetInstance = $this->Context->getWorkData($ecInst0);
$this->renderTaskStep2($parentElementContents, $usesElement);
}
exit();
*/
}
// ... then we process the element contents...
IEnumerable<InstanceHandle> elementContents = GetRelatedInstances(element, GetInstance(KnownRelationshipGuids.Element__has__Element_Content));
foreach (InstanceHandle elementContent2 in elementContents)
{
Response? resp = ProcessElementContent(ctx, elementContent2, form, fqecidPrefix);
if (resp != null)
{
return resp;
}
}
// ... finally we run the CT - Control Transaction Method to return the response
InstanceHandle processedByCt = GetRelatedInstance(element, GetInstance(KnownRelationshipGuids.Element__processed_by__Control_Transaction_Method));
if (processedByCt != InstanceHandle.Empty)
{
Console.Error.WriteLine("oms: processing element with CT {0}", processedByCt.GlobalIdentifier);
// hack
IEnumerable<InstanceHandle> usesBuildResponseMethodBindings = GetRelatedInstances(processedByCt, GetInstance(KnownRelationshipGuids.Control_Transaction_Method__uses__Build_Response_Method_Binding));
Console.Error.WriteLine("---> has {0} BRMBs", usesBuildResponseMethodBindings.Count());
foreach (InstanceHandle usesBuildResponseMethodBinding in usesBuildResponseMethodBindings)
{
Console.Error.WriteLine("oms: evaluating BRMB {0}", usesBuildResponseMethodBinding.GlobalIdentifier);
IEnumerable<InstanceHandle> trueConditions = GetRelatedInstances(usesBuildResponseMethodBinding, GetInstance(KnownRelationshipGuids.Condition_Group__has_true_condition__Executable_returning_Work_Data));
IEnumerable<InstanceHandle> falseConditions = GetRelatedInstances(usesBuildResponseMethodBinding, GetInstance(KnownRelationshipGuids.Condition_Group__has_false_condition__Executable_returning_Work_Data));
bool useAnyCondition = GetAttributeValue<bool>(usesBuildResponseMethodBinding, GetInstance(KnownAttributeGuids.Boolean.UseAnyCondition));
if (EvaluateConditions(ctx, trueConditions, falseConditions, useAnyCondition))
{
InstanceHandle executesMethod = GetRelatedInstance(usesBuildResponseMethodBinding, GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method));
Console.Error.WriteLine("----> ok, executing method {0}", executesMethod.GlobalIdentifier);
// execute BRMB
string targetURL = GetAttributeValue<string>(executesMethod, GetInstance(KnownAttributeGuids.Text.TargetURL));
if (targetURL != null)
{
return new RedirectResponse(targetURL);
}
}
}
/*
$executesMethod = $oms->getRelatedInstance($usesBRMB, KnownRelationshipGuids::Method_Binding__executes__Method);
if ($executesMethod === null)
{
trigger_error("task_step: 1; uses BRMB " . $usesBRMB . "; executes method is null");
}
$usesElement = $oms->getRelatedInstance($executesMethod, KnownRelationshipGuids::Build_UI_Response_Method__uses__Executable_returning_Element);
$this->updateWorkDataWithElementContents($parentElementContents, $element);
$usesElementContents = $oms->getRelatedInstances($usesElement, KnownRelationshipGuids::Element__has__Element_Content);
if (count($usesElementContents) > 0)
{
$ecInst0 = $oms->getRelatedInstance($usesElementContents[0], KnownRelationshipGuids::Element_Content__has__Instance);
$this->TargetInstance = $this->Context->getWorkData($ecInst0);
$this->renderTaskStep2($parentElementContents, $usesElement);
}
exit();
*/
return FailureResponse.NotImplemented;
}
}
else
{
Renderer renderer = new Renderer(this);
Widget widget = renderer.Parse(context, initiatingElement, InstanceHandle.Empty, InstanceHandle.Empty);
Widget widget = renderer.Parse(ctx, element, InstanceHandle.Empty, InstanceHandle.Empty);
if (widget == null)
{
return FailureResponse.UnexpectedFailure;
@ -1704,18 +1875,74 @@ public abstract class Oms
return FailureResponse.UnexpectedFailure;
}
public string GetLabelForUIElement(InstanceHandle parentElementContent)
{
InstanceHandle parentInstance = GetRelatedInstance(parentElementContent, GetInstance(KnownRelationshipGuids.Element_Content__has__Instance));
string label = GetAttributeValue<string>(parentElementContent, GetInstance(KnownAttributeGuids.Text.LabelOverride));
if (label == null)
private Response? ProcessElementContent(OmsContext context, InstanceHandle elementContent, IDictionary<string, string> form, string fqecidPrefix)
{
InstanceHandle elementContentInstance = GetRelatedInstance(elementContent, GetInstance(KnownRelationshipGuids.Element_Content__has__Instance));
if (IsInstanceOf(elementContentInstance, GetInstance(KnownInstanceGuids.Classes.Element)))
{
label = GetAttributeValue<string>(parentElementContent, GetInstance(KnownAttributeGuids.Text.Label));
if (label == null)
return ProcessElement(context, elementContentInstance, form, fqecidPrefix + GetInstanceKey(elementContentInstance).ToString() + ":");
}
else if (IsInstanceOf(elementContentInstance, GetInstance(KnownInstanceGuids.Classes.TextAttribute)))
{
string key = fqecidPrefix + GetInstanceKey(elementContent);
string text = GetInstanceText(elementContentInstance);
if (form.ContainsKey(key))
{
label = GetInstanceText(parentInstance);
string value = form[key];
}
}
return label;
}
return null;
}
private HashAlgorithm hashAlgorithm = System.Security.Cryptography.SHA512.Create();
public InstanceHandle CreateUser(string username, string password)
{
InstanceHandle c_User = GetInstance(KnownInstanceGuids.Classes.User);
InstanceHandle a_UserName = GetInstance(KnownAttributeGuids.Text.UserName);
InstanceHandle a_PasswordSalt = GetInstance(KnownAttributeGuids.Text.PasswordSalt);
InstanceHandle a_PasswordHash = GetInstance(KnownAttributeGuids.Text.PasswordHash);
string salt = Guid.NewGuid().ToString("N").ToLowerInvariant();
string hash = Convert.ToHexString(hashAlgorithm.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password + salt))).ToLowerInvariant();
InstanceHandle i_User = CreateInstanceOf(c_User);
SetAttributeValue(i_User, a_UserName, username);
SetAttributeValue(i_User, a_PasswordSalt, salt);
SetAttributeValue(i_User, a_PasswordHash, hash);
return i_User;
}
public bool EvaluateConditions(OmsContext context, IEnumerable<InstanceHandle> trueConditions, IEnumerable<InstanceHandle> falseConditions, bool useAnyCondition)
{
bool value = false;
if (trueConditions != null)
{
foreach (InstanceHandle trueCondition in trueConditions)
{
InstanceHandle ret = Execute(context, trueCondition);
object? retval = context.GetWorkData(ret);
if (retval is bool && ((bool)retval))
{
value = true;
break;
}
}
}
if (falseConditions != null)
{
foreach (InstanceHandle falseCondition in falseConditions)
{
InstanceHandle ret = Execute(context, falseCondition);
object? retval = context.GetWorkData(ret);
if (retval is bool && (!(bool)retval))
{
value = true;
break;
}
}
}
return value;
}
}

View File

@ -25,6 +25,7 @@ public class OmsContext
{
public Oms Oms { get; }
public OmsStackTrace StackTrace { get; }
private Stack<Dictionary<InstanceHandle, object>> WorkDataSets = new Stack<Dictionary<InstanceHandle, object>>();
internal OmsContext(Oms oms)
{
@ -33,6 +34,7 @@ public class OmsContext
}
private Dictionary<InstanceHandle, object?> _WorkData = new Dictionary<InstanceHandle, object?>();
private Dictionary<InstanceHandle, object?> _GlobalData = new Dictionary<InstanceHandle, object?>();
public object? GetWorkData(WorkSet parm)
{
return GetWorkData(parm.Handle);
@ -42,6 +44,12 @@ public class OmsContext
if (_WorkData.ContainsKey(parm))
return _WorkData[parm];
foreach (Dictionary<InstanceHandle, object> set in WorkDataSets)
{
if (set.ContainsKey(parm))
return set[parm];
}
// Console.Error.WriteLine("work data not found for parm {0}", Oms.GetGlobalIdentifier(parm));
return null;
}
@ -108,6 +116,8 @@ public class OmsContext
}
}
}
value = ((IEnumerable<InstanceHandle>)value).FirstOrDefault();
}
else if (value is IEnumerable<InstanceWrapper>)
{
@ -141,4 +151,39 @@ public class OmsContext
}
_WorkData[parm] = value;
}
public void Push(InstanceHandle methodOrMethodBinding)
{
StackTrace.Push(methodOrMethodBinding);
WorkDataSets.Push(_WorkData);
_WorkData = new Dictionary<InstanceHandle, object?>();
}
public InstanceHandle Pop()
{
InstanceHandle methodOrMethodBinding = StackTrace.Pop();
_WorkData = WorkDataSets.Pop();
return methodOrMethodBinding;
}
public IDictionary<InstanceHandle, object?> GetAllWorkData()
{
return _WorkData;
}
public T GetGlobal<T>(InstanceHandle parm, T defaultValue = default(T))
{
if (_GlobalData.ContainsKey(parm))
{
if (_GlobalData[parm] is T)
{
return (T)(_GlobalData[parm]);
}
}
return defaultValue;
}
public void SetGlobal(InstanceHandle parm, object? value)
{
_GlobalData[parm] = value;
}
}

View File

@ -74,8 +74,11 @@ public abstract class Widget
if (!displayOptions.Contains(OMS.GetInstance(KnownInstanceGuids.ElementContentDisplayOptions.DoNotShowLabel)))
{
string label = OMS.GetLabelForUIElement(ParentElementContent);
obj.Add("label", label);
if (!OMS.IsInstanceOf(ParentInstance, OMS.GetInstance(KnownInstanceGuids.Classes.Element)))
{
string label = OMS.GetLabelForUIElement(ParentElementContent);
obj.Add("label", label);
}
}
if (!ShouldBeEnabled())
{

View File

@ -59,7 +59,7 @@ public class Element : Widget
// otherwise, we are a hbox
// return "hbox";
return "vbox";
return "fieldSet";
}
}

View File

@ -41,7 +41,7 @@ public class CommonTests : MethodTestsBase
Assert.That(delegate ()
{
IReadOnlyCollection<InstanceHandle> specifiedInstances = Oms.ExecuteStaticMethodReturningInstanceSet(context, dummyMethodRsmb);
IEnumerable<InstanceHandle> specifiedInstances = Oms.ExecuteStaticMethodReturningInstanceSet(context, dummyMethodRsmb);
}, Throws.InvalidOperationException);
}

View File

@ -44,7 +44,7 @@ public class GetSpecifiedInstancesMethodTests : MethodTestsBase
nom = Oms.GetInstanceText(gsiMethodRsmb);
OmsContext context = Oms.CreateContext();
IReadOnlyCollection<InstanceHandle> specifiedInstances = Oms.ExecuteStaticMethodReturningInstanceSet(context, gsiMethodRsmb);
IEnumerable<InstanceHandle> specifiedInstances = Oms.ExecuteStaticMethodReturningInstanceSet(context, gsiMethodRsmb);
Assert.That(specifiedInstances, Contains.Item(irTestClassInstance));
}

View File

@ -0,0 +1,94 @@
using System;
using Mocha.Core.Oop;
namespace Mocha.Core.Tests;
[TestFixture]
public class ModuleTests : OmsTestsBase
{
[Test]
public void ToplevelModuleInstanceText()
{
InstanceHandle ihMochaBaseSystem = Oms.GetInstance(KnownInstanceGuids.Modules.MochaBaseSystem);
string text = Oms.GetInstanceText(ihMochaBaseSystem);
Assert.That(text, Is.EqualTo("Mocha Base System"));
}
[Test]
public void SublevelModuleInstanceText()
{
InstanceHandle ihOOPMethodExamples = Oms.GetInstance(KnownInstanceGuids.Modules.OOPMethodExamples);
string text = Oms.GetInstanceText(ihOOPMethodExamples);
Assert.That(text, Is.EqualTo("Mocha Base System:OOP:OOP Method Examples"));
}
[Test]
public void TopLevelModuleName()
{
InstanceHandle ihMochaBaseSystem = Oms.GetInstance(KnownInstanceGuids.Modules.MochaBaseSystem);
InstanceHandle c_Module = Oms.GetInstance(KnownInstanceGuids.Classes.Module);
Method Module__get__Name = Oms.GetMethod(c_Module, "get", "Name");
Assert.That(Module__get__Name, Is.Not.Null);
//
OmsContext context = Oms.CreateContext();
InstanceHandle ret = Oms.Execute(context, Module__get__Name, ihMochaBaseSystem);
object? val = context.GetWorkData(ret);
Assert.That(val, Is.TypeOf<string>().And.EqualTo("Mocha Base System"));
}
[Test]
public void OOPMethodExamples_ParentModuleIs_OOP()
{
InstanceHandle ihOOPMethodExamples = Oms.GetInstance(KnownInstanceGuids.Modules.OOPMethodExamples);
InstanceHandle ihOOP = Oms.GetInstance(KnownInstanceGuids.Modules.OOP);
InstanceHandle c_Module = Oms.GetInstance(KnownInstanceGuids.Classes.Module);
Method Module__get__Parent_Module = Oms.GetMethod(c_Module, "get", "Parent Module");
Assert.That(Module__get__Parent_Module, Is.Not.Null);
OmsContext context = Oms.CreateContext();
InstanceHandle ret = Oms.Execute(context, Module__get__Parent_Module, ihOOPMethodExamples);
object? val = context.GetWorkData(ret);
Assert.That(val, Is.TypeOf<InstanceHandle>().And.EqualTo(ihOOP));
}
[Test]
public void MochaBaseSystem_ParentModuleIs_Empty()
{
InstanceHandle ihMochaBaseSystem = Oms.GetInstance(KnownInstanceGuids.Modules.MochaBaseSystem);
InstanceHandle c_Module = Oms.GetInstance(KnownInstanceGuids.Classes.Module);
Method Module__get__Parent_Module = Oms.GetMethod(c_Module, "get", "Parent Module");
Assert.That(Module__get__Parent_Module, Is.Not.Null);
OmsContext context = Oms.CreateContext();
InstanceHandle ret = Oms.Execute(context, Module__get__Parent_Module, ihMochaBaseSystem);
object? val = context.GetWorkData(ret);
Assert.That(val, Is.Null.Or.EqualTo(InstanceHandle.Empty));
}
[Test]
public void Module__get__Fully_Qualified_Name__method_components()
{
InstanceHandle ihMochaBaseSystem = Oms.GetInstance(KnownInstanceGuids.Modules.MochaBaseSystem);
InstanceHandle c_Module = Oms.GetInstance(KnownInstanceGuids.Classes.Module);
InstanceHandle method = Oms.GetInstance(new Guid("{0ab85e0b-5577-475a-b914-4578ffb928d7}"));
IEnumerable<InstanceHandle> ms = Oms.GetRelatedInstances(method, Oms.GetInstance(KnownRelationshipGuids.Build_Attribute_Method__builds_with__Build_Attribute_Method_Component));
InstanceHandle m2 = Oms.GetInstance(new Guid("{27b070c9-7130-414b-960d-511f2836ef06}"));
IEnumerable<InstanceHandle> ms2 = Oms.GetRelatedInstances(method, Oms.GetInstance(KnownRelationshipGuids.Build_Attribute_Method__builds_with__Build_Attribute_Method_Component));
OmsContext context = Oms.CreateContext();
InstanceHandle ret = Oms.Execute(context, method, ihMochaBaseSystem);
object? val = context.GetWorkData(ret);
}
}

View File

@ -0,0 +1,73 @@
using System;
using System.Text.Json.Nodes;
namespace Mocha.Core.Tests.UI;
[TestFixture]
public class UITests : OmsTestsBase
{
[Test]
public void LoginPageElement()
{
InstanceHandle loginPage = Oms.GetInstance(KnownInstanceGuids.Pages.LoginPage);
OmsContext context = Oms.CreateContext();
Response pageOutput = Oms.ProcessElement(context, loginPage);
JsonObject json = pageOutput.GetResponse(Oms, context);
Assert.That(json["result"].GetValue<string>(), Is.EqualTo("success"));
Assert.That(json["value"]["body"]["widget"].GetValue<string>(), Is.EqualTo("fieldSet"));
}
[Test]
public void LoginPageElementSubmit()
{
Oms.CreateUser("testing", "testing");
InstanceHandle loginPage = Oms.GetInstance(KnownInstanceGuids.Pages.LoginPage);
InstanceHandle loginPageSubedit = Oms.GetInstance(new Guid("{2b7d4481-b7c2-4e26-a917-e3ff7c367a8a}"));
OmsContext context = Oms.CreateContext();
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["{c67f305e-bd4d-4628-816b-55fb85ea1b67}"] = "testing";
dict["{51b51be3-44fd-48f1-971f-682aee0a6132}"] = "testing";
Response pageOutput = Oms.ProcessElement(context, loginPageSubedit, dict);
JsonObject json = pageOutput.GetResponse(Oms, context);
string s_Token = context.GetGlobal<string>(Oms.GetInstance(KnownAttributeGuids.Text.Token));
Assert.That(s_Token, Is.Not.Empty);
Assert.That(json["result"].GetValue<string>(), Is.EqualTo("success"));
Assert.That(json["type"].GetValue<string>(), Is.EqualTo("redirect"));
Assert.That(json["destinationUrl"].GetValue<string>(), Is.EqualTo("~/d/home.htmld"));
}
[Test]
public void LoginPageElementSubmitBadPassword()
{
InstanceHandle loginPage = Oms.GetInstance(KnownInstanceGuids.Pages.LoginPage);
InstanceHandle loginPageSubedit = Oms.GetInstance(new Guid("{2b7d4481-b7c2-4e26-a917-e3ff7c367a8a}"));
OmsContext context = Oms.CreateContext();
Dictionary<string, string> dict = new();
dict["{c67f305e-bd4d-4628-816b-55fb85ea1b67}"] = "superuser";
dict["{51b51be3-44fd-48f1-971f-682aee0a6132}"] = "testing";
Response pageOutput = Oms.ProcessElement(context, loginPageSubedit, dict);
object i_User = context.GetWorkData(Oms.GetInstance(KnownInstanceGuids.Classes.User));
Assert.That(i_User, Is.Null);
JsonObject json = pageOutput.GetResponse(Oms, context);
// ??? should this return a result=failure?
Assert.That(json["result"].GetValue<string>(), Is.EqualTo("success"));
Assert.That(json["type"].GetValue<string>(), Is.EqualTo("redirect"));
Assert.That(json["destinationUrl"].GetValue<string>(), Does.StartWith("~/d/logout.htmld"));
}
}