mirror of
https://github.com/apple/container.git
synced 2026-07-15 05:57:01 +00:00
0885cdd6a9
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
87 lines
3.2 KiB
Swift
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)
|
|
}
|
|
}
|
|
}
|