<commit_before>#![feature (plugin, custom_derive)]
#![plugin (serde_macros)]

#[macro_use]
extern crate time_steward;

extern crate rand;
extern crate bincode;

use time_steward::stewards::crossverified as s;
use time_steward::{TimeSteward, TimeStewardFromConstants, TimeStewardFromSnapshot, DeterministicRandomId, Column, ColumnId, RowId, PredictorId, EventId,
     ColumnType, EventType, PredictorType};
use time_steward::stewards::amortized;
use time_steward::stewards::memoized_flat;

type Time = i64;

const HOW_MANY_PHILOSOPHERS: i32 = 7;

time_steward_basics!(struct Basics {
  type Time = Time;
  type Constants = ();
  type IncludedTypes = TimeStewardTypes;
});

#[derive (Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
struct Philosopher {
  // This is sometimes in the future because
  // they muse philosophically about handshakes
  // for a while, whenever one of them happens.
  time_when_next_initiates_handshake: Time,
}
impl Column for Philosopher {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x4084d1501468b6dd)
  }
}

type Steward = s::Steward<Basics, amortized::Steward<Basics>, memoized_flat::Steward<Basics>>;

fn get_philosopher_id(index: i32) -> RowId {
  DeterministicRandomId::new(&(0x2302c38efb47e0d0u64, index))
}

type TimeStewardTypes = (ColumnType<Philosopher>,
                         EventType<Initialize>,
                         EventType<Tweak>,
                         EventType<TweakUnsafe>,
                         EventType<Shake>,
                         PredictorType<Shaker>);

fn display_snapshot<S: time_steward::Snapshot<Basics = Basics>>(snapshot: &S) {
  println!("snapshot for {}", snapshot.now());
  for index in 0..HOW_MANY_PHILOSOPHERS {
    println!("{}",
             snapshot.get::<Philosopher>(get_philosopher_id(index))
               .expect("missing philosopher")
               .time_when_next_initiates_handshake);
  }
}

time_steward_predictor! (
  struct Shaker, Basics, PredictorId(0x0e7f27c7643f8167), watching Philosopher,
  | pa, whodunnit | {
// println!("Planning {}", whodunnit);
  let me = pa.get::<Philosopher>(whodunnit).unwrap().clone();
  pa.predict_at_time(me.time_when_next_initiates_handshake, Shake::new (whodunnit));
});

time_steward_event! (
  struct Shake {whodunnit: RowId}, Basics, EventId (0x8987a0b8e7d3d624),
  | &self, m | {
    let now = *m.now();
    let friend_id = get_philosopher_id(m.gen_range(0, HOW_MANY_PHILOSOPHERS));
    let awaken_time_1 = now + m.gen_range(-1, 4);
    let awaken_time_2 = now + m.gen_range(-1, 7);
// println!("SHAKE!!! @{}. {}={}; {}={}", now, self.whodunnit, awaken_time_2, friend_id, awaken_time_1);
// IF YOU SHAKE YOUR OWN HAND YOU RECOVER
// IN THE SECOND TIME APPARENTLY
    m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_1,
                             }));
    m.set::<Philosopher>(self.whodunnit,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_2,
                             }));
  }
);

time_steward_event! (
  struct Initialize {}, Basics, EventId (0xd5e73d8ba6ec59a2),
  | &self, m | {
    println!("FIAT!!!!!");
    for i in 0..HOW_MANY_PHILOSOPHERS {
      m.set::<Philosopher>(get_philosopher_id(i),
        Some(Philosopher {
          time_when_next_initiates_handshake: (i + 1) as Time,
        })
      );
    }
  }
);

time_steward_event! (
  struct Tweak {}, Basics, EventId (0xfe9ff3047f9a9552),
  | &self, m | {
    println!(" Tweak !!!!!");
    let now = *m.now();
    let friend_id = get_philosopher_id(m.gen_range(0, HOW_MANY_PHILOSOPHERS));
    let awaken_time = now + m.gen_range(-1, 7);

    m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time,
                             }));
  }
);

use rand::{Rng, SeedableRng, ChaChaRng};
thread_local! {static INCONSISTENT: u32 = rand::thread_rng().gen::<u32>();}

time_steward_event! (
  struct TweakUnsafe {}, Basics, EventId (0xa1618440808703da),
  | &self, m | {
    println!(" TweakUnsafe !!!!!");
    let now = *m.now();
    let friend_id = get_philosopher_id(m.gen_range(0, HOW_MANY_PHILOSOPHERS));

    let inconsistent = INCONSISTENT.with (| value | {
      *value
    });
    let mut rng = ChaChaRng::from_seed (& [inconsistent, m. next_u32()]);
    let awaken_time = now + rng.gen_range(-1, 7);

    m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time,
                             }));
  }
);

pub fn testfunc() {
  let mut stew: Steward = Steward::from_constants(());

  stew.insert_fiat_event(0,
                       DeterministicRandomId::new(&0x32e1570766e768a7u64),
                       Initialize::new())
    .unwrap();

  let mut snapshots = Vec::new();
  for increment in 1..21 {
    snapshots.push(stew.snapshot_before(&(increment * 100i64)));
    stew = Steward::from_snapshot::<<Steward as TimeSteward>::Snapshot> (snapshots.last().unwrap().as_ref().unwrap());
  }
  for snapshot in snapshots.iter_mut()
    .map(|option| option.as_mut().expect("all these snapshots should have been valid")) {
    display_snapshot(snapshot);
    let mut writer: Vec<u8> = Vec::with_capacity(128);
    time_steward::serialize_snapshot:: <Basics, <Steward as TimeSteward>::Snapshot,_> (snapshot, &mut writer, bincode::SizeLimit::Infinite).unwrap();
    // let serialized = String::from_utf8 (serializer.into_inner()).unwrap();
    println!("{:?}", writer);
    use std::io::Cursor;
    let mut reader = Cursor::new(writer);
    let deserialized = time_steward::deserialize_snapshot:: <Basics, _> (&mut reader, bincode::SizeLimit::Infinite/*serialized.as_bytes().iter().map (| bite | Ok (bite.clone()))*/).unwrap();
    println!("{:?}", deserialized);
    display_snapshot(&deserialized);
    use time_steward::MomentaryAccessor;
    display_snapshot(&Steward::from_snapshot::<time_steward::FiatSnapshot<Basics>>(&deserialized).snapshot_before(deserialized.now()).unwrap());
  }
  // panic!("anyway")
}

#[test]
fn actuallytest() {
  testfunc();
}

#[test]
fn local_synchronization_test() {
  use time_steward::stewards::simply_synchronized;
  use std::net::{TcpListener, TcpStream};
  use std::io::{BufReader, BufWriter};
  let listener = TcpListener::bind(("127.0.0.1", 0)).unwrap();
  let port = listener.local_addr().unwrap().port();
  ::std::thread::spawn(move || {
    let end_0 = listener.accept().unwrap().0;
    let mut stew_0: simply_synchronized::Steward<Basics, amortized::Steward<Basics>> =
      simply_synchronized::Steward::new(DeterministicRandomId::new(&0u32),
                                        0,
                                        4,
                                        (),
                                        BufReader::new(end_0.try_clone().unwrap()),
                                        BufWriter::new(end_0));
    stew_0.insert_fiat_event(0,
                         DeterministicRandomId::new(&0x32e1570766e768a7u64),
                         Initialize::new())
      .unwrap();

    for increment in 1..21 {
      let time = increment * 100i64;
      if increment % 3 == 0 {
        stew_0.insert_fiat_event(time, DeterministicRandomId::new(&increment), Tweak::new())
          .unwrap();
      }
      stew_0.snapshot_before(&time);
      stew_0.settle_before(time);
    }
    stew_0.finish();
  });
  let end_1 = TcpStream::connect(("127.0.0.1", port)).unwrap();
  let mut stew_1: simply_synchronized::Steward<Basics, amortized::Steward<Basics>> =
    simply_synchronized::Steward::new(DeterministicRandomId::new(&1u32),
                                      0,
                                      4,
                                      (),
                                      BufReader::new(end_1.try_clone().unwrap()),
                                      BufWriter::new(end_1));

  for increment in 1..21 {
    let time = increment * 100i64;
    if increment % 4 == 0 {
      stew_1.insert_fiat_event(time, DeterministicRandomId::new(&increment), Tweak::new()).unwrap();
    }
    stew_1.snapshot_before(&time);
    stew_1.settle_before(time);
  }
  stew_1.finish();
}

