<commit_before>// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Run line break test data.

// Run on:
// http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/LineBreakTest.txt
// or use randomized data from tools/gen_rand_icu.cc (same format)

extern crate xi_unicode;

use xi_unicode::{LineBreakIterator, LineBreakLeafIter};

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

fn quote_str(s: &str) -> String {
    let mut result = String::new();
    for c in s.chars() {
        if c == '"' || c == '\\' {
            result.push('\\');
        }
        if ' ' <= c && c <= '~' {
            result.push(c);
        } else {
            result.push_str(&format!("\\u{{{:04x}}}", c as u32));
        }
    }
    result
}

fn check_breaks(s: &str, breaks: &[usize]) -> bool {
    let my_breaks = LineBreakIterator::new(s)
        .map(|(bk, _hard)| bk)
        .collect::<Vec<_>>();
    if my_breaks != breaks {
        println!("failed case: \"{}\"", quote_str(s));
        println!("expected {:?} actual {:?}", breaks, my_breaks);
        return false;
    }
    true
}

// Verify that starting iteration at a break is insensitive to look-behind.
fn check_lb(s: &str) -> bool {
    let breaks = LineBreakIterator::new(s).collect::<Vec<_>>();
    for i in 0..breaks.len() - 1 {
        let mut cursor = LineBreakLeafIter::new(s, breaks[i].0);
        for &bk in &breaks[i + 1..] {
            let mut next = cursor.next(s);
            if next.0 == s.len() {
                next = (s.len(), true);
            }
            if next != bk {
                println!("failed case: \"{}\"", quote_str(s));
                println!("expected {:?} actual {:?}", bk, next);
                return false;
            }
        }
    }
    true
}

fn run_test(filename: &str, lb: bool) -> std::io::Result<()> {
    let f = File::open(filename)?;
    let mut reader = BufReader::new(f);
    let mut pass = 0;
    let mut total = 0;
    loop {
        let mut line = String::new();
        if treader.read_line(&mut line)? == 0 { break };
        let mut s = String::new();
        let mut breaks = Vec::new();
        for token in line.split_whitespace() {
            if token == "÷" {
                breaks.push(s.len());
            } else if token == "×" {
            } else if token == "#" {
                break;
            } else if let Ok(cp) = u32::from_str_radix(token, 16) {
                s.push(std::char::from_u32(cp).unwrap());
            }
        }
        total += 1;
        if lb {
            if check_lb(&s) { pass += 1; }
        } else {
            if check_breaks(&s, &breaks) { pass += 1; }
        }
    }
    println!("{}/{} pass", pass, total);
    Ok(())
}

fn main() {
    let mut args = std::env::args();
    let _ = args.next();
    let filename = args.next().unwrap();
    match args.next() {
        None => {
            let _ = run_test(&filename, false);
        }
        Some(ref s) if s == "--lookbehind" => {
            let _ = run_test(&filename, true);
        }
        _ => {
            println!("unknown argument");
        }
    }
}
<commit_msg>Replaced try! macro whit new 1.13 ? syntax<commit_after>// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Run line break test data.

// Run on:
// http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/LineBreakTest.txt
// or use randomized data from tools/gen_rand_icu.cc (same format)

extern crate xi_unicode;

use xi_unicode::{LineBreakIterator, LineBreakLeafIter};

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

fn quote_str(s: &str) -> String {
    let mut result = String::new();
    for c in s.chars() {
        if c == '"' || c == '\\' {
            result.push('\\');
        }
        if ' ' <= c && c <= '~' {
            result.push(c);
        } else {
            result.push_str(&format!("\\u{{{:04x}}}", c as u32));
        }
    }
    result
}

fn check_breaks(s: &str, breaks: &[usize]) -> bool {
    let my_breaks = LineBreakIterator::new(s)
        .map(|(bk, _hard)| bk)
        .collect::<Vec<_>>();
    if my_breaks != breaks {
        println!("failed case: \"{}\"", quote_str(s));
        println!("expected {:?} actual {:?}", breaks, my_breaks);
        return false;
    }
    true
}

// Verify that starting iteration at a break is insensitive to look-behind.
fn check_lb(s: &str) -> bool {
    let breaks = LineBreakIterator::new(s).collect::<Vec<_>>();
    for i in 0..breaks.len() - 1 {
        let mut cursor = LineBreakLeafIter::new(s, breaks[i].0);
        for &bk in &breaks[i + 1..] {
            let mut next = cursor.next(s);
            if next.0 == s.len() {
                next = (s.len(), true);
            }
            if next != bk {
                println!("failed case: \"{}\"", quote_str(s));
                println!("expected {:?} actual {:?}", bk, next);
                return false;
            }
        }
    }
    true
}

fn run_test(filename: &str, lb: bool) -> std::io::Result<()> {
    let f = File::open(filename)?;
    let mut reader = BufReader::new(f);
    let mut pass = 0;
    let mut total = 0;
    loop {
        let mut line = String::new();
        if reader.read_line(&mut line)? == 0 { break };
        let mut s = String::new();
        let mut breaks = Vec::new();
        for token in line.split_whitespace() {
            if token == "÷" {
                breaks.push(s.len());
            } else if token == "×" {
            } else if token == "#" {
                break;
            } else if let Ok(cp) = u32::from_str_radix(token, 16) {
                s.push(std::char::from_u32(cp).unwrap());
            }
        }
        total += 1;
        if lb {
            if check_lb(&s) { pass += 1; }
        } else {
            if check_breaks(&s, &breaks) { pass += 1; }
        }
    }
    println!("{}/{} pass", pass, total);
    Ok(())
}

fn main() {
    let mut args = std::env::args();
    let _ = args.next();
    let filename = args.next().unwrap();
    match args.next() {
        None => {
            let _ = run_test(&filename, false);
        }
        Some(ref s) if s == "--lookbehind" => {
            let _ = run_test(&filename, true);
        }
        _ => {
            println!("unknown argument");
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate getopts;
extern crate test;

use test::{AutoColor, TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName};
use test::ShouldFail;
use getopts::{getopts, reqopt};
use std::{os, str};
use std::old_io::fs;
use std::old_io::Reader;
use std::old_io::process::{Command, Ignored, CreatePipe, InheritFd, ExitStatus};
use std::old_path::Path;
use std::thunk::Thunk;

#[derive(Clone)]
struct Config {
    source_dir: String,
    filter: Option<String>
}

fn main() {
    let args = os::args();
    let config = parse_config(args.into_iter().collect());
    let opts = test_options(config.clone());
    let tests = find_tests(config);
    match run_tests_console(&opts, tests) {
        Ok(false) => os::set_exit_status(1), // tests failed
        Err(_) => os::set_exit_status(2),    // I/O-related failure
        _ => (),
    }
}

fn parse_config(args: Vec<String>) -> Config {
    let args = args.tail();
    let opts = vec!(reqopt("s", "source-dir", "source-dir", "source-dir"));
    let matches = match getopts(args, opts.as_slice()) {
      Ok(m) => m,
      Err(f) => panic!(format!("{}", f))
    };

    Config {
        source_dir: matches.opt_str("source-dir").unwrap(),
        filter: matches.free.first().map(|s| s.clone())
    }
}

fn test_options(config: Config) -> TestOpts {
    TestOpts {
        filter: config.filter,
        run_ignored: false,
        run_tests: true,
        run_benchmarks: false,
        logfile: None,
        nocapture: false,
        color: AutoColor,
    }
}

fn find_tests(config: Config) -> Vec<TestDescAndFn> {
    let files_res = fs::readdir(&Path::new(config.source_dir));
    let mut files = match files_res {
        Ok(files) => files,
        _ => panic!("Error reading directory."),
    };
    files.retain(|file| file.extension_str() == Some("html") );
    return files.iter().map(|file| make_test(format!("{}", file.display()))).collect();
}

fn make_test(file: String) -> TestDescAndFn {
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(file.clone()),
            ignore: false,
            should_fail: ShouldFail::No,
        },
        testfn: DynTestFn(Thunk::new(move || { run_test(file) }))
    }
}

fn run_test(file: String) {
    let path = os::make_absolute(&Path::new(file)).unwrap();
    // FIXME (#1094): not the right way to transform a path
    let infile = format!("file://{}", path.display());
    let stdout = CreatePipe(false, true);
    let stderr = InheritFd(2);
    let args = ["-z", "-f", infile.as_slice()];

    let mut prc = match Command::new(os::self_exe_path().unwrap().join("servo"))
        .args(args.as_slice())
        .stdin(Ignored)
        .stdout(stdout)
        .stderr(stderr)
        .spawn()
    {
        Ok(p) => p,
        _ => panic!("Unable to spawn process."),
    };
    let mut output = Vec::new();
    loop {
        let byte = prc.stdout.as_mut().unwrap().read_byte();
        match byte {
            Ok(byte) => {
                print!("{}", byte as char);
                output.push(byte);
            }
            _ => break
        }
    }

    let out = str::from_utf8(output.as_slice());
    let lines: Vec<&str> = out.unwrap().split('\n').collect();
    for &line in lines.iter() {
        if line.contains("TEST-UNEXPECTED-FAIL") {
            panic!(line.to_string());
        }
    }

    let retval = prc.wait();
    if retval != Ok(ExitStatus(0)) {
        panic!("Servo exited with non-zero status {:?}", retval);
    }
}
<commit_msg>Fixes #5159<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(collections, core, io, os, path, rustc_private, std_misc, test)]

extern crate getopts;
extern crate test;

use test::{AutoColor, TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName};
use test::ShouldFail;
use getopts::{getopts, reqopt};
use std::{os, str, env};
use std::old_io::fs;
use std::old_io::Reader;
use std::old_io::process::{Command, Ignored, CreatePipe, InheritFd, ExitStatus};
use std::old_path::Path;
use std::thunk::Thunk;

#[derive(Clone)]
struct Config {
    source_dir: String,
    filter: Option<String>
}

fn main() {
    let args = env::args();
    let config = parse_config(args.map(|x| x.into_string().unwrap()).collect());
    let opts = test_options(config.clone());
    let tests = find_tests(config);
    match run_tests_console(&opts, tests) {
        Ok(false) => env::set_exit_status(1), // tests failed
        Err(_) => env::set_exit_status(2),    // I/O-related failure
        _ => (),
    }
}

fn parse_config(args: Vec<String>) -> Config {
    let args = args.tail();
    let opts = vec!(reqopt("s", "source-dir", "source-dir", "source-dir"));
    let matches = match getopts(args, opts.as_slice()) {
      Ok(m) => m,
      Err(f) => panic!(format!("{}", f))
    };

    Config {
        source_dir: matches.opt_str("source-dir").unwrap(),
        filter: matches.free.first().map(|s| s.clone())
    }
}

fn test_options(config: Config) -> TestOpts {
    TestOpts {
        filter: config.filter,
        run_ignored: false,
        run_tests: true,
        run_benchmarks: false,
        logfile: None,
        nocapture: false,
        color: AutoColor,
    }
}

fn find_tests(config: Config) -> Vec<TestDescAndFn> {
    let files_res = fs::readdir(&Path::new(config.source_dir));
    let mut files = match files_res {
        Ok(files) => files,
        _ => panic!("Error reading directory."),
    };
    files.retain(|file| file.extension_str() == Some("html") );
    return files.iter().map(|file| make_test(format!("{}", file.display()))).collect();
}

fn make_test(file: String) -> TestDescAndFn {
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(file.clone()),
            ignore: false,
            should_fail: ShouldFail::No,
        },
        testfn: DynTestFn(Thunk::new(move || { run_test(file) }))
    }
}

