vergen/feature/
rustc.rs

1// Copyright (c) 2022 vergen developers
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use anyhow::{Error, Result};
10use derive_builder::Builder as DeriveBuilder;
11use rustc_version::{Channel, VersionMeta, version_meta};
12use std::env;
13use vergen_lib::{
14    AddEntries, CargoRerunIfChanged, CargoRustcEnvMap, CargoWarning, DefaultConfig, VergenKey,
15    add_default_map_entry, add_map_entry,
16    constants::{
17        RUSTC_CHANNEL_NAME, RUSTC_COMMIT_DATE, RUSTC_COMMIT_HASH, RUSTC_HOST_TRIPLE_NAME,
18        RUSTC_LLVM_VERSION, RUSTC_SEMVER_NAME,
19    },
20};
21
22/// The `VERGEN_RUSTC_*` configuration features
23///
24/// **NOTE** - All rustc instructions are considered deterministic.  If you change
25/// the version of rustc you are compiling with, these values should change if
26/// being used in the generated binary.
27///
28/// | Variable | Sample |
29/// | -------  | ------ |
30/// | `VERGEN_RUSTC_CHANNEL` | nightly |
31/// | `VERGEN_RUSTC_COMMIT_DATE` | 2021-02-24 |
32/// | `VERGEN_RUSTC_COMMIT_HASH` | a8486b64b0c87dabd045453b6c81500015d122d6 |
33/// | `VERGEN_RUSTC_HOST_TRIPLE` | apple-darwin |
34/// | `VERGEN_RUSTC_LLVM_VERSION` | 11.0 |
35/// | `VERGEN_RUSTC_SEMVER` | 1.52.0-nightly |
36///
37/// # Example
38/// Emit all of the rustc instructions
39///
40/// ```
41/// # use anyhow::Result;
42/// # use vergen::Emitter;
43/// # use vergen::RustcBuilder;
44/// #
45/// # fn main() -> Result<()> {
46/// let rustc = RustcBuilder::all_rustc()?;
47/// Emitter::default().add_instructions(&rustc)?.emit();
48/// #   Ok(())
49/// # }
50/// ```
51///
52/// Emit some of the rustc instructions
53///
54/// ```
55/// # use anyhow::Result;
56/// # use vergen::Emitter;
57/// # use vergen::RustcBuilder;
58/// #
59/// # fn main() -> Result<()> {
60/// let rustc = RustcBuilder::default().channel(true).semver(true).build()?;
61/// Emitter::default().add_instructions(&rustc)?.emit();
62/// #   Ok(())
63/// # }
64/// ```
65///
66/// Override output with your own value
67///
68/// ```
69/// # use anyhow::Result;
70/// # use std::env;
71/// # use vergen::Emitter;
72/// # use vergen::RustcBuilder;
73/// #
74/// # fn main() -> Result<()> {
75/// temp_env::with_var("VERGEN_RUSTC_CHANNEL", Some("this is the channel I want output"), || {
76///     let result = || -> Result<()> {
77///         let rustc = RustcBuilder::default().channel(true).semver(true).build()?;
78///         Emitter::default().add_instructions(&rustc)?.emit();   
79///         Ok(())  
80///     }();
81///     assert!(result.is_ok());
82/// });
83/// #   Ok(())
84/// # }
85/// ```
86///
87#[derive(Clone, Copy, Debug, DeriveBuilder, PartialEq)]
88#[allow(clippy::struct_excessive_bools)]
89pub struct Rustc {
90    /// Enable the rustc channel
91    #[builder(default = "false")]
92    channel: bool,
93    /// Enable the rustc commit date
94    #[builder(default = "false")]
95    commit_date: bool,
96    /// Enable the rustc SHA
97    #[builder(default = "false")]
98    commit_hash: bool,
99    /// Enable rustc host triple
100    #[builder(default = "false")]
101    host_triple: bool,
102    /// Enable rustc LLVM version
103    #[builder(default = "false")]
104    llvm_version: bool,
105    /// Enable the rustc semver
106    #[builder(default = "false")]
107    semver: bool,
108    #[cfg(test)]
109    #[builder(default = "None", setter(skip))]
110    str_to_test: Option<&'static str>,
111}
112
113impl RustcBuilder {
114    /// Enable all of the `VERGEN_RUSTC_*` options
115    ///
116    /// # Errors
117    /// The underlying build function can error
118    ///
119    pub fn all_rustc() -> Result<Rustc> {
120        Self::default()
121            .channel(true)
122            .commit_date(true)
123            .commit_hash(true)
124            .host_triple(true)
125            .llvm_version(true)
126            .semver(true)
127            .build()
128            .map_err(Into::into)
129    }
130}
131
132impl Rustc {
133    fn any(self) -> bool {
134        self.channel
135            || self.commit_date
136            || self.commit_hash
137            || self.host_triple
138            || self.llvm_version
139            || self.semver
140    }
141
142    #[cfg(not(test))]
143    fn add_rustc_map_entries(
144        self,
145        cargo_rustc_env: &mut CargoRustcEnvMap,
146        cargo_warning: &mut CargoWarning,
147    ) -> Result<()> {
148        self.add_rustc_to_map(version_meta(), cargo_rustc_env, cargo_warning)
149    }
150
151    #[cfg(test)]
152    fn add_rustc_map_entries(
153        self,
154        cargo_rustc_env: &mut CargoRustcEnvMap,
155        cargo_warning: &mut CargoWarning,
156    ) -> Result<()> {
157        use rustc_version::version_meta_for;
158
159        let vm = if let Some(rustc_str) = self.str_to_test {
160            version_meta_for(rustc_str)
161        } else {
162            version_meta()
163        };
164        self.add_rustc_to_map(vm, cargo_rustc_env, cargo_warning)
165    }
166
167    fn add_rustc_to_map(
168        self,
169        rustc_res: std::result::Result<VersionMeta, rustc_version::Error>,
170        cargo_rustc_env: &mut CargoRustcEnvMap,
171        cargo_warning: &mut CargoWarning,
172    ) -> Result<()> {
173        let rustc = rustc_res?;
174
175        if self.channel {
176            if let Ok(_value) = env::var(RUSTC_CHANNEL_NAME) {
177                add_default_map_entry(VergenKey::RustcChannel, cargo_rustc_env, cargo_warning);
178            } else {
179                let channel = match rustc.channel {
180                    Channel::Dev => "dev",
181                    Channel::Nightly => "nightly",
182                    Channel::Beta => "beta",
183                    Channel::Stable => "stable",
184                };
185                add_map_entry(VergenKey::RustcChannel, channel, cargo_rustc_env);
186            }
187        }
188
189        if self.commit_date {
190            if let Ok(_value) = env::var(RUSTC_COMMIT_DATE) {
191                add_default_map_entry(VergenKey::RustcCommitDate, cargo_rustc_env, cargo_warning);
192            } else if let Some(commit_date) = rustc.commit_date {
193                add_map_entry(VergenKey::RustcCommitDate, commit_date, cargo_rustc_env);
194            } else {
195                add_default_map_entry(VergenKey::RustcCommitDate, cargo_rustc_env, cargo_warning);
196            }
197        }
198
199        if self.commit_hash {
200            if let Ok(_value) = env::var(RUSTC_COMMIT_HASH) {
201                add_default_map_entry(VergenKey::RustcCommitHash, cargo_rustc_env, cargo_warning);
202            } else if let Some(commit_hash) = rustc.commit_hash {
203                add_map_entry(VergenKey::RustcCommitHash, commit_hash, cargo_rustc_env);
204            } else {
205                add_default_map_entry(VergenKey::RustcCommitHash, cargo_rustc_env, cargo_warning);
206            }
207        }
208
209        if self.host_triple {
210            if let Ok(_value) = env::var(RUSTC_HOST_TRIPLE_NAME) {
211                add_default_map_entry(VergenKey::RustcHostTriple, cargo_rustc_env, cargo_warning);
212            } else {
213                add_map_entry(VergenKey::RustcHostTriple, rustc.host, cargo_rustc_env);
214            }
215        }
216
217        if self.llvm_version {
218            if let Ok(_value) = env::var(RUSTC_LLVM_VERSION) {
219                add_default_map_entry(VergenKey::RustcLlvmVersion, cargo_rustc_env, cargo_warning);
220            } else if let Some(llvm_version) = rustc.llvm_version {
221                add_map_entry(
222                    VergenKey::RustcLlvmVersion,
223                    format!("{llvm_version}"),
224                    cargo_rustc_env,
225                );
226            } else {
227                add_default_map_entry(VergenKey::RustcLlvmVersion, cargo_rustc_env, cargo_warning);
228            }
229        }
230
231        if self.semver {
232            if let Ok(_value) = env::var(RUSTC_SEMVER_NAME) {
233                add_default_map_entry(VergenKey::RustcSemver, cargo_rustc_env, cargo_warning);
234            } else {
235                add_map_entry(
236                    VergenKey::RustcSemver,
237                    format!("{}", rustc.semver),
238                    cargo_rustc_env,
239                );
240            }
241        }
242
243        Ok(())
244    }
245
246    #[cfg(test)]
247    fn with_rustc_str(&mut self, rustc_str: &'static str) -> &mut Self {
248        self.str_to_test = Some(rustc_str);
249        self
250    }
251}
252
253impl AddEntries for Rustc {
254    fn add_map_entries(
255        &self,
256        _idempotent: bool,
257        cargo_rustc_env: &mut CargoRustcEnvMap,
258        _cargo_rerun_if_changed: &mut CargoRerunIfChanged,
259        cargo_warning: &mut CargoWarning,
260    ) -> Result<()> {
261        if self.any() {
262            self.add_rustc_map_entries(cargo_rustc_env, cargo_warning)
263        } else {
264            Ok(())
265        }
266    }
267
268    fn add_default_entries(
269        &self,
270        config: &DefaultConfig,
271        cargo_rustc_env_map: &mut CargoRustcEnvMap,
272        _cargo_rerun_if_changed: &mut CargoRerunIfChanged,
273        cargo_warning: &mut CargoWarning,
274    ) -> Result<()> {
275        if *config.fail_on_error() {
276            let error = Error::msg(format!("{:?}", config.error()));
277            Err(error)
278        } else {
279            if self.channel {
280                add_default_map_entry(VergenKey::RustcChannel, cargo_rustc_env_map, cargo_warning);
281            }
282            if self.commit_date {
283                add_default_map_entry(
284                    VergenKey::RustcCommitDate,
285                    cargo_rustc_env_map,
286                    cargo_warning,
287                );
288            }
289            if self.commit_hash {
290                add_default_map_entry(
291                    VergenKey::RustcCommitHash,
292                    cargo_rustc_env_map,
293                    cargo_warning,
294                );
295            }
296            if self.host_triple {
297                add_default_map_entry(
298                    VergenKey::RustcHostTriple,
299                    cargo_rustc_env_map,
300                    cargo_warning,
301                );
302            }
303            if self.llvm_version {
304                add_default_map_entry(
305                    VergenKey::RustcLlvmVersion,
306                    cargo_rustc_env_map,
307                    cargo_warning,
308                );
309            }
310            if self.semver {
311                add_default_map_entry(VergenKey::RustcSemver, cargo_rustc_env_map, cargo_warning);
312            }
313
314            Ok(())
315        }
316    }
317}
318
319#[cfg(test)]
320mod test {
321    use super::RustcBuilder;
322    use crate::Emitter;
323    use anyhow::Result;
324    use serial_test::serial;
325    use std::io::Write;
326    use temp_env::with_var;
327    use vergen_lib::count_idempotent;
328
329    #[test]
330    #[serial]
331    #[allow(clippy::clone_on_copy, clippy::redundant_clone)]
332    fn rustc_clone_works() -> Result<()> {
333        let rustc = RustcBuilder::all_rustc()?;
334        let another = rustc.clone();
335        assert_eq!(another, rustc);
336        Ok(())
337    }
338
339    #[test]
340    #[serial]
341    fn rustc_debug_works() -> Result<()> {
342        let rustc = RustcBuilder::all_rustc()?;
343        let mut buf = vec![];
344        write!(buf, "{rustc:?}")?;
345        assert!(!buf.is_empty());
346        Ok(())
347    }
348
349    #[test]
350    #[serial]
351    fn rustc_default() -> Result<()> {
352        let rustc = RustcBuilder::default().build()?;
353        let emitter = Emitter::default().add_instructions(&rustc)?.test_emit();
354        assert_eq!(0, emitter.cargo_rustc_env_map().len());
355        assert_eq!(0, count_idempotent(emitter.cargo_rustc_env_map()));
356        assert_eq!(0, emitter.cargo_warning().len());
357        Ok(())
358    }
359
360    #[test]
361    #[serial]
362    fn rustc_all_idempotent() -> Result<()> {
363        let rustc = RustcBuilder::all_rustc()?;
364        let config = Emitter::default()
365            .idempotent()
366            .add_instructions(&rustc)?
367            .test_emit();
368        assert_eq!(6, config.cargo_rustc_env_map().len());
369        assert_eq!(0, count_idempotent(config.cargo_rustc_env_map()));
370        assert_eq!(0, config.cargo_warning().len());
371        Ok(())
372    }
373
374    #[test]
375    #[serial]
376    fn rustc_all() -> Result<()> {
377        let rustc = RustcBuilder::all_rustc()?;
378        let config = Emitter::default().add_instructions(&rustc)?.test_emit();
379        assert_eq!(6, config.cargo_rustc_env_map().len());
380        assert_eq!(0, count_idempotent(config.cargo_rustc_env_map()));
381        assert_eq!(0, config.cargo_warning().len());
382        Ok(())
383    }
384
385    #[test]
386    #[serial]
387    fn rustc_commit_date() -> Result<()> {
388        let rustc = RustcBuilder::default().commit_date(true).build()?;
389        let config = Emitter::default().add_instructions(&rustc)?.test_emit();
390        assert_eq!(1, config.cargo_rustc_env_map().len());
391        assert_eq!(0, count_idempotent(config.cargo_rustc_env_map()));
392        assert_eq!(0, config.cargo_warning().len());
393        Ok(())
394    }
395
396    #[test]
397    #[serial]
398    fn rustc_commit_hash() -> Result<()> {
399        let rustc = RustcBuilder::default().commit_hash(true).build()?;
400        let config = Emitter::default().add_instructions(&rustc)?.test_emit();
401        assert_eq!(1, config.cargo_rustc_env_map().len());
402        assert_eq!(0, count_idempotent(config.cargo_rustc_env_map()));
403        assert_eq!(0, config.cargo_warning().len());
404        Ok(())
405    }
406
407    #[test]
408    #[serial]
409    fn rustc_host_triple() -> Result<()> {
410        let rustc = RustcBuilder::default().host_triple(true).build()?;
411        let config = Emitter::default().add_instructions(&rustc)?.test_emit();
412        assert_eq!(1, config.cargo_rustc_env_map().len());
413        assert_eq!(0, count_idempotent(config.cargo_rustc_env_map()));
414        assert_eq!(0, config.cargo_warning().len());
415        Ok(())
416    }
417
418    #[test]
419    #[serial]
420    fn rustc_llvm_version() -> Result<()> {
421        let rustc = RustcBuilder::default().llvm_version(true).build()?;
422        let config = Emitter::default().add_instructions(&rustc)?.test_emit();
423        assert_eq!(1, config.cargo_rustc_env_map().len());
424        assert_eq!(0, count_idempotent(config.cargo_rustc_env_map()));
425        assert_eq!(0, config.cargo_warning().len());
426        Ok(())
427    }
428
429    #[test]
430    #[serial]
431    fn rustc_semver() -> Result<()> {
432        let rustc = RustcBuilder::default().semver(true).build()?;
433        let config = Emitter::default().add_instructions(&rustc)?.test_emit();
434        assert_eq!(1, config.cargo_rustc_env_map().len());
435        assert_eq!(0, count_idempotent(config.cargo_rustc_env_map()));
436        assert_eq!(0, config.cargo_warning().len());
437        Ok(())
438    }
439
440    const NO_LLVM: &str = r"rustc 1.68.0-nightly (270c94e48 2022-12-28)
441binary: rustc
442commit-hash: 270c94e484e19764a2832ef918c95224eb3f17c7
443commit-date: 2022-12-28
444host: x86_64-unknown-linux-gnu
445release: 1.68.0-nightly
446    ";
447
448    #[test]
449    #[serial]
450    fn no_llvm_in_rustc() -> Result<()> {
451        let mut rustc = RustcBuilder::all_rustc()?;
452        let _ = rustc.with_rustc_str(NO_LLVM);
453        let emitter = Emitter::default()
454            .fail_on_error()
455            .add_instructions(&rustc)?
456            .test_emit();
457        assert_eq!(6, emitter.cargo_rustc_env_map().len());
458        assert_eq!(1, count_idempotent(emitter.cargo_rustc_env_map()));
459        assert_eq!(1, emitter.cargo_warning().len());
460        Ok(())
461    }
462
463    const DEV_BUILD: &str = r"rustc 1.68.0-nightly (270c94e48 2022-12-28)
464binary: rustc
465commit-hash: 270c94e484e19764a2832ef918c95224eb3f17c7
466commit-date: 2022-12-28
467host: x86_64-unknown-linux-gnu
468release: 1.68.0-dev
469LLVM version: 15.0.6
470    ";
471
472    #[test]
473    #[serial]
474    fn rustc_dev_build() -> Result<()> {
475        let mut rustc = RustcBuilder::all_rustc()?;
476        let _ = rustc.with_rustc_str(DEV_BUILD);
477        let emitter = Emitter::default()
478            .fail_on_error()
479            .add_instructions(&rustc)?
480            .test_emit();
481        assert_eq!(6, emitter.cargo_rustc_env_map().len());
482        assert_eq!(0, count_idempotent(emitter.cargo_rustc_env_map()));
483        assert_eq!(0, emitter.cargo_warning().len());
484        Ok(())
485    }
486
487    const UNKNOWN_BITS: &str = r"rustc 1.68.0-nightly (270c94e48 2022-12-28)
488binary: rustc
489commit-hash: unknown
490commit-date: unknown
491host: x86_64-unknown-linux-gnu
492release: 1.68.0-dev
493LLVM version: 15.0.6
494    ";
495
496    #[test]
497    #[serial]
498    fn rustc_unknown_bits() -> Result<()> {
499        let mut rustc = RustcBuilder::all_rustc()?;
500        let _ = rustc.with_rustc_str(UNKNOWN_BITS);
501        let emitter = Emitter::default()
502            .fail_on_error()
503            .add_instructions(&rustc)?
504            .test_emit();
505        assert_eq!(6, emitter.cargo_rustc_env_map().len());
506        assert_eq!(2, count_idempotent(emitter.cargo_rustc_env_map()));
507        assert_eq!(2, emitter.cargo_warning().len());
508        Ok(())
509    }
510
511    #[test]
512    #[serial]
513    fn rustc_fails_on_bad_input() -> Result<()> {
514        let mut rustc = RustcBuilder::all_rustc()?;
515        let _ = rustc.with_rustc_str("a_bad_rustcvv_string");
516        assert!(
517            Emitter::default()
518                .fail_on_error()
519                .add_instructions(&rustc)
520                .is_err()
521        );
522        Ok(())
523    }
524
525    #[test]
526    #[serial]
527    fn rustc_defaults_on_bad_input() -> Result<()> {
528        let mut rustc = RustcBuilder::all_rustc()?;
529        let _ = rustc.with_rustc_str("a_bad_rustcvv_string");
530        let emitter = Emitter::default().add_instructions(&rustc)?.test_emit();
531        assert_eq!(6, emitter.cargo_rustc_env_map().len());
532        assert_eq!(6, count_idempotent(emitter.cargo_rustc_env_map()));
533        assert_eq!(6, emitter.cargo_warning().len());
534        Ok(())
535    }
536
537    #[test]
538    #[serial]
539    fn rustc_channel_override_works() {
540        with_var("VERGEN_RUSTC_CHANNEL", Some("this is a bad date"), || {
541            let result = || -> Result<()> {
542                let mut stdout_buf = vec![];
543                let rustc = RustcBuilder::all_rustc()?;
544                assert!(
545                    Emitter::default()
546                        .add_instructions(&rustc)?
547                        .emit_to(&mut stdout_buf)
548                        .is_ok()
549                );
550                let output = String::from_utf8_lossy(&stdout_buf);
551                assert!(output.contains("cargo:rustc-env=VERGEN_RUSTC_CHANNEL=this is a bad date"));
552                Ok(())
553            }();
554            assert!(result.is_ok());
555        });
556    }
557
558    #[test]
559    #[serial]
560    fn rustc_commit_date_override_works() {
561        with_var(
562            "VERGEN_RUSTC_COMMIT_DATE",
563            Some("this is a bad date"),
564            || {
565                let result =
566                    || -> Result<()> {
567                        let mut stdout_buf = vec![];
568                        let rustc = RustcBuilder::all_rustc()?;
569                        assert!(
570                            Emitter::default()
571                                .add_instructions(&rustc)?
572                                .emit_to(&mut stdout_buf)
573                                .is_ok()
574                        );
575                        let output = String::from_utf8_lossy(&stdout_buf);
576                        assert!(output.contains(
577                            "cargo:rustc-env=VERGEN_RUSTC_COMMIT_DATE=this is a bad date"
578                        ));
579                        Ok(())
580                    }();
581                assert!(result.is_ok());
582            },
583        );
584    }
585
586    #[test]
587    #[serial]
588    fn rustc_commit_hash_override_works() {
589        with_var(
590            "VERGEN_RUSTC_COMMIT_HASH",
591            Some("this is a bad date"),
592            || {
593                let result =
594                    || -> Result<()> {
595                        let mut stdout_buf = vec![];
596                        let rustc = RustcBuilder::all_rustc()?;
597                        assert!(
598                            Emitter::default()
599                                .add_instructions(&rustc)?
600                                .emit_to(&mut stdout_buf)
601                                .is_ok()
602                        );
603                        let output = String::from_utf8_lossy(&stdout_buf);
604                        assert!(output.contains(
605                            "cargo:rustc-env=VERGEN_RUSTC_COMMIT_HASH=this is a bad date"
606                        ));
607                        Ok(())
608                    }();
609                assert!(result.is_ok());
610            },
611        );
612    }
613
614    #[test]
615    #[serial]
616    fn rustc_host_triple_override_works() {
617        with_var(
618            "VERGEN_RUSTC_HOST_TRIPLE",
619            Some("this is a bad date"),
620            || {
621                let result =
622                    || -> Result<()> {
623                        let mut stdout_buf = vec![];
624                        let rustc = RustcBuilder::all_rustc()?;
625                        assert!(
626                            Emitter::default()
627                                .add_instructions(&rustc)?
628                                .emit_to(&mut stdout_buf)
629                                .is_ok()
630                        );
631                        let output = String::from_utf8_lossy(&stdout_buf);
632                        assert!(output.contains(
633                            "cargo:rustc-env=VERGEN_RUSTC_HOST_TRIPLE=this is a bad date"
634                        ));
635                        Ok(())
636                    }();
637                assert!(result.is_ok());
638            },
639        );
640    }
641
642    #[test]
643    #[serial]
644    fn rustc_llvm_version_override_works() {
645        with_var(
646            "VERGEN_RUSTC_LLVM_VERSION",
647            Some("this is a bad date"),
648            || {
649                let result =
650                    || -> Result<()> {
651                        let mut stdout_buf = vec![];
652                        let rustc = RustcBuilder::all_rustc()?;
653                        assert!(
654                            Emitter::default()
655                                .add_instructions(&rustc)?
656                                .emit_to(&mut stdout_buf)
657                                .is_ok()
658                        );
659                        let output = String::from_utf8_lossy(&stdout_buf);
660                        assert!(output.contains(
661                            "cargo:rustc-env=VERGEN_RUSTC_LLVM_VERSION=this is a bad date"
662                        ));
663                        Ok(())
664                    }();
665                assert!(result.is_ok());
666            },
667        );
668    }
669
670    #[test]
671    #[serial]
672    fn rustc_semver_override_works() {
673        with_var("VERGEN_RUSTC_SEMVER", Some("this is a bad date"), || {
674            let result = || -> Result<()> {
675                let mut stdout_buf = vec![];
676                let rustc = RustcBuilder::all_rustc()?;
677                assert!(
678                    Emitter::default()
679                        .add_instructions(&rustc)?
680                        .emit_to(&mut stdout_buf)
681                        .is_ok()
682                );
683                let output = String::from_utf8_lossy(&stdout_buf);
684                assert!(output.contains("cargo:rustc-env=VERGEN_RUSTC_SEMVER=this is a bad date"));
685                Ok(())
686            }();
687            assert!(result.is_ok());
688        });
689    }
690}