#[test]
#[should_panic (expected = "event occurred this way locally")]
fn local_synchronization_failure() {
  use time_steward::stewards::simply_synchronized;
  use std::net::{TcpListener, TcpStream};
  use std::io::{BufReader, BufWriter};
  let listener = TcpListener::bind(("127.0.0.1", 0)).unwrap();
  let port = listener.local_addr().unwrap().port();
  ::std::thread::spawn(move || {
    let end_0 = listener.accept().unwrap().0;
    let mut stew_0: simply_synchronized::Steward<Basics, amortized::Steward<Basics>> =
      simply_synchronized::Steward::new(DeterministicRandomId::new(&0u32),
                                        0,
                                        4,
                                        (),
                                        BufReader::new(end_0.try_clone().unwrap()),
                                        BufWriter::new(end_0));
    stew_0.insert_fiat_event(0,
                         DeterministicRandomId::new(&0x32e1570766e768a7u64),
                         Initialize::new())
      .unwrap();

    for increment in 1..21 {
      let time = increment * 100i64;
      if increment % 3 == 0 {
        stew_0.insert_fiat_event(time,
                             DeterministicRandomId::new(&increment),
                             TweakUnsafe::new())
          .unwrap();
      }
      stew_0.snapshot_before(&time);
      stew_0.settle_before(time);
    }
    stew_0.finish();
  });
  let end_1 = TcpStream::connect(("127.0.0.1", port)).unwrap();
  let mut stew_1: simply_synchronized::Steward<Basics, amortized::Steward<Basics>> =
    simply_synchronized::Steward::new(DeterministicRandomId::new(&1u32),
                                      0,
                                      4,
                                      (),
                                      BufReader::new(end_1.try_clone().unwrap()),
                                      BufWriter::new(end_1));

  for increment in 1..21 {
    let time = increment * 100i64;
    if increment % 4 == 0 {
      stew_1.insert_fiat_event(time,
                           DeterministicRandomId::new(&increment),
                           TweakUnsafe::new())
        .unwrap();
    }
    stew_1.snapshot_before(&time);
    stew_1.settle_before(time);
  }
  stew_1.finish();
}
<commit_msg>Made more variations of handshakes tests<commit_after>#![feature (plugin, custom_derive)]
#![plugin (serde_macros)]

#[macro_use]
extern crate time_steward;

extern crate rand;
extern crate bincode;

use time_steward::{TimeSteward, TimeStewardFromConstants, TimeStewardFromSnapshot, DeterministicRandomId, Column, ColumnId, RowId, PredictorId, EventId,
     ColumnType, EventType, PredictorType};
use time_steward::stewards::{inefficient_flat, memoized_flat, amortized, flat_to_inefficient_full, crossverified};

type Time = i64;

const HOW_MANY_PHILOSOPHERS: i32 = 7;

time_steward_basics!(struct Basics {
  type Time = Time;
  type Constants = ();
  type IncludedTypes = TimeStewardTypes;
});

#[derive (Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
struct Philosopher {
  // This is sometimes in the future because
  // they muse philosophically about handshakes
  // for a while, whenever one of them happens.
  time_when_next_initiates_handshake: Time,
}
impl Column for Philosopher {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x4084d1501468b6dd)
  }
}

fn get_philosopher_id(index: i32) -> RowId {
  DeterministicRandomId::new(&(0x2302c38efb47e0d0u64, index))
}

type TimeStewardTypes = (ColumnType<Philosopher>,
                         EventType<Initialize>,
                         EventType<Tweak>,
                         EventType<TweakUnsafe>,
                         EventType<Shake>,
                         PredictorType<Shaker>);

fn display_snapshot<S: time_steward::Snapshot<Basics = Basics>>(snapshot: &S) {
  println!("snapshot for {}", snapshot.now());
  for index in 0..HOW_MANY_PHILOSOPHERS {
    println!("{}",
             snapshot.get::<Philosopher>(get_philosopher_id(index))
               .expect("missing philosopher")
               .time_when_next_initiates_handshake);
  }
}

time_steward_predictor! (
  struct Shaker, Basics, PredictorId(0x0e7f27c7643f8167), watching Philosopher,
  | pa, whodunnit | {
// println!("Planning {}", whodunnit);
  let me = pa.get::<Philosopher>(whodunnit).unwrap().clone();
  pa.predict_at_time(me.time_when_next_initiates_handshake, Shake::new (whodunnit));
});

time_steward_event! (
  struct Shake {whodunnit: RowId}, Basics, EventId (0x8987a0b8e7d3d624),
  | &self, m | {
    let now = *m.now();
    let friend_id = get_philosopher_id(m.gen_range(0, HOW_MANY_PHILOSOPHERS));
    let awaken_time_1 = now + m.gen_range(-1, 4);
    let awaken_time_2 = now + m.gen_range(-1, 7);
// println!("SHAKE!!! @{}. {}={}; {}={}", now, self.whodunnit, awaken_time_2, friend_id, awaken_time_1);
// IF YOU SHAKE YOUR OWN HAND YOU RECOVER
// IN THE SECOND TIME APPARENTLY
    m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_1,
                             }));
    m.set::<Philosopher>(self.whodunnit,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_2,
                             }));
  }
);

time_steward_event! (
  struct Initialize {}, Basics, EventId (0xd5e73d8ba6ec59a2),
  | &self, m | {
    println!("FIAT!!!!!");
    for i in 0..HOW_MANY_PHILOSOPHERS {
      m.set::<Philosopher>(get_philosopher_id(i),
        Some(Philosopher {
          time_when_next_initiates_handshake: (i + 1) as Time,
        })
      );
    }
  }
);

time_steward_event! (
  struct Tweak {}, Basics, EventId (0xfe9ff3047f9a9552),
  | &self, m | {
    println!(" Tweak !!!!!");
    let now = *m.now();
    let friend_id = get_philosopher_id(m.gen_range(0, HOW_MANY_PHILOSOPHERS));
    let awaken_time = now + m.gen_range(-1, 7);

    m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time,
                             }));
  }
);

use rand::{Rng, SeedableRng, ChaChaRng};
thread_local! {static INCONSISTENT: u32 = rand::thread_rng().gen::<u32>();}

time_steward_event! (
  struct TweakUnsafe {}, Basics, EventId (0xa1618440808703da),
  | &self, m | {
    println!(" TweakUnsafe !!!!!");
    let now = *m.now();
    let friend_id = get_philosopher_id(m.gen_range(0, HOW_MANY_PHILOSOPHERS));

    let inconsistent = INCONSISTENT.with (| value | {
      *value
    });
    let mut rng = ChaChaRng::from_seed (& [inconsistent, m. next_u32()]);
    let awaken_time = now + rng.gen_range(-1, 7);

    m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time,
                             }));
  }
);

#[test]
pub fn handshakes_simple() {
  type Steward = crossverified::Steward<Basics, inefficient_flat::Steward<Basics>, memoized_flat::Steward<Basics>>;
  let mut stew: Steward = Steward::from_constants(());

  stew.insert_fiat_event(0,
                       DeterministicRandomId::new(&0x32e1570766e768a7u64),
                       Initialize::new())
    .unwrap();

  for increment in 1..21 {
    let snapshot: <Steward as TimeSteward>::Snapshot = stew.snapshot_before(&(increment * 100i64)).unwrap();
    display_snapshot(&snapshot);
  }
}

#[test]
pub fn handshakes_reloading() {
  type Steward = crossverified::Steward<Basics, amortized::Steward<Basics>, memoized_flat::Steward<Basics>>;
  let mut stew: Steward = Steward::from_constants(());

  stew.insert_fiat_event(0,
                       DeterministicRandomId::new(&0x32e1570766e768a7u64),
                       Initialize::new())
    .unwrap();

  let mut snapshots = Vec::new();
  for increment in 1..21 {
    snapshots.push(stew.snapshot_before(&(increment * 100i64)));
    stew = Steward::from_snapshot::<<Steward as TimeSteward>::Snapshot> (snapshots.last().unwrap().as_ref().unwrap());
  }
  for snapshot in snapshots.iter_mut()
    .map(|option| option.as_mut().expect("all these snapshots should have been valid")) {
    display_snapshot(snapshot);
    let mut writer: Vec<u8> = Vec::with_capacity(128);
    time_steward::serialize_snapshot:: <Basics, <Steward as TimeSteward>::Snapshot,_> (snapshot, &mut writer, bincode::SizeLimit::Infinite).unwrap();
    // let serialized = String::from_utf8 (serializer.into_inner()).unwrap();
    println!("{:?}", writer);
    use std::io::Cursor;
    let mut reader = Cursor::new(writer);
    let deserialized = time_steward::deserialize_snapshot:: <Basics, _> (&mut reader, bincode::SizeLimit::Infinite/*serialized.as_bytes().iter().map (| bite | Ok (bite.clone()))*/).unwrap();
    println!("{:?}", deserialized);
    display_snapshot(&deserialized);
    use time_steward::MomentaryAccessor;
    display_snapshot(&Steward::from_snapshot::<time_steward::FiatSnapshot<Basics>>(&deserialized).snapshot_before(deserialized.now()).unwrap());
  }
  // panic!("anyway")
}

