Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed duplicate entries in schema when type has virtual members #282

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
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
35 changes: 31 additions & 4 deletions Gigya.ServiceContract/HttpService/ServiceSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public ServiceSchema(Type[] interfaces)
SetHashCode();
}

// TODO: Why?
public string Hash { get; set; }

private void SetHashCode()
Expand Down Expand Up @@ -192,10 +193,36 @@ public TypeSchema(Type type, IEnumerable<Attribute> attributes) : base(type, att

private IEnumerable<FieldSchema> GetFields(Type type)
{
var baseFields = type.BaseType != typeof(object) && type.BaseType != null ? GetFields(type.BaseType) : new FieldSchema[0];
var properties = type.GetProperties().Select(_ => new FieldSchema(_));
var fields = type.GetFields().Select(_ => new FieldSchema(_));
return baseFields.Concat(properties).Concat(fields);
var fields = new Dictionary<string, FieldSchema>();

while (type != null)
{
void add(FieldSchema fs)
{
if (fields.TryGetValue(fs.Name, out var s))
s.Attributes = s.Attributes.Union(fs.Attributes).ToArray();
else
fields.Add(fs.Name, fs);
}

void addRange(IEnumerable<FieldSchema> fss)
{
foreach (var fs in fss)
add(fs);
}

addRange(type
.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Select(x => new FieldSchema(x)));

addRange(type
.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Select(x => new FieldSchema(x)));

type = type.BaseType;
}

return fields.Values;
}

private bool IsCompositeType(Type type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ class DataParamBase
{
[Sensitive]
public int BaseField;

public virtual int VirtProp { get; set; }
}
class Data: DataParamBase
{
public string s;
public Nested n;

public override int VirtProp { get => base.VirtProp; set => base.VirtProp = value; }
}

class Nested
Expand All @@ -60,6 +64,35 @@ internal interface ITestInterface
Task<ResponseData> DoSomething(int i, double? nd, string s, [Sensitive] Data data);
}

abstract class AbctractClass
{
public abstract int PropAbstractVirtual { get; set; }
public abstract int PropAbstract { get; set; }
}

class VirtClass : AbctractClass
{
public int fldHidden;
public override int PropAbstractVirtual { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override int PropAbstract { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

public virtual int PropVirtual { get; set; }
}

class SpecificClass : VirtClass
{
// TODO: UB
public new int fldHidden;
public override int PropAbstractVirtual { get => base.PropAbstractVirtual; set => base.PropAbstractVirtual = value; }
public override int PropVirtual { get => base.PropVirtual; set => base.PropVirtual = value; }
}

internal interface IDoublesTest
{
[PublicEndpoint("test")]
Task Test(SpecificClass obj);
}

[TestFixture,Parallelizable(ParallelScope.Fixtures)]
public class ServiceSchemaTests
{
Expand Down Expand Up @@ -93,18 +126,26 @@ public void TestSerialization()
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[2].Name == "s");
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Attributes.Length == 1);
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Attributes[0].Attribute is SensitiveAttribute);
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[0].Name == nameof(DataParamBase.BaseField));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[0].Attributes[0].Attribute is SensitiveAttribute);
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[0].Type == typeof(int));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[1].Name == nameof(Data.s));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[1].Type == typeof(string));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[3].Name == nameof(DataParamBase.BaseField));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[3].Attributes[0].Attribute is SensitiveAttribute);
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[3].Type == typeof(int));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[0].Name == nameof(Data.s));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Parameters[3].Fields[0].Type == typeof(string));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Response.Type == typeof(ResponseData));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Response.Fields[0].Name == nameof(ResponseData.a));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Response.Fields[0].Type == typeof(string));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Response.Fields[1].Name == nameof(ResponseData.b));
Assert.IsTrue(schema.Interfaces[0].Methods[0].Response.Fields[1].Type == typeof(int));
}

[Test]
public void ServiceSchema_DoesntContainDuplicates()
{
ServiceSchema schema = new ServiceSchema(new[] { typeof(IDoublesTest) });

Assert.AreEqual(4, schema.Interfaces[0].Methods[0].Parameters[0].Fields.Length);
}


[Test]
public void TestUnknownAttribute()
Expand Down