fn run_test(file: String) {
    let path = os::make_absolute(&Path::new(file)).unwrap();
    // FIXME (#1094): not the right way to transform a path
    let infile = format!("file://{}", path.display());
    let stdout = CreatePipe(false, true);
    let stderr = InheritFd(2);
    let args = ["-z", "-f", infile.as_slice()];

    let mut prc = match Command::new(os::self_exe_path().unwrap().join("servo"))
        .args(args.as_slice())
        .stdin(Ignored)
        .stdout(stdout)
        .stderr(stderr)
        .spawn()
    {
        Ok(p) => p,
        _ => panic!("Unable to spawn process."),
    };
    let mut output = Vec::new();
    loop {
        let byte = prc.stdout.as_mut().unwrap().read_byte();
        match byte {
            Ok(byte) => {
                print!("{}", byte as char);
                output.push(byte);
            }
            _ => break
        }
    }

    let out = str::from_utf8(output.as_slice());
    let lines: Vec<&str> = out.unwrap().split('\n').collect();
    for &line in lines.iter() {
        if line.contains("TEST-UNEXPECTED-FAIL") {
            panic!(line.to_string());
        }
    }

    let retval = prc.wait();
    if retval != Ok(ExitStatus(0)) {
        panic!("Servo exited with non-zero status {:?}", retval);
    }
}
<|endoftext|>


<commit_before>//! Crate to `#include` C++ headers in your Rust code, and generate
//! idiomatic bindings using `cxx`. See [include_cpp] for details.

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(test)]
mod reduce_test;

use std::{
    fs::File,
    io::Write,
    os::unix::prelude::PermissionsExt,
    path::{Path, PathBuf},
    process::Command,
};

use autocxx_engine::{get_clang_path, preprocess};
use clap::{crate_authors, crate_version, App, Arg, ArgMatches};
use indoc::indoc;
use itertools::Itertools;
use tempfile::TempDir;

static LONG_HELP: &str = indoc! {"
Command line utility to minimize autocxx bug cases.

This is a wrapper for creduce.

Example command-line:
autocxx-reduce -I my-inc-dir -h my-header -d 'generate!(\"MyClass\")' -k -- --n 64
"};

fn main() {
    let matches = App::new("autocxx-reduce")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Reduce a C++ test case")
        .long_about(LONG_HELP)
        .arg(
            Arg::with_name("inc")
                .short("I")
                .long("inc")
                .multiple(true)
                .number_of_values(1)
                .value_name("INCLUDE DIRS")
                .help("include path")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("define")
                .short("D")
                .long("define")
                .multiple(true)
                .number_of_values(1)
                .value_name("DEFINE")
                .help("macro definition")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("header")
                .short("h")
                .long("header")
                .multiple(true)
                .number_of_values(1)
                .required(true)
                .value_name("HEADER")
                .help("header file name")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("directive")
                .short("d")
                .long("directive")
                .multiple(true)
                .number_of_values(1)
                .value_name("DIRECTIVE")
                .help("directives to put within include_cpp!")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("problem")
                .short("p")
                .long("problem")
                .required(true)
                .value_name("PROBLEM")
                .help("problem string we're looking for... may be in logs, or in generated C++, or generated .rs")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("creduce")
                .long("creduce")
                .required(true)
                .value_name("PATH")
                .help("creduce binary location")
                .default_value("creduce")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("output")
                .short("o")
                .long("output")
                .value_name("OUTPUT")
                .help("where to write minimized output")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("gen-cmd")
                .short("g")
                .long("gen-cmd")
                .value_name("GEN-CMD")
                .help("where to find autocxx-gen")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("keep")
                .short("k")
                .long("keep-dir")
                .help("keep the temporary directory for debugging purposes"),
        )
        .arg(
            Arg::with_name("clang-args")
                .short("c")
                .long("clang-arg")
                .multiple(true)
                .value_name("CLANG_ARG")
                .help("Extra arguments to pass to Clang"),
        )
        .arg(
            Arg::with_name("no-precompile")
                .long("no-precompile")
                .help("Do not precompile the C++ header before passing to autocxxgen"),
        )
        .arg(
            Arg::with_name("no-postcompile")
                .long("no-postcompile")
                .help("Do not post-compile the C++ generated by autocxxgen"),
        )
        .arg(Arg::with_name("creduce-args").last(true).multiple(true))
        .get_matches();
    run(matches).unwrap();
}

fn run(matches: ArgMatches) -> Result<(), std::io::Error> {
    let keep_tmp = matches.is_present("keep");
    let tmp_dir = TempDir::new()?;
    let r = do_run(matches, &tmp_dir);
    if keep_tmp {
        println!(
            "Keeping temp dir created at: {}",
            tmp_dir.into_path().to_str().unwrap()
        );
    }
    r
}

fn do_run(matches: ArgMatches, tmp_dir: &TempDir) -> Result<(), std::io::Error> {
    let incs: Vec<_> = matches
        .values_of("inc")
        .unwrap_or_default()
        .map(PathBuf::from)
        .collect();
    let defs: Vec<_> = matches.values_of("define").unwrap_or_default().collect();
    let headers: Vec<_> = matches.values_of("header").unwrap_or_default().collect();
    let listing_path = tmp_dir.path().join("listing.h");
    create_concatenated_header(&headers, &listing_path)?;
    let concat_path = tmp_dir.path().join("concat.h");
    announce_progress(&format!(
        "Preprocessing {:?} to {:?}",
        listing_path, concat_path
    ));
    preprocess(&listing_path, &concat_path, &incs, &defs)?;
    let rs_path = tmp_dir.path().join("input.rs");
    let directives: Vec<_> = std::iter::once("#include \"concat.h\"\n".to_string())
        .chain(
            matches
                .values_of("directive")
                .unwrap_or_default()
                .map(|s| format!("{}\n", s)),
        )
        .collect();
    create_rs_file(&rs_path, &directives)?;
    let extra_clang_args: Vec<_> = matches
        .values_of("clang-args")
        .unwrap_or_default()
        .collect();
    let default_gen_cmd = std::env::current_exe()?
        .parent()
        .unwrap()
        .join("autocxx-gen")
        .to_str()
        .unwrap()
        .to_string();
    let gen_cmd = matches.value_of("gen-cmd").unwrap_or(&default_gen_cmd);
    run_sample_gen_cmd(gen_cmd, &rs_path, &tmp_dir.path(), &extra_clang_args)?;
    let interestingness_test = tmp_dir.path().join("test.sh");
    create_interestingness_test(
        gen_cmd,
        &interestingness_test,
        matches.value_of("problem").unwrap(),
        &rs_path,
        &extra_clang_args,
        matches.value_of("no-precompile").is_none(),
        matches.value_of("no-postcompile").is_none(),
    )?;
    run_interestingness_test(&interestingness_test);
    run_creduce(
        matches.value_of("creduce").unwrap(),
        &interestingness_test,
        &concat_path,
        matches.values_of("creduce-args").unwrap_or_default(),
    );
    announce_progress("creduce completed");
    let output_path = matches.value_of("output");
    match output_path {
        None => print_minimized_case(&concat_path)?,
        Some(output_path) => {
            std::fs::copy(&concat_path, &PathBuf::from(output_path))?;
        }
    };
    Ok(())
}

fn announce_progress(msg: &str) {
    println!("=== {} ===", msg);
}

fn print_minimized_case(concat_path: &Path) -> Result<(), std::io::Error> {
    announce_progress("Completed. Minimized test case:");
    let contents = std::fs::read_to_string(concat_path)?;
    println!("{}", contents);
    Ok(())
}

/// Arguments we pass to creduce if supported. This pass always seems to cause a crash
/// as far as I can tell, so always exclude it. It may be environment-dependent,
/// of course, but as I'm the primary user of this tool I am ruthlessly removing it.
const REMOVE_PASS_LINE_MARKERS: &[&str] = &["--remove-pass", "pass_line_markers", "*"];
const SKIP_INITIAL_PASSES: &[&str] = &["--skip-initial-passes"];

fn creduce_supports_remove_pass(creduce_cmd: &str) -> bool {
    let msg = Command::new(creduce_cmd)
        .arg("--help")
        .output()
        .unwrap()
        .stdout;
    let msg = std::str::from_utf8(&msg).unwrap();
    msg.contains("--remove-pass")
}

fn run_creduce<'a>(
    creduce_cmd: &str,
    interestingness_test: &'a Path,
    concat_path: &'a Path,
    creduce_args: impl Iterator<Item = &'a str>,
) {
    announce_progress("creduce");
    let args = std::iter::once(interestingness_test.to_str().unwrap())
        .chain(std::iter::once(concat_path.to_str().unwrap()))
        .chain(creduce_args)
        .chain(
            if creduce_supports_remove_pass(creduce_cmd) {
                REMOVE_PASS_LINE_MARKERS
            } else {
                SKIP_INITIAL_PASSES
            }
            .iter()
            .copied(),
        )
        .collect::<Vec<_>>();
    println!("Command: {} {}", creduce_cmd, args.join(" "));
    Command::new(creduce_cmd)
        .args(args)
        .status()
        .expect("failed to creduce");
}