#[test]
fn handshakes_retroactive() {
  type Steward = crossverified::Steward<Basics, amortized::Steward<Basics>, flat_to_inefficient_full::Steward<Basics, memoized_flat::Steward <Basics> >>;
  let mut stew: Steward = Steward::from_constants(());

  stew.insert_fiat_event(0,
                       DeterministicRandomId::new(&0x32e1570766e768a7u64),
                       Initialize::new())
    .unwrap();

  stew.snapshot_before(&(2000i64));
  for increment in 1..21 {
    stew.insert_fiat_event(increment * 100i64, DeterministicRandomId::new(&increment), Tweak::new()).unwrap();
    let snapshot: <Steward as TimeSteward>::Snapshot = stew.snapshot_before(&(2000i64)).unwrap();
    display_snapshot(&snapshot);
  }

}

#[test]
fn local_synchronization_test() {
  use time_steward::stewards::simply_synchronized;
  use std::net::{TcpListener, TcpStream};
  use std::io::{BufReader, BufWriter};
  let listener = TcpListener::bind(("127.0.0.1", 0)).unwrap();
  let port = listener.local_addr().unwrap().port();
  ::std::thread::spawn(move || {
    let end_0 = listener.accept().unwrap().0;
    let mut stew_0: simply_synchronized::Steward<Basics, amortized::Steward<Basics>> =
      simply_synchronized::Steward::new(DeterministicRandomId::new(&0u32),
                                        0,
                                        4,
                                        (),
                                        BufReader::new(end_0.try_clone().unwrap()),
                                        BufWriter::new(end_0));
    stew_0.insert_fiat_event(0,
                         DeterministicRandomId::new(&0x32e1570766e768a7u64),
                         Initialize::new())
      .unwrap();

    for increment in 1..21 {
      let time = increment * 100i64;
      if increment % 3 == 0 {
        stew_0.insert_fiat_event(time, DeterministicRandomId::new(&increment), Tweak::new())
          .unwrap();
      }
      stew_0.snapshot_before(&time);
      stew_0.settle_before(time);
    }
    stew_0.finish();
  });
  let end_1 = TcpStream::connect(("127.0.0.1", port)).unwrap();
  let mut stew_1: simply_synchronized::Steward<Basics, amortized::Steward<Basics>> =
    simply_synchronized::Steward::new(DeterministicRandomId::new(&1u32),
                                      0,
                                      4,
                                      (),
                                      BufReader::new(end_1.try_clone().unwrap()),
                                      BufWriter::new(end_1));

  for increment in 1..21 {
    let time = increment * 100i64;
    if increment % 4 == 0 {
      stew_1.insert_fiat_event(time, DeterministicRandomId::new(&increment), Tweak::new()).unwrap();
    }
    stew_1.snapshot_before(&time);
    stew_1.settle_before(time);
  }
  stew_1.finish();
}

#[test]
#[should_panic (expected = "event occurred this way locally")]
fn local_synchronization_failure() {
  use time_steward::stewards::simply_synchronized;
  use std::net::{TcpListener, TcpStream};
  use std::io::{BufReader, BufWriter};
  let listener = TcpListener::bind(("127.0.0.1", 0)).unwrap();
  let port = listener.local_addr().unwrap().port();
  ::std::thread::spawn(move || {
    let end_0 = listener.accept().unwrap().0;
    let mut stew_0: simply_synchronized::Steward<Basics, amortized::Steward<Basics>> =
      simply_synchronized::Steward::new(DeterministicRandomId::new(&0u32),
                                        0,
                                        4,
                                        (),
                                        BufReader::new(end_0.try_clone().unwrap()),
                                        BufWriter::new(end_0));
    stew_0.insert_fiat_event(0,
                         DeterministicRandomId::new(&0x32e1570766e768a7u64),
                         Initialize::new())
      .unwrap();

    for increment in 1..21 {
      let time = increment * 100i64;
      if increment % 3 == 0 {
        stew_0.insert_fiat_event(time,
                             DeterministicRandomId::new(&increment),
                             TweakUnsafe::new())
          .unwrap();
      }
      stew_0.snapshot_before(&time);
      stew_0.settle_before(time);
    }
    stew_0.finish();
  });
  let end_1 = TcpStream::connect(("127.0.0.1", port)).unwrap();
  let mut stew_1: simply_synchronized::Steward<Basics, amortized::Steward<Basics>> =
    simply_synchronized::Steward::new(DeterministicRandomId::new(&1u32),
                                      0,
                                      4,
                                      (),
                                      BufReader::new(end_1.try_clone().unwrap()),
                                      BufWriter::new(end_1));

  for increment in 1..21 {
    let time = increment * 100i64;
    if increment % 4 == 0 {
      stew_1.insert_fiat_event(time,
                           DeterministicRandomId::new(&increment),
                           TweakUnsafe::new())
        .unwrap();
    }
    stew_1.snapshot_before(&time);
    stew_1.settle_before(time);
  }
  stew_1.finish();
}
<|endoftext|>


<commit_before>extern crate gimli;

use gimli::{AttributeValue, DebugAbbrev, DebugAranges, DebugInfo, DebugLine, DebugLoc,
            DebugPubNames, DebugPubTypes, DebugRanges, DebugStr, LittleEndian};
use std::env;
use std::collections::hash_map::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::new();
    if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") {
        path.push(dir);
    }
    path.push("fixtures/self");
    path.push(section);

    println!("Reading section \"{}\" at path {:?}", section, path);
    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

#[test]
fn test_parse_self_debug_info() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);

        while cursor.next_dfs().expect("Should parse next dfs").is_some() {
            let entry = cursor.current().expect("Should have a current entry");

            let mut attrs = entry.attrs();
            while let Some(_) = attrs.next().expect("Should parse entry's attribute") {}
        }
    }
}

#[test]
fn test_parse_self_debug_line() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::new(&debug_line, LittleEndian);

    let debug_str = read_section("debug_str");
    let debug_str = DebugStr::new(&debug_str, LittleEndian);

    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);
        cursor.next_dfs().expect("Should parse next dfs");

        let unit_entry = cursor.current().expect("Should have a root entry");

        let comp_dir = unit_entry
            .attr(gimli::DW_AT_comp_dir)
            .expect("Should parse comp_dir attribute")
            .and_then(|attr| attr.string_value(&debug_str));
        let comp_name = unit_entry
            .attr(gimli::DW_AT_name)
            .expect("Should parse name attribute")
            .and_then(|attr| attr.string_value(&debug_str));

        if let Some(AttributeValue::DebugLineRef(offset)) =
            unit_entry
                .attr_value(gimli::DW_AT_stmt_list)
                .expect("Should parse stmt_list") {
            let program = debug_line
                .program(offset, unit.address_size(), comp_dir, comp_name)
                .expect("should parse line number program header");

            let mut results = Vec::new();
            let mut rows = program.rows();
            while let Some((_, row)) =
                rows.next_row()
                    .expect("Should parse and execute all rows in the line number program") {
                results.push(*row);
            }
            results.reverse();

            let program = debug_line
                .program(offset, unit.address_size(), comp_dir, comp_name)
                .expect("should parse line number program header");
            let (program, sequences) =
                program
                    .sequences()
                    .expect("should parse and execute the entire line number program");
            assert!(!sequences.is_empty()); // Should be at least one sequence.
            for sequence in sequences {
                let mut rows = program.resume_from(&sequence);
                while let Some((_, row)) =
                    rows.next_row()
                        .expect("Should parse and execute all rows after resuming") {
                    let other_row = results.pop().unwrap();
                    assert!(row.address() >= sequence.start);
                    assert!(row.address() <= sequence.end);
                    assert_eq!(row.address(), other_row.address());
                    assert_eq!(row.line(), other_row.line());
                }
            }
            assert!(results.is_empty());
        }
    }
}

#[test]
fn test_parse_self_debug_loc() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_loc = read_section("debug_loc");
    let debug_loc = DebugLoc::new(&debug_loc, LittleEndian);

    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);
        cursor.next_dfs().expect("Should parse next dfs");

        let mut low_pc = 0;

        {
            let unit_entry = cursor.current().expect("Should have a root entry");
            let low_pc_attr = unit_entry
                .attr_value(gimli::DW_AT_low_pc)
                .expect("Should parse low_pc");
            if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
                low_pc = address;
            }
        }

        while cursor.next_dfs().expect("Should parse next dfs").is_some() {
            let entry = cursor.current().expect("Should have a current entry");
            let mut attrs = entry.attrs();
            while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                if let AttributeValue::DebugLocRef(offset) = attr.value() {
                    let mut locs = debug_loc
                        .locations(offset, unit.address_size(), low_pc)
                        .expect("Should parse locations OK");
                    while let Some(loc) = locs.next().expect("Should parse next location") {
                        assert!(loc.range.begin <= loc.range.end);
                    }
                }
            }
        }
    }
}

