Rename testing crate to tools, and add README

master
Manos Pitsidianakis 2020-08-27 17:18:58 +03:00
parent a37faf0bec
commit 6302d9d618
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
10 changed files with 263 additions and 6 deletions

View File

@ -70,7 +70,7 @@ opt-level = "z"
debug = false debug = false
[workspace] [workspace]
members = ["melib", "testing", ] members = ["melib", "tools", ]
[features] [features]
default = ["sqlite3", "notmuch", "regexp", "smtp"] default = ["sqlite3", "notmuch", "regexp", "smtp"]

View File

@ -1,5 +1,5 @@
[package] [package]
name = "testing" name = "tools"
version = "0.4.1" version = "0.4.1"
authors = ["Manos Pitsidianakis <el13635@mail.ntua.gr>"] authors = ["Manos Pitsidianakis <el13635@mail.ntua.gr>"]
workspace = ".." workspace = ".."
@ -14,8 +14,12 @@ name = "mboxparse"
path = "src/mboxparse.rs" path = "src/mboxparse.rs"
[[bin]] [[bin]]
name = "imapconn" name = "imapshell"
path = "src/imap_conn.rs" path = "src/imapshell.rs"
[[bin]]
name = "smtp_conn"
path = "src/smtp_conn.rs"
[dependencies] [dependencies]
melib = { path = "../melib", version = "*", features = ["debug-tracing", "unicode_algorithms"] } melib = { path = "../melib", version = "*", features = ["debug-tracing", "unicode_algorithms"] }

46
tools/README.md 100644
View File

@ -0,0 +1,46 @@
# meli tools
This crate holds a collection of small binaries used for meli development. Of note is `imapshell` which opens a shell to an IMAP server for the user to play with.
## imapshell
```shell
cd tools/
cargo build --bin imapshell
# Usage: imap_conn server_hostname server_username server_password server_port
rlwrap ./target/debug/imapshell "mail.domain.tld" "epilys@domain.tld" "hunter2" 143
```
Example session:
First, the IMAP connections performs its own non-interactive setup:
```text
[2020-08-27 17:11:33]["main"] melib/src/backends/imap/connection.rs:459_25: sent: M1 CAPABILITY
[2020-08-27 17:11:33]["main"] melib/src/backends/imap/connection.rs:408_33: &ret[last_line_idx..] = "M1 OK Pre-login capabilities listed, post-login capabilities have more.\r\n"
[2020-08-27 17:11:33]["main"] melib/src/backends/imap/connection.rs:459_25: sent: M2 LOGIN "epilys@domain.tld" "hunter2"
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/connection.rs:459_25: sent: M3 CAPABILITY
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/connection.rs:408_33: &ret[last_line_idx..] = "M3 OK Capability completed (0.000 + 0.120 + 0.119 secs).\r\n"
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/connection.rs:459_25: sent: M4 ENABLE CONDSTORE
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/connection.rs:408_33: &ret[last_line_idx..] = "M4 OK Enabled (0.000 + 0.120 + 0.119 secs).\r\n"
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/protocol_parser.rs:261_9: &val = "M4 OK Enabled (0.000 + 0.120 + 0.119 secs).\r\n"
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/connection.rs:459_25: sent: M5 COMPRESS DEFLATE
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/connection.rs:408_33: &ret[last_line_idx..] = "M5 OK Begin compression (0.000 + 0.127 + 0.126 secs).\r\n"
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/protocol_parser.rs:261_9: &val = "M5 OK Begin compression (0.000 + 0.127 + 0.126 secs).\r\n"
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/protocol_parser.rs:261_9: &val = "M5 OK Begin compression (0.000 + 0.127 + 0.126 secs).\r\n"
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/connection.rs:459_25: sent: M6 NOOP
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/connection.rs:408_33: &ret[last_line_idx..] = "M6 OK NOOP completed (0.000 + 0.000 secs).\r\n"
[2020-08-27 17:11:34]["main"] melib/src/backends/imap/protocol_parser.rs:261_9: &val = "M6 OK NOOP completed (0.000 + 0.000 secs).\r\n"
```
Then, input is read line by line and sent to the server. You don't have to prefix the commands with a unique ID, that is taken care of by the tool. Example command and reply:
```text
LIST "" "INBOX"
[2020-08-27 17:14:53]["main"] melib/src/backends/imap/connection.rs:717_9: send_command
[2020-08-27 17:14:53]["main"] melib/src/backends/imap/connection.rs:437_9: stream send_command()
[2020-08-27 17:14:53]["main"] melib/src/backends/imap/connection.rs:459_25: sent: M8 LIST "" "INBOX"
[2020-08-27 17:14:53]["main"] melib/src/backends/imap/connection.rs:729_13: send_command ok
[2020-08-27 17:14:53]["main"] melib/src/backends/imap.rs:1241_21: out: * LIST (\HasChildren) "." INBOX
M8 OK List completed (0.000 + 0.000 secs).
```

