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

Fix - Avoid usage of JsonConvert in test host process #1881

Merged
merged 4 commits into from
Jan 3, 2019
Merged
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
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