move test binaries to examples/

These aren't installed and are only used for manual testing,
so there's no reason to force them to be built all the time.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller
2020-06-16 13:32:23 +02:00
parent 929a13b357
commit d19c96d507
15 changed files with 0 additions and 0 deletions

View File

@ -1,82 +0,0 @@
use anyhow::{Error};
// chacha20-poly1305
fn rate_test(name: &str, bench: &dyn Fn() -> usize) {
print!("{:<20} ", name);
let start = std::time::SystemTime::now();
let duration = std::time::Duration::new(1, 0);
let mut bytes = 0;
loop {
bytes += bench();
let elapsed = start.elapsed().unwrap();
if elapsed > duration { break; }
}
let elapsed = start.elapsed().unwrap();
let elapsed = (elapsed.as_secs() as f64) +
(elapsed.subsec_millis() as f64)/1000.0;
println!("{:>8.1} MB/s", (bytes as f64)/(elapsed*1024.0*1024.0));
}
fn main() -> Result<(), Error> {
let input = proxmox::sys::linux::random_data(1024*1024)?;
rate_test("crc32", &|| {
let mut crchasher = crc32fast::Hasher::new();
crchasher.update(&input);
let _checksum = crchasher.finalize();
input.len()
});
rate_test("zstd", &|| {
zstd::block::compress(&input, 1).unwrap();
input.len()
});
rate_test("sha256", &|| {
openssl::sha::sha256(&input);
input.len()
});
let key = proxmox::sys::linux::random_data(32)?;
let iv = proxmox::sys::linux::random_data(16)?;
let cipher = openssl::symm::Cipher::aes_256_gcm();
rate_test("aes-256-gcm", &|| {
let mut tag = [0u8;16];
openssl::symm::encrypt_aead(
cipher,
&key,
Some(&iv),
b"",
&input,
&mut tag).unwrap();
input.len()
});
let cipher = openssl::symm::Cipher::chacha20_poly1305();
rate_test("chacha20-poly1305", &|| {
let mut tag = [0u8;16];
openssl::symm::encrypt_aead(
cipher,
&key,
Some(&iv[..12]),
b"",
&input,
&mut tag).unwrap();
input.len()
});
Ok(())
}

View File

@ -1,93 +0,0 @@
use anyhow::{Error};
use proxmox::api::{*, cli::*};
#[api(
input: {
properties: {
text: {
type: String,
description: "Some text.",
}
}
},
)]
/// Echo command. Print the passed text.
///
/// Returns: nothing
fn echo_command(
text: String,
) -> Result<(), Error> {
println!("{}", text);
Ok(())
}
#[api(
input: {
properties: {
verbose: {
type: Boolean,
optional: true,
description: "Verbose output.",
}
}
},
)]
/// Hello command.
///
/// Returns: nothing
fn hello_command(
verbose: Option<bool>,
) -> Result<(), Error> {
if verbose.unwrap_or(false) {
println!("Hello, how are you!");
} else {
println!("Hello!");
}
Ok(())
}
#[api(input: { properties: {} })]
/// Quit command. Exit the program.
///
/// Returns: nothing
fn quit_command() -> Result<(), Error> {
println!("Goodbye.");
std::process::exit(0);
}
fn cli_definition() -> CommandLineInterface {
let cmd_def = CliCommandMap::new()
.insert("quit", CliCommand::new(&API_METHOD_QUIT_COMMAND))
.insert("hello", CliCommand::new(&API_METHOD_HELLO_COMMAND))
.insert("echo", CliCommand::new(&API_METHOD_ECHO_COMMAND)
.arg_param(&["text"])
)
.insert_help();
CommandLineInterface::Nested(cmd_def)
}
fn main() -> Result<(), Error> {
let helper = CliHelper::new(cli_definition());
let mut rl = rustyline::Editor::<CliHelper>::new();
rl.set_helper(Some(helper));
while let Ok(line) = rl.readline("# prompt: ") {
let helper = rl.helper().unwrap();
let args = shellword_split(&line)?;
let rpcenv = CliEnvironment::new();
let _ = handle_command(helper.cmd_def(), "", args, rpcenv, None);
rl.add_history_entry(line);
}
Ok(())
}

View File

