public void OrderSensitiveValueComparisonListTests_DefaultObjectComparer() { var equalityComparer = new DefaultObjectComparer <ArtifactChange>(); var listOne = CreateTestList(equalityComparer); // Populate the second list with references from the first. var listTwo = new OrderSensitiveValueComparisonList <ArtifactChange>(equalityComparer); for (int i = 0; i < listOne.Count; i++) { listTwo.Add(listOne[i]); } // Every list s/be equal to itself. listOne.Equals(listOne).Should().Be(true); // Two lists with shared objects, by reference, in the same // order should be regarded as equivalent. listOne.Equals(listTwo).Should().Be(true); ArtifactChange toSwap = listTwo[0]; listTwo[0] = listTwo[1]; listTwo[1] = toSwap; // We have reordered two objects that are themselves identical. // The comparison should fail as the order of references changed. listOne.Equals(listTwo).Should().Be(false); }
private static OrderSensitiveValueComparisonList <Artifact> ConstructFilesChain(IList <Artifact> existingFiles, Artifact currentFile) { var fileChain = new OrderSensitiveValueComparisonList <Artifact>(Artifact.ValueComparer); int parentIndex; do { currentFile = currentFile.DeepClone(); parentIndex = currentFile.ParentIndex; // Index information is entirely irrelevant for the identity of nested files, // as each element of the chain could be stored at arbitrary locations in // the run.files table. And so we elide this information. currentFile.ParentIndex = -1; if (currentFile.Location != null) { currentFile.Location.Index = -1; } fileChain.Add(currentFile); if (parentIndex != -1) { currentFile = existingFiles[parentIndex]; } } while (parentIndex != -1); return(fileChain); }
private static OrderSensitiveValueComparisonList <LogicalLocation> ConstructLogicalLocationsChain( LogicalLocation currentLogicalLocation, IList <LogicalLocation> existingLogicalLocations) { var logicalLocationChain = new OrderSensitiveValueComparisonList <LogicalLocation>(LogicalLocation.ValueComparer); int parentIndex; do { currentLogicalLocation = currentLogicalLocation.DeepClone(); parentIndex = currentLogicalLocation.ParentIndex; // Index information is entirely irrelevant for the identity of nested logical locations, // as each element of the chain could be stored at arbitrary locations in the // run.logicalLocations table. And so we elide this information. currentLogicalLocation.ParentIndex = -1; currentLogicalLocation.Index = -1; logicalLocationChain.Add(currentLogicalLocation); if (parentIndex != -1) { currentLogicalLocation = existingLogicalLocations[parentIndex]; } } while (parentIndex != -1); return(logicalLocationChain); }
private int CacheArtifact(Artifact artifact, IList <Artifact> currentArtifacts) { artifact = artifact.DeepClone(); int parentIndex = artifact.ParentIndex; // Ensure all parent nodes are remapped. if (parentIndex != -1) { // Important: the input results we are rewriting need to refer // to the historical files index in order to understand parenting. artifact.ParentIndex = CacheArtifact(currentArtifacts[parentIndex], currentArtifacts); } // Equally important, the artifact chain is a specially constructed key that // operates against the newly constructed files array in CurrentArtifacts. OrderSensitiveValueComparisonList <Artifact> artifactChain = ConstructArtifactsChain(artifact, Artifacts); if (!ArtifactToIndex.TryGetValue(artifactChain, out int remappedIndex)) { remappedIndex = ArtifactToIndex.Count; this.Artifacts.Add(artifact); ArtifactToIndex[artifactChain] = remappedIndex; Debug.Assert(ArtifactToIndex.Count == this.Artifacts.Count); if (artifact.Location != null) { artifact.Location.Index = remappedIndex; } } return(remappedIndex); }
private int CacheLogicalLocation(LogicalLocation logicalLocation, IList <LogicalLocation> currentLogicalLocations) { logicalLocation = logicalLocation.DeepClone(); // Ensure all parent nodes are remapped. int parentIndex = logicalLocation.ParentIndex; if (parentIndex != -1) { logicalLocation.ParentIndex = CacheLogicalLocation(currentLogicalLocations[parentIndex], currentLogicalLocations); } OrderSensitiveValueComparisonList <LogicalLocation> logicalLocationChain = ConstructLogicalLocationsChain(logicalLocation, LogicalLocations); if (!LogicalLocationToIndex.TryGetValue(logicalLocationChain, out int remappedIndex)) { remappedIndex = LogicalLocationToIndex.Count; logicalLocation.Index = remappedIndex; this.LogicalLocations.Add(logicalLocation); LogicalLocationToIndex[logicalLocationChain] = remappedIndex; } return(remappedIndex); }
public void OrderSensitiveValueComparisonListTests_ValueComparer() { // Two identical lists with elements that are // distinct objects, by reference. OrderSensitiveValueComparisonList <ArtifactChange> listOne = CreateTestList(ArtifactChange.ValueComparer); OrderSensitiveValueComparisonList <ArtifactChange> listTwo = CreateTestList(ArtifactChange.ValueComparer); // Every list s/be equal to itself listOne.Equals(listOne).Should().Be(true); // As initialized, these objects are different, due // to a unique GUID property on each list listOne.Equals(listTwo).Should().Be(false); // Make the two lists equivalent, by value listTwo[2].SetProperty(DIFFERENTIATING_PROPERTY_NAME, listOne[2].GetProperty <Guid>(DIFFERENTIATING_PROPERTY_NAME)); listOne.Equals(listTwo).Should().Be(true); ArtifactChange toSwap = listTwo[0]; listTwo[0] = listTwo[1]; listTwo[1] = toSwap; // We have reordered two objects that are themselves identical. // by value. The comparison should still succeed. listOne.Equals(listTwo).Should().Be(true); }
private OrderSensitiveValueComparisonList <ArtifactChange> CreateTestList(IEqualityComparer <ArtifactChange> equalityComparer) { // Test list. First two elements are identical. The third element is unique. var fileChangeOne = new ArtifactChange(); var fileChangeTwo = new ArtifactChange(); var fileChangeThree = new ArtifactChange(); Guid differentiatingProperty = Guid.NewGuid(); fileChangeThree.SetProperty(DIFFERENTIATING_PROPERTY_NAME, differentiatingProperty); var list = new OrderSensitiveValueComparisonList <ArtifactChange>(equalityComparer); list.AddRange(new[] { fileChangeOne, fileChangeTwo, fileChangeThree }); return(list); }