Skip to content

Commit

Permalink
DYN1198- Heterogeneous list update gives infinite loop (DynamoDS#9408)
Browse files Browse the repository at this point in the history
* Heterogenous list crash fix

* Adding test case for heterogeneous list crash

* Adding tests

* Adding new test

* fix remaining edge cases

* revert assemblysharedinfo file

* Updating failing tests

* add new method to prevent API break

* simplify SelectMany
  • Loading branch information
reddyashish authored and aparajit-pratap committed Jan 13, 2019
1 parent 8ecd628 commit e7e9388
Show file tree
Hide file tree
Showing 5 changed files with 471 additions and 24 deletions.
52 changes: 28 additions & 24 deletions src/Engine/ProtoCore/Lang/Replication/Replicator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,46 +201,50 @@ public static List<List<StackValue>> ComputeAllReducedParams(
RuntimeCore runtimeCore)
{
//Copy the types so unaffected ones get copied back directly
List<StackValue> basicList = new List<StackValue>(formalParams);
var basicList = new List<StackValue>(formalParams);

//Compute the reduced Type args
List<List<StackValue>> reducedParams = new List<List<StackValue>>();
var reducedParams = new List<List<StackValue>>();
reducedParams.Add(basicList);

foreach (ReplicationInstruction ri in replicationInstructions)
foreach (var ri in replicationInstructions)
{
var indices = ri.Zipped ? ri.ZipIndecies : new List<int> { ri.CartesianIndex };
foreach (int index in indices)
{
//This should generally be a collection, so we need to do a one phase unboxing
var targets = reducedParams.Select(r => r[index]).ToList();
foreach (var target in targets)
var target = basicList[index];

if (!target.IsArray)
{
if (!target.IsArray)
{
System.Console.WriteLine("WARNING: Replication unbox requested on Singleton. Trap: 437AD20D-9422-40A3-BFFD-DA4BAD7F3E5F");
continue;
}
System.Console.WriteLine("WARNING: Replication unbox requested on Singleton. Trap: 437AD20D-9422-40A3-BFFD-DA4BAD7F3E5F");
continue;
}

var array = runtimeCore.Heap.ToHeapObject<DSArray>(target);
if (array.Count == 0)
{
continue;
}
var array = runtimeCore.Heap.ToHeapObject<DSArray>(target);
if (array.Count == 0)
{
continue;
}

var arrayStats = ArrayUtils.GetTypeExamplesForLayer(target, runtimeCore).Values;
var arrayStats = new HashSet<StackValue>();
foreach (var targetTemp in targets)
{
var temp = ArrayUtils.GetTypeExamplesForLayer2(targetTemp, runtimeCore).ToList();
arrayStats.UnionWith(temp);
}

List<List<StackValue>> clonedList = new List<List<StackValue>>(reducedParams);
reducedParams.Clear();
var clonedList = new List<List<StackValue>>(reducedParams);
reducedParams.Clear();

foreach (StackValue sv in arrayStats)
foreach (var sv in arrayStats)
{
foreach (var lst in clonedList)
{
foreach (List<StackValue> lst in clonedList)
{
List<StackValue> newArgs = new List<StackValue>(lst);
newArgs[index] = sv;
reducedParams.Add(newArgs);
}
var newArgs = new List<StackValue>(lst);
newArgs[index] = sv;
reducedParams.Add(newArgs);
}
}
}
Expand Down
41 changes: 41 additions & 0 deletions src/Engine/ProtoCore/Utils/ArrayUtils.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using ProtoCore.DSASM;
using ProtoCore.Exceptions;
using ProtoCore.Runtime;
Expand Down Expand Up @@ -117,6 +118,7 @@ public static ClassNode GetGreatestCommonSubclassForArray(StackValue array, Runt
return runtimeCore.DSExecutable.classTable.ClassNodes[orderedTypes.First()];
}

// TODO gantaa/pratapa: Remove this deprecated method in 3.0 and rename GetTypeExamplesForLayer2
public static Dictionary<int, StackValue> GetTypeExamplesForLayer(StackValue array, RuntimeCore runtimeCore)
{
Dictionary<int, StackValue> usageFreq = new Dictionary<int, StackValue>();
Expand All @@ -138,6 +140,45 @@ public static Dictionary<int, StackValue> GetTypeExamplesForLayer(StackValue arr
return usageFreq;
}

public static IEnumerable<StackValue> GetTypeExamplesForLayer2(StackValue array, RuntimeCore runtimeCore)
{
var usageFreq = new Dictionary<int, List<StackValue>>();

if (!array.IsArray)
{
usageFreq.Add(array.metaData.type, new List<StackValue> {array});

// return flattened list of unique values
return usageFreq.Values.SelectMany(x => x);
}

//This is the element on the heap that manages the data structure
var dsArray = runtimeCore.Heap.ToHeapObject<DSArray>(array);
foreach (var sv in dsArray.Values)
{
// If sv is an array type, continue adding array values to usageFreq dictionary
// as different arrays need not necessarily contain the same types.
if (sv.IsArray)
{
List<StackValue> list;
if (usageFreq.TryGetValue(sv.metaData.type, out list))
{
list.Add(sv);
}
else
{
usageFreq.Add(sv.metaData.type, new List<StackValue> {sv});
}
}
else if (!usageFreq.ContainsKey(sv.metaData.type))
{
usageFreq.Add(sv.metaData.type, new List<StackValue> {sv});
}
}
// return flattened list of unique values
return usageFreq.Values.SelectMany(x => x);
}



/// <summary>
Expand Down
14 changes: 14 additions & 0 deletions test/DynamoCoreTests/DSEvaluationModelTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,20 @@ public void TestMAGN9507()
OpenModel(dynFilePath);
AssertPreviewValue("3bf992eb-ecc9-4fcc-a90b-9b1ee7e925e9", 3);
}

[Test, Category("UnitTests")]
public void TestHeterogenousList()
{
// open test graph
RunModel(@"core\dsevaluation\test_hetereogenous_list.dyn");

var guidX = "0cb9b9ea3c004c099c31ddfac1ebbb09";
var guidY = "e7711f22858f4ea6bb23112f274b8914";
var guidZ = "a8519f77028643d4af2c0bc415a163fc";
AssertPreviewValue(guidX, new object[] { null, null, null, 5 });
AssertPreviewValue(guidY, new object[] { null, null, null, 10.2 });
AssertPreviewValue(guidZ, new object[] { null, null, null, 15.2 });
}
}

[Category("DSCustomNode")]
Expand Down
45 changes: 45 additions & 0 deletions test/Engine/ProtoTest/Associative/BuiltinMethodsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,51 @@ public void TestTryGetValuesFromDictionary08()
thisTest.Verify("r", null);
}

[Test]
public void TestTryGetValuesFromDictionary09()
{
string code = @"
a = { ""in"" : 42, ""out"" : 24 };
b = { ""in"" : 24, ""out"" : 42 };
c = [[a],[[b]]];
r1 = Dictionary.ValueAtKey(c, ""in"");
r2 = Dictionary.ValueAtKey(c, ""out"");
";
var mirror = thisTest.RunScriptSource(code);
thisTest.Verify("r1", new object[] { new object[] { 42 } , new object[] { new object[] { 24 } } });
thisTest.Verify("r2", new object[] { new object[] { 24 } , new object[] { new object[] { 42 } } });
}

[Test]
public void TestTryGetValuesFromDictionary10()
{
string code = @"
a = { ""in"" : 42, ""out"" : 24 };
b = { ""in"" : 24, ""out"" : 42 };
c = [[[a]],b];
r1 = Dictionary.ValueAtKey(c, ""in"");
r2 = Dictionary.ValueAtKey(c, ""out"");
";
var mirror = thisTest.RunScriptSource(code);
thisTest.Verify("r1", new object[] { new object[] { new object[] { 42 } }, 24 });
thisTest.Verify("r2", new object[] { new object[] { new object[] { 24 } }, 42 });
}

[Test]
public void TestTryGetValuesFromDictionary11()
{
string code = @"
a = [ ""in"" , 42, ""out"" , 24 ];
b = { ""in"" : 24, ""out"" : 42 };
c = [a,[b]];
r1 = Dictionary.ValueAtKey(c, ""in"");
r2 = Dictionary.ValueAtKey(c, ""out"");
";
var mirror = thisTest.RunScriptSource(code);
thisTest.Verify("r1", new object[] { new object[] { null, null, null, null }, new object[] { 24 } });
thisTest.Verify("r2", new object[] { new object[] { null, null, null, null }, new object[] { 42 } });
}

[Test]
public void TestGetKeysFromNonArray()
{
Expand Down
Loading

0 comments on commit e7e9388

Please sign in to comment.