#[test]
fn test_parse_self_debug_ranges() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_ranges = read_section("debug_ranges");
    let debug_ranges = DebugRanges::new(&debug_ranges, LittleEndian);

    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);
        cursor.next_dfs().expect("Should parse next dfs");

        let mut low_pc = 0;

        {
            let unit_entry = cursor.current().expect("Should have a root entry");
            let low_pc_attr = unit_entry
                .attr_value(gimli::DW_AT_low_pc)
                .expect("Should parse low_pc");
            if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
                low_pc = address;
            }
        }

        while cursor.next_dfs().expect("Should parse next dfs").is_some() {
            let entry = cursor.current().expect("Should have a current entry");
            let mut attrs = entry.attrs();
            while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                if let AttributeValue::DebugRangesRef(offset) = attr.value() {
                    let mut ranges = debug_ranges
                        .ranges(offset, unit.address_size(), low_pc)
                        .expect("Should parse ranges OK");
                    while let Some(range) = ranges.next().expect("Should parse next range") {
                        assert!(range.begin <= range.end);
                    }
                }
            }
        }
    }
}

#[test]
fn test_parse_self_debug_aranges() {
    let debug_aranges = read_section("debug_aranges");
    let debug_aranges = DebugAranges::new(&debug_aranges, LittleEndian);

    let mut aranges = debug_aranges.items();
    while let Some(_) = aranges.next().expect("Should parse arange OK") {
        // Not really anything else we can check right now.
    }
}

#[test]
fn test_parse_self_debug_pubnames() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_pubnames = read_section("debug_pubnames");
    let debug_pubnames = DebugPubNames::new(&debug_pubnames, LittleEndian);

    let mut units = HashMap::new();
    let mut abbrevs = HashMap::new();
    let mut pubnames = debug_pubnames.items();
    while let Some(entry) = pubnames.next().expect("Should parse pubname OK") {
        let unit_offset = entry.unit_header_offset();
        let unit = units.entry(unit_offset).or_insert_with(|| {
            debug_info
                .header_from_offset(unit_offset)
                .expect("Should parse unit header OK")
        });
        let abbrev_offset = unit.debug_abbrev_offset();
        let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| {
            debug_abbrev
                .abbreviations(abbrev_offset)
                .expect("Should parse abbreviations OK")
        });
        let mut cursor = unit.entries_at_offset(abbrevs, entry.die_offset())
            .expect("DIE offset should be valid");
        assert!(cursor.next_dfs().expect("Should parse DIE").is_some());
    }
}

#[test]
fn test_parse_self_debug_pubtypes() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_pubtypes = read_section("debug_pubtypes");
    let debug_pubtypes = DebugPubTypes::new(&debug_pubtypes, LittleEndian);

    let mut units = HashMap::new();
    let mut abbrevs = HashMap::new();
    let mut pubtypes = debug_pubtypes.items();
    while let Some(entry) = pubtypes.next().expect("Should parse pubtype OK") {
        let unit_offset = entry.unit_header_offset();
        let unit = units.entry(unit_offset).or_insert_with(|| {
            debug_info
                .header_from_offset(unit_offset)
                .expect("Should parse unit header OK")
        });
        let abbrev_offset = unit.debug_abbrev_offset();
        let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| {
            debug_abbrev
                .abbreviations(abbrev_offset)
                .expect("Should parse abbreviations OK")
        });
        let mut cursor = unit.entries_at_offset(abbrevs, entry.die_offset())
            .expect("DIE offset should be valid");
        assert!(cursor.next_dfs().expect("Should parse DIE").is_some());
    }
}

// Because `.eh_frame` doesn't contain address sizes, we need to assume the
// native word size, so this test is only valid on 64-bit machines (as the
// `.eh_frame` fixture data was created on a 64-bit machine).
#[cfg(target_pointer_width = "64")]
#[test]
fn test_parse_self_eh_frame() {
    use gimli::{BaseAddresses, CieOrFde, EhFrame, UnwindSection};

    let eh_frame = read_section("eh_frame");
    let eh_frame = EhFrame::new(&eh_frame, LittleEndian);

    let bases = BaseAddresses::default().set_cfi(0).set_data(0).set_text(0);
    let mut entries = eh_frame.entries(&bases);
    while let Some(entry) = entries.next().expect("Should parse CFI entry OK") {
        match entry {
            CieOrFde::Cie(cie) => {
                let mut instrs = cie.instructions();
                while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") {
                    // TODO FITZGEN
                }
            }
            CieOrFde::Fde(partial) => {
                let fde = partial
                    .parse(|offset| eh_frame.cie_from_offset(&bases, offset))
                    .expect("Should be able to get CIE for FDE");

                let mut instrs = fde.instructions();
                while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") {
                    // TODO FITZGEN
                }
            }
        }
    }
}
<commit_msg>Extend parse_self tests for operations<commit_after>extern crate gimli;

use gimli::{AttributeValue, DebugAbbrev, DebugAranges, DebugInfo, DebugLine, DebugLoc,
            DebugPubNames, DebugPubTypes, DebugRanges, DebugStr, Expression, Format, LittleEndian,
            Operation, Reader};
use std::env;
use std::collections::hash_map::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::new();
    if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") {
        path.push(dir);
    }
    path.push("fixtures/self");
    path.push(section);

    println!("Reading section \"{}\" at path {:?}", section, path);
    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

fn parse_expression<R: Reader>(expr: Expression<R>, address_size: u8, format: Format) {
    let mut pc = expr.0.clone();
    while !pc.is_empty() {
        Operation::parse(&mut pc, &expr.0, address_size, format).expect("Should parse operation");
    }

    // Also attempt to evaluate some of it.
    let mut eval = expr.evaluation(address_size, format);
    eval.set_initial_value(0);
    eval.evaluate().expect("Should evaluate expression");
}

#[test]
fn test_parse_self_debug_info() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);

        while cursor.next_dfs().expect("Should parse next dfs").is_some() {
            let entry = cursor.current().expect("Should have a current entry");

            let mut attrs = entry.attrs();
            while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                if let AttributeValue::Exprloc(expression) = attr.value() {
                    parse_expression(expression, unit.address_size(), unit.format());
                }
            }
        }
    }
}

#[test]
fn test_parse_self_debug_line() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::new(&debug_line, LittleEndian);

    let debug_str = read_section("debug_str");
    let debug_str = DebugStr::new(&debug_str, LittleEndian);

    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);
        cursor.next_dfs().expect("Should parse next dfs");

        let unit_entry = cursor.current().expect("Should have a root entry");

        let comp_dir = unit_entry
            .attr(gimli::DW_AT_comp_dir)
            .expect("Should parse comp_dir attribute")
            .and_then(|attr| attr.string_value(&debug_str));
        let comp_name = unit_entry
            .attr(gimli::DW_AT_name)
            .expect("Should parse name attribute")
            .and_then(|attr| attr.string_value(&debug_str));

        if let Some(AttributeValue::DebugLineRef(offset)) =
            unit_entry
                .attr_value(gimli::DW_AT_stmt_list)
                .expect("Should parse stmt_list") {
            let program = debug_line
                .program(offset, unit.address_size(), comp_dir, comp_name)
                .expect("should parse line number program header");

            let mut results = Vec::new();
            let mut rows = program.rows();
            while let Some((_, row)) =
                rows.next_row()
                    .expect("Should parse and execute all rows in the line number program") {
                results.push(*row);
            }
            results.reverse();

            let program = debug_line
                .program(offset, unit.address_size(), comp_dir, comp_name)
                .expect("should parse line number program header");
            let (program, sequences) =
                program
                    .sequences()
                    .expect("should parse and execute the entire line number program");
            assert!(!sequences.is_empty()); // Should be at least one sequence.
            for sequence in sequences {
                let mut rows = program.resume_from(&sequence);
                while let Some((_, row)) =
                    rows.next_row()
                        .expect("Should parse and execute all rows after resuming") {
                    let other_row = results.pop().unwrap();
                    assert!(row.address() >= sequence.start);
                    assert!(row.address() <= sequence.end);
                    assert_eq!(row.address(), other_row.address());
                    assert_eq!(row.line(), other_row.line());
                }
            }
            assert!(results.is_empty());
        }
    }
}

#[test]
fn test_parse_self_debug_loc() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_loc = read_section("debug_loc");
    let debug_loc = DebugLoc::new(&debug_loc, LittleEndian);

    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);
        cursor.next_dfs().expect("Should parse next dfs");

        let mut low_pc = 0;

        {
            let unit_entry = cursor.current().expect("Should have a root entry");
            let low_pc_attr = unit_entry
                .attr_value(gimli::DW_AT_low_pc)
                .expect("Should parse low_pc");
            if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
                low_pc = address;
            }
        }

        while cursor.next_dfs().expect("Should parse next dfs").is_some() {
            let entry = cursor.current().expect("Should have a current entry");
            let mut attrs = entry.attrs();
            while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                if let AttributeValue::DebugLocRef(offset) = attr.value() {
                    let mut locs = debug_loc
                        .locations(offset, unit.address_size(), low_pc)
                        .expect("Should parse locations OK");
                    while let Some(loc) = locs.next().expect("Should parse next location") {
                        assert!(loc.range.begin <= loc.range.end);
                        parse_expression(loc.data, unit.address_size(), unit.format());
                    }
                }
            }
        }
    }
}

