diff --git a/Build/build.ps1 b/Build/build.ps1
index 8d64dea3..4602aee4 100644
--- a/Build/build.ps1
+++ b/Build/build.ps1
@@ -20,7 +20,7 @@
@{Name = "Newtonsoft.Json.Portable"; TestsName = "Newtonsoft.Json.Tests.Portable"; Constants="PORTABLE"; FinalDir="Portable"; NuGetDir = "portable-net40+sl4+wp7+win8"; Framework="net-4.0"; Sign=$true},
@{Name = "Newtonsoft.Json.WinRT"; TestsName = $null; Constants="NETFX_CORE"; FinalDir="WinRT"; NuGetDir = "winrt45"; Framework="net-4.5"; Sign=$true},
- @{Name = "Newtonsoft.Json.WindowsPhone"; TestsName = $null; Constants="SILVERLIGHT;WINDOWS_PHONE"; FinalDir="WindowsPhone"; NuGetDir = "sl3-wp,sl4-windowsphone71"; Framework="net-4.0"; Sign=$true},
+ #@{Name = "Newtonsoft.Json.WindowsPhone"; TestsName = $null; Constants="SILVERLIGHT;WINDOWS_PHONE"; FinalDir="WindowsPhone"; NuGetDir = "sl3-wp,sl4-windowsphone71"; Framework="net-4.0"; Sign=$true},
@{Name = "Newtonsoft.Json.Silverlight"; TestsName = "Newtonsoft.Json.Tests.Silverlight"; Constants="SILVERLIGHT"; FinalDir="Silverlight"; NuGetDir = "sl4"; Framework="net-4.0"; Sign=$true},
@{Name = "Newtonsoft.Json.Net35"; TestsName = "Newtonsoft.Json.Tests.Net35"; Constants="NET35"; FinalDir="Net35"; NuGetDir = "net35"; Framework="net-2.0"; Sign=$true},
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj
index 1e1aeb83..9fc726da 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj
@@ -99,6 +99,7 @@
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj
index 7135f3fe..0ff3fca1 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net35.csproj
@@ -141,6 +141,7 @@
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj
index 311db840..0f9a2ec9 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Portable.csproj
@@ -134,6 +134,7 @@
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj
index f3c761dd..d4256caa 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Silverlight.csproj
@@ -139,6 +139,7 @@
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.WinRT.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.WinRT.csproj
index 2803ba5c..ed469769 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.WinRT.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.WinRT.csproj
@@ -173,6 +173,7 @@
+
diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
index eddf8a79..f89253c0 100644
--- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
+++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj
@@ -153,6 +153,7 @@
+
diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
index 94901795..7b5c016c 100644
--- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
+++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
@@ -64,8 +64,8 @@ namespace Newtonsoft.Json.Tests
[TestFixture]
public class PerformanceTests : TestFixtureBase
{
- private const int Iterations = 100;
- //private const int Iterations = 5000;
+ //private const int Iterations = 100;
+ private const int Iterations = 5000;
#region Data
diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
index e2e3fbf2..bcbdae61 100644
--- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
+++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
@@ -76,5 +76,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
-[assembly: AssemblyFileVersion("4.5.10.15504")]
+[assembly: AssemblyFileVersion("4.5.10.15509")]
#endif
diff --git a/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs
new file mode 100644
index 00000000..f024b476
--- /dev/null
+++ b/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs
@@ -0,0 +1,510 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters;
+using System.Text;
+#if !NETFX_CORE
+using NUnit.Framework;
+#else
+using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
+using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
+using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
+#endif
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Tests.TestObjects;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+
+namespace Newtonsoft.Json.Tests.Serialization
+{
+ [TestFixture]
+ public class TraceWriterTests : TestFixtureBase
+ {
+ [Test]
+ public void Serialize()
+ {
+ var traceWriter = new InMemoryTraceWriter
+ {
+ LevelFilter = TraceLevel.Info
+ };
+
+ string json =
+ JsonConvert.SerializeObject(
+ new TraceTestObject
+ {
+ StringArray = new[] {"1", "2"},
+ IntList = new List {1, 2},
+ Version = new Version(1, 2, 3, 4),
+ StringDictionary =
+ new Dictionary
+ {
+ {"1", "!"},
+ {"Two", "!!"},
+ {"III", "!!!"}
+ }
+ },
+ new JsonSerializerSettings
+ {
+ TraceWriter = traceWriter,
+ Formatting = Formatting.Indented
+ });
+
+ Assert.AreEqual("Started serializing Newtonsoft.Json.Tests.Serialization.TraceTestObject. Path ''.", traceWriter.TraceRecords[0].Message);
+ Assert.AreEqual("Started serializing System.Collections.Generic.List`1[System.Int32]. Path 'IntList'.", traceWriter.TraceRecords[1].Message);
+ Assert.AreEqual("Finished serializing System.Collections.Generic.List`1[System.Int32]. Path 'IntList'.", traceWriter.TraceRecords[2].Message);
+ Assert.AreEqual("Started serializing System.String[]. Path 'StringArray'.", traceWriter.TraceRecords[3].Message);
+ Assert.AreEqual("Finished serializing System.String[]. Path 'StringArray'.", traceWriter.TraceRecords[4].Message);
+ Assert.AreEqual("Started serializing System.Version. Path 'Version'.", traceWriter.TraceRecords[5].Message);
+ Assert.AreEqual("Finished serializing System.Version. Path 'Version'.", traceWriter.TraceRecords[6].Message);
+ Assert.AreEqual("Started serializing System.Collections.Generic.Dictionary`2[System.String,System.String]. Path 'StringDictionary'.", traceWriter.TraceRecords[7].Message);
+ Assert.AreEqual("Finished serializing System.Collections.Generic.Dictionary`2[System.String,System.String]. Path 'StringDictionary'.", traceWriter.TraceRecords[8].Message);
+ Assert.AreEqual("Finished serializing Newtonsoft.Json.Tests.Serialization.TraceTestObject. Path ''.", traceWriter.TraceRecords[9].Message);
+ }
+
+ [Test]
+ public void Deserialize()
+ {
+ InMemoryTraceWriter traceWriter = new InMemoryTraceWriter
+ {
+ LevelFilter = TraceLevel.Info
+ };
+
+ TraceTestObject o2 = JsonConvert.DeserializeObject(
+ @"{
+ ""IntList"": [
+ 1,
+ 2
+ ],
+ ""StringArray"": [
+ ""1"",
+ ""2""
+ ],
+ ""Version"": {
+ ""Major"": 1,
+ ""Minor"": 2,
+ ""Build"": 3,
+ ""Revision"": 4,
+ ""MajorRevision"": 0,
+ ""MinorRevision"": 4
+ },
+ ""StringDictionary"": {
+ ""1"": ""!"",
+ ""Two"": ""!!"",
+ ""III"": ""!!!""
+ }
+}",
+ new JsonSerializerSettings
+ {
+ TraceWriter = traceWriter
+ });
+
+ Assert.AreEqual(2, o2.IntList.Count);
+ Assert.AreEqual(2, o2.StringArray.Length);
+ Assert.AreEqual(1, o2.Version.Major);
+ Assert.AreEqual(2, o2.Version.Minor);
+ Assert.AreEqual(3, o2.StringDictionary.Count);
+
+ Assert.AreEqual("Started deserializing Newtonsoft.Json.Tests.Serialization.TraceTestObject. Path 'IntList', line 2, position 13.", traceWriter.TraceRecords[0].Message);
+ Assert.AreEqual("Started deserializing System.Collections.Generic.IList`1[System.Int32]. Path 'IntList', line 2, position 15.", traceWriter.TraceRecords[1].Message);
+ Assert.AreEqual("Finished deserializing System.Collections.Generic.IList`1[System.Int32]. Path 'IntList', line 5, position 4.", traceWriter.TraceRecords[2].Message);
+ Assert.AreEqual("Started deserializing System.String[]. Path 'StringArray', line 6, position 19.", traceWriter.TraceRecords[3].Message);
+ Assert.AreEqual("Finished deserializing System.String[]. Path 'StringArray', line 9, position 4.", traceWriter.TraceRecords[4].Message);
+ Assert.AreEqual("Deserializing System.Version using a non-default constructor 'Void .ctor(Int32, Int32, Int32, Int32)'. Path 'Version.Major', line 11, position 13.", traceWriter.TraceRecords[5].Message);
+ Assert.AreEqual("Started deserializing System.Version. Path 'Version', line 17, position 4.", traceWriter.TraceRecords[6].Message);
+ Assert.AreEqual("Finished deserializing System.Version. Path 'Version', line 17, position 4.", traceWriter.TraceRecords[7].Message);
+ Assert.AreEqual("Started deserializing System.Collections.Generic.IDictionary`2[System.String,System.String]. Path 'StringDictionary.1', line 19, position 9.", traceWriter.TraceRecords[8].Message);
+ Assert.AreEqual("Finished deserializing System.Collections.Generic.IDictionary`2[System.String,System.String]. Path 'StringDictionary', line 22, position 4.", traceWriter.TraceRecords[9].Message);
+ Assert.AreEqual("Finished deserializing Newtonsoft.Json.Tests.Serialization.TraceTestObject. Path '', line 23, position 2.", traceWriter.TraceRecords[10].Message);
+ }
+
+ [Test]
+ public void ErrorDeserializing()
+ {
+ string json = @"{""Integer"":""hi""}";
+
+ var traceWriter = new InMemoryTraceWriter
+ {
+ LevelFilter = TraceLevel.Info
+ };
+
+ ExceptionAssert.Throws(
+ "Could not convert string to integer: hi. Path 'Integer', line 1, position 15.",
+ () =>
+ {
+ JsonConvert.DeserializeObject(
+ json,
+ new JsonSerializerSettings
+ {
+ TraceWriter = traceWriter
+ });
+ });
+
+ Assert.AreEqual(2, traceWriter.TraceRecords.Count);
+
+ Assert.AreEqual(TraceLevel.Info, traceWriter.TraceRecords[0].Level);
+ Assert.AreEqual("Started deserializing Newtonsoft.Json.Tests.Serialization.IntegerTestClass. Path 'Integer', line 1, position 11.", traceWriter.TraceRecords[0].Message);
+
+ Assert.AreEqual(TraceLevel.Error, traceWriter.TraceRecords[1].Level);
+ Assert.AreEqual("Error deserializing Newtonsoft.Json.Tests.Serialization.IntegerTestClass. Could not convert string to integer: hi. Path 'Integer', line 1, position 15.", traceWriter.TraceRecords[1].Message);
+ }
+
+ [Test]
+ public void ErrorDeserializingNested()
+ {
+ string json = @"{""IntList"":[1, ""two""]}";
+
+ var traceWriter = new InMemoryTraceWriter
+ {
+ LevelFilter = TraceLevel.Info
+ };
+
+ ExceptionAssert.Throws(
+ "Could not convert string to integer: two. Path 'IntList[1]', line 1, position 20.",
+ () =>
+ {
+ JsonConvert.DeserializeObject(
+ json,
+ new JsonSerializerSettings
+ {
+ TraceWriter = traceWriter
+ });
+ });
+
+ Assert.AreEqual(3, traceWriter.TraceRecords.Count);
+
+ Assert.AreEqual(TraceLevel.Info, traceWriter.TraceRecords[0].Level);
+ Assert.AreEqual("Started deserializing Newtonsoft.Json.Tests.Serialization.TraceTestObject. Path 'IntList', line 1, position 11.", traceWriter.TraceRecords[0].Message);
+
+ Assert.AreEqual(TraceLevel.Info, traceWriter.TraceRecords[1].Level);
+ Assert.AreEqual("Started deserializing System.Collections.Generic.IList`1[System.Int32]. Path 'IntList', line 1, position 12.", traceWriter.TraceRecords[1].Message);
+
+ Assert.AreEqual(TraceLevel.Error, traceWriter.TraceRecords[2].Level);
+ Assert.AreEqual("Error deserializing System.Collections.Generic.IList`1[System.Int32]. Could not convert string to integer: two. Path 'IntList[1]', line 1, position 20.", traceWriter.TraceRecords[2].Message);
+ }
+
+ [Test]
+ public void SerializeDictionarysWithPreserveObjectReferences()
+ {
+ PreserveReferencesHandlingTests.CircularDictionary circularDictionary = new PreserveReferencesHandlingTests.CircularDictionary();
+ circularDictionary.Add("other", new PreserveReferencesHandlingTests.CircularDictionary { { "blah", null } });
+ circularDictionary.Add("self", circularDictionary);
+
+ InMemoryTraceWriter traceWriter = new InMemoryTraceWriter
+ {
+ LevelFilter = TraceLevel.Verbose
+ };
+
+ JsonConvert.SerializeObject(
+ circularDictionary,
+ Formatting.Indented,
+ new JsonSerializerSettings
+ {
+ PreserveReferencesHandling = PreserveReferencesHandling.All,
+ TraceWriter = traceWriter
+ });
+
+ Assert.IsTrue(traceWriter.TraceRecords.Any(r => r.Message == "Writing object reference Id '1' for Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+CircularDictionary. Path ''."));
+ Assert.IsTrue(traceWriter.TraceRecords.Any(r => r.Message == "Writing object reference Id '2' for Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+CircularDictionary. Path 'other'."));
+ Assert.IsTrue(traceWriter.TraceRecords.Any(r => r.Message == "Writing object reference to Id '1' for Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+CircularDictionary. Path 'self'."));
+ }
+
+ [Test]
+ public void DeserializeDictionarysWithPreserveObjectReferences()
+ {
+ string json = @"{
+ ""$id"": ""1"",
+ ""other"": {
+ ""$id"": ""2"",
+ ""blah"": null
+ },
+ ""self"": {
+ ""$ref"": ""1""
+ }
+}";
+
+ InMemoryTraceWriter traceWriter = new InMemoryTraceWriter
+ {
+ LevelFilter = TraceLevel.Verbose
+ };
+
+ JsonConvert.DeserializeObject(json,
+ new JsonSerializerSettings
+ {
+ PreserveReferencesHandling = PreserveReferencesHandling.All,
+ TraceWriter = traceWriter
+ });
+
+ Assert.IsTrue(traceWriter.TraceRecords.Any(r => r.Message == "Read object reference Id '1' for Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+CircularDictionary. Path 'other', line 3, position 11."));
+ Assert.IsTrue(traceWriter.TraceRecords.Any(r => r.Message == "Read object reference Id '2' for Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+CircularDictionary. Path 'other.blah', line 5, position 12."));
+ Assert.IsTrue(traceWriter.TraceRecords.Any(r => r.Message == "Resolved object reference '1' to Newtonsoft.Json.Tests.Serialization.PreserveReferencesHandlingTests+CircularDictionary. Path 'self', line 9, position 4."));
+ }
+
+ [Test]
+ public void WriteTypeNameForObjects()
+ {
+ InMemoryTraceWriter traceWriter = new InMemoryTraceWriter
+ {
+ LevelFilter = TraceLevel.Verbose
+ };
+
+ IList