Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: CI

# Trigger the workflow on pushes to main branches and pull requests
on:
push:
branches:
- main
- master
- develop
pull_request:
branches:
- main
- master
- develop

jobs:
build-and-test:
runs-on: ubuntu-latest

defaults:
run:
working-directory: csharp

steps:
# Step 1: Checkout the repository
- name: Checkout repository
uses: actions/checkout@v4

# Step 2: Setup .NET SDK
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'

# Step 3: Restore dependencies
- name: Restore dependencies
run: dotnet restore

# Step 4: Build the project
- name: Build
run: dotnet build --configuration Release --no-restore

# Step 5: Run tests
- name: Test
run: dotnet test --configuration Release --no-build --verbosity normal --collect:"XPlat Code Coverage"

# Step 6: Upload test results
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: '**/TestResults/**/*'

# Step 7: Build summary
- name: Build Summary
if: always()
run: |
echo "### Build Summary :rocket:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Status**: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY
echo "- **Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
5 changes: 5 additions & 0 deletions csharp/.changeset/fix-issue-62-review-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'Foundation.Data.Doublets.Cli': patch
---

Fixed explicit indexed numeric updates so auto-created numeric references do not steal the substitution pair, and added issue 62 regression coverage.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System;
using System.IO;
using System.Linq;
using Platform.Data.Doublets;
using Xunit;
using DoubletLink = Platform.Data.Doublets.Link<uint>;

namespace Foundation.Data.Doublets.Cli.Tests
{
public class Issue62ReviewCoverageTests
{
[Fact]
public void ExplicitNumericIdUpdate_CanBeReversedWithAnotherUpdate()
{
RunTestWithLinks(links =>
{
ProcessQuery(links, "(() ((1: 1 1)))");
AssertLink(links, 1, 1, 1);

ProcessQuery(links, "(((1: 1 1)) ((1: 2 2)))");
AssertLink(links, 1, 2, 2);

ProcessQuery(links, "(((1: 2 2)) ((1: 1 1)))");
AssertLink(links, 1, 1, 1);
});
}

[Fact]
public void NamedLink_CreateDeleteRecreate_DoesNotLeaveStaleNameMapping()
{
RunTestWithLinks(links =>
{
ProcessQuery(links, "(() ((child: father mother)))");
var firstChild = links.GetByName("child");
Assert.NotEqual(links.Constants.Null, firstChild);

ProcessQuery(links, "((child: father mother)) ()");
Assert.Equal(links.Constants.Null, links.GetByName("child"));
Assert.Null(links.GetName(firstChild));

ProcessQuery(links, "(() ((child: father mother)))");
var recreatedChild = links.GetByName("child");
Assert.NotEqual(links.Constants.Null, recreatedChild);
Assert.Equal("child", links.GetName(recreatedChild));
});
}

private static void RunTestWithLinks(Action<NamedTypesDecorator<uint>> testAction)
{
var tempDbFile = Path.GetTempFileName();
NamedTypesDecorator<uint>? links = null;
try
{
links = new NamedTypesDecorator<uint>(tempDbFile);
testAction(links);
}
finally
{
if (links != null && File.Exists(links.NamedLinksDatabaseFileName))
{
File.Delete(links.NamedLinksDatabaseFileName);
}
if (File.Exists(tempDbFile))
{
File.Delete(tempDbFile);
}
}
}

private static void ProcessQuery(NamedTypesDecorator<uint> links, string query)
{
AdvancedMixedQueryProcessor.ProcessQuery(
links,
new AdvancedMixedQueryProcessor.Options
{
Query = query,
AutoCreateMissingReferences = true
});
}

private static void AssertLink(NamedTypesDecorator<uint> links, uint index, uint source, uint target)
{
var any = links.Constants.Any;
var allLinks = links.All(new DoubletLink(any, any, any))
.Select(link => new DoubletLink(link))
.ToList();

var formattedLinks = string.Join(" ", allLinks.Select(link => $"({link.Index}: {link.Source}->{link.Target})"));
Assert.True(
allLinks.Any(link => link.Index == index && link.Source == source && link.Target == target),
$"Expected link ({index}: {source}->{target}) but found: {formattedLinks}");
}
}
}
26 changes: 24 additions & 2 deletions csharp/Foundation.Data.Doublets.Cli.Tests/PinnedTypesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,28 @@ public void Should_Create_And_Iterate_Over_Types()
}
}

[Fact]
public void Should_Terminate_Enumeration_When_Iterated_Without_Take()
{
// Arrange
var tempDbFile = Path.GetTempFileName();
try
{
using var links = new UnitedMemoryLinks<ulong>(tempDbFile);
var pinnedTypes = new PinnedTypes<ulong>(links);

// Act
var result = pinnedTypes.ToList();

// Assert
Assert.Equal(new ulong[] { 1, 2, 3, 4, 5, 6 }, result);
}
finally
{
File.Delete(tempDbFile);
}
}

[Fact]
public void Should_Validate_Existing_Links()
{
Expand Down Expand Up @@ -103,7 +125,7 @@ public void Should_Throw_Exception_For_Invalid_Link_Structure()
var allLinks = links.All();

// Act & Assert
var exception = Assert.Throws<InvalidOperationException>(() =>
var exception = Assert.Throws<UnexpectedLinkStructureException>(() =>
{
var result = new List<ulong>();
foreach (var type in pinnedTypes.Take(numberOfTypes))
Expand Down Expand Up @@ -248,4 +270,4 @@ public void Should_Destructure_PinnedTypes()
}
}
}
}
}
Loading
Loading