<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//  based on:
//  http://shootout.alioth.debian.org/
//   u64q/program.php?test=mandelbrot&lang=python3&id=2
//
//  takes 2 optional args:
//   square image size, defaults to 80_u
//   output path, default is "" (no output), "-" means stdout
//
//  in the shootout, they use 16000 as image size
//
//  writes pbm image to output path

extern mod std;
use io::WriterUtil;
use std::map::HashMap;

struct cmplx {
    re: f64,
    im: f64
}

impl cmplx : ops::Mul<cmplx,cmplx> {
    pure fn mul(&self, x: &cmplx) -> cmplx {
        cmplx {
            re: self.re*(*x).re - self.im*(*x).im,
            im: self.re*(*x).im + self.im*(*x).re
        }
    }
}

impl cmplx : ops::Add<cmplx,cmplx> {
    pure fn add(&self, x: &cmplx) -> cmplx {
        cmplx {
            re: self.re + (*x).re,
            im: self.im + (*x).im
        }
    }
}

struct Line {i: uint, b: ~[u8]}

pure fn cabs(x: cmplx) -> f64
{
    x.re*x.re + x.im*x.im
}

fn mb(x: cmplx) -> bool
{
    let mut z = cmplx {re: 0f64, im: 0f64};
    let mut i = 0;
    let mut in = true;
    while i < 50 {
        z = z*z + x;
        if cabs(z) >= 4f64 {
            in = false;
            break;
        }
        i += 1;
    }
    in
}

fn fillbyte(x: cmplx, incr: f64) -> u8 {
    let mut rv = 0_u8;
    let mut i = 0_u8;
    while i < 8_u8 {
        let z = cmplx {re: x.re + (i as f64)*incr, im: x.im};
        if mb(z) {
            rv += 1_u8 << (7_u8 - i);
        }
        i += 1_u8;
    }
    rv
}

fn chanmb(i: uint, size: uint, ch: oldcomm::Chan<Line>) -> ()
{
    let mut crv = ~[];
    let incr = 2f64/(size as f64);
    let y = incr*(i as f64) - 1f64;
    let xincr = 8f64*incr;
    for uint::range(0_u, size/8_u) |j| {
        let x = cmplx {re: xincr*(j as f64) - 1.5f64, im: y};
        crv.push(fillbyte(x, incr));
    };
    oldcomm::send(ch, Line {i:i, b: move crv});
}

type devnull = {dn: int};

impl devnull: io::Writer {
    fn write(_b: &[const u8]) {}
    fn seek(_i: int, _s: io::SeekStyle) {}
    fn tell() -> uint {0_u}
    fn flush() -> int {0}
    fn get_type() -> io::WriterType { io::File }
}

fn writer(path: ~str, writech: oldcomm::Chan<oldcomm::Chan<Line>>, size: uint)
{
    let p: oldcomm::Port<Line> = oldcomm::Port();
    let ch = oldcomm::Chan(&p);
    oldcomm::send(writech, ch);
    let cout: io::Writer = match path {
        ~"" => {
            {dn: 0} as io::Writer
        }
        ~"-" => {
            io::stdout()
        }
        _ => {
            result::get(
                &io::file_writer(&Path(path),
                ~[io::Create, io::Truncate]))
        }
    };
    cout.write_line(~"P4");
    cout.write_line(fmt!("%u %u", size, size));
    let lines: HashMap<uint, ~[u8]> = HashMap();
    let mut done = 0_u;
    let mut i = 0_u;
    while i < size {
        let aline = oldcomm::recv(p);
        if aline.i == done {
            debug!("W %u", aline.i);
            cout.write(aline.b);
            done += 1_u;
            let mut prev = done;
            while prev <= i {
                if lines.contains_key(prev) {
                    debug!("WS %u", prev);
                    cout.write(lines.get(prev));
                    done += 1_u;
                    lines.remove(prev);
                    prev += 1_u;
                }
                else {
                    break
                }
            };
        }
        else {
            debug!("S %u", aline.i);
            lines.insert(aline.i, copy aline.b);    // FIXME: bad for perf
        };
        i += 1_u;
    }
}

fn main() {
    let args = os::args();
    let args = if os::getenv(~"RUST_BENCH").is_some() {
        ~[~"", ~"4000"]
    } else {
        args
    };

    let path = if vec::len(args) < 3_u { ~"" }
    else { copy args[2] };  // FIXME: bad for perf

    let size = if vec::len(args) < 2_u { 80_u }
    else { uint::from_str(args[1]).get() };

    let writep = oldcomm::Port();
    let writech = oldcomm::Chan(&writep);
    do task::spawn |move path| {
        writer(copy path, writech, size);
    };
    let ch = oldcomm::recv(writep);
    for uint::range(0_u, size) |j| {
        do task::spawn { chanmb(j, size, ch) };
    };
}
<commit_msg>Update shootout-mandelbrot to work with the new io::Writer<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//  based on:
//  http://shootout.alioth.debian.org/
//   u64q/program.php?test=mandelbrot&lang=python3&id=2
//
//  takes 2 optional args:
//   square image size, defaults to 80_u
//   output path, default is "" (no output), "-" means stdout
//
//  in the shootout, they use 16000 as image size
//
//  writes pbm image to output path

extern mod std;
use io::WriterUtil;
use std::map::HashMap;

struct cmplx {
    re: f64,
    im: f64
}

impl cmplx : ops::Mul<cmplx,cmplx> {
    pure fn mul(&self, x: &cmplx) -> cmplx {
        cmplx {
            re: self.re*(*x).re - self.im*(*x).im,
            im: self.re*(*x).im + self.im*(*x).re
        }
    }
}

impl cmplx : ops::Add<cmplx,cmplx> {
    pure fn add(&self, x: &cmplx) -> cmplx {
        cmplx {
            re: self.re + (*x).re,
            im: self.im + (*x).im
        }
    }
}

struct Line {i: uint, b: ~[u8]}

pure fn cabs(x: cmplx) -> f64
{
    x.re*x.re + x.im*x.im
}

fn mb(x: cmplx) -> bool
{
    let mut z = cmplx {re: 0f64, im: 0f64};
    let mut i = 0;
    let mut in = true;
    while i < 50 {
        z = z*z + x;
        if cabs(z) >= 4f64 {
            in = false;
            break;
        }
        i += 1;
    }
    in
}

fn fillbyte(x: cmplx, incr: f64) -> u8 {
    let mut rv = 0_u8;
    let mut i = 0_u8;
    while i < 8_u8 {
        let z = cmplx {re: x.re + (i as f64)*incr, im: x.im};
        if mb(z) {
            rv += 1_u8 << (7_u8 - i);
        }
        i += 1_u8;
    }
    rv
}

fn chanmb(i: uint, size: uint, ch: oldcomm::Chan<Line>) -> ()
{
    let mut crv = ~[];
    let incr = 2f64/(size as f64);
    let y = incr*(i as f64) - 1f64;
    let xincr = 8f64*incr;
    for uint::range(0_u, size/8_u) |j| {
        let x = cmplx {re: xincr*(j as f64) - 1.5f64, im: y};
        crv.push(fillbyte(x, incr));
    };
    oldcomm::send(ch, Line {i:i, b: move crv});
}

type devnull = {dn: int};

impl devnull: io::Writer {
    fn write(&self, _b: &[const u8]) {}
    fn seek(&self, _i: int, _s: io::SeekStyle) {}
    fn tell(&self) -> uint {0_u}
    fn flush(&self) -> int {0}
    fn get_type(&self) -> io::WriterType { io::File }
}

fn writer(path: ~str, writech: oldcomm::Chan<oldcomm::Chan<Line>>, size: uint)
{
    let p: oldcomm::Port<Line> = oldcomm::Port();
    let ch = oldcomm::Chan(&p);
    oldcomm::send(writech, ch);
    let cout: io::Writer = match path {
        ~"" => {
            {dn: 0} as io::Writer
        }
        ~"-" => {
            io::stdout()
        }
        _ => {
            result::get(
                &io::file_writer(&Path(path),
                ~[io::Create, io::Truncate]))
        }
    };
    cout.write_line(~"P4");
    cout.write_line(fmt!("%u %u", size, size));
    let lines: HashMap<uint, ~[u8]> = HashMap();
    let mut done = 0_u;
    let mut i = 0_u;
    while i < size {
        let aline = oldcomm::recv(p);
        if aline.i == done {
            debug!("W %u", aline.i);
            cout.write(aline.b);
            done += 1_u;
            let mut prev = done;
            while prev <= i {
                if lines.contains_key(prev) {
                    debug!("WS %u", prev);
                    cout.write(lines.get(prev));
                    done += 1_u;
                    lines.remove(prev);
                    prev += 1_u;
                }
                else {
                    break
                }
            };
        }
        else {
            debug!("S %u", aline.i);
            lines.insert(aline.i, copy aline.b);    // FIXME: bad for perf
        };
        i += 1_u;
    }
}

fn main() {
    let args = os::args();
    let args = if os::getenv(~"RUST_BENCH").is_some() {
        ~[~"", ~"4000"]
    } else {
        args
    };

    let path = if vec::len(args) < 3_u { ~"" }
    else { copy args[2] };  // FIXME: bad for perf

    let size = if vec::len(args) < 2_u { 80_u }
    else { uint::from_str(args[1]).get() };

    let writep = oldcomm::Port();
    let writech = oldcomm::Chan(&writep);
    do task::spawn |move path| {
        writer(copy path, writech, size);
    };
    let ch = oldcomm::recv(writep);
    for uint::range(0_u, size) |j| {
        do task::spawn { chanmb(j, size, ch) };
    };
}
<|endoftext|>


<commit_before>// aux-build:arc_wake.rs
// edition:2018
// run-pass

#![allow(unused_variables)]
#![feature(async_await)]

// Test that the drop order for parameters in a fn and async fn matches up. Also test that
// parameters (used or unused) are not dropped until the async fn is cancelled.
// This file is mostly copy-pasted from drop-order-for-async-fn-parameters.rs

extern crate arc_wake;

use arc_wake::ArcWake;
use std::cell::RefCell;
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;
use std::task::{Context, Poll};

struct EmptyWaker;

impl ArcWake for EmptyWaker {
    fn wake(self: Arc<Self>) {}
}

#[derive(Debug, Eq, PartialEq)]
enum DropOrder {
    Function,
    Val(&'static str),
}

type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;

struct D(&'static str, DropOrderListPtr);

impl Drop for D {
    fn drop(&mut self) {
        self.1.borrow_mut().push(DropOrder::Val(self.0));
    }
}

struct NeverReady;

impl Future for NeverReady {
    type Output = ();
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        Poll::Pending
    }
}

/// Check that unused bindings are dropped after the function is polled.
async fn foo_async(x: D, _y: D) {
    x.1.borrow_mut().push(DropOrder::Function);
    NeverReady.await;
}

fn foo_sync(x: D, _y: D) {
    x.1.borrow_mut().push(DropOrder::Function);
}

/// Check that underscore patterns are dropped after the function is polled.
async fn bar_async(x: D, _: D) {
    x.1.borrow_mut().push(DropOrder::Function);
    NeverReady.await;
}

fn bar_sync(x: D, _: D) {
    x.1.borrow_mut().push(DropOrder::Function);
}

/// Check that underscore patterns within more complex patterns are dropped after the function
/// is polled.
async fn baz_async((x, _): (D, D)) {
    x.1.borrow_mut().push(DropOrder::Function);
    NeverReady.await;
}

fn baz_sync((x, _): (D, D)) {
    x.1.borrow_mut().push(DropOrder::Function);
}

/// Check that underscore and unused bindings within and outwith more complex patterns are dropped
/// after the function is polled.
async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
    x.1.borrow_mut().push(DropOrder::Function);
    NeverReady.await;
}

fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
    x.1.borrow_mut().push(DropOrder::Function);
}

struct Foo;

impl Foo {
    /// Check that unused bindings are dropped after the method is polled.
    async fn foo_async(x: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn foo_sync(x: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore patterns are dropped after the method is polled.
    async fn bar_async(x: D, _: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn bar_sync(x: D, _: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore patterns within more complex patterns are dropped after the method
    /// is polled.
    async fn baz_async((x, _): (D, D)) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn baz_sync((x, _): (D, D)) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore and unused bindings within and outwith more complex patterns are
    /// dropped after the method is polled.
    async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }
}

struct Bar<'a>(PhantomData<&'a ()>);

impl<'a> Bar<'a> {
    /// Check that unused bindings are dropped after the method with self is polled.
    async fn foo_async(&'a self, x: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn foo_sync(&'a self, x: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore patterns are dropped after the method with self is polled.
    async fn bar_async(&'a self, x: D, _: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn bar_sync(&'a self, x: D, _: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore patterns within more complex patterns are dropped after the method
    /// with self is polled.
    async fn baz_async(&'a self, (x, _): (D, D)) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn baz_sync(&'a self, (x, _): (D, D)) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore and unused bindings within and outwith more complex patterns are
    /// dropped after the method with self is polled.
    async fn foobar_async(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn foobar_sync(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }
}

fn assert_drop_order_after_cancel<Fut: Future<Output = ()>>(
    f: impl FnOnce(DropOrderListPtr) -> Fut,
    g: impl FnOnce(DropOrderListPtr),
) {
    let empty = Arc::new(EmptyWaker);
    let waker = ArcWake::into_waker(empty);
    let mut cx = Context::from_waker(&waker);

    let actual_order = Rc::new(RefCell::new(Vec::new()));
    let mut fut = Box::pin(f(actual_order.clone()));
    let _ = fut.as_mut().poll(&mut cx);

    // Parameters are never dropped until the future completes.
    assert_eq!(*actual_order.borrow(), vec![DropOrder::Function]);

    drop(fut);

    let expected_order = Rc::new(RefCell::new(Vec::new()));
    g(expected_order.clone());
    assert_eq!(*actual_order.borrow(), *expected_order.borrow());
}

fn main() {
    // Free functions (see doc comment on function for what it tests).
    assert_drop_order_after_cancel(
        |l| foo_async(D("x", l.clone()), D("_y", l.clone())),
        |l| foo_sync(D("x", l.clone()), D("_y", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| bar_async(D("x", l.clone()), D("_", l.clone())),
        |l| bar_sync(D("x", l.clone()), D("_", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| baz_async((D("x", l.clone()), D("_", l.clone()))),
        |l| baz_sync((D("x", l.clone()), D("_", l.clone()))),
    );
    assert_drop_order_after_cancel(
        |l| {
            foobar_async(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
        |l| {
            foobar_sync(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
    );

    // Methods w/out self (see doc comment on function for what it tests).
    assert_drop_order_after_cancel(
        |l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())),
        |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())),
        |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))),
        |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))),
    );
    assert_drop_order_after_cancel(
        |l| {
            Foo::foobar_async(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
        |l| {
            Foo::foobar_sync(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
    );

    // Methods (see doc comment on function for what it tests).
    let b = Bar(Default::default());
    assert_drop_order_after_cancel(
        |l| b.foo_async(D("x", l.clone()), D("_y", l.clone())),
        |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| b.bar_async(D("x", l.clone()), D("_", l.clone())),
        |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| b.baz_async((D("x", l.clone()), D("_", l.clone()))),
        |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))),
    );
    assert_drop_order_after_cancel(
        |l| {
            b.foobar_async(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
        |l| {
            b.foobar_sync(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
    );
}
<commit_msg>fixup! test drop order for parameters when a future is dropped part-way through execution<commit_after>// aux-build:arc_wake.rs
// edition:2018
// run-pass

#![allow(unused_variables)]
#![feature(async_await)]

// Test that the drop order for parameters in a fn and async fn matches up. Also test that
// parameters (used or unused) are not dropped until the async fn is cancelled.
// This file is mostly copy-pasted from drop-order-for-async-fn-parameters.rs

extern crate arc_wake;

use arc_wake::ArcWake;
use std::cell::RefCell;
use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;
use std::task::{Context, Poll};

struct EmptyWaker;

impl ArcWake for EmptyWaker {
    fn wake(self: Arc<Self>) {}
}

#[derive(Debug, Eq, PartialEq)]
enum DropOrder {
    Function,
    Val(&'static str),
}

type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;

struct D(&'static str, DropOrderListPtr);

impl Drop for D {
    fn drop(&mut self) {
        self.1.borrow_mut().push(DropOrder::Val(self.0));
    }
}

struct NeverReady;

impl Future for NeverReady {
    type Output = ();
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        Poll::Pending
    }
}

/// Check that unused bindings are dropped after the function is polled.
async fn foo_async(x: D, _y: D) {
    x.1.borrow_mut().push(DropOrder::Function);
    NeverReady.await;
}

fn foo_sync(x: D, _y: D) {
    x.1.borrow_mut().push(DropOrder::Function);
}

/// Check that underscore patterns are dropped after the function is polled.
async fn bar_async(x: D, _: D) {
    x.1.borrow_mut().push(DropOrder::Function);
    NeverReady.await;
}

fn bar_sync(x: D, _: D) {
    x.1.borrow_mut().push(DropOrder::Function);
}

/// Check that underscore patterns within more complex patterns are dropped after the function
/// is polled.
async fn baz_async((x, _): (D, D)) {
    x.1.borrow_mut().push(DropOrder::Function);
    NeverReady.await;
}

fn baz_sync((x, _): (D, D)) {
    x.1.borrow_mut().push(DropOrder::Function);
}

/// Check that underscore and unused bindings within and outwith more complex patterns are dropped
/// after the function is polled.
async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
    x.1.borrow_mut().push(DropOrder::Function);
    NeverReady.await;
}

fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
    x.1.borrow_mut().push(DropOrder::Function);
}

struct Foo;

impl Foo {
    /// Check that unused bindings are dropped after the method is polled.
    async fn foo_async(x: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn foo_sync(x: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore patterns are dropped after the method is polled.
    async fn bar_async(x: D, _: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn bar_sync(x: D, _: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore patterns within more complex patterns are dropped after the method
    /// is polled.
    async fn baz_async((x, _): (D, D)) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn baz_sync((x, _): (D, D)) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore and unused bindings within and outwith more complex patterns are
    /// dropped after the method is polled.
    async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }
}

struct Bar<'a>(PhantomData<&'a ()>);

impl<'a> Bar<'a> {
    /// Check that unused bindings are dropped after the method with self is polled.
    async fn foo_async(&'a self, x: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn foo_sync(&'a self, x: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore patterns are dropped after the method with self is polled.
    async fn bar_async(&'a self, x: D, _: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn bar_sync(&'a self, x: D, _: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore patterns within more complex patterns are dropped after the method
    /// with self is polled.
    async fn baz_async(&'a self, (x, _): (D, D)) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn baz_sync(&'a self, (x, _): (D, D)) {
        x.1.borrow_mut().push(DropOrder::Function);
    }

    /// Check that underscore and unused bindings within and outwith more complex patterns are
    /// dropped after the method with self is polled.
    async fn foobar_async(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
        NeverReady.await;
    }

    fn foobar_sync(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
        x.1.borrow_mut().push(DropOrder::Function);
    }
}

fn assert_drop_order_after_cancel<Fut: Future<Output = ()>>(
    f: impl FnOnce(DropOrderListPtr) -> Fut,
    g: impl FnOnce(DropOrderListPtr),
) {
    let empty = Arc::new(EmptyWaker);
    let waker = ArcWake::into_waker(empty);
    let mut cx = Context::from_waker(&waker);

    let actual_order = Rc::new(RefCell::new(Vec::new()));
    let mut fut = Box::pin(f(actual_order.clone()));
    let _ = fut.as_mut().poll(&mut cx);

    // Parameters are never dropped until the future completes.
    assert_eq!(*actual_order.borrow(), vec![DropOrder::Function]);

    drop(fut);

    let expected_order = Rc::new(RefCell::new(Vec::new()));
    g(expected_order.clone());
    assert_eq!(*actual_order.borrow(), *expected_order.borrow());
}

fn main() {
    // Free functions (see doc comment on function for what it tests).
    assert_drop_order_after_cancel(
        |l| foo_async(D("x", l.clone()), D("_y", l.clone())),
        |l| foo_sync(D("x", l.clone()), D("_y", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| bar_async(D("x", l.clone()), D("_", l.clone())),
        |l| bar_sync(D("x", l.clone()), D("_", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| baz_async((D("x", l.clone()), D("_", l.clone()))),
        |l| baz_sync((D("x", l.clone()), D("_", l.clone()))),
    );
    assert_drop_order_after_cancel(
        |l| {
            foobar_async(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
        |l| {
            foobar_sync(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
    );

    // Methods w/out self (see doc comment on function for what it tests).
    assert_drop_order_after_cancel(
        |l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())),
        |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())),
        |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))),
        |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))),
    );
    assert_drop_order_after_cancel(
        |l| {
            Foo::foobar_async(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
        |l| {
            Foo::foobar_sync(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
    );

    // Methods (see doc comment on function for what it tests).
    let b = Bar(Default::default());
    assert_drop_order_after_cancel(
        |l| b.foo_async(D("x", l.clone()), D("_y", l.clone())),
        |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| b.bar_async(D("x", l.clone()), D("_", l.clone())),
        |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())),
    );
    assert_drop_order_after_cancel(
        |l| b.baz_async((D("x", l.clone()), D("_", l.clone()))),
        |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))),
    );
    assert_drop_order_after_cancel(
        |l| {
            b.foobar_async(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
        |l| {
            b.foobar_sync(
                D("x", l.clone()),
                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
                D("_", l.clone()),
                D("_y", l.clone()),
            )
        },
    );
}
<|endoftext|>


<commit_before>use std::result::Result;
use std::marker::PhantomData;
use std::error::Error;
use serde::*;
use serde_json::*;

use super::super::tool::*;
use super::super::environment::*;

///
/// Represents a tool made from a function
///
pub struct FnTool<TIn: Deserialize, TOut: Serialize, TErr: Serialize> {
    function: Box<Fn(TIn) -> Result<TOut, TErr>>
}

///
/// Creates a Tool from a function that can produce an error but does not use an environment
///
pub fn make_tool<TIn: Deserialize, TOut: Serialize, TErr: Serialize, F: 'static+Fn(TIn) -> Result<TOut, TErr>>(function: F) -> FnTool<TIn, TOut, TErr> {
    FnTool { function: Box::new(function) }
}

///
/// Creates a Tool from a function that cannot produce an error and doesn't use an environment
///
pub fn make_pure_tool<TIn: Deserialize, TOut: Serialize, F: 'static+Fn(TIn) -> TOut>(function: F) -> FnTool<TIn, TOut, ()> {
    make_tool(move |input| { Ok(function(input)) })
}

impl<TIn, TOut, TErr> Tool for FnTool<TIn, TOut, TErr>
where TIn: Deserialize, TOut: Serialize, TErr: Serialize {
    fn invoke_json(&self, input: Value, _environment: &Environment) -> Result<Value, Value> {
        // Decode
        let input_decoded = from_value::<TIn>(input);

        // Chain into the tool itself
        match input_decoded {
            Ok(input_decoded) => {
                // Successfully decoded as the tool's input format
                let result = (self.function)(input_decoded);

                // Encode the error or the result
                // The encoding can go wrong, and we need to handle it slightly differently for the error or the success case
                match result {
                    Ok(res) => {
                        let encoded = to_value(res);
                        match encoded {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "JSON encode failed",
                                "description":  erm.description()
                            }])
                        }
                    },

                    Err(erm) => {
                        let encoded = to_value(erm);
                        match encoded {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "Error encode failed",
                                "description":  erm.description()
                            }])
                        }
                    }
                }
            },

            Err(input_error) => {
                // Input does not match the format expected by the tool
                Err(json![{
                    "error":        "JSON input decode failed",
                    "description":  input_error.description(),
                }])
            }
        }
    }
}

///
/// Represents a tool with Rust types
///
pub struct TypedTool<'a, TIn: Serialize, TOut: Deserialize> {
    param1: PhantomData<TIn>,
    param2: PhantomData<TOut>,
    tool: &'a Tool
}

impl<'a, TIn: Serialize, TOut: Deserialize> TypedTool<'a, TIn, TOut> {
    ///
    /// Creates an object that can be used to invoke a tool with typed parameters instead of pure JSON
    ///
    pub fn from(tool: &'a Tool) -> TypedTool<'a, TIn, TOut> {
        TypedTool { param1: PhantomData, param2: PhantomData, tool: tool }
    }

    ///
    /// Invokes this tool
    ///
    pub fn invoke(&self, input: TIn, environment: &Environment) -> Result<TOut, Value> {
        let json_input = to_value(input);

        match json_input {
            Ok(json_input) => {
                let json_output = self.tool.invoke_json(json_input, environment);

                match json_output {
                    Ok(json_output) => {
                        let result = from_value::<TOut>(json_output);
                        match result {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "Result decode failed",
                                "description":  erm.description()
                            }])
                        }
                    },

                    Err(json_error) => {
                        Err(json_error)
                    }
                }
            },

