From a062f8704731821b591887f27e7ce9fb7515b29f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Feb 2015 18:18:06 -0800 Subject: Update to std::io --- tests/all.rs | 5 +-- tests/channel.rs | 29 +++++++++------- tests/session.rs | 23 ++++++++----- tests/sftp.rs | 19 +++++++---- tests/tempdir.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 147 insertions(+), 31 deletions(-) create mode 100644 tests/tempdir.rs (limited to 'tests') diff --git a/tests/all.rs b/tests/all.rs index 491e4d4..a8d50af 100644 --- a/tests/all.rs +++ b/tests/all.rs @@ -1,17 +1,18 @@ #![deny(warnings)] -#![feature(old_io, core, old_path, env)] +#![feature(io, core, path, env, net, fs)] extern crate ssh2; extern crate libc; use std::env; -use std::old_io::TcpStream; +use std::net::TcpStream; mod agent; mod session; mod channel; mod knownhosts; mod sftp; +mod tempdir; pub fn socket() -> TcpStream { TcpStream::connect("127.0.0.1:22").unwrap() diff --git a/tests/channel.rs b/tests/channel.rs index 254f0fe..38a39aa 100644 --- a/tests/channel.rs +++ b/tests/channel.rs @@ -1,4 +1,5 @@ -use std::old_io::{TcpListener, Listener, Acceptor, TcpStream}; +use std::io::prelude::*; +use std::net::{TcpStream, TcpListener}; use std::thread; #[test] @@ -20,8 +21,9 @@ fn reading_data() { let (_tcp, sess) = ::authed_session(); let mut channel = sess.channel_session().unwrap(); channel.exec("echo foo").unwrap(); - let output = channel.read_to_string().unwrap(); - assert_eq!(output.as_slice(), "foo\n"); + let mut output = String::new(); + channel.read_to_string(&mut output).unwrap(); + assert_eq!(output, "foo\n"); } #[test] @@ -31,8 +33,9 @@ fn writing_data() { channel.exec("read foo && echo $foo").unwrap(); channel.write_all(b"foo\n").unwrap(); channel.close().unwrap(); - let output = channel.read_to_string().unwrap(); - assert_eq!(output.as_slice(), "foo\n"); + let mut output = String::new(); + channel.read_to_string(&mut output).unwrap(); + assert_eq!(output, "foo\n"); } #[test] @@ -42,8 +45,9 @@ fn eof() { channel.adjust_receive_window(10, false).unwrap(); channel.exec("read foo").unwrap(); channel.send_eof().unwrap(); - let output = channel.read_to_string().unwrap(); - assert_eq!(output.as_slice(), ""); + let mut output = String::new(); + channel.read_to_string(&mut output).unwrap(); + assert_eq!(output, ""); } #[test] @@ -64,11 +68,10 @@ fn setenv() { #[test] fn direct() { - let mut l = TcpListener::bind("127.0.0.1:0").unwrap(); - let addr = l.socket_name().unwrap(); - let mut a = l.listen().unwrap(); + let a = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = a.socket_addr().unwrap(); let t = thread::scoped(move|| { - let mut s = a.accept().unwrap(); + let mut s = a.accept().unwrap().0; let b = &mut [0, 0, 0]; s.read(b).unwrap(); assert_eq!(b.as_slice(), [1, 2, 3].as_slice()); @@ -76,7 +79,7 @@ fn direct() { }); let (_tcp, sess) = ::authed_session(); let mut channel = sess.channel_direct_tcpip("127.0.0.1", - addr.port, None).unwrap(); + addr.port(), None).unwrap(); channel.write_all(&[1, 2, 3]).unwrap(); let r = &mut [0, 0, 0]; channel.read(r).unwrap(); @@ -90,7 +93,7 @@ fn forward() { let (mut listen, port) = sess.channel_forward_listen(39249, None, None) .unwrap(); let t = thread::scoped(move|| { - let mut s = TcpStream::connect(("127.0.0.1", port)).unwrap(); + let mut s = TcpStream::connect(&("127.0.0.1", port)).unwrap(); let b = &mut [0, 0, 0]; s.read(b).unwrap(); assert_eq!(b.as_slice(), [1, 2, 3].as_slice()); diff --git a/tests/session.rs b/tests/session.rs index 8a97710..36f8c7c 100644 --- a/tests/session.rs +++ b/tests/session.rs @@ -1,5 +1,8 @@ use std::env; -use std::old_io::{self, File, TempDir}; +use std::fs::File; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; +use tempdir::TempDir; use ssh2::{Session, MethodType, HashType}; @@ -53,10 +56,12 @@ fn keepalive() { #[test] fn scp_recv() { let (_tcp, sess) = ::authed_session(); - let (mut ch, _) = sess.scp_recv(&Path::new(".ssh/authorized_keys")).unwrap(); - let data = ch.read_to_string().unwrap(); - let p = Path::new(env::var("HOME").unwrap()).join(".ssh/authorized_keys"); - let expected = File::open(&p).read_to_string().unwrap(); + let (mut ch, _) = sess.scp_recv(Path::new(".ssh/authorized_keys")).unwrap(); + let mut data = String::new(); + ch.read_to_string(&mut data).unwrap(); + let p = PathBuf::new(&env::var("HOME").unwrap()).join(".ssh/authorized_keys"); + let mut expected = String::new(); + File::open(&p).unwrap().read_to_string(&mut expected).unwrap(); assert!(data == expected); } @@ -64,10 +69,10 @@ fn scp_recv() { fn scp_send() { let td = TempDir::new("test").unwrap(); let (_tcp, sess) = ::authed_session(); - let mut ch = sess.scp_send(&td.path().join("foo"), - old_io::USER_FILE, 6, None).unwrap(); + let mut ch = sess.scp_send(&td.path().join("foo"), 0o644, 6, None).unwrap(); ch.write_all(b"foobar").unwrap(); drop(ch); - let actual = File::open(&td.path().join("foo")).read_to_end().unwrap(); - assert_eq!(actual.as_slice(), b"foobar"); + let mut actual = Vec::new(); + File::open(&td.path().join("foo")).unwrap().read_to_end(&mut actual).unwrap(); + assert_eq!(actual, b"foobar"); } diff --git a/tests/sftp.rs b/tests/sftp.rs index d3b8042..c0940a5 100644 --- a/tests/sftp.rs +++ b/tests/sftp.rs @@ -1,5 +1,7 @@ -use std::old_io::{self, fs, File, TempDir}; -use std::old_io::fs::PathExtensions; +use std::io::prelude::*; +use std::fs::{self, File}; + +use tempdir::TempDir; #[test] fn smoke() { @@ -11,22 +13,25 @@ fn smoke() { fn ops() { let td = TempDir::new("foo").unwrap(); File::create(&td.path().join("foo")).unwrap(); - fs::mkdir(&td.path().join("bar"), old_io::USER_DIR).unwrap(); + fs::create_dir(&td.path().join("bar")).unwrap(); let (_tcp, sess) = ::authed_session(); let sftp = sess.sftp().unwrap(); sftp.opendir(&td.path().join("bar")).unwrap(); let mut foo = sftp.open(&td.path().join("foo")).unwrap(); - sftp.mkdir(&td.path().join("bar2"), old_io::USER_DIR).unwrap(); + sftp.mkdir(&td.path().join("bar2"), 0o755).unwrap(); assert!(td.path().join("bar2").is_dir()); sftp.rmdir(&td.path().join("bar2")).unwrap(); sftp.create(&td.path().join("foo5")).unwrap().write_all(b"foo").unwrap(); - assert_eq!(File::open(&td.path().join("foo5")).read_to_end().unwrap(), - b"foo".to_vec()); + let mut v = Vec::new(); + File::open(&td.path().join("foo5")).unwrap().read_to_end(&mut v).unwrap(); + assert_eq!(v, b"foo"); assert_eq!(sftp.stat(&td.path().join("foo")).unwrap().size, Some(0)); - assert_eq!(foo.read_to_end().unwrap(), Vec::new()); + v.truncate(0); + foo.read_to_end(&mut v).unwrap(); + assert_eq!(v, Vec::new()); sftp.symlink(&td.path().join("foo"), &td.path().join("foo2")).unwrap(); diff --git a/tests/tempdir.rs b/tests/tempdir.rs new file mode 100644 index 0000000..cad52c6 --- /dev/null +++ b/tests/tempdir.rs @@ -0,0 +1,102 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate rand; + +use std::env; +use std::io::{self, Error, ErrorKind}; +use std::fs; +use std::path::{self, PathBuf, AsPath}; +use self::rand::{thread_rng, Rng}; + +/// A wrapper for a path to temporary directory implementing automatic +/// scope-based deletion. +pub struct TempDir { + path: Option, +} + +// How many times should we (re)try finding an unused random name? It should be +// enough that an attacker will run out of luck before we run out of patience. +const NUM_RETRIES: u32 = 1 << 31; +// How many characters should we include in a random file name? It needs to +// be enough to dissuade an attacker from trying to preemptively create names +// of that length, but not so huge that we unnecessarily drain the random number +// generator of entropy. +const NUM_RAND_CHARS: usize = 12; + +impl TempDir { + /// Attempts to make a temporary directory inside of `tmpdir` whose name + /// will have the prefix `prefix`. The directory will be automatically + /// deleted once the returned wrapper is destroyed. + /// + /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] // rand usage + pub fn new_in(tmpdir: &P, prefix: &str) + -> io::Result { + let tmpdir = tmpdir.as_path(); + assert!(tmpdir.is_absolute()); + + let mut rng = thread_rng(); + for _ in 0..NUM_RETRIES { + let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect(); + let leaf = if prefix.len() > 0 { + format!("{}.{}", prefix, suffix) + } else { + // If we're given an empty string for a prefix, then creating a + // directory starting with "." would lead to it being + // semi-invisible on some systems. + suffix + }; + let path = tmpdir.join(&leaf); + match fs::create_dir(&path) { + Ok(_) => return Ok(TempDir { path: Some(path) }), + Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {} + Err(e) => return Err(e) + } + } + + Err(Error::new(ErrorKind::PathAlreadyExists, + "too many temporary directories already exist", + None)) + } + + /// Attempts to make a temporary directory inside of `env::temp_dir()` whose + /// name will have the prefix `prefix`. The directory will be automatically + /// deleted once the returned wrapper is destroyed. + /// + /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] + pub fn new(prefix: &str) -> io::Result { + TempDir::new_in(&env::temp_dir(), prefix) + } + + /// Access the wrapped `std::path::Path` to the temporary directory. + pub fn path(&self) -> &path::Path { + self.path.as_ref().unwrap() + } + + fn cleanup_dir(&mut self) -> io::Result<()> { + match self.path { + Some(ref p) => fs::remove_dir_all(p), + None => Ok(()) + } + } +} + +impl Drop for TempDir { + fn drop(&mut self) { + let _ = self.cleanup_dir(); + } +} + +// the tests for this module need to change the path using change_dir, +// and this doesn't play nicely with other tests so these unit tests are located +// in src/test/run-pass/tempfile.rs + -- cgit v1.2.3