fn run_sample_gen_cmd(
    gen_cmd: &str,
    rs_file: &Path,
    tmp_dir: &Path,
    extra_clang_args: &[&str],
) -> Result<(), std::io::Error> {
    let args = format_gen_cmd(rs_file, tmp_dir.to_str().unwrap(), extra_clang_args);
    let args = args.collect::<Vec<_>>();
    let args_str = args.join(" ");
    announce_progress(&format!("Running sample gen cmd: {} {}", gen_cmd, args_str));
    Command::new(gen_cmd).args(args).status()?;
    Ok(())
}

fn format_gen_cmd<'a>(
    rs_file: &Path,
    dir: &str,
    extra_clang_args: &'a [&str],
) -> impl Iterator<Item = String> + 'a {
    let args = [
        "-o".to_string(),
        dir.to_string(),
        "-I".to_string(),
        dir.to_string(),
        rs_file.to_str().unwrap().to_string(),
        "--gen-rs-complete".to_string(),
        "--gen-cpp".to_string(),
        "--".to_string(),
    ]
    .to_vec();
    args.into_iter()
        .chain(extra_clang_args.iter().map(|s| s.to_string()))
}

fn create_interestingness_test(
    gen_cmd: &str,
    test_path: &Path,
    problem: &str,
    rs_file: &Path,
    extra_clang_args: &[&str],
    precompile: bool,
    postcompile: bool,
) -> Result<(), std::io::Error> {
    announce_progress("Creating interestingness test");
    // Ensure we refer to the input header by relative path
    // because creduce will invoke us in some other directory with
    // a copy thereof.
    let mut args = format_gen_cmd(rs_file, "$(pwd)", extra_clang_args);
    let args = args.join(" ");
    let precompile_step = make_compile_step(precompile, "concat.h", extra_clang_args);
    let postcompile_step = format!(
        "; {} 2>&1",
        make_compile_step(postcompile, "gen0.cc", extra_clang_args)
    );
    let content = format!(
        indoc! {"
        #!/bin/sh
        set -e
        echo Precompile
        {}
        echo Move
        mv concat.h concat-body.h
        echo Codegen
        (echo \"#ifndef __CONCAT_H__\"; echo \"#define __CONCAT_H__\"; echo '#include \"concat-body.h\"'; echo \"#endif\") > concat.h
        ({} {} 2>&1 && cat gen.complete.rs && cat autocxxgen*.h {}) | grep \"{}\"  >/dev/null 2>&1
        echo Remove
        rm concat.h
        echo Swap back
        mv concat-body.h concat.h
        echo Done
    "},
        precompile_step, gen_cmd, args, postcompile_step, problem
    );
    println!("Interestingness test:\n{}", content);
    {
        let mut file = File::create(test_path)?;
        file.write_all(content.as_bytes())?;
    }

    let mut perms = std::fs::metadata(&test_path)?.permissions();
    perms.set_mode(0o700);
    std::fs::set_permissions(&test_path, perms)?;
    Ok(())
}

fn make_compile_step(enabled: bool, file: &str, extra_clang_args: &[&str]) -> String {
    if enabled {
        format!(
            "{} -I. {} {}",
            get_clang_path(),
            file,
            extra_clang_args.join(" ")
        )
    } else {
        "".into()
    }
}

fn run_interestingness_test(test_path: &Path) {
    announce_progress("Running interestingness test");
    let status = Command::new(test_path).status().unwrap();
    announce_progress(&format!(
        "Have run interestingness test - result is {:?}",
        status.code()
    ));
}

fn create_rs_file(rs_path: &Path, directives: &[String]) -> Result<(), std::io::Error> {
    announce_progress("Creating Rust input file");
    let mut file = File::create(rs_path)?;
    file.write_all("use autocxx::include_cpp;\ninclude_cpp! (\n".as_bytes())?;
    for directive in directives {
        file.write_all(directive.as_bytes())?;
    }
    file.write_all(");\n".as_bytes())?;
    Ok(())
}

fn create_concatenated_header(headers: &[&str], listing_path: &Path) -> Result<(), std::io::Error> {
    announce_progress("Creating preprocessed header");
    let mut file = File::create(listing_path)?;
    for header in headers {
        file.write_all(format!("#include \"{}\"\n", header).as_bytes())?;
    }
    Ok(())
}
<commit_msg>Cease to pre-run test, now that it may delete concat.h<commit_after>//! Crate to `#include` C++ headers in your Rust code, and generate
//! idiomatic bindings using `cxx`. See [include_cpp] for details.

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(test)]
mod reduce_test;

use std::{
    fs::File,
    io::Write,
    os::unix::prelude::PermissionsExt,
    path::{Path, PathBuf},
    process::Command,
};

use autocxx_engine::{get_clang_path, preprocess};
use clap::{crate_authors, crate_version, App, Arg, ArgMatches};
use indoc::indoc;
use itertools::Itertools;
use tempfile::TempDir;

static LONG_HELP: &str = indoc! {"
Command line utility to minimize autocxx bug cases.

This is a wrapper for creduce.

Example command-line:
autocxx-reduce -I my-inc-dir -h my-header -d 'generate!(\"MyClass\")' -k -- --n 64
"};

fn main() {
    let matches = App::new("autocxx-reduce")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Reduce a C++ test case")
        .long_about(LONG_HELP)
        .arg(
            Arg::with_name("inc")
                .short("I")
                .long("inc")
                .multiple(true)
                .number_of_values(1)
                .value_name("INCLUDE DIRS")
                .help("include path")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("define")
                .short("D")
                .long("define")
                .multiple(true)
                .number_of_values(1)
                .value_name("DEFINE")
                .help("macro definition")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("header")
                .short("h")
                .long("header")
                .multiple(true)
                .number_of_values(1)
                .required(true)
                .value_name("HEADER")
                .help("header file name")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("directive")
                .short("d")
                .long("directive")
                .multiple(true)
                .number_of_values(1)
                .value_name("DIRECTIVE")
                .help("directives to put within include_cpp!")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("problem")
                .short("p")
                .long("problem")
                .required(true)
                .value_name("PROBLEM")
                .help("problem string we're looking for... may be in logs, or in generated C++, or generated .rs")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("creduce")
                .long("creduce")
                .required(true)
                .value_name("PATH")
                .help("creduce binary location")
                .default_value("creduce")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("output")
                .short("o")
                .long("output")
                .value_name("OUTPUT")
                .help("where to write minimized output")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("gen-cmd")
                .short("g")
                .long("gen-cmd")
                .value_name("GEN-CMD")
                .help("where to find autocxx-gen")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("keep")
                .short("k")
                .long("keep-dir")
                .help("keep the temporary directory for debugging purposes"),
        )
        .arg(
            Arg::with_name("clang-args")
                .short("c")
                .long("clang-arg")
                .multiple(true)
                .value_name("CLANG_ARG")
                .help("Extra arguments to pass to Clang"),
        )
        .arg(
            Arg::with_name("no-precompile")
                .long("no-precompile")
                .help("Do not precompile the C++ header before passing to autocxxgen"),
        )
        .arg(
            Arg::with_name("no-postcompile")
                .long("no-postcompile")
                .help("Do not post-compile the C++ generated by autocxxgen"),
        )
        .arg(Arg::with_name("creduce-args").last(true).multiple(true))
        .get_matches();
    run(matches).unwrap();
}

fn run(matches: ArgMatches) -> Result<(), std::io::Error> {
    let keep_tmp = matches.is_present("keep");
    let tmp_dir = TempDir::new()?;
    let r = do_run(matches, &tmp_dir);
    if keep_tmp {
        println!(
            "Keeping temp dir created at: {}",
            tmp_dir.into_path().to_str().unwrap()
        );
    }
    r
}

fn do_run(matches: ArgMatches, tmp_dir: &TempDir) -> Result<(), std::io::Error> {
    let incs: Vec<_> = matches
        .values_of("inc")
        .unwrap_or_default()
        .map(PathBuf::from)
        .collect();
    let defs: Vec<_> = matches.values_of("define").unwrap_or_default().collect();
    let headers: Vec<_> = matches.values_of("header").unwrap_or_default().collect();
    let listing_path = tmp_dir.path().join("listing.h");
    create_concatenated_header(&headers, &listing_path)?;
    let concat_path = tmp_dir.path().join("concat.h");
    announce_progress(&format!(
        "Preprocessing {:?} to {:?}",
        listing_path, concat_path
    ));
    preprocess(&listing_path, &concat_path, &incs, &defs)?;
    let rs_path = tmp_dir.path().join("input.rs");
    let directives: Vec<_> = std::iter::once("#include \"concat.h\"\n".to_string())
        .chain(
            matches
                .values_of("directive")
                .unwrap_or_default()
                .map(|s| format!("{}\n", s)),
        )
        .collect();
    create_rs_file(&rs_path, &directives)?;
    let extra_clang_args: Vec<_> = matches
        .values_of("clang-args")
        .unwrap_or_default()
        .collect();
    let default_gen_cmd = std::env::current_exe()?
        .parent()
        .unwrap()
        .join("autocxx-gen")
        .to_str()
        .unwrap()
        .to_string();
    let gen_cmd = matches.value_of("gen-cmd").unwrap_or(&default_gen_cmd);
    run_sample_gen_cmd(gen_cmd, &rs_path, &tmp_dir.path(), &extra_clang_args)?;
    let interestingness_test = tmp_dir.path().join("test.sh");
    create_interestingness_test(
        gen_cmd,
        &interestingness_test,
        matches.value_of("problem").unwrap(),
        &rs_path,
        &extra_clang_args,
        matches.value_of("no-precompile").is_none(),
        matches.value_of("no-postcompile").is_none(),
    )?;
    run_creduce(
        matches.value_of("creduce").unwrap(),
        &interestingness_test,
        &concat_path,
        matches.values_of("creduce-args").unwrap_or_default(),
    );
    announce_progress("creduce completed");
    let output_path = matches.value_of("output");
    match output_path {
        None => print_minimized_case(&concat_path)?,
        Some(output_path) => {
            std::fs::copy(&concat_path, &PathBuf::from(output_path))?;
        }
    };
    Ok(())
}

fn announce_progress(msg: &str) {
    println!("=== {} ===", msg);
}

fn print_minimized_case(concat_path: &Path) -> Result<(), std::io::Error> {
    announce_progress("Completed. Minimized test case:");
    let contents = std::fs::read_to_string(concat_path)?;
    println!("{}", contents);
    Ok(())
}

/// Arguments we pass to creduce if supported. This pass always seems to cause a crash
/// as far as I can tell, so always exclude it. It may be environment-dependent,
/// of course, but as I'm the primary user of this tool I am ruthlessly removing it.
const REMOVE_PASS_LINE_MARKERS: &[&str] = &["--remove-pass", "pass_line_markers", "*"];
const SKIP_INITIAL_PASSES: &[&str] = &["--skip-initial-passes"];

fn creduce_supports_remove_pass(creduce_cmd: &str) -> bool {
    let msg = Command::new(creduce_cmd)
        .arg("--help")
        .output()
        .unwrap()
        .stdout;
    let msg = std::str::from_utf8(&msg).unwrap();
    msg.contains("--remove-pass")
}

fn run_creduce<'a>(
    creduce_cmd: &str,
    interestingness_test: &'a Path,
    concat_path: &'a Path,
    creduce_args: impl Iterator<Item = &'a str>,
) {
    announce_progress("creduce");
    let args = std::iter::once(interestingness_test.to_str().unwrap())
        .chain(std::iter::once(concat_path.to_str().unwrap()))
        .chain(creduce_args)
        .chain(
            if creduce_supports_remove_pass(creduce_cmd) {
                REMOVE_PASS_LINE_MARKERS
            } else {
                SKIP_INITIAL_PASSES
            }
            .iter()
            .copied(),
        )
        .collect::<Vec<_>>();
    println!("Command: {} {}", creduce_cmd, args.join(" "));
    Command::new(creduce_cmd)
        .args(args)
        .status()
        .expect("failed to creduce");
}

fn run_sample_gen_cmd(
    gen_cmd: &str,
    rs_file: &Path,
    tmp_dir: &Path,
    extra_clang_args: &[&str],
) -> Result<(), std::io::Error> {
    let args = format_gen_cmd(rs_file, tmp_dir.to_str().unwrap(), extra_clang_args);
    let args = args.collect::<Vec<_>>();
    let args_str = args.join(" ");
    announce_progress(&format!("Running sample gen cmd: {} {}", gen_cmd, args_str));
    Command::new(gen_cmd).args(args).status()?;
    Ok(())
}

fn format_gen_cmd<'a>(
    rs_file: &Path,
    dir: &str,
    extra_clang_args: &'a [&str],
) -> impl Iterator<Item = String> + 'a {
    let args = [
        "-o".to_string(),
        dir.to_string(),
        "-I".to_string(),
        dir.to_string(),
        rs_file.to_str().unwrap().to_string(),
        "--gen-rs-complete".to_string(),
        "--gen-cpp".to_string(),
        "--".to_string(),
    ]
    .to_vec();
    args.into_iter()
        .chain(extra_clang_args.iter().map(|s| s.to_string()))
}