            Err(erm) => {
                Err(json![{
                    "error":        "Input encode failed",
                    "description":  erm.description()
                }])
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::super::super::*;
    use super::super::*;
    use std::result::Result;
    use serde_json::*;              // Rust says unused, but the json! macro will not work without this

    #[derive(Serialize, Deserialize)]
    struct TestIn {
        input: i32
    }

    #[derive(Serialize, Deserialize, PartialEq, Eq)]
    struct TestOut {
        output: i32
    }

    fn test_tool(x: TestIn) -> Result<TestOut, ()> {
        Ok(TestOut { output: x.input + 1 })
    }

    #[test]
    fn can_call_tool_via_json_interface() {
        let tool        = make_tool(test_tool);
        let environment = EmptyEnvironment::new();
        let result      = tool.invoke_json(json![{ "input": 4 }], &environment);

        assert!(result == Ok(json![{ "output": 5 }]));
    }

    #[test]
    fn can_call_tool_via_typed_interface() {
        let tool        = make_pure_tool(|x: i32| { x+1 });
        let environment = EmptyEnvironment::new();

        let typed_tool  = TypedTool::from(&tool);
        let result      = typed_tool.invoke(4, &environment);

        assert!(result == Ok(5));
    }
}
<commit_msg>Add a new helper method that makes it possible to get a typed tool straight back from an environment<commit_after>use std::result::Result;
use std::marker::PhantomData;
use std::error::Error;
use serde::*;
use serde_json::*;

use super::super::tool::*;
use super::super::environment::*;

///
/// Represents a tool made from a function
///
pub struct FnTool<TIn: Deserialize, TOut: Serialize, TErr: Serialize> {
    function: Box<Fn(TIn) -> Result<TOut, TErr>>
}

///
/// Creates a Tool from a function that can produce an error but does not use an environment
///
pub fn make_tool<TIn: Deserialize, TOut: Serialize, TErr: Serialize, F: 'static+Fn(TIn) -> Result<TOut, TErr>>(function: F) -> FnTool<TIn, TOut, TErr> {
    FnTool { function: Box::new(function) }
}

///
/// Creates a Tool from a function that cannot produce an error and doesn't use an environment
///
pub fn make_pure_tool<TIn: Deserialize, TOut: Serialize, F: 'static+Fn(TIn) -> TOut>(function: F) -> FnTool<TIn, TOut, ()> {
    make_tool(move |input| { Ok(function(input)) })
}

impl<TIn, TOut, TErr> Tool for FnTool<TIn, TOut, TErr>
where TIn: Deserialize, TOut: Serialize, TErr: Serialize {
    fn invoke_json(&self, input: Value, _environment: &Environment) -> Result<Value, Value> {
        // Decode
        let input_decoded = from_value::<TIn>(input);

        // Chain into the tool itself
        match input_decoded {
            Ok(input_decoded) => {
                // Successfully decoded as the tool's input format
                let result = (self.function)(input_decoded);

                // Encode the error or the result
                // The encoding can go wrong, and we need to handle it slightly differently for the error or the success case
                match result {
                    Ok(res) => {
                        let encoded = to_value(res);
                        match encoded {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "JSON encode failed",
                                "description":  erm.description()
                            }])
                        }
                    },

                    Err(erm) => {
                        let encoded = to_value(erm);
                        match encoded {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "Error encode failed",
                                "description":  erm.description()
                            }])
                        }
                    }
                }
            },

            Err(input_error) => {
                // Input does not match the format expected by the tool
                Err(json![{
                    "error":        "JSON input decode failed",
                    "description":  input_error.description(),
                }])
            }
        }
    }
}

///
/// Represents a tool with Rust types
///
pub struct TypedTool<TIn: Serialize, TOut: Deserialize> {
    param1: PhantomData<TIn>,
    param2: PhantomData<TOut>,
    tool: Box<Tool>

    // tool could be &'a Tool and it would work as Box<Tool> implements Tool - except rust's deref behaviour
    // gets in the way: trying to pass a reference to a box actually passes a reference to the boxed thing, which
    // then doesn't work because the size is unknown
}

impl<TIn: Serialize, TOut: Deserialize> TypedTool<TIn, TOut> {
    ///
    /// Creates an object that can be used to invoke a tool with typed parameters instead of pure JSON
    ///
    pub fn from(tool: Box<Tool>) -> TypedTool<TIn, TOut> {
        TypedTool { param1: PhantomData, param2: PhantomData, tool: tool }
    }

    ///
    /// Invokes this tool
    ///
    pub fn invoke(&self, input: TIn, environment: &Environment) -> Result<TOut, Value> {
        let json_input = to_value(input);

        match json_input {
            Ok(json_input) => {
                let json_output = self.tool.invoke_json(json_input, environment);

                match json_output {
                    Ok(json_output) => {
                        let result = from_value::<TOut>(json_output);
                        match result {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "Result decode failed",
                                "description":  erm.description()
                            }])
                        }
                    },

                    Err(json_error) => {
                        Err(json_error)
                    }
                }
            },

            Err(erm) => {
                Err(json![{
                    "error":        "Input encode failed",
                    "description":  erm.description()
                }])
            }
        }
    }
}

///
/// Extension trait for environments that makes it possible to get a Rust typed tool immediately
///
pub trait TypedEnvironment {
    ///
    /// Retrieves a tool using a Rust interface by name
    ///
    fn get_typed_tool<'a, TIn: Serialize, TOut: Deserialize>(&self, name: &str) -> Result<TypedTool<TIn, TOut>, RetrieveToolError>;
}

impl<TEnv> TypedEnvironment for TEnv where TEnv: Environment {
    ///
    /// Retrieves a tool using a Rust interface by name
    ///
    fn get_typed_tool<'a, TIn: Serialize, TOut: Deserialize>(&self, name: &str) -> Result<TypedTool<TIn, TOut>, RetrieveToolError> {
        self.get_json_tool(name).map(|tool| TypedTool::from(tool))
    }
}

#[cfg(test)]
mod test {
    use super::super::super::*;
    use super::super::*;
    use std::result::Result;
    use serde_json::*;              // Rust says unused, but the json! macro will not work without this

    #[derive(Serialize, Deserialize)]
    struct TestIn {
        input: i32
    }

    #[derive(Serialize, Deserialize, PartialEq, Eq)]
    struct TestOut {
        output: i32
    }

    fn test_tool(x: TestIn) -> Result<TestOut, ()> {
        Ok(TestOut { output: x.input + 1 })
    }

    #[test]
    fn can_call_tool_via_json_interface() {
        let tool        = make_tool(test_tool);
        let environment = EmptyEnvironment::new();
        let result      = tool.invoke_json(json![{ "input": 4 }], &environment);

        assert!(result == Ok(json![{ "output": 5 }]));
    }

    #[test]
    fn can_call_tool_via_typed_interface() {
        let tool        = make_pure_tool(|x: i32| { x+1 });
        let environment = EmptyEnvironment::new();

        let typed_tool  = TypedTool::from(Box::new(tool));
        let result      = typed_tool.invoke(4, &environment);

        assert!(result == Ok(5));
    }
}
<|endoftext|>


<commit_before>extern crate syn;
extern crate quote;

use syn::{File as SynFile, Item, Ident, TraitItem, FnArg};
use quote::ToTokens;

use std::fs::File;
use std::env::args;
use std::io::Read;

