diff --git a/Differ.xcodeproj/project.pbxproj b/Differ.xcodeproj/project.pbxproj index 8dfb19d..accdfb1 100644 --- a/Differ.xcodeproj/project.pbxproj +++ b/Differ.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 6F5641F027B09338009F0F6F /* ExtendedPatchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5641EF27B09338009F0F6F /* ExtendedPatchTests.swift */; }; 900E03A41DE7C6C60033A799 /* Differ.h in Headers */ = {isa = PBXBuildFile; fileRef = C92178BB1CD0023E004642C7 /* Differ.h */; settings = {ATTRIBUTES = (Public, ); }; }; 900E03A51DE7C6D60033A799 /* Differ.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9EE87161CCFCA83006BD90E /* Differ.framework */; }; 90382F122075D23E006EFFBF /* NestedBatchUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90382F112075D23E006EFFBF /* NestedBatchUpdate.swift */; }; @@ -44,6 +45,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 6F5641EF27B09338009F0F6F /* ExtendedPatchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtendedPatchTests.swift; sourceTree = ""; }; 900E039F1DE7C3370033A799 /* Universal-Framework-Target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Universal-Framework-Target.xcconfig"; sourceTree = ""; }; 900E03A01DE7C3370033A799 /* Universal-Target-Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Universal-Target-Base.xcconfig"; sourceTree = ""; }; 900E03AF1DE7F1E80033A799 /* Deployment-Targets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Deployment-Targets.xcconfig"; sourceTree = ""; }; @@ -138,6 +140,7 @@ C921BF701E15448300747566 /* NestedExtendedDiffTests.swift */, C991189D1DDB4F1100067A60 /* PatchApplyTests.swift */, C9C924791DBB97130006ACC4 /* PatchSortTests.swift */, + 6F5641EF27B09338009F0F6F /* ExtendedPatchTests.swift */, ); path = DifferTests; sourceTree = ""; @@ -279,6 +282,7 @@ C921BF711E15448300747566 /* NestedExtendedDiffTests.swift in Sources */, C90CD7191DFB43C600BE9114 /* NestedDiffTests.swift in Sources */, E2F1C8561E3A14DF00FBE786 /* BatchUpdateTests.swift in Sources */, + 6F5641F027B09338009F0F6F /* ExtendedPatchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests/DifferTests/ExtendedPatchTests.swift b/Tests/DifferTests/ExtendedPatchTests.swift new file mode 100644 index 0000000..eca2362 --- /dev/null +++ b/Tests/DifferTests/ExtendedPatchTests.swift @@ -0,0 +1,77 @@ +import XCTest +import Differ + +class ExtendedPatchTests: XCTestCase { + func testDifferScenario1() throws { + let input = [1, 3, 4] + let output = [1, 2, 3, 4] + let result = runDiffer(start: input, end: output) + XCTAssertEqual(output, result) + } + + func testDifferScenario2() throws { + let input = [1, 2, 3, 4] + let output = [1, 3, 4] + let result = runDiffer(start: input, end: output) + XCTAssertEqual(output, result) + } + + func testDifferScenario3() throws { + let input = [1, 2, 3, 4] + let output = [4, 3, 2, 1] + let result = runDiffer(start: input, end: output) + XCTAssertEqual(output, result) + } + + /// This fails: Thread 1: Fatal error: Index out of range + /// MOVE number from 8 4 [4, 4, 3, 8, 2, 5, 6, 9] + /// The array is only 8 elements long, not 9 + func testDifferScenarioFailure() throws { + let input = [7, 2, 5, 6, 9] + let output = [4, 4, 3, 8, 9, 5, 2, 5] + let result = runDiffer(start: input, end: output) + XCTAssertEqual(output, result) + } + + /// This is another example of a failed scenario + func testDifferScenarioFailure_alternative() throws { + let input = [9, 0, 10, 5] + let output = [1, 2, 7, 5, 6, 5, 10, 6, 9, 10] + let result = runDiffer(start: input, end: output) + XCTAssertEqual(output, result) + } + + func testDifferScenario5() throws { + let input = [7, 2, 5, 6, 9] + let output = [4, 4, 3, 8, 9, 5, 2, 5] + let result = runDiffer(start: input, end: output) + XCTAssertEqual(output, result) + } +} + +private func runDiffer(start: [T], end: [T]) -> [T] { + let patches = Differ.extendedPatch(from: start, to: end) + var workingSet = start + + for patch in patches { + switch patch { + case .insertion(index: let index, element: let element): + print("INSERT \(element) at", index) + workingSet.insert(element, at: index) + print(workingSet) + case .deletion(index: let index): + print("REMOVE \(workingSet[index]) at", index) + workingSet.remove(at: index) + print(workingSet) + case .move(from: let from, to: let to): + print("MOVE number from", from, to, workingSet) + let val = workingSet[from] + print(val) + workingSet.remove(at: from) + workingSet.insert(val, at: to) + print(workingSet) + } + } + + return workingSet +}