#[test]
fn test_parse_self_debug_ranges() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_ranges = read_section("debug_ranges");
    let debug_ranges = DebugRanges::new(&debug_ranges, LittleEndian);

    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);
        cursor.next_dfs().expect("Should parse next dfs");

        let mut low_pc = 0;

        {
            let unit_entry = cursor.current().expect("Should have a root entry");
            let low_pc_attr = unit_entry
                .attr_value(gimli::DW_AT_low_pc)
                .expect("Should parse low_pc");
            if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
                low_pc = address;
            }
        }

        while cursor.next_dfs().expect("Should parse next dfs").is_some() {
            let entry = cursor.current().expect("Should have a current entry");
            let mut attrs = entry.attrs();
            while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                if let AttributeValue::DebugRangesRef(offset) = attr.value() {
                    let mut ranges = debug_ranges
                        .ranges(offset, unit.address_size(), low_pc)
                        .expect("Should parse ranges OK");
                    while let Some(range) = ranges.next().expect("Should parse next range") {
                        assert!(range.begin <= range.end);
                    }
                }
            }
        }
    }
}

#[test]
fn test_parse_self_debug_aranges() {
    let debug_aranges = read_section("debug_aranges");
    let debug_aranges = DebugAranges::new(&debug_aranges, LittleEndian);

    let mut aranges = debug_aranges.items();
    while let Some(_) = aranges.next().expect("Should parse arange OK") {
        // Not really anything else we can check right now.
    }
}

#[test]
fn test_parse_self_debug_pubnames() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_pubnames = read_section("debug_pubnames");
    let debug_pubnames = DebugPubNames::new(&debug_pubnames, LittleEndian);

    let mut units = HashMap::new();
    let mut abbrevs = HashMap::new();
    let mut pubnames = debug_pubnames.items();
    while let Some(entry) = pubnames.next().expect("Should parse pubname OK") {
        let unit_offset = entry.unit_header_offset();
        let unit = units.entry(unit_offset).or_insert_with(|| {
            debug_info
                .header_from_offset(unit_offset)
                .expect("Should parse unit header OK")
        });
        let abbrev_offset = unit.debug_abbrev_offset();
        let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| {
            debug_abbrev
                .abbreviations(abbrev_offset)
                .expect("Should parse abbreviations OK")
        });
        let mut cursor = unit.entries_at_offset(abbrevs, entry.die_offset())
            .expect("DIE offset should be valid");
        assert!(cursor.next_dfs().expect("Should parse DIE").is_some());
    }
}

#[test]
fn test_parse_self_debug_pubtypes() {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_pubtypes = read_section("debug_pubtypes");
    let debug_pubtypes = DebugPubTypes::new(&debug_pubtypes, LittleEndian);

    let mut units = HashMap::new();
    let mut abbrevs = HashMap::new();
    let mut pubtypes = debug_pubtypes.items();
    while let Some(entry) = pubtypes.next().expect("Should parse pubtype OK") {
        let unit_offset = entry.unit_header_offset();
        let unit = units.entry(unit_offset).or_insert_with(|| {
            debug_info
                .header_from_offset(unit_offset)
                .expect("Should parse unit header OK")
        });
        let abbrev_offset = unit.debug_abbrev_offset();
        let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| {
            debug_abbrev
                .abbreviations(abbrev_offset)
                .expect("Should parse abbreviations OK")
        });
        let mut cursor = unit.entries_at_offset(abbrevs, entry.die_offset())
            .expect("DIE offset should be valid");
        assert!(cursor.next_dfs().expect("Should parse DIE").is_some());
    }
}

// Because `.eh_frame` doesn't contain address sizes, we need to assume the
// native word size, so this test is only valid on 64-bit machines (as the
// `.eh_frame` fixture data was created on a 64-bit machine).
#[cfg(target_pointer_width = "64")]
#[test]
fn test_parse_self_eh_frame() {
    use gimli::{BaseAddresses, CieOrFde, EhFrame, UnwindSection};

    let eh_frame = read_section("eh_frame");
    let eh_frame = EhFrame::new(&eh_frame, LittleEndian);

    let bases = BaseAddresses::default().set_cfi(0).set_data(0).set_text(0);
    let mut entries = eh_frame.entries(&bases);
    while let Some(entry) = entries.next().expect("Should parse CFI entry OK") {
        match entry {
            CieOrFde::Cie(cie) => {
                let mut instrs = cie.instructions();
                while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") {
                    // TODO FITZGEN
                }
            }
            CieOrFde::Fde(partial) => {
                let fde = partial
                    .parse(|offset| eh_frame.cie_from_offset(&bases, offset))
                    .expect("Should be able to get CIE for FDE");

                let mut instrs = fde.instructions();
                while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") {
                    // TODO FITZGEN
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate semver;
extern crate crates_index;
extern crate tempdir;

use tempdir::TempDir;
use crates_index::Index;
use semver::Version;

// This test checks to see if every existing crate parses successfully. Important to not break the
// Rust universe!

#[cfg(feature = "ci")]
#[test]
fn test_regressions() {
    let dir = TempDir::new("semver").unwrap();
    let index = Index::new(dir.into_path());
    index.clone().unwrap();

    for krate in index.crates() {
        for version in krate.versions() {
            let v = version.version();
            assert!(Version::parse(v).is_ok(), "failed: {} ({})", version.name(), v);
        }
    }
}
<commit_msg>Fix warnings<commit_after>extern crate semver;
extern crate crates_index;
extern crate tempdir;

// This test checks to see if every existing crate parses successfully. Important to not break the
// Rust universe!

#[cfg(feature = "ci")]
#[test]
fn test_regressions() {
    use tempdir::TempDir;
    use crates_index::Index;
    use semver::Version;

    let dir = TempDir::new("semver").unwrap();
    let index = Index::new(dir.into_path());
    index.clone().unwrap();

    for krate in index.crates() {
        for version in krate.versions() {
            let v = version.version();
            assert!(Version::parse(v).is_ok(), "failed: {} ({})", version.name(), v);
        }
    }
}
<|endoftext|>


<commit_before>extern crate elementtree;

use elementtree::{Element, QName};

#[test]
fn test_basics() {
    let root = Element::from_reader(r#"<?xml version="1.0"?>
    <root>
        <list>
            <item>Item 1</item>Tail 1
            <item>Item 2</item>Tail 2
            <item>Item 3</item>Tail 3
        </list>
    </root>
    "#.as_bytes()).unwrap();

    let list = root.find("list").unwrap();
    assert_eq!(list.tag(), &QName::from("list"));

    let items: Vec<_> = list.children().map(|x| x.text()).collect();
    assert_eq!(items.as_slice(), &["Item 1", "Item 2", "Item 3"]);

    let tails: Vec<_> = list.children().map(|x| x.tail().trim()).collect();
    assert_eq!(tails.as_slice(), &["Tail 1", "Tail 2", "Tail 3"]);
}

#[test]
fn test_attributes() {
    let root = Element::from_reader(r#"<?xml version="1.0"?>
    <root>
        <list a="1" b="2" c="3">
            <item attr="foo1"/>
            <item attr="foo2"/>
            <item attr="foo3"/>
        </list>
    </root>
    "#.as_bytes()).unwrap();

    let list = root.find("list").unwrap();
    assert_eq!(list.tag(), &QName::from("list"));

    let items: Vec<_> = list.children().map(|x| x.get_attr("attr").unwrap_or("")).collect();
    assert_eq!(items.as_slice(), &["foo1", "foo2", "foo3"]);

    let mut attrs: Vec<_> = list.attrs().map(|(k, v)| format!("{}={}", k, v)).collect();
    attrs.sort();
    assert_eq!(attrs.iter().map(|x| x.as_str()).collect::<Vec<_>>(), vec!["a=1", "b=2", "c=3"]);

    assert_eq!(list.attr_count(), 3);
}

#[test]
fn test_namespaces() {
    let root = Element::from_reader(r#"<?xml version="1.0"?>
    <root xmlns="root" xmlns:foo="child">
        <list a="1" b="2" c="3">
            <item foo:attr="foo1"/>
            <item foo:attr="foo2"/>
            <item foo:attr="foo3"/>
        </list>
    </root>
    "#.as_bytes()).unwrap();

    let list = root.find("{root}list").unwrap();
    assert_eq!(list.tag(), &QName::from("{root}list"));

    let items: Vec<_> = list.children().map(|x| x.get_attr("{child}attr").unwrap_or("")).collect();
    assert_eq!(items.as_slice(), &["foo1", "foo2", "foo3"]);

    let mut attrs: Vec<_> = list.attrs().map(|(k, v)| format!("{}={}", k, v)).collect();
    attrs.sort();
    assert_eq!(attrs.iter().map(|x| x.as_str()).collect::<Vec<_>>(), vec!["a=1", "b=2", "c=3"]);

    assert_eq!(list.attr_count(), 3);
}
<commit_msg>Added entity test<commit_after>extern crate elementtree;

use elementtree::{Element, QName};

#[test]
fn test_basics() {
    let root = Element::from_reader(r#"<?xml version="1.0"?>
    <root>
        <list>
            <item>Item 1</item>Tail 1
            <item>Item 2</item>Tail 2
            <item>Item 3</item>Tail 3
        </list>
    </root>
    "#.as_bytes()).unwrap();

    let list = root.find("list").unwrap();
    assert_eq!(list.tag(), &QName::from("list"));

    let items: Vec<_> = list.children().map(|x| x.text()).collect();
    assert_eq!(items.as_slice(), &["Item 1", "Item 2", "Item 3"]);

    let tails: Vec<_> = list.children().map(|x| x.tail().trim()).collect();
    assert_eq!(tails.as_slice(), &["Tail 1", "Tail 2", "Tail 3"]);
}

#[test]
fn test_attributes() {
    let root = Element::from_reader(r#"<?xml version="1.0"?>
    <root>
        <list a="1" b="2" c="3">
            <item attr="foo1"/>
            <item attr="foo2"/>
            <item attr="foo3"/>
        </list>
    </root>
    "#.as_bytes()).unwrap();

    let list = root.find("list").unwrap();
    assert_eq!(list.tag(), &QName::from("list"));

    let items: Vec<_> = list.children().map(|x| x.get_attr("attr").unwrap_or("")).collect();
    assert_eq!(items.as_slice(), &["foo1", "foo2", "foo3"]);

    let mut attrs: Vec<_> = list.attrs().map(|(k, v)| format!("{}={}", k, v)).collect();
    attrs.sort();
    assert_eq!(attrs.iter().map(|x| x.as_str()).collect::<Vec<_>>(), vec!["a=1", "b=2", "c=3"]);

    assert_eq!(list.attr_count(), 3);
}

#[test]
fn test_namespaces() {
    let root = Element::from_reader(r#"<?xml version="1.0"?>
    <root xmlns="root" xmlns:foo="child">
        <list a="1" b="2" c="3">
            <item foo:attr="foo1"/>
            <item foo:attr="foo2"/>
            <item foo:attr="foo3"/>
        </list>
    </root>
    "#.as_bytes()).unwrap();

    let list = root.find("{root}list").unwrap();
    assert_eq!(list.tag(), &QName::from("{root}list"));

    let items: Vec<_> = list.children().map(|x| x.get_attr("{child}attr").unwrap_or("")).collect();
    assert_eq!(items.as_slice(), &["foo1", "foo2", "foo3"]);

    let mut attrs: Vec<_> = list.attrs().map(|(k, v)| format!("{}={}", k, v)).collect();
    attrs.sort();
    assert_eq!(attrs.iter().map(|x| x.as_str()).collect::<Vec<_>>(), vec!["a=1", "b=2", "c=3"]);

    assert_eq!(list.attr_count(), 3);
}

#[test]
fn test_entities() {
    let root = Element::from_reader(r#"<?xml version="1.0"?>
    <root>S</root>
    "#.as_bytes()).unwrap();

    assert_eq!(root.text(), "S");
}
<|endoftext|>


<commit_before>extern crate tiny_http;

use std::net::TcpStream;
use std::io::{Read, Write};
use std::thread;

#[allow(dead_code)]
mod support;

#[test]
fn connection_close_header() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "GET / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n")).unwrap();
    thread::sleep_ms(1000);

    (write!(client, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n")).unwrap();

    // if the connection was not closed, this will err with timeout
    // client.set_keepalive(Some(1)).unwrap(); FIXME: reenable this
    let mut out = Vec::new();
    client.read_to_end(&mut out).unwrap();
}

#[test]
fn http_1_0_connection_close() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n")).unwrap();

    // if the connection was not closed, this will err with timeout
    // client.set_keepalive(Some(1)).unwrap(); FIXME: reenable this
    let mut out = Vec::new();
    client.read_to_end(&mut out).unwrap();
}

/* FIXME: uncomment and fix
#[test]
fn detect_connection_closed() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "GET / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n")).unwrap();
    thread::sleep_ms(1000);

    client.shutdown(Shutdown::Write);

    // if the connection was not closed, this will err with timeout
    client.set_keepalive(Some(1)).unwrap(); FIXME: reenable this
    let mut out = Vec::new();
    client.read_to_end(&mut out).unwrap();
}
*/

#[test]
fn poor_network_test() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "G")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "ET /he")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "llo HT")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "TP/1.")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "1\r\nHo")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "st: localho")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "st\r\nConnec")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "tion: close\r")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "\n\r")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "\n")).unwrap();

    // client.set_keepalive(Some(2)).unwrap(); FIXME: reenable this
    let mut data = String::new();
    client.read_to_string(&mut data).unwrap();
    assert!(data.ends_with("hello world"));
}

#[test]
fn pipelining_test() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")).unwrap();
    (write!(client, "GET /hello HTTP/1.1\r\nHost: localhost\r\n\r\n")).unwrap();
    (write!(client, "GET /world HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n")).unwrap();

    // client.set_keepalive(Some(2)).unwrap(); FIXME: reenable this
    let mut data = String::new();
    client.read_to_string(&mut data).unwrap();
    assert_eq!(data.split("hello world").count(), 4);
}

#[test]
fn server_crash_results_in_response() {
    let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
    let port = server.server_addr().port();
    let mut client = TcpStream::connect(("127.0.0.1", port)).unwrap();

    thread::spawn(move || {
        server.recv().unwrap();
        // oops, server crash
    });

    (write!(client, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n")).unwrap();

    // client.set_keepalive(Some(2)).unwrap(); FIXME: reenable this
    let mut content = String::new();
    client.read_to_string(&mut content).unwrap();
    assert!(&content[9..].starts_with("5"));   // 5xx status code
}

#[test]
fn responses_reordered() {
    let (server, mut client) = support::new_one_server_one_client();

    (write!(client, "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")).unwrap();
    (write!(client, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n")).unwrap();

    thread::spawn(move || {
        let rq1 = server.recv().unwrap();
        let rq2 = server.recv().unwrap();

        thread::spawn(move || {
            rq2.respond(tiny_http::Response::from_string(format!("second request"))).unwrap();
        });

        thread::sleep_ms(100);

        thread::spawn(move || {
            rq1.respond(tiny_http::Response::from_string(format!("first request"))).unwrap();
        });
    });

    // client.set_keepalive(Some(2)).unwrap(); FIXME: reenable this
    let mut content = String::new();
    client.read_to_string(&mut content).unwrap();
    assert!(content.ends_with("second request"));
}

/* FIXME: uncomment and fix
#[test]
fn connection_timeout() {
    let (server, mut client) = {
        let server = tiny_http::ServerBuilder::new()
            .with_client_connections_timeout(3000)
            .with_random_port().build().unwrap();
        let port = server.server_addr().port();
        let client = TcpStream::connect(("127.0.0.1", port)).unwrap();
        (server, client)
    };

    let (tx_stop, rx_stop) = mpsc::channel();

    // executing server in parallel
    thread::spawn(move || {
        loop {
            server.try_recv();
            thread::sleep_ms(100);
            if rx_stop.try_recv().is_ok() { break }
        }
    });

    // waiting for the 408 response
    let mut content = String::new();
    client.read_to_string(&mut content).unwrap();
    assert!(&content[9..].starts_with("408"));

    // stopping server
    tx_stop.send(());
}
*/
<commit_msg>Uncomment and fix detect_connection_closed test<commit_after>extern crate tiny_http;

use std::net::{TcpStream, Shutdown};
use std::io::{Read, Write};
use std::thread;

#[allow(dead_code)]
mod support;

#[test]
fn connection_close_header() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "GET / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n")).unwrap();
    thread::sleep_ms(1000);

    (write!(client, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n")).unwrap();

    // if the connection was not closed, this will err with timeout
    // client.set_keepalive(Some(1)).unwrap(); FIXME: reenable this
    let mut out = Vec::new();
    client.read_to_end(&mut out).unwrap();
}

#[test]
fn http_1_0_connection_close() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n")).unwrap();

    // if the connection was not closed, this will err with timeout
    // client.set_keepalive(Some(1)).unwrap(); FIXME: reenable this
    let mut out = Vec::new();
    client.read_to_end(&mut out).unwrap();
}

#[test]
fn detect_connection_closed() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "GET / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n")).unwrap();
    thread::sleep_ms(1000);

    client.shutdown(Shutdown::Write).unwrap();

    // if the connection was not closed, this will err with timeout
    // client.set_keepalive(Some(1)).unwrap(); FIXME: reenable this
    let mut out = Vec::new();
    client.read_to_end(&mut out).unwrap();
}

#[test]
fn poor_network_test() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "G")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "ET /he")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "llo HT")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "TP/1.")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "1\r\nHo")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "st: localho")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "st\r\nConnec")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "tion: close\r")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "\n\r")).unwrap();
    thread::sleep_ms(100);
    (write!(client, "\n")).unwrap();

    // client.set_keepalive(Some(2)).unwrap(); FIXME: reenable this
    let mut data = String::new();
    client.read_to_string(&mut data).unwrap();
    assert!(data.ends_with("hello world"));
}

