#![cfg(feature = "swift")]
pub mod common;
use common::{Choice, Test};
use facet_generate::generation::{CodeGeneratorConfig, Encoding, SourceInstaller, swift};
use std::{fs::File, io::Write as _, path::Path, process::Command};
#[test]
fn test_swift_runtime_autotests() {
let runtime_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("runtime/swift");
let status = Command::new("swift")
.current_dir(runtime_path.to_str().unwrap())
.arg("test")
.status()
.unwrap();
assert!(status.success());
}
#[test]
fn test_swift_bincode_runtime_on_simple_data() {
let dir = tempfile::tempdir().unwrap();
let config = CodeGeneratorConfig::new("Testing".to_string()).with_encoding(Encoding::Bincode);
let registry = common::get_simple_registry();
let mut installer = swift::Installer::new(&config.module_name, dir.path());
installer.install_module(&config, ®istry).unwrap();
installer.install_serde_runtime().unwrap();
let reference = bincode::serialize(&Test {
a: vec![4, 6],
b: (-3, 5),
c: Choice::C { x: 7 },
})
.unwrap();
std::fs::create_dir_all(dir.path().join("Sources/main")).unwrap();
let main_path = dir.path().join("Sources/main/main.swift");
let mut main = File::create(main_path).unwrap();
writeln!(
main,
r#"
import Serde
import Testing
var input : [UInt8] = [{0}]
let value = try Test.bincodeDeserialize(input: input)
let value2 = Test.init(
a: [4, 6],
b: Tuple2.init(-3, 5),
c: Choice.c(x: 7)
)
assert(value == value2, "value != value2")
let output = try value2.bincodeSerialize()
assert(input == output, "input != output")
input += [0]
do {{
let _ = try Test.bincodeDeserialize(input: input)
assertionFailure("Was expecting an error")
}}
catch {{}}
do {{
let input2 : [UInt8] = [0, 1]
let _ = try Test.bincodeDeserialize(input: input2)
assertionFailure("Was expecting an error")
}}
catch {{}}
"#,
reference
.iter()
.map(|x| format!("{x}"))
.collect::<Vec<_>>()
.join(", "),
)
.unwrap();
let mut file = File::create(dir.path().join("Package.swift")).unwrap();
write!(
file,
r#"// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "Testing",
targets: [
.target(
name: "Serde",
dependencies: []),
.target(
name: "Testing",
dependencies: ["Serde"]),
.target(
name: "main",
dependencies: ["Serde", "Testing"]
),
]
)
"#
)
.unwrap();
let status = Command::new("swift")
.current_dir(dir.path())
.arg("run")
.status()
.unwrap();
assert!(status.success());
}
#[test]
fn test_swift_bincode_runtime_on_supported_types() {
let dir = tempfile::tempdir().unwrap();
let config = CodeGeneratorConfig::new("Testing".to_string()).with_encoding(Encoding::Bincode);
let registry = common::get_registry();
let mut installer = swift::Installer::new(&config.module_name, dir.path());
installer.install_module(&config, ®istry).unwrap();
installer.install_serde_runtime().unwrap();
std::fs::create_dir_all(dir.path().join("Sources/main")).unwrap();
let main_path = dir.path().join("Sources/main/main.swift");
let mut main = File::create(main_path).unwrap();
let positive_encodings = common::get_positive_samples()
.iter()
.map(|bytes| quote_bytes(bytes))
.collect::<Vec<_>>()
.join(", ");
writeln!(
main,
r#"
import Serde
import Testing
let positive_inputs : [[UInt8]] = [{positive_encodings}]
for input in positive_inputs {{
let value = try SerdeData.bincodeDeserialize(input: input)
let output = try value.bincodeSerialize()
assert(input == output, "input != output:\n \(input)\n \(output)")
// Test self-equality for the Serde value.
let value2 = try SerdeData.bincodeDeserialize(input: input)
assert(value == value2, "Deserialized value should test equal to itself: \(input)")
// Test simple mutations of the input.
for i in 0..<min(40, input.count) {{
var input3 = input
input3[i] ^= 0x80
let value3 = try? SerdeData.bincodeDeserialize(input: input3)
if let value3 = value3 {{
assert(value3 != value, "Modified input should give a different value:\n \(input)\n \(input3)")
}}
}}
}}
"#,
)
.unwrap();
let mut file = File::create(dir.path().join("Package.swift")).unwrap();
write!(
file,
r#"// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "Testing",
targets: [
.target(
name: "Serde",
dependencies: []),
.target(
name: "Testing",
dependencies: ["Serde"]),
.target(
name: "main",
dependencies: ["Serde", "Testing"]
),
]
)
"#
)
.unwrap();
let status = Command::new("swift")
.current_dir(dir.path())
.arg("run")
.status()
.unwrap();
assert!(status.success());
}
fn quote_bytes(bytes: &[u8]) -> String {
format!(
"[{}]",
bytes
.iter()
.map(|x| format!("{x}"))
.collect::<Vec<_>>()
.join(", ")
)
}