use std::io::{Read, Write};
use std::net::TcpListener;
use std::thread;
use rayforce::{q::QConnection, Runtime, Table};
fn long_vec(vals: &[i64]) -> Vec<u8> {
let mut b = vec![7u8, 0u8];
b.extend_from_slice(&(vals.len() as i32).to_le_bytes());
for v in vals {
b.extend_from_slice(&v.to_le_bytes());
}
b
}
fn sym_vec(syms: &[&str]) -> Vec<u8> {
let mut b = vec![11u8, 0u8];
b.extend_from_slice(&(syms.len() as i32).to_le_bytes());
for s in syms {
b.extend_from_slice(s.as_bytes());
b.push(0);
}
b
}
fn table(names: &[&str], cols: &[Vec<u8>]) -> Vec<u8> {
let mut b = vec![98u8, 0u8, 99u8];
b.extend(sym_vec(names));
b.push(0u8); b.push(0u8); b.extend_from_slice(&(cols.len() as i32).to_le_bytes());
for c in cols {
b.extend_from_slice(c);
}
b
}
fn msg(body: &[u8]) -> Vec<u8> {
let size = (8 + body.len()) as u32;
let mut b = vec![1u8, 2u8, 0u8, 0u8]; b.extend_from_slice(&size.to_le_bytes());
b.extend_from_slice(body);
b
}
fn spawn_mock(response: Vec<u8>) -> u16 {
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let port = listener.local_addr().unwrap().port();
thread::spawn(move || {
if let Ok((mut sock, _)) = listener.accept() {
let mut hs = [0u8; 2];
let _ = sock.read_exact(&mut hs);
let _ = sock.write_all(&[3u8]);
let mut hdr = [0u8; 8];
if sock.read_exact(&mut hdr).is_ok() {
let size = u32::from_le_bytes([hdr[4], hdr[5], hdr[6], hdr[7]]) as usize;
let mut body = vec![0u8; size.saturating_sub(8)];
let _ = sock.read_exact(&mut body);
}
let _ = sock.write_all(&response);
}
});
port
}
#[test]
fn q_pulls_a_table() {
let _rt = Runtime::new().unwrap();
let response = msg(&table(
&["seq", "sym"],
&[long_vec(&[1, 2, 3]), sym_vec(&["AAPL", "MSFT", "GOOG"])],
));
let port = spawn_mock(response);
let conn = QConnection::connect("127.0.0.1", port).unwrap();
let v = conn.execute("select from fixmsgs where i > 0").unwrap();
let t = Table::from_value(v).unwrap();
assert_eq!(t.shape(), (3, 2));
assert_eq!(
t.column("seq").unwrap().as_slice::<i64>().unwrap(),
&[1, 2, 3]
);
let sym = t.column("sym").unwrap();
assert_eq!(sym.get(0).unwrap().as_sym().unwrap(), "AAPL");
assert_eq!(sym.get(2).unwrap().as_sym().unwrap(), "GOOG");
}
#[test]
fn q_surfaces_server_error() {
let _rt = Runtime::new().unwrap();
let mut body = vec![(-128i8) as u8];
body.extend_from_slice(b"type\0");
let port = spawn_mock(msg(&body));
let conn = QConnection::connect("127.0.0.1", port).unwrap();
assert!(conn.execute("1+`a").is_err());
}