View File

@ -0,0 +1,7 @@
extern crate ui;
use ui::terminal::embed::create_pty;
fn main() -> std::io::Result<()> {
create_pty().unwrap();
Ok(())
}

View File

@ -8,7 +8,7 @@ use melib::{AccountSettings, BackendEventConsumer};
/// ///
/// # Example invocation: /// # Example invocation:
/// ```sh /// ```sh
/// ./imap_conn server_hostname server_username server_password server_port"); /// ./imapshell server_hostname server_username server_password server_port");
/// ``` /// ```
/// ///
/// `danger_accept_invalid_certs` is turned on by default, so no certificate validation is performed. /// `danger_accept_invalid_certs` is turned on by default, so no certificate validation is performed.
@ -16,7 +16,7 @@ use melib::{AccountSettings, BackendEventConsumer};
fn main() -> Result<()> { fn main() -> Result<()> {
let mut args = std::env::args().skip(1).collect::<Vec<String>>(); let mut args = std::env::args().skip(1).collect::<Vec<String>>();
if args.len() != 4 { if args.len() != 4 {
eprintln!("Usage: imap_conn server_hostname server_username server_password server_port"); eprintln!("Usage: imapshell server_hostname server_username server_password server_port");
std::process::exit(1); std::process::exit(1);
} }

View File

@ -0,0 +1,150 @@
extern crate melib;
use melib::Result;
use melib::StackVec;
use std::str::FromStr;
extern crate text_processing;
use text_processing::line_break::*;
use text_processing::Graphemes;
fn cost(i: usize, j: usize, width: usize, minima: &Vec<usize>, offsets: &Vec<usize>) -> usize {
let w = offsets[j] + j - offsets[i] - i - 1;
if w > width {
return 65536 * (w - width);
}
minima[i] + (width - w) * (width - w)
}
fn smawk(
rows: &mut StackVec<usize>,
columns: &mut StackVec<usize>,
minima: &mut Vec<usize>,
breaks: &mut Vec<usize>,
width: usize,
offsets: &Vec<usize>,
) {
let mut stack = StackVec::new();
let mut i = 0;
while i < rows.len() {
if stack.len() > 0 {
let c = columns[stack.len() - 1];
if cost(*stack.iter().last().unwrap(), c, width, minima, offsets)
< cost(rows[i], c, width, minima, offsets)
{
if stack.len() < columns.len() {
stack.push(rows[i]);
}
i += 1;
} else {
stack.pop();
}
} else {
stack.push(rows[i]);
i += 1;
}
}
let rows = &mut stack;
if columns.len() > 1 {
let mut odd_columns = columns.iter().skip(1).step_by(2).cloned().collect();
smawk(rows, &mut odd_columns, minima, breaks, width, offsets);
for (i, o) in odd_columns.into_iter().enumerate() {
columns.set(2 * i + 1, o);
}
}
let mut i = 0;
let mut j = 0;
while j < columns.len() {
let end = if j + 1 < columns.len() {
breaks[columns[j + 1]]
} else {
*rows.iter().last().unwrap()
};
let c = cost(rows[i], columns[j], width, minima, offsets);
if c < minima[columns[j]] {
minima[columns[j]] = c;
breaks[columns[j]] = rows[i];
}
if rows[i] < end {
i += 1;
} else {
j += 2;
}
}
}
fn linear(text: &str, width: usize) -> Vec<String> {
let mut words = text.split_whitespace().collect::<Vec<&str>>();
let breaks = LineBreakCandidateIter::new(text).collect::<Vec<(usize, LineBreakCandidate)>>();
let count = words.len();
let mut minima = vec![std::usize::MAX - 1; count + 1];
minima[0] = 0;
let mut offsets = Vec::with_capacity(words.len());
offsets.push(0);
for w in words.iter() {
offsets.push(offsets.iter().last().unwrap() + w.grapheme_len());
}
let mut breaks = vec![0; count + 1];
let mut n = count + 1;
let mut i = 1;
let mut offset = 0;
loop {
let r = std::cmp::min(n, 2 * i);
let edge = i + offset;
smawk(
&mut (offset..edge).collect(),
&mut (edge..(r + offset)).collect(),
&mut minima,
&mut breaks,
width,
&offsets,
);
let x = minima[r - 1 + offset];
let mut for_was_broken = false;
for j in i..(r - 1) {
let y = cost(j + offset, r - 1 + offset, width, &minima, &offsets);
if y <= x {
n -= j;
i = 1;
offset += j;
for_was_broken = true;
break;
}
}
if !for_was_broken {
if r == n {
break;
}
i *= 2;
}
}
let mut lines = Vec::new();
let mut j = count;
while j > 0 {
let mut line = words[breaks[j]..j].join(" ");
lines.push(line);
j = breaks[j];
}
lines.reverse();
lines
}
fn main() -> Result<()> {
let text = std::fs::read_to_string(std::env::args().nth(1).unwrap())?;
let width = usize::from_str(&std::env::args().nth(2).unwrap()).unwrap();
//let paragraphs = text.split("\n\n").collect::<Vec<&str>>();
for _ in 0..(width - 1) {
print!(" ");
}
println!("|");
for l in linear(&text, width) {
println!("{}", l);
}
for _ in 0..(width - 1) {
print!(" ");
}
println!("|");
Ok(())
}

View File

@ -0,0 +1,50 @@
extern crate melib;
use melib::futures;
use melib::smol;
use melib::smtp::*;
use melib::Result;
/// Opens an interactive shell on an IMAP server. Suggested use is with rlwrap(1)
///
/// # Example invocation:
/// ```sh
/// ./imap_conn server_hostname server_username server_password server_port");
/// ```
///
/// `danger_accept_invalid_certs` is turned on by default, so no certificate validation is performed.
fn main() -> Result<()> {
let conf = SmtpServerConf {
hostname: "smtp1.ntua.gr".into(),
port: 587,
security: SmtpSecurity::StartTLS {
danger_accept_invalid_certs: false,
},
extensions: SmtpExtensionSupport::default(),
auth: SmtpAuth::Auto {
username: "el13635".into(),
password: Password::CommandEval(
"gpg2 --no-tty -q -d ~/.passwords/msmtp/ntua.gpg".into(),
),
require_auth: true,
},
envelope_from: String::new(),
};
for _ in 0..1 {
std::thread::spawn(|| smol::run(futures::future::pending::<()>()));
}
let mut conn = futures::executor::block_on(SmtpConnection::new_connection(conf)).unwrap();
futures::executor::block_on(conn.mail_transaction(
r##"To: pr.birch@gmail.com
Auto-Submitted: auto-generated
Subject: Fwd: *** SMTP TEST #2 information ***
From: Manos <el13635@mail.ntua.gr>
Message-Id: <E1hSjnr-0003fN-RL2@postretch>
Date: Mon, 13 Jul 2020 15:02:15 +0300
postretch : May 20 18:02:00 : epilys : user NOT in sudoers ; TTY=pts/13 ; PWD=/tmp/db-project ; USER=postgres ; COMMAND=/usr/bin/dropdb Prescriptions-R-X"##,
)).unwrap();
Ok(())
}