@ -1,68 +0,0 @@
use std::io::Write;
use anyhow::{Error};
use chrono::{DateTime, Utc};
use proxmox_backup::client::{HttpClient, HttpClientOptions, BackupReader};
pub struct DummyWriter {
bytes: usize,
}
impl Write for DummyWriter {
fn write(&mut self, data: &[u8]) -> Result<usize, std::io::Error> {
self.bytes += data.len();
Ok(data.len())
}
fn flush(&mut self) -> Result<(), std::io::Error> {
Ok(())
}
}
async fn run() -> Result<(), Error> {
let host = "localhost";
let username = "root@pam";
let options = HttpClientOptions::new()
.interactive(true)
.ticket_cache(true);
let client = HttpClient::new(host, username, options)?;
let backup_time = "2019-06-28T10:49:48Z".parse::<DateTime<Utc>>()?;
let client = BackupReader::start(client, None, "store2", "host", "elsa", backup_time, true)
.await?;
let start = std::time::SystemTime::now();
let mut bytes = 0;
for _ in 0..100 {
let mut writer = DummyWriter { bytes: 0 };
client.speedtest(&mut writer).await?;
println!("Received {} bytes", writer.bytes);
bytes += writer.bytes;
}
let elapsed = start.elapsed().unwrap();
let elapsed = (elapsed.as_secs() as f64) +
(elapsed.subsec_millis() as f64)/1000.0;
println!("Downloaded {} bytes, {} MB/s", bytes, (bytes as f64)/(elapsed*1024.0*1024.0));
Ok(())
}
#[tokio::main]
async fn main() {
if let Err(err) = proxmox_backup::tools::runtime::main(run()) {
eprintln!("ERROR: {}", err);
}
println!("DONE");
}

View File

@ -1,14 +0,0 @@
use anyhow::{Error};
use proxmox::api::format::*;
use proxmox_backup::api2;
fn main() -> Result<(), Error> {
let api = api2::backup::BACKUP_API_ROUTER;
dump_api(&mut std::io::stdout(), &api, ".", 0)?;
Ok(())
}

View File

@ -1,20 +0,0 @@
use anyhow::{Error};
use proxmox::api::format::*;
use proxmox::api::cli::*;
use proxmox_backup::backup::catalog_shell_cli;
fn main() -> Result<(), Error> {
match catalog_shell_cli() {
CommandLineInterface::Nested(map) => {
let usage = generate_nested_usage("", &map, DocumentationFormat::ReST);
println!("{}", usage);
}
_ => unreachable!(),
}
Ok(())
}

View File

@ -1,14 +0,0 @@
use anyhow::{Error};
use proxmox::api::format::dump_api;
use proxmox_backup::api2;
fn main() -> Result<(), Error> {
let api = api2::reader::READER_API_ROUTER;
dump_api(&mut std::io::stdout(), &api, ".", 0)?;
Ok(())
}

View File

@ -1,62 +0,0 @@
use anyhow::{bail, Error};
use std::thread;
use std::path::PathBuf;
use std::io::Write;
// tar handle files that shrink during backup, by simply padding with zeros.
//
// this binary run multiple thread which writes some large files, then truncates
// them in a loop.
// # tar cf test.tar ./dyntest1/
// tar: dyntest1/testfile0.dat: File shrank by 2768972800 bytes; padding with zeros
// tar: dyntest1/testfile17.dat: File shrank by 2899853312 bytes; padding with zeros
// tar: dyntest1/testfile2.dat: File shrank by 3093422080 bytes; padding with zeros
// tar: dyntest1/testfile7.dat: File shrank by 2833252864 bytes; padding with zeros
// # pxar create test.pxar ./dyntest1/
// Error: detected shrunk file "./dyntest1/testfile0.dat" (22020096 < 12679380992)
fn create_large_file(path: PathBuf) {
println!("TEST {:?}", path);
let mut file = std::fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(&path).unwrap();
let buffer = vec![0u8; 64*1024];
loop {
for _ in 0..64 {
file.write_all(&buffer).unwrap();
}
file.sync_all().unwrap();
//println!("TRUNCATE {:?}", path);
file.set_len(0).unwrap();
}
}
fn main() -> Result<(), Error> {
let base = PathBuf::from("dyntest1");
let _ = std::fs::create_dir(&base);
let mut handles = vec![];
for i in 0..20 {
let base = base.clone();
handles.push(thread::spawn(move || {
create_large_file(base.join(format!("testfile{}.dat", i)));
}));
}
for h in handles {
if h.join().is_err() {
bail!("join failed");
}
}
Ok(())
}

