Benchmarks and test factorization
This commit is contained in:
parent
275d9e73b1
commit
e01f960ddc
|
@ -17,3 +17,10 @@ num_enum = "0.4.1"
|
|||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_bytes = "0.11"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3"
|
||||
|
||||
[[bench]]
|
||||
name = "codec"
|
||||
harness = false
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
# cargo install cargo-watch
|
||||
watch:
|
||||
cargo watch -c -x 'check --all-targets' -x 'test --all-targets -- --nocapture'
|
||||
cargo watch -c -x 'test --all-targets -- --nocapture'
|
||||
|
||||
bench:
|
||||
cargo bench --benches
|
||||
|
||||
clippy-watch:
|
||||
cargo watch -c -x 'clippy --all-targets'
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use preserves::value::{self, decoder, encoder};
|
||||
use preserves::{de, ser};
|
||||
use std::io::Read;
|
||||
|
||||
#[path = "../tests/samples/mod.rs"]
|
||||
mod samples;
|
||||
use samples::TestCases;
|
||||
|
||||
pub fn bench_decoder(c: &mut Criterion) {
|
||||
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
||||
let mut bs = vec![];
|
||||
fh.read_to_end(&mut bs).ok();
|
||||
c.bench_function("decode samples.bin", |b| b.iter(
|
||||
|| decoder::from_bytes(&bs[..]).demand_next().unwrap()));
|
||||
}
|
||||
|
||||
pub fn bench_encoder(c: &mut Criterion) {
|
||||
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
||||
let v = decoder::from_read(&mut fh).demand_next().unwrap();
|
||||
c.bench_function("encode samples.bin", |b| b.iter(|| {
|
||||
let mut bs = vec![];
|
||||
encoder::Encoder::new(&mut bs).write(&v).unwrap();
|
||||
bs
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn bench_de(c: &mut Criterion) {
|
||||
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
||||
let mut bs = vec![];
|
||||
fh.read_to_end(&mut bs).ok();
|
||||
c.bench_function("deserialize samples.bin", |b| b.iter(
|
||||
|| de::from_bytes::<TestCases>(&bs[..]).unwrap()));
|
||||
}
|
||||
|
||||
pub fn bench_ser(c: &mut Criterion) {
|
||||
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
||||
let v: TestCases = de::from_read(&mut fh).unwrap();
|
||||
c.bench_function("serialize samples.bin", |b| b.iter(|| {
|
||||
let mut bs = vec![];
|
||||
ser::to_writer(&mut bs, &v).unwrap();
|
||||
bs
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn bench_decoder_de(c: &mut Criterion) {
|
||||
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
||||
let mut bs = vec![];
|
||||
fh.read_to_end(&mut bs).ok();
|
||||
c.bench_function("decode-then-deserialize samples.bin", |b| b.iter(
|
||||
|| value::de::from_value::<TestCases>(&decoder::from_bytes(&bs[..]).demand_next().unwrap()).unwrap()));
|
||||
}
|
||||
|
||||
pub fn bench_ser_encoder(c: &mut Criterion) {
|
||||
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
||||
let v: TestCases = de::from_read(&mut fh).unwrap();
|
||||
c.bench_function("serialize-then-encode samples.bin", |b| b.iter(|| {
|
||||
let mut bs = vec![];
|
||||
encoder::Encoder::new(&mut bs).write(&value::ser::to_value(&v)).unwrap();
|
||||
bs
|
||||
}));
|
||||
}
|
||||
|
||||
criterion_group!(codec, bench_decoder, bench_encoder);
|
||||
criterion_group!(serde, bench_de, bench_ser);
|
||||
criterion_group!(codec_then_serde, bench_decoder_de, bench_ser_encoder);
|
||||
criterion_main!(codec, serde, codec_then_serde);
|
|
@ -489,97 +489,3 @@ mod serde_tests {
|
|||
assert_eq!(v, y);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod samples_tests {
|
||||
use crate::symbol::Symbol;
|
||||
use crate::error::{is_eof_io_error, is_syntax_io_error};
|
||||
use crate::value::de::from_value as deserialize_from_value;
|
||||
use crate::value::decoder;
|
||||
use crate::value::encoder::encode_bytes;
|
||||
use crate::value::{IOValue, Map};
|
||||
use std::iter::Iterator;
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
struct TestCases {
|
||||
tests: Map<Symbol, TestCase>
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
enum TestCase {
|
||||
Test(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
NondeterministicTest(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
StreamingTest(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
DecodeTest(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
ParseError(String),
|
||||
ParseShort(String),
|
||||
ParseEOF(String),
|
||||
DecodeError(#[serde(with = "serde_bytes")] Vec<u8>),
|
||||
DecodeShort(#[serde(with = "serde_bytes")] Vec<u8>),
|
||||
DecodeEOF(#[serde(with = "serde_bytes")] Vec<u8>),
|
||||
}
|
||||
|
||||
fn decode_all<'de>(bytes: &'de [u8]) -> Result<Vec<IOValue>, std::io::Error> {
|
||||
let d = decoder::from_bytes(bytes);
|
||||
d.collect()
|
||||
}
|
||||
|
||||
#[test] fn run() -> std::io::Result<()> {
|
||||
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
||||
let mut d = decoder::from_read(&mut fh);
|
||||
let tests: TestCases = deserialize_from_value(&d.next().unwrap().unwrap()).unwrap();
|
||||
// println!("{:#?}", tests);
|
||||
|
||||
for (Symbol(ref name), ref case) in tests.tests {
|
||||
println!("{:?} ==> {:?}", name, case);
|
||||
match case {
|
||||
TestCase::Test(ref bin, ref val) => {
|
||||
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
|
||||
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
|
||||
assert_eq!(&encode_bytes(val)?, bin);
|
||||
}
|
||||
TestCase::NondeterministicTest(ref bin, ref val) => {
|
||||
// The test cases in samples.txt are carefully
|
||||
// written so that while strictly
|
||||
// "nondeterministic", the order of keys in
|
||||
// dictionaries follows Preserves order.
|
||||
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
|
||||
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
|
||||
assert_eq!(&encode_bytes(val)?, bin);
|
||||
}
|
||||
TestCase::StreamingTest(ref bin, ref val) => {
|
||||
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
|
||||
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
|
||||
}
|
||||
TestCase::DecodeTest(ref bin, ref val) => {
|
||||
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
|
||||
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
|
||||
}
|
||||
TestCase::ParseError(_) => (),
|
||||
TestCase::ParseShort(_) => (),
|
||||
TestCase::ParseEOF(_) => (),
|
||||
TestCase::DecodeError(ref bin) => {
|
||||
match decode_all(&bin[..]) {
|
||||
Ok(_) => panic!("Unexpected success"),
|
||||
Err(e) => if is_syntax_io_error(&e) {
|
||||
()
|
||||
} else {
|
||||
panic!("Unexpected error {:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
TestCase::DecodeShort(ref bin) => {
|
||||
assert!(if let Err(e) = decoder::from_bytes(bin).next().unwrap() {
|
||||
is_eof_io_error(&e)
|
||||
} else {
|
||||
false
|
||||
})
|
||||
}
|
||||
TestCase::DecodeEOF(ref bin) => {
|
||||
assert!(decoder::from_bytes(bin).next().is_none());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -426,7 +426,10 @@ impl<'de, S: BinarySource<'de>> BinaryReader<'de, S> {
|
|||
fn peek_next_nonannotation_op(&mut self) -> ReaderResult<(Op, u8)> {
|
||||
loop {
|
||||
match decodeop(self.peek()?)? {
|
||||
(Op::Misc(0), 5) => self.skip()?,
|
||||
(Op::Misc(0), 5) => {
|
||||
self.skip()?;
|
||||
self.skip_value()?;
|
||||
},
|
||||
other => return Ok(other),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
use preserves::symbol::Symbol;
|
||||
use preserves::value::{IOValue, Map};
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct TestCases {
|
||||
pub tests: Map<Symbol, TestCase>
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub enum TestCase {
|
||||
Test(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
NondeterministicTest(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
StreamingTest(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
DecodeTest(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
ParseError(String),
|
||||
ParseShort(String),
|
||||
ParseEOF(String),
|
||||
DecodeError(#[serde(with = "serde_bytes")] Vec<u8>),
|
||||
DecodeShort(#[serde(with = "serde_bytes")] Vec<u8>),
|
||||
DecodeEOF(#[serde(with = "serde_bytes")] Vec<u8>),
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
use preserves::error::{is_eof_io_error, is_syntax_io_error};
|
||||
use preserves::symbol::Symbol;
|
||||
use preserves::value::de::from_value as deserialize_from_value;
|
||||
use preserves::value::decoder;
|
||||
use preserves::value::encoder::encode_bytes;
|
||||
use preserves::value::IOValue;
|
||||
use std::iter::Iterator;
|
||||
|
||||
mod samples;
|
||||
use samples::*;
|
||||
|
||||
fn decode_all<'de>(bytes: &'de [u8]) -> Result<Vec<IOValue>, std::io::Error> {
|
||||
let d = decoder::from_bytes(bytes);
|
||||
d.collect()
|
||||
}
|
||||
|
||||
#[test] fn run() -> std::io::Result<()> {
|
||||
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
||||
let mut d = decoder::from_read(&mut fh);
|
||||
let tests: TestCases = deserialize_from_value(&d.next().unwrap().unwrap()).unwrap();
|
||||
// println!("{:#?}", tests);
|
||||
|
||||
for (Symbol(ref name), ref case) in tests.tests {
|
||||
println!("{:?} ==> {:?}", name, case);
|
||||
match case {
|
||||
TestCase::Test(ref bin, ref val) => {
|
||||
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
|
||||
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
|
||||
assert_eq!(&encode_bytes(val)?, bin);
|
||||
}
|
||||
TestCase::NondeterministicTest(ref bin, ref val) => {
|
||||
// The test cases in samples.txt are carefully
|
||||
// written so that while strictly
|
||||
// "nondeterministic", the order of keys in
|
||||
// dictionaries follows Preserves order.
|
||||
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
|
||||
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
|
||||
assert_eq!(&encode_bytes(val)?, bin);
|
||||
}
|
||||
TestCase::StreamingTest(ref bin, ref val) => {
|
||||
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
|
||||
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
|
||||
}
|
||||
TestCase::DecodeTest(ref bin, ref val) => {
|
||||
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
|
||||
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
|
||||
}
|
||||
TestCase::ParseError(_) => (),
|
||||
TestCase::ParseShort(_) => (),
|
||||
TestCase::ParseEOF(_) => (),
|
||||
TestCase::DecodeError(ref bin) => {
|
||||
match decode_all(&bin[..]) {
|
||||
Ok(_) => panic!("Unexpected success"),
|
||||
Err(e) => if is_syntax_io_error(&e) {
|
||||
()
|
||||
} else {
|
||||
panic!("Unexpected error {:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
TestCase::DecodeShort(ref bin) => {
|
||||
assert!(if let Err(e) = decoder::from_bytes(bin).next().unwrap() {
|
||||
is_eof_io_error(&e)
|
||||
} else {
|
||||
false
|
||||
})
|
||||
}
|
||||
TestCase::DecodeEOF(ref bin) => {
|
||||
assert!(decoder::from_bytes(bin).next().is_none());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue