global: snapshot

This commit is contained in:
nym21
2026-01-13 22:32:29 +01:00
parent 0c442b4a71
commit e77993fb76
61 changed files with 5047 additions and 5404 deletions

View File

@@ -0,0 +1,822 @@
//! Tests that verify pattern analysis using the real catalog.
use std::collections::HashSet;
use std::fmt::Write;
use brk_bindgen::ClientMetadata;
use brk_types::TreeNode;
/// Load the catalog from the JSON file.
fn load_catalog() -> TreeNode {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/catalog.json");
let catalog_json = std::fs::read_to_string(path).expect("Failed to read catalog.json");
serde_json::from_str(&catalog_json).expect("Failed to parse catalog.json")
}
/// Load OpenAPI spec from api.json.
fn load_openapi_json() -> String {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/api.json");
std::fs::read_to_string(path).expect("Failed to read api.json")
}
/// Load metadata from the catalog.
#[allow(unused)]
fn load_metadata() -> ClientMetadata {
ClientMetadata::from_catalog(load_catalog())
}
/// Collect all leaf metric names from a tree.
fn collect_leaf_names(node: &TreeNode, names: &mut HashSet<String>) {
match node {
TreeNode::Leaf(leaf) => {
names.insert(leaf.name().to_string());
}
TreeNode::Branch(children) => {
for child in children.values() {
collect_leaf_names(child, names);
}
}
}
}
#[test]
fn test_catalog_loads() {
let catalog = load_catalog();
// Should be a branch with top-level categories
let TreeNode::Branch(categories) = &catalog else {
panic!("Expected catalog to be a branch");
};
// Check some expected top-level categories exist
assert!(
categories.contains_key("addresses"),
"Missing addresses category"
);
assert!(categories.contains_key("blocks"), "Missing blocks category");
assert!(categories.contains_key("market"), "Missing market category");
assert!(categories.contains_key("supply"), "Missing supply category");
println!("Catalog has {} top-level categories", categories.len());
}
#[test]
fn test_all_leaves_have_names() {
let catalog = load_catalog();
let mut names = HashSet::new();
collect_leaf_names(&catalog, &mut names);
println!("Catalog has {} unique metric names", names.len());
assert!(!names.is_empty(), "Should have at least some metrics");
// All names should be non-empty
for name in &names {
assert!(!name.is_empty(), "Found empty metric name");
}
}
#[test]
fn test_pattern_detection() {
let catalog = load_catalog();
let (patterns, concrete_to_pattern, concrete_to_type_param) =
brk_bindgen::detect_structural_patterns(&catalog);
println!("Detected {} structural patterns", patterns.len());
println!(
"Concrete to pattern mappings: {}",
concrete_to_pattern.len()
);
println!("Type parameter mappings: {}", concrete_to_type_param.len());
// Print pattern details
for pattern in &patterns {
let mode_str = match &pattern.mode {
Some(brk_bindgen::PatternMode::Suffix { relatives }) => {
format!("Suffix({})", relatives.len())
}
Some(brk_bindgen::PatternMode::Prefix { prefixes }) => {
format!("Prefix({})", prefixes.len())
}
None => "None".to_string(),
};
println!(
" {} (fields: {}, generic: {}, mode: {})",
pattern.name,
pattern.fields.len(),
pattern.is_generic,
mode_str
);
}
// Should have detected some patterns
assert!(!patterns.is_empty(), "Should detect at least some patterns");
// Check that parameterizable patterns have valid modes
for pattern in &patterns {
if pattern.is_parameterizable() {
let mode = pattern.mode.as_ref().unwrap();
match mode {
brk_bindgen::PatternMode::Suffix { relatives } => {
assert_eq!(
relatives.len(),
pattern.fields.len(),
"Pattern {} should have relative for each field",
pattern.name
);
}
brk_bindgen::PatternMode::Prefix { prefixes } => {
assert_eq!(
prefixes.len(),
pattern.fields.len(),
"Pattern {} should have prefix for each field",
pattern.name
);
}
}
}
}
}
#[test]
fn test_cost_basis_pattern() {
let catalog = load_catalog();
let (patterns, _, _) = brk_bindgen::detect_structural_patterns(&catalog);
// Find CostBasisPattern2 and inspect it
let cost_basis = patterns
.iter()
.find(|p| p.name == "CostBasisPattern2")
.expect("CostBasisPattern2 should exist");
println!("CostBasisPattern2:");
println!(
" Fields: {:?}",
cost_basis
.fields
.iter()
.map(|f| &f.name)
.collect::<Vec<_>>()
);
println!(" Mode: {:?}", cost_basis.mode);
println!(" Is generic: {}", cost_basis.is_generic);
// With suffix naming convention (cost_basis_max, cost_basis_min, cost_basis):
//
// At root level: common prefix is "cost_basis_" -> suffix mode
// max -> "max"
// min -> "min"
// percentiles -> "" (identity)
//
// At lth_ level: common prefix is "lth_cost_basis_" -> suffix mode
// max -> "max"
// min -> "min"
// percentiles -> "" (identity)
//
// Both use suffix mode with same relatives, so pattern IS parameterizable!
assert!(
cost_basis.is_parameterizable(),
"CostBasisPattern2 should be parameterizable with consistent suffix mode"
);
}
#[test]
fn test_realized_pattern3_fields() {
let catalog = load_catalog();
let metadata = ClientMetadata::from_catalog(catalog);
let pattern = metadata
.find_pattern("RealizedPattern3")
.expect("RealizedPattern3 should exist");
println!("RealizedPattern3 fields:");
for field in &pattern.fields {
let is_branch = field.is_branch();
let is_pattern = metadata.find_pattern(&field.rust_type).is_some();
let is_param = metadata.is_parameterizable(&field.rust_type);
println!(
" {} -> {} (branch={}, pattern={}, param={})",
field.name, field.rust_type, is_branch, is_pattern, is_param
);
}
// Check if RealizedPattern3 is considered parameterizable
println!(
"\nRealizedPattern3 is_parameterizable (metadata): {}",
metadata.is_parameterizable("RealizedPattern3")
);
}
#[test]
fn test_parameterizable_patterns_have_mode() {
let catalog = load_catalog();
let (patterns, _, _) = brk_bindgen::detect_structural_patterns(&catalog);
// All patterns that appear 2+ times should either:
// 1. Be parameterizable (have a mode)
// 2. Or have inconsistent instances (mode = None)
//
// Patterns with mode = None should be inlined, not generate factories
let parameterizable: Vec<_> = patterns.iter().filter(|p| p.is_parameterizable()).collect();
let non_parameterizable: Vec<_> = patterns
.iter()
.filter(|p| !p.is_parameterizable())
.collect();
println!("\nParameterizable patterns ({}):", parameterizable.len());
for p in &parameterizable {
let mode = p.mode.as_ref().unwrap();
let mode_type = match mode {
brk_bindgen::PatternMode::Suffix { .. } => "Suffix",
brk_bindgen::PatternMode::Prefix { .. } => "Prefix",
};
println!(" {} ({} fields, {})", p.name, p.fields.len(), mode_type);
}
println!(
"\nNon-parameterizable patterns ({}):",
non_parameterizable.len()
);
for p in &non_parameterizable {
println!(" {} ({} fields)", p.name, p.fields.len());
}
// Verify all parameterizable patterns have valid modes with all fields
for pattern in &parameterizable {
let mode = pattern.mode.as_ref().unwrap();
let field_names: HashSet<_> = pattern.fields.iter().map(|f| f.name.clone()).collect();
match mode {
brk_bindgen::PatternMode::Suffix { relatives } => {
let mode_fields: HashSet<_> = relatives.keys().cloned().collect();
assert_eq!(
field_names, mode_fields,
"Pattern {} suffix mode should have all fields",
pattern.name
);
}
brk_bindgen::PatternMode::Prefix { prefixes } => {
let mode_fields: HashSet<_> = prefixes.keys().cloned().collect();
assert_eq!(
field_names, mode_fields,
"Pattern {} prefix mode should have all fields",
pattern.name
);
}
}
}
}
#[test]
fn test_index_patterns() {
let catalog = load_catalog();
let (used_indexes, index_patterns) = brk_bindgen::detect_index_patterns(&catalog);
println!("Used indexes: {:?}", used_indexes);
println!("Index set patterns: {}", index_patterns.len());
for pattern in &index_patterns {
println!(" {} -> {:?}", pattern.name, pattern.indexes);
}
// Should have detected some index patterns
assert!(!index_patterns.is_empty(), "Should detect index patterns");
}
#[test]
fn test_generated_rust_output() {
let catalog = load_catalog();
let metadata = ClientMetadata::from_catalog(catalog.clone());
// Collect all metric names from the catalog
let mut all_metrics = HashSet::new();
collect_leaf_names(&catalog, &mut all_metrics);
// Generate Rust client output
let mut rust_output = String::new();
brk_bindgen::rust::client::generate_imports(&mut rust_output);
brk_bindgen::rust::client::generate_base_client(&mut rust_output);
brk_bindgen::rust::client::generate_metric_pattern_trait(&mut rust_output);
brk_bindgen::rust::client::generate_endpoint(&mut rust_output);
brk_bindgen::rust::client::generate_index_accessors(
&mut rust_output,
&metadata.index_set_patterns,
);
brk_bindgen::rust::client::generate_pattern_structs(
&mut rust_output,
&metadata.structural_patterns,
&metadata,
);
brk_bindgen::rust::tree::generate_tree(&mut rust_output, &metadata.catalog, &metadata);
brk_bindgen::rust::api::generate_main_client(&mut rust_output, &[]);
// Count metrics that appear as direct string literals
let mut direct_metrics = 0;
for metric in &all_metrics {
if rust_output.contains(&format!("\"{}\"", metric)) {
direct_metrics += 1;
}
}
println!("\nGenerated Rust output stats:");
println!(" Total metrics in catalog: {}", all_metrics.len());
println!(" Direct string literals: {}", direct_metrics);
println!(
" Via pattern factories: {}",
all_metrics.len() - direct_metrics
);
println!(" Output size: {} bytes", rust_output.len());
// Write output to actual client location
let output_path = concat!(env!("CARGO_MANIFEST_DIR"), "/../brk_client/src/lib.rs");
std::fs::write(output_path, &rust_output).expect("Failed to write client output");
println!(" Wrote output to: {}", output_path);
// Verify the output contains the key components
assert!(rust_output.contains("fn _m("), "Should define _m helper");
assert!(
rust_output.contains("pub struct MetricsTree"),
"Should have MetricsTree"
);
assert!(
rust_output.contains("impl MetricsTree"),
"Should have MetricsTree impl"
);
// Count parameterizable patterns (these use _m for dynamic metric names)
// Use metadata.is_parameterizable() for full recursive check
let parameterizable_count = metadata
.structural_patterns
.iter()
.filter(|p| metadata.is_parameterizable(&p.name))
.count();
println!(" Parameterizable patterns: {}", parameterizable_count);
// Verify all pattern structs are generated (parameterizable and non)
for pattern in &metadata.structural_patterns {
assert!(
rust_output.contains(&format!("pub struct {}", pattern.name)),
"Missing pattern struct: {}",
pattern.name
);
}
println!("\nGenerated Rust client is complete!");
}
#[test]
fn test_generated_javascript_output() {
let catalog = load_catalog();
let metadata = ClientMetadata::from_catalog(catalog.clone());
// Collect all metric names from the catalog
let mut all_metrics = HashSet::new();
collect_leaf_names(&catalog, &mut all_metrics);
// Load schemas from OpenAPI spec only (catalog schemas require runtime data)
let openapi_json = load_openapi_json();
let schemas = brk_bindgen::extract_schemas(&openapi_json);
// Generate JavaScript client output
let mut js_output = String::new();
writeln!(js_output, "// Auto-generated BRK JavaScript client").unwrap();
writeln!(js_output, "// Do not edit manually\n").unwrap();
brk_bindgen::javascript::types::generate_type_definitions(&mut js_output, &schemas);
brk_bindgen::javascript::client::generate_base_client(&mut js_output);
brk_bindgen::javascript::client::generate_index_accessors(
&mut js_output,
&metadata.index_set_patterns,
);
brk_bindgen::javascript::client::generate_structural_patterns(
&mut js_output,
&metadata.structural_patterns,
&metadata,
);
brk_bindgen::javascript::tree::generate_tree_typedefs(
&mut js_output,
&metadata.catalog,
&metadata,
);
brk_bindgen::javascript::tree::generate_main_client(
&mut js_output,
&metadata.catalog,
&metadata,
&[],
);
// Count metrics that appear as direct string literals
let mut direct_metrics = 0;
for metric in &all_metrics {
if js_output.contains(&format!("'{}'", metric))
|| js_output.contains(&format!("\"{}\"", metric))
{
direct_metrics += 1;
}
}
println!("\nGenerated JavaScript output stats:");
println!(" Total metrics in catalog: {}", all_metrics.len());
println!(" Direct string literals: {}", direct_metrics);
println!(
" Via pattern factories: {}",
all_metrics.len() - direct_metrics
);
println!(" Output size: {} bytes", js_output.len());
println!(" Output lines: {}", js_output.lines().count());
// Write output to actual client location
let output_path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../modules/brk-client/index.js"
);
std::fs::write(output_path, &js_output).expect("Failed to write JS client output");
println!(" Wrote output to: {}", output_path);
// Verify the output contains key components
assert!(js_output.contains("const _m ="), "Should define _m helper");
assert!(js_output.contains("const _p ="), "Should define _p helper");
assert!(
js_output.contains("@typedef {Object} MetricsTree"),
"Should have MetricsTree typedef"
);
assert!(
js_output.contains("class BrkClient"),
"Should have BrkClient class"
);
// Verify all pattern factories are generated
for pattern in &metadata.structural_patterns {
assert!(
js_output.contains(&format!("function create{}(", pattern.name)),
"Missing pattern factory: {}",
pattern.name
);
}
println!("\nGenerated JavaScript client is complete!");
}
#[test]
fn test_generated_python_output() {
let catalog = load_catalog();
let metadata = ClientMetadata::from_catalog(catalog.clone());
// Collect all metric names from the catalog
let mut all_metrics = HashSet::new();
collect_leaf_names(&catalog, &mut all_metrics);
// Load schemas from OpenAPI spec only (catalog schemas require runtime data)
let openapi_json = load_openapi_json();
let schemas = brk_bindgen::extract_schemas(&openapi_json);
// Generate Python client output
let mut py_output = String::new();
writeln!(py_output, "# Auto-generated BRK Python client").unwrap();
writeln!(py_output, "# Do not edit manually\n").unwrap();
writeln!(py_output, "from typing import TypeVar, Generic, Any, Optional, List, Literal, TypedDict, Union, Protocol, overload").unwrap();
writeln!(
py_output,
"from http.client import HTTPSConnection, HTTPConnection"
)
.unwrap();
writeln!(py_output, "from urllib.parse import urlparse").unwrap();
writeln!(py_output, "import json\n").unwrap();
writeln!(py_output, "T = TypeVar('T')\n").unwrap();
brk_bindgen::python::types::generate_type_definitions(&mut py_output, &schemas);
brk_bindgen::python::client::generate_base_client(&mut py_output);
brk_bindgen::python::client::generate_endpoint_class(&mut py_output);
brk_bindgen::python::client::generate_index_accessors(
&mut py_output,
&metadata.index_set_patterns,
);
brk_bindgen::python::client::generate_structural_patterns(
&mut py_output,
&metadata.structural_patterns,
&metadata,
);
brk_bindgen::python::tree::generate_tree_classes(&mut py_output, &metadata.catalog, &metadata);
brk_bindgen::python::api::generate_main_client(&mut py_output, &[]);
// Count metrics that appear as direct string literals
let mut direct_metrics = 0;
for metric in &all_metrics {
if py_output.contains(&format!("'{}'", metric))
|| py_output.contains(&format!("\"{}\"", metric))
{
direct_metrics += 1;
}
}
println!("\nGenerated Python output stats:");
println!(" Total metrics in catalog: {}", all_metrics.len());
println!(" Direct string literals: {}", direct_metrics);
println!(
" Via pattern factories: {}",
all_metrics.len() - direct_metrics
);
println!(" Output size: {} bytes", py_output.len());
println!(" Output lines: {}", py_output.lines().count());
// Write output to actual client location
let output_path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../packages/brk_client/brk_client/__init__.py"
);
std::fs::write(output_path, &py_output).expect("Failed to write Python client output");
println!(" Wrote output to: {}", output_path);
// Verify the output contains key components
assert!(py_output.contains("def _m("), "Should define _m helper");
assert!(py_output.contains("def _p("), "Should define _p helper");
assert!(
py_output.contains("class MetricsTree:"),
"Should have MetricsTree class"
);
assert!(
py_output.contains("class BrkClient"),
"Should have BrkClient class"
);
// Verify all pattern classes have constructors
for pattern in &metadata.structural_patterns {
assert!(
py_output.contains(&format!("class {}:", pattern.name))
|| py_output.contains(&format!("class {}(", pattern.name)),
"Missing pattern class: {}",
pattern.name
);
}
println!("\nGenerated Python client is complete!");
}
#[test]
fn test_cost_basis_relatives() {
let catalog = load_catalog();
// Find cost_basis branches that have 3 direct children (max, min, percentiles)
fn find_cost_basis_with_percentiles(
node: &TreeNode,
path: &str,
) -> Vec<(String, Vec<(String, String)>)> {
let mut results = Vec::new();
if let TreeNode::Branch(children) = node {
for (name, child) in children {
let child_path = if path.is_empty() {
name.clone()
} else {
format!("{}.{}", path, name)
};
if name == "cost_basis"
&& let TreeNode::Branch(cb_children) = child
&& cb_children.contains_key("percentiles")
{
// Found a cost_basis with percentiles
let mut metrics = Vec::new();
for (field_name, field_node) in cb_children {
match field_node {
TreeNode::Leaf(leaf) => {
metrics.push((field_name.clone(), leaf.name().to_string()));
}
TreeNode::Branch(pct_children) => {
// Get first percentile as example
if let Some((_, TreeNode::Leaf(first))) = pct_children.iter().next()
{
metrics.push((
format!("{}.first", field_name),
first.name().to_string(),
));
}
}
}
}
results.push((child_path.clone(), metrics));
}
results.extend(find_cost_basis_with_percentiles(child, &child_path));
}
}
results
}
let instances = find_cost_basis_with_percentiles(&catalog, "");
println!("\nCostBasisPattern2 instances (with percentiles):");
for (path, metrics) in instances.iter().take(10) {
println!(" {}:", path);
for (field, metric) in metrics {
println!(" {} -> {}", field, metric);
}
}
// Now compute what relatives the pattern detection would see
// The key is: percentiles returns its BASE (common prefix of pct05, pct10, etc.)
// not the individual percentile metrics
use brk_bindgen::find_common_prefix;
println!("\nComputing relatives (simulating branch base returns):");
for (path, metrics) in instances.iter().take(5) {
println!(" Instance: {}", path);
// For leaves (max, min), the base is the metric name
// For branches (percentiles), the base is the common prefix of its children
let mut child_bases: std::collections::HashMap<String, String> =
std::collections::HashMap::new();
for (field, metric) in metrics {
if field.starts_with("percentiles.") {
// This is a percentile metric - compute what the percentiles branch would return
// The base is the metric name with the pct suffix stripped
let base = metric
.strip_suffix("_pct05")
.or_else(|| metric.strip_suffix("_pct10"))
.unwrap_or(metric)
.to_string();
child_bases.insert("percentiles".to_string(), base);
} else {
child_bases.insert(field.clone(), metric.clone());
}
}
let bases: Vec<&str> = child_bases.values().map(|s| s.as_str()).collect();
println!(" Child bases:");
for (field, base) in &child_bases {
println!(" {} -> {}", field, base);
}
if let Some(prefix) = find_common_prefix(&bases) {
println!(" Common prefix: '{}'", prefix);
for (field, base) in &child_bases {
let relative = base.strip_prefix(&prefix).unwrap_or(base);
println!(" {} -> relative '{}'", field, relative);
}
} else {
println!(" No common prefix found!");
}
}
}
#[test]
fn test_debug_cost_basis_pattern2_mode() {
// Debug why CostBasisPattern2 has mode=None
let catalog = load_catalog();
let metadata = brk_bindgen::ClientMetadata::from_catalog(catalog.clone());
let pattern_lookup = metadata.pattern_lookup();
let pattern = metadata
.find_pattern("CostBasisPattern2")
.expect("CostBasisPattern2 should exist");
println!("\nCostBasisPattern2 fields:");
for field in &pattern.fields {
println!(" {} (type: {})", field.name, field.rust_type);
}
println!("Mode: {:?}", pattern.mode);
// Now debug the instance collection
#[derive(Debug, Clone)]
struct DebugInstanceAnalysis {
base: String,
field_parts: std::collections::HashMap<String, String>,
is_suffix_mode: bool,
}
fn collect_debug(
node: &TreeNode,
pattern_lookup: &std::collections::HashMap<Vec<brk_bindgen::PatternField>, String>,
all_analyses: &mut std::collections::HashMap<String, Vec<DebugInstanceAnalysis>>,
) -> Option<String> {
match node {
TreeNode::Leaf(leaf) => Some(leaf.name().to_string()),
TreeNode::Branch(children) => {
let mut child_bases: std::collections::HashMap<String, String> =
std::collections::HashMap::new();
for (field_name, child_node) in children {
if let Some(base) = collect_debug(child_node, pattern_lookup, all_analyses) {
child_bases.insert(field_name.clone(), base);
}
}
if child_bases.is_empty() {
return None;
}
// Analyze this instance
let bases: Vec<&str> = child_bases.values().map(|s| s.as_str()).collect();
let (base, field_parts, is_suffix_mode) =
if let Some(common_prefix) = brk_bindgen::find_common_prefix(&bases) {
let base = common_prefix.trim_end_matches('_').to_string();
let mut parts = std::collections::HashMap::new();
for (field_name, child_base) in &child_bases {
let relative = if *child_base == base {
String::new()
} else {
child_base
.strip_prefix(&common_prefix)
.unwrap_or(child_base)
.to_string()
};
parts.insert(field_name.clone(), relative);
}
(base, parts, true)
} else {
let base = child_bases.values().next().cloned().unwrap_or_default();
let parts = child_bases
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
(base, parts, true)
};
let analysis = DebugInstanceAnalysis {
base: base.clone(),
field_parts,
is_suffix_mode,
};
// Get the pattern name for this node
let fields = brk_bindgen::get_node_fields(children, pattern_lookup);
if let Some(pattern_name) = pattern_lookup.get(&fields) {
all_analyses
.entry(pattern_name.clone())
.or_default()
.push(analysis);
}
Some(base)
}
}
}
let mut all_analyses: std::collections::HashMap<String, Vec<DebugInstanceAnalysis>> =
std::collections::HashMap::new();
collect_debug(&catalog, &pattern_lookup, &mut all_analyses);
if let Some(analyses) = all_analyses.get("CostBasisPattern2") {
println!(
"\nCollected {} instances of CostBasisPattern2:",
analyses.len()
);
for (i, a) in analyses.iter().enumerate() {
println!(" Instance {}:", i);
println!(" base: {}", a.base);
println!(" is_suffix: {}", a.is_suffix_mode);
println!(" field_parts:");
for (f, p) in &a.field_parts {
println!(" {} -> '{}'", f, p);
}
}
// Check consistency
if analyses.len() >= 2 {
let first = &analyses[0];
for (i, a) in analyses.iter().enumerate().skip(1) {
if a.is_suffix_mode != first.is_suffix_mode {
println!(" INCONSISTENT: Instance {} has different mode", i);
}
for (field, part) in &a.field_parts {
if first.field_parts.get(field) != Some(part) {
println!(
" INCONSISTENT: Instance {} field '{}' has part '{}' vs '{}'",
i,
field,
part,
first
.field_parts
.get(field)
.unwrap_or(&"<missing>".to_string())
);
}
}
}
}
} else {
println!("\nNo instances collected for CostBasisPattern2!");
}
}
#[test]
fn test_root_cost_basis_prefix() {
use brk_bindgen::find_common_prefix;
// Root-level cost_basis has:
// max -> "max_cost_basis"
// min -> "min_cost_basis"
// percentiles -> "cost_basis" (base of pct05, pct10, etc.)
let bases = vec!["max_cost_basis", "min_cost_basis", "cost_basis"];
let prefix = find_common_prefix(&bases);
println!("Root cost_basis prefix: {:?}", prefix);
// Compare with nested cost_basis
let nested_bases = vec![
"utxos_at_least_15y_old_max_cost_basis",
"utxos_at_least_15y_old_min_cost_basis",
"utxos_at_least_15y_old_cost_basis",
];
let nested_prefix = find_common_prefix(&nested_bases);
println!("Nested cost_basis prefix: {:?}", nested_prefix);
}