Files
wehub-resource-sync 680845cb1c
Build containerization / Verify commit signatures (push) Has been skipped
Build containerization / containerization (push) Successful in 0s
Linux build / Linux compile check (push) Has been cancelled
Linux build / Determine Swift version (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:25:30 +08:00

132 lines
4.6 KiB
Swift

//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// 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 ContainerizationExtras
@Suite("IPv6 Mixed IPv4 Notation Tests")
struct IPv6IPv4ParsingTests {
@Test(
"Extract IPv4 suffix from various IPv6 formats",
arguments: [
("::192.168.1.1", "::", [UInt8(192), UInt8(168), UInt8(1), UInt8(1)]),
("::ffff:192.0.2.1", "::ffff", [UInt8(192), UInt8(0), UInt8(2), UInt8(1)]),
("fe80::192.168.1.1", "fe80::", [UInt8(192), UInt8(168), UInt8(1), UInt8(1)]),
("2001:db8::192.0.2.1", "2001:db8::", [UInt8(192), UInt8(0), UInt8(2), UInt8(1)]),
("0:0:0:0:0:0:192.168.1.1", "0:0:0:0:0:0", [UInt8(192), UInt8(168), UInt8(1), UInt8(1)]),
]
)
func testIPv4SuffixExtraction(input: String, expectedIPv6: String, expectedIPv4: [UInt8]) throws {
let result = try #require(try IPv6Address.extractIPv4Suffix(from: input))
#expect(result.0 == expectedIPv6)
#expect(result.1 == expectedIPv4)
}
@Test(
"No IPv4 suffix for pure IPv6 addresses",
arguments: [
"2001:db8::1",
"fe80::1",
"::",
"::1",
]
)
func testPureIPv6ReturnsNil(address: String) throws {
#expect(try IPv6Address.extractIPv4Suffix(from: address) == nil)
}
@Test(
"Invalid IPv4 suffix throws error",
arguments: [
"::256.1.1.1",
"::192.168.1",
"::192.168.001.1",
]
)
func testInvalidIPv4Throws(invalid: String) {
#expect(throws: AddressError.self) {
_ = try IPv6Address.extractIPv4Suffix(from: invalid)
}
}
@Test(
"IPv4 bytes always at positions 12-15",
arguments: [
"::192.168.1.1",
"::ffff:127.0.0.1",
"fe80::10.0.0.1",
]
)
func testIPv4BytePlacement(address: String) throws {
let parsed = try IPv6Address.parse(address)
let ipv4String = String(address.split(separator: ":").last!)
let ipv4 = try IPv4Address.parse(ipv4String)
#expect(parsed.bytes[12] == UInt8((ipv4 >> 24) & 0xFF))
#expect(parsed.bytes[13] == UInt8((ipv4 >> 16) & 0xFF))
#expect(parsed.bytes[14] == UInt8((ipv4 >> 8) & 0xFF))
#expect(parsed.bytes[15] == UInt8(ipv4 & 0xFF))
}
@Test(
"Unspecified address with IPv4 suffix",
arguments: [
("::192.168.1.1", [UInt8(192), UInt8(168), UInt8(1), UInt8(1)]),
("::0.0.0.1", [UInt8(0), UInt8(0), UInt8(0), UInt8(1)]),
("::255.255.255.255", [UInt8(255), UInt8(255), UInt8(255), UInt8(255)]),
]
)
func testUnspecifiedWithIPv4(address: String, ipv4: [UInt8]) throws {
let parsed = try IPv6Address.parse(address)
#expect(parsed.bytes[0..<12].allSatisfy { $0 == 0 })
#expect(Array(parsed.bytes[12..<16]) == ipv4)
}
@Test("IPv4 with zone identifier")
func testIPv4WithZone() throws {
let parsed = try IPv6Address.parse("::192.168.1.1%lo0")
#expect(parsed.zone == "lo0")
#expect(Array(parsed.bytes[12..<16]) == [192, 168, 1, 1])
}
@Test(
"IPv4-mapped addresses (::ffff:x.x.x.x)",
arguments: [
"::ffff:127.0.0.1",
"::ffff:192.168.1.1",
]
)
func testIPv4MappedAddresses(address: String) throws {
let parsed = try IPv6Address.parse(address)
#expect(parsed.bytes[0..<10].allSatisfy { $0 == 0 })
#expect(parsed.bytes[10] == 0xff && parsed.bytes[11] == 0xff)
}
@Test("Complex ellipsis with IPv4")
func testComplexEllipsisWithIPv4() throws {
let address = "2001:db8:85a3::8a2e:192.168.1.1"
let parsed = try IPv6Address.parse(address)
#expect(parsed.bytes[10] == 0x8a && parsed.bytes[11] == 0x2e)
#expect(Array(parsed.bytes[12..<16]) == [192, 168, 1, 1])
}
}