mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-04 02:31:36 +00:00
test(csharp-scope): integration fixtures for Units 6c/6d/6e runtime behavior
Close the integration-coverage gap flagged in the production-readiness
review. Units 6c (collection-accessor unwrap), 6d (using-static member
injection), and 6e (overload disambig + interface dispatch) previously
had only hook-level unit tests; the end-to-end wiring was exercised
only by the parity harness.
Three minimal fixtures + four new it() blocks:
* csharp-collection-accessor — RenderAll iterates
Dictionary<string, Widget>.Values and calls .Render(); asserts the
CALLS edge lands on Widget.Render.
* csharp-using-static — `using static Helpers.MathUtils;` makes
Square(int) a free-callable in the consumer; asserts the CALLS
edge lands on MathUtils.Square.
* csharp-overload-interface — three assertions:
1. Run → Log binds to the 2-arg overload only (arity narrowing);
verified via target Method node's parameterTypes.length === 2.
2. Run → Greet emits one primary edge to IGreeter.Greet plus two
reason='interface-dispatch' siblings to En/FrGreeter.Greet.
3. Interface-dispatch fan-out excludes the primary target.
Verified:
- csharp integration 189/189 passing
This commit is contained in:
parent
952350801c
commit
fed95a9ef4
13 changed files with 204 additions and 0 deletions
5
gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/CollectionAccessor.csproj
vendored
Normal file
5
gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/CollectionAccessor.csproj
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
8
gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Models/Widget.cs
vendored
Normal file
8
gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Models/Widget.cs
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
namespace Models;
|
||||
|
||||
public class Widget
|
||||
{
|
||||
public void Render()
|
||||
{
|
||||
}
|
||||
}
|
||||
17
gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Services/Renderer.cs
vendored
Normal file
17
gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Services/Renderer.cs
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
using Models;
|
||||
|
||||
namespace Services;
|
||||
|
||||
public class Renderer
|
||||
{
|
||||
private Dictionary<string, Widget> _widgets = new();
|
||||
|
||||
public void RenderAll()
|
||||
{
|
||||
foreach (var w in _widgets.Values)
|
||||
{
|
||||
w.Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
14
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Caller.cs
vendored
Normal file
14
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Caller.cs
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using Greeting;
|
||||
|
||||
namespace App;
|
||||
|
||||
public class Caller
|
||||
{
|
||||
private Logger _logger = new();
|
||||
|
||||
public string Run(IGreeter greeter)
|
||||
{
|
||||
_logger.Log("starting", 1);
|
||||
return greeter.Greet();
|
||||
}
|
||||
}
|
||||
12
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Logger.cs
vendored
Normal file
12
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Logger.cs
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
namespace App;
|
||||
|
||||
public class Logger
|
||||
{
|
||||
public void Log(string message)
|
||||
{
|
||||
}
|
||||
|
||||
public void Log(string message, int level)
|
||||
{
|
||||
}
|
||||
}
|
||||
9
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/EnGreeter.cs
vendored
Normal file
9
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/EnGreeter.cs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
namespace Greeting;
|
||||
|
||||
public class EnGreeter : IGreeter
|
||||
{
|
||||
public string Greet()
|
||||
{
|
||||
return "hello";
|
||||
}
|
||||
}
|
||||
9
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/FrGreeter.cs
vendored
Normal file
9
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/FrGreeter.cs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
namespace Greeting;
|
||||
|
||||
public class FrGreeter : IGreeter
|
||||
{
|
||||
public string Greet()
|
||||
{
|
||||
return "bonjour";
|
||||
}
|
||||
}
|
||||
6
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/IGreeter.cs
vendored
Normal file
6
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/IGreeter.cs
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
namespace Greeting;
|
||||
|
||||
public interface IGreeter
|
||||
{
|
||||
string Greet();
|
||||
}
|
||||
5
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/OverloadInterface.csproj
vendored
Normal file
5
gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/OverloadInterface.csproj
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
11
gitnexus/test/fixtures/lang-resolution/csharp-using-static/App/Calculator.cs
vendored
Normal file
11
gitnexus/test/fixtures/lang-resolution/csharp-using-static/App/Calculator.cs
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using static Helpers.MathUtils;
|
||||
|
||||
namespace App;
|
||||
|
||||
public class Calculator
|
||||
{
|
||||
public int Compute(int value)
|
||||
{
|
||||
return Square(value);
|
||||
}
|
||||
}
|
||||
9
gitnexus/test/fixtures/lang-resolution/csharp-using-static/Helpers/MathUtils.cs
vendored
Normal file
9
gitnexus/test/fixtures/lang-resolution/csharp-using-static/Helpers/MathUtils.cs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
namespace Helpers;
|
||||
|
||||
public static class MathUtils
|
||||
{
|
||||
public static int Square(int x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
}
|
||||
5
gitnexus/test/fixtures/lang-resolution/csharp-using-static/UsingStatic.csproj
vendored
Normal file
5
gitnexus/test/fixtures/lang-resolution/csharp-using-static/UsingStatic.csproj
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -197,6 +197,100 @@ describe('C# member-call resolution', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Collection-accessor unwrap (Unit 6c): data.Values on Dictionary<K,V>
|
||||
// resolves to the value type's class.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('C# collection-accessor unwrap', () => {
|
||||
let result: PipelineResult;
|
||||
|
||||
beforeAll(async () => {
|
||||
result = await runPipelineFromRepo(path.join(FIXTURES, 'csharp-collection-accessor'), () => {});
|
||||
}, 60000);
|
||||
|
||||
it('resolves RenderAll → Render through Dictionary<string, Widget>.Values', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const renderCall = calls.find((c) => c.source === 'RenderAll' && c.target === 'Render');
|
||||
expect(renderCall).toBeDefined();
|
||||
expect(renderCall!.targetFilePath).toBe('Models/Widget.cs');
|
||||
expect(['import-resolved', 'global']).toContain(renderCall!.rel.reason);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// using-static member injection (Unit 6d): `using static X.Y;` exposes Y's
|
||||
// static methods as free-callables in the consumer.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('C# using static member injection', () => {
|
||||
let result: PipelineResult;
|
||||
|
||||
beforeAll(async () => {
|
||||
result = await runPipelineFromRepo(path.join(FIXTURES, 'csharp-using-static'), () => {});
|
||||
}, 60000);
|
||||
|
||||
it('resolves Compute → Square via `using static Helpers.MathUtils;`', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const sqCall = calls.find((c) => c.source === 'Compute' && c.target === 'Square');
|
||||
expect(sqCall).toBeDefined();
|
||||
expect(sqCall!.targetFilePath).toBe('Helpers/MathUtils.cs');
|
||||
expect(['import-resolved', 'global']).toContain(sqCall!.rel.reason);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Overload disambiguation + interface dispatch (Unit 6e).
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('C# overload disambiguation and interface dispatch', () => {
|
||||
let result: PipelineResult;
|
||||
|
||||
beforeAll(async () => {
|
||||
result = await runPipelineFromRepo(path.join(FIXTURES, 'csharp-overload-interface'), () => {});
|
||||
}, 60000);
|
||||
|
||||
it('Run → Log resolves to the 2-arg overload (arity narrowing)', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const logCalls = calls.filter((c) => c.source === 'Run' && c.target === 'Log');
|
||||
// With collapse-by-caller-target enabled and arity narrowing, Run
|
||||
// should bind to the 2-arg overload only — not the 1-arg sibling.
|
||||
expect(logCalls.length).toBe(1);
|
||||
// Verify targetId points to the 2-arg overload by checking the
|
||||
// target Method node's parameterTypes length.
|
||||
const target = result.graph.getNode(logCalls[0].rel.targetId);
|
||||
expect(target).toBeDefined();
|
||||
const parameterTypes = (target!.properties as { parameterTypes?: string[] }).parameterTypes;
|
||||
expect(parameterTypes).toBeDefined();
|
||||
expect(parameterTypes!.length).toBe(2);
|
||||
});
|
||||
|
||||
it('Run → Greet emits primary edge to IGreeter.Greet plus interface-dispatch siblings', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const greetCalls = calls.filter((c) => c.source === 'Run' && c.target === 'Greet');
|
||||
// One primary edge (IGreeter.Greet) + two interface-dispatch edges
|
||||
// (EnGreeter.Greet, FrGreeter.Greet).
|
||||
expect(greetCalls.length).toBe(3);
|
||||
|
||||
const primaries = greetCalls.filter((c) => c.rel.reason !== 'interface-dispatch');
|
||||
expect(primaries.length).toBe(1);
|
||||
expect(primaries[0].targetFilePath).toBe('Greeting/IGreeter.cs');
|
||||
|
||||
const fanout = greetCalls.filter((c) => c.rel.reason === 'interface-dispatch');
|
||||
expect(fanout.length).toBe(2);
|
||||
const fanoutPaths = fanout.map((c) => c.targetFilePath).sort();
|
||||
expect(fanoutPaths).toEqual(['Greeting/EnGreeter.cs', 'Greeting/FrGreeter.cs']);
|
||||
});
|
||||
|
||||
it('interface-dispatch fan-out excludes the primary target (no self-edge)', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const fanout = calls.filter((c) => c.source === 'Run' && c.rel.reason === 'interface-dispatch');
|
||||
for (const edge of fanout) {
|
||||
expect(edge.targetFilePath).not.toBe('Greeting/IGreeter.cs');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Primary constructor resolution: class User(string name, int age) { }
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue