Skip to content

Commit b352bb6

Browse files
authored
Merge pull request #50 from IvanMurzak/fix/serialization-issue
fix: Tuple serialization
2 parents 627d085 + d146d4e commit b352bb6

6 files changed

Lines changed: 1349 additions & 9 deletions

File tree

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
using System.Linq;
2+
using System.Reflection;
3+
using System.Runtime.CompilerServices;
4+
using com.IvanMurzak.ReflectorNet.Converter;
5+
using com.IvanMurzak.ReflectorNet.Model;
6+
using com.IvanMurzak.ReflectorNet.Utils;
7+
using Xunit.Abstractions;
8+
9+
namespace com.IvanMurzak.ReflectorNet.Tests.ReflectorTests
10+
{
11+
public class ValueTuplePropertiesTests : BaseTest
12+
{
13+
public ValueTuplePropertiesTests(ITestOutputHelper output) : base(output) { }
14+
15+
[Fact]
16+
public void ListValueTupleProperties()
17+
{
18+
// Arrange
19+
var tupleType = typeof((int, bool));
20+
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
21+
22+
// Act
23+
var allProperties = tupleType.GetProperties(flags);
24+
25+
_output.WriteLine($"Type: {tupleType.FullName}");
26+
_output.WriteLine($"Properties found: {allProperties.Length}");
27+
_output.WriteLine("");
28+
29+
foreach (var prop in allProperties)
30+
{
31+
_output.WriteLine($"Property: {prop.Name}");
32+
_output.WriteLine($" DeclaringType: {prop.DeclaringType?.FullName}");
33+
_output.WriteLine($" PropertyType: {prop.PropertyType.FullName}");
34+
_output.WriteLine($" CanRead: {prop.CanRead}");
35+
_output.WriteLine($" CanWrite: {prop.CanWrite}");
36+
_output.WriteLine($" GetIndexParameters().Length: {prop.GetIndexParameters().Length}");
37+
_output.WriteLine("");
38+
}
39+
}
40+
41+
[Fact]
42+
public void ListValueTupleFields()
43+
{
44+
// Arrange
45+
var tupleType = typeof((int, bool));
46+
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
47+
48+
// Act
49+
var allFields = tupleType.GetFields(flags);
50+
51+
_output.WriteLine($"Type: {tupleType.FullName}");
52+
_output.WriteLine($"Fields found: {allFields.Length}");
53+
_output.WriteLine("");
54+
55+
foreach (var field in allFields)
56+
{
57+
_output.WriteLine($"Field: {field.Name}");
58+
_output.WriteLine($" DeclaringType: {field.DeclaringType?.FullName}");
59+
_output.WriteLine($" FieldType: {field.FieldType.FullName}");
60+
_output.WriteLine($" IsPublic: {field.IsPublic}");
61+
_output.WriteLine("");
62+
}
63+
}
64+
65+
[Fact]
66+
public void ListValueTupleInterfaceProperties()
67+
{
68+
// Arrange
69+
var tupleType = typeof((int, bool));
70+
71+
_output.WriteLine($"Type: {tupleType.FullName}");
72+
_output.WriteLine($"Implemented interfaces:");
73+
74+
foreach (var _interface in tupleType.GetInterfaces())
75+
{
76+
_output.WriteLine($" - {_interface.FullName}");
77+
78+
var interfaceMap = tupleType.GetInterfaceMap(_interface);
79+
_output.WriteLine($" Interface methods:");
80+
for (int i = 0; i < interfaceMap.InterfaceMethods.Length; i++)
81+
{
82+
_output.WriteLine($" {interfaceMap.InterfaceMethods[i].Name} -> {interfaceMap.TargetMethods[i].Name}");
83+
}
84+
}
85+
}
86+
87+
[Fact]
88+
public void Serialize_ValueTuple_WithLogger_ShowsAllAttempts()
89+
{
90+
// Arrange
91+
var reflector = new Reflector();
92+
var tuple = (42, true);
93+
var logs = new Logs();
94+
var logger = new StringBuilderLogger();
95+
96+
// Act
97+
var serialized = reflector.Serialize(tuple, logs: logs, logger: logger);
98+
99+
_output.WriteLine("System logs:");
100+
_output.WriteLine(logger.ToString());
101+
_output.WriteLine("");
102+
_output.WriteLine("AI logs:");
103+
_output.WriteLine(logs.ToString());
104+
_output.WriteLine("");
105+
_output.WriteLine($"Serialized: {serialized.ToJson(reflector)}");
106+
107+
// Assert
108+
Assert.NotNull(serialized);
109+
}
110+
111+
[Fact]
112+
public void FilterIndexerProperties()
113+
{
114+
// This test verifies that indexer properties are properly filtered
115+
var tupleType = typeof((int, bool));
116+
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
117+
118+
var allProperties = tupleType.GetProperties(flags);
119+
var nonIndexerProperties = allProperties.Where(p => p.GetIndexParameters().Length == 0).ToList();
120+
121+
_output.WriteLine($"All properties: {allProperties.Length}");
122+
_output.WriteLine($"Non-indexer properties: {nonIndexerProperties.Count}");
123+
124+
foreach (var prop in nonIndexerProperties)
125+
{
126+
_output.WriteLine($"Non-indexer property: {prop.Name} ({prop.PropertyType.Name})");
127+
}
128+
129+
// All ValueTuple properties should be fields, not properties
130+
// If there are indexer properties, they should be filtered out
131+
foreach (var prop in allProperties.Where(p => p.GetIndexParameters().Length > 0))
132+
{
133+
_output.WriteLine($"Indexer property found: {prop.Name} - THIS SHOULD BE FILTERED");
134+
}
135+
}
136+
137+
[Fact]
138+
public void TupleReflectionConverter_FiltersIndexerProperties()
139+
{
140+
// Arrange
141+
var reflector = new Reflector();
142+
var tupleType = typeof((int, bool));
143+
var converter = reflector.Converters.GetConverter(tupleType);
144+
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
145+
146+
Assert.NotNull(converter);
147+
148+
// Act
149+
var serializableProperties = converter.GetSerializableProperties(reflector, tupleType, flags);
150+
151+
// Assert - No indexer properties should be returned
152+
Assert.NotNull(serializableProperties);
153+
var propList = serializableProperties.ToList();
154+
155+
_output.WriteLine($"Serializable properties count: {propList.Count}");
156+
foreach (var prop in propList)
157+
{
158+
_output.WriteLine($" Property: {prop.Name} ({prop.PropertyType.Name})");
159+
Assert.Empty(prop.GetIndexParameters()); // No indexers
160+
}
161+
162+
// Should not contain the ITuple.Item indexer
163+
Assert.DoesNotContain(propList, p => p.Name.Contains("ITuple.Item"));
164+
}
165+
166+
[Fact]
167+
public void TupleReflectionConverter_ImplementsITuple()
168+
{
169+
// Verify that ValueTuple implements ITuple
170+
var tupleType = typeof((int, bool));
171+
172+
Assert.True(typeof(ITuple).IsAssignableFrom(tupleType));
173+
_output.WriteLine($"ValueTuple<int, bool> implements ITuple: {typeof(ITuple).IsAssignableFrom(tupleType)}");
174+
}
175+
}
176+
}

0 commit comments

Comments
 (0)