Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  memory_test.rs

  Sprache: Rust
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */


//! A frontend for memory testing.

use {
    crate::std::{env, io::Write, mem::size_of},
    anyhow::Context,
    memtest::{Outcome, Runner, RunnerArgs, TestKind},
    rand::{seq::SliceRandom, thread_rng},
    serde_json,
};

// runtimeobject and propsys are not automatically linked correctly
#[cfg(windows)]
#[link(name = "runtimeobject")]
#[link(name = "propsys")]
extern "C" {}

// Writing to stdout/stderr should only fail with parent fatal errors (like BrokenPipe), in which
// case there's no point in trying to print related error information, panicking, etc.
macro_rules! quiet_println {
    ( $($e:expr),* ) => {{
        let _ = writeln!(std::io::stdout(), $($e),*);
    }};
}

macro_rules! quiet_eprintln {
    ( $($e:expr),* ) => {{
        let _ = writeln!(std::io::stderr(), $($e),*);
    }};
}

/// Usage: crashreporter --memtest <memsize_mb> <json formatted memtest_runner_args>
///        Set the env var `MOZ_CRASHREPORTER_MEMTEST_KINDS` to specify prioritized memtest kinds
pub fn main() {
    let (mem_usize_count, memtest_runner_args, memtest_kinds) = match parse_args() {
        Ok(parsed) => parsed,
        Err(e) => {
            quiet_eprintln!("Error: {e:?}");
            std::process::exit(1);
        }
    };
    let mut memory = allocate_memory(mem_usize_count);

    let memtest_report_list = Runner::from_test_kinds(&memtest_runner_args, memtest_kinds)
        .run(&mut memory)
        .expect("failed to run memtest-runner");

    let mut output_json = serde_json::to_value(&memtest_report_list)
        .expect("memtest report list failed to serialize");
    output_json["memtest_failed"] = memtest_report_list
        .iter()
        .any(|report| matches!(report.outcome, Ok(Outcome::Fail(_))))
        .into();

    quiet_println!("{}", output_json.to_string());
}

/// Parse command line arguments and environment to return the parameters for running memtest,
/// including a usize for the requested memory vector length, RunnerArgs and a vector of
/// TestKinds to run.
fn parse_args() -> anyhow::Result<(usize, RunnerArgs, Vec<TestKind>)> {
    const KIB: usize = 1024;
    const MIB: usize = 1024 * KIB;

    let mut iter = env::args_os().skip(2).map_while(|s| s.into_string().ok());

    let memsize_mb: usize = iter
        .next()
        .and_then(|s| s.parse().ok())
        .context("missing/invalid memsize_MB")?;
    let memtest_runner_args = iter
        .next()
        .and_then(|s| serde_json::from_str(&s).ok())
        .context("missing/invalid memtest_runner_args")?;

    Ok((
        memsize_mb * MIB / size_of::<usize>(),
        memtest_runner_args,
        get_memtest_kinds()?,
    ))
}

/// Returns a vector of TestKind that contains all kinds, but prioritizes the given kinds.
fn get_memtest_kinds() -> anyhow::Result<Vec<TestKind>> {
    let env_string = env::var(ekey!("MEMTEST_KINDS")).unwrap_or_default();

    let specified = env_string
        .split_whitespace()
        .map(|s| s.parse().context("failed to parse memtest kinds"))
        .collect::<anyhow::Result<Vec<TestKind>>>()?;

    let mut remaining: Vec<_> = TestKind::ALL
        .iter()
        .filter(|k| !specified.contains(k))
        .cloned()
        .collect();
    remaining.shuffle(&mut thread_rng());

    let mut kinds = [specified, remaining].concat();

    // The Block Move Test requires special care. It only performs timeout checking during its
    // starting and ending phase. To avoid violating the timeout limit, we only run it if it is the
    // first test, where we are certain it has enough time to run.
    let block_move_idx = kinds
        .iter()
        .position(|k| matches!(k, TestKind::BlockMove))
        .expect("BlockMove should exist in TestKind::ALL");
    if block_move_idx != 0 {
        kinds.remove(block_move_idx);
    }

    Ok(kinds)
}

fn allocate_memory(mut mem_usize_count: usize) -> Vec<usize> {
    let mut memory = Vec::new();
    while mem_usize_count > 0 && memory.try_reserve_exact(mem_usize_count).is_err() {
        mem_usize_count /= 2;
    }
    memory.resize(mem_usize_count, 0);
    memory
}

/// Encapsulated logic for launching and interacting with a memory testing process.
pub mod child {
    use crate::std::{
        env,
        mem::ManuallyDrop,
        process::{Child, Command, Stdio},
        time::Duration,
    };
    use anyhow::Context;
    use memtest::RunnerArgs;

    /// The memtest child process.
    pub struct Memtest {
        child: ManuallyDrop<Child>,
    }

    impl Memtest {
        /// Try to start an asynchronous memory test.
        pub fn spawn() -> Option<Self> {
            match spawn_memtest() {
                Ok(child) => Some(Memtest {
                    child: ManuallyDrop::new(child),
                }),
                Err(e) => {
                    log::error!("failed to spawn memtest process: {e:#}");
                    None
                }
            }
        }

        /// Return the memtest output, waiting for testing to complete.
        pub fn collect_output_for_submission(mut self) -> anyhow::Result<String> {
            let child = unsafe { ManuallyDrop::take(&mut self.child) };
            std::mem::forget(self);

            let output = child
                .wait_with_output()
                .context("failed to wait on memtest process")?;
            if output.status.success() {
                String::from_utf8(output.stdout)
                    .context("failed to get valid string from memtest stdout")
            } else {
                String::from_utf8(output.stderr)
                    .context("failed to get valid string from memtest stderr")
            }
        }
    }

    impl Drop for Memtest {
        fn drop(&mut self) {
            if let Err(e) = self.child.kill() {
                log::warn!("failed to kill memtest process: {e}");
            }
            if let Err(e) = self.child.wait() {
                log::warn!("failed to wait on memtest process after kill: {e}");
            }
            unsafe { ManuallyDrop::drop(&mut self.child) };
        }
    }

    fn spawn_memtest() -> anyhow::Result<Child> {
        let memsize_mb = 1024;
        let memtest_runner_args = RunnerArgs {
            timeout: Duration::from_secs(3),
            mem_lock_mode: memtest::MemLockMode::Resizable,
            allow_working_set_resize: true,
            allow_multithread: true,
            allow_early_termination: true,
        };

        let curr_exe = env::current_exe().context("failed to get current exe path")?;
        Command::new(curr_exe)
            .arg("--memtest")
            .arg(memsize_mb.to_string())
            .arg(
                serde_json::to_string(&memtest_runner_args)
                    .expect("memtest_runner_args conversion to json string should not fail"),
            )
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .map_err(|e| e.into())
    }
}

Messung V0.5 in Prozent
C=88 H=99 G=93

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002