Skip to content

Commit 1951e6a

Browse files
Merge pull request #7810 from Unity-Technologies/sg2/fix/hash-compute
[GSG-0] Fix hash computation
2 parents acedfed + c7ee730 commit 1951e6a

File tree

4 files changed

+122
-7
lines changed

4 files changed

+122
-7
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using System.Runtime.CompilerServices;
2+
3+
[assembly: InternalsVisibleTo("Unity.ContextLayeredDataStorage.Tests")]

com.unity.sg2/Editor/ContextLayeredDataStorage/AssemblyInfo.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.sg2/Editor/ContextLayeredDataStorage/ElementID.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,13 @@ private List<string> Path
103103
{
104104
m_pathList.Add(new string(subPath));
105105
}
106-
106+
107107
}
108108
return m_pathList;
109109
}
110110
}
111111

112-
private int PathHash(int index)
112+
internal int PathHash(int index)
113113
{
114114
if(m_pathHash == null)
115115
{
@@ -153,7 +153,7 @@ private int PathHash(int index)
153153
i++;
154154
if(i == index)
155155
{
156-
startIndex = j;
156+
startIndex = j+1;
157157
}
158158
if(i == index+1)
159159
{
@@ -167,7 +167,7 @@ private int PathHash(int index)
167167
length++;
168168
}
169169
}
170-
170+
171171
}
172172
m_pathHash[index] = GetDeterministicStringHash(m_fullPath, startIndex, length);
173173
}
@@ -230,17 +230,17 @@ public override int GetHashCode()
230230
return m_hash;
231231
}
232232

233-
private static int GetDeterministicStringHash(char[] str, int startIndex, int length)
233+
internal static int GetDeterministicStringHash(char[] str, int startIndex, int length)
234234
{
235235
unchecked
236236
{
237237
int hash1 = (5381 << 16) + 5381;
238238
int hash2 = hash1;
239239

240-
for (int i = startIndex; i < length; i += 2)
240+
for (int i = startIndex; i < startIndex + length; i += 2)
241241
{
242242
hash1 = ((hash1 << 5) + hash1) ^ str[i];
243-
if (i == length - 1)
243+
if (i == (startIndex + length) - 1)
244244
break;
245245
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
246246
}

com.unity.sg2/Tests/ContextLayeredDataStorage/ContextLayeredDataStorageTests.cs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,115 @@ public void TestCopyDataBranch()
409409

410410
}
411411

412+
[Test]
413+
public void DeterministicHashInsideStringWorks()
414+
{
415+
var string1 = "This.Is.The.First.String";
416+
var string2 = "The.Second.String.This.Is";
417+
418+
var thisLength = "This".Length;
419+
var s1ThisStart = 0;
420+
var s2ThisStart = string2.IndexOf("This");
421+
422+
Assert.AreEqual(
423+
ElementID.GetDeterministicStringHash(string1.ToCharArray(), s1ThisStart, thisLength),
424+
ElementID.GetDeterministicStringHash(string2.ToCharArray(), s2ThisStart, thisLength));
425+
}
426+
427+
[Test]
428+
public void PathHashFromFullPathIsNeverHashOfDot()
429+
{
430+
var dotHash = ElementID.GetDeterministicStringHash(".".ToCharArray(), 0, 0);
431+
var element = new ElementID("This.Is.A.Path");
432+
433+
for (var i = 0; i < 4; i++)
434+
{
435+
Assert.AreNotEqual(dotHash, element.PathHash(i));
436+
}
437+
}
438+
439+
[Test]
440+
public void PathHashFromCharPathIsNeverHashOfDot()
441+
{
442+
var dotHash = ElementID.GetDeterministicStringHash(".".ToCharArray(), 0, 0);
443+
var element = new ElementID(new []{"This", "Is", "A", "Path"});
444+
445+
for (var i = 0; i < 4; i++)
446+
{
447+
Assert.AreNotEqual(dotHash, element.PathHash(i));
448+
}
449+
}
450+
451+
[Test]
452+
public void PathHashFromCharPathAndFullPathAreSame()
453+
{
454+
var element1 = new ElementID(new []{"This", "Is", "A", "Path"});
455+
var element2 = new ElementID("This.Is.A.Path");
456+
457+
for (var i = 0; i < 4; i++)
458+
{
459+
Assert.AreEqual(element1.PathHash(i), element2.PathHash(i));
460+
}
461+
}
462+
463+
[Test]
464+
public void IsSubPathWorks()
465+
{
466+
var pathGroup1 = new[]
467+
{
468+
new ElementID("765348756348576348"),
469+
new ElementID("765348756348576348.A"),
470+
new ElementID("765348756348576348.A.Gjdhfgdj"),
471+
new ElementID("765348756348576348.A.Gjdhfgdj.93847")
472+
};
473+
474+
var pathGroup2 = new[]
475+
{
476+
new ElementID("765348756348576348"),
477+
new ElementID("765348756348576348.B"),
478+
new ElementID("765348756348576348.B.Gjdhfgdj"),
479+
new ElementID("765348756348576348.B.Gjdhfgdj.93847")
480+
};
481+
482+
var pathGroup3 = new[]
483+
{
484+
new ElementID("456438756348748376"),
485+
new ElementID("456438756348748376.A"),
486+
new ElementID("456438756348748376.A.Gjdhfgdj"),
487+
new ElementID("456438756348748376.A.Gjdhfgdj.93847")
488+
};
489+
490+
// Within each group, an element is the subpath of the next path.
491+
foreach (var group in new[] {pathGroup1, pathGroup2, pathGroup3})
492+
{
493+
for (var i = 0; i < group.Length - 1; i++)
494+
{
495+
Assert.IsTrue(group[i].IsSubpathOf(group[i+ 1]), $"IsSubpathOf failed at index {i} for {group}");
496+
}
497+
}
498+
499+
for (var i = 0; i < pathGroup1.Length; i++)
500+
{
501+
for (var j = 0; j < pathGroup2.Length; j++)
502+
{
503+
if (i != 0)
504+
Assert.IsFalse(pathGroup1[i].IsSubpathOf(pathGroup2[j]), $"IsSubpathOf failed at indices {i},{j}");
505+
506+
if (j != 0)
507+
Assert.IsFalse(pathGroup2[j].IsSubpathOf(pathGroup1[i]), $"IsSubpathOf failed at indices {i},{j}");
508+
}
509+
}
510+
511+
for (var i = 0; i < pathGroup1.Length; i++)
512+
{
513+
for (var j = 0; j < pathGroup3.Length; j++)
514+
{
515+
Assert.IsFalse(pathGroup1[i].IsSubpathOf(pathGroup3[j]), $"IsSubpathOf failed at indices {i},{j}");
516+
Assert.IsFalse(pathGroup3[j].IsSubpathOf(pathGroup1[i]), $"IsSubpathOf failed at indices {i},{j}");
517+
}
518+
}
519+
}
520+
412521
// TODO (Brett) This is commented out to bring tests to a passing status.
413522
// TODO (Brett) This test was not removed because it is indicating a valuable failure
414523
// TODO (Brett) that should be addressed.

0 commit comments

Comments
 (0)