fix regressions introduced by tighter OOP restrictions and add unit tests for HTTP OMS server

This commit is contained in:
Michael Becker 2025-01-05 23:37:09 -05:00
parent 36b5d8a7c5
commit 3c5bfc6f6a
27 changed files with 457 additions and 80 deletions

@ -1 +1 @@
Subproject commit 15db6ef037159d1efed4f372d50deb5b6ec33cef
Subproject commit 78649bc72e2dd513f5dedc9103fb765b968399e3

View File

@ -51,6 +51,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Zq.Tests", "mocha-dot
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Zq.Integration", "mocha-dotnet\src\lib\Mocha.Zq.Integration\Mocha.Zq.Integration.csproj", "{ADD7359E-0E3B-4435-B812-EC961C52DA2A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Oms.Server.Tests", "mocha-dotnet\tests\Mocha.Oms.Server.Tests\Mocha.Oms.Server.Tests.csproj", "{271CBF6A-07E4-46EB-A418-513E9FD89E36}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -101,6 +103,10 @@ Global
{ADD7359E-0E3B-4435-B812-EC961C52DA2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADD7359E-0E3B-4435-B812-EC961C52DA2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADD7359E-0E3B-4435-B812-EC961C52DA2A}.Release|Any CPU.Build.0 = Release|Any CPU
{271CBF6A-07E4-46EB-A418-513E9FD89E36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{271CBF6A-07E4-46EB-A418-513E9FD89E36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{271CBF6A-07E4-46EB-A418-513E9FD89E36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{271CBF6A-07E4-46EB-A418-513E9FD89E36}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -127,6 +133,7 @@ Global
{04985CF7-45AA-4C67-9EEC-BDDF2DFC5C98} = {A2C401E9-FED4-43BA-A928-566239894CEE}
{F5D1EF0F-B42F-4237-B08A-7A78143C3ECB} = {27C300F5-5172-4225-A6F7-3503B9007DD8}
{ADD7359E-0E3B-4435-B812-EC961C52DA2A} = {A2C401E9-FED4-43BA-A928-566239894CEE}
{271CBF6A-07E4-46EB-A418-513E9FD89E36} = {27C300F5-5172-4225-A6F7-3503B9007DD8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D28A9CF8-0235-4F8F-865F-C460BDCAE16D}

View File

@ -1,4 +1,4 @@
namespace Mocha.OMS.Server;
namespace Mocha.Oms.Server;
using Mocha.Core;
@ -42,12 +42,12 @@ public class Program : WebApplication
public Program()
{
ShortName = "mocha-oms-server";
oms = new MemoryOms();
Oms = new MemoryOms();
}
private LibraryHandle l_System, l_Web;
private Oms oms;
public Oms Oms { get; }
protected override WebServer CreateWebServer()
{
@ -70,10 +70,10 @@ public class Program : WebApplication
}
// this all has to be done before the Web server is started...
oms.Initialize();
Oms.Initialize();
TenantHandle th = oms.CreateTenant("super");
oms.SelectTenant(th);
TenantHandle th = Oms.CreateTenant("super");
Oms.SelectTenant(th);
string path;
if (System.Environment.OSVersion.Platform == PlatformID.Win32NT)
@ -99,22 +99,22 @@ public class Program : WebApplication
return;
}
if (!TryLoadLibrary(oms, path, "net.alcetech.Mocha.System.mcl"))
if (!TryLoadLibrary(Oms, path, "net.alcetech.Mocha.System.mcl"))
{
return;
}
if (!TryLoadLibrary(oms, path, "net.alcetech.Mocha.Web.mcl"))
if (!TryLoadLibrary(Oms, path, "net.alcetech.Mocha.Web.mcl"))
{
return;
}
// implement functions to get user IP address
oms.RegisterSystemAttributeRoutine<string>(KnownInstanceGuids.SystemAttributeRoutines.GetIPAddress, delegate (Oms oms2, OmsContext ctx2)
Oms.RegisterSystemAttributeRoutine<string>(KnownInstanceGuids.SystemAttributeRoutines.GetIPAddress, delegate (Oms oms2, OmsContext ctx2)
{
// !HACK
return ctx2.GetExtraData<string>("Client.IPAddress");
});
oms.SystemRoutineExecuted += oms_SystemRoutineExecuted;
Oms.SystemRoutineExecuted += oms_SystemRoutineExecuted;
// now we can start the Web server
base.OnStartup(e);
@ -158,7 +158,7 @@ public class Program : WebApplication
OmsContext ctx = null;
if (!e.Context.Session.ContainsKey("OmsContext"))
{
ctx = oms.CreateContext();
ctx = Oms.CreateContext();
e.Context.Session["OmsContext"] = ctx;
}
ctx = (OmsContext)e.Context.Session["OmsContext"];
@ -186,7 +186,7 @@ public class Program : WebApplication
else if (e.Context.Request.PathParts.Length > 1)
{
OmsServer server = new OmsServer();
server.ProcessRequest(e, oms, ctx, sw);
server.ProcessRequest(e, Oms, ctx, sw);
}
else
{

View File

@ -436,5 +436,7 @@ namespace Mocha.Core
public static Guid Get_Instances_Method__returns__Work_Set { get; } = new Guid("{7d0f93b1-8c93-464e-a44d-d674f910b589}");
public static Guid Get_Instances_Method__selects_instances_of__Class { get; } = new Guid("{c0b85d90-de8c-44c2-9420-c5e724ccdf2c}");
public static Guid Method_Binding__uses_super__Return_Instance_Set_Method_Binding { get; } = new Guid("{444279f1-3bf9-4d1f-848e-e7bf33fa0fd7}");
public static Guid Metadata_With_Access_Modifier__has__Access_Modifier { get; } = new Guid("{c8551fb1-6dc5-47cb-8b8f-204d49e6007e}");
}
}

View File

@ -92,6 +92,7 @@ public class EvaluateBooleanExpressionMethodImplementation : MethodImplementatio
{
InstanceHandle target = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Evaluate_Boolean_Expression_Method__has_target__Executable_returning_Work_Data));
InstanceHandle[] rtarget_value = new InstanceHandle[0];
object? rtarget_valueraw = null;
InstanceHandle[] rsource_value = new InstanceHandle[0];
if (rsource_valueraw is InstanceHandle[])
@ -110,7 +111,7 @@ public class EvaluateBooleanExpressionMethodImplementation : MethodImplementatio
else if (oms.IsInstanceOf(target, oms.GetInstance(KnownInstanceGuids.Classes.Executable)))
{
InstanceHandle rtarget = oms.Execute(context, target);
object? rtarget_valueraw = context.GetWorkData(rtarget);
rtarget_valueraw = context.GetWorkData(rtarget);
}
else
{
@ -151,7 +152,7 @@ public class EvaluateBooleanExpressionMethodImplementation : MethodImplementatio
else if (comparison == oms.GetInstance(KnownInstanceGuids.LogicalOperators.EqualTo))
{
// ! FIXME ! Implement This !
value = false;
value = (rsource_valueraw?.Equals(rtarget_valueraw)).GetValueOrDefault(false);
}
else
{

View File

@ -30,15 +30,15 @@ public class GetAttributeMethodImplementation : MethodImplementation
throw new InvalidOperationException("no Work Set specified for method");
}
InstanceHandle? forInstance = (InstanceHandle?) context.GetWorkData(irForClass);
IInstanceReference? forInstance = (IInstanceReference?) context.GetWorkData(irForClass);
if (forInstance == null)
{
throw new NullReferenceException(String.Format("non-static method call without instance reference {0}", oms.GetGlobalIdentifier(irForClass)));
}
if (oms.IsInstanceOf(forInstance.Value, oms.GetInstance(KnownInstanceGuids.Classes.WorkSet)))
if (oms.IsInstanceOf(forInstance, oms.GetInstance(KnownInstanceGuids.Classes.WorkSet)))
{
forInstance = (InstanceHandle?) context.GetWorkData(forInstance.Value);
forInstance = (InstanceHandle?) context.GetWorkData(forInstance);
}
if (forInstance is InstanceHandle forInstanceHandle)

View File

@ -28,7 +28,7 @@ public class GetRelationshipMethodImplementation : MethodImplementation
InstanceHandle irForClass = oms.GetRelatedInstance(method, oms.GetInstance(KnownRelationshipGuids.Method__for__Class));
InstanceHandle? forClassInstanceV = context.GetWorkData<InstanceHandle?>(irForClass);
IInstanceReference? forClassInstanceV = context.GetWorkData<IInstanceReference?>(irForClass);
bool singular = oms.GetAttributeValue<bool>(method, oms.GetInstance(KnownAttributeGuids.Boolean.Singular), false);
@ -43,7 +43,7 @@ public class GetRelationshipMethodImplementation : MethodImplementation
// HACK: there is no `GR - Get Relationship Method.returns Work Set`
if (forClassInstanceV != null)
{
ihs = oms.GetRelatedInstances((InstanceHandle)forClassInstanceV, returnsRelationship);
ihs = oms.GetRelatedInstances(forClassInstanceV, returnsRelationship);
}
if (singular)

View File

@ -17,25 +17,13 @@
namespace Mocha.Core;
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;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json.Nodes;
using System.Xml.XPath;
using MBS.Core;
using MBS.Core.Collections;
using MBS.Core.Extensibility;
using MBS.Core.IO;
using Mocha.Core.MethodImplementations;
using Mocha.Core.Oop;
using Mocha.Core.Responses;
using Mocha.Core.UI;
@ -485,11 +473,11 @@ public abstract class Oms
}
protected abstract IReadOnlyCollection<InstanceHandle> GetRelatedInstancesInternal(InstanceHandle source, InstanceHandle relationship, DateTime effectiveDate);
public IReadOnlyCollection<InstanceHandle> GetRelatedInstances(InstanceHandle source, InstanceHandle relationship, DateTime effectiveDate)
public IReadOnlyCollection<InstanceHandle> GetRelatedInstances(IInstanceReference source, InstanceHandle relationship, DateTime effectiveDate)
{
return GetRelatedInstancesInternal(source, relationship, effectiveDate);
return GetRelatedInstancesInternal(source.GetHandle(), relationship, effectiveDate);
}
public IReadOnlyCollection<InstanceHandle> GetRelatedInstances(InstanceHandle source, InstanceHandle relationship)
public IReadOnlyCollection<InstanceHandle> GetRelatedInstances(IInstanceReference source, InstanceHandle relationship)
{
return GetRelatedInstances(source, relationship, DateTime.Now);
}
@ -845,7 +833,7 @@ public abstract class Oms
return false;
}
private bool RecursiveClassHasSuperclass(InstanceHandle clasz, InstanceHandle superclasz)
private bool RecursiveClassHasSuperclass(IInstanceReference clasz, InstanceHandle superclasz)
{
IEnumerable<InstanceHandle> inheritedClasses = GetRelatedInstances(clasz, GetInstance(KnownRelationshipGuids.Class__has_super__Class));
foreach (InstanceHandle ih in inheritedClasses)
@ -862,7 +850,7 @@ public abstract class Oms
return false;
}
public bool IsInstanceOf(InstanceHandle instance, InstanceHandle parentClass, bool exactMatch = false)
public bool IsInstanceOf(IInstanceReference instance, InstanceHandle parentClass, bool exactMatch = false)
{
InstanceHandle parentClass1 = GetParentClass(instance);
bool value = Object.Equals(parentClass1, parentClass);
@ -873,7 +861,7 @@ public abstract class Oms
return value;
}
public bool IsSubclassOf(InstanceHandle subclasz, InstanceHandle clasz, bool exactMatch = false)
public bool IsSubclassOf(IInstanceReference subclasz, InstanceHandle clasz, bool exactMatch = false)
{
bool value = Object.Equals(subclasz, clasz);
if (!value && !exactMatch)
@ -1093,12 +1081,12 @@ public abstract class Oms
}
return defaultValue;
}
public InstanceHandle Execute(OmsContext context, InstanceHandle methodOrMethodBinding, InstanceHandle? targetInstance = null)
public InstanceHandle Execute(OmsContext context, InstanceHandle methodOrMethodBinding, IInstanceReference? targetInstance = null)
{
InstanceHandle parentClass = GetParentClass(methodOrMethodBinding);
Guid parentClassId = GetGlobalIdentifier(parentClass);
context.Push(methodOrMethodBinding);
context.Push(methodOrMethodBinding, targetInstance);
// context.StackTrace.Push(methodOrMethodBinding);
InstanceHandle? retval = null;
@ -1115,14 +1103,27 @@ public abstract class Oms
{
InstanceHandle assignsToParm = GetRelatedInstance(parm, GetInstance(KnownRelationshipGuids.Parameter_Assignment__assigns_to__Work_Data));
InstanceHandle assignsFromWorkData = GetRelatedInstance(parm, GetInstance(KnownRelationshipGuids.Parameter_Assignment__assigns_from__Executable_returning_Work_Data));
IInstanceReference assignsFromWorkData = GetRelatedInstance(parm, GetInstance(KnownRelationshipGuids.Parameter_Assignment__assigns_from__Executable_returning_Work_Data));
if (IsInstanceOf(assignsFromWorkData, GetInstance(KnownInstanceGuids.Classes.Class)))
{
assignsFromWorkData = context.GetWorkData<InstanceHandle>(assignsFromWorkData);
assignsFromWorkData = context.GetWorkData<IInstanceReference>(assignsFromWorkData);
}
context.SetWorkData(assignsToParm, assignsFromWorkData);
}
retval = ExecuteMethodBinding(context, methodOrMethodBinding);
InstanceHandle relatedMethod = GetRelatedInstance(methodOrMethodBinding, GetInstance<Relationship>(KnownRelationshipGuids.Method_Binding__executes__Method));
InstanceHandle relatedMethod_for_Class = GetRelatedInstance(relatedMethod, GetInstance<Relationship>(KnownRelationshipGuids.Method__for__Class));
if (relatedMethod_for_Class != InstanceHandle.Empty)
{
//!HACK!
object? wd = context.GetWorkData(relatedMethod_for_Class);
if (wd is IInstanceReference)
{
targetInstance = ((IInstanceReference)context.GetWorkData(relatedMethod_for_Class)).GetHandle();
}
}
retval = ExecuteMethodBinding(context, methodOrMethodBinding, targetInstance);
InstanceHandle ihSuperRSMB = GetRelatedInstance(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Method_Binding__uses_super__Return_Instance_Set_Method_Binding));
if (ihSuperRSMB != InstanceHandle.Empty)
@ -1150,10 +1151,56 @@ public abstract class Oms
{
if (methodImplementations.ContainsKey(parentClassId))
{
if (targetInstance == null)
{
InstanceHandle forClass = GetRelatedInstance(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Method__for__Class));
if (forClass != InstanceHandle.Empty)
{
IInstanceReference? irTarget = context.GetWorkData<IInstanceReference?>(forClass);
if (irTarget != null)
{
targetInstance = irTarget.GetHandle();
}
}
}
bool is_static = GetAttributeValue<bool>(methodOrMethodBinding, GetInstance(KnownAttributeGuids.Boolean.Static));
if (!is_static && targetInstance == null)
{
throw new NullReferenceException(String.Format("Attempt to call instance method `{0}` without an instance", methodOrMethodBinding));
}
if (targetInstance == null)
{
}
InstanceHandle i_ForClass = GetRelatedInstance(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Method__for__Class));
InstanceHandle i_AccessModifier = GetRelatedInstance(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Metadata_With_Access_Modifier__has__Access_Modifier));
if (i_AccessModifier == GetInstance(KnownInstanceGuids.AccessModifiers.Private))
{
// private methods may not be called from outside the defining class
if (context.StackTrace.Count > 2)
{
InstanceHandle caller = context.StackTrace.Peek();
InstanceHandle caller2 = context.StackTrace.Peek(1);
}
else
{
// we are either a method or a method binding calling a method
// which is an entry point. we do not originate from
// the defining class, so block this call
throw new MethodAccessException("calling entry point method or method binding outside of defining class");
}
}
else if (i_AccessModifier == GetInstance(KnownInstanceGuids.AccessModifiers.Protected))
{
// protected methods may be called only from within the defining class or its subclasses
}
if (targetInstance != null)
{
InstanceHandle hh = targetInstance.GetValueOrDefault();
InstanceHandle hh = targetInstance.GetHandle();
InstanceHandle pclassInstance = GetParentClass(hh);
context.SetWorkData(pclassInstance, hh);
}
@ -1178,10 +1225,10 @@ public abstract class Oms
}
}
private InstanceHandle ExecuteMethodBinding(OmsContext context, InstanceHandle methodBinding)
private InstanceHandle ExecuteMethodBinding(OmsContext context, InstanceHandle methodBinding, IInstanceReference? targetInstance = null)
{
InstanceHandle method = GetRelatedInstance(methodBinding, GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method));
return Execute(context, method);
return Execute(context, method, targetInstance);
}
public OmsContext CreateContext()
@ -1288,7 +1335,7 @@ public abstract class Oms
OmsContext context = CreateContext();
context.SetWorkData(parentClass, inst);
InstanceHandle wd = Execute(context, ramb);
InstanceHandle wd = Execute(context, ramb, inst);
string value = context.GetWorkData<string>(wd);
return value;

