1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#![deny(unsafe_code)]
#[macro_use]
extern crate dlopen_derive;
use std::{io, process, time::{SystemTime, UNIX_EPOCH}};
use anyhow::{anyhow, Context, Result};
use args::{CargoArguments, CargoSpawnedArguments, PreflightCommand};
use cargo::{build_artifact, get_host_target, get_metadata};
use harness::{AvionicsHarness, PanicCaught, PanicHang};
use preflight::{
uom::{
self,
si::{
length::{meter, Length},
SI,
},
},
Sensors, Vector3,
};
use shell::Shell;
use structopt::StructOpt;
use uom::si::time::{second, Time};
mod args;
mod cargo;
mod harness;
mod panic;
mod shell;
fn main() -> io::Result<()> {
let mut shell = Shell::new();
let CargoSpawnedArguments::Preflight(args) = CargoSpawnedArguments::from_args();
match args.command {
PreflightCommand::Check { cargo } => {
if let Err(e) = load_harness(&cargo, &mut shell) {
shell.error(format!("{:#}", e))?;
process::exit(1);
} else {
shell.status("Success", "built and loaded avionics harness successfully")?;
}
}
PreflightCommand::Test {
cargo,
panic,
display,
sim,
} => match load_harness(&cargo, &mut shell) {
Err(e) => {
shell.error(format!("{:#}", e))?;
process::exit(1);
},
Ok(harness) => match test_harness(harness.setup_panic(panic)) {
Err(e) => {
shell.error(format!("{:#}", e))?;
process::exit(1);
},
Ok(false) => {
shell.error("harness failed to run")?;
process::exit(1);
},
Ok(true) => shell.status("Finished", "TODO:")?,
},
},
}
Ok(())
}
fn test_harness(mut harness: AvionicsHarness<PanicCaught>) -> Result<bool> {
let start_time = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs_f32();
for _ in 0..10 {
println!(
"{:?}",
Length::<SI<f64>, _>::new::<meter>(0.0f64)
.into_format_args(meter, preflight::uom::fmt::DisplayStyle::Description),
);
let tick_time = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs_f32();
let result = harness.guide(Sensors {
altitude: Length::new::<meter>(0.0),
linear_acceleration: Vector3::zero(),
gravity_acceleration: Vector3::zero(),
both_acceleration: Vector3::zero(),
orientation: Vector3::zero(),
angular_velocity: Vector3::zero(),
magnetic_field: Vector3::zero(),
running_time: Time::new::<second>(tick_time - start_time),
});
dbg!(&result);
}
Ok(true)
}
fn load_harness(
cargo_args: &CargoArguments,
shell: &mut Shell,
) -> anyhow::Result<AvionicsHarness<PanicHang>> {
let host_target = get_host_target()?;
let metadata = get_metadata(&cargo_args).map_err(|e| match e {
cargo_metadata::Error::CargoMetadata { stderr } => {
anyhow!("{}", stderr.trim_start_matches("error: "))
}
e => anyhow!("{}", e),
})?;
let package = metadata
.root_package()
.context("could not find the root package for this workspace")?;
let has_dylib_target = package
.targets
.iter()
.any(|t| t.kind.contains(&"dylib".to_string()));
if has_dylib_target {
shell.warning(
"the crate probably should not have a library target with a crate_type of 'dylib'",
)?;
shell.note("this will be added automatically when this command is run. crate_type should be `staticlib` or `cdylib`")?;
}
match build_artifact(&cargo_args, &host_target, package)? {
None => Err(anyhow!(
"the cargo build did not produce any valid artifacts"
)),
Some(artifact_file) => {
shell.status("Loading", artifact_file.to_string_lossy())?;
let harness = AvionicsHarness::load(&artifact_file)
.context("failed to load built shared library")?;
if let Some(harness) = harness {
Ok(harness)
} else {
Err(anyhow!("the dylib was not setup using the `#[avionics_harness]` macro or is using an out of date dependency to preflight"))
}
}
}
}