servo: Merge #4702 - Bug #3219 - Assign hostfile using the HOST_FILE environment variable (from shinglyu:bug3219); r=jdm

This is a fix for bug #3219 . This patch allows the user to specify a disposiable hostfile using the `HOST_FILE` environment variable. Therefore, we can run tests on test servers without actually changing the system hostfile.

Source-Repo: https://github.com/servo/servo
Source-Revision: 237cdee9e462bc7b070d9fe1a7722ad961ff25c2
This commit is contained in:
Shing Lyu 2015-02-05 20:30:45 -07:00
Родитель 8637f836b7
Коммит 4c4a49bac3
2 изменённых файлов: 102 добавлений и 2 удалений

Просмотреть файл

@ -25,6 +25,31 @@ use url::Url;
use std::borrow::ToOwned;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thunk::Invoke;
use std::collections::HashMap;
use std::io::{BufferedReader, File};
use std::mem;
use std::os;
#[cfg(test)]
use std::io::{Listener, Acceptor, TimedOut};
#[cfg(test)]
use std::io::net::tcp::TcpListener;
static mut HOST_TABLE: Option<*mut HashMap<String, String>> = None;
pub fn global_init() {
if let Some(host_file_path) = os::getenv("HOST_FILE") {
//TODO: handle bad file path and corrupted file
let path = Path::new(host_file_path);
let mut file = BufferedReader::new(File::open(&path));
if let Ok(lines) = file.read_to_string(){
unsafe {
let host_table: *mut HashMap<String, String> = mem::transmute(parse_hostfile(lines.as_slice()));
HOST_TABLE = Some(host_table);
}
}
}
}
pub enum ControlMsg {
/// Request the data associated with a particular URL
@ -203,6 +228,29 @@ pub fn new_resource_task(user_agent: Option<String>) -> ResourceTask {
setup_chan
}
pub fn parse_hostfile(hostfile_content: &str) -> Box<HashMap<String, String>> {
let mut host_table = HashMap::new();
let lines: Vec<&str> = hostfile_content.split('\n').collect();
for line in lines.iter() {
let ip_host: Vec<&str> = line.split(' ').collect();
if ip_host.len() == 2 {
host_table.insert(ip_host[1].to_owned(), ip_host[0].to_owned());
}
}
box host_table
}
pub fn replace_hosts(mut load_data: LoadData, host_table: *mut HashMap<String, String>) -> LoadData {
if let Some(h) = load_data.url.domain_mut() {
unsafe {
if let Some(ip) = (*host_table).get(h) {
*h = ip.clone();
}
}
}
return load_data;
}
struct ResourceManager {
from_client: Receiver<ControlMsg>,
user_agent: Option<String>,
@ -252,8 +300,13 @@ impl ResourceManager {
}
}
fn load(&mut self, load_data: LoadData) {
let mut load_data = load_data;
fn load(&mut self, mut load_data: LoadData) {
unsafe {
if let Some(host_table) = HOST_TABLE {
load_data = replace_hosts(load_data, host_table);
}
}
self.user_agent.as_ref().map(|ua| load_data.headers.set(UserAgent(ua.clone())));
let senders = ResponseSenders {
immediate_consumer: self.sniffer_task.clone(),
@ -334,3 +387,45 @@ fn test_bad_scheme() {
}
resource_task.send(ControlMsg::Exit);
}
#[test]
fn test_parse_hostfile() {
let mock_host_file_content = "127.0.0.1 foo.bar.com\n127.0.0.2 servo.test.server";
let host_table = parse_hostfile(mock_host_file_content);
assert_eq!(2, (*host_table).len());
assert_eq!("127.0.0.1".to_owned(), *host_table.get(&"foo.bar.com".to_owned()).unwrap());
assert_eq!("127.0.0.2".to_owned(), *host_table.get(&"servo.test.server".to_owned()).unwrap());
}
//TODO: test mal-formed file content
#[test]
fn test_replace_hosts() {
let mut host_table_box = box HashMap::new();
host_table_box.insert("foo.bar.com".to_owned(), "127.0.0.1".to_owned());
host_table_box.insert("servo.test.server".to_owned(), "127.0.0.2".to_owned());
let host_table: *mut HashMap<String, String> = unsafe {mem::transmute(host_table_box)};
//Start the TCP server
let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
let port = listener.socket_name().unwrap().port;
let mut acceptor = listener.listen().unwrap();
//Start the resource task and make a request to our TCP server
let resource_task = new_resource_task(None);
let (start_chan, _) = channel();
let mut raw_url: String = "http://foo.bar.com:".to_string();
raw_url = raw_url + port.to_string().as_slice();
let url = Url::parse(raw_url.as_slice()).unwrap();
resource_task.send(ControlMsg::Load(replace_hosts(LoadData::new(url, start_chan), host_table)));
match acceptor.accept() {
Ok(..) => assert!(true, "received request"),
Err(ref e) if e.kind == TimedOut => { assert!(false, "timed out!"); },
Err(_) => assert!(false, "error")
}
resource_task.send(ControlMsg::Exit);
drop(acceptor);
}

Просмотреть файл

@ -12,6 +12,7 @@ extern crate libc;
extern crate servo;
extern crate time;
extern crate util;
extern crate "net" as servo_net;
#[cfg(not(test))]
extern crate "glutin_app" as app;
@ -29,6 +30,9 @@ use libc::c_int;
#[cfg(not(test))]
use util::opts;
#[cfg(not(test))]
use servo_net::resource_task;
#[cfg(not(test))]
use servo::Browser;
#[cfg(not(test))]
@ -113,6 +117,7 @@ fn setup_logging() {
fn main() {
if opts::from_cmdline_args(get_args().as_slice()) {
setup_logging();
resource_task::global_init();
let window = if opts::get().headless {
None