fn create_interestingness_test(
    gen_cmd: &str,
    test_path: &Path,
    problem: &str,
    rs_file: &Path,
    extra_clang_args: &[&str],
    precompile: bool,
    postcompile: bool,
) -> Result<(), std::io::Error> {
    announce_progress("Creating interestingness test");
    // Ensure we refer to the input header by relative path
    // because creduce will invoke us in some other directory with
    // a copy thereof.
    let mut args = format_gen_cmd(rs_file, "$(pwd)", extra_clang_args);
    let args = args.join(" ");
    let precompile_step = make_compile_step(precompile, "concat.h", extra_clang_args);
    let postcompile_step = format!(
        "; {} 2>&1",
        make_compile_step(postcompile, "gen0.cc", extra_clang_args)
    );
    let content = format!(
        indoc! {"
        #!/bin/sh
        set -e
        echo Precompile
        {}
        echo Move
        mv concat.h concat-body.h
        echo Codegen
        (echo \"#ifndef __CONCAT_H__\"; echo \"#define __CONCAT_H__\"; echo '#include \"concat-body.h\"'; echo \"#endif\") > concat.h
        ({} {} 2>&1 && cat gen.complete.rs && cat autocxxgen*.h {}) | grep \"{}\"  >/dev/null 2>&1
        echo Remove
        rm concat.h
        echo Swap back
        mv concat-body.h concat.h
        echo Done
    "},
        precompile_step, gen_cmd, args, postcompile_step, problem
    );
    println!("Interestingness test:\n{}", content);
    {
        let mut file = File::create(test_path)?;
        file.write_all(content.as_bytes())?;
    }

    let mut perms = std::fs::metadata(&test_path)?.permissions();
    perms.set_mode(0o700);
    std::fs::set_permissions(&test_path, perms)?;
    Ok(())
}

fn make_compile_step(enabled: bool, file: &str, extra_clang_args: &[&str]) -> String {
    if enabled {
        format!(
            "{} -I. {} {}",
            get_clang_path(),
            file,
            extra_clang_args.join(" ")
        )
    } else {
        "".into()
    }
}

fn create_rs_file(rs_path: &Path, directives: &[String]) -> Result<(), std::io::Error> {
    announce_progress("Creating Rust input file");
    let mut file = File::create(rs_path)?;
    file.write_all("use autocxx::include_cpp;\ninclude_cpp! (\n".as_bytes())?;
    for directive in directives {
        file.write_all(directive.as_bytes())?;
    }
    file.write_all(");\n".as_bytes())?;
    Ok(())
}

fn create_concatenated_header(headers: &[&str], listing_path: &Path) -> Result<(), std::io::Error> {
    announce_progress("Creating preprocessed header");
    let mut file = File::create(listing_path)?;
    for header in headers {
        file.write_all(format!("#include \"{}\"\n", header).as_bytes())?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>extern crate httpd = "tiny-http";

use std::io::net::tcp::TcpStream;

#[test]
fn basic_handling() {
    let (server, port) = httpd::Server::new_with_random_port().unwrap();

    let mut stream = std::io::net::tcp::TcpStream::connect("127.0.0.1", port);
    write!(stream, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n");

    let request = server.recv().unwrap();
    assert!(request.get_method().equiv(&"get"));
    //assert!(request.get_url() == "/");
    request.respond(httpd::Response::from_string(format!("hello world")));

    server.try_recv().unwrap();

    let content = stream.read_to_string().unwrap();
    assert!(content.as_slice().ends_with("hello world"));
}
<commit_msg>Test now ignored because of deadlock<commit_after>extern crate httpd = "tiny-http";

use std::io::net::tcp::TcpStream;

#[test]
#[ignore]
fn basic_handling() {
    let (server, port) = httpd::Server::new_with_random_port().unwrap();

    let mut stream = std::io::net::tcp::TcpStream::connect("127.0.0.1", port).unwrap();
    write!(stream, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n");

    let request = server.recv().unwrap();
    assert!(request.get_method().equiv(&"get"));
    //assert!(request.get_url() == "/");
    request.respond(httpd::Response::from_string(format!("hello world")));

    server.try_recv().unwrap();

    let content = stream.read_to_string().unwrap();
    assert!(content.as_slice().ends_with("hello world"));
}
<|endoftext|>


<commit_before>
extern crate ruster_unsafe;
use ruster_unsafe::*;

use std::process::Command;
use std::env;
use std::path::Path;
use std::collections::HashMap;
use std::iter::FromIterator;
use std::mem::size_of;

#[test]
fn test1() {
	let out_dir = env::var("OUT_DIR").unwrap();

	// get erts include path
	let erts_include = String::from_utf8(Command::new("escript").arg("get_erts_path.erl")
		.output().unwrap().stdout).unwrap();

	println!("include {:?}", erts_include)
;
	// Compile C program
	let exe = Path::new(&out_dir).join("struct_size");
    Command::new("cc").arg("-o").arg(&exe).arg("-I").arg(&erts_include).arg("tests/struct_size.c")
    	.status().unwrap();

    // Run C program that lists C NIF runtime information.
    let stdout:Vec<u8> = Command::new(&exe).output().unwrap().stdout;
 	let output:&str = std::str::from_utf8(&stdout).unwrap();

 	// Parse C program output into hashmap of (&str, u32)
	let sizemap = HashMap::<&str, usize>::from_iter(
		output.lines().map(|ln|ln.split(" "))
		.map(|mut it| (it.next().unwrap(), it.next().unwrap().parse().unwrap())));

	/* types to check are:

	ERL_NIF_UINT
	ERL_NIF_TERM
	ErlNifFunc
	ErlNifEntry
	ErlNifBinary
	ErlNifPid
	ErlNifSysInfo
	ErlNifMapIterator

	*/

	assert_eq!(&size_of::<ERL_NIF_UINT>(),      sizemap.get("ERL_NIF_UINT").unwrap());
	assert_eq!(&size_of::<ERL_NIF_TERM>(),      sizemap.get("ERL_NIF_TERM").unwrap());
	assert_eq!(&size_of::<ErlNifFunc>(),        sizemap.get("ErlNifFunc").unwrap());
	assert_eq!(&size_of::<ErlNifEntry>(),       sizemap.get("ErlNifEntry").unwrap());
	assert_eq!(&size_of::<ErlNifBinary>(),      sizemap.get("ErlNifBinary").unwrap());
	assert_eq!(&size_of::<ErlNifPid>(),         sizemap.get("ErlNifPid").unwrap());
	assert_eq!(&size_of::<ErlNifSysInfo>(),     sizemap.get("ErlNifSysInfo").unwrap());
	assert_eq!(&size_of::<ErlNifMapIterator>(), sizemap.get("ErlNifMapIterator").unwrap());
}
<commit_msg>improve error reporting in struct size test<commit_after>
extern crate ruster_unsafe;
use ruster_unsafe::*;

use std::process::Command;
use std::env;
use std::path::Path;
use std::collections::HashMap;
use std::iter::FromIterator;
use std::mem::size_of;

#[test]
fn test1() {

	let out_dir = env::var("OUT_DIR").unwrap();

	// use environment escript and cc if available
	let escript = env::var("ESCRIPT").unwrap_or("escript".to_string());
	let cc      = env::var("CC").unwrap_or("cc".to_string());

	// get erts include path
	let erts_include = Command::new(escript).arg("get_erts_path.erl")
		.output()
		.map_err(|_| "Can't run escript")
		.map(|out| {
			match out.status.success() {
				true => out.stdout,
				false => panic!("Can't run get_erts_path.erl")
			}
		})
		.map(String::from_utf8)
		.unwrap().unwrap();

	//println!("include {:?}", erts_include);

	// Compile C program
	let exe = Path::new(&out_dir).join("struct_size");
    match Command::new(cc).arg("-o").arg(&exe).arg("-I").arg(&erts_include).arg("tests/struct_size.c")
    	.status()
    	.map_err(|_|"Can't find c compiler (cc or value of environment CC)")
    	.unwrap().success() {
    		false => panic!("Can't compile struct_size.c"),
    		_ => ()
    	}

    // Run C program that lists C NIF runtime information.
    let stdout:Vec<u8> = Command::new(&exe).output()
    	.map_err(|_|"Can't run C runtime information program")
    	.unwrap().stdout;

 	let output:&str = std::str::from_utf8(&stdout).unwrap();

 	// Parse C program output into hashmap of (&str, u32)
	let sizemap = HashMap::<&str, usize>::from_iter(
		output.lines().map(|ln|ln.split(" "))
		.map(|mut it| (it.next().unwrap(), it.next().unwrap().parse().unwrap())));

	/* types to check are:

	ERL_NIF_UINT
	ERL_NIF_TERM
	ErlNifFunc
	ErlNifEntry
	ErlNifBinary
	ErlNifPid
	ErlNifSysInfo
	ErlNifMapIterator

	*/

	assert_eq!(&size_of::<ERL_NIF_UINT>(),      sizemap.get("ERL_NIF_UINT").unwrap());
	assert_eq!(&size_of::<ERL_NIF_TERM>(),      sizemap.get("ERL_NIF_TERM").unwrap());
	assert_eq!(&size_of::<ErlNifFunc>(),        sizemap.get("ErlNifFunc").unwrap());
	assert_eq!(&size_of::<ErlNifEntry>(),       sizemap.get("ErlNifEntry").unwrap());
	assert_eq!(&size_of::<ErlNifBinary>(),      sizemap.get("ErlNifBinary").unwrap());
	assert_eq!(&size_of::<ErlNifPid>(),         sizemap.get("ErlNifPid").unwrap());
	assert_eq!(&size_of::<ErlNifSysInfo>(),     sizemap.get("ErlNifSysInfo").unwrap());
	assert_eq!(&size_of::<ErlNifMapIterator>(), sizemap.get("ErlNifMapIterator").unwrap());
}
<|endoftext|>


<commit_before>extern crate cymbalum;
use cymbalum::*;

fn main() {
    let mut universe = Universe::from_cell(UnitCell::cubic(20.0));

    for i in 0..10 {
        for j in 0..10 {
            for k in 0..10 {
                let mut part = Particle::new("Ar");
                part.set_position(Vector3D::new(
                        i as f64 * 2.0,
                        j as f64 * 2.0,
                        k as f64 * 2.0
                ));
                universe.add_particle(part);
            }
        }
    }
    universe.add_pair_interaction("Ar", "Ar", LennardJones{sigma: 3.4, epsilon: 1e-4});

    let mut simulation = Simulation::new(MolecularDynamics::new(1.0));
    simulation.add_output(TrajectoryOutput::new("trajectory.xyz"));

    simulation.run(&mut universe, 500);

    println!("All done!")
}
<commit_msg>Update the MD example<commit_after>extern crate cymbalum;
use cymbalum::*;

fn main() {
    let mut universe = Universe::from_cell(UnitCell::cubic(17.0));

    // Create a cubic crystal of Argon by hand.
    for i in 0..5 {
        for j in 0..5 {
            for k in 0..5 {
                let mut part = Particle::new("Ar");
                part.set_position(Vector3D::new(
                        i as f64 * 3.4,
                        j as f64 * 3.4,
                        k as f64 * 3.4
                ));
                universe.add_particle(part);
            }
        }
    }
    universe.add_pair_interaction("Ar", "Ar", LennardJones{sigma: 3.4, epsilon: 1e-4});

    let mut velocities = BoltzmanVelocities::new(300.0);
    velocities.seed(129);
    velocities.init(&mut universe);

    let mut simulation = Simulation::new(MolecularDynamics::new(1.0));
    simulation.add_output(TrajectoryOutput::new("trajectory.xyz"));

    simulation.run(&mut universe, 500);

    println!("All done!")
}
<|endoftext|>


<commit_before>use std::ops::Range;
use std::slice;
use libc::c_void;

use objc::Id;
use {INSObject, INSCopying, INSMutableCopying, NSRange};

pub trait INSData : INSObject {
    fn len(&self) -> usize {
        unsafe {
            msg_send![self, length]
        }
    }

    fn bytes(&self) -> &[u8] {
        let ptr: *const c_void = unsafe { msg_send![self, bytes] };
        // The bytes pointer may be null for length zero
        let (ptr, len) = if ptr.is_null() {
            (0x1 as *const u8, 0)
        } else {
            (ptr as *const u8, self.len())
        };
        unsafe {
            slice::from_raw_parts(ptr, len)
        }
    }

    fn with_bytes(bytes: &[u8]) -> Id<Self> {
        let cls = <Self as INSObject>::class();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytes:bytes.as_ptr()
                                                       length:bytes.len()];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSData);

impl INSData for NSData { }

impl INSCopying for NSData {
    type Output = NSData;
}

impl INSMutableCopying for NSData {
    type Output = NSMutableData;
}

pub trait INSMutableData : INSData {
    fn bytes_mut(&mut self) -> &mut [u8] {
        let ptr: *mut c_void = unsafe { msg_send![self, mutableBytes] };
        // The bytes pointer may be null for length zero
        let (ptr, len) = if ptr.is_null() {
            (0x1 as *mut u8, 0)
        } else {
            (ptr as *mut u8, self.len())
        };
        unsafe {
            slice::from_raw_parts_mut(ptr, len)
        }
    }

    fn set_len(&mut self, len: usize) {
        unsafe {
            let _: () = msg_send![self, setLength:len];
        }
    }

    fn append(&mut self, bytes: &[u8]) {
        unsafe {
            let _: () = msg_send![self, appendBytes:bytes.as_ptr()
                                             length:bytes.len()];
        }
    }

    fn replace_range(&mut self, range: Range<usize>, bytes: &[u8]) {
        let range = NSRange::from_range(range);
        unsafe {
            let _: () = msg_send![self, replaceBytesInRange:range
                                                  withBytes:bytes.as_ptr()
                                                     length:bytes.len()];
        }
    }

    fn set_bytes(&mut self, bytes: &[u8]) {
        let len = self.len();
        self.replace_range(0..len, bytes);
    }
}

object_struct!(NSMutableData);

impl INSData for NSMutableData { }

impl INSMutableData for NSMutableData { }

impl INSCopying for NSMutableData {
    type Output = NSData;
}

impl INSMutableCopying for NSMutableData {
    type Output = NSMutableData;
}

#[cfg(test)]
mod tests {
    use objc::Id;
    use INSObject;
    use super::{INSData, INSMutableData, NSData, NSMutableData};

    #[test]
    fn test_bytes() {
        let bytes = [3, 7, 16, 52, 112, 19];
        let data: Id<NSData> = INSData::with_bytes(&bytes);
        assert!(data.len() == bytes.len());
        assert!(data.bytes() == bytes);
    }

    #[test]
    fn test_no_bytes() {
        let data: Id<NSData> = INSObject::new();
        assert!(Some(data.bytes()).is_some());
    }

    #[test]
    fn test_bytes_mut() {
        let mut data: Id<NSMutableData> = INSData::with_bytes(&[7, 16]);
        data.bytes_mut()[0] = 3;
        assert!(data.bytes() == [3, 16]);
    }

    #[test]
    fn test_set_len() {
        let mut data: Id<NSMutableData> = INSData::with_bytes(&[7, 16]);
        data.set_len(4);
        assert!(data.len() == 4);
        assert!(data.bytes() == [7, 16, 0, 0]);

        data.set_len(1);
        assert!(data.len() == 1);
        assert!(data.bytes() == [7]);
    }

    #[test]
    fn test_append() {
        let mut data: Id<NSMutableData> = INSData::with_bytes(&[7, 16]);
        data.append(&[3, 52]);
        assert!(data.len() == 4);
        assert!(data.bytes() == [7, 16, 3, 52]);
    }

    #[test]
    fn test_replace() {
        let mut data: Id<NSMutableData> = INSData::with_bytes(&[7, 16]);
        data.replace_range(0..0, &[3]);
        assert!(data.bytes() == [3, 7, 16]);

        data.replace_range(1..2, &[52, 13]);
        assert!(data.bytes() == [3, 52, 13, 16]);

        data.replace_range(2..4, &[6]);
        assert!(data.bytes() == [3, 52, 6]);

        data.set_bytes(&[8, 17]);
        assert!(data.bytes() == [8, 17]);
    }
}
<commit_msg>Added NSData from_vec method.<commit_after>use std::mem;
use std::ops::Range;
use std::slice;
use libc::c_void;

use objc::Id;
use objc::block::{Block, ConcreteBlock};
use {INSObject, INSCopying, INSMutableCopying, NSRange};

pub trait INSData : INSObject {
    fn len(&self) -> usize {
        unsafe {
            msg_send![self, length]
        }
    }

    fn bytes(&self) -> &[u8] {
        let ptr: *const c_void = unsafe { msg_send![self, bytes] };
        // The bytes pointer may be null for length zero
        let (ptr, len) = if ptr.is_null() {
            (0x1 as *const u8, 0)
        } else {
            (ptr as *const u8, self.len())
        };
        unsafe {
            slice::from_raw_parts(ptr, len)
        }
    }

    fn with_bytes(bytes: &[u8]) -> Id<Self> {
        let cls = <Self as INSObject>::class();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytes:bytes.as_ptr()
                                                       length:bytes.len()];
            Id::from_retained_ptr(obj)
        }
    }

    fn from_vec(bytes: Vec<u8>) -> Id<Self> {
        let capacity = bytes.capacity();
        let dealloc = ConcreteBlock::new(move |bytes: *mut c_void, len: usize| unsafe {
            // Recreate the Vec and let it drop
            let _ = Vec::from_raw_parts(bytes as *mut u8, len, capacity);
        });
        let mut dealloc = dealloc.copy();
        let dealloc: &mut Block<(*mut c_void, usize), ()> = &mut dealloc;

        let mut bytes = bytes;
        let cls = <Self as INSObject>::class();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytesNoCopy:bytes.as_mut_ptr()
                                                             length:bytes.len()
                                                        deallocator:dealloc];
            mem::forget(bytes);
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSData);

impl INSData for NSData { }

impl INSCopying for NSData {
    type Output = NSData;
}

impl INSMutableCopying for NSData {
    type Output = NSMutableData;
}

pub trait INSMutableData : INSData {
    fn bytes_mut(&mut self) -> &mut [u8] {
        let ptr: *mut c_void = unsafe { msg_send![self, mutableBytes] };
        // The bytes pointer may be null for length zero
        let (ptr, len) = if ptr.is_null() {
            (0x1 as *mut u8, 0)
        } else {
            (ptr as *mut u8, self.len())
        };
        unsafe {
            slice::from_raw_parts_mut(ptr, len)
        }
    }

    fn set_len(&mut self, len: usize) {
        unsafe {
            let _: () = msg_send![self, setLength:len];
        }
    }

    fn append(&mut self, bytes: &[u8]) {
        unsafe {
            let _: () = msg_send![self, appendBytes:bytes.as_ptr()
                                             length:bytes.len()];
        }
    }

    fn replace_range(&mut self, range: Range<usize>, bytes: &[u8]) {
        let range = NSRange::from_range(range);
        unsafe {
            let _: () = msg_send![self, replaceBytesInRange:range
                                                  withBytes:bytes.as_ptr()
                                                     length:bytes.len()];
        }
    }

    fn set_bytes(&mut self, bytes: &[u8]) {
        let len = self.len();
        self.replace_range(0..len, bytes);
    }
}

object_struct!(NSMutableData);

impl INSData for NSMutableData { }

impl INSMutableData for NSMutableData { }

impl INSCopying for NSMutableData {
    type Output = NSData;
}

impl INSMutableCopying for NSMutableData {
    type Output = NSMutableData;
}

#[cfg(test)]
mod tests {
    use objc::Id;
    use INSObject;
    use super::{INSData, INSMutableData, NSData, NSMutableData};

    #[test]
    fn test_bytes() {
        let bytes = [3, 7, 16, 52, 112, 19];
        let data: Id<NSData> = INSData::with_bytes(&bytes);
        assert!(data.len() == bytes.len());
        assert!(data.bytes() == bytes);
    }

    #[test]
    fn test_no_bytes() {
        let data: Id<NSData> = INSObject::new();
        assert!(Some(data.bytes()).is_some());
    }

    #[test]
    fn test_bytes_mut() {
        let mut data: Id<NSMutableData> = INSData::with_bytes(&[7, 16]);
        data.bytes_mut()[0] = 3;
        assert!(data.bytes() == [3, 16]);
    }

    #[test]
    fn test_set_len() {
        let mut data: Id<NSMutableData> = INSData::with_bytes(&[7, 16]);
        data.set_len(4);
        assert!(data.len() == 4);
        assert!(data.bytes() == [7, 16, 0, 0]);

        data.set_len(1);
        assert!(data.len() == 1);
        assert!(data.bytes() == [7]);
    }

    #[test]
    fn test_append() {
        let mut data: Id<NSMutableData> = INSData::with_bytes(&[7, 16]);
        data.append(&[3, 52]);
        assert!(data.len() == 4);
        assert!(data.bytes() == [7, 16, 3, 52]);
    }

    #[test]
    fn test_replace() {
        let mut data: Id<NSMutableData> = INSData::with_bytes(&[7, 16]);
        data.replace_range(0..0, &[3]);
        assert!(data.bytes() == [3, 7, 16]);

        data.replace_range(1..2, &[52, 13]);
        assert!(data.bytes() == [3, 52, 13, 16]);

        data.replace_range(2..4, &[6]);
        assert!(data.bytes() == [3, 52, 6]);

        data.set_bytes(&[8, 17]);
        assert!(data.bytes() == [8, 17]);
    }

    #[test]
    fn test_from_vec() {
        let bytes = vec![3, 7, 16];
        let bytes_ptr = bytes.as_ptr();

        let data: Id<NSData> = INSData::from_vec(bytes);
        assert!(data.bytes().as_ptr() == bytes_ptr);
    }
}
<|endoftext|>


<commit_before>use super::scheduler_future::*;

use futures::prelude::*;
use futures::task;
use futures::task::{Poll};
use futures::channel::oneshot;

use std::mem;
use std::pin::*;

///
/// The state of a SyncFuture operation
///
enum SyncFutureState<TFn, TFuture>
where TFuture: Future {
    /// Waiting for the queue to start running the future
    WaitingForQueue(oneshot::Receiver<()>, TFn),

    /// Evaluating an active future for its result
    WaitingForFuture(TFuture),

    /// Finished evaluating
    Completed
}

///
/// Represents a future that runs synchronously with a queue
///
/// The future is only run in an exclusive time slot within the queue - this property is used to guarantee the
/// safety of `Desync::future_sync`, which provides exclusive access to the data store while the future is running.
/// The queue is allowed to continue once the returned future has completed.
///
pub struct SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    /// The state of this future
    state: SyncFutureState<TFn, TFuture>,

    /// Tracks this future on the scheduler (this allows polling this future to invoke desync's thread-stealing semantics instead of leaving the queue scheduling to a separate thread)
    scheduler_future: SchedulerFuture<()>,

    /// Signals when the future has finished running (None if this future is completed)
    task_finished: Option<oneshot::Sender<()>>
}

impl<TFn, TFuture> SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    ///
    /// Creates a new SyncFuture
    ///
    pub fn new(create_future: TFn, scheduler_future: SchedulerFuture<()>, queue_ready: oneshot::Receiver<()>, task_finished: oneshot::Sender<()>) -> SyncFuture<TFn, TFuture> {
        SyncFuture {
            state:              SyncFutureState::WaitingForQueue(queue_ready, create_future),
            scheduler_future:   scheduler_future,
            task_finished:      Some(task_finished)
        }
    }
}

impl<TFn, TFuture> Future for SyncFuture<TFn, TFuture>
where   TFn:                Unpin+Send+FnOnce() -> TFuture,
        TFuture:            Unpin+Send+Future,
        TFuture::Output:    Send {
    type Output = Result<TFuture::Output, oneshot::Canceled>;

    fn poll(mut self: Pin<&mut Self>, context: &mut task::Context) -> Poll<Self::Output> {
        use self::SyncFutureState::*;

        // Rust doesn't seem to have a way to let us update the state in-place, so we need to swap out the old state and swap in the new state
        let result;
        let mut state = Completed;
        mem::swap(&mut state, &mut self.state);

        // Update the state now we own it
        state = match state {
            WaitingForQueue(mut recv, create_future) => {
                // Check the scheduler future (give it a chance to steal the thread)
                if let Poll::Ready(Err(_)) = self.scheduler_future.poll_unpin(context) {
                    // The queue will never get to the point of polling this future
                    result = Poll::Ready(Err(oneshot::Canceled));
                    self.task_finished.take().map(|finished| finished.send(()));
                    Completed
                } else {
                    // Poll the receiver
                    match recv.poll_unpin(context) {
                        Poll::Ready(Ok(())) => {
                            // Start the future
                            let mut future = create_future();

                            // Poll it immediately to determine its status
                            if let Poll::Ready(future_result) = future.poll_unpin(context) {
                                // Future has completed
                                result = Poll::Ready(Ok(future_result));
                                self.task_finished.take().map(|finished| finished.send(()));
                                Completed
                            } else {
                                // Future is still running
                                result = Poll::Pending;
                                WaitingForFuture(future)
                            }
                        }

                        Poll::Ready(Err(_)) => {
                            // Future never became ready
                            result = Poll::Ready(Err(oneshot::Canceled));
                            Completed
                        }

                        Poll::Pending => {
                            // Waiting for the queue to start this future
                            result = Poll::Pending;
                            WaitingForQueue(recv, create_future)
                        }
                    }
                }
            }

            WaitingForFuture(mut future) => {
                if let Poll::Ready(future_result) = future.poll_unpin(context) {
                    // Future has completed
                    result = Poll::Ready(Ok(future_result));
                    self.task_finished.take().map(|finished| finished.send(()));
                    Completed
                } else {
                    // Future is still running
                    result = Poll::Pending;
                    WaitingForFuture(future)
                }
            }

            Completed => {
                // Polling after the result has been returned
                result = Poll::Ready(Err(oneshot::Canceled));
                Completed
            }
        };

        // Swap the state back into the structure
        self.state = state;

        result
    }
}
<commit_msg>Partial fix: need to poll the scheduler future to completion before the sync future finishes<commit_after>use super::scheduler_future::*;

use futures::prelude::*;
use futures::task;
use futures::task::{Poll};
use futures::channel::oneshot;

use std::mem;
use std::pin::*;

///
/// The state of a SyncFuture operation
///
enum SyncFutureState<TFn, TFuture>
where TFuture: Future {
    /// Waiting for the queue to start running the future
    WaitingForQueue(oneshot::Receiver<()>, TFn),

    /// Evaluating an active future for its result
    WaitingForFuture(TFuture),

    /// The sync future has completed and now we're waiting for the scheduler to complete
    WaitingForScheduler(Box<TFuture::Output>),

    /// Finished evaluating
    Completed
}

///
/// Represents a future that runs synchronously with a queue
///
/// The future is only run in an exclusive time slot within the queue - this property is used to guarantee the
/// safety of `Desync::future_sync`, which provides exclusive access to the data store while the future is running.
/// The queue is allowed to continue once the returned future has completed.
///
pub struct SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    /// The state of this future
    state: SyncFutureState<TFn, TFuture>,

    /// Tracks this future on the scheduler (this allows polling this future to invoke desync's thread-stealing semantics instead of leaving the queue scheduling to a separate thread)
    scheduler_future: SchedulerFuture<()>,

    /// Signals when the future has finished running (None if this future is completed)
    task_finished: Option<oneshot::Sender<()>>
}

impl<TFn, TFuture> SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    ///
    /// Creates a new SyncFuture
    ///
    pub fn new(create_future: TFn, scheduler_future: SchedulerFuture<()>, queue_ready: oneshot::Receiver<()>, task_finished: oneshot::Sender<()>) -> SyncFuture<TFn, TFuture> {
        SyncFuture {
            state:              SyncFutureState::WaitingForQueue(queue_ready, create_future),
            scheduler_future:   scheduler_future,
            task_finished:      Some(task_finished)
        }
    }
}