#[test]
fn pipelining_test() {
    let mut client = support::new_client_to_hello_world_server();

    (write!(client, "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")).unwrap();
    (write!(client, "GET /hello HTTP/1.1\r\nHost: localhost\r\n\r\n")).unwrap();
    (write!(client, "GET /world HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n")).unwrap();

    // client.set_keepalive(Some(2)).unwrap(); FIXME: reenable this
    let mut data = String::new();
    client.read_to_string(&mut data).unwrap();
    assert_eq!(data.split("hello world").count(), 4);
}

#[test]
fn server_crash_results_in_response() {
    let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
    let port = server.server_addr().port();
    let mut client = TcpStream::connect(("127.0.0.1", port)).unwrap();

    thread::spawn(move || {
        server.recv().unwrap();
        // oops, server crash
    });

    (write!(client, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n")).unwrap();

    // client.set_keepalive(Some(2)).unwrap(); FIXME: reenable this
    let mut content = String::new();
    client.read_to_string(&mut content).unwrap();
    assert!(&content[9..].starts_with("5"));   // 5xx status code
}

#[test]
fn responses_reordered() {
    let (server, mut client) = support::new_one_server_one_client();

    (write!(client, "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")).unwrap();
    (write!(client, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n")).unwrap();

    thread::spawn(move || {
        let rq1 = server.recv().unwrap();
        let rq2 = server.recv().unwrap();

        thread::spawn(move || {
            rq2.respond(tiny_http::Response::from_string(format!("second request"))).unwrap();
        });

        thread::sleep_ms(100);

        thread::spawn(move || {
            rq1.respond(tiny_http::Response::from_string(format!("first request"))).unwrap();
        });
    });

    // client.set_keepalive(Some(2)).unwrap(); FIXME: reenable this
    let mut content = String::new();
    client.read_to_string(&mut content).unwrap();
    assert!(content.ends_with("second request"));
}

/* FIXME: uncomment and fix
#[test]
fn connection_timeout() {
    let (server, mut client) = {
        let server = tiny_http::ServerBuilder::new()
            .with_client_connections_timeout(3000)
            .with_random_port().build().unwrap();
        let port = server.server_addr().port();
        let client = TcpStream::connect(("127.0.0.1", port)).unwrap();
        (server, client)
    };

    let (tx_stop, rx_stop) = mpsc::channel();

    // executing server in parallel
    thread::spawn(move || {
        loop {
            server.try_recv();
            thread::sleep_ms(100);
            if rx_stop.try_recv().is_ok() { break }
        }
    });

    // waiting for the 408 response
    let mut content = String::new();
    client.read_to_string(&mut content).unwrap();
    assert!(&content[9..].starts_with("408"));

    // stopping server
    tx_stop.send(());
}
*/
<|endoftext|>


<commit_before>
extern crate centralgithook;
use centralgithook::*;
#[allow(dead_code)]
mod helpers;
extern crate git2;
extern crate tempdir;
use tempdir::TempDir;

fn sorted(mut v: Vec<String>) -> Vec<String>
{
    v.sort();
    v
}

#[test]
fn test_find_all_subtrees()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);
    let subdirs = scratch.find_all_subdirs(&head.as_commit().unwrap().tree().unwrap());
    assert_eq!(0, subdirs.len());

    repo.add_file("bla/foo");
    let head = scratch.transfer(&repo.commit("2"), &repo.path);
    let subdirs = scratch.find_all_subdirs(&head.as_commit().unwrap().tree().unwrap());
    assert_eq!(vec![
        format!("bla"),
    ],
               sorted(subdirs));

    repo.add_file("a/b/c/d/foo");
    let head = scratch.transfer(&repo.commit("2"), &repo.path);
    let subdirs = scratch.find_all_subdirs(&head.as_commit().unwrap().tree().unwrap());
    assert_eq!(vec![
        format!("a"),
        format!("a/b"),
        format!("a/b/c"),
        format!("a/b/c/d"),
        format!("bla"),
    ],
               sorted(subdirs));

    repo.add_file("a/b/c/.bla/foo");
    let head = scratch.transfer(&repo.commit("2"), &repo.path);
    let subdirs = scratch.find_all_subdirs(&head.as_commit().unwrap().tree().unwrap());
    assert_eq!(vec![
        format!("a"),
        format!("a/b"),
        format!("a/b/c"),
        format!("a/b/c/d"),
        format!("bla"),
    ],
               sorted(subdirs));
}

fn split_subdir_ref(repo: &helpers::TestRepo, module: &str, newrev: git2::Oid) -> Option<git2::Oid>
{
    repo.shell.command("rm -Rf refs/original");
    repo.shell.command("rm -Rf .git-rewrite");

    repo.repo.set_head_detached(newrev).expect("can't detatch head");;

    repo.shell.command(&format!("git filter-branch --subdirectory-filter {}/ -- HEAD",
                                module));

    return Some(repo.repo
        .revparse_single("HEAD")
        .expect("can't find rewritten branch")
        .id());
}

#[test]
fn test_split_subdir_one_commit()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()),
               scratch.split_subdir("foo", head.id()));
}

#[test]
fn test_split_subdir_two_commits()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("foo/bla_bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()),
               scratch.split_subdir("foo", head.id()));
}

#[test]
fn test_split_subdir_three_commits_middle_unrelated()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("x");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("foo/bla_bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()),
               scratch.split_subdir("foo", head.id()));
}

#[test]
fn test_split_subdir_three_commits_first_unrelated()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("x");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("foo/bla_bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()),
               scratch.split_subdir("foo", head.id()));
}

#[test]
fn test_split_subdir_branch()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("foo_on_master"), &repo.path);
    repo.shell.command("git checkout -b tmp");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_on_tmp"), &repo.path);
    repo.shell.command("git checkout master");
    repo.shell.command("git merge tmp --no-ff -m foo_merge");

    let head = scratch.transfer(&repo.rev("HEAD"), &repo.path);

    let actual = scratch.split_subdir("foo", head.id());

    scratch.repo.reference("refs/heads/actual", actual.unwrap(), true, "x").expect("err 3");

    let shell = Shell { cwd: scratch.repo.path().to_path_buf() };

    // shell.command("gitk --all");
    assert_eq!(fparents(&shell.command("git log --pretty=format:%s-@%p --topo-order")),
               fparents(&repo.shell
                   .command("git log --pretty=format:%s-@%p --topo-order --grep=foo_ ")));
}

#[test]
fn test_split_subdir_branch_unrelated()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("foo_on_master"), &repo.path);
    repo.shell.command("git checkout -b tmp");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_on_tmp"), &repo.path);
    repo.add_file("x/bla_bla");
    let _ = scratch.transfer(&repo.commit("x_on_tmp"), &repo.path);
    repo.shell.command("git checkout master");
    repo.shell.command("git merge tmp --no-ff -m foo_merge");

    let head = scratch.transfer(&repo.rev("HEAD"), &repo.path);

    let actual = scratch.split_subdir("foo", head.id());

    scratch.repo.reference("refs/heads/actual", actual.unwrap(), true, "x").expect("err 3");

    let shell = Shell { cwd: scratch.repo.path().to_path_buf() };

    // shell.command("gitk --all");
    assert_eq!(fparents(&shell.command("git log --pretty=format:%s-@%p --topo-order")),
               fparents(&repo.shell
                   .command("git log --pretty=format:%s-@%p --topo-order --grep=foo_ ")));
}

#[test]
fn test_split_merge_identical_to_first()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/initial");
    let _ = scratch.transfer(&repo.commit("foo_initial_on_master"), &repo.path);

    repo.shell.command("git branch tmp");

    repo.shell.command("git checkout master");
    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("foo_second_on_master"), &repo.path);

    repo.shell.command("git checkout tmp");
    repo.add_file("foo/bla");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_second_on_tmp"), &repo.path);

    repo.shell.command("git checkout master");
    repo.shell.command("git merge tmp --no-ff -m foo_merge");

    println!("{}", repo.shell.command("git log"));
    let head = scratch.transfer(&repo.rev("HEAD"), &repo.path);

    let actual = scratch.split_subdir("foo", head.id());

    let shell = Shell { cwd: scratch.repo.path().to_path_buf() };
    scratch.repo.reference("refs/heads/actual", actual.unwrap(), true, "x").expect("err 2");

    // shell.command("gitk --all");
    assert_eq!(fparents(&shell.command("git log --pretty=format:%s-@%p --topo-order")),
               fparents(&repo.shell
                   .command("git log --pretty=format:%s-@%p --topo-order --grep=foo_ ")));
}

fn fparents(s: &str) -> String
{
    let mut o = String::new();
    for l in s.lines() {
        let spl = l.split("@");
        let m = spl.clone().nth(0).unwrap();
        let p = spl.clone().nth(1).unwrap();
        o.push_str(&format!("{}@{}\n",
                            m,
                            match p.len()/6 {
                                2 => "merge",
                                1 => "normal",
                                _ => "orphan",
                            }));
    }

    // println!("fparents:\n{}",o); assert!(false);

    return o;
}

