1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License in the LICENSE file at the
6// root of this repository, or online at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
1516//! Internal utility proc-macros for persist.
17//!
18//! Note: This is separate from the `mz_persist_client` crate because
19//! `proc-macro` crates are only allowed to export procedural macros and nothing
20//! else.
2122use proc_macro::TokenStream;
23use proc_macro2::TokenStream as TokenStream2;
24use quote::quote;
25use syn::{ItemFn, ReturnType, parse_macro_input};
2627/// Persist wrapper around the `test` macro.
28///
29/// The wrapper automatically runs the test with various interesting
30/// configurations.
31#[proc_macro_attribute]
32pub fn test(attr: TokenStream, item: TokenStream) -> TokenStream {
33 test_impl(attr, item)
34}
3536/// Implementation for the `#[mz_persist_proc::test]` macro.
37fn test_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
38let args = TokenStream2::from(attr);
39let item = parse_macro_input!(item as ItemFn);
4041let attrs = &item.attrs;
42let async_ = &item.sig.asyncness;
43let await_ = if async_.is_some() {
44quote! {.await}
45 } else {
46quote! {}
47 };
48let inputs = &item.sig.inputs;
49let body = &item.block;
50let test_name = &item.sig.ident;
5152// Note that Rust does not allow us to have a test function with
53 // #[should_panic] that has a non-unit return value.
54let ret = match &item.sig.output {
55 ReturnType::Default => quote! {},
56 ReturnType::Type(_, type_) => quote! {-> #type_},
57 };
5859quote! {
60#[::mz_ore::test(
61 #args
62 )]
63#(#attrs)*
64 #async_ fn #test_name() #ret {
65 #async_ fn test_impl(#inputs) #ret {
66 #body
67 }
6869let dyncfgs = [
70 {
71// Inline writes disabled
72let mut x = ::mz_dyncfg::ConfigUpdates::default();
73 x.add_dynamic("persist_inline_writes_single_max_bytes", ::mz_dyncfg::ConfigVal::Usize(0));
74 x.add_dynamic("persist_inline_writes_total_max_bytes", ::mz_dyncfg::ConfigVal::Usize(0));
75 x
76 },
77 {
78// Inline writes enabled
79let mut x = ::mz_dyncfg::ConfigUpdates::default();
80 x.add_dynamic("persist_inline_writes_single_max_bytes", ::mz_dyncfg::ConfigVal::Usize(4 * 1024));
81 x.add_dynamic("persist_inline_writes_total_max_bytes", ::mz_dyncfg::ConfigVal::Usize(1024 * 1024));
82 x
83 },
84 {
85// Stress inline writes backpressure
86let mut x = ::mz_dyncfg::ConfigUpdates::default();
87 x.add_dynamic("persist_inline_writes_single_max_bytes", ::mz_dyncfg::ConfigVal::Usize(4 * 1024));
88 x.add_dynamic("persist_inline_writes_total_max_bytes", ::mz_dyncfg::ConfigVal::Usize(0));
89 x
90 },
91 {
92// Enable new compaction tracking / claiming
93let mut x = ::mz_dyncfg::ConfigUpdates::default();
94 x.add_dynamic("persist_claim_unclaimed_compactions", ::mz_dyncfg::ConfigVal::Bool(true));
95 x
96 },
97 {
98let mut x = ::mz_dyncfg::ConfigUpdates::default();
99 x.add_dynamic("persist_record_schema_id", ::mz_dyncfg::ConfigVal::Bool(true));
100 x
101 },
102 {
103let mut x = ::mz_dyncfg::ConfigUpdates::default();
104 x.add_dynamic("persist_encoding_enable_dictionary", ::mz_dyncfg::ConfigVal::Bool(true));
105 x
106 },
107 {
108let mut x = ::mz_dyncfg::ConfigUpdates::default();
109 x.add_dynamic("persist_batch_max_run_len", ::mz_dyncfg::ConfigVal::Usize(4));
110 x
111 },
112 ];
113114for (idx, dyncfgs) in dyncfgs.into_iter().enumerate() {
115let debug = dyncfgs.updates.iter().map(|(name, val)| {
116format!(" {}={:?}", name, val.val.clone().unwrap())
117 }).collect::<String>();
118eprintln!("mz_persist_proc::test {}{}", idx, debug);
119 test_impl(dyncfgs)#await_
120 }
121 }
122 }
123 .into()
124}