use chrony_confile::prelude::*;
use std::fs;
use std::process;
fn run() -> bool {
let mut all_ok = true;
println!("\n=== SECTION 1: Zero-argument flags ===");
for (name, input) in [
("rtconutc", "rtconutc"),
("rtcsync", "rtcsync"),
("lock_all", "lock_all"),
("manual", "manual"),
("noclientlog", "noclientlog"),
("nosystemcert", "nosystemcert"),
("dumponexit", "dumponexit"),
] {
let test_name = format!("parse {}", name);
match ChronyConfig::parse(input) {
Ok(c) => {
if c.directives().count() == 1 {
println!(" PASS {:<55}", test_name);
} else {
println!(" FAIL {:<55} expected 1 directive, got {}", test_name, c.directives().count());
all_ok = false;
}
}
Err(e) => {
println!(" FAIL {:<55} {e}", test_name);
all_ok = false;
}
}
}
println!("\n=== SECTION 2: Single-string directives ===");
for (name, input, _expected_path) in [
("dumpdir", "dumpdir /var/lib/chrony", "/var/lib/chrony"),
("logdir", "logdir /var/log/chrony", "/var/log/chrony"),
("rtcdevice", "rtcdevice /dev/rtc0", "/dev/rtc0"),
("rtcfile", "rtcfile /var/lib/chrony/rtc", "/var/lib/chrony/rtc"),
("pidfile", "pidfile /run/chronyd.pid", "/run/chronyd.pid"),
("user", "user chrony", "chrony"),
("keyfile", "keyfile /etc/chrony/keys", "/etc/chrony/keys"),
("confdir", "confdir /etc/chrony.d", "/etc/chrony.d"),
("sourcedir", "sourcedir /var/lib/chrony", "/var/lib/chrony"),
("bindaddress", "bindaddress 0.0.0.0", "0.0.0.0"),
("ntsservercert", "ntsservercert /etc/chrony/cert.pem", "/etc/chrony/cert.pem"),
("ntsserverkey", "ntsserverkey /etc/chrony/key.pem", "/etc/chrony/key.pem"),
("ntsdumpdir", "ntsdumpdir /var/lib/chrony/nts", "/var/lib/chrony/nts"),
("ntpsigndsocket", "ntpsigndsocket /var/lib/samba/ntp_signd", "/var/lib/samba/ntp_signd"),
("ntsntpserver", "ntsntpserver nts.example.com", "nts.example.com"),
("leapsectz", "leapsectz right/UTC", "right/UTC"),
("leapseclist", "leapseclist /usr/share/zoneinfo/leap-seconds.list", "/usr/share/zoneinfo/leap-seconds.list"),
] {
let test_name = format!("parse {}", name);
match ChronyConfig::parse(input) {
Ok(c) => {
println!(" PASS {:<55}", test_name);
let output = c.to_string().trim().to_string();
let reparsed = ChronyConfig::parse(&format!("{output}\n"));
if reparsed.is_err() {
println!(" WARN {:<55} round-trip failed", format!("{name} round-trip"));
}
}
Err(e) => {
println!(" FAIL {:<55} {e}", test_name);
all_ok = false;
}
}
}
println!("\n=== SECTION 3: Integer directives ===");
for (name, input) in [
("port 123", "port 123"),
("port 0", "port 0"),
("cmdport 323", "cmdport 323"),
("dscp 46", "dscp 46"),
("minsources 2", "minsources 2"),
("maxsamples 32", "maxsamples 32"),
("minsamples 8", "minsamples 8"),
("logbanner 64", "logbanner 64"),
("maxntsconnections 200", "maxntsconnections 200"),
("ntsrotate 86400", "ntsrotate 86400"),
("ntsrefresh 1209600", "ntsrefresh 1209600"),
("refresh 604800", "refresh 604800"),
("sched_priority 50", "sched_priority 50"),
("ptpdomain 100", "ptpdomain 100"),
("ntsprocesses 4", "ntsprocesses 4"),
("maxtxbuffers 512", "maxtxbuffers 512"),
("ptpport 319", "ptpport 319"),
("acquisitionport 12345", "acquisitionport 12345"),
("ntsport 4460", "ntsport 4460"),
] {
match ChronyConfig::parse(input) {
Ok(_) => println!(" PASS {:<55}", format!("parse {name}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("parse {name}"));
all_ok = false;
}
}
}
for (name, input) in [
("port not a number", "port abc"),
("dscp out of range", "dscp 100"),
("sched_priority out of range", "sched_priority 200"),
] {
match ChronyConfig::parse(input) {
Err(_) => println!(" PASS {:<55}", format!("{name} → error")),
Ok(_) => {
println!(" FAIL {:<55} expected error", format!("{name} → error"));
all_ok = false;
}
}
}
println!("\n=== SECTION 4: Double directives ===");
for (name, input) in [
("clockprecision 1e-6", "clockprecision 1e-6"),
("corrtimeratio 2.5", "corrtimeratio 2.5"),
("maxdistance 5.0", "maxdistance 5.0"),
("maxjitter 0.5", "maxjitter 0.5"),
("combinelimit 5.0", "combinelimit 5.0"),
("reselectdist 1e-3", "reselectdist 1e-3"),
("stratumweight 0.01", "stratumweight 0.01"),
("maxclockerror 2.5", "maxclockerror 2.5"),
("maxdrift 100000.0", "maxdrift 100000.0"),
("maxupdateskew 500.0", "maxupdateskew 500.0"),
("maxslewrate 50000.0", "maxslewrate 50000.0"),
("logchange 0.5", "logchange 0.5"),
("rtcautotrim 1.0", "rtcautotrim 1.0"),
("hwtstimeout 0.002", "hwtstimeout 0.002"),
] {
match ChronyConfig::parse(input) {
Ok(_) => println!(" PASS {:<55}", format!("parse {name}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("parse {name}"));
all_ok = false;
}
}
}
println!("\n=== SECTION 5: Keyword enums ===");
for mode in ["require", "prefer", "mix", "ignore"] {
match ChronyConfig::parse(&format!("authselectmode {mode}")) {
Ok(_) => println!(" PASS {:<55}", format!("authselectmode {mode}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("authselectmode {mode}"));
all_ok = false;
}
}
}
for mode in ["system", "step", "slew", "ignore"] {
match ChronyConfig::parse(&format!("leapsecmode {mode}")) {
Ok(_) => println!(" PASS {:<55}", format!("leapsecmode {mode}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("leapsecmode {mode}"));
all_ok = false;
}
}
}
println!("\n=== SECTION 6: Multi-argument directives ===");
for (name, input) in [
("fallbackdrift", "fallbackdrift 16 19"),
("makestep", "makestep 1.0 3"),
("maxchange", "maxchange 1.0 10 -1"),
("mailonchange", "mailonchange root@localhost 0.5"),
("clientloglimit", "clientloglimit 1048576"),
] {
match ChronyConfig::parse(input) {
Ok(_) => println!(" PASS {:<55}", format!("parse {name}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("parse {name}"));
all_ok = false;
}
}
}
println!("\n=== SECTION 7: DriftFile ===");
match ChronyConfig::parse("driftfile /var/lib/chrony/drift") {
Ok(c) => {
if let Some(DirectiveKind::DriftFile(df)) =
c.find("driftfile").next().map(|d| &d.kind)
{
if df.path == "/var/lib/chrony/drift" && df.interval.is_none() {
println!(" PASS {:<55}", "driftfile basic");
} else {
println!(" FAIL {:<55} path or interval mismatch", "driftfile basic");
all_ok = false;
}
}
}
Err(e) => {
println!(" FAIL {:<55} {e}", "driftfile basic");
all_ok = false;
}
}
match ChronyConfig::parse("driftfile /var/lib/chrony/drift interval 1800") {
Ok(c) => {
if let Some(DirectiveKind::DriftFile(df)) =
c.find("driftfile").next().map(|d| &d.kind)
{
if df.interval == Some(1800) {
println!(" PASS {:<55}", "driftfile with interval");
} else {
println!(" FAIL {:<55} interval mismatch", "driftfile with interval");
all_ok = false;
}
}
}
Err(e) => {
println!(" FAIL {:<55} {e}", "driftfile with interval");
all_ok = false;
}
}
println!("\n=== SECTION 8: Server directive ===");
let server_input = "server ntp.example.com iburst prefer minpoll 4 maxpoll 8 port 123 ntsport 4460 key 42 certset 1 maxdelay 2.5 polltarget 16 minstratum 2 version 4 filter 8 offset 0.001";
match ChronyConfig::parse(server_input) {
Ok(c) => {
if let Some(DirectiveKind::Server(s)) = c.find("server").next().map(|d| &d.kind) {
let checks = [
("hostname", s.hostname == "ntp.example.com"),
("iburst", s.iburst),
("prefer", s.prefer()),
("minpoll", s.minpoll.get() == 4),
("maxpoll", s.maxpoll.get() == 8),
("port", s.port.get() == 123),
("authkey", s.authkey == 42),
("cert_set", s.cert_set == 1),
("max_delay", (s.max_delay - 2.5).abs() < 1e-10),
("poll_target", s.poll_target.get() == 16),
("min_stratum", s.min_stratum.get() == 2),
("version", s.version.map(|v| v.get()) == Some(4)),
("filter", s.filter == Some(8)),
("offset", (s.offset - 0.001).abs() < 1e-10),
];
for (field, ok) in &checks {
if *ok {
println!(" PASS {:<55}", format!("server {field}"));
} else {
println!(" FAIL {:<55}", format!("server {field}"));
all_ok = false;
}
}
}
}
Err(e) => {
println!(" FAIL {:<55} {e}", "server all options");
all_ok = false;
}
}
println!("\n=== SECTION 9: Pool directive ===");
match ChronyConfig::parse("pool pool.ntp.org iburst maxsources 6") {
Ok(c) => {
if let Some(DirectiveKind::Pool(p)) = c.find("pool").next().map(|d| &d.kind) {
let checks = [
("hostname", p.source.hostname == "pool.ntp.org"),
("iburst", p.source.iburst),
("max_sources", p.max_sources == 6),
];
for (field, ok) in &checks {
println!(" {} {:<55}", if *ok { "PASS" } else { "FAIL" }, format!("pool {field}"));
if !ok { all_ok = false; }
}
}
}
Err(e) => {
println!(" FAIL {:<55} {e}", "pool directive");
all_ok = false;
}
}
match ChronyConfig::parse("server ntp.example.com maxsources 6") {
Err(_) => println!(" PASS {:<55}", "server rejects maxsources"),
Ok(_) => {
println!(" FAIL {:<55}", "server rejects maxsources");
all_ok = false;
}
}
println!("\n=== SECTION 10: Refclock ===");
for (name, input) in [
("PPS", "refclock PPS /dev/pps0 poll 4 dpoll -4 rate 6 width 0.001"),
("SHM", "refclock SHM 0 poll 4 refid SHM0"),
("SOCK", "refclock SOCK /var/run/chrony.sock"),
("PHC", "refclock PHC /dev/ptp0 dpoll 4 poll 6 noselect"),
("PPS with prefer", "refclock PPS /dev/pps0 prefer trust offset 0.001 delay 1e-8 stratum 1 tai"),
] {
match ChronyConfig::parse(input) {
Ok(_) => println!(" PASS {:<55}", format!("refclock {name}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("refclock {name}"));
all_ok = false;
}
}
}
println!("\n=== SECTION 11: Allow/Deny ===");
for (name, input) in [
("allow all", "allow all"),
("allow subnet", "allow 192.168.0.0/16"),
("allow short subnet", "allow 192.168.123"),
("deny all", "deny all"),
("deny subnet", "deny 192.168.1.0/24"),
("cmdallow all", "cmdallow all 10.0.0.0/8"),
("cmddeny", "cmddeny"),
] {
match ChronyConfig::parse(input) {
Ok(_) => println!(" PASS {:<55}", format!("parse {name}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("parse {name}"));
all_ok = false;
}
}
}
println!("\n=== SECTION 12: Ratelimit ===");
for (name, input) in [
("ratelimit defaults", "ratelimit"),
("ratelimit all opts", "ratelimit interval 4 burst 16 leak 2 kod 1"),
("ntsratelimit", "ntsratelimit interval 8 burst 32 leak 3"),
("cmdratelimit", "cmdratelimit interval -10 burst 4 leak 1"),
] {
match ChronyConfig::parse(input) {
Ok(_) => println!(" PASS {:<55}", format!("parse {name}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("parse {name}"));
all_ok = false;
}
}
}
println!("\n=== SECTION 13: TempComp ===");
match ChronyConfig::parse("tempcomp /sys/class/hwmon/temp 4.0 25.0 0.0 1.0 0.0") {
Ok(c) => {
if let Some(DirectiveKind::TempComp(tc)) = c.find("tempcomp").next().map(|d| &d.kind) {
if matches!(tc, TempCompConfig::Coefficients { .. }) {
println!(" PASS {:<55}", "tempcomp coefficients form");
} else {
println!(" FAIL {:<55}", "tempcomp coefficients form");
all_ok = false;
}
}
}
Err(e) => {
println!(" FAIL {:<55} {e}", "tempcomp coefficients");
all_ok = false;
}
}
match ChronyConfig::parse("tempcomp /sys/class/hwmon/temp 4.0 /etc/points.txt") {
Ok(c) => {
if let Some(DirectiveKind::TempComp(tc)) = c.find("tempcomp").next().map(|d| &d.kind) {
if matches!(tc, TempCompConfig::PointFile { .. }) {
println!(" PASS {:<55}", "tempcomp pointfile form");
} else {
println!(" FAIL {:<55}", "tempcomp pointfile form");
all_ok = false;
}
}
}
Err(e) => {
println!(" FAIL {:<55} {e}", "tempcomp pointfile");
all_ok = false;
}
}
println!("\n=== SECTION 14: Complex directives ===");
for (name, input) in [
("local defaults", "local"),
("local all opts", "local stratum 5 orphan waitsynced 60 waitunsynced 10"),
("smoothtime basic", "smoothtime 400 0.001"),
("smoothtime leaponly", "smoothtime 400 0.001 leaponly"),
("broadcast", "broadcast 64 192.168.123.255"),
("broadcast with port", "broadcast 32 10.0.0.255 123"),
("log multi", "log tracking measurements statistics rtc"),
("hwtimestamp basic", "hwtimestamp eth0 minpoll 4 maxpoll 6 rxfilter ntp"),
("hwtimestamp nocrossts", "hwtimestamp eth0 nocrossts rxfilter all"),
("ntsaeads", "ntsaeads 15 30 45"),
("opencommands", "opencommands activity sources tracking"),
("ntstrustedcerts", "ntstrustedcerts /etc/chrony/certs"),
("ntstrustedcerts with id", "ntstrustedcerts 5 /etc/chrony/certs"),
("initstepslew", "initstepslew 0.5 ntp1.example.com ntp2.example.com"),
("peer", "peer 192.168.1.1 minpoll 6 maxpoll 10"),
] {
match ChronyConfig::parse(input) {
Ok(_) => println!(" PASS {:<55}", format!("parse {name}")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("parse {name}"));
all_ok = false;
}
}
}
println!("\n=== SECTION 15: Round-trip fidelity ===");
let complex_config = "\
# NTP servers
server ntp1.example.com iburst prefer minpoll 4
server ntp2.example.com iburst
# Pool
pool pool.ntp.org maxsources 6
# Drift
driftfile /var/lib/chrony/drift interval 3600
# Access
allow 192.168.0.0/16
allow 10.0.0.0/8
# Clock
makestep 1.0 3
maxdistance 5.0
rtconutc
rtcsync
log tracking measurements statistics
";
match ChronyConfig::parse(complex_config) {
Ok(c1) => {
let serialized = c1.to_string();
match ChronyConfig::parse(&serialized) {
Ok(c2) => {
let reserialized = c2.to_string();
if serialized == reserialized {
println!(" PASS {:<55}", "full round-trip serialization stability");
} else {
println!(" FAIL {:<55} serialized outputs differ", "full round-trip serialization stability");
all_ok = false;
}
}
Err(e) => {
println!(" FAIL {:<55} reparse failed: {e}", "full round-trip serialization stability");
all_ok = false;
}
}
}
Err(e) => {
println!(" FAIL {:<55} parse failed: {e}", "full round-trip serialization stability");
all_ok = false;
}
}
println!("\n=== SECTION 16: Case insensitivity ===");
for (name, input) in [
("SERVER upppercase", "SERVER ntp.example.com IBURST PREFER"),
("SeRvEr mixed", "SeRvEr ntp.example.com IbUrSt PrEfEr"),
("DRIFTFILE upper", "DRIFTFILE /var/lib/chrony/drift"),
("LeApSeCmOdE mixed", "LeApSeCmOdE SlEw"),
] {
match ChronyConfig::parse(input) {
Ok(_) => println!(" PASS {:<55}", name),
Err(e) => {
println!(" FAIL {:<55} {e}", name);
all_ok = false;
}
}
}
println!("\n=== SECTION 17: Builder API ===");
let mut config = ChronyConfig::new();
let server = ServerBuilder::new("ntp.example.com")
.iburst()
.prefer()
.minpoll(PollInterval::new(4).unwrap())
.maxpoll(PollInterval::new(8).unwrap())
.build();
config.push_directive(*server);
config.add_blank();
config.push(DirectiveKind::RtcOnUtc);
config.push(DirectiveKind::LockAll);
if config.directives().count() == 3 {
println!(" PASS {:<55}", "builder + push API");
} else {
println!(" FAIL {:<55} expected 3 directives, got {}", "builder + push API", config.directives().count());
all_ok = false;
}
println!("\n=== SECTION 18: Validation ===");
match ChronyConfig::parse("server ntp.example.com minpoll 4 maxpoll 8") {
Ok(c) => {
let errors = c.validate();
if errors.is_empty() {
println!(" PASS {:<55}", "valid config → no errors");
} else {
println!(" FAIL {:<55} got {:?}", "valid config → no errors", errors.len());
all_ok = false;
}
}
Err(e) => {
println!(" FAIL {:<55} parse error: {e}", "valid config → no errors");
all_ok = false;
}
}
match ChronyConfig::parse("server ntp.example.com minpoll 8 maxpoll 4") {
Ok(c) => {
let errors = c.validate();
if !errors.is_empty() {
println!(" PASS {:<55}", "minpoll > maxpoll → error");
} else {
println!(" FAIL {:<55} expected validation error", "minpoll > maxpoll → error");
all_ok = false;
}
}
Err(e) => {
println!(" FAIL {:<55} parse error: {e}", "minpoll > maxpoll → error");
all_ok = false;
}
}
match ChronyConfig::parse("ntsservercert a.crt\nntsservercert b.crt\nntsserverkey a.key\n") {
Ok(c) => {
let errors = c.validate();
if !errors.is_empty() {
println!(" PASS {:<55}", "NTS cert/key mismatch → error");
} else {
println!(" FAIL {:<55} expected validation error", "NTS cert/key mismatch → error");
all_ok = false;
}
}
Err(e) => {
println!(" FAIL {:<55} parse error: {e}", "NTS cert/key mismatch → error");
all_ok = false;
}
}
println!("\n=== SECTION 19: SourceFile parsing ===");
let sources_input = "\
server ntp1.example.com iburst
server ntp2.example.com prefer
# This is a comment
pool pool.ntp.org maxsources 6
badline this should be skipped
server ntp3.example.com
";
let sf = SourceFile::parse(sources_input);
let entry_count = sf.nodes.iter().filter(|n| matches!(n, SourceNode::Entry(_))).count();
if entry_count == 4 {
println!(" PASS {:<55}", "source file parsing (4 entries, 1 bad line)");
} else {
println!(" FAIL {:<55} expected 4 entries, got {entry_count}", "source file parsing");
all_ok = false;
}
let sf2: SourceFile = "server ntp1.example.com\npeer 192.168.1.1\n".parse().unwrap();
if sf2.nodes.len() == 2 {
println!(" PASS {:<55}", "SourceFile FromStr");
} else {
println!(" FAIL {:<55} expected 2 entries", "SourceFile FromStr");
all_ok = false;
}
println!("\n=== SECTION 20: Error handling ===");
match ChronyConfig::parse("bogus_directive") {
Err(_) => println!(" PASS {:<55}", "strict: invalid directive → error"),
Ok(_) => {
println!(" FAIL {:<55}", "strict: invalid directive → error");
all_ok = false;
}
}
match ChronyConfig::parse("port") {
Err(_) => println!(" PASS {:<55}", "strict: missing argument → error"),
Ok(_) => {
println!(" FAIL {:<55}", "strict: missing argument → error");
all_ok = false;
}
}
match ChronyConfig::parse("rtconutc extra") {
Err(_) => println!(" PASS {:<55}", "strict: too many args → error"),
Ok(_) => {
println!(" FAIL {:<55}", "strict: too many args → error");
all_ok = false;
}
}
let lenient_input = "\
server good1.example.com
bogus_line_should_be_skipped
server good2.example.com iburst
port
server good3.example.com
";
let (config, warnings) = ChronyConfig::parse_lenient(lenient_input);
let count = config.directives().count();
if count == 3 && !warnings.is_empty() {
println!(" PASS {:<55}", "lenient: 3 valid, skipping 2 errors");
} else {
println!(" FAIL {:<55} expected 3 directives + warnings, got {count} + {w}", "lenient", w = warnings.len());
all_ok = false;
}
println!("\n=== SECTION 21: Include expansion ===");
let tmp = std::env::temp_dir().join("chrony_confile_test");
let _ = fs::remove_dir_all(&tmp);
fs::create_dir_all(&tmp).unwrap();
fs::write(tmp.join("included.conf"), "server include.example.com iburst\nrtconutc\n").unwrap();
let conf_d = tmp.join("conf.d");
fs::create_dir_all(&conf_d).unwrap();
fs::write(conf_d.join("01-server.conf"), "server confdir1.example.com\n").unwrap();
fs::write(conf_d.join("02-server.conf"), "server confdir2.example.com\n").unwrap();
let sources_d = tmp.join("sources.d");
fs::create_dir_all(&sources_d).unwrap();
fs::write(sources_d.join("1.sources"), "server source1.example.com iburst\n").unwrap();
let main_config = format!(
"server main.example.com prefer\n\
include {}/included.conf\n\
confdir {}/conf.d\n",
tmp.display(), tmp.display()
);
match ChronyConfig::parse(&main_config) {
Ok(config) => {
let server_count = config.find("server").count();
let has_include = config.find("include").count() > 0;
if server_count == 1 && has_include {
println!(" PASS {:<55}", "include preserved as AST node");
} else {
println!(" FAIL {:<55} expected 1 server + include node", "include preserved as AST node");
all_ok = false;
}
match config.expand(&tmp) {
Ok(expanded) => {
let expanded_servers = expanded.find("server").count();
let has_rtconutc = expanded.find("rtconutc").count() > 0;
if expanded_servers == 4 && has_rtconutc {
println!(" PASS {:<55}", "expand: 4 servers + rtconutc resolved");
} else {
println!(" FAIL {:<55} expected 4 servers, got {expanded_servers}", "expand resolution");
all_ok = false;
}
}
Err(e) => {
println!(" FAIL {:<55} expand error: {e}", "expand resolution");
all_ok = false;
}
}
}
Err(e) => {
println!(" FAIL {:<55} parse error: {e}", "include/confdir config");
all_ok = false;
}
}
let deep_include = tmp.join("deep.conf");
fs::write(&deep_include, format!("include {deep}\n", deep = deep_include.display())).unwrap();
match ChronyConfig::parse(&format!("include {deep}", deep = deep_include.display())) {
Ok(config) => {
match config.expand(&tmp) {
Err(_) => println!(" PASS {:<55}", "include level exceeded → error"),
Ok(_) => {
println!(" FAIL {:<55} expected error for deep include", "include level exceeded → error");
all_ok = false;
}
}
}
Err(e) => {
println!(" FAIL {:<55} parse error: {e}", "include level exceeded");
all_ok = false;
}
}
let _ = fs::remove_dir_all(&tmp);
println!("\n=== SECTION 22: Deprecated directives ===");
for deprecated in ["commandkey", "generatecommandkey", "linux_freq_scale", "linux_hz"] {
match ChronyConfig::parse(deprecated) {
Ok(_) => println!(" PASS {:<55}", format!("deprecated: {deprecated} accepted")),
Err(e) => {
println!(" FAIL {:<55} {e}", format!("deprecated: {deprecated}"));
all_ok = false;
}
}
}
println!("\n=== SECTION 23: Send + Sync ===");
#[allow(dead_code)]
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<ChronyConfig>();
assert_send_sync::<Directive>();
assert_send_sync::<DirectiveKind>();
assert_send_sync::<ConfigNode>();
assert_send_sync::<SourceFile>();
assert_send_sync::<Span>();
assert_send_sync::<ParseError>();
assert_send_sync::<PollInterval>();
assert_send_sync::<UdpPort>();
println!(" PASS {:<55}", "all major types Send + Sync");
println!();
all_ok
}
fn main() {
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ chrony-confile v0.1.0 — Real Machine Test Suite ║");
println!("╚══════════════════════════════════════════════════════════════╝");
println!("\nEnvironment:");
println!(" arch: {}", std::env::consts::ARCH);
println!(" os: {}", std::env::consts::OS);
println!(" target: {}-{}", std::env::consts::ARCH, std::env::consts::OS);
println!(" version: {}", env!("CARGO_PKG_VERSION"));
println!(" pid: {}", std::process::id());
let success = run();
println!("\n╔══════════════════════════════════════════════════════════════╗");
if success {
println!("║ ALL TESTS PASSED ║");
} else {
println!("║ SOME TESTS FAILED ║");
}
println!("╚══════════════════════════════════════════════════════════════╝\n");
if !success {
process::exit(1);
}
}