THRIFT-5216 generate DeepCopy methods
Client: netstd
Patch: Jens Geyer
This closes #2155
diff --git a/lib/netstd/Makefile.am b/lib/netstd/Makefile.am
index 503a176..abb680c 100644
--- a/lib/netstd/Makefile.am
+++ b/lib/netstd/Makefile.am
@@ -23,12 +23,21 @@
$(DOTNETCORE) build -c Release
check-local:
+ $(DOTNETCORE) test Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
$(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj
$(DOTNETCORE) test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
clean-local:
$(RM) -r Thrift/bin
$(RM) -r Thrift/obj
+ $(RM) -r Benchmarks/Thrift.Benchmarks/bin
+ $(RM) -r Benchmarks/Thrift.Benchmarks/obj
+ $(RM) -r Tests/Thrift.Tests/bin
+ $(RM) -r Tests/Thrift.Tests/obj
+ $(RM) -r Tests/Thrift.IntegrationTests/bin
+ $(RM) -r Tests/Thrift.IntegrationTests/obj
+ $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/bin
+ $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/obj
EXTRA_DIST = \
README.md \
@@ -36,6 +45,7 @@
Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj \
Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj \
Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs \
+ Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift \
Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift \
Tests/Thrift.Tests/Thrift.Tests.csproj \
Tests/Thrift.Tests/Protocols \
@@ -55,4 +65,4 @@
build.sh \
runtests.cmd \
runtests.sh
-
\ No newline at end of file
+
diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
index d2db348..1938ddc 100644
--- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
+++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
@@ -42,13 +42,16 @@
</Exec>
<Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -gen netstd:wcf,union,serial -r ./CassandraTest.thrift" />
<Exec Condition="Exists('thrift')" Command="thrift -gen netstd:wcf,union,serial -r ./CassandraTest.thrift" />
- <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -gen netstd:wcf,union,serial -r ./CassandraTest.thrift" />
+ <Exec Condition="Exists('$(ProjectDir)/../../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../../compiler/cpp/thrift -gen netstd:wcf,union,serial -r ./CassandraTest.thrift" />
+ <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -gen netstd:wcf,union,serial -r ./optional_required_default.thrift" />
+ <Exec Condition="Exists('thrift')" Command="thrift -gen netstd:wcf,union,serial -r ./optional_required_default.thrift" />
+ <Exec Condition="Exists('$(ProjectDir)/../../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../../compiler/cpp/thrift -gen netstd:wcf,union,serial -r ./optional_required_default.thrift" />
<Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -gen netstd:wcf,union,serial -r ./../../../../test/ThriftTest.thrift" />
<Exec Condition="Exists('thrift')" Command="thrift -gen netstd:wcf,union,serial -r ./../../../../test/ThriftTest.thrift" />
- <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -gen netstd:wcf,union,serial -r ./../../../../test/ThriftTest.thrift" />
+ <Exec Condition="Exists('$(ProjectDir)/../../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../../compiler/cpp/thrift -gen netstd:wcf,union,serial -r ./../../../../test/ThriftTest.thrift" />
<Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -gen netstd:wcf,union,serial -r ./../../../../contrib/fb303/if/fb303.thrift" />
<Exec Condition="Exists('thrift')" Command="thrift -gen netstd:wcf,union,serial -r ./../../../../contrib/fb303/if/fb303.thrift" />
- <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -gen netstd:wcf,union,serial -r ./../../../../contrib/fb303/if/fb303.thrift" />
+ <Exec Condition="Exists('$(ProjectDir)/../../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../../compiler/cpp/thrift -gen netstd:wcf,union,serial -r ./../../../../contrib/fb303/if/fb303.thrift" />
</Target>
</Project>
diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift
new file mode 100644
index 0000000..1f6c7ee
--- /dev/null
+++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift
@@ -0,0 +1,143 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+// Testcase for THRIFT-5216 generate DeepCopy methods
+
+namespace netstd OptReqDefTest
+
+enum Distance
+{
+ foo = 0,
+ bar = 1,
+ baz = 2
+}
+
+struct RaceDetails
+{
+ // this is really the max field index used here, intentionally placed at the beginning
+ 666: required Distance triplesix
+
+ // without default values
+
+ 1: optional Distance opt_one
+ 2: optional double opt_two
+ 3: optional i16 opt_three
+ 4: optional string opt_four
+ 5: optional binary opt_five
+ 6: optional list<i32> opt_six
+ 7: optional set<i64> opt_seven
+ 8: optional map<i8,i16> opt_eight
+
+ 11: required Distance req_one
+ 12: required double req_two
+ 13: required i16 req_three
+ 14: required string req_four
+ 15: required binary req_five
+ 16: required list<i32> req_six
+ 17: required set<i64> req_seven
+ 18: required map<i8,i16> req_eight
+
+ 21: Distance def_one
+ 22: double def_two
+ 23: i16 def_three
+ 24: string def_four
+ 25: binary def_five
+ 26: list<i32> def_six
+ 27: set<i64> def_seven
+ 28: map<i8,i16> def_eight
+
+ // having default values
+
+ 31: optional Distance opt_one_with_value = Distance.bar
+ 32: optional double opt_two_with_value = 2.22
+ 33: optional i16 opt_three_with_value = 3
+ 34: optional string opt_four_with_value = "four"
+ 35: optional binary opt_five_with_value = "five\t"
+ 36: optional list<i32> opt_six_with_value = [6]
+ 37: optional set<i64> opt_seven_with_value = [7]
+ 38: optional map<i8,i16> opt_eight_with_value = { 8 : 8 }
+
+ 41: required Distance req_one_with_value = Distance.bar
+ 42: required double req_two_with_value = 2.22
+ 43: required i16 req_three_with_value = 3
+ 44: required string req_four_with_value = "four"
+ 45: required binary req_five_with_value = "five"
+ 46: required list<i32> req_six_with_value = [6]
+ 47: required set<i64> req_seven_with_value = [7]
+ 48: required map<i8,i16> req_eight_with_value = { 8 : 8 }
+
+ 51: Distance def_one_with_value = Distance.bar
+ 52: double def_two_with_value = 2.22
+ 53: i16 def_three_with_value = 3
+ 54: string def_four_with_value = "four"
+ 55: binary def_five_with_value = "five"
+ 56: list<i32> def_six_with_value = [6]
+ 57: set<i64> def_seven_with_value = [7]
+ 58: map<i8,i16> def_eight_with_value = { 8 : 8 }
+
+ 90: optional bool last_of_the_mohicans
+
+ // some more complicated ones, including recursion
+
+ 300: required list<Distance> far_list
+ 301: optional set<Distance> far_set
+ 302: map<Distance,Distance> far_map
+
+ 310: required set<list<Distance>> far_set_list
+ 311: optional list<map<i8,set<Distance>>> far_list_map_set
+ 312: map<Distance,RDs> far_map_dist_to_rds
+
+ 320: required RaceDetails req_nested
+ 321: optional RaceDetails opt_nested
+ 322: RaceDetails def_nested
+
+ 330: required jack req_union
+ 331: optional jack opt_union
+ 332: jack def_union
+}
+
+union jack {
+ 1: list<RaceDetails2> stars
+ 2: list<RDs> stripes
+
+ 310: set<list<Distance>> far_set_list
+ 311: list<map<i8,set<Distance>>> far_list_map_set
+ 312: map<Distance,RDs> far_map_dist_to_rds
+
+ 320: jack nested_union
+ 321: RaceDetails nested_struct
+
+ 401: optional Distance opt_one
+ 402: optional double opt_two
+ 403: optional i16 opt_three
+ 404: optional string opt_four
+ 405: optional binary opt_five
+ 406: optional list<i32> opt_six
+ 407: optional set<i64> opt_seven
+ 408: optional map<i8,i16> opt_eight
+}
+
+typedef RaceDetails RaceDetails2
+typedef list<RaceDetails> RDs
+
+exception CrashBoomBang {
+ 1 : i32 MyErrorCode
+}
+
+service foobar {
+ set<set<set<Distance>>> DoItNow( 1 : list<list<list<RaceDetails>>> rd, 2: i32 mitDefault = 42) throws (1: CrashBoomBang cbb)
+}
+
diff --git a/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs b/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs
index 1be99b4..061032a 100644
--- a/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs
+++ b/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
@@ -17,6 +17,8 @@
using System;
using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography.Xml;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Thrift.Collections;
@@ -30,54 +32,209 @@
//TODO: Add tests for IEnumerable with objects and primitive values inside
[TestMethod]
- public void TCollection_Equals_Primitive_Test()
+ public void TCollection_List_Equals_Primitive_Test()
{
var collection1 = new List<int> {1,2,3};
var collection2 = new List<int> {1,2,3};
-
- var result = TCollections.Equals(collection1, collection2);
-
- Assert.IsTrue(result);
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
}
[TestMethod]
- public void TCollection_Equals_Primitive_Different_Test()
+ public void TCollection_List_Equals_Primitive_Different_Test()
{
var collection1 = new List<int> { 1, 2, 3 };
var collection2 = new List<int> { 1, 2 };
+ Assert.IsFalse(TCollections.Equals(collection1, collection2));
+ Assert.IsFalse(collection1.SequenceEqual(collection2));
- var result = TCollections.Equals(collection1, collection2);
-
- Assert.IsFalse(result);
+ collection2.Add(4);
+ Assert.IsFalse(TCollections.Equals(collection1, collection2));
+ Assert.IsFalse(collection1.SequenceEqual(collection2));
}
[TestMethod]
- public void TCollection_Equals_Objects_Test()
+ public void TCollection_List_Equals_Objects_Test()
{
var collection1 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
var collection2 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
-
- var result = TCollections.Equals(collection1, collection2);
-
- // references to different collections
- Assert.IsFalse(result);
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
}
[TestMethod]
- public void TCollection_Equals_OneAndTheSameObject_Test()
+ public void TCollection_List_List_Equals_Objects_Test()
+ {
+ var collection1 = new List<List<ExampleClass>> { new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } };
+ var collection2 = new List<List<ExampleClass>> { new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } };
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual()
+ }
+
+ [TestMethod]
+ public void TCollection_List_Equals_OneAndTheSameObject_Test()
{
var collection1 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
var collection2 = collection1;
-
- var result = TCollections.Equals(collection1, collection2);
-
- // references to one and the same collection
- Assert.IsTrue(result);
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
}
+ [TestMethod]
+ public void TCollection_Set_Equals_Primitive_Test()
+ {
+ var collection1 = new THashSet<int> {1,2,3};
+ var collection2 = new THashSet<int> {1,2,3};
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
+ }
+
+ [TestMethod]
+ public void TCollection_Set_Equals_Primitive_Different_Test()
+ {
+ var collection1 = new THashSet<int> { 1, 2, 3 };
+ var collection2 = new THashSet<int> { 1, 2 };
+ Assert.IsFalse(TCollections.Equals(collection1, collection2));
+ Assert.IsFalse(collection1.SequenceEqual(collection2));
+
+ collection2.Add(4);
+ Assert.IsFalse(TCollections.Equals(collection1, collection2));
+ Assert.IsFalse(collection1.SequenceEqual(collection2));
+ }
+
+ [TestMethod]
+ public void TCollection_Set_Equals_Objects_Test()
+ {
+ var collection1 = new THashSet<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+ var collection2 = new THashSet<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
+ }
+
+ [TestMethod]
+ public void TCollection_Set_Set_Equals_Objects_Test()
+ {
+ var collection1 = new THashSet<THashSet<ExampleClass>> { new THashSet<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } };
+ var collection2 = new THashSet<THashSet<ExampleClass>> { new THashSet<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } };
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual()
+ }
+
+ [TestMethod]
+ public void TCollection_Set_Equals_OneAndTheSameObject_Test()
+ {
+ var collection1 = new THashSet<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+ var collection2 = collection1; // references to one and the same collection
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
+ }
+
+
+ [TestMethod]
+ public void TCollection_Map_Equals_Primitive_Test()
+ {
+ var collection1 = new Dictionary<int, int> { [1] = 1, [2] = 2, [3] = 3 };
+ var collection2 = new Dictionary<int, int> { [1] = 1, [2] = 2, [3] = 3 };
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
+ }
+
+ [TestMethod]
+ public void TCollection_Map_Equals_Primitive_Different_Test()
+ {
+ var collection1 = new Dictionary<int, int> { [1] = 1, [2] = 2, [3] = 3 };
+ var collection2 = new Dictionary<int, int> { [1] = 1, [2] = 2 };
+ Assert.IsFalse(TCollections.Equals(collection1, collection2));
+ Assert.IsFalse(collection1.SequenceEqual(collection2));
+
+ collection2[3] = 3;
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
+
+ collection2[3] = 4;
+ Assert.IsFalse(TCollections.Equals(collection1, collection2));
+ }
+
+ [TestMethod]
+ public void TCollection_Map_Equals_Objects_Test()
+ {
+ var collection1 = new Dictionary<int, ExampleClass>
+ {
+ [1] = new ExampleClass { X = 1 },
+ [-1] = new ExampleClass { X = 2 }
+ };
+ var collection2 = new Dictionary<int, ExampleClass>
+ {
+ [1] = new ExampleClass { X = 1 },
+ [-1] = new ExampleClass { X = 2 }
+ };
+
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
+ }
+
+ [TestMethod]
+ public void TCollection_Map_Map_Equals_Objects_Test()
+ {
+ var collection1 = new Dictionary<int, Dictionary<int, ExampleClass>>
+ {
+ [0] = new Dictionary<int, ExampleClass>
+ {
+ [1] = new ExampleClass { X = 1 },
+ [-1] = new ExampleClass { X = 2 }
+ }
+ };
+ var collection2 = new Dictionary<int, Dictionary<int, ExampleClass>>
+ {
+ [0] = new Dictionary<int, ExampleClass>
+ {
+ [1] = new ExampleClass { X = 1 },
+ [-1] = new ExampleClass { X = 2 }
+ }
+ };
+
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual()
+ }
+
+ [TestMethod]
+ public void TCollection_Map_Equals_OneAndTheSameObject_Test()
+ {
+ var collection1 = new Dictionary<int, ExampleClass>
+ {
+ [1] = new ExampleClass { X = 1 },
+ [-1] = new ExampleClass { X = 2 }
+ };
+ var collection2 = collection1;
+ Assert.IsTrue(TCollections.Equals(collection1, collection2));
+ Assert.IsTrue(collection1.SequenceEqual(collection2));
+ }
+
+
private class ExampleClass
{
public int X { get; set; }
+
+ // all Thrift-generated classes override Equals(), we do just the same
+ public override bool Equals(object that)
+ {
+ if (!(that is ExampleClass other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+
+ return this.X == other.X;
+ }
+
+ // overriding Equals() requires GetHashCode() as well
+ public override int GetHashCode()
+ {
+ int hashcode = 157;
+ unchecked
+ {
+ hashcode = (hashcode * 397) + X.GetHashCode();
+ }
+ return hashcode;
+ }
}
}
}
+
diff --git a/lib/netstd/Tests/Thrift.Tests/DataModel/DeepCopy.cs b/lib/netstd/Tests/Thrift.Tests/DataModel/DeepCopy.cs
new file mode 100644
index 0000000..f717b4d
--- /dev/null
+++ b/lib/netstd/Tests/Thrift.Tests/DataModel/DeepCopy.cs
@@ -0,0 +1,603 @@
+// Licensed to the Apache Software Foundation(ASF) under one
+// or more contributor license agreements.See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using OptReqDefTest;
+using Thrift.Collections;
+
+namespace Thrift.Tests.DataModel
+{
+ // ReSharper disable once InconsistentNaming
+ [TestClass]
+ public class DeepCopyTests
+ {
+ [TestMethod]
+ public void Test_Complex_DeepCopy()
+ {
+ var first = InitializeInstance(new RaceDetails());
+ VerifyIdenticalContent(first, InitializeInstance(new RaceDetails()));
+
+ var second = first.DeepCopy();
+ VerifyIdenticalContent(first, second);
+ ModifyInstance(second,0);
+ VerifyDifferentContent(first, second);
+ VerifyIdenticalContent(first, InitializeInstance(new RaceDetails()));
+
+ var third = second.DeepCopy();
+ VerifyIdenticalContent(second, third);
+ ModifyInstance(third,0);
+ VerifyDifferentContent(second, third);
+ VerifyIdenticalContent(first, InitializeInstance(new RaceDetails()));
+ }
+
+ private RaceDetails MakeNestedRaceDetails(int nesting)
+ {
+ if (++nesting > 1)
+ return null;
+
+ var instance = new RaceDetails();
+ InitializeInstance(instance,nesting);
+ return instance;
+ }
+
+ private jack MakeNestedUnion(int nesting)
+ {
+ if (++nesting > 1)
+ return null;
+
+ var details = new RaceDetails();
+ InitializeInstance(details,nesting);
+ return new jack.nested_struct(details);
+ }
+
+
+ private RaceDetails InitializeInstance(RaceDetails instance, int nesting = 0)
+ {
+ // at init, we intentionally leave all non-required fields unset
+ Assert.IsFalse(instance.__isset.opt_one);
+ Assert.IsFalse(instance.__isset.opt_two);
+ Assert.IsFalse(instance.__isset.opt_three);
+ Assert.IsFalse(instance.__isset.opt_four);
+ Assert.IsFalse(instance.__isset.opt_five);
+ Assert.IsFalse(instance.__isset.opt_six);
+ Assert.IsFalse(instance.__isset.opt_seven);
+ Assert.IsFalse(instance.__isset.opt_eight);
+
+ // set all required to null/default
+ instance.Req_one = default;
+ instance.Req_two = default;
+ instance.Req_three = default;
+ instance.Req_four = default;
+ instance.Req_five = default;
+ instance.Req_six = default;
+ instance.Req_seven = default;;
+ instance.Req_eight = default;
+
+ // leave non-required fields unset again
+ Assert.IsFalse(instance.__isset.def_one);
+ Assert.IsFalse(instance.__isset.def_two);
+ Assert.IsFalse(instance.__isset.def_three);
+ Assert.IsFalse(instance.__isset.def_four);
+ Assert.IsFalse(instance.__isset.def_five);
+ Assert.IsFalse(instance.__isset.def_six);
+ Assert.IsFalse(instance.__isset.def_seven);
+ Assert.IsFalse(instance.__isset.def_eight);
+
+ // these should have IDL defaults set
+
+ Assert.IsTrue(instance.__isset.opt_one_with_value);
+ Assert.IsTrue(instance.__isset.opt_two_with_value);
+ Assert.IsTrue(instance.__isset.opt_three_with_value);
+ Assert.IsTrue(instance.__isset.opt_four_with_value);
+ Assert.IsTrue(instance.__isset.opt_five_with_value);
+ Assert.IsTrue(instance.__isset.opt_six_with_value);
+ Assert.IsTrue(instance.__isset.opt_seven_with_value);
+ Assert.IsTrue(instance.__isset.opt_eight_with_value);
+
+ Assert.AreEqual(instance.Req_one_with_value, (Distance)1);
+ Assert.AreEqual(instance.Req_two_with_value, 2.22);
+ Assert.AreEqual(instance.Req_three_with_value, 3);
+ Assert.AreEqual(instance.Req_four_with_value, "four");
+ Assert.AreEqual("five", Encoding.UTF8.GetString(instance.Req_five_with_value));
+
+ Assert.IsTrue(instance.Req_six_with_value.Count == 1);
+ Assert.AreEqual(instance.Req_six_with_value[0], 6 );
+
+ Assert.IsTrue(instance.Req_seven_with_value.Count == 1);
+ Assert.IsTrue(instance.Req_seven_with_value.Contains(7));
+
+ Assert.IsTrue(instance.Req_eight_with_value.Count == 1);
+ Assert.IsTrue(instance.Req_eight_with_value[8] == 8);
+
+ Assert.IsTrue(instance.__isset.def_one_with_value);
+ Assert.IsTrue(instance.__isset.def_two_with_value);
+ Assert.IsTrue(instance.__isset.def_three_with_value);
+ Assert.IsTrue(instance.__isset.def_four_with_value);
+ Assert.IsTrue(instance.__isset.def_five_with_value);
+ Assert.IsTrue(instance.__isset.def_six_with_value);
+ Assert.IsTrue(instance.__isset.def_seven_with_value);
+ Assert.IsTrue(instance.__isset.def_eight_with_value);
+
+ instance.Last_of_the_mohicans = true;
+
+ if (nesting < 2)
+ {
+ instance.Far_list = new List<Distance>() { Distance.foo, Distance.bar, Distance.baz };
+ instance.Far_set = new THashSet<Distance>() { Distance.foo, Distance.bar, Distance.baz };
+ instance.Far_map = new Dictionary<Distance, Distance>() { [Distance.foo] = Distance.foo, [Distance.bar] = Distance.bar, [Distance.baz] = Distance.baz };
+
+ instance.Far_set_list = new THashSet<List<Distance>>() { new List<Distance>() { Distance.foo } };
+ instance.Far_list_map_set = new List<Dictionary<sbyte, THashSet<Distance>>>() { new Dictionary<sbyte, THashSet<Distance>>() { [1] = new THashSet<Distance>() { Distance.baz } } };
+ instance.Far_map_dist_to_rds = new Dictionary<Distance, List<RaceDetails>>() { [Distance.bar] = new List<RaceDetails>() { MakeNestedRaceDetails(nesting) } };
+
+ instance.Req_nested = MakeNestedRaceDetails(nesting);
+ Assert.IsFalse(instance.__isset.opt_nested);
+ Assert.IsFalse(instance.__isset.def_nested);
+
+ instance.Req_union = MakeNestedUnion(nesting);
+ Assert.IsFalse(instance.__isset.opt_union);
+ Assert.IsFalse(instance.__isset.def_union);
+ }
+
+ instance.Triplesix = (Distance)666;
+
+ return instance;
+ }
+
+ private void ModifyInstance(RaceDetails instance, int level)
+ {
+ if ((instance == null) || (++level > 4))
+ return;
+
+ instance.Opt_one = ModifyValue(instance.Opt_one);
+ instance.Opt_two = ModifyValue(instance.Opt_two);
+ instance.Opt_three = ModifyValue(instance.Opt_three);
+ instance.Opt_four = ModifyValue(instance.Opt_four);
+ instance.Opt_five = ModifyValue(instance.Opt_five);
+ instance.Opt_six = ModifyValue(instance.Opt_six);
+ instance.Opt_seven = ModifyValue(instance.Opt_seven);
+ instance.Opt_eight = ModifyValue(instance.Opt_eight);
+
+ instance.Req_one = ModifyValue(instance.Req_one);
+ instance.Req_two = ModifyValue(instance.Req_two);
+ instance.Req_three = ModifyValue(instance.Req_three);
+ instance.Req_four = ModifyValue(instance.Req_four);
+ instance.Req_five = ModifyValue(instance.Req_five);
+ instance.Req_six = ModifyValue(instance.Req_six);
+ instance.Req_seven = ModifyValue(instance.Req_seven);
+ instance.Req_eight = ModifyValue(instance.Req_eight);
+
+ instance.Def_one = ModifyValue(instance.Def_one);
+ instance.Def_two = ModifyValue(instance.Def_two);
+ instance.Def_three = ModifyValue(instance.Def_three);
+ instance.Def_four = ModifyValue(instance.Def_four);
+ instance.Def_five = ModifyValue(instance.Def_five);
+ instance.Def_six = ModifyValue(instance.Def_six);
+ instance.Def_seven = ModifyValue(instance.Def_seven);
+ instance.Def_eight = ModifyValue(instance.Def_eight);
+
+ instance.Opt_one_with_value = ModifyValue(instance.Opt_one_with_value);
+ instance.Opt_two_with_value = ModifyValue(instance.Opt_two_with_value);
+ instance.Opt_three_with_value = ModifyValue(instance.Opt_three_with_value);
+ instance.Opt_four_with_value = ModifyValue(instance.Opt_four_with_value);
+ instance.Opt_five_with_value = ModifyValue(instance.Opt_five_with_value);
+ instance.Opt_six_with_value = ModifyValue(instance.Opt_six_with_value);
+ instance.Opt_seven_with_value = ModifyValue(instance.Opt_seven_with_value);
+ instance.Opt_eight_with_value = ModifyValue(instance.Opt_eight_with_value);
+
+ instance.Req_one_with_value = ModifyValue(instance.Req_one_with_value);
+ instance.Req_two_with_value = ModifyValue(instance.Req_two_with_value);
+ instance.Req_three_with_value = ModifyValue(instance.Req_three_with_value);
+ instance.Req_four_with_value = ModifyValue(instance.Req_four_with_value);
+ instance.Req_five_with_value = ModifyValue(instance.Req_five_with_value);
+ instance.Req_six_with_value = ModifyValue(instance.Req_six_with_value);
+ instance.Req_seven_with_value = ModifyValue(instance.Req_seven_with_value);
+ instance.Req_eight_with_value = ModifyValue(instance.Req_eight_with_value);
+
+ instance.Def_one_with_value = ModifyValue(instance.Def_one_with_value);
+ instance.Def_two_with_value = ModifyValue(instance.Def_two_with_value);
+ instance.Def_three_with_value = ModifyValue(instance.Def_three_with_value);
+ instance.Def_four_with_value = ModifyValue(instance.Def_four_with_value);
+ instance.Def_five_with_value = ModifyValue(instance.Def_five_with_value);
+ instance.Def_six_with_value = ModifyValue(instance.Def_six_with_value);
+ instance.Def_seven_with_value = ModifyValue(instance.Def_seven_with_value);
+ instance.Def_eight_with_value = ModifyValue(instance.Def_eight_with_value);
+
+ instance.Last_of_the_mohicans = ModifyValue(instance.Last_of_the_mohicans);
+
+ instance.Far_list = ModifyValue(instance.Far_list);
+ instance.Far_set = ModifyValue(instance.Far_set);
+ instance.Far_map = ModifyValue(instance.Far_map);
+
+ instance.Far_set_list = ModifyValue(instance.Far_set_list);
+ instance.Far_list_map_set = ModifyValue(instance.Far_list_map_set);
+ instance.Far_map_dist_to_rds = ModifyValue(instance.Far_map_dist_to_rds, level);
+
+ instance.Req_nested = ModifyValue(instance.Req_nested, level);
+ instance.Opt_nested = ModifyValue(instance.Opt_nested, level);
+ instance.Def_nested = ModifyValue(instance.Def_nested, level);
+
+ instance.Req_union = ModifyValue(instance.Req_union, level);
+ instance.Opt_union = ModifyValue(instance.Opt_union, level);
+ instance.Def_union = ModifyValue(instance.Def_union, level);
+
+ instance.Triplesix = ModifyValue(instance.Triplesix);
+ }
+
+ private jack ModifyValue(jack value, int level)
+ {
+ if (++level > 4)
+ return value;
+
+ if (value == null)
+ value = MakeNestedUnion(0);
+ Debug.Assert(value.As_nested_struct != null);
+ ModifyInstance(value.As_nested_struct, level);
+ return value;
+ }
+
+ private RaceDetails ModifyValue(RaceDetails value, int level)
+ {
+ if (++level > 4)
+ return value;
+
+ if (value == null)
+ value = new RaceDetails();
+ ModifyInstance(value,level);
+ return value;
+ }
+
+ private Dictionary<Distance, List<RaceDetails>> ModifyValue(Dictionary<Distance, List<RaceDetails>> value, int level)
+ {
+ if (value == null)
+ value = new Dictionary<Distance, List<RaceDetails>>();
+
+ if (++level > 4)
+ return value;
+
+ var details = new RaceDetails();
+ InitializeInstance(details);
+ value[Distance.foo] = new List<RaceDetails>() { details };
+
+ if (value.TryGetValue(Distance.bar, out var list) && (list.Count > 0))
+ {
+ ModifyInstance(list[0], level);
+ list.Add(null);
+ }
+
+ value[Distance.baz] = null;
+
+ return value;
+ }
+
+ private List<Dictionary<sbyte, THashSet<Distance>>> ModifyValue(List<Dictionary<sbyte, THashSet<Distance>>> value)
+ {
+ if (value == null)
+ value = new List<Dictionary<sbyte, THashSet<Distance>>>();
+
+ if (value.Count == 0)
+ value.Add(new Dictionary<sbyte, THashSet<Distance>>());
+ else
+ value.Add(null);
+
+ sbyte key = (sbyte)(value[0].Count + 10);
+ if (value[0].Count == 0)
+ value[0].Add(key, new THashSet<Distance>());
+ else
+ value[0].Add(key, null);
+
+ foreach (var entry in value)
+ {
+ if (entry != null)
+ {
+ foreach (var pair in entry)
+ {
+ if (pair.Value != null)
+ {
+ if (pair.Value.Contains(Distance.baz))
+ pair.Value.Remove(Distance.baz);
+ else
+ pair.Value.Add(Distance.baz);
+ }
+ }
+ }
+ }
+
+ return value;
+ }
+
+ private THashSet<List<Distance>> ModifyValue(THashSet<List<Distance>> value)
+ {
+ if (value == null)
+ value = new THashSet<List<Distance>>();
+
+ if (value.Count == 0)
+ value.Add(new List<Distance>());
+ else
+ value.Add(null);
+
+ foreach (var entry in value)
+ if( entry != null)
+ entry.Add(Distance.baz);
+
+ return value;
+ }
+
+ private Dictionary<Distance, Distance> ModifyValue(Dictionary<Distance, Distance> value)
+ {
+ if (value == null)
+ value = new Dictionary<Distance, Distance>();
+ value[Distance.foo] = value.ContainsKey(Distance.foo) ? ++value[Distance.foo] : Distance.foo;
+ value[Distance.bar] = value.ContainsKey(Distance.bar) ? ++value[Distance.bar] : Distance.bar;
+ value[Distance.baz] = value.ContainsKey(Distance.baz) ? ++value[Distance.baz] : Distance.baz;
+ return value;
+ }
+
+ private THashSet<Distance> ModifyValue(THashSet<Distance> value)
+ {
+ if (value == null)
+ value = new THashSet<Distance>();
+
+ if (value.Contains(Distance.foo))
+ value.Remove(Distance.foo);
+ else
+ value.Add(Distance.foo);
+
+ if (value.Contains(Distance.bar))
+ value.Remove(Distance.bar);
+ else
+ value.Add(Distance.bar);
+
+ if (value.Contains(Distance.baz))
+ value.Remove(Distance.baz);
+ else
+ value.Add(Distance.baz);
+
+ return value;
+ }
+
+ private List<Distance> ModifyValue(List<Distance> value)
+ {
+ if (value == null)
+ value = new List<Distance>();
+ value.Add(Distance.foo);
+ value.Add(Distance.bar);
+ value.Add(Distance.baz);
+ return value;
+ }
+
+ private bool ModifyValue(bool value)
+ {
+ return !value;
+ }
+
+ private Dictionary<sbyte, short> ModifyValue(Dictionary<sbyte, short> value)
+ {
+ if (value == null)
+ value = new Dictionary<sbyte, short>();
+ value.Add((sbyte)(value.Count + 10), (short)value.Count);
+ return value;
+ }
+
+ private THashSet<long> ModifyValue(THashSet<long> value)
+ {
+ if (value == null)
+ value = new THashSet<long>();
+ value.Add(value.Count+100);
+ return value;
+ }
+
+ private List<int> ModifyValue(List<int> value)
+ {
+ if (value == null)
+ value = new List<int>();
+ value.Add(value.Count);
+ return value;
+ }
+
+ private byte[] ModifyValue(byte[] value)
+ {
+ if (value == null)
+ value = new byte[1] { 0 };
+ if (value.Length > 0)
+ value[0] = (value[0] < 0xFF) ? ++value[0] : (byte)0;
+ return value;
+ }
+
+ private string ModifyValue(string value)
+ {
+ return value + "1";
+ }
+
+ private double ModifyValue(double value)
+ {
+ return value + 1.1;
+ }
+
+ private short ModifyValue(short value)
+ {
+ return ++value;
+ }
+
+ private Distance ModifyValue(Distance value)
+ {
+ return ++value;
+ }
+
+ private void VerifyDifferentContent(RaceDetails first, RaceDetails second)
+ {
+ Assert.AreNotEqual(first, second);
+
+ Assert.AreNotEqual(first.Opt_two, second.Opt_two);
+ Assert.AreNotEqual(first.Opt_three, second.Opt_three);
+ Assert.AreNotEqual(first.Opt_four, second.Opt_four);
+ Assert.IsFalse(TCollections.Equals(first.Opt_five, second.Opt_five));
+ Assert.IsFalse(TCollections.Equals(first.Opt_six, second.Opt_six));
+ Assert.IsFalse(TCollections.Equals(first.Opt_seven, second.Opt_seven));
+ Assert.IsFalse(TCollections.Equals(first.Opt_eight, second.Opt_eight));
+
+ Assert.AreNotEqual(first.Req_one, second.Req_one);
+ Assert.AreNotEqual(first.Req_two, second.Req_two);
+ Assert.AreNotEqual(first.Req_three, second.Req_three);
+ Assert.AreNotEqual(first.Req_four, second.Req_four);
+ Assert.IsFalse(TCollections.Equals(first.Req_five, second.Req_five));
+ Assert.IsFalse(TCollections.Equals(first.Req_six, second.Req_six));
+ Assert.IsFalse(TCollections.Equals(first.Req_seven, second.Req_seven));
+ Assert.IsFalse(TCollections.Equals(first.Req_eight, second.Req_eight));
+
+ Assert.AreNotEqual(first.Def_one, second.Def_one);
+ Assert.AreNotEqual(first.Def_two, second.Def_two);
+ Assert.AreNotEqual(first.Def_three, second.Def_three);
+ Assert.AreNotEqual(first.Def_four, second.Def_four);
+ Assert.IsFalse(TCollections.Equals(first.Def_five, second.Def_five));
+ Assert.IsFalse(TCollections.Equals(first.Def_six, second.Def_six));
+ Assert.IsFalse(TCollections.Equals(first.Def_seven, second.Def_seven));
+ Assert.IsFalse(TCollections.Equals(first.Def_eight, second.Def_eight));
+
+ Assert.AreNotEqual(first.Opt_one_with_value, second.Opt_one_with_value);
+ Assert.AreNotEqual(first.Opt_two_with_value, second.Opt_two_with_value);
+ Assert.AreNotEqual(first.Opt_three_with_value, second.Opt_three_with_value);
+ Assert.AreNotEqual(first.Opt_four_with_value, second.Opt_four_with_value);
+ Assert.IsFalse(TCollections.Equals(first.Opt_five_with_value, second.Opt_five_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Opt_six_with_value, second.Opt_six_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Opt_seven_with_value, second.Opt_seven_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Opt_eight_with_value, second.Opt_eight_with_value));
+
+ Assert.AreNotEqual(first.Req_one_with_value, second.Req_one_with_value);
+ Assert.AreNotEqual(first.Req_two_with_value, second.Req_two_with_value);
+ Assert.AreNotEqual(first.Req_three_with_value, second.Req_three_with_value);
+ Assert.AreNotEqual(first.Req_four_with_value, second.Req_four_with_value);
+ Assert.IsFalse(TCollections.Equals(first.Req_five_with_value, second.Req_five_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Req_six_with_value, second.Req_six_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Req_seven_with_value, second.Req_seven_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Req_eight_with_value, second.Req_eight_with_value));
+
+ Assert.AreNotEqual(first.Def_one_with_value, second.Def_one_with_value);
+ Assert.AreNotEqual(first.Def_two_with_value, second.Def_two_with_value);
+ Assert.AreNotEqual(first.Def_three_with_value, second.Def_three_with_value);
+ Assert.AreNotEqual(first.Def_four_with_value, second.Def_four_with_value);
+ Assert.IsFalse(TCollections.Equals(first.Def_five_with_value, second.Def_five_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Def_six_with_value, second.Def_six_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Def_seven_with_value, second.Def_seven_with_value));
+ Assert.IsFalse(TCollections.Equals(first.Def_eight_with_value, second.Def_eight_with_value));
+
+ Assert.AreNotEqual(first.Last_of_the_mohicans, second.Last_of_the_mohicans);
+
+ Assert.IsFalse(TCollections.Equals(first.Far_list, second.Far_list));
+ Assert.IsFalse(TCollections.Equals(first.Far_set, second.Far_set));
+ Assert.IsFalse(TCollections.Equals(first.Far_map, second.Far_map));
+
+ Assert.IsFalse(TCollections.Equals(first.Far_set_list, second.Far_set_list));
+ Assert.IsFalse(TCollections.Equals(first.Far_list_map_set, second.Far_list_map_set));
+ Assert.IsFalse(TCollections.Equals(first.Far_map_dist_to_rds, second.Far_map_dist_to_rds));
+
+ Assert.AreNotEqual(first.Req_nested, second.Req_nested);
+ Assert.AreNotEqual(first.Opt_nested, second.Opt_nested);
+ Assert.AreNotEqual(first.Def_nested, second.Def_nested);
+
+ Assert.AreNotEqual(first.Req_union, second.Req_union);
+ Assert.AreNotEqual(first.Opt_union, second.Opt_union);
+ Assert.AreNotEqual(first.Def_union, second.Def_union);
+
+ Assert.AreNotEqual(first.Triplesix, second.Triplesix);
+ }
+
+ private void VerifyIdenticalContent(RaceDetails first, RaceDetails second)
+ {
+ Assert.AreEqual(first, second);
+
+ Assert.AreEqual(first.Opt_two, second.Opt_two);
+ Assert.AreEqual(first.Opt_three, second.Opt_three);
+ Assert.AreEqual(first.Opt_four, second.Opt_four);
+ Assert.IsTrue(TCollections.Equals(first.Opt_five, second.Opt_five));
+ Assert.IsTrue(TCollections.Equals(first.Opt_six, second.Opt_six));
+ Assert.IsTrue(TCollections.Equals(first.Opt_seven, second.Opt_seven));
+ Assert.IsTrue(TCollections.Equals(first.Opt_eight, second.Opt_eight));
+
+ Assert.AreEqual(first.Req_one, second.Req_one);
+ Assert.AreEqual(first.Req_two, second.Req_two);
+ Assert.AreEqual(first.Req_three, second.Req_three);
+ Assert.AreEqual(first.Req_four, second.Req_four);
+ Assert.IsTrue(TCollections.Equals(first.Req_five, second.Req_five));
+ Assert.IsTrue(TCollections.Equals(first.Req_six, second.Req_six));
+ Assert.IsTrue(TCollections.Equals(first.Req_seven, second.Req_seven));
+ Assert.IsTrue(TCollections.Equals(first.Req_eight, second.Req_eight));
+
+ Assert.AreEqual(first.Def_one, second.Def_one);
+ Assert.AreEqual(first.Def_two, second.Def_two);
+ Assert.AreEqual(first.Def_three, second.Def_three);
+ Assert.AreEqual(first.Def_four, second.Def_four);
+ Assert.IsTrue(TCollections.Equals(first.Def_five, second.Def_five));
+ Assert.IsTrue(TCollections.Equals(first.Def_six, second.Def_six));
+ Assert.IsTrue(TCollections.Equals(first.Def_seven, second.Def_seven));
+ Assert.IsTrue(TCollections.Equals(first.Def_eight, second.Def_eight));
+
+ Assert.AreEqual(first.Opt_one_with_value, second.Opt_one_with_value);
+ Assert.AreEqual(first.Opt_two_with_value, second.Opt_two_with_value);
+ Assert.AreEqual(first.Opt_three_with_value, second.Opt_three_with_value);
+ Assert.AreEqual(first.Opt_four_with_value, second.Opt_four_with_value);
+ Assert.IsTrue(TCollections.Equals(first.Opt_five_with_value, second.Opt_five_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Opt_six_with_value, second.Opt_six_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Opt_seven_with_value, second.Opt_seven_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Opt_eight_with_value, second.Opt_eight_with_value));
+
+ Assert.AreEqual(first.Req_one_with_value, second.Req_one_with_value);
+ Assert.AreEqual(first.Req_two_with_value, second.Req_two_with_value);
+ Assert.AreEqual(first.Req_three_with_value, second.Req_three_with_value);
+ Assert.AreEqual(first.Req_four_with_value, second.Req_four_with_value);
+ Assert.IsTrue(TCollections.Equals(first.Req_five_with_value, second.Req_five_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Req_six_with_value, second.Req_six_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Req_seven_with_value, second.Req_seven_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Req_eight_with_value, second.Req_eight_with_value));
+
+ Assert.AreEqual(first.Def_one_with_value, second.Def_one_with_value);
+ Assert.AreEqual(first.Def_two_with_value, second.Def_two_with_value);
+ Assert.AreEqual(first.Def_three_with_value, second.Def_three_with_value);
+ Assert.AreEqual(first.Def_four_with_value, second.Def_four_with_value);
+ Assert.IsTrue(TCollections.Equals(first.Def_five_with_value, second.Def_five_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Def_six_with_value, second.Def_six_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Def_seven_with_value, second.Def_seven_with_value));
+ Assert.IsTrue(TCollections.Equals(first.Def_eight_with_value, second.Def_eight_with_value));
+
+ Assert.AreEqual(first.Last_of_the_mohicans, second.Last_of_the_mohicans);
+
+ Assert.IsTrue(TCollections.Equals(first.Far_list, second.Far_list));
+ Assert.IsTrue(TCollections.Equals(first.Far_set, second.Far_set));
+ Assert.IsTrue(TCollections.Equals(first.Far_map, second.Far_map));
+
+ Assert.IsTrue(TCollections.Equals(first.Far_set_list, second.Far_set_list));
+ Assert.IsTrue(TCollections.Equals(first.Far_list_map_set, second.Far_list_map_set));
+ Assert.IsTrue(TCollections.Equals(first.Far_map_dist_to_rds, second.Far_map_dist_to_rds));
+
+ Assert.AreEqual(first.Req_nested, second.Req_nested);
+ Assert.AreEqual(first.Opt_nested, second.Opt_nested);
+ Assert.AreEqual(first.Def_nested, second.Def_nested);
+
+ Assert.AreEqual(first.Req_union, second.Req_union);
+ Assert.AreEqual(first.Opt_union, second.Opt_union);
+ Assert.AreEqual(first.Def_union, second.Def_union);
+
+ Assert.AreEqual(first.Triplesix, second.Triplesix);
+ }
+
+ }
+}
diff --git a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj
index 20fdfe4..4b39e7d 100644
--- a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj
+++ b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<!--
Licensed to the Apache Software Foundation(ASF) under one
or more contributor license agreements.See the NOTICE file
@@ -29,6 +29,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Thrift\Thrift.csproj" />
+ <ProjectReference Include="..\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
diff --git a/lib/netstd/Thrift/Collections/TCollections.cs b/lib/netstd/Thrift/Collections/TCollections.cs
index 147bfc7..b386c37 100644
--- a/lib/netstd/Thrift/Collections/TCollections.cs
+++ b/lib/netstd/Thrift/Collections/TCollections.cs
@@ -16,11 +16,12 @@
// under the License.
using System.Collections;
+using System.Collections.Generic;
namespace Thrift.Collections
{
// ReSharper disable once InconsistentNaming
- public class TCollections
+ public static class TCollections
{
/// <summary>
/// This will return true if the two collections are value-wise the same.
@@ -38,6 +39,18 @@
return false;
}
+ // for dictionaries, we need to compare keys and values separately
+ // because KeyValuePair<K,V>.Equals() will not do what we want
+ var fdict = first as IDictionary;
+ var sdict = second as IDictionary;
+ if ((fdict != null) || (sdict != null))
+ {
+ if ((fdict == null) || (sdict == null))
+ return false;
+ return TCollections.Equals(fdict.Keys, sdict.Keys)
+ && TCollections.Equals(fdict.Values, sdict.Values);
+ }
+
var fiter = first.GetEnumerator();
var siter = second.GetEnumerator();
@@ -91,11 +104,13 @@
unchecked
{
- hashcode = (hashcode*397) ^ (objHash);
+ hashcode = (hashcode * 397) ^ (objHash);
}
}
return hashcode;
}
+
+
}
-}
\ No newline at end of file
+}
diff --git a/lib/netstd/Thrift/Collections/THashSet.cs b/lib/netstd/Thrift/Collections/THashSet.cs
index ffab577..8dfb9e3 100644
--- a/lib/netstd/Thrift/Collections/THashSet.cs
+++ b/lib/netstd/Thrift/Collections/THashSet.cs
@@ -60,12 +60,12 @@
Items.CopyTo(array, arrayIndex);
}
- public IEnumerator GetEnumerator()
+ IEnumerator IEnumerable.GetEnumerator()
{
return Items.GetEnumerator();
}
- IEnumerator<T> IEnumerable<T>.GetEnumerator()
+ public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>) Items).GetEnumerator();
}
diff --git a/lib/netstd/Thrift/Protocol/TBase.cs b/lib/netstd/Thrift/Protocol/TBase.cs
index b5ef2ae..df9dd34 100644
--- a/lib/netstd/Thrift/Protocol/TBase.cs
+++ b/lib/netstd/Thrift/Protocol/TBase.cs
@@ -22,12 +22,13 @@
{
public interface TUnionBase
{
- Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken = default(CancellationToken));
+ Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken = default);
}
// ReSharper disable once InconsistentNaming
public interface TBase : TUnionBase
{
- Task ReadAsync(TProtocol tProtocol, CancellationToken cancellationToken = default(CancellationToken));
+ Task ReadAsync(TProtocol tProtocol, CancellationToken cancellationToken = default);
}
+
}
diff --git a/lib/netstd/Thrift/Collections/ToStringExtension.cs b/lib/netstd/Thrift/Protocol/ToString.cs
similarity index 95%
rename from lib/netstd/Thrift/Collections/ToStringExtension.cs
rename to lib/netstd/Thrift/Protocol/ToString.cs
index 40dd9dd..14fa520 100644
--- a/lib/netstd/Thrift/Collections/ToStringExtension.cs
+++ b/lib/netstd/Thrift/Protocol/ToString.cs
@@ -21,7 +21,7 @@
using System.Text;
using Thrift.Protocol;
-namespace Thrift.Collections
+namespace Thrift.Protocol
{
@@ -73,7 +73,7 @@
}
else
{
- sb.Append(self.ToString());
+ sb.Append(self != null? self.ToString() : "<null>");
}
}
}