fix bugs, get more bugs...

This commit is contained in:
Michael Becker 2024-10-10 08:11:11 -04:00
parent c3776a0ba3
commit 32ecee29a4
11 changed files with 278 additions and 52 deletions

@ -1 +1 @@
Subproject commit a18167f13f14d45bff57f8d88cea1e9060d3fa60
Subproject commit a40a8b3685a377ab183eb0c906acf8c806b4e215

9
mocha-dotnet-new Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
# mocha-dotnet-new
# creates a new DotNet project and adds all the references needed to use
# Mocha from within .NET
dotnet new console
dotnet add reference /usr/lib/mocha/dotnet/Mocha.Core.dll
dotnet add reference /usr/lib/mocha/dotnet/MBS.Core.dll

View File

@ -64,20 +64,8 @@ public abstract class Oms
{
InitializeInternal();
AccessModifier.Private = new AccessModifier(GetInstance(KnownInstanceGuids.AccessModifiers.Private));
AccessModifier.Protected = new AccessModifier(GetInstance(KnownInstanceGuids.AccessModifiers.Protected));
AccessModifier.Public = new AccessModifier(GetInstance(KnownInstanceGuids.AccessModifiers.Public));
AccessModifier.RootA2 = new AccessModifier(GetInstance(KnownInstanceGuids.AccessModifiers.RootA2));
UpdateSyntacticSugar();
PropertyInfo[] pis = typeof(RelationalOperator).GetProperties(BindingFlags.Static | BindingFlags.Public);
foreach (PropertyInfo pi in pis)
{
PropertyInfo pi2 = typeof(KnownInstanceGuids.RelationalOperators).GetProperty(pi.Name, BindingFlags.Public | BindingFlags.Static);
Guid guid = (Guid)pi2.GetValue(null);
pi.SetValue(null, new RelationalOperator(GetInstance(guid)));
}
RegisterSystemRoutine(KnownInstanceGuids.SystemAttributeRoutines.GetRuntimeVersion, new SystemAttributeRoutine<string>(this, KnownInstanceGuids.SystemAttributeRoutines.GetRuntimeVersion, delegate (Oms oms, OmsContext context)
{
return RuntimeVersion.ToString();
@ -141,12 +129,45 @@ public abstract class Oms
public TenantHandle CurrentTenant { get; private set; }
protected abstract bool SelectTenantInternal(TenantHandle tenant);
private void UpdateSyntacticSugar()
{
if (CurrentTenant != TenantHandle.Empty)
{
// now that tenant is selected, update the syntactic sugar properties
// !!! THIS IS PROBABLY NOT THREAD-SAFE. BE VERY VERY CAREFUL !!!
UpdateSyntacticSugar<AccessModifier>(typeof(KnownInstanceGuids.AccessModifiers));
UpdateSyntacticSugar<RelationalOperator>(typeof(KnownInstanceGuids.RelationalOperators));
}
}
private void UpdateSyntacticSugar<T>(Type sourceType) where T : ConcreteInstanceWrapper
{
Type destinationType = typeof(T);
PropertyInfo[] pis = destinationType.GetProperties(BindingFlags.Static | BindingFlags.Public);
foreach (PropertyInfo pi in pis)
{
PropertyInfo pi2 = sourceType.GetProperty(pi.Name, BindingFlags.Public | BindingFlags.Static);
Guid guid = (Guid)pi2.GetValue(null);
if (TryGetInstance(guid, out InstanceHandle ih))
{
object objT = destinationType.Assembly.CreateInstance(destinationType.FullName, false, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { ih }, null, null);
pi.SetValue(null, objT);
}
else
{
}
}
}
protected abstract bool SelectTenantInternal(TenantHandle tenant);
public void SelectTenant(TenantHandle tenant)
{
if (SelectTenantInternal(tenant))
{
CurrentTenant = tenant;
UpdateSyntacticSugar();
}
}
@ -1116,6 +1137,11 @@ public abstract class Oms
{
AddLibraryReferenceInternal(library);
}
protected abstract void RemoveLibraryReferenceInternal(LibraryHandle library);
public void RemoveLibraryReference(LibraryHandle library)
{
RemoveLibraryReferenceInternal(library);
}
private Dictionary<string, LibraryHandle> _libraries = new Dictionary<string, LibraryHandle>();
/// <summary>
@ -1249,6 +1275,20 @@ public abstract class Oms
return lh;
}
private Dictionary<LibraryHandle, string> _libraryFileNames = new Dictionary<LibraryHandle, string>();
public LibraryHandle LoadLibrary(Type type, string manifestResourceStreamName)
{
Stream? st = type.Assembly.GetManifestResourceStream(manifestResourceStreamName);
if (st != null)
{
LibraryHandle lh = LoadLibrary(st);
_libraryFileNames[lh] = manifestResourceStreamName;
return lh;
}
throw new KeyNotFoundException(String.Format("manifest resource stream named '{0}' not found", manifestResourceStreamName));
}
protected abstract void InitializeLibraryInternal(LibraryHandle lh, Library lib);
public string? GetTenantName(TenantHandle tenant)

View File

@ -34,6 +34,9 @@ public class MemoryOms : Oms
private Dictionary<InstanceHandle, Dictionary<InstanceHandle, List<AttributeValue>>> _Attributes = new Dictionary<InstanceHandle, Dictionary<InstanceHandle, List<AttributeValue>>>();
private Dictionary<InstanceHandle, Dictionary<InstanceHandle, List<RelationshipValue>>> _Relationships = new Dictionary<InstanceHandle, Dictionary<InstanceHandle, List<RelationshipValue>>>();
// private Dictionary<Guid, LibraryInst_g> _libraryInst_gs = new Dictionary<Guid, LibraryInst_g>();
// private Dictionary<InstanceHandle, LibraryInst_g> _libraryInst_is = new Dictionary<InstanceHandle, LibraryInst_g>();
public Guid GetGlobalIdentifier(InstanceHandle instance)
{
if (_guidsByInstance.ContainsKey(instance))
@ -240,6 +243,16 @@ public class MemoryOms : Oms
_libraryReferences[_CurrentTenant].Add(library);
}
}
protected override void RemoveLibraryReferenceInternal(LibraryHandle library)
{
if (_libraryReferences.ContainsKey(_CurrentTenant))
{
if (_libraryReferences[_CurrentTenant].Contains(library))
{
_libraryReferences[_CurrentTenant].Remove(library);
}
}
}
protected override Guid GetGlobalIdentifierInternal(InstanceHandle instance)
{
@ -249,10 +262,19 @@ public class MemoryOms : Oms
Guid gid = _CurrentTenantData.GetGlobalIdentifier(instance);
if (gid == Guid.Empty)
{
if (_libraryInst_is.ContainsKey(instance))
if (_libraryReferences.ContainsKey(_CurrentTenant))
{
gid = _libraryInst_is[instance].GlobalIdentifier;
foreach (LibraryHandle lh in _libraryReferences[_CurrentTenant])
{
gid = _libraries[lh].GetGlobalIdentifier(instance);
if (gid != Guid.Empty)
return gid;
}
}
// if (_libraryInst_is.ContainsKey(instance))
// {
// gid = _libraryInst_is[instance].GlobalIdentifier;
// }
}
return gid;
}
@ -298,9 +320,9 @@ public class MemoryOms : Oms
{
InstanceHandle ih = lib.CreateInstance(inst.InstanceGuid);
LibraryInst_g lig = new LibraryInst_g() { GlobalIdentifier = inst.InstanceGuid, InstanceHandle = ih, SourceLibrary = lh };
_libraryInst_is[ih] = lig;
_libraryInst_gs[inst.InstanceGuid] = lig;
// LibraryInst_g lig = new LibraryInst_g() { GlobalIdentifier = inst.InstanceGuid, InstanceHandle = ih, SourceLibrary = lh };
// _libraryInst_is[ih] = lig;
// _libraryInst_gs[inst.InstanceGuid] = lig;
}
foreach (LibraryAttribute att in data.Attributes)
{
@ -328,8 +350,6 @@ public class MemoryOms : Oms
public InstanceHandle InstanceHandle;
public Guid GlobalIdentifier;
}
private Dictionary<Guid, LibraryInst_g> _libraryInst_gs = new Dictionary<Guid, LibraryInst_g>();
private Dictionary<InstanceHandle, LibraryInst_g> _libraryInst_is = new Dictionary<InstanceHandle, LibraryInst_g>();
protected override bool TryGetInstanceInternal(Guid globalIdentifier, out InstanceHandle ih)
{
@ -339,27 +359,30 @@ public class MemoryOms : Oms
bool v = _CurrentTenantData.TryGetInstance(globalIdentifier, out ih);
if (!v)
{
if (_libraryInst_gs.ContainsKey(globalIdentifier))
{
ih = _libraryInst_gs[globalIdentifier].InstanceHandle;
return true;
}
else
{
foreach (LibraryHandle lh in _libraryReferences[_CurrentTenant])
// if (_libraryInst_gs.ContainsKey(globalIdentifier))
// {
// ih = _libraryInst_gs[globalIdentifier].InstanceHandle;
// return true;
// }
// else
// {
if (_libraryReferences.ContainsKey(_CurrentTenant))
{
if (_libraries.ContainsKey(lh))
foreach (LibraryHandle lh in _libraryReferences[_CurrentTenant])
{
if (_libraries[lh].TryGetInstance(globalIdentifier, out ih))
if (_libraries.ContainsKey(lh))
{
LibraryInst_g g = new LibraryInst_g() { InstanceHandle = ih, SourceLibrary = lh, GlobalIdentifier = globalIdentifier };
_libraryInst_gs[globalIdentifier] = g;
_libraryInst_is[ih] = g;
return true;
if (_libraries[lh].TryGetInstance(globalIdentifier, out ih))
{
// LibraryInst_g g = new LibraryInst_g() { InstanceHandle = ih, SourceLibrary = lh, GlobalIdentifier = globalIdentifier };
// _libraries[lh]._libraryInst_gs[globalIdentifier] = g;
// _libraries[lh]._libraryInst_is[ih] = g;
return true;
}
}
}
}
}
// }
}
return v;
}

View File

@ -142,9 +142,11 @@ public class McxMiniLibraryPlugin : LibraryPlugin
Guid sourceInstanceGuid = guids[sourceInstanceIndex];
Guid relationshipInstanceGuid = guids[relationshipInstanceIndex];
Guid targetInstanceGuid = guids[targetInstanceIndex];
library.Relationships.Add(new LibraryRelationship(sourceInstanceGuid, relationshipInstanceGuid, targetInstanceGuid));
if (targetInstanceIndex >= 0 && targetInstanceIndex < guids.Count)
{
Guid targetInstanceGuid = guids[targetInstanceIndex];
library.Relationships.Add(new LibraryRelationship(sourceInstanceGuid, relationshipInstanceGuid, targetInstanceGuid));
}
}
r.BaseStream.Seek(stringTableSection.Offset, SeekOrigin.Begin);

View File

@ -131,4 +131,23 @@ public class BasicTests : OmsTestsBase
Oms.SetAttributeValue(irTestClassInstance, irTestTextAttribute, irTestClass);
}, Throws.ArgumentException, "Assigning something other than a System.String value to a Text Attribute MUST throw an ArgumentException.");
}
[Test]
public void TextAttribute_GetInstance_returns_same_InstanceHandle_before_and_after_LoadLibrary()
{
// remove the Web reference just for this test
// Oms.RemoveLibraryReference(lhWeb);
InstanceHandle ihTextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
// load the other library, but do not reference it yet
LibraryHandle lhWeb = Oms.LoadLibrary(typeof(LibraryLoaderTests), "Mocha.Core.Tests.Resources.net.alcetech.Mocha.Web.mcl");
// add back the reference to the other library
// Oms.AddLibraryReference(lhWeb);
InstanceHandle ihTextAttribute2 = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
Assert.That(ihTextAttribute2, Is.EqualTo(ihTextAttribute));
}
}