View File

@ -25,8 +25,21 @@ public class OmsContext
{
public Oms Oms { get; }
public OmsStackTrace StackTrace { get; }
private Stack<IInstanceReference?> TargetInstances = new Stack<IInstanceReference?>();
private Stack<Dictionary<InstanceHandle, object>> WorkDataSets = new Stack<Dictionary<InstanceHandle, object>>();
public IInstanceReference? TargetInstance
{
get
{
if (TargetInstances.Count > 0)
{
return TargetInstances.Peek();
}
return null;
}
}
internal OmsContext(Oms oms)
{
Oms = oms;
@ -35,26 +48,47 @@ 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)
public object? GetWorkData(IInstanceReference parm)
{
return GetWorkData(parm.GetHandle());
}
public object? GetWorkData(InstanceHandle parm)
{
if (_WorkData.ContainsKey(parm))
return _WorkData[parm];
if (_WorkData.ContainsKey(parm.GetHandle()))
return _WorkData[parm.GetHandle()];
foreach (Dictionary<InstanceHandle, object> set in WorkDataSets)
{
if (set.ContainsKey(parm))
return set[parm];
if (set.ContainsKey(parm.GetHandle()))
{
object? val = set[parm.GetHandle()];
if (val != null)
{
return val;
}
}
}
foreach (KeyValuePair<InstanceHandle, object> kvp in _WorkData)
{
if (Oms.IsSubclassOf(kvp.Key, parm.GetHandle()))
{
return kvp.Value;
}
}
foreach (Dictionary<InstanceHandle, object> set in WorkDataSets)
{
foreach (KeyValuePair<InstanceHandle, object> kvp in set)
{
if (Oms.IsSubclassOf(kvp.Key, parm.GetHandle()))
{
return kvp.Value;
}
}
}
// Console.Error.WriteLine("work data not found for parm {0}", Oms.GetGlobalIdentifier(parm));
return null;
}
public T GetWorkData<T>(InstanceHandle parm, T defaultValue = default(T))
public T GetWorkData<T>(IInstanceReference parm, T defaultValue = default(T))
{
object? val = GetWorkData(parm);
if (val is T)
@ -64,7 +98,7 @@ public class OmsContext
return defaultValue;
}
public void SetWorkData(WorkSet parm, object? value)
public void SetWorkData(IInstanceReference parm, object? value)
{
SetWorkData(parm.GetHandle(), value);
}
@ -147,10 +181,11 @@ public class OmsContext
_WorkData[parm] = value;
}
public void Push(InstanceHandle methodOrMethodBinding)
public void Push(InstanceHandle methodOrMethodBinding, IInstanceReference? targetInstance = null)
{
StackTrace.Push(methodOrMethodBinding);
WorkDataSets.Push(_WorkData);
TargetInstances.Push(targetInstance);
_WorkData = new Dictionary<InstanceHandle, object?>();
}
@ -158,6 +193,8 @@ public class OmsContext
{
InstanceHandle methodOrMethodBinding = StackTrace.Pop();
_WorkData = WorkDataSets.Pop();
TargetInstances.Pop();
return methodOrMethodBinding;
}