View File

@ -1,108 +0,0 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use anyhow::{Error};
use futures::future::TryFutureExt;
use futures::stream::Stream;
use tokio::net::TcpStream;
// Simple H2 client to test H2 download speed using h2server.rs
struct Process {
body: h2::RecvStream,
trailers: bool,
bytes: usize,
}
impl Future for Process {
type Output = Result<usize, Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let this = self.get_mut();
loop {
if this.trailers {
match futures::ready!(this.body.poll_trailers(cx)) {
Ok(Some(trailers)) => println!("trailers: {:?}", trailers),
Ok(None) => (),
Err(err) => return Poll::Ready(Err(Error::from(err))),
}
println!("Received {} bytes", this.bytes);
return Poll::Ready(Ok(this.bytes));
} else {
match futures::ready!(Pin::new(&mut this.body).poll_next(cx)) {
Some(Ok(chunk)) => {
this.body.flow_control().release_capacity(chunk.len())?;
this.bytes += chunk.len();
// println!("GOT FRAME {}", chunk.len());
},
Some(Err(err)) => return Poll::Ready(Err(Error::from(err))),
None => {
this.trailers = true;
},
}
}
}
}
}
fn send_request(
mut client: h2::client::SendRequest<bytes::Bytes>,
) -> impl Future<Output = Result<usize, Error>> {
println!("sending request");
let request = http::Request::builder()
.uri("http://localhost/")
.body(())
.unwrap();
let (response, _stream) = client.send_request(request, true).unwrap();
response
.map_err(Error::from)
.and_then(|response| {
Process { body: response.into_body(), trailers: false, bytes: 0 }
})
}
fn main() -> Result<(), Error> {
proxmox_backup::tools::runtime::main(run())
}
async fn run() -> Result<(), Error> {
let start = std::time::SystemTime::now();
let conn = TcpStream::connect(std::net::SocketAddr::from(([127,0,0,1], 8008)))
.await?;
let (client, h2) = h2::client::Builder::new()
.initial_connection_window_size(1024*1024*1024)
.initial_window_size(1024*1024*1024)
.max_frame_size(4*1024*1024)
.handshake(conn)
.await?;
tokio::spawn(async move {
if let Err(err) = h2.await {
println!("GOT ERR={:?}", err);
}
});
let mut bytes = 0;
for _ in 0..2000 {
bytes += send_request(client.clone()).await?;
}
let elapsed = start.elapsed().unwrap();
let elapsed = (elapsed.as_secs() as f64) +
(elapsed.subsec_millis() as f64)/1000.0;
println!("Downloaded {} bytes, {} MB/s", bytes, (bytes as f64)/(elapsed*1024.0*1024.0));
Ok(())
}

View File

