1 // Generated by gir (https://github.com/gtk-rs/gir @ 1bef39f)
2 // from gir-files (https://github.com/gtk-rs/gir-files @ 7d95377)
3 // from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git @ 831b444)
4 // DO NOT EDIT
5 
6 use gstreamer_net_sys::*;
7 use std::env;
8 use std::error::Error;
9 use std::ffi::OsString;
10 use std::mem::{align_of, size_of};
11 use std::path::Path;
12 use std::process::Command;
13 use std::str;
14 use tempfile::Builder;
15 
16 static PACKAGES: &[&str] = &["gstreamer-net-1.0"];
17 
18 #[derive(Clone, Debug)]
19 struct Compiler {
20     pub args: Vec<String>,
21 }
22 
23 impl Compiler {
new() -> Result<Self, Box<dyn Error>>24     pub fn new() -> Result<Self, Box<dyn Error>> {
25         let mut args = get_var("CC", "cc")?;
26         args.push("-Wno-deprecated-declarations".to_owned());
27         // For _Generic
28         args.push("-std=c11".to_owned());
29         // For %z support in printf when using MinGW.
30         args.push("-D__USE_MINGW_ANSI_STDIO".to_owned());
31         args.extend(get_var("CFLAGS", "")?);
32         args.extend(get_var("CPPFLAGS", "")?);
33         args.extend(pkg_config_cflags(PACKAGES)?);
34         Ok(Self { args })
35     }
36 
compile(&self, src: &Path, out: &Path) -> Result<(), Box<dyn Error>>37     pub fn compile(&self, src: &Path, out: &Path) -> Result<(), Box<dyn Error>> {
38         let mut cmd = self.to_command();
39         cmd.arg(src);
40         cmd.arg("-o");
41         cmd.arg(out);
42         let status = cmd.spawn()?.wait()?;
43         if !status.success() {
44             return Err(format!("compilation command {:?} failed, {}", &cmd, status).into());
45         }
46         Ok(())
47     }
48 
to_command(&self) -> Command49     fn to_command(&self) -> Command {
50         let mut cmd = Command::new(&self.args[0]);
51         cmd.args(&self.args[1..]);
52         cmd
53     }
54 }
55 
get_var(name: &str, default: &str) -> Result<Vec<String>, Box<dyn Error>>56 fn get_var(name: &str, default: &str) -> Result<Vec<String>, Box<dyn Error>> {
57     match env::var(name) {
58         Ok(value) => Ok(shell_words::split(&value)?),
59         Err(env::VarError::NotPresent) => Ok(shell_words::split(default)?),
60         Err(err) => Err(format!("{} {}", name, err).into()),
61     }
62 }
63 
pkg_config_cflags(packages: &[&str]) -> Result<Vec<String>, Box<dyn Error>>64 fn pkg_config_cflags(packages: &[&str]) -> Result<Vec<String>, Box<dyn Error>> {
65     if packages.is_empty() {
66         return Ok(Vec::new());
67     }
68     let pkg_config = env::var_os("PKG_CONFIG").unwrap_or_else(|| OsString::from("pkg-config"));
69     let mut cmd = Command::new(pkg_config);
70     cmd.arg("--cflags");
71     cmd.args(packages);
72     let out = cmd.output()?;
73     if !out.status.success() {
74         return Err(format!("command {:?} returned {}", &cmd, out.status).into());
75     }
76     let stdout = str::from_utf8(&out.stdout)?;
77     Ok(shell_words::split(stdout.trim())?)
78 }
79 
80 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
81 struct Layout {
82     size: usize,
83     alignment: usize,
84 }
85 
86 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
87 struct Results {
88     /// Number of successfully completed tests.
89     passed: usize,
90     /// Total number of failed tests (including those that failed to compile).
91     failed: usize,
92 }
93 
94 impl Results {
record_passed(&mut self)95     fn record_passed(&mut self) {
96         self.passed += 1;
97     }
record_failed(&mut self)98     fn record_failed(&mut self) {
99         self.failed += 1;
100     }
summary(&self) -> String101     fn summary(&self) -> String {
102         format!("{} passed; {} failed", self.passed, self.failed)
103     }
expect_total_success(&self)104     fn expect_total_success(&self) {
105         if self.failed == 0 {
106             println!("OK: {}", self.summary());
107         } else {
108             panic!("FAILED: {}", self.summary());
109         };
110     }
111 }
112 
113 #[test]
cross_validate_constants_with_c()114 fn cross_validate_constants_with_c() {
115     let mut c_constants: Vec<(String, String)> = Vec::new();
116 
117     for l in get_c_output("constant").unwrap().lines() {
118         let mut words = l.trim().split(';');
119         let name = words.next().expect("Failed to parse name").to_owned();
120         let value = words
121             .next()
122             .and_then(|s| s.parse().ok())
123             .expect("Failed to parse value");
124         c_constants.push((name, value));
125     }
126 
127     let mut results = Results::default();
128 
129     for ((rust_name, rust_value), (c_name, c_value)) in
130         RUST_CONSTANTS.iter().zip(c_constants.iter())
131     {
132         if rust_name != c_name {
133             results.record_failed();
134             eprintln!("Name mismatch:\nRust: {:?}\nC:    {:?}", rust_name, c_name,);
135             continue;
136         }
137 
138         if rust_value != c_value {
139             results.record_failed();
140             eprintln!(
141                 "Constant value mismatch for {}\nRust: {:?}\nC:    {:?}",
142                 rust_name, rust_value, &c_value
143             );
144             continue;
145         }
146 
147         results.record_passed();
148     }
149 
150     results.expect_total_success();
151 }
152 
153 #[test]
cross_validate_layout_with_c()154 fn cross_validate_layout_with_c() {
155     let mut c_layouts = Vec::new();
156 
157     for l in get_c_output("layout").unwrap().lines() {
158         let mut words = l.trim().split(';');
159         let name = words.next().expect("Failed to parse name").to_owned();
160         let size = words
161             .next()
162             .and_then(|s| s.parse().ok())
163             .expect("Failed to parse size");
164         let alignment = words
165             .next()
166             .and_then(|s| s.parse().ok())
167             .expect("Failed to parse alignment");
168         c_layouts.push((name, Layout { size, alignment }));
169     }
170 
171     let mut results = Results::default();
172 
173     for ((rust_name, rust_layout), (c_name, c_layout)) in RUST_LAYOUTS.iter().zip(c_layouts.iter())
174     {
175         if rust_name != c_name {
176             results.record_failed();
177             eprintln!("Name mismatch:\nRust: {:?}\nC:    {:?}", rust_name, c_name,);
178             continue;
179         }
180 
181         if rust_layout != c_layout {
182             results.record_failed();
183             eprintln!(
184                 "Layout mismatch for {}\nRust: {:?}\nC:    {:?}",
185                 rust_name, rust_layout, &c_layout
186             );
187             continue;
188         }
189 
190         results.record_passed();
191     }
192 
193     results.expect_total_success();
194 }
195 
get_c_output(name: &str) -> Result<String, Box<dyn Error>>196 fn get_c_output(name: &str) -> Result<String, Box<dyn Error>> {
197     let tmpdir = Builder::new().prefix("abi").tempdir()?;
198     let exe = tmpdir.path().join(name);
199     let c_file = Path::new("tests").join(name).with_extension("c");
200 
201     let cc = Compiler::new().expect("configured compiler");
202     cc.compile(&c_file, &exe)?;
203 
204     let mut abi_cmd = Command::new(exe);
205     let output = abi_cmd.output()?;
206     if !output.status.success() {
207         return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into());
208     }
209 
210     Ok(String::from_utf8(output.stdout)?)
211 }
212 
213 const RUST_LAYOUTS: &[(&str, Layout)] = &[
214     (
215         "GstNetAddressMeta",
216         Layout {
217             size: size_of::<GstNetAddressMeta>(),
218             alignment: align_of::<GstNetAddressMeta>(),
219         },
220     ),
221     (
222         "GstNetClientClock",
223         Layout {
224             size: size_of::<GstNetClientClock>(),
225             alignment: align_of::<GstNetClientClock>(),
226         },
227     ),
228     (
229         "GstNetClientClockClass",
230         Layout {
231             size: size_of::<GstNetClientClockClass>(),
232             alignment: align_of::<GstNetClientClockClass>(),
233         },
234     ),
235     (
236         "GstNetControlMessageMeta",
237         Layout {
238             size: size_of::<GstNetControlMessageMeta>(),
239             alignment: align_of::<GstNetControlMessageMeta>(),
240         },
241     ),
242     (
243         "GstNetTimePacket",
244         Layout {
245             size: size_of::<GstNetTimePacket>(),
246             alignment: align_of::<GstNetTimePacket>(),
247         },
248     ),
249     (
250         "GstNetTimeProvider",
251         Layout {
252             size: size_of::<GstNetTimeProvider>(),
253             alignment: align_of::<GstNetTimeProvider>(),
254         },
255     ),
256     (
257         "GstNetTimeProviderClass",
258         Layout {
259             size: size_of::<GstNetTimeProviderClass>(),
260             alignment: align_of::<GstNetTimeProviderClass>(),
261         },
262     ),
263     (
264         "GstNtpClock",
265         Layout {
266             size: size_of::<GstNtpClock>(),
267             alignment: align_of::<GstNtpClock>(),
268         },
269     ),
270     (
271         "GstNtpClockClass",
272         Layout {
273             size: size_of::<GstNtpClockClass>(),
274             alignment: align_of::<GstNtpClockClass>(),
275         },
276     ),
277     (
278         "GstPtpClock",
279         Layout {
280             size: size_of::<GstPtpClock>(),
281             alignment: align_of::<GstPtpClock>(),
282         },
283     ),
284     (
285         "GstPtpClockClass",
286         Layout {
287             size: size_of::<GstPtpClockClass>(),
288             alignment: align_of::<GstPtpClockClass>(),
289         },
290     ),
291 ];
292 
293 const RUST_CONSTANTS: &[(&str, &str)] = &[
294     ("GST_NET_TIME_PACKET_SIZE", "16"),
295     ("GST_PTP_CLOCK_ID_NONE", "18446744073709551615"),
296     (
297         "GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED",
298         "GstPtpStatisticsBestMasterClockSelected",
299     ),
300     (
301         "GST_PTP_STATISTICS_NEW_DOMAIN_FOUND",
302         "GstPtpStatisticsNewDomainFound",
303     ),
304     (
305         "GST_PTP_STATISTICS_PATH_DELAY_MEASURED",
306         "GstPtpStatisticsPathDelayMeasured",
307     ),
308     (
309         "GST_PTP_STATISTICS_TIME_UPDATED",
310         "GstPtpStatisticsTimeUpdated",
311     ),
312 ];
313