impl<TFn, TFuture> Future for SyncFuture<TFn, TFuture>
where   TFn:                Unpin+Send+FnOnce() -> TFuture,
        TFuture:            Unpin+Send+Future,
        TFuture::Output:    Send {
    type Output = Result<TFuture::Output, oneshot::Canceled>;

    fn poll(mut self: Pin<&mut Self>, context: &mut task::Context) -> Poll<Self::Output> {
        use self::SyncFutureState::*;

        // Rust doesn't seem to have a way to let us update the state in-place, so we need to swap out the old state and swap in the new state
        let result;
        let mut state = Completed;
        mem::swap(&mut state, &mut self.state);

        // Update the state now we own it
        state = match state {
            WaitingForQueue(mut recv, create_future) => {
                // Check the scheduler future (give it a chance to steal the thread)
                if let Poll::Ready(Err(_)) = self.scheduler_future.poll_unpin(context) {
                    // The queue will never get to the point of polling this future
                    result = Poll::Ready(Err(oneshot::Canceled));
                    self.task_finished.take().map(|finished| finished.send(()));
                    Completed
                } else {
                    // Poll the receiver
                    match recv.poll_unpin(context) {
                        Poll::Ready(Ok(())) => {
                            // Start the future
                            let mut future = create_future();

                            // Poll it immediately to determine its status
                            if let Poll::Ready(future_result) = future.poll_unpin(context) {
                                // Future has completed
                                result = Poll::Pending;
                                self.task_finished.take().map(|finished| finished.send(()));
                                WaitingForScheduler(Box::new(future_result))
                            } else {
                                // Future is still running
                                result = Poll::Pending;
                                WaitingForFuture(future)
                            }
                        }

                        Poll::Ready(Err(_)) => {
                            // Future never became ready
                            result = Poll::Ready(Err(oneshot::Canceled));
                            Completed
                        }

                        Poll::Pending => {
                            // Waiting for the queue to start this future
                            result = Poll::Pending;
                            WaitingForQueue(recv, create_future)
                        }
                    }
                }
            }

            WaitingForFuture(mut future) => {
                if let Poll::Ready(future_result) = future.poll_unpin(context) {
                    // Future has completed
                    result = Poll::Pending;
                    self.task_finished.take().map(|finished| finished.send(()));
                    WaitingForScheduler(Box::new(future_result))
                } else {
                    // Future is still running
                    result = Poll::Pending;
                    WaitingForFuture(future)
                }
            }

            WaitingForScheduler(future_result) => {
                // Poll until the scheduler has finished running the task entirely (can deadlock while draining if we don't)
                if let Poll::Ready(_) = self.scheduler_future.poll_unpin(context) {
                    result = Poll::Ready(Ok(*future_result));
                    Completed
                } else {
                    result = Poll::Pending;
                    WaitingForScheduler(future_result)
                }
            }

            Completed => {
                // Polling after the result has been returned
                result = Poll::Ready(Err(oneshot::Canceled));
                Completed
            }
        };

        // Swap the state back into the structure
        self.state = state;

        result
    }
}
<|endoftext|>