@ -1,130 +0,0 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use anyhow::{format_err, Error};
use futures::future::TryFutureExt;
use futures::stream::Stream;
// Simple H2 client to test H2 download speed using h2s-server.rs
struct Process {
body: h2::RecvStream,
trailers: bool,
bytes: usize,
}
impl Future for Process {
type Output = Result<usize, Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let this = self.get_mut();
loop {
if this.trailers {
match futures::ready!(this.body.poll_trailers(cx)) {
Ok(Some(trailers)) => println!("trailers: {:?}", trailers),
Ok(None) => (),
Err(err) => return Poll::Ready(Err(Error::from(err))),
}
println!("Received {} bytes", this.bytes);
return Poll::Ready(Ok(this.bytes));
} else {
match futures::ready!(Pin::new(&mut this.body).poll_next(cx)) {
Some(Ok(chunk)) => {
this.body.flow_control().release_capacity(chunk.len())?;
this.bytes += chunk.len();
// println!("GOT FRAME {}", chunk.len());
},
Some(Err(err)) => return Poll::Ready(Err(Error::from(err))),
None => {
this.trailers = true;
},
}
}
}
}
}
fn send_request(
mut client: h2::client::SendRequest<bytes::Bytes>,
) -> impl Future<Output = Result<usize, Error>> {
println!("sending request");
let request = http::Request::builder()
.uri("http://localhost/")
.body(())
.unwrap();
let (response, _stream) = client.send_request(request, true).unwrap();
response
.map_err(Error::from)
.and_then(|response| {
Process { body: response.into_body(), trailers: false, bytes: 0 }
})
}
fn main() -> Result<(), Error> {
proxmox_backup::tools::runtime::main(run())
}
async fn run() -> Result<(), Error> {
let start = std::time::SystemTime::now();
let conn =
tokio::net::TcpStream::connect(std::net::SocketAddr::from(([127,0,0,1], 8008))).await?;
conn.set_nodelay(true).unwrap();
conn.set_recv_buffer_size(1024*1024).unwrap();
use openssl::ssl::{SslConnector, SslMethod};
let mut ssl_connector_builder = SslConnector::builder(SslMethod::tls()).unwrap();
ssl_connector_builder.set_verify(openssl::ssl::SslVerifyMode::NONE);
let conn =
tokio_openssl::connect(
ssl_connector_builder.build().configure()?,
"localhost",
conn,
)
.await
.map_err(|err| format_err!("connect failed - {}", err))?;
let (client, h2) = h2::client::Builder::new()
.initial_connection_window_size(1024*1024*1024)
.initial_window_size(1024*1024*1024)
.max_frame_size(4*1024*1024)
.handshake(conn)
.await?;
// Spawn a task to run the conn...
tokio::spawn(async move {
if let Err(e) = h2.await {
println!("GOT ERR={:?}", e);
}
});
let mut bytes = 0;
for _ in 0..100 {
match send_request(client.clone()).await {
Ok(b) => {
bytes += b;
}
Err(e) => {
println!("ERROR {}", e);
return Ok(());
}
}
}
let elapsed = start.elapsed().unwrap();
let elapsed = (elapsed.as_secs() as f64) +
(elapsed.subsec_millis() as f64)/1000.0;
println!("Downloaded {} bytes, {} MB/s", bytes, (bytes as f64)/(elapsed*1024.0*1024.0));
Ok(())
}

View File

@ -1,81 +0,0 @@
use std::sync::Arc;
use anyhow::{format_err, Error};
use futures::*;
use hyper::{Request, Response, Body};
use openssl::ssl::{SslMethod, SslAcceptor, SslFiletype};
use tokio::net::{TcpListener, TcpStream};
use proxmox_backup::configdir;
// Simple H2 server to test H2 speed with h2s-client.rs
fn main() -> Result<(), Error> {
proxmox_backup::tools::runtime::main(run())
}
async fn run() -> Result<(), Error> {
let key_path = configdir!("/proxy.key");
let cert_path = configdir!("/proxy.pem");
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
acceptor.set_private_key_file(key_path, SslFiletype::PEM)
.map_err(|err| format_err!("unable to read proxy key {} - {}", key_path, err))?;
acceptor.set_certificate_chain_file(cert_path)
.map_err(|err| format_err!("unable to read proxy cert {} - {}", cert_path, err))?;
acceptor.check_private_key().unwrap();
let acceptor = Arc::new(acceptor.build());
let mut listener = TcpListener::bind(std::net::SocketAddr::from(([127,0,0,1], 8008))).await?;
println!("listening on {:?}", listener.local_addr());
loop {
let (socket, _addr) = listener.accept().await?;
tokio::spawn(handle_connection(socket, Arc::clone(&acceptor))
.map(|res| {
if let Err(err) = res {
eprintln!("Error: {}", err);
}
}));
}
}
async fn handle_connection(
socket: TcpStream,
acceptor: Arc<SslAcceptor>,
) -> Result<(), Error> {
socket.set_nodelay(true).unwrap();
socket.set_send_buffer_size(1024*1024).unwrap();
socket.set_recv_buffer_size(1024*1024).unwrap();
let socket = tokio_openssl::accept(acceptor.as_ref(), socket).await?;
let mut http = hyper::server::conn::Http::new();
http.http2_only(true);
// increase window size: todo - find optiomal size
let max_window_size = (1 << 31) - 2;
http.http2_initial_stream_window_size(max_window_size);
http.http2_initial_connection_window_size(max_window_size);
let service = hyper::service::service_fn(|_req: Request<Body>| {
println!("Got request");
let buffer = vec![65u8; 1024*1024]; // nonsense [A,A,A,A...]
let body = Body::from(buffer);
let response = Response::builder()
.status(http::StatusCode::OK)
.header(http::header::CONTENT_TYPE, "application/octet-stream")
.body(body)
.unwrap();
future::ok::<_, Error>(response)
});
http.serve_connection(socket, service)
.map_err(Error::from)
.await?;
println!("H2 connection CLOSE !");
Ok(())
}