View File

@ -109,6 +109,10 @@ public class OmsMethodBuilder
{
InstanceHandle method = Oms.CreateInstanceOf(methodClassInstance, globalIdentifier);
Oms.AssignRelationship(method, Oms.GetInstance(KnownRelationshipGuids.Method__for__Class), forClassInstance);
if (accessModifier != null)
{
Oms.AssignRelationship(method, Oms.GetInstance(KnownRelationshipGuids.Metadata_With_Access_Modifier__has__Access_Modifier), accessModifier.GetHandle());
}
if (!Oms.ValidateConstraints)
{
// sibling relationships aren't being generated automatically

View File

@ -22,6 +22,7 @@ namespace Mocha.Core;
public class OmsStackTrace
{
private Stack<InstanceHandle> stack = new Stack<InstanceHandle>();
public int Count { get { return stack.Count; } }
private OmsContext parent;
internal OmsStackTrace(OmsContext parent)
@ -53,4 +54,14 @@ public class OmsStackTrace
}
return sb.ToString();
}
public InstanceHandle Peek(int level = 0)
{
if (level == 0)
{
InstanceHandle ih = stack.Peek();
return ih;
}
return stack.ElementAt(level);
}
}

View File

@ -42,6 +42,7 @@ public class ZqIntegrator
}
}
InstanceHandle a_Name = OMS.GetInstance(KnownAttributeGuids.Text.Name);
InstanceKey parentIK = OMS.GetInstanceKey(ih);
foreach (ZqInstance inst in zql.Instances)
{
@ -51,7 +52,6 @@ public class ZqIntegrator
OMS.SetInstanceKey(ih2, inst.InstanceKey);
}
InstanceHandle a_Name = OMS.GetInstance(KnownAttributeGuids.Text.Name);
if (a_Name != InstanceHandle.Empty)
{
if (inst.Name != null)
@ -65,6 +65,15 @@ public class ZqIntegrator
{
if (meth is ZqSimpleReturnMethod gsi)
{
AccessModifier? accessModifier;
switch (meth.AccessModifier)
{
case ZqAccessModifier.Private: accessModifier = AccessModifier.Private; break;
case ZqAccessModifier.Protected: accessModifier = AccessModifier.Protected; break;
case ZqAccessModifier.Public: accessModifier = AccessModifier.Public; break;
default: accessModifier = AccessModifier.RootA2; break;
}
Core.Oop.WorkSet ws = OMS.CreateWorkSet(meth.Name);
if (gsi.ReturnValue is ZqArray)
{
@ -81,14 +90,14 @@ public class ZqIntegrator
}
}
OMS.MethodBuilder.CreateGetSpecifiedInstancesMethod(ih.GetHandle(), null, meth.Name, ws, list.ToArray());
OMS.MethodBuilder.CreateGetSpecifiedInstancesMethod(ih.GetHandle(), null, meth.Name, accessModifier, meth.IsStatic, ws, list.ToArray());
}
else if (gsi.ReturnValue is ZqVariableReference)
{
object r = ResolveVariable(ih, ((ZqVariableReference)gsi.ReturnValue).Name);
if (r is InstanceHandle ihret)
{
OMS.MethodBuilder.CreateGetSpecifiedInstancesMethod(ih.GetHandle(), null, meth.Name, ws, ihret);
OMS.MethodBuilder.CreateGetSpecifiedInstancesMethod(ih.GetHandle(), null, meth.Name, accessModifier, meth.IsStatic, ws, ihret);
}
}
}
@ -98,7 +107,7 @@ public class ZqIntegrator
return null;
}
private object ResolveVariable(Class parentClassInstance, string name)
public object ResolveVariable(Class parentClassInstance, string name)
{
InstanceHandle ihret = OMS.GetInstanceByName(parentClassInstance, name);
if (ihret != InstanceHandle.Empty)
@ -183,7 +192,7 @@ public class ZqIntegrator
throw new NotImplementedException();
}
private string ZqNormalizeName(string fullName)
public string ZqNormalizeName(string fullName)
{
return fullName.Replace("-", "_").Replace(" ", "").Replace("(", "_").Replace(")", "_");
}

