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_check_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-check-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 "GstHarness",
216 Layout {
217 size: size_of::<GstHarness>(),
218 alignment: align_of::<GstHarness>(),
219 },
220 ),
221 (
222 "GstTestClock",
223 Layout {
224 size: size_of::<GstTestClock>(),
225 alignment: align_of::<GstTestClock>(),
226 },
227 ),
228 (
229 "GstTestClockClass",
230 Layout {
231 size: size_of::<GstTestClockClass>(),
232 alignment: align_of::<GstTestClockClass>(),
233 },
234 ),
235 ];
236
237 const RUST_CONSTANTS: &[(&str, &str)] = &[];
238