View File

@ -8,19 +8,10 @@ public class EmbeddedMiniOms : MemoryOms
{
base.InitializeInternal();
LibraryHandle lh = LoadLibrary(typeof(EmbeddedMiniOms), "Mocha.Core.Tests.Resources.net.alcetech.Mocha.System.mcl");
TenantHandle th = CreateTenant("super");
SelectTenant(th);
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
Stream? stream = asm.GetManifestResourceStream("Mocha.Core.Tests.Resources.net.alcetech.Mocha.System.mcl");
if (stream != null)
{
LibraryHandle lh = LoadLibrary(stream);
this.AddLibraryReference(lh);
}
else
{
throw new InvalidOperationException("Manifest resource stream not found!");
}
AddLibraryReference(lh);
}
}

View File

@ -0,0 +1,56 @@
// 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/>.
using System.Runtime.CompilerServices;
using Mocha.Core.OmsImplementations.Mini;
namespace Mocha.Core.Tests;
[TestFixture]
public class InheritanceTests : OmsTestsBase
{
[Test]
public void TextAttribute_ParentClass_is_Class()
{
InstanceHandle ihTextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
InstanceHandle ihClass = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle ihParentClass = Oms.GetParentClass(ihTextAttribute);
Assert.That(ihParentClass, Is.EqualTo(ihClass));
}
[Test]
public void TextAttribute_ParentClass_is_Class_when_multiple_libraries_are_referenced()
{
// add a reference to the other library
LibraryHandle lhWeb = Oms.LoadLibrary(typeof(LibraryLoaderTests), "Mocha.Core.Tests.Resources.net.alcetech.Mocha.Web.mcl");
Oms.AddLibraryReference(lhWeb);
// ??? this is weird. the moment we add that library reference, this suddenly breaks
// 2024-10-09 08:24 beckermj - this is why we have this unit test
// the reason is that the inst for guid {c2f36542...} is NOT the same instance handle as the originally registered one
// we need to fix GetInstance so that it returns the same InstanceHandle for the same GUID
// ... or maybe get rid of InstanceHandles entirely
InstanceHandle ihTextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
InstanceHandle ihClass = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle ihParentClass = Oms.GetParentClass(ihTextAttribute);
Assert.That(ihParentClass, Is.EqualTo(ihClass));
}
}