View File

@ -45,6 +45,9 @@ public abstract class ZqMethod : ZqObject, IZqMethod
public ZqMethodCall? Executable { get; internal set; } = null;
public virtual ZqDataType ReturnDataType { get; set; }
public bool IsStatic { get; set; }
public ZqAccessModifier AccessModifier { get; set; }
public ZqMethod(string name)
{
Name = name;

View File

@ -239,7 +239,7 @@ public class ZqParser
}
else if (tok.Equals("function"))
{
return ParseFunction(text, ref i, ref parms);
ZqMethod? p = ParseFunction(text, ref i, ref parms);
}
else if (tok.Equals("}"))
{
@ -251,9 +251,15 @@ public class ZqParser
return thisClass;
}
private ZqObject? ParseFunction2(string text, ref int i, ref ZqDefParms parms)
private ZqMethod? ParseFunction(string text, ref int i, ref ZqDefParms parms)
{
throw new NotImplementedException();
ZqMethod? p = ParseFunction2(text, ref i, ref parms);
if (p != null)
{
p.IsStatic = parms.isStatic;
p.AccessModifier = parms.accessModifier;
}
return p;
}
private bool IsModifier(string? tok, ref ZqDefParms parms)
@ -437,7 +443,7 @@ public class ZqParser
}
}
private ZqMethod? ParseFunction(string pp, ref int j, ref ZqDefParms defparms)
private ZqMethod? ParseFunction2(string pp, ref int j, ref ZqDefParms defparms)
{
string functionName = ReadUntil(pp, ref j, '(', false).Trim();
List<ZqParameter> parmListList = new List<ZqParameter>();

View File

@ -184,7 +184,7 @@ public class McxMiniLibraryPlugin : LibraryPlugin
protected override void LoadInternal(string filename, Library library)
{
FileStream fs = File.Open(filename, FileMode.Open);
FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
LoadInternal(fs, library);
}
}

