Files
Sidhartha Mani 0885cdd6a9 Native Builder: DiffKey and Differ Procol (#482)
This PR introduces the `Differ` with methods:

```swift
// Differ protocol
func diff(base: Snapshot?, target: Snapshot) async throws -> Descriptor
func apply(descriptor: Descriptor, to base: Snapshot?) async throws -> Snapshot
```

It also introduces `DiffKey`, which is a MerkeTree based key for fast
diff computations between two dirs
2025-08-12 11:23:55 -07:00

87 lines
3.2 KiB
Swift

//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the container project authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
import Foundation
import Testing
@testable import ContainerBuildSnapshotter
@Suite struct FileContentDifferTests {
@Test func attributesOnlyShortCircuit() throws {
let d = FileContentDiffer()
let r = try d.diff(oldURL: nil, newURL: nil, attributesOnly: true)
#expect(r == .attributeOnly)
}
@Test func nilSidesMeanContentChanged() throws {
let d = FileContentDiffer()
// old only
#expect(try d.diff(oldURL: URL(fileURLWithPath: "/tmp/missing"), newURL: nil) == .contentChanged)
// new only
#expect(try d.diff(oldURL: nil, newURL: URL(fileURLWithPath: "/tmp/missing")) == .contentChanged)
}
@Test func equalContentAttributeOnly() throws {
try TestUtils.withTempDir { dir in
let a = dir.appendingPathComponent("a.txt")
let b = dir.appendingPathComponent("b.txt")
try TestUtils.writeString(a, "same")
try TestUtils.writeString(b, "same")
let d = FileContentDiffer()
let r = try d.diff(oldURL: a, newURL: b)
#expect(r == .attributeOnly)
}
}
@Test func changedContentDetected() throws {
try TestUtils.withTempDir { dir in
let a = dir.appendingPathComponent("a.txt")
let b = dir.appendingPathComponent("b.txt")
try TestUtils.writeString(a, "hello")
try TestUtils.writeString(b, "world")
let d = FileContentDiffer()
let r = try d.diff(oldURL: a, newURL: b)
#expect(r == .contentChanged)
}
}
@Test func largeFileChunking() throws {
try TestUtils.withTempDir { dir in
let a = dir.appendingPathComponent("a.bin")
let b = dir.appendingPathComponent("b.bin")
// ~10MB payload
let block = Data(repeating: 0xAB, count: 1024 * 1024) // 1MiB
var payload = Data()
for _ in 0..<10 { payload.append(block) }
try TestUtils.write(a, contents: payload)
try TestUtils.write(b, contents: payload)
let d = FileContentDiffer()
#expect(try d.diff(oldURL: a, newURL: b) == .attributeOnly)
// flip one byte
var changed = payload
changed[changed.count / 2] = 0xCD
try TestUtils.write(b, contents: changed)
#expect(try d.diff(oldURL: a, newURL: b) == .contentChanged)
}
}
}