fn main() {
  let path = args().nth(1).unwrap();
  let mut file = File::open(path).unwrap();
  let mut content = String::new();
  file.read_to_string(&mut content).unwrap();
  let file: SynFile = syn::parse_str(&content).unwrap();
  for item in file.items {
    let t = match item {
      Item::Trait(t) => t,
      _ => continue
    };
    if t.ident != Ident::from("EventHandler") {
      continue;
    }
    for item in t.items {
      let mut m = match item {
        TraitItem::Method(m) => m,
        _ => continue
      };
      if m.attrs.len() == 1 {
        // I'm sorry
        if m.attrs.remove(0).into_tokens().to_string() != "# [ cfg ( feature = \"cache\" ) ]" {
          continue;
        }
      }
      let method_ident = m.sig.ident;
      let method_args = m.sig.decl.inputs;
      print!("handler!({}, ", method_ident);
      let num_args = method_args.len();
      for (i, arg) in method_args.into_iter().enumerate() {
        match arg {
          FnArg::Captured(captured) => print!("param{}: {}", i, captured.ty.into_tokens()),
          _ => continue
        }
        if i != num_args - 1 {
          print!(", ");
        }
      }
      println!(");");
    }
  }
}
<commit_msg>fix: don't output non-cache handlers<commit_after>extern crate syn;
extern crate quote;

use syn::{File as SynFile, Item, Ident, TraitItem, FnArg};
use quote::ToTokens;

use std::fs::File;
use std::env::args;
use std::io::Read;

fn main() {
  let path = args().nth(1).unwrap();
  let mut file = File::open(path).unwrap();
  let mut content = String::new();
  file.read_to_string(&mut content).unwrap();
  let file: SynFile = syn::parse_str(&content).unwrap();
  for item in file.items {
    let t = match item {
      Item::Trait(t) => t,
      _ => continue
    };
    if t.ident != Ident::from("EventHandler") {
      continue;
    }
    'item: for item in t.items {
      let mut m = match item {
        TraitItem::Method(m) => m,
        _ => continue
      };
      if !m.attrs.is_empty() {
        // I'm sorry
        for attr in m.attrs {
          if attr.into_tokens().to_string() == r#"# [ cfg ( not ( feature = "cache" ) ) ]"# {
            continue 'item;
          }
        }
      }
      let method_ident = m.sig.ident;
      let method_args = m.sig.decl.inputs;
      print!("handler!({}, ", method_ident);
      let num_args = method_args.len();
      for (i, arg) in method_args.into_iter().enumerate() {
        match arg {
          FnArg::Captured(captured) => print!("param{}: {}", i, captured.ty.into_tokens()),
          _ => continue
        }
        if i != num_args - 1 {
          print!(", ");
        }
      }
      println!(");");
    }
  }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::net::ToSocketAddrs;
use std::thread;
use std::io;
use std::sync::Arc;
use std::sync::Mutex;

use futures;
use futures::Future;
use futures::stream::Stream;

use native_tls::TlsAcceptor;

use tokio_core;
use tokio_core::reactor;

//use tokio_tls;

use httpbis::solicit::HttpError;

use httpbis::for_test::*;

/// Single connection HTTP/server.
/// Accepts only one connection.
pub struct HttpServerOneConn {
    from_loop: FromLoop,
    join_handle: Option<thread::JoinHandle<()>>,
    shutdown_tx: Option<futures::Complete<()>>,
    conn: Arc<Mutex<Option<HttpServerConnectionAsync>>>,
}

struct FromLoop {
    port: u16,
}

impl HttpServerOneConn {
    pub fn new_fn<S>(port: u16, service: S) -> Self
        where S : Fn(Headers, HttpPartFutureStreamSend) -> HttpPartFutureStreamSend + Send + 'static
    {
        HttpServerOneConn::new_fn_impl(port, None, service)
    }

    pub fn new_tls_fn<S>(port: u16, server_context: TlsAcceptor, service: S) -> Self
        where S : Fn(Headers, HttpPartFutureStreamSend) -> HttpPartFutureStreamSend + Send + 'static
    {
        HttpServerOneConn::new_fn_impl(port, Some(server_context), service)
    }

    #[allow(dead_code)]
    fn new_fn_impl<S>(port: u16, server_context: Option<TlsAcceptor>, service: S) -> Self
        where S : Fn(Headers, HttpPartFutureStreamSend) -> HttpPartFutureStreamSend + Send + 'static
    {
        let (from_loop_tx, from_loop_rx) = futures::oneshot();
        let (shutdown_tx, shutdown_rx) = futures::oneshot::<()>();

        let conn: Arc<Mutex<Option<HttpServerConnectionAsync>>> = Default::default();

        let conn_for_thread = conn.clone();

        let join_handle = thread::spawn(move || {
            let mut lp = reactor::Core::new().unwrap();

            let listener = tokio_core::net::TcpListener::bind(&("::1", port).to_socket_addrs().unwrap().next().unwrap(), &lp.handle()).unwrap();

            let actual_port = listener.local_addr().unwrap().port();
            from_loop_tx.send(FromLoop {
                port: actual_port,
            }).ok().unwrap();

            let handle = lp.handle();

            let future = listener.incoming().into_future()
                .map_err(|_| HttpError::from(io::Error::new(io::ErrorKind::Other, "something")))
                .and_then(move |(conn, listener)| {
                    // incoming stream is endless
                    let (conn, _) = conn.unwrap();

                    // close listening port
                    drop(listener);

                    if let Some(_server_context) = server_context {
                        //HttpServerConnectionAsync::new_tls_fn(&handle, conn, server_context, service)
                        unimplemented!()
                    } else {
                        let (conn, future) = HttpServerConnectionAsync::new_plain_fn(
                            &handle, conn, Default::default(), service);
                        *conn_for_thread.lock().unwrap() = Some(conn);
                        future
                    }
                });

            let shutdown_rx = shutdown_rx.then(|_| futures::finished::<_, ()>(()));
            let future = future.then(|_| futures::finished::<_, ()>(()));

            lp.run(shutdown_rx.select(future)).ok();
        });

        HttpServerOneConn {
            from_loop: from_loop_rx.wait().unwrap(),
            join_handle: Some(join_handle),
            shutdown_tx: Some(shutdown_tx),
            conn: conn,
        }
    }
}

#[allow(dead_code)]
impl HttpServerOneConn {
    pub fn port(&self) -> u16 {
        self.from_loop.port
    }

    pub fn dump_state(&self) -> ConnectionStateSnapshot {
        let g = self.conn.lock().expect("lock");
        let conn = g.as_ref().expect("conn");
        conn.dump_state().wait().expect("dump_status")
    }
}

impl Drop for HttpServerOneConn {
    fn drop(&mut self) {
        self.shutdown_tx.take().unwrap().complete(());
        self.join_handle.take().unwrap().join().ok();
    }
}
<commit_msg>Warnings<commit_after>#![allow(dead_code)]

use std::net::ToSocketAddrs;
use std::thread;
use std::io;
use std::sync::Arc;
use std::sync::Mutex;

use futures;
use futures::Future;
use futures::stream::Stream;

use native_tls::TlsAcceptor;

use tokio_core;
use tokio_core::reactor;

//use tokio_tls;

use httpbis::solicit::HttpError;

use httpbis::for_test::*;

/// Single connection HTTP/server.
/// Accepts only one connection.
pub struct HttpServerOneConn {
    from_loop: FromLoop,
    join_handle: Option<thread::JoinHandle<()>>,
    shutdown_tx: Option<futures::Complete<()>>,
    conn: Arc<Mutex<Option<HttpServerConnectionAsync>>>,
}

struct FromLoop {
    port: u16,
}

impl HttpServerOneConn {
    pub fn new_fn<S>(port: u16, service: S) -> Self
        where S : Fn(Headers, HttpPartFutureStreamSend) -> HttpPartFutureStreamSend + Send + 'static
    {
        HttpServerOneConn::new_fn_impl(port, None, service)
    }

    pub fn new_tls_fn<S>(port: u16, server_context: TlsAcceptor, service: S) -> Self
        where S : Fn(Headers, HttpPartFutureStreamSend) -> HttpPartFutureStreamSend + Send + 'static
    {
        HttpServerOneConn::new_fn_impl(port, Some(server_context), service)
    }

    #[allow(dead_code)]
    fn new_fn_impl<S>(port: u16, server_context: Option<TlsAcceptor>, service: S) -> Self
        where S : Fn(Headers, HttpPartFutureStreamSend) -> HttpPartFutureStreamSend + Send + 'static
    {
        let (from_loop_tx, from_loop_rx) = futures::oneshot();
        let (shutdown_tx, shutdown_rx) = futures::oneshot::<()>();

        let conn: Arc<Mutex<Option<HttpServerConnectionAsync>>> = Default::default();

        let conn_for_thread = conn.clone();

        let join_handle = thread::spawn(move || {
            let mut lp = reactor::Core::new().unwrap();

            let listener = tokio_core::net::TcpListener::bind(&("::1", port).to_socket_addrs().unwrap().next().unwrap(), &lp.handle()).unwrap();

            let actual_port = listener.local_addr().unwrap().port();
            from_loop_tx.send(FromLoop {
                port: actual_port,
            }).ok().unwrap();

            let handle = lp.handle();

            let future = listener.incoming().into_future()
                .map_err(|_| HttpError::from(io::Error::new(io::ErrorKind::Other, "something")))
                .and_then(move |(conn, listener)| {
                    // incoming stream is endless
                    let (conn, _) = conn.unwrap();

                    // close listening port
                    drop(listener);

                    if let Some(_server_context) = server_context {
                        //HttpServerConnectionAsync::new_tls_fn(&handle, conn, server_context, service)
                        unimplemented!()
                    } else {
                        let (conn, future) = HttpServerConnectionAsync::new_plain_fn(
                            &handle, conn, Default::default(), service);
                        *conn_for_thread.lock().unwrap() = Some(conn);
                        future
                    }
                });

            let shutdown_rx = shutdown_rx.then(|_| futures::finished::<_, ()>(()));
            let future = future.then(|_| futures::finished::<_, ()>(()));

            lp.run(shutdown_rx.select(future)).ok();
        });

        HttpServerOneConn {
            from_loop: from_loop_rx.wait().unwrap(),
            join_handle: Some(join_handle),
            shutdown_tx: Some(shutdown_tx),
            conn: conn,
        }
    }
}

#[allow(dead_code)]
impl HttpServerOneConn {
    pub fn port(&self) -> u16 {
        self.from_loop.port
    }

    pub fn dump_state(&self) -> ConnectionStateSnapshot {
        let g = self.conn.lock().expect("lock");
        let conn = g.as_ref().expect("conn");
        conn.dump_state().wait().expect("dump_status")
    }
}