View File

@ -1,51 +0,0 @@
use anyhow::{Error};
use futures::*;
// Simple H2 server to test H2 speed with h2client.rs
use tokio::net::TcpListener;
use tokio::io::{AsyncRead, AsyncWrite};
use proxmox_backup::client::pipe_to_stream::PipeToSendStream;
fn main() -> Result<(), Error> {
proxmox_backup::tools::runtime::main(run())
}
async fn run() -> Result<(), Error> {
let mut listener = TcpListener::bind(std::net::SocketAddr::from(([127,0,0,1], 8008))).await?;
println!("listening on {:?}", listener.local_addr());
loop {
let (socket, _addr) = listener.accept().await?;
tokio::spawn(handle_connection(socket)
.map(|res| {
if let Err(err) = res {
eprintln!("Error: {}", err);
}
}));
}
}
async fn handle_connection<T: AsyncRead + AsyncWrite + Unpin>(socket: T) -> Result<(), Error> {
let mut conn = h2::server::handshake(socket).await?;
println!("H2 connection bound");
while let Some((request, mut respond)) = conn.try_next().await? {
println!("GOT request: {:?}", request);
let response = http::Response::builder()
.status(http::StatusCode::OK)
.body(())
.unwrap();
let send = respond.send_response(response, false).unwrap();
let data = vec![65u8; 1024*1024];
PipeToSendStream::new(bytes::Bytes::from(data), send).await?;
println!("DATA SENT");
}
Ok(())
}

View File

@ -1,116 +0,0 @@
extern crate proxmox_backup;
// also see https://www.johndcook.com/blog/standard_deviation/
use anyhow::{Error};
use std::io::{Read, Write};
use proxmox_backup::backup::*;
struct ChunkWriter {
chunker: Chunker,
last_chunk: usize,
chunk_offset: usize,
chunk_count: usize,
m_old: f64,
m_new: f64,
s_old: f64,
s_new: f64,
}
impl ChunkWriter {
fn new(chunk_size: usize) -> Self {
ChunkWriter {
chunker: Chunker::new(chunk_size),
last_chunk: 0,
chunk_offset: 0,
chunk_count: 0,
m_old: 0.0,
m_new: 0.0,
s_old: 0.0,
s_new: 0.0,
}
}
fn record_stat(&mut self, chunk_size: f64) {
self.chunk_count += 1;
if self.chunk_count == 1 {
self.m_old = chunk_size;
self.m_new = chunk_size;
self.s_old = 0.0;
} else {
self.m_new = self.m_old + (chunk_size - self.m_old)/(self.chunk_count as f64);
self.s_new = self.s_old +
(chunk_size - self.m_old)*(chunk_size - self.m_new);
// set up for next iteration
self.m_old = self.m_new;
self.s_old = self.s_new;
}
let variance = if self.chunk_count > 1 {
self.s_new/((self.chunk_count -1)as f64)
} else { 0.0 };
let std_deviation = variance.sqrt();
let deviation_per = (std_deviation*100.0)/self.m_new;
println!("COUNT {:10} SIZE {:10} MEAN {:10} DEVIATION {:3}%", self.chunk_count, chunk_size, self.m_new as usize, deviation_per as usize);
}
}
impl Write for ChunkWriter {
fn write(&mut self, data: &[u8]) -> std::result::Result<usize, std::io::Error> {
let chunker = &mut self.chunker;
let pos = chunker.scan(data);
if pos > 0 {
self.chunk_offset += pos;
let chunk_size = self.chunk_offset - self.last_chunk;
self.record_stat(chunk_size as f64);
self.last_chunk = self.chunk_offset;
Ok(pos)
} else {
self.chunk_offset += data.len();
Ok(data.len())
}
}
fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
Ok(())
}
}
fn main() -> Result<(), Error> {
let mut file = std::fs::File::open("/dev/urandom")?;
let mut bytes = 0;
let mut buffer = [0u8; 64*1024];
let mut writer = ChunkWriter::new(4096*1024);
loop {
file.read_exact(&mut buffer)?;
bytes += buffer.len();
writer.write_all(&buffer)?;
if bytes > 1024*1024*1024 { break; }
}
Ok(())
}

