#![allow(missing_docs)]
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use mockforge_core::openapi_routes::create_registry_from_json;
use mockforge_core::templating::expand_str;
use mockforge_core::validation::{validate_json_schema, ValidationResult, Validator};
use serde_json::json;
fn bench_template_rendering(c: &mut Criterion) {
let mut group = c.benchmark_group("template_rendering");
group.bench_function("simple", |b| {
let template = "Hello {{uuid}}!";
b.iter(|| expand_str(black_box(template)));
});
group.bench_function("complex", |b| {
let template = r#"
User: {{user.name}}
Email: {{user.email}}
Age: {{user.age}}
Address: {{user.address.street}}, {{user.address.city}}
"#;
b.iter(|| expand_str(black_box(template)));
});
group.bench_function("arrays", |b| {
let template = "{{#each items}}{{name}}: {{price}}\n{{/each}}";
b.iter(|| expand_str(black_box(template)));
});
group.finish();
}
fn bench_json_validation(c: &mut Criterion) {
let mut group = c.benchmark_group("json_validation");
let simple_schema = json!({
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let simple_data = json!({"name": "test"});
let simple_validator = Validator::from_json_schema(&simple_schema).unwrap();
group.bench_function("simple", |b| {
b.iter(|| {
let result = match simple_validator.validate(black_box(&simple_data)) {
Ok(_) => ValidationResult::success(),
Err(e) => ValidationResult::failure(vec![e.to_string()]),
};
black_box(result)
});
});
let complex_schema = json!({
"type": "object",
"properties": {
"user": {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"email": {"type": "string", "format": "email"},
"age": {"type": "integer", "minimum": 0, "maximum": 150}
},
"required": ["name", "email"]
}
},
"required": ["user"]
});
let complex_data = json!({
"user": {
"name": "John Doe",
"email": "john@example.com",
"age": 30
}
});
let complex_validator = Validator::from_json_schema(&complex_schema).unwrap();
group.bench_function("complex", |b| {
b.iter(|| {
let result = match complex_validator.validate(black_box(&complex_data)) {
Ok(_) => ValidationResult::success(),
Err(e) => ValidationResult::failure(vec![e.to_string()]),
};
black_box(result)
});
});
group.finish();
}
fn bench_openapi_parsing(c: &mut Criterion) {
let mut group = c.benchmark_group("openapi_parsing");
let small_spec = json!({
"openapi": "3.0.0",
"info": {
"title": "Test API",
"version": "1.0.0"
},
"paths": {
"/users": {
"get": {
"summary": "Get users",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"}
}
}
}
}
}
}
}
}
}
}
});
group.bench_function("small_spec", |b| {
b.iter_with_setup(
|| small_spec.clone(),
|spec| {
let result = create_registry_from_json(black_box(spec));
black_box(result)
},
);
});
let mut paths = serde_json::Map::new();
for i in 0..10 {
let path = format!("/resource{}", i);
paths.insert(
path,
json!({
"get": {
"summary": format!("Get resource {}", i),
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"}
}
}
}
}
}
}
}
}),
);
}
let medium_spec = json!({
"openapi": "3.0.0",
"info": {
"title": "Test API",
"version": "1.0.0"
},
"paths": paths
});
group.bench_function("medium_spec_10_paths", |b| {
b.iter_with_setup(
|| medium_spec.clone(),
|spec| {
let result = create_registry_from_json(black_box(spec));
black_box(result)
},
);
});
group.finish();
}
fn bench_data_generation(c: &mut Criterion) {
use mockforge_data::{DataConfig, DataGenerator, SchemaDefinition};
use serde_json::json;
let mut group = c.benchmark_group("data_generation");
let schema = SchemaDefinition::from_json_schema(&json!({
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"id": {"type": "string"}
}
}))
.unwrap();
let config = DataConfig {
rows: 1,
..Default::default()
};
group.bench_function("generate_single_record", |b| {
b.iter_with_setup(
|| {
DataGenerator::new(schema.clone(), config.clone()).unwrap()
},
|mut generator| {
let result = generator.generate_single().unwrap();
black_box(result)
},
);
});
group.finish();
}
fn bench_encryption(c: &mut Criterion) {
use mockforge_core::encryption::{EncryptionAlgorithm, EncryptionKey};
use rand::{rng, Rng};
let mut group = c.benchmark_group("encryption");
group.bench_function("aes256_gcm", |b| {
b.iter_with_setup(
|| {
let mut key_bytes = [0u8; 32];
rng().fill(&mut key_bytes);
EncryptionKey::new(EncryptionAlgorithm::Aes256Gcm, key_bytes.to_vec()).unwrap()
},
|key| {
let plaintext = "benchmark test data for encryption performance testing";
let encrypted = key.encrypt(plaintext, None).unwrap();
let decrypted = key.decrypt(&encrypted, None).unwrap();
black_box(decrypted)
},
);
});
group.bench_function("chacha20_poly1305", |b| {
b.iter_with_setup(
|| {
let mut key_bytes = [0u8; 32];
rng().fill(&mut key_bytes);
EncryptionKey::new(EncryptionAlgorithm::ChaCha20Poly1305, key_bytes.to_vec())
.unwrap()
},
|key| {
let plaintext = "benchmark test data for encryption performance testing";
let encrypted = key.encrypt(plaintext, None).unwrap();
let decrypted = key.decrypt(&encrypted, None).unwrap();
black_box(decrypted)
},
);
});
group.finish();
}
fn create_large_openapi_spec() -> serde_json::Value {
let mut paths = serde_json::Map::new();
for i in 0..100 {
let path = format!("/api/v1/resource_{}", i);
paths.insert(path, json!({
"get": {
"summary": format!("Get resource {}", i),
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {"type": "string"}
},
{
"name": "filter",
"in": "query",
"schema": {"type": "string"}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"},
"description": {"type": "string"},
"metadata": {
"type": "object",
"properties": {
"created_at": {"type": "string", "format": "date-time"},
"updated_at": {"type": "string", "format": "date-time"},
"tags": {
"type": "array",
"items": {"type": "string"}
}
}
}
}
}
}
}
}
}
},
"post": {
"summary": format!("Create resource {}", i),
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"description": {"type": "string"}
},
"required": ["name"]
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {"type": "integer"}
}
}
}
}
}
}
}
}));
}
json!({
"openapi": "3.0.0",
"info": {
"title": "Large Test API",
"version": "1.0.0",
"description": "A large API spec for memory benchmarking"
},
"paths": paths
})
}
fn bench_memory_usage(c: &mut Criterion) {
let mut group = c.benchmark_group("memory");
group.sample_size(10);
let large_spec = create_large_openapi_spec();
group.bench_function("large_spec_parsing", |b| {
b.iter_with_setup(
|| large_spec.clone(), |spec| {
let result = create_registry_from_json(black_box(spec));
black_box(result)
},
);
});
group.bench_function("deep_template_rendering", |b| {
b.iter_with_setup(
|| {
let mut template = String::from("{{#each items}}");
for i in 0..10 {
template.push_str(&format!(" Level {}: {{{{level{}}}}}\n", i, i));
template.push_str(" {{#each nested}}");
}
for _ in 0..10 {
template.push_str(" {{/each}}");
}
template.push_str("{{/each}}");
template
},
|template| {
let result = expand_str(black_box(&template));
black_box(result)
},
);
});
group.bench_function("large_data_validation", |b| {
b.iter_with_setup(
|| {
let schema = json!({
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string", "minLength": 1},
"email": {"type": "string", "format": "email"},
"metadata": {
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": {"type": "string"}
}
}
}
},
"required": ["id", "name", "email"]
},
"minItems": 1
});
let mut data = Vec::new();
for i in 0..100 {
data.push(json!({
"id": i,
"name": format!("User {}", i),
"email": format!("user{}@example.com", i),
"metadata": {
"tags": ["tag1", "tag2", "tag3"]
}
}));
}
(schema, json!(data))
},
|(schema, data)| {
let result = validate_json_schema(black_box(&data), black_box(&schema));
black_box(result)
},
);
});
group.finish();
}
criterion_group!(
benches,
bench_template_rendering,
bench_json_validation,
bench_openapi_parsing,
bench_data_generation,
bench_encryption,
bench_memory_usage
);
criterion_main!(benches);