<commit_before>mod ack;
mod blocked;
mod connection_close;
mod goaway;
mod padding;
mod ping;
mod rst_stream;
mod stop_waiting;
mod stream;
mod window_update;
<commit_msg>Add generic Frame encoding/decoding tests<commit_after>mod ack;
mod blocked;
mod connection_close;
mod goaway;
mod padding;
mod ping;
mod rst_stream;
mod stop_waiting;
mod stream;
mod window_update;

use std::io;

use quic::errors::Error;
use quic::frames;

#[test]
fn test_encoding() {
    let mut write = io::Cursor::new(Vec::new());

    let frame = frames::Frame::Ack(
        frames::ack::AckFrame {
            largest_acknowledged: 42,
            ack_delay: 32,

            first_ack_block_length: 64,
            extra_ack_blocks: Vec::new(),

            first_timestamp: None,
            extra_timestamps: Vec::new(),
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Blocked(
        frames::blocked::BlockedFrame { stream_id: 42 }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::ConnectionClose(
        frames::connection_close::ConnectionCloseFrame {
            error_code: 42,
            reason_phrase: None,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::GoAway(
        frames::goaway::GoAwayFrame {
            error_code: 42,
            last_good_stream_id: 32,
            reason_phrase: None,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Padding(
        frames::padding::PaddingFrame {}
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Ping(
        frames::ping::PingFrame {}
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::RstStream(
        frames::rst_stream::RstStreamFrame {
            error_code: 42,
            stream_id: 32,
            final_offset: 64,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::StopWaiting(
        frames::stop_waiting::StopWaitingFrame {
            least_acked_delta: 0x00001042DEADCAFE,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::Stream(
        frames::stream::StreamFrame {
            stream_id: 42,
            offset: 32,
            stream_data: vec![0x68, 0x65, 0x6C, 0x6C, 0x6F],
            fin: false,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    let frame = frames::Frame::WindowUpdate(
        frames::window_update::WindowUpdateFrame {
            stream_id: 42,
            byte_offset: 32,
        }
    );
    frame.encode(&mut write, 6, false).unwrap();

    assert_eq!(
        write.into_inner(),
        vec![
            // ack frame
            0x4F,
            0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x2A,
            0x00, 0x20,

            0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // blocked frame
            0x05,
            0x00, 0x00, 0x00, 0x2A,

            // connection close frame
            0x02,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00,

            // goaway frame
            0x03,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00,

            // padding frame
            0x00,

            // ping frame
            0x07,

            // rst stream frame
            0x01,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // stop waiting frame
            0x06,
            0x10, 0x42, 0xDE, 0xAD, 0xCA, 0xFE,

            // stream frame
            0xBF,
            0x00, 0x05,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
            0x68, 0x65, 0x6C, 0x6C, 0x6F,

            // window update frame
            0x04,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
        ]
    );
}

#[test]
fn test_decoding() {
    let mut read = io::Cursor::new(
        vec![
            // ack frame
            0x4F,
            0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x2A,
            0x00, 0x20,

            0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // blocked frame
            0x05,
            0x00, 0x00, 0x00, 0x2A,

            // connection close frame
            0x02,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00,

            // goaway frame
            0x03,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00,

            // padding frame
            0x00,

            // ping frame
            0x07,

            // rst stream frame
            0x01,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x20,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,

            // stop waiting frame
            0x06,
            0x10, 0x42, 0xDE, 0xAD, 0xCA, 0xFE,

            // stream frame
            0xBF,
            0x00, 0x05,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
            0x68, 0x65, 0x6C, 0x6C, 0x6F,

            // window update frame
            0x04,
            0x00, 0x00, 0x00, 0x2A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
        ]
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Ack(
            frames::ack::AckFrame {
                largest_acknowledged: 42,
                ack_delay: 32,

                first_ack_block_length: 64,
                extra_ack_blocks: Vec::new(),

                first_timestamp: None,
                extra_timestamps: Vec::new(),
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Blocked(
            frames::blocked::BlockedFrame { stream_id: 42 }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::ConnectionClose(
            frames::connection_close::ConnectionCloseFrame {
                error_code: 42,
                reason_phrase: None,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::GoAway(
            frames::goaway::GoAwayFrame {
                error_code: 42,
                last_good_stream_id: 32,
                reason_phrase: None,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Padding(
            frames::padding::PaddingFrame {}
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Ping(
            frames::ping::PingFrame {}
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::RstStream(
            frames::rst_stream::RstStreamFrame {
                error_code: 42,
                stream_id: 32,
                final_offset: 64,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::StopWaiting(
            frames::stop_waiting::StopWaitingFrame {
                least_acked_delta: 0x00001042DEADCAFE,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::Stream(
            frames::stream::StreamFrame {
                stream_id: 42,
                offset: 32,
                stream_data: vec![0x68, 0x65, 0x6C, 0x6C, 0x6F],
                fin: false,
            }
        )
    );

    let frame = frames::Frame::decode(&mut read, 6).unwrap();
    assert_eq!(
        frame,
        frames::Frame::WindowUpdate(
            frames::window_update::WindowUpdateFrame {
                stream_id: 42,
                byte_offset: 32,
            }
        )
    );

    match frames::Frame::decode(&mut read, 6) {
        Err(Error::Decoding(_)) => {},
        _ => assert!(false, "Error expected"),
    };
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{Result, Write};
use std::process::{Child, ChildStdin, Command, Stdio};
use std::str;
use tree_sitter::Parser;

pub(crate) struct LogSession(Child, ChildStdin);

pub(crate) fn start_logging_graphs(parser: &mut Parser, path: &str) -> Result<LogSession> {
    let mut dot_file = File::create(path)?;
    dot_file.write(b"<!DOCTYPE html>\n<style>svg { width: 100%; }</style>\n\n")?;
    let mut dot_process = Command::new("dot")
        .arg("-Tsvg")
        .stdin(Stdio::piped())
        .stdout(dot_file)
        .spawn()
        .expect("Failed to run Dot");
    let dot_stdin = dot_process
        .stdin
        .take()
        .expect("Failed to open stdin for Dot");
    parser.print_dot_graphs(&dot_stdin);
    Ok(LogSession(dot_process, dot_stdin))
}

pub(crate) fn stop_logging_graphs(parser: &mut Parser, mut session: LogSession) -> Result<()> {
    drop(session.1);
    parser.stop_printing_dot_graphs();
    session.0.wait()?;

    if cfg!(target_os = "macos") {
        Command::new("open").arg("log.html").output()?;
    }

    Ok(())
}
<commit_msg>Avoid using unix-specific methods on windows<commit_after>use std::fs::File;
use std::io::{Result, Write};
use std::process::{Child, ChildStdin, Command, Stdio};
use std::str;
use tree_sitter::Parser;

#[cfg(windows)]
pub(crate) struct LogSession();

#[cfg(windows)]
pub(crate) fn start_logging_graphs(parser: &mut Parser, path: &str) -> Result<LogSession> {
    Ok(LogSession())
}

#[cfg(windows)]
pub(crate) fn stop_logging_graphs(parser: &mut Parser, mut session: LogSession) -> Result<()> {
    Ok(())
}

#[cfg(unix)]
pub(crate) struct LogSession(Child, ChildStdin);

#[cfg(unix)]
pub(crate) fn start_logging_graphs(parser: &mut Parser, path: &str) -> Result<LogSession> {
    let mut dot_file = File::create(path)?;
    dot_file.write(b"<!DOCTYPE html>\n<style>svg { width: 100%; }</style>\n\n")?;
    let mut dot_process = Command::new("dot")
        .arg("-Tsvg")
        .stdin(Stdio::piped())
        .stdout(dot_file)
        .spawn()
        .expect("Failed to run Dot");
    let dot_stdin = dot_process
        .stdin
        .take()
        .expect("Failed to open stdin for Dot");

    parser.print_dot_graphs(&dot_stdin);

    Ok(LogSession(dot_process, dot_stdin))
}

#[cfg(unix)]
pub(crate) fn stop_logging_graphs(parser: &mut Parser, mut session: LogSession) -> Result<()> {
    drop(session.1);

    if cfg!(unix) {
        parser.stop_printing_dot_graphs();
    }

    session.0.wait()?;

    if cfg!(target_os = "macos") {
        Command::new("open").arg("log.html").output()?;
    }

    Ok(())
}
<|endoftext|>