View File

@ -1,50 +0,0 @@
extern crate proxmox_backup;
//use proxmox_backup::backup::chunker::*;
use proxmox_backup::backup::*;
fn main() {
let mut buffer = Vec::new();
for i in 0..20*1024*1024 {
for j in 0..4 {
let byte = ((i >> (j<<3))&0xff) as u8;
//println!("BYTE {}", byte);
buffer.push(byte);
}
}
let mut chunker = Chunker::new(64*1024);
let count = 5;
let start = std::time::SystemTime::now();
let mut chunk_count = 0;
for _i in 0..count {
let mut pos = 0;
let mut _last = 0;
while pos < buffer.len() {
let k = chunker.scan(&buffer[pos..]);
if k == 0 {
//println!("LAST {}", pos);
break;
} else {
_last = pos;
pos += k;
chunk_count += 1;
//println!("CHUNK {} {}", pos, pos-last);
}
}
}
let elapsed = start.elapsed().unwrap();
let elapsed = (elapsed.as_secs() as f64) +
(elapsed.subsec_millis() as f64)/1000.0;
let mbytecount = ((count*buffer.len()) as f64) / (1024.0*1024.0);
let avg_chunk_size = mbytecount/(chunk_count as f64);
let mbytes_per_sec = mbytecount/elapsed;
println!("SPEED = {} MB/s, avg chunk size = {} KB", mbytes_per_sec, avg_chunk_size*1024.0);
}

View File

@ -1,53 +0,0 @@
use anyhow::{Error};
use futures::*;
extern crate proxmox_backup;
use proxmox_backup::backup::*;
// Test Chunker with real data read from a file.
//
// To generate some test input use:
// # dd if=/dev/urandom of=random-test.dat bs=1M count=1024 iflag=fullblock
//
// Note: I can currently get about 830MB/s
fn main() {
if let Err(err) = proxmox_backup::tools::runtime::main(run()) {
panic!("ERROR: {}", err);
}
}
async fn run() -> Result<(), Error> {
let file = tokio::fs::File::open("random-test.dat").await?;
let stream = tokio_util::codec::FramedRead::new(file, tokio_util::codec::BytesCodec::new())
.map_ok(|bytes| bytes.to_vec())
.map_err(Error::from);
//let chunk_stream = FixedChunkStream::new(stream, 4*1024*1024);
let mut chunk_stream = ChunkStream::new(stream, None);
let start_time = std::time::Instant::now();
let mut repeat = 0;
let mut stream_len = 0;
while let Some(chunk) = chunk_stream.try_next().await? {
if chunk.len() > 16*1024*1024 {
panic!("Chunk too large {}", chunk.len());
}
repeat += 1;
stream_len += chunk.len();
println!("Got chunk {}", chunk.len());
}
let speed = ((stream_len*1_000_000)/(1024*1024))/(start_time.elapsed().as_micros() as usize);
println!("Uploaded {} chunks in {} seconds ({} MB/s).", repeat, start_time.elapsed().as_secs(), speed);
println!("Average chunk size was {} bytes.", stream_len/repeat);
println!("time per request: {} microseconds.", (start_time.elapsed().as_micros())/(repeat as u128));
Ok(())
}

View File

@ -1,37 +0,0 @@
use anyhow::{Error};
use proxmox_backup::client::*;
async fn upload_speed() -> Result<usize, Error> {
let host = "localhost";
let datastore = "store2";
let username = "root@pam";
let options = HttpClientOptions::new()
.interactive(true)
.ticket_cache(true);
let client = HttpClient::new(host, username, options)?;
let backup_time = chrono::Utc::now();
let client = BackupWriter::start(client, datastore, "host", "speedtest", backup_time, false).await?;
println!("start upload speed test");
let res = client.upload_speedtest().await?;
Ok(res)
}
fn main() {
match proxmox_backup::tools::runtime::main(upload_speed()) {
Ok(mbs) => {
println!("average upload speed: {} MB/s", mbs);
}
Err(err) => {
eprintln!("ERROR: {}", err);
}
}
}