impl Drop for HttpServerOneConn {
    fn drop(&mut self) {
        drop(self.shutdown_tx.take().unwrap().send(()));
        self.join_handle.take().unwrap().join().ok();
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io;
use std::os::windows::fs::FileExt;

use super::LogOffset;

fn<F: FileExt> seek_read_exact(file: &mut F, mut buf: &mut[u8], mut offset: u64) -> io::Result<()> {
    while !buf.is_empty() {
        match file.seek_read(buf, offset) {
            Ok(0) => break,
            Ok(n) => {
                let tmp = buf;
                buf = &mut tmp[n..];
                offset += n;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                           "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}

fn<F: FileExt> seek_write_all(file: &mut F, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
    while !buf.is_empty() {
        match file.seek_write(buf, offset) {
            Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero,
                                               "failed to write whole buffer")),
            Ok(n) => {
                buf = &buf[n..];
                offset += n;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}

pub(crate) fn pread_exact(
    file: &File,
    buf: &mut [u8],
    offset: LogOffset,
) -> io::Result<()> {
    let mut f = file.try_clone()?;
    seek_read_exact(&mut f, buf, offset)
}

pub(crate) fn pwrite_all(
    file: &File,
    buf: &[u8],
    offset: LogOffset,
) -> io::Result<()> {
    let mut f = file.try_clone()?;
    seek_write_all(&mut f, buf, offset)
}
<commit_msg>Fix syntax, add casts<commit_after>use std::fs::File;
use std::io;
use std::os::windows::fs::FileExt;

use super::LogOffset;

fn seek_read_exact<F: FileExt>(file: &mut F, mut buf: &mut[u8], mut offset: u64) -> io::Result<()> {
    while !buf.is_empty() {
        match file.seek_read(buf, offset) {
            Ok(0) => break,
            Ok(n) => {
                let tmp = buf;
                buf = &mut tmp[n..];
                offset += n as u64;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                           "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}

fn seek_write_all<F: FileExt>(file: &mut F, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
    while !buf.is_empty() {
        match file.seek_write(buf, offset) {
            Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero,
                                               "failed to write whole buffer")),
            Ok(n) => {
                buf = &buf[n..];
                offset += n as u64;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}

pub(crate) fn pread_exact(
    file: &File,
    buf: &mut [u8],
    offset: LogOffset,
) -> io::Result<()> {
    let mut f = file.try_clone()?;
    seek_read_exact(&mut f, buf, offset)
}

pub(crate) fn pwrite_all(
    file: &File,
    buf: &[u8],
    offset: LogOffset,
) -> io::Result<()> {
    let mut f = file.try_clone()?;
    seek_write_all(&mut f, buf, offset)
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobRequireVariable {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_require_variable(conn: &Connection) {
    conn.execute(
        "CREATE TABLE JOB_REQUIRE_VARIABLE (
                  id                    INTEGER PRIMARY KEY ASC,
                  fk_job                INTEGER NOT NULL,
                  fk_variable           INTEGER NOT NULL,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES JOB_REQUIRE_VARIABLE(id) ON UPDATE CASCADE
                  )",
        &[],
    ).unwrap();
}

pub fn insert_job_require_variable(
    conn: &Connection,
    job: &i32,
    variable: &i32,
) -> Result<i32, &'static str> {
    let me = JobRequireVariable {
        id: 0,
        fk_job: *job,
        fk_variable: *variable,
    };
    let job_require_variable_instance = conn.execute(
        "INSERT INTO JOB_REQUIRE_VARIABLE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if job_require_variable_instance.is_err() {
        return Err("Insert failed");
    }
    job_require_variable_instance.unwrap();
    return Ok(0);
}

pub fn list_job_require_variable(conn: &Connection) -> Vec<JobRequireVariable> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    let mut items = Vec::<JobRequireVariable>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_require_variable_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found job_require_variable {:?}", person.unwrap());
    }
}

pub fn pk_job_require_variable_by_name(
    conn: &Connection,
    job: &i32,
    variable: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE WHERE fk_job = ?1 AND fk_variable = ?2").unwrap();
    let job_require_variable_iter = stmt.query_map(&[job, variable], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    if job_require_variable_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = job_require_variable_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>Remove unused variables<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobRequireVariable {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_require_variable(conn: &Connection) {
    conn.execute(
        "CREATE TABLE JOB_REQUIRE_VARIABLE (
                  id                    INTEGER PRIMARY KEY ASC,
                  fk_job                INTEGER NOT NULL,
                  fk_variable           INTEGER NOT NULL,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES JOB_REQUIRE_VARIABLE(id) ON UPDATE CASCADE
                  )",
        &[],
    ).unwrap();
}

pub fn insert_job_require_variable(
    conn: &Connection,
    job: &i32,
    variable: &i32,
) -> Result<i32, &'static str> {
    let me = JobRequireVariable {
        id: 0,
        fk_job: *job,
        fk_variable: *variable,
    };
    let job_require_variable_instance = conn.execute(
        "INSERT INTO JOB_REQUIRE_VARIABLE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if job_require_variable_instance.is_err() {
        return Err("Insert failed");
    }
    job_require_variable_instance.unwrap();
    return Ok(0);
}

pub fn list_job_require_variable(conn: &Connection) -> Vec<JobRequireVariable> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    let mut items = Vec::<JobRequireVariable>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_require_variable_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found job_require_variable {:?}", person.unwrap());
    }
}

pub fn pk_job_require_variable_by_name(
    conn: &Connection,
    job: &i32,
    variable: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE WHERE fk_job = ?1 AND fk_variable = ?2").unwrap();
    let job_require_variable_iter = stmt.query_map(&[job, variable], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    if job_require_variable_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = job_require_variable_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>use super::*;

pub struct PriceFilter {
    pub locale: String,
}

impl PriceFilter {
    fn currencies(&self) -> &'static str {
        "$¢£¤¥֏؋৲৳৻૱௹฿₠₡₢₣₤₥₦₧₨₩₪₫€₭₮₯₰₱₲₳₴₵₶₷₸₹₺₽﹩＄￠￡￥￦"
    }
}

impl LinterFilter for PriceFilter {
    fn locales(&self) -> Vec<&'static str> {
        vec!("de", "fr")
    }

    fn message(&self) -> &'static str {
        match &self.locale as &str {
            "de" | "fr" => "The currency sign should be written after the amount and a non-breaking space.",
            _ => "",
        }
    }

    fn regex_pattern(&self) -> String {
        match &self.locale as &str {
            // Matches one of the following:
            // - digits followed by a character (or none) other than a non-breaking space followed
            //   by any of currencies() return values (ex: `120€` or `120 $`);
            // - any of currencies() return values followed by any whitespace character (or not)
            //   followed by digits (ex: `€120` or `$ 120`).
            "de" | "fr" => format!("([\\d]+[^ ]?[{}]{{1}}|[{}]{{1}}[\\s]?[\\d]+)", self.currencies(), self.currencies()),
            _ => "".to_string(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    struct ExpectedWarning {
        locale: &'static str,
        text: &'static str,
        start: usize,
        end: usize,
    }

    fn expected_warnings() -> Vec<ExpectedWarning> {
        vec!(
            ExpectedWarning { locale: "de", text: "€120", start: 0, end: 6},
            ExpectedWarning { locale: "de", text: "120 €", start: 0, end: 7},
            ExpectedWarning { locale: "de", text: "120€", start: 0, end: 6},
            ExpectedWarning { locale: "fr", text: "€120", start: 0, end: 6},
            ExpectedWarning { locale: "fr", text: "120 €", start: 0, end: 7},
            ExpectedWarning { locale: "fr", text: "120€", start: 0, end: 6}
        )
    }

    #[test]
    fn test_filters_when_warnings() {
        for expected_warning in expected_warnings() {
            let filter = PriceFilter { locale: expected_warning.locale.to_string() };

            let result = filter.check(expected_warning.text);

            assert!(result.is_err());

            let warnings = result.err().unwrap();

            assert_eq!(1, warnings.len());
            assert_eq!(expected_warning.start, warnings[0].start);
            assert_eq!(expected_warning.end, warnings[0].end);
        }
    }

    #[test]
    fn test_filter_when_de_and_no_warnings() {
        let filter = PriceFilter { locale: "de".to_string() };

        let result = filter.check("120 €");

        assert_eq!(false, result.is_err());
        assert_eq!((), result.unwrap());
    }

    #[test]
    fn test_filter_when_fr_and_no_warnings() {
        let filter = PriceFilter { locale: "fr".to_string() };

        let result = filter.check("120 €");

        assert_eq!(false, result.is_err());
        assert_eq!((), result.unwrap());
    }
}

<commit_msg>Add Spanish in PriceFilter<commit_after>use super::*;

pub struct PriceFilter {
    pub locale: String,
}

impl PriceFilter {
    fn currencies(&self) -> &'static str {
        "$¢£¤¥֏؋৲৳৻૱௹฿₠₡₢₣₤₥₦₧₨₩₪₫€₭₮₯₰₱₲₳₴₵₶₷₸₹₺₽﹩＄￠￡￥￦"
    }
}

impl LinterFilter for PriceFilter {
    fn locales(&self) -> Vec<&'static str> {
        vec!("de", "es", "fr")
    }

    fn message(&self) -> &'static str {
        match &self.locale as &str {
            "de" | "es" | "fr" => "The currency sign should be written after the amount and a non-breaking space.",
            _ => "",
        }
    }

    fn regex_pattern(&self) -> String {
        match &self.locale as &str {
            // Matches one of the following:
            // - digits followed by a character (or none) other than a non-breaking space followed
            //   by any of currencies() return values (ex: `120€` or `120 $`);
            // - any of currencies() return values followed by any whitespace character (or not)
            //   followed by digits (ex: `€120` or `$ 120`).
            "de" | "es" | "fr" => format!("([\\d]+[^ ]?[{}]{{1}}|[{}]{{1}}[\\s]?[\\d]+)", self.currencies(), self.currencies()),
            _ => "".to_string(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    struct ExpectedWarning {
        locale: &'static str,
        text: &'static str,
        start: usize,
        end: usize,
    }

    fn expected_warnings() -> Vec<ExpectedWarning> {
        vec!(
            ExpectedWarning { locale: "de", text: "€120", start: 0, end: 6},
            ExpectedWarning { locale: "de", text: "120 €", start: 0, end: 7},
            ExpectedWarning { locale: "de", text: "120€", start: 0, end: 6},

            ExpectedWarning { locale: "es", text: "€120", start: 0, end: 6},
            ExpectedWarning { locale: "es", text: "120 €", start: 0, end: 7},
            ExpectedWarning { locale: "es", text: "120€", start: 0, end: 6},

            ExpectedWarning { locale: "fr", text: "€120", start: 0, end: 6},
            ExpectedWarning { locale: "fr", text: "120 €", start: 0, end: 7},
            ExpectedWarning { locale: "fr", text: "120€", start: 0, end: 6}
        )
    }

    #[test]
    fn test_filters_when_warnings() {
        for expected_warning in expected_warnings() {
            let filter = PriceFilter { locale: expected_warning.locale.to_string() };

            let result = filter.check(expected_warning.text);

            assert!(result.is_err());

            let warnings = result.err().unwrap();

            assert_eq!(1, warnings.len());
            assert_eq!(expected_warning.start, warnings[0].start);
            assert_eq!(expected_warning.end, warnings[0].end);
        }
    }

    #[test]
    fn test_filter_when_de_and_no_warnings() {
        let filter = PriceFilter { locale: "de".to_string() };

        let result = filter.check("120 €");

        assert_eq!(false, result.is_err());
        assert_eq!((), result.unwrap());
    }

    #[test]
    fn test_filter_when_es_and_no_warnings() {
        let filter = PriceFilter { locale: "es".to_string() };

        let result = filter.check("120 €");

        assert_eq!(false, result.is_err());
        assert_eq!((), result.unwrap());
    }

    #[test]
    fn test_filter_when_fr_and_no_warnings() {
        let filter = PriceFilter { locale: "fr".to_string() };

        let result = filter.check("120 €");

        assert_eq!(false, result.is_err());
        assert_eq!((), result.unwrap());
    }
}

<|endoftext|>


<commit_before>#![cfg(feature = "serde-serialize")]

use na::{
    DMatrix, Isometry3, IsometryMatrix3, Matrix3x4, Point3, Quaternion, Rotation3, Similarity3,
    SimilarityMatrix3, Translation3, Unit,
};
use rand;
use serde_json;

macro_rules! test_serde(
    ($($test: ident, $ty: ident);* $(;)*) => {$(
        #[test]
        fn $test() {
            let v: $ty<f32> = rand::random();
            let serialized = serde_json::to_string(&v).unwrap();
            assert_eq!(v, serde_json::from_str(&serialized).unwrap());
        }
    )*}
);

#[test]
fn serde_dmatrix() {
    let v: DMatrix<f32> = DMatrix::new_random(3, 4);
    let serialized = serde_json::to_string(&v).unwrap();
    assert_eq!(v, serde_json::from_str(&serialized).unwrap());
}

test_serde!(
    serde_matrix3x4,          Matrix3x4;
    serde_point3,             Point3;
    serde_translation3,       Translation3;
    serde_rotation3,          Rotation3;
    serde_isometry3,          Isometry3;
    serde_isometry_matrix3,   IsometryMatrix3;
    serde_similarity3,        Similarity3;
    serde_similarity_matrix3, SimilarityMatrix3;
    serde_quaternion,         Quaternion;
);

#[test]
fn serde_flat() {
    // The actual storage is hidden behind three layers of wrapper types that shouldn't appear in serialized form.
    let v = Unit::new_normalize(Quaternion::new(0., 0., 0., 1.));
    let serialized = serde_json::to_string(&v).unwrap();
    assert_eq!(serialized, "[0.0,0.0,1.0,0.0]");
}
<commit_msg>Add tests for serialization of 2D transformations.<commit_after>#![cfg(feature = "serde-serialize")]

use na::{
    DMatrix, Isometry3, IsometryMatrix3, Matrix3x4, Point3, Quaternion, Rotation3, Similarity3,
    SimilarityMatrix3, Translation3, Unit, Point2, Translation2, Rotation2, Isometry2, IsometryMatrix2,
    Similarity2, SimilarityMatrix2,
};
use rand;
use serde_json;

macro_rules! test_serde(
    ($($test: ident, $ty: ident);* $(;)*) => {$(
        #[test]
        fn $test() {
            let v: $ty<f32> = rand::random();
            let serialized = serde_json::to_string(&v).unwrap();
            assert_eq!(v, serde_json::from_str(&serialized).unwrap());
        }
    )*}
);

#[test]
fn serde_dmatrix() {
    let v: DMatrix<f32> = DMatrix::new_random(3, 4);
    let serialized = serde_json::to_string(&v).unwrap();
    assert_eq!(v, serde_json::from_str(&serialized).unwrap());
}

test_serde!(
    serde_matrix3x4,          Matrix3x4;
    serde_point3,             Point3;
    serde_translation3,       Translation3;
    serde_rotation3,          Rotation3;
    serde_isometry3,          Isometry3;
    serde_isometry_matrix3,   IsometryMatrix3;
    serde_similarity3,        Similarity3;
    serde_similarity_matrix3, SimilarityMatrix3;
    serde_quaternion,         Quaternion;
    serde_point2,             Point2;
    serde_translation2,       Translation2;
    serde_rotation2,          Rotation2;
    serde_isometry2,          Isometry2;
    serde_isometry_matrix2,   IsometryMatrix2;
    serde_similarity2,        Similarity2;
    serde_similarity_matrix2, SimilarityMatrix2;
);

#[test]
fn serde_flat() {
    // The actual storage is hidden behind three layers of wrapper types that shouldn't appear in serialized form.
    let v = Unit::new_normalize(Quaternion::new(0., 0., 0., 1.));
    let serialized = serde_json::to_string(&v).unwrap();
    assert_eq!(serialized, "[0.0,0.0,1.0,0.0]");
}
<|endoftext|>


<commit_before>#[cfg(feature = "integration_tests")]
extern crate kafka;

#[cfg(feature = "integration_tests")]
extern crate rand;

#[cfg(feature = "integration_tests")]
#[macro_use]
extern crate log;

#[cfg(feature = "integration_tests")]
extern crate env_logger;

#[cfg(feature = "integration_tests")]
extern crate openssl;

#[cfg(feature = "integration_tests")]
#[macro_use]
extern crate lazy_static;

#[cfg(feature = "integration_tests")]
mod integration {
    use std;

    use kafka::client::{KafkaClient, Compression, GroupOffsetStorage, SecurityConfig};
    use openssl;
    use openssl::x509::X509;
    use openssl::pkey::PKey;
    use openssl::rsa::Rsa;
    use openssl::ssl::{SslConnectorBuilder, SslMethod, SSL_VERIFY_NONE};

    mod client;
    mod consumer_producer;

    pub const LOCAL_KAFKA_BOOTSTRAP_HOST: &str = "localhost:9092";
    pub const TEST_TOPIC_NAME: &str = "kafka-rust-test";
    pub const TEST_TOPIC_NAME_2: &str = "kafka-rust-test2";
    pub const TEST_GROUP_NAME: &str = "kafka-rust-tester";
    pub const TEST_TOPIC_PARTITIONS: [i32; 2] = [0, 1];
    pub const KAFKA_CONSUMER_OFFSETS_TOPIC_NAME: &str = "__consumer_offsets";
    const RSA_KEY_SIZE: u32 = 2024;

    // env vars
    const KAFKA_CLIENT_SECURE: &str = "KAFKA_CLIENT_SECURE";

    lazy_static! {
        static ref KAFKA_CLIENT_COMPRESSION: Compression = {
            match option_env!("KAFKA_CLIENT_COMPRESSION") {
                None => Compression::NONE,
                Some(compression_str) => {
                    match compression_str {
                        "GZIP" => Compression::GZIP,
                        "SNAPPY" => Compression::SNAPPY,
                        _ => Compression::NONE,
                    }
                }
            }
        };
    }

    /// Constructs a Kafka client for the integration tests, and loads
    /// its metadata so it is ready to use.
    pub(crate) fn new_ready_kafka_client() -> KafkaClient {
        let mut client = new_kafka_client();
        client.load_metadata_all().unwrap();
        client
    }

    /// Constructs a Kafka client for the integration tests.
    pub(crate) fn new_kafka_client() -> KafkaClient {
        let hosts = vec![LOCAL_KAFKA_BOOTSTRAP_HOST.to_owned()];

        let mut client = if let Some(security_config) = new_security_config() {
            KafkaClient::new_secure(hosts, security_config.unwrap())
        } else {
            KafkaClient::new(hosts)
        };

        client.set_group_offset_storage(GroupOffsetStorage::Kafka);
        client.set_compression(*KAFKA_CLIENT_COMPRESSION);
        debug!("Constructing client: {:?}", client);

        client
    }

    /// Returns a new security config if the `KAFKA_CLIENT_SECURE`
    /// environment variable is set to a non-empty string.
    pub(crate) fn new_security_config()
        -> Option<Result<SecurityConfig, openssl::error::ErrorStack>>
    {
        match std::env::var_os(KAFKA_CLIENT_SECURE) {
            Some(ref val) if val.as_os_str() != "" => (),
            _ => return None,
        }

        Some(new_key_pair().and_then(get_security_config))
    }

    /// If the `KAFKA_CLIENT_SECURE` environment variable is set, return a
    /// `SecurityConfig`.
    pub(crate) fn get_security_config(
        keypair: openssl::x509::X509,
    ) -> Result<SecurityConfig, openssl::error::ErrorStack> {
        let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();

        {
            let ctx = builder.builder_mut();
            ctx.set_cipher_list("DEFAULT").unwrap();
            ctx.set_certificate(&*keypair).unwrap();
            ctx.set_verify(SSL_VERIFY_NONE);
        }

        let connector = builder.build();
        let security_config = SecurityConfig::new(connector);
        Ok(security_config.with_hostname_verification(false))
    }

    pub(crate) fn new_key_pair() -> Result<X509, openssl::error::ErrorStack> {
        let rsa = Rsa::generate(RSA_KEY_SIZE)?;
        let pkey = PKey::from_rsa(rsa)?;
        let mut builder = X509::builder()?;
        builder.set_pubkey(&*pkey)?;
        Ok(builder.build())
    }
}
<commit_msg>Get Kafka compression env var at run time, not build time<commit_after>#[cfg(feature = "integration_tests")]
extern crate kafka;

#[cfg(feature = "integration_tests")]
extern crate rand;

#[cfg(feature = "integration_tests")]
#[macro_use]
extern crate log;

#[cfg(feature = "integration_tests")]
extern crate env_logger;

#[cfg(feature = "integration_tests")]
extern crate openssl;

#[cfg(feature = "integration_tests")]
#[macro_use]
extern crate lazy_static;

#[cfg(feature = "integration_tests")]
mod integration {
    use std;
    use std::collections::HashMap;

    use kafka::client::{KafkaClient, Compression, GroupOffsetStorage, SecurityConfig};

    use openssl;
    use openssl::x509::X509;
    use openssl::pkey::PKey;
    use openssl::rsa::Rsa;
    use openssl::ssl::{SslConnectorBuilder, SslMethod, SSL_VERIFY_NONE};

    mod client;
    mod consumer_producer;

    pub const LOCAL_KAFKA_BOOTSTRAP_HOST: &str = "localhost:9092";
    pub const TEST_TOPIC_NAME: &str = "kafka-rust-test";
    pub const TEST_TOPIC_NAME_2: &str = "kafka-rust-test2";
    pub const TEST_GROUP_NAME: &str = "kafka-rust-tester";
    pub const TEST_TOPIC_PARTITIONS: [i32; 2] = [0, 1];
    pub const KAFKA_CONSUMER_OFFSETS_TOPIC_NAME: &str = "__consumer_offsets";
    const RSA_KEY_SIZE: u32 = 2024;

    // env vars
    const KAFKA_CLIENT_SECURE: &str = "KAFKA_CLIENT_SECURE";
    const KAFKA_CLIENT_COMPRESSION: &str = "KAFKA_CLIENT_COMPRESSION";

    lazy_static! {
        static ref COMPRESSIONS: HashMap<&'static str, Compression> = {
            let mut m = HashMap::new();

            m.insert("", Compression::NONE);
            m.insert("none", Compression::NONE);
            m.insert("NONE", Compression::NONE);

            m.insert("snappy", Compression::SNAPPY);
            m.insert("SNAPPY", Compression::SNAPPY);

            m.insert("gzip", Compression::GZIP);
            m.insert("GZIP", Compression::GZIP);

            m
        };
    }

    /// Constructs a Kafka client for the integration tests, and loads
    /// its metadata so it is ready to use.
    pub(crate) fn new_ready_kafka_client() -> KafkaClient {
        let mut client = new_kafka_client();
        client.load_metadata_all().unwrap();
        client
    }

    /// Constructs a Kafka client for the integration tests.
    pub(crate) fn new_kafka_client() -> KafkaClient {
        let hosts = vec![LOCAL_KAFKA_BOOTSTRAP_HOST.to_owned()];

        let mut client = if let Some(security_config) = new_security_config() {
            KafkaClient::new_secure(hosts, security_config.unwrap())
        } else {
            KafkaClient::new(hosts)
        };

        client.set_group_offset_storage(GroupOffsetStorage::Kafka);

        let compression = std::env::var(KAFKA_CLIENT_COMPRESSION).unwrap_or(String::from(""));
        let compression = COMPRESSIONS.get(&*compression).unwrap();

        client.set_compression(*compression);
        debug!("Constructing client: {:?}", client);

        client
    }

    /// Returns a new security config if the `KAFKA_CLIENT_SECURE`
    /// environment variable is set to a non-empty string.
    pub(crate) fn new_security_config()
        -> Option<Result<SecurityConfig, openssl::error::ErrorStack>>
    {
        match std::env::var_os(KAFKA_CLIENT_SECURE) {
            Some(ref val) if val.as_os_str() != "" => (),
            _ => return None,
        }

        Some(new_key_pair().and_then(get_security_config))
    }

    /// If the `KAFKA_CLIENT_SECURE` environment variable is set, return a
    /// `SecurityConfig`.
    pub(crate) fn get_security_config(
        keypair: openssl::x509::X509,
    ) -> Result<SecurityConfig, openssl::error::ErrorStack> {
        let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();

        {
            let ctx = builder.builder_mut();
            ctx.set_cipher_list("DEFAULT").unwrap();
            ctx.set_certificate(&*keypair).unwrap();
            ctx.set_verify(SSL_VERIFY_NONE);
        }

        let connector = builder.build();
        let security_config = SecurityConfig::new(connector);
        Ok(security_config.with_hostname_verification(false))
    }

    pub(crate) fn new_key_pair() -> Result<X509, openssl::error::ErrorStack> {
        let rsa = Rsa::generate(RSA_KEY_SIZE)?;
        let pkey = PKey::from_rsa(rsa)?;
        let mut builder = X509::builder()?;
        builder.set_pubkey(&*pkey)?;
        Ok(builder.build())
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate cemu_smm;

use cemu_smm::thumbnail2::*;
use std::fs::{read, read_dir, File};
use std::io::{self, prelude::*};
use std::path::PathBuf;
use std::process::Command;

fn decrypt_test_assets() -> io::Result<()> {
    for entry in read_dir("tests/assets/saves/smm2")? {
        let entry = entry?;
        let file_name = entry.file_name();
        let file_name = file_name.to_str().unwrap();
        if file_name.starts_with("course_") && file_name.ends_with(".btl") {
            let path = entry.path();
            let out_path: Vec<&str> = path.to_str().unwrap().split('.').collect();
            let out_path = out_path[0].to_owned() + ".decrypted";
            let mut command = Command::new("./decryptor_linux");
            command.arg(entry.path()).arg(out_path);
            command.output().unwrap();
        }
    }
    Ok(())
}

// #[test]
fn thumbnail_decrypt() {
    decrypt_test_assets().unwrap();
}

#[test]
fn thumbnail_get_jpeg() {
    for (_, thumbnail, expected) in get_test_assets().into_iter() {
        let mut thumbnail = Thumbnail2::new(thumbnail);

        assert_eq!(thumbnail.get_jpeg_no_opt(), &expected[..]);
    }
}

#[test]
fn thumbnail_optimize_jpeg() {
    for (path, thumbnail, decrypted) in get_test_assets().into_iter() {
        let mut thumbnail = Thumbnail2::new(thumbnail);

        thumbnail.optimize_jpeg().unwrap();

        let out_path: Vec<&str> = path.to_str().unwrap().split('.').collect();
        let out_path = out_path[0].to_owned() + ".opt";
        let mut file = File::create(out_path).unwrap();
        file.write_all(thumbnail.get_jpeg()).unwrap();

        assert!(thumbnail.get_jpeg().len() <= decrypted.len());
    }
}

fn get_test_assets() -> Vec<(PathBuf, Vec<u8>, Vec<u8>)> {
    let mut thumbnails = vec![];
    for entry in read_dir("tests/assets/saves/smm2").unwrap() {
        let entry = entry.unwrap();
        let file_name = entry.file_name();
        let file_name = file_name.to_str().unwrap();
        if file_name.starts_with("course_thumb_") && file_name.ends_with(".btl") {
            let path = entry.path();
            let out_path: Vec<&str> = path.to_str().unwrap().split('.').collect();
            let out_path = out_path[0].to_owned() + ".decrypted";
            thumbnails.push((path.clone(), read(path).unwrap(), read(out_path).unwrap()));
        }
    }
    thumbnails
}
<commit_msg>update thumbnail tests<commit_after>#![allow(dead_code)]

extern crate cemu_smm;

use cemu_smm::thumbnail2::*;
use std::fs::{read, read_dir, File};
use std::io::{self, prelude::*};
use std::path::PathBuf;
use std::process::Command;

fn decrypt_test_assets() -> io::Result<()> {
    let save_folders = vec![
        "tests/assets/saves/smm2/save1",
        "tests/assets/saves/smm2/save2",
    ];
    for folder in save_folders {
        for entry in read_dir(folder)? {
            let entry = entry?;
            let file_name = entry.file_name();
            let file_name = file_name.to_str().unwrap();
            if file_name.starts_with("course_") && file_name.ends_with(".btl") {
                let path = entry.path();
                let out_path: Vec<&str> = path.to_str().unwrap().split('.').collect();
                let out_path = out_path[0].to_owned() + ".decrypted";
                let mut command = Command::new("./decryptor_linux");
                command.arg(entry.path()).arg(out_path);
                command.output().unwrap();
            }
        }
    }
    Ok(())
}

// #[test]
fn thumbnail_decrypt() {
    decrypt_test_assets().unwrap();
}

#[test]
fn thumbnail_get_jpeg() {
    for (_, thumbnail, expected) in get_test_assets().into_iter() {
        let mut thumbnail = Thumbnail2::new(thumbnail);

        assert_eq!(thumbnail.get_jpeg_no_opt(), &expected[..]);
    }
}

#[test]
fn thumbnail_optimize_jpeg() {
    for (path, thumbnail, decrypted) in get_test_assets().into_iter() {
        let mut thumbnail = Thumbnail2::new(thumbnail);

        thumbnail.optimize_jpeg().unwrap();

        let out_path: Vec<&str> = path.to_str().unwrap().split('.').collect();
        let out_path = out_path[0].to_owned() + ".opt";
        let mut file = File::create(out_path).unwrap();
        file.write_all(thumbnail.get_jpeg()).unwrap();

        assert!(thumbnail.get_jpeg().len() <= decrypted.len());
    }
}

fn get_test_assets() -> Vec<(PathBuf, Vec<u8>, Vec<u8>)> {
    let mut thumbnails = vec![];
    for entry in read_dir("tests/assets/saves/smm2").unwrap() {
        let entry = entry.unwrap();
        let file_name = entry.file_name();
        let file_name = file_name.to_str().unwrap();
        if file_name.starts_with("course_thumb_") && file_name.ends_with(".btl") {
            let path = entry.path();
            let out_path: Vec<&str> = path.to_str().unwrap().split('.').collect();
            let out_path = out_path[0].to_owned() + ".decrypted";
            thumbnails.push((path.clone(), read(path).unwrap(), read(out_path).unwrap()));
        }
    }
    thumbnails
}
<|endoftext|>


<commit_before>use gemlab::mesh::{At, Mesh};
use gemlab::StrError;
use russell_chk::assert_vec_approx_eq;
use russell_lab::Vector;

#[test]
fn column_distorted_tris_quads() -> Result<(), StrError> {
    // read mesh
    let mesh = Mesh::from_text_file("./data/meshes/column_distorted_tris_quads.msh")?;

    // check sizes
    assert_eq!(mesh.points.len(), 13);
    assert_eq!(mesh.cells.len(), 7);
    assert_eq!(mesh.boundary_points.len(), 13);
    assert_eq!(mesh.boundary_edges.len(), 13);
    assert_eq!(mesh.boundary_faces.len(), 0);

    // check cells
    assert_eq!(mesh.cells[0].points, &[0, 7, 8, 1]);
    assert_eq!(mesh.cells[1].points, &[1, 8, 9, 2]);
    assert_eq!(mesh.cells[2].points, &[2, 9, 10, 3]);
    assert_eq!(mesh.cells[3].points, &[3, 10, 4]);
    assert_eq!(mesh.cells[4].points, &[4, 10, 11]);
    assert_eq!(mesh.cells[5].points, &[4, 11, 5]);
    assert_eq!(mesh.cells[6].points, &[5, 11, 12, 6]);

    // check edges
    let edge = mesh.boundary_edges.get(&(0, 1)).unwrap();
    assert_eq!(edge.points, &[0, 1]);
    let edge = mesh.boundary_edges.get(&(9, 10)).unwrap();
    assert_eq!(edge.points, &[10, 9]);
    let edge = mesh.boundary_edges.get(&(3, 4)).unwrap();
    assert_eq!(edge.points, &[3, 4]);

    // the magnitude of the normal vector should be equal to edge_length / 2.0
    // for both tris or quas where 2.0 corresponds to the edge_length in the reference system
    // Note that the edge is mapped to [-1,+1] in both Lin or Qua

    // edge keys and correct normal vectors (solutions)
    let edge_keys_and_solutions = [
        // left
        (vec![(0, 1)], [-0.5 / 2.0, 0.0]),
        (vec![(1, 2)], [-0.5 / 2.0, 0.0]),
        (vec![(2, 3)], [-1.0 / 2.0, 0.0]),
        (vec![(3, 4)], [-0.5 / 2.0, 0.0]),
        (vec![(4, 5)], [-0.5 / 2.0, 0.0]),
        (vec![(5, 6)], [-0.1 / 2.0, 0.0]),
        // right
        (vec![(7, 8)], [0.2 / 2.0, 0.0]),
        (vec![(8, 9)], [0.8 / 2.0, 0.0]),
        (vec![(9, 10)], [0.8 / 2.0, 0.0]),
        (vec![(10, 11)], [1.2 / 2.0, 0.0]),
        (vec![(11, 12)], [0.1 / 2.0, 0.0]),
        // bottom
        (vec![(0, 7)], [0.0, -1.0 / 2.0]),
        // top
        (vec![(6, 12)], [0.0, 1.0 / 2.0]),
    ];

    // check if the normal vectors at boundary are outward
    let mut normal = Vector::new(mesh.space_ndim);
    let ksi = &[0.0, 0.0, 0.0];
    for (edge_keys, solution) in &edge_keys_and_solutions {
        for edge_key in edge_keys {
            let mut edge_shape = mesh.alloc_shape_boundary_edge(edge_key)?;
            assert_eq!(edge_shape.nnode, 2);
            edge_shape.calc_boundary_normal(&mut normal, ksi)?;
            assert_vec_approx_eq!(normal.as_data(), solution, 1e-14);
        }
    }

    // find points
    let points = mesh.find_boundary_points(At::X(0.0))?;
    assert_eq!(points, &[0, 1, 2, 3, 4, 5, 6]);
    let points = mesh.find_boundary_points(At::X(1.0))?;
    assert_eq!(points, &[7, 8, 9, 10, 11, 12]);

    // find edges
    let edges = mesh.find_boundary_edges(At::X(0.0))?;
    assert_eq!(edges, &[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]);
    let edges = mesh.find_boundary_edges(At::X(1.0))?;
    assert_eq!(edges, &[(7, 8), (8, 9), (9, 10), (10, 11), (11, 12)]);

    // find faces
    let faces = mesh.find_boundary_faces(At::X(0.0))?;
    assert_eq!(faces.len(), 0);
    Ok(())
}

#[test]
fn rectangle_tris_quads() -> Result<(), StrError> {
    // read mesh
    let mesh = Mesh::from_text_file("./data/meshes/rectangle_tris_quads.msh")?;

    // the magnitude of the normal vector should be equal to edge_length / 2.0
    // for both tris or quas where 2.0 corresponds to the edge_length in the reference system
    // Note that the edge is mapped to [-1,+1] in both Lin or Qua

    // edge keys and correct normal vectors (solutions)
    let edge_keys_and_solutions = [
        // left
        (vec![(0, 3), (3, 7), (7, 10)], [-1.0 / 2.0, 0.0]),
        // right
        (vec![(2, 6), (6, 9), (9, 13)], [1.0 / 2.0, 0.0]),
        // bottom
        (vec![(0, 1), (1, 2)], [0.0, -2.0 / 2.0]),
    ];

    // check if the normal vectors at boundary are outward
    let mut normal = Vector::new(mesh.space_ndim);
    let ksi = &[0.0, 0.0, 0.0];
    for (edge_keys, solution) in &edge_keys_and_solutions {
        for edge_key in edge_keys {
            let mut edge_shape = mesh.alloc_shape_boundary_edge(edge_key)?;
            assert_eq!(edge_shape.nnode, 2);
            edge_shape.calc_boundary_normal(&mut normal, ksi)?;
            assert_vec_approx_eq!(normal.as_data(), solution, 1e-14);
        }
    }

    // find edges
    let edges = mesh.find_boundary_edges(At::X(0.0))?;
    assert_eq!(edges, &[(0, 3), (3, 7), (7, 10), (10, 14)]);
    let edges = mesh.find_boundary_edges(At::X(4.0))?;
    assert_eq!(edges, &[(2, 6), (6, 9), (9, 13)]);
    Ok(())
}
<commit_msg>Improve test<commit_after>use gemlab::mesh::{At, Mesh};
use gemlab::shapes::Shape;
use gemlab::util::SQRT_2;
use gemlab::StrError;
use russell_chk::{assert_approx_eq, assert_vec_approx_eq};
use russell_lab::Vector;

#[test]
fn column_distorted_tris_quads() -> Result<(), StrError> {
    // read mesh
    let mesh = Mesh::from_text_file("./data/meshes/column_distorted_tris_quads.msh")?;

    // check sizes
    assert_eq!(mesh.points.len(), 13);
    assert_eq!(mesh.cells.len(), 7);
    assert_eq!(mesh.boundary_points.len(), 13);
    assert_eq!(mesh.boundary_edges.len(), 13);
    assert_eq!(mesh.boundary_faces.len(), 0);

    // check cells
    assert_eq!(mesh.cells[0].points, &[0, 7, 8, 1]);
    assert_eq!(mesh.cells[1].points, &[1, 8, 9, 2]);
    assert_eq!(mesh.cells[2].points, &[2, 9, 10, 3]);
    assert_eq!(mesh.cells[3].points, &[3, 10, 4]);
    assert_eq!(mesh.cells[4].points, &[4, 10, 11]);
    assert_eq!(mesh.cells[5].points, &[4, 11, 5]);
    assert_eq!(mesh.cells[6].points, &[5, 11, 12, 6]);

    // check edges
    let edge = mesh.boundary_edges.get(&(0, 1)).unwrap();
    assert_eq!(edge.points, &[0, 1]);
    let edge = mesh.boundary_edges.get(&(9, 10)).unwrap();
    assert_eq!(edge.points, &[10, 9]);
    let edge = mesh.boundary_edges.get(&(3, 4)).unwrap();
    assert_eq!(edge.points, &[3, 4]);

    // the magnitude of the normal vector should be equal to edge_length / 2.0
    // for both tris or quas where 2.0 corresponds to the edge_length in the reference system
    // Note that the edge is mapped to [-1,+1] in both Lin or Qua

    // edge keys and correct normal vectors (solutions)
    let edge_keys_and_solutions = [
        // left
        (vec![(0, 1)], [-0.5 / 2.0, 0.0]),
        (vec![(1, 2)], [-0.5 / 2.0, 0.0]),
        (vec![(2, 3)], [-1.0 / 2.0, 0.0]),
        (vec![(3, 4)], [-0.5 / 2.0, 0.0]),
        (vec![(4, 5)], [-0.5 / 2.0, 0.0]),
        (vec![(5, 6)], [-0.1 / 2.0, 0.0]),
        // right
        (vec![(7, 8)], [0.2 / 2.0, 0.0]),
        (vec![(8, 9)], [0.8 / 2.0, 0.0]),
        (vec![(9, 10)], [0.8 / 2.0, 0.0]),
        (vec![(10, 11)], [1.2 / 2.0, 0.0]),
        (vec![(11, 12)], [0.1 / 2.0, 0.0]),
        // bottom
        (vec![(0, 7)], [0.0, -1.0 / 2.0]),
        // top
        (vec![(6, 12)], [0.0, 1.0 / 2.0]),
    ];

    // check if the normal vectors at boundary are outward
    let mut normal = Vector::new(mesh.space_ndim);
    let ksi = &[0.0, 0.0, 0.0];
    for (edge_keys, solution) in &edge_keys_and_solutions {
        for edge_key in edge_keys {
            let mut edge_shape = mesh.alloc_shape_boundary_edge(edge_key)?;
            assert_eq!(edge_shape.nnode, 2);
            edge_shape.calc_boundary_normal(&mut normal, ksi)?;
            assert_vec_approx_eq!(normal.as_data(), solution, 1e-14);
        }
    }

    // find points
    let points = mesh.find_boundary_points(At::X(0.0))?;
    assert_eq!(points, &[0, 1, 2, 3, 4, 5, 6]);
    let points = mesh.find_boundary_points(At::X(1.0))?;
    assert_eq!(points, &[7, 8, 9, 10, 11, 12]);

    // find edges
    let edges = mesh.find_boundary_edges(At::X(0.0))?;
    assert_eq!(edges, &[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]);
    let edges = mesh.find_boundary_edges(At::X(1.0))?;
    assert_eq!(edges, &[(7, 8), (8, 9), (9, 10), (10, 11), (11, 12)]);

    // find faces
    let faces = mesh.find_boundary_faces(At::X(0.0))?;
    assert_eq!(faces.len(), 0);
    Ok(())
}

#[test]
fn rectangle_tris_quads() -> Result<(), StrError> {
    // read mesh
    let mesh = Mesh::from_text_file("./data/meshes/rectangle_tris_quads.msh")?;

    // the magnitude of the normal vector should be equal to edge_length / 2.0
    // for both tris or quas where 2.0 corresponds to the edge_length in the reference system
    // Note that the edge is mapped to [-1,+1] in both Lin or Qua

    // edge keys and correct normal vectors (solutions)
    let edge_keys_and_solutions = [
        // left
        (vec![(0, 3), (3, 7), (7, 10)], [-1.0 / 2.0, 0.0]),
        // right
        (vec![(2, 6), (6, 9), (9, 13)], [1.0 / 2.0, 0.0]),
        // bottom
        (vec![(0, 1), (1, 2)], [0.0, -2.0 / 2.0]),
    ];

    // check if the normal vectors at boundary are outward
    let mut normal = Vector::new(mesh.space_ndim);
    let ksi = &[0.0, 0.0, 0.0];
    for (edge_keys, solution) in &edge_keys_and_solutions {
        for edge_key in edge_keys {
            let mut edge_shape = mesh.alloc_shape_boundary_edge(edge_key)?;
            assert_eq!(edge_shape.nnode, 2);
            edge_shape.calc_boundary_normal(&mut normal, ksi)?;
            assert_vec_approx_eq!(normal.as_data(), solution, 1e-14);
        }
    }

    // find edges
    let edges = mesh.find_boundary_edges(At::X(0.0))?;
    assert_eq!(edges, &[(0, 3), (3, 7), (7, 10), (10, 14)]);
    let edges = mesh.find_boundary_edges(At::X(4.0))?;
    assert_eq!(edges, &[(2, 6), (6, 9), (9, 13)]);

    // edge (4,7)
    let mut shape_edge_4_7 = Shape::new(2, 1, 2)?;
    shape_edge_4_7.set_node(7, 0, 0, mesh.points[7].coords[0])?;
    shape_edge_4_7.set_node(7, 0, 1, mesh.points[7].coords[1])?;
    shape_edge_4_7.set_node(11, 1, 0, mesh.points[11].coords[0])?;
    shape_edge_4_7.set_node(11, 1, 1, mesh.points[11].coords[1])?;
    let length_edge_4_7 = SQRT_2;
    let mut length_numerical = 0.0;
    for index in 0..shape_edge_4_7.integ_points.len() {
        let iota = &shape_edge_4_7.integ_points[index];
        let weight = shape_edge_4_7.integ_points[index][3];
        let det_jac = shape_edge_4_7.calc_jacobian(iota)?;
        length_numerical += weight * det_jac;
    }
    assert_approx_eq!(length_edge_4_7, length_numerical, 1e-14);
    let mut normal = Vector::new(2);
    shape_edge_4_7.calc_boundary_normal(&mut normal, &[0.0, 0.0])?;
    let l = length_edge_4_7 / 2.0;
    assert_vec_approx_eq!(normal.as_data(), &[-l / SQRT_2, l / SQRT_2], 1e-14);

    // cell 5
    let mut shape_cell_5 = mesh.alloc_shape_cell(5)?;
    let mut area_numerical = 0.0;
    for index in 0..shape_cell_5.integ_points.len() {
        let iota = &shape_cell_5.integ_points[index];
        let weight = shape_cell_5.integ_points[index][3];
        let det_jac = shape_cell_5.calc_jacobian(iota)?;
        area_numerical += weight * det_jac;
    }
    assert_approx_eq!(area_numerical, length_edge_4_7 * length_edge_4_7, 1e-15);
    Ok(())
}
<|endoftext|>