View File

@ -0,0 +1,84 @@
// 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/>.
using System.Runtime.CompilerServices;
using Mocha.Core.OmsImplementations.Mini;
namespace Mocha.Core.Tests;
[TestFixture]
public class LibraryLoaderTests : OmsTestsBase
{
private LibraryHandle lhWeb;
protected override void AfterSetup()
{
base.AfterSetup();
// add a reference to the other library
lhWeb = Oms.LoadLibrary(typeof(LibraryLoaderTests), "Mocha.Core.Tests.Resources.net.alcetech.Mocha.Web.mcl");
Oms.AddLibraryReference(lhWeb);
}
[Test]
public void TextAttribute_GetInstance_returns_same_InstanceHandle_before_and_after_AddLibraryReference()
{
// remove the Web reference just for this test
Oms.RemoveLibraryReference(lhWeb);
InstanceHandle ihTextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
// add back the reference to the other library
Oms.AddLibraryReference(lhWeb);
InstanceHandle ihTextAttribute2 = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
Assert.That(ihTextAttribute, Is.EqualTo(ihTextAttribute2));
}
[Test]
public void Class_referenced_from_One_library_Accessible_from_Another()
{
// First we make sure that Class (defined in Mocha.System, which we are known to have) loads
InstanceHandle ihClass = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
Assert.That(ihClass, Is.Not.EqualTo(InstanceHandle.Empty));
// Now we try loading Mocha.Web::`Route`, if this fails, we fail our test
bool succeeded = Oms.TryGetInstance(KnownInstanceGuids.Classes.Route, out InstanceHandle ihRoute);
Assert.That(succeeded, Is.True);
Assert.That(ihRoute, Is.Not.EqualTo(InstanceHandle.Empty));
}
[Test]
public void Parent_Class_referenced_from_One_library_Accessible_from_Another()
{
// First we make sure that Class (defined in Mocha.System, which we are known to have) loads
InstanceHandle ihClass = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
Assert.That(ihClass, Is.Not.EqualTo(InstanceHandle.Empty));
// Now we try loading Mocha.Web::`Route`, if this fails, we fail our test
bool succeeded = Oms.TryGetInstance(KnownInstanceGuids.Classes.Route, out InstanceHandle ihRoute);
Assert.That(succeeded, Is.True);
Assert.That(ihRoute, Is.Not.EqualTo(InstanceHandle.Empty));
// `Route` parent class should be `Class`
InstanceHandle ihPClass = Oms.GetParentClass(ihRoute);
Assert.That(ihPClass, Is.EqualTo(ihClass));
}
}

View File

@ -44,6 +44,7 @@
<ItemGroup>
<EmbeddedResource Include="Resources\net.alcetech.Mocha.System.mcl" />
<EmbeddedResource Include="Resources\net.alcetech.Mocha.Web.mcl" />
</ItemGroup>
</Project>

View File

@ -0,0 +1 @@
../../../../mocha-common/mocha-common/output/net.alcetech.Mocha.Web.mcl