Skip to content

Commit 2ec221a

Browse files
authored
Fix bug when comparing the Platform struct (#833)
This fixes a latent bug in the `Platform` types equality operator where two platforms with differing OS's would be treated as the same if they both had variant set to 'v8' or nil
1 parent 5796abe commit 2ec221a

2 files changed

Lines changed: 45 additions & 14 deletions

File tree

Sources/ContainerizationOCI/Platform.swift

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -250,25 +250,22 @@ extension Platform: Hashable {
250250

251251
/// `==` compares if **lhs** and **rhs** are the exact same platforms.
252252
public static func == (lhs: Platform, rhs: Platform) -> Bool {
253+
guard lhs.os == rhs.os else {
254+
return false
255+
}
256+
guard lhs.architecture == rhs.architecture else {
257+
return false
258+
}
259+
253260
// NOTE:
254261
// If the platform struct was created by setting the fields directly and not using (from: String)
255262
// then, there is a possibility that for arm64 architecture, the variant may be set to nil
256263
// In that case, the variant should be assumed to v8
257-
if lhs.architecture == "arm64" && rhs.architecture == "arm64" {
258-
// The following checks effectively verify
259-
// that one operand has nil value and other has "v8"
260-
if lhs.variant == nil || rhs.variant == nil {
261-
if lhs.variant == "v8" || rhs.variant == "v8" {
262-
return true
263-
}
264-
}
264+
if lhs.architecture == "arm64" {
265+
return (lhs.variant ?? "v8") == (rhs.variant ?? "v8")
265266
}
266267

267-
let osEqual = lhs.os == rhs.os
268-
let archEqual = lhs.architecture == rhs.architecture
269-
let variantEqual = lhs.variant == rhs.variant
270-
271-
return osEqual && archEqual && variantEqual
268+
return lhs.variant == rhs.variant
272269
}
273270

274271
public func hash(into hasher: inout Swift.Hasher) {

Tests/ContainerizationOCITests/OCIPlatformTests.swift

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ struct OCIPlatformTests {
3333

3434
@Test func differentOS() {
3535
let lhs = Platform(arch: "arm64", os: "linux")
36-
let rhs = Platform(arch: "arm64", os: "darwin")
36+
let rhs = Platform(arch: "arm64", os: "windows")
3737
#expect(lhs != rhs, "Different OS should not be equal")
3838
}
3939

@@ -81,4 +81,38 @@ struct OCIPlatformTests {
8181
set.insert(withoutVariant)
8282
#expect(set.contains(withV8), "arm64/v8 must be found in a Set that contains arm64 with nil variant")
8383
}
84+
85+
@Test func arm64_differentOS_nilAndV8() {
86+
let linux = Platform(arch: "arm64", os: "linux", variant: nil)
87+
let windows = Platform(arch: "arm64", os: "windows", variant: "v8")
88+
#expect(linux != windows, "The arm64 nil/v8 variant rule must not ignore a differing OS")
89+
#expect(windows != linux, "The arm64 nil/v8 variant rule must not ignore a differing OS")
90+
}
91+
92+
@Test func arm64_differentOS_bothV8() {
93+
let linux = Platform(arch: "arm64", os: "linux", variant: "v8")
94+
let windows = Platform(arch: "arm64", os: "windows", variant: "v8")
95+
#expect(linux != windows, "Same arch and variant but different OS => not equal")
96+
}
97+
98+
@Test func arm64_normalizedArchDifferentOS() {
99+
// aarch64 normalizes to arm64, so both sides hit the arm64 variant rule.
100+
let linux = Platform(arch: "aarch64", os: "linux", variant: nil)
101+
let windows = Platform(arch: "arm64", os: "windows", variant: "v8")
102+
#expect(linux != windows, "Normalized arm64 platforms with a differing OS => not equal")
103+
}
104+
105+
@Test func arm64_differentOS_setLookup() {
106+
let linux = Platform(arch: "arm64", os: "linux", variant: nil)
107+
let windows = Platform(arch: "arm64", os: "windows", variant: "v8")
108+
var set = Set<Platform>()
109+
set.insert(linux)
110+
#expect(!set.contains(windows), "windows/arm64/v8 must not be found in a Set holding linux/arm64")
111+
}
112+
113+
@Test func arm64_platformMatcherDifferentOS() {
114+
let matcher = createPlatformMatcher(for: Platform(arch: "arm64", os: "linux", variant: nil))
115+
#expect(!matcher(Platform(arch: "arm64", os: "windows", variant: "v8")), "matcher must reject a differing OS")
116+
#expect(matcher(Platform(arch: "arm64", os: "linux", variant: "v8")), "matcher must accept the same OS with an implied v8 variant")
117+
}
84118
}

0 commit comments

Comments
 (0)