View File

@ -48,7 +48,7 @@ public class BasicTests : OmsTestsBase
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestAttribute = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute), TEST_ATTR_GUID);
InstanceHandle irTestAttribute = Oms.GetInstance(TEST_ATTR_GUID);
Assert.That(irTestAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
Oms.AddAttribute(irTestClass, irTestAttribute);

View File

@ -7,11 +7,15 @@ namespace Mocha.Core.Tests;
public class DerivedInstanceTests : OmsTestsBase
{
Class TEST_CLASS_DERIVED;
InstanceKey ik_derived;
protected override void AfterSetup()
{
base.AfterSetup();
TEST_CLASS_DERIVED = Oms.CreateClass("Test Class (Derived)");
ik_derived = Oms.GetInstanceKey(TEST_CLASS_DERIVED);
Oms.SetAttributeValue(TEST_CLASS_DERIVED, Oms.GetInstance(KnownAttributeGuids.Boolean.Derived), true);
// Derived classes are represented only by InstanceKeys with the form {ClassId}!{DerivedData}, where
@ -43,7 +47,7 @@ public class DerivedInstanceTests : OmsTestsBase
[Test]
public void Derived_Instance_Test__instance_key_Parse()
{
string ikStr = "154!FQAAABVUZXN0IENsYXNzIERlcml2ZWQgIzE=";
string ikStr = String.Format("{0}!FQAAABVUZXN0IENsYXNzIERlcml2ZWQgIzE=", ik_derived.InstanceIndex);
InstanceKey ik = InstanceKey.Parse(ikStr);
InstanceHandle ih = Oms.GetInstance(ik);

View File

@ -22,6 +22,24 @@ namespace Mocha.Core.Tests.MethodTests;
public class EvaluateBooleanExpressionMethodTests : MethodTestsBase
{
[Test]
public void Test_EBE_Method__is__Static()
{
InstanceHandle c_OMS = Oms.GetInstance(KnownInstanceGuids.Classes.OMS);
InstanceHandle c_Method = Oms.GetInstance(KnownInstanceGuids.Classes.Method);
Method OMS__get__Runtime_Version = Oms.GetMethod(c_OMS, "get", "Runtime Version");
MethodReturningAttribute Method__is__Static = (MethodReturningAttribute) Oms.GetMethod(c_Method, "is", "Static");
MethodBinding mb = Method__is__Static.CreateMethodBinding(Oms);
OmsContext context = Oms.CreateContext();
InstanceHandle h = Oms.Execute(context, mb, OMS__get__Runtime_Version);
object? val = context.GetWorkData(h);
Assert.That(val, Is.EqualTo(true));
}
[Test]
public void Test_EBE_Returns_False_if_Method_is_NOT_Get_Attribute_Method()
{
@ -37,7 +55,7 @@ public class EvaluateBooleanExpressionMethodTests : MethodTestsBase
context.SetWorkData(c_Instance, Instance__get__Parent_Class);
InstanceHandle wsRet = Oms.Execute(context, Instance__get__Parent_Class);
InstanceHandle pclass = (InstanceHandle)context.GetWorkData(wsRet);
object? pclass = context.GetWorkData(wsRet);
Assert.That(pclass, Is.EqualTo(Oms.GetInstance(KnownInstanceGuids.MethodClasses.GetRelationshipMethod)));

View File

@ -29,7 +29,7 @@ namespace Mocha.Core.Tests.MethodTests
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
InstanceHandle irTestClassInstance = Oms.CreateInstanceOf(irTestClass);
InstanceHandle irTestAttribute = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute), TEST_ATTR_GUID);
InstanceHandle irTestAttribute = Oms.GetInstance(TEST_ATTR_GUID);
Assert.That(irTestAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
Oms.AddAttribute(irTestClass, irTestAttribute);

View File

@ -112,10 +112,10 @@ public class MethodBindingTests : MethodTestsBase
WorkSet ws = Oms.CreateWorkSet("Singleton OMS");
GetSpecifiedInstancesMethod m1 = Oms.MethodBuilder.CreateGetSpecifiedInstancesMethod(c_OMS.GetHandle(), "get", "Singleton", ws, new InstanceHandle[] { i_OMS });
GetSpecifiedInstancesMethod m1 = Oms.MethodBuilder.CreateGetSpecifiedInstancesMethod(c_OMS.GetHandle(), "get", "Singleton", AccessModifier.Public, true, ws, new InstanceHandle[] { i_OMS });
ReturnInstanceSetMethodBinding rsmb1 = m1.CreateMethodBinding(Oms);
GetSpecifiedInstancesMethod m2 = Oms.MethodBuilder.CreateGetSpecifiedInstancesMethod(c_OMS.GetHandle(), "get", "Singleton 2", ws, new InstanceHandle[] { i_OMS2 });
GetSpecifiedInstancesMethod m2 = Oms.MethodBuilder.CreateGetSpecifiedInstancesMethod(c_OMS.GetHandle(), "get", "Singleton 2", AccessModifier.Public, true, ws, new InstanceHandle[] { i_OMS2 });
ReturnInstanceSetMethodBinding rsmb2 = m2.CreateMethodBinding(Oms);
ReturnInstanceSetMethodBinding rsmb3 = m2.CreateMethodBinding(Oms);

View File

@ -23,8 +23,8 @@ public abstract class MethodTestsBase : OmsTestsBase
{
Guid gid_r_Test_Class__has__Test_Class_2 = new Guid("{a5b67aad-e46f-4673-b339-77417396b2fe}");
Guid gid_r_Test_Class_2__for__Test_Class = new Guid("{2864dfd9-0313-4801-96bf-b9be99ea172d}");
Guid gid_r_Test_Class__has_multiple__Test_Class_2 = new Guid("{a5b67aad-e46f-4673-b339-77417396b2fe}");
Guid gid_r_Test_Class_2__multiple_for__Test_Class = new Guid("{2864dfd9-0313-4801-96bf-b9be99ea172d}");
Guid gid_r_Test_Class__has_multiple__Test_Class_2 = new Guid("{4c51e214-68c8-4e14-8e94-4e4667f05778}");
Guid gid_r_Test_Class_2__multiple_for__Test_Class = new Guid("{fcf70fa7-ebd0-438a-a534-ee31dbe3b04f}");
protected Class c_TestClass, c_TestClass2;
protected Relationship r_Test_Class__has__Test_Class_2, r_Test_Class_2__for__Test_Class;

View File

@ -0,0 +1,74 @@
using System;
using Mocha.Core.Oop;
using Mocha.Core.Oop.Methods;
namespace Mocha.Core.Tests.Oop;
public class AccessModifierTests : OmsTestsBase
{
[Test]
public void Public_Static_Method_Called_With_Default_Context_Succeeds()
{
Class c_TestClass = Oms.GetInstance<Class>(TEST_CLASS_GUID);
Class c_TestClass2 = Oms.GetInstance<Class>(TEST_CLASS2_GUID);
InstanceHandle a_Value = Oms.GetInstance(KnownAttributeGuids.Text.Value);
BuildAttributeMethod ba1 = Oms.MethodBuilder.CreateBuildAttributeMethod(c_TestClass.GetHandle(), "get", "Test Text 1", AccessModifier.Public, true, a_Value, "Test Text 1");
ReturnAttributeMethodBinding ramb1 = ba1.CreateMethodBinding(Oms);
OmsContext context = Oms.CreateContext();
string value = Oms.ExecuteReturningAttributeValue<string>(context, ramb1);
Assert.That(value, Is.EqualTo("Test Text 1"));
}
[Test]
public void Private_Static_Method_Called_Outside_Defining_Class_Fails()
{
Class c_TestClass = Oms.GetInstance<Class>(TEST_CLASS_GUID);
Class c_TestClass2 = Oms.GetInstance<Class>(TEST_CLASS2_GUID);
InstanceHandle a_Value = Oms.GetInstance(KnownAttributeGuids.Text.Value);
BuildAttributeMethod ba1 = Oms.MethodBuilder.CreateBuildAttributeMethod(c_TestClass.GetHandle(), "get", "Test Text 1", AccessModifier.Private, true, a_Value, "Test Text 1");
ReturnAttributeMethodBinding ramb1 = ba1.CreateMethodBinding(Oms);
Assert.That(delegate ()
{
OmsContext context = Oms.CreateContext();
string value = Oms.ExecuteReturningAttributeValue<string>(context, ramb1);
Assert.That(value, Is.EqualTo("Test Text 1"));
}, Throws.InstanceOf<MethodAccessException>());
}
[Test]
public void Private_Static_Method_Called_From_Another_Class_Fails()
{
Class c_TestClass = Oms.GetInstance<Class>(TEST_CLASS_GUID);
Class c_TestClass2 = Oms.GetInstance<Class>(TEST_CLASS2_GUID);
InstanceHandle a_Value = Oms.GetInstance(KnownAttributeGuids.Text.Value);
BuildAttributeMethod ba1 = Oms.MethodBuilder.CreateBuildAttributeMethod(c_TestClass.GetHandle(), "get", "Test Text 1", AccessModifier.Private, true, a_Value, "Test Text 1");
ReturnAttributeMethodBinding ramb1 = ba1.CreateMethodBinding(Oms);
InstanceHandle a1 = Oms.GetInstance(KnownAttributeGuids.Text.Value);
// InstanceHandle usesReferenceInstanceSet = Oms.MethodBuilder.CreateGetRelationshipMethod(c_TestClass.GetHandle(), r_Test_Class_1__get__Test_Class
// GetAttributeMethod ga1 = Oms.MethodBuilder.CreateGetReferencedAttributeMethod(c_TestClass2.GetHandle(), "get", "referenced Test Text 1", AccessModifier.Public, true, a1, usesReferenceInstanceSet, usesAnswerExecutableReturningAttribute, usesAccumulationFunction,usesOrderExecutableReturningAttribute);
// FIXME: find a way to refer to ^^ BA from another class
// BuildAttributeMethod ga1 = Oms.MethodBuilder.CreateGetReferencedAttributeMethod(c_TestClass2, "get", "Test Text 1 from Test Class 1", AccessModifier.Public, true, a_Value, "Test Text 1");
// ReturnAttributeMethodBinding ramb2 = ga1.CreateMethodBinding(Oms);
Assert.That(delegate ()
{
OmsContext context = Oms.CreateContext();
string value = Oms.ExecuteReturningAttributeValue<string>(context, ramb1);
Assert.That(value, Is.EqualTo("Test Text 1"));
}, Throws.InstanceOf<MethodAccessException>());
}
}

View File

@ -37,8 +37,9 @@ public class RelationshipTests : OmsTestsBase
{
InstanceHandle c_Class = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
c_TestClass = Oms.CreateClass("Test Class", TEST_CLASS_GUID);
c_TestClass2 = Oms.CreateClass("Test Class 2", TEST_CLASS2_GUID);
c_TestClass = Oms.GetInstance<Class>(TEST_CLASS_GUID);
c_TestClass2 = Oms.GetInstance<Class>(TEST_CLASS2_GUID);
c_TestClassInstance = Oms.CreateInstanceOf(c_TestClass);
c_TestClass2Instance1 = Oms.CreateInstanceOf(c_TestClass2);

View File

@ -0,0 +1,125 @@
using System.Net;
using System.Net.Http.Json;
using System.Text.Json.Nodes;
using Mocha.Core;
using NUnit.Framework.Interfaces;
namespace Mocha.Oms.Server.Tests;
public class Tests
{
private Thread ServerThread;
private Program program;
[SetUp]
public void Setup()
{
program = new Program();
program.SupportEmbeddedHosting = true;
int exitCode = program.Start();
}
[TearDown]
public void TearDown()
{
program.Stop();
}
[Test]
public async Task Tenant_List_Test()
{
Assert.That(program, Is.Not.Null);
HttpClient client = new HttpClient();
HttpResponseMessage resp = client.Send(new HttpRequestMessage(HttpMethod.Get, BuildUrl("/tenants")));
Assert.That(resp.StatusCode, Is.EqualTo(System.Net.HttpStatusCode.OK));
Assert.That(resp.Content.Headers.ContentType.ToString(), Is.EqualTo("application/json"));
string content = await resp.Content.ReadAsStringAsync();
JsonObject json = JsonNode.Parse(content) as JsonObject;
Assert.That(json["result"].ToString(), Is.EqualTo("success"));
Assert.That(json["tenants"].AsArray().Count, Is.EqualTo(1));
Assert.That(json["tenants"].AsArray()[0].ToString(), Is.EqualTo("super"));
}
[Test]
public async Task Instance_Json_Test()
{
Assert.That(program, Is.Not.Null);
InstanceHandle h = program.Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceKey k = program.Oms.GetInstanceKey(h);
Guid g = program.Oms.GetGlobalIdentifier(h);
string sz = program.Oms.GetInstanceText(h);
HttpClient client = new HttpClient();
HttpResponseMessage resp = client.Send(new HttpRequestMessage(HttpMethod.Get, BuildUrl("/tenants/super/instances/1$1")));
Assert.That(resp.StatusCode, Is.EqualTo(System.Net.HttpStatusCode.OK));
Assert.That(resp.Content.Headers.ContentType.ToString(), Is.EqualTo("application/json"));
string content = await resp.Content.ReadAsStringAsync();
JsonObject json = JsonNode.Parse(content) as JsonObject;
Assert.That(InstanceKey.Parse(json["iid"].ToString()), Is.EqualTo(k));
Assert.That(new Guid(json["globalIdentifier"].ToString()), Is.EqualTo(g));
Assert.That(json["text"].ToString(), Is.EqualTo(sz));
}
[Test, TestCase("1$1"), TestCase("1$2"), TestCase("1$3"), TestCase("4$1"), TestCase("6$3")]
public async Task Instance_Json_Test_Multi(string ik)
{
Assert.That(program, Is.Not.Null);
InstanceHandle h = program.Oms.GetInstance(InstanceKey.Parse(ik));
InstanceKey k = program.Oms.GetInstanceKey(h);
Guid g = program.Oms.GetGlobalIdentifier(h);
string sz = program.Oms.GetInstanceText(h);
HttpClient client = new HttpClient();
HttpResponseMessage resp = client.Send(new HttpRequestMessage(HttpMethod.Get, BuildUrl(String.Format("/tenants/super/instances/{0}", ik))));
Assert.That(resp.StatusCode, Is.EqualTo(System.Net.HttpStatusCode.OK));
Assert.That(resp.Content.Headers.ContentType.ToString(), Is.EqualTo("application/json"));
string content = await resp.Content.ReadAsStringAsync();
JsonObject json = JsonNode.Parse(content) as JsonObject;
Assert.That(InstanceKey.Parse(json["iid"].ToString()), Is.EqualTo(k));
Assert.That(new Guid(json["globalIdentifier"].ToString()), Is.EqualTo(g));
Assert.That(json["text"].ToString(), Is.EqualTo(sz));
}
[Test]
public async Task Element_Test()
{
Assert.That(program, Is.Not.Null);
InstanceHandle h = program.Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceKey k = program.Oms.GetInstanceKey(h);
Guid g = program.Oms.GetGlobalIdentifier(h);
string sz = program.Oms.GetInstanceText(h);
HttpClient client = new HttpClient();
HttpResponseMessage resp = client.Send(new HttpRequestMessage(HttpMethod.Get, BuildUrl("/tenants/super/instances/6$3/element")));
Assert.That(resp.StatusCode, Is.EqualTo(System.Net.HttpStatusCode.OK));
Assert.That(resp.Content.Headers.ContentType.ToString(), Is.EqualTo("application/json"));
string content = await resp.Content.ReadAsStringAsync();
JsonObject json = JsonNode.Parse(content) as JsonObject;
Assert.That(json["result"].ToString(), Is.EqualTo("success"));
Assert.That(json["value"]["widget"].ToString(), Is.EqualTo("root"));
}
protected string? BuildUrl(string v)
{
return String.Format("http://localhost:{0}{1}", program.Port, v);
}
}

View File

@ -0,0 +1 @@
global using NUnit.Framework;

View File

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../../framework-dotnet/framework-dotnet/src/lib/MBS.Core/MBS.Core.csproj" />
<ProjectReference Include="../../src/app/Mocha.Oms.Server/Mocha.Oms.Server.csproj" />
<ProjectReference Include="../../src/lib/Mocha.Core.UI.Server/Mocha.Core.UI.Server.csproj" />
<ProjectReference Include="../../src/lib/Mocha.Core/Mocha.Core.csproj" />
</ItemGroup>
</Project>

@ -1 +1 @@
Subproject commit e6b974f6514320f43228da2abdcd0ce66b3c30c1
Subproject commit 19d487683468db5b7e34d449ac105b088cef9b5a