#[test]
fn test_split_merge_identical_to_second()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("foo_on_master"), &repo.path);

    repo.shell.command("git checkout -b tmp");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_on_tmp"), &repo.path);

    repo.shell.command("git checkout master");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_on_master_2"), &repo.path);
    repo.shell.command("git merge tmp --no-ff -m foo_merge");
    println!("{}", repo.shell.command("git log"));
    let head = scratch.transfer(&repo.rev("HEAD"), &repo.path);

    let actual = scratch.split_subdir("foo", head.id());

    let shell = Shell { cwd: scratch.repo.path().to_path_buf() };
    scratch.repo.reference("refs/heads/actual", actual.unwrap(), true, "x").expect("err 2");

    // shell.command("gitk --all");
    assert_eq!(fparents(&shell.command("git log --pretty=format:%s-@%p --topo-order")),
               fparents(&repo.shell
                   .command("git log --pretty=format:%s-@%p --topo-order --grep=foo_ ")));
}
<commit_msg>add test<commit_after>
extern crate centralgithook;
use centralgithook::*;
#[allow(dead_code)]
mod helpers;
extern crate git2;
extern crate tempdir;
use tempdir::TempDir;

fn sorted(mut v: Vec<String>) -> Vec<String>
{
    v.sort();
    v
}

#[test]
fn test_find_all_subtrees()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);
    let subdirs = scratch.find_all_subdirs(&head.as_commit().unwrap().tree().unwrap());
    assert_eq!(0, subdirs.len());

    repo.add_file("bla/foo");
    let head = scratch.transfer(&repo.commit("2"), &repo.path);
    let subdirs = scratch.find_all_subdirs(&head.as_commit().unwrap().tree().unwrap());
    assert_eq!(vec![
        format!("bla"),
    ],
               sorted(subdirs));

    repo.add_file("a/b/c/d/foo");
    let head = scratch.transfer(&repo.commit("2"), &repo.path);
    let subdirs = scratch.find_all_subdirs(&head.as_commit().unwrap().tree().unwrap());
    assert_eq!(vec![
        format!("a"),
        format!("a/b"),
        format!("a/b/c"),
        format!("a/b/c/d"),
        format!("bla"),
    ],
               sorted(subdirs));

    repo.add_file("a/b/c/.bla/foo");
    let head = scratch.transfer(&repo.commit("2"), &repo.path);
    let subdirs = scratch.find_all_subdirs(&head.as_commit().unwrap().tree().unwrap());
    assert_eq!(vec![
        format!("a"),
        format!("a/b"),
        format!("a/b/c"),
        format!("a/b/c/d"),
        format!("bla"),
    ],
               sorted(subdirs));
}

fn split_subdir_ref(repo: &helpers::TestRepo, module: &str, newrev: git2::Oid) -> Option<git2::Oid>
{
    repo.shell.command("rm -Rf refs/original");
    repo.shell.command("rm -Rf .git-rewrite");

    repo.repo.set_head_detached(newrev).expect("can't detatch head");;

    repo.shell.command(&format!("git filter-branch --subdirectory-filter {}/ -- HEAD",
                                module));

    return Some(repo.repo
        .revparse_single("HEAD")
        .expect("can't find rewritten branch")
        .id());
}

#[test]
fn test_split_subdir_one_commit()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()),
               scratch.split_subdir("foo", head.id()));
}

#[test]
fn test_split_subdir_two_commits()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("foo/bla_bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()),
               scratch.split_subdir("foo", head.id()));
}

#[test]
fn test_split_subdir_two_commits_first_empty()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.shell.command("git commit --allow-empty -m empty");
    repo.add_file("foo/bla_bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.shell.command("git log");

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()), scratch.split_subdir("foo", head.id()));
    // assert!(false);
}

#[test]
fn test_split_subdir_three_commits_middle_unrelated()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("x");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("foo/bla_bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()),
               scratch.split_subdir("foo", head.id()));
}

#[test]
fn test_split_subdir_three_commits_first_unrelated()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("x");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("1"), &repo.path);
    repo.add_file("foo/bla_bla");
    let head = scratch.transfer(&repo.commit("1"), &repo.path);

    assert_eq!(split_subdir_ref(&repo, "foo", head.id()),
               scratch.split_subdir("foo", head.id()));
}

#[test]
fn test_split_subdir_branch()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("foo_on_master"), &repo.path);
    repo.shell.command("git checkout -b tmp");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_on_tmp"), &repo.path);
    repo.shell.command("git checkout master");
    repo.shell.command("git merge tmp --no-ff -m foo_merge");

    let head = scratch.transfer(&repo.rev("HEAD"), &repo.path);

    let actual = scratch.split_subdir("foo", head.id());

    scratch.repo.reference("refs/heads/actual", actual.unwrap(), true, "x").expect("err 3");

    let shell = Shell { cwd: scratch.repo.path().to_path_buf() };

    // shell.command("gitk --all");
    assert_eq!(fparents(&shell.command("git log --pretty=format:%s-@%p --topo-order")),
               fparents(&repo.shell
                   .command("git log --pretty=format:%s-@%p --topo-order --grep=foo_ ")));
}

#[test]
fn test_split_subdir_branch_unrelated()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("foo_on_master"), &repo.path);
    repo.shell.command("git checkout -b tmp");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_on_tmp"), &repo.path);
    repo.add_file("x/bla_bla");
    let _ = scratch.transfer(&repo.commit("x_on_tmp"), &repo.path);
    repo.shell.command("git checkout master");
    repo.shell.command("git merge tmp --no-ff -m foo_merge");

    let head = scratch.transfer(&repo.rev("HEAD"), &repo.path);

    let actual = scratch.split_subdir("foo", head.id());

    scratch.repo.reference("refs/heads/actual", actual.unwrap(), true, "x").expect("err 3");

    let shell = Shell { cwd: scratch.repo.path().to_path_buf() };

    // shell.command("gitk --all");
    assert_eq!(fparents(&shell.command("git log --pretty=format:%s-@%p --topo-order")),
               fparents(&repo.shell
                   .command("git log --pretty=format:%s-@%p --topo-order --grep=foo_ ")));
}

#[test]
fn test_split_merge_identical_to_first()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/initial");
    let _ = scratch.transfer(&repo.commit("foo_initial_on_master"), &repo.path);

    repo.shell.command("git branch tmp");

    repo.shell.command("git checkout master");
    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("foo_second_on_master"), &repo.path);

    repo.shell.command("git checkout tmp");
    repo.add_file("foo/bla");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_second_on_tmp"), &repo.path);

    repo.shell.command("git checkout master");
    repo.shell.command("git merge tmp --no-ff -m foo_merge");

    println!("{}", repo.shell.command("git log"));
    let head = scratch.transfer(&repo.rev("HEAD"), &repo.path);

    let actual = scratch.split_subdir("foo", head.id());

    let shell = Shell { cwd: scratch.repo.path().to_path_buf() };
    scratch.repo.reference("refs/heads/actual", actual.unwrap(), true, "x").expect("err 2");

    // shell.command("gitk --all");
    assert_eq!(fparents(&shell.command("git log --pretty=format:%s-@%p --topo-order")),
               fparents(&repo.shell
                   .command("git log --pretty=format:%s-@%p --topo-order --grep=foo_ ")));
}

fn fparents(s: &str) -> String
{
    let mut o = String::new();
    for l in s.lines() {
        let spl = l.split("@");
        let m = spl.clone().nth(0).unwrap();
        let p = spl.clone().nth(1).unwrap();
        o.push_str(&format!("{}@{}\n",
                            m,
                            match p.len()/6 {
                                2 => "merge",
                                1 => "normal",
                                _ => "orphan",
                            }));
    }

    // println!("fparents:\n{}",o); assert!(false);

    return o;
}

#[test]
fn test_split_merge_identical_to_second()
{
    let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
    let host = helpers::TestHost::new();
    let scratch = Scratch::new(&td.path().join("scratch"), &host);
    let repo = helpers::TestRepo::new(&td.path().join("repo"));

    repo.add_file("foo/bla");
    let _ = scratch.transfer(&repo.commit("foo_on_master"), &repo.path);

    repo.shell.command("git checkout -b tmp");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_on_tmp"), &repo.path);

    repo.shell.command("git checkout master");
    repo.add_file("foo/bla_bla");
    let _ = scratch.transfer(&repo.commit("foo_on_master_2"), &repo.path);
    repo.shell.command("git merge tmp --no-ff -m foo_merge");
    println!("{}", repo.shell.command("git log"));
    let head = scratch.transfer(&repo.rev("HEAD"), &repo.path);

    let actual = scratch.split_subdir("foo", head.id());

    let shell = Shell { cwd: scratch.repo.path().to_path_buf() };
    scratch.repo.reference("refs/heads/actual", actual.unwrap(), true, "x").expect("err 2");

    // shell.command("gitk --all");
    assert_eq!(fparents(&shell.command("git log --pretty=format:%s-@%p --topo-order")),
               fparents(&repo.shell
                   .command("git log --pretty=format:%s-@%p --topo-order --grep=foo_ ")));
}
<|endoftext|>