Skip to content

Commit

Permalink
Fix - Avoid usage of JsonConvert in test host process (#1881)
Browse files Browse the repository at this point in the history
* Removing json convert

* Reorganizing code

* Removinf default settings usage for json serializer
  • Loading branch information
abhishkk committed Jan 3, 2019
1 parent 31dc9fc commit 5689373
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@ namespace Microsoft.TestPlatform.Protocol
using Newtonsoft.Json.Serialization;

/// <summary>
/// JsonDataSerializes serializes and deserializes data using Json format
/// JsonDataSerializer serializes and deserializes data using Json format
/// </summary>
public class JsonDataSerializer
{
private static JsonDataSerializer instance;

private static JsonSerializer serializer;
private static JsonSerializer payloadSerializer; // used when data to be serialized/deserialized contains payload
private static JsonSerializer serializer; // generic serializer

/// <summary>
/// Prevents a default instance of the <see cref="JsonDataSerializer"/> class from being created.
/// </summary>
private JsonDataSerializer()
{
serializer = JsonSerializer.Create(
serializer = JsonSerializer.Create();
payloadSerializer = JsonSerializer.Create(
new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
Expand All @@ -35,7 +36,7 @@ private JsonDataSerializer()
#if DEBUG
// MemoryTraceWriter can help diagnose serialization issues. Enable it for
// debug builds only.
serializer.TraceWriter = new MemoryTraceWriter();
payloadSerializer.TraceWriter = new MemoryTraceWriter();
#endif
}

Expand Down Expand Up @@ -68,20 +69,9 @@ public Message DeserializeMessage(string rawMessage)
/// <returns>The deserialized payload.</returns>
public T DeserializePayload<T>(Message message)
{
T retValue = default(T);

// TODO: Currently we use json serializer auto only for non-testmessage types
// CHECK: Can't we just use auto for everything
if (Microsoft.TestPlatform.Protocol.MessageType.TestMessage.Equals(message.MessageType))
{
retValue = message.Payload.ToObject<T>();
}
else
{
retValue = message.Payload.ToObject<T>(serializer);
}

return retValue;
return MessageType.TestMessage.Equals(message.MessageType) ?
message.Payload.ToObject<T>(serializer) :
message.Payload.ToObject<T>(payloadSerializer);
}

/// <summary>
Expand All @@ -95,7 +85,7 @@ public T Deserialize<T>(string json)
using (var stringReader = new StringReader(json))
using (var jsonReader = new JsonTextReader(stringReader))
{
return serializer.Deserialize<T>(jsonReader);
return payloadSerializer.Deserialize<T>(jsonReader);
}
}

Expand All @@ -117,18 +107,9 @@ public string SerializeMessage(string messageType)
/// <returns>Serialized message.</returns>
public string SerializePayload(string messageType, object payload)
{
JToken serializedPayload = null;

// TODO: Currently we use json serializer auto only for non-testmessage types
// CHECK: Can't we just use auto for everything
if (MessageType.TestMessage.Equals(messageType))
{
serializedPayload = JToken.FromObject(payload);
}
else
{
serializedPayload = JToken.FromObject(payload, serializer);
}
JToken serializedPayload = MessageType.TestMessage.Equals(messageType) ?
JToken.FromObject(payload, serializer) :
JToken.FromObject(payload, payloadSerializer);

return JsonConvert.SerializeObject(new Message { MessageType = messageType, Payload = serializedPayload });
}
Expand All @@ -144,7 +125,7 @@ public string Serialize<T>(T data)
using (var stringWriter = new StringWriter())
using (var jsonWriter = new JsonTextWriter(stringWriter))
{
serializer.Serialize(jsonWriter, data);
payloadSerializer.Serialize(jsonWriter, data);

return stringWriter.ToString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ public class JsonDataSerializer : IDataSerializer
{
private static JsonDataSerializer instance;

private static JsonSerializer payloadSerializer;
private static JsonSerializer payloadSerializer2;
private static JsonSerializer payloadSerializer; // payload serializer for version <= 1
private static JsonSerializer payloadSerializer2; // payload serializer for version >= 2
private static JsonSerializer serializer; // generic serializer

/// <summary>
/// Prevents a default instance of the <see cref="JsonDataSerializer"/> class from being created.
Expand All @@ -36,6 +37,7 @@ private JsonDataSerializer()
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};

serializer = JsonSerializer.Create();
payloadSerializer = JsonSerializer.Create(jsonSettings);
payloadSerializer2 = JsonSerializer.Create(jsonSettings);

Expand Down Expand Up @@ -70,9 +72,7 @@ public static JsonDataSerializer Instance
/// <returns>A <see cref="Message"/> instance.</returns>
public Message DeserializeMessage(string rawMessage)
{
// Convert to VersionedMessage
// Message can be deserialized to VersionedMessage where version will be 0
return JsonConvert.DeserializeObject<VersionedMessage>(rawMessage);
return this.Deserialize<VersionedMessage>(serializer, rawMessage);
}

/// <summary>
Expand All @@ -83,13 +83,9 @@ public Message DeserializeMessage(string rawMessage)
/// <returns>The deserialized payload.</returns>
public T DeserializePayload<T>(Message message)
{
T retValue = default(T);

var versionedMessage = message as VersionedMessage;
var serializer = this.GetPayloadSerializer(versionedMessage?.Version);

retValue = message.Payload.ToObject<T>(serializer);
return retValue;
var payloadSerializer = this.GetPayloadSerializer(versionedMessage?.Version);
return this.Deserialize<T>(payloadSerializer, message.Payload);
}

/// <summary>
Expand All @@ -101,13 +97,8 @@ public T DeserializePayload<T>(Message message)
/// <returns>An instance of <see cref="T"/>.</returns>
public T Deserialize<T>(string json, int version = 1)
{
var serializer = this.GetPayloadSerializer(version);

using (var stringReader = new StringReader(json))
using (var jsonReader = new JsonTextReader(stringReader))
{
return serializer.Deserialize<T>(jsonReader);
}
var payloadSerializer = this.GetPayloadSerializer(version);
return this.Deserialize<T>(payloadSerializer, json);
}

/// <summary>
Expand All @@ -117,7 +108,7 @@ public T Deserialize<T>(string json, int version = 1)
/// <returns>Serialized message.</returns>
public string SerializeMessage(string messageType)
{
return JsonConvert.SerializeObject(new Message { MessageType = messageType });
return this.Serialize(serializer, new Message { MessageType = messageType });
}

/// <summary>
Expand All @@ -128,9 +119,7 @@ public string SerializeMessage(string messageType)
/// <returns>Serialized message.</returns>
public string SerializePayload(string messageType, object payload)
{
var serializedPayload = JToken.FromObject(payload, payloadSerializer);

return JsonConvert.SerializeObject(new Message { MessageType = messageType, Payload = serializedPayload });
return this.SerializePayload(messageType, payload, 1);
}

/// <summary>
Expand All @@ -142,14 +131,25 @@ public string SerializePayload(string messageType, object payload)
/// <returns>Serialized message.</returns>
public string SerializePayload(string messageType, object payload, int version)
{
var serializer = this.GetPayloadSerializer(version);
var serializedPayload = JToken.FromObject(payload, serializer);
var payloadSerializer = this.GetPayloadSerializer(version);
var serializedPayload = JToken.FromObject(payload, payloadSerializer);

var message = version > 1 ?
new VersionedMessage { MessageType = messageType, Version = version, Payload = serializedPayload } :
new Message { MessageType = messageType, Payload = serializedPayload };
return version > 1 ?
this.Serialize(serializer, new VersionedMessage { MessageType = messageType, Version = version, Payload = serializedPayload }) :
this.Serialize(serializer, new Message { MessageType = messageType, Payload = serializedPayload });
}

return JsonConvert.SerializeObject(message);
/// <summary>
/// Serialize an object to JSON using default serialization settings.
/// </summary>
/// <typeparam name="T">Type of object to serialize.</typeparam>
/// <param name="data">Instance of the object to serialize.</param>
/// <param name="version">Version to be stamped.</param>
/// <returns>JSON string.</returns>
public string Serialize<T>(T data, int version = 1)
{
var payloadSerializer = this.GetPayloadSerializer(version);
return this.Serialize(payloadSerializer, data);
}

/// <inheritdoc/>
Expand All @@ -165,25 +165,50 @@ public T Clone<T>(T obj)
}

/// <summary>
/// Serialize an object to JSON using default serialization settings.
/// Serialize data.
/// </summary>
/// <typeparam name="T">Type of object to serialize.</typeparam>
/// <param name="data">Instance of the object to serialize.</param>
/// <param name="version">Version to be stamped.</param>
/// <returns>JSON string.</returns>
public string Serialize<T>(T data, int version = 1)
/// <typeparam name="T">Type of data.</typeparam>
/// <param name="serializer">Serializer.</param>
/// <param name="data">Data to be serialized.</param>
/// <returns>Serialized data.</returns>
private string Serialize<T>(JsonSerializer serializer, T data)
{
var serializer = this.GetPayloadSerializer(version);

using (var stringWriter = new StringWriter())
using (var jsonWriter = new JsonTextWriter(stringWriter))
{
serializer.Serialize(jsonWriter, data);

return stringWriter.ToString();
}
}

/// <summary>
/// Deserialize data.
/// </summary>
/// <typeparam name="T">Type of data.</typeparam>
/// <param name="serializer">Serializer.</param>
/// <param name="data">Data to be deserialized.</param>
/// <returns>Deserialized data.</returns>
private T Deserialize<T>(JsonSerializer serializer, string data)
{
using (var stringReader = new StringReader(data))
using (var jsonReader = new JsonTextReader(stringReader))
{
return serializer.Deserialize<T>(jsonReader);
}
}

/// <summary>
/// Deserialize JToken object to T object.
/// </summary>
/// <typeparam name="T">Type of data.</typeparam>
/// <param name="serializer">Serializer.</param>
/// <param name="jToken">JToken to be deserialized.</param>
/// <returns>Deserialized data.</returns>
private T Deserialize<T>(JsonSerializer serializer, JToken jToken)
{
return jToken.ToObject<T>(serializer);
}

private JsonSerializer GetPayloadSerializer(int? version)
{
return version == 2 ? payloadSerializer2 : payloadSerializer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
// key value pairs.
foreach (var property in properties.Values<JToken>())
{
var testProperty = property["Key"].ToObject<TestProperty>();
var testProperty = property["Key"].ToObject<TestProperty>(serializer);

// Let the null values be passed in as null data
var token = property["Value"];
Expand All @@ -43,7 +43,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
// If the property is already a string. No need to convert again.
if (token.Type == JTokenType.String)
{
propertyData = token.ToObject<string>();
propertyData = token.ToObject<string>(serializer);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
// key value pairs.
foreach (var property in properties)
{
var testProperty = property["Key"].ToObject<TestProperty>();
var testProperty = property["Key"].ToObject<TestProperty>(serializer);

// Let the null values be passed in as null data
var token = property["Value"];
Expand All @@ -58,7 +58,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
// If the property is already a string. No need to convert again.
if (token.Type == JTokenType.String)
{
propertyData = token.ToObject(typeof(string));
propertyData = token.ToObject(typeof(string), serializer);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
// key value pairs.
foreach (var property in properties.Values<JToken>())
{
var testProperty = property["Key"].ToObject<TestProperty>();
var testProperty = property["Key"].ToObject<TestProperty>(serializer);

// Let the null values be passed in as null data
var token = property["Value"];
Expand All @@ -70,7 +70,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
// If the property is already a string. No need to convert again.
if (token.Type == JTokenType.String)
{
propertyData = token.ToObject<string>();
propertyData = token.ToObject<string>(serializer);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec
{
EqtTrace.Info("Discovery Session Initialize.");
this.testHostManagerFactoryReady.Wait();
var pathToAdditionalExtensions = message.Payload.ToObject<IEnumerable<string>>();
var pathToAdditionalExtensions = this.dataSerializer.DeserializePayload<IEnumerable<string>>(message);
jobQueue.QueueJob(
() =>
testHostManagerFactory.GetDiscoveryManager().Initialize(pathToAdditionalExtensions), 0);
Expand All @@ -252,7 +252,7 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec
EqtTrace.Info("Discovery started.");
this.testHostManagerFactoryReady.Wait();
var discoveryEventsHandler = new TestDiscoveryEventHandler(this);
var discoveryCriteria = message.Payload.ToObject<DiscoveryCriteria>();
var discoveryCriteria = this.dataSerializer.DeserializePayload<DiscoveryCriteria>(message);
jobQueue.QueueJob(
() =>
testHostManagerFactory.GetDiscoveryManager()
Expand All @@ -265,7 +265,7 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec
{
EqtTrace.Info("Execution Session Initialize.");
this.testHostManagerFactoryReady.Wait();
var pathToAdditionalExtensions = message.Payload.ToObject<IEnumerable<string>>();
var pathToAdditionalExtensions = this.dataSerializer.DeserializePayload<IEnumerable<string>>(message);
jobQueue.QueueJob(
() =>
testHostManagerFactory.GetExecutionManager().Initialize(pathToAdditionalExtensions), 0);
Expand All @@ -277,7 +277,7 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec
EqtTrace.Info("Execution started.");
var testRunEventsHandler = new TestRunEventsHandler(this);
this.testHostManagerFactoryReady.Wait();
var testRunCriteriaWithSources = message.Payload.ToObject<TestRunCriteriaWithSources>();
var testRunCriteriaWithSources = this.dataSerializer.DeserializePayload<TestRunCriteriaWithSources>(message);
jobQueue.QueueJob(
() =>
testHostManagerFactory.GetExecutionManager()
Expand Down
Loading

0 comments on commit 5689373

Please sign in to comment.