From 041973b91c04f2e06b27e5fda8c5726aecfb8a64 Mon Sep 17 00:00:00 2001 From: Daniel Schwartz-Narbonne Date: Thu, 23 May 2024 14:40:49 -0400 Subject: [PATCH 01/54] [profiling] Fuzz profiler API --- Cargo.lock | 22 ++++++++++++++++++++++ profiling/Cargo.toml | 5 +++-- profiling/src/api.rs | 16 ++++++++++++++++ profiling/src/internal/profile.rs | 10 ++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc280d547..439009e41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,6 +130,15 @@ version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "arrayref" version = "0.3.7" @@ -613,6 +622,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac749fb4f2e14734e835a9352c0d1eb2ab62a025d4c56a823fa3f391e015741a" dependencies = [ + "arbitrary", "bolero-generator-derive", "either", "rand_core", @@ -1190,6 +1200,7 @@ name = "datadog-profiling" version = "10.0.0" dependencies = [ "anyhow", + "arbitrary", "bitmaps", "bolero", "bolero-generator", @@ -1535,6 +1546,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "diff" version = "0.1.13" diff --git a/profiling/Cargo.toml b/profiling/Cargo.toml index e877b778c..a06234594 100644 --- a/profiling/Cargo.toml +++ b/profiling/Cargo.toml @@ -46,6 +46,7 @@ tokio-util = "0.7.1" byteorder = { version = "1.5", features = ["std"] } [dev-dependencies] -bolero = "0.10.1" -bolero-generator = "0.10.2" +arbitrary = { version = "1.3.2", features = ["derive", "derive_arbitrary"] } +bolero = { version = "0.10.1", features = ["arbitrary"] } +bolero-generator = { version = "0.10.2", features = ["arbitrary"] } criterion = "0.5.1" diff --git a/profiling/src/api.rs b/profiling/src/api.rs index 477fd75ec..3342c8601 100644 --- a/profiling/src/api.rs +++ b/profiling/src/api.rs @@ -343,6 +343,22 @@ impl<'a> TryFrom<&'a pprof::Profile> for Profile<'a> { } } +#[cfg(test)] +pub mod OwnedApi { + #[derive(Clone, Debug, Eq, PartialEq)] + #[cfg_attr(test, derive(bolero_generator::TypeGenerator))] + pub struct ValueType { + pub typ: String, + pub unit: String, + } + + impl<'a> From<&'a ValueType> for super::ValueType<'a> { + fn from(value: &'a ValueType) -> Self { + super::ValueType::new(&value.typ, &value.unit) + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/profiling/src/internal/profile.rs b/profiling/src/internal/profile.rs index 09bcfe274..3dcf10587 100644 --- a/profiling/src/internal/profile.rs +++ b/profiling/src/internal/profile.rs @@ -545,6 +545,16 @@ impl Profile { mod api_tests { use super::*; + #[test] + fn fuzz() { + use bolero::TypeGenerator; + + bolero::check!().with_generator(Vec::::gen()).for_each(|val| { + let sample_types : Vec<_> = val.iter().map(api::ValueType::from).collect(); + Profile::new(SystemTime::now(), &sample_types, None); + }) + } + #[test] fn interning() { let sample_types = [api::ValueType::new("samples", "count")]; From 50929a6f466132c811c94cc564118cbc545e4ae9 Mon Sep 17 00:00:00 2001 From: Daniel Schwartz-Narbonne Date: Thu, 23 May 2024 15:06:46 -0400 Subject: [PATCH 02/54] make owned types orthogonal to api types --- profiling/src/internal/mod.rs | 1 - profiling/src/internal/owned_types.rs | 17 +++++++++-------- profiling/src/internal/profile.rs | 18 +++++++++--------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/profiling/src/internal/mod.rs b/profiling/src/internal/mod.rs index 72f11a9c1..063fd7006 100644 --- a/profiling/src/internal/mod.rs +++ b/profiling/src/internal/mod.rs @@ -23,7 +23,6 @@ pub use label::*; pub use location::*; pub use mapping::*; pub use observation::*; -pub use owned_types::*; pub use profile::*; pub use sample::*; pub use stack_trace::*; diff --git a/profiling/src/internal/owned_types.rs b/profiling/src/internal/owned_types.rs index 4df1058ca..9769ba3a7 100644 --- a/profiling/src/internal/owned_types.rs +++ b/profiling/src/internal/owned_types.rs @@ -1,17 +1,18 @@ // Copyright 2021-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 -use crate::api::{Period, ValueType}; +use crate::api; #[derive(Clone)] -pub struct OwnedValueType { +#[cfg_attr(test, derive(bolero_generator::TypeGenerator))] +pub struct ValueType { pub typ: Box, pub unit: Box, } -impl<'a> From<&'a ValueType<'a>> for OwnedValueType { +impl<'a> From<&'a api::ValueType<'a>> for ValueType { #[inline] - fn from(value_type: &'a ValueType<'a>) -> Self { + fn from(value_type: &'a api::ValueType<'a>) -> Self { Self { typ: String::from(value_type.r#type).into(), unit: String::from(value_type.unit).into(), @@ -21,15 +22,15 @@ impl<'a> From<&'a ValueType<'a>> for OwnedValueType { #[derive(Clone)] pub struct OwnedPeriod { - pub typ: OwnedValueType, + pub typ: ValueType, pub value: i64, } -impl<'a> From<&'a Period<'a>> for OwnedPeriod { +impl<'a> From<&'a api::Period<'a>> for OwnedPeriod { #[inline] - fn from(period: &'a Period<'a>) -> Self { + fn from(period: &'a api::Period<'a>) -> Self { Self { - typ: OwnedValueType::from(&period.r#type), + typ: ValueType::from(&period.r#type), value: period.value, } } diff --git a/profiling/src/internal/profile.rs b/profiling/src/internal/profile.rs index 3dcf10587..ceb0a10ad 100644 --- a/profiling/src/internal/profile.rs +++ b/profiling/src/internal/profile.rs @@ -19,10 +19,10 @@ pub struct Profile { /// maintains them in a way that does not depend on the string table. The /// Option part is this is taken from the old profile and moved to the new /// one. - owned_sample_types: Option>, + owned_sample_types: Option>, /// When profiles are reset, the period needs to be preserved. This /// stores it in a way that does not depend on the string table. - owned_period: Option, + owned_period: Option, endpoints: Endpoints, functions: FxIndexSet, labels: FxIndexSet