use std::collections::BTreeMap;
#[derive(Debug, Clone)]
pub struct IrVerificationResult {
pub name: String,
pub passed: bool,
pub ir_text: String,
pub patterns_found: Vec<String>,
pub patterns_missing: Vec<String>,
pub warnings: Vec<String>,
pub errors: Vec<String>,
}
impl IrVerificationResult {
pub fn pass(name: &str, ir_text: &str, found: Vec<String>) -> Self {
Self {
name: name.to_string(),
passed: true,
ir_text: ir_text.to_string(),
patterns_found: found,
patterns_missing: Vec::new(),
warnings: Vec::new(),
errors: Vec::new(),
}
}
pub fn fail(name: &str, ir_text: &str, missing: Vec<String>) -> Self {
Self {
name: name.to_string(),
passed: false,
ir_text: ir_text.to_string(),
patterns_found: Vec::new(),
patterns_missing: missing,
warnings: Vec::new(),
errors: Vec::new(),
}
}
pub fn summary(&self) -> String {
let status = if self.passed { "PASS" } else { "FAIL" };
format!(
"{}: {} (found={}, missing={})",
self.name,
status,
self.patterns_found.len(),
self.patterns_missing.len()
)
}
}
#[derive(Debug, Clone, Default)]
pub struct StdlibTestResults {
pub results: Vec<IrVerificationResult>,
pub passed: usize,
pub failed: usize,
}
impl StdlibTestResults {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, result: IrVerificationResult) {
if result.passed {
self.passed += 1;
} else {
self.failed += 1;
}
self.results.push(result);
}
pub fn all_pass(&self) -> bool {
self.failed == 0
}
pub fn pass_rate(&self) -> f64 {
let total = self.passed + self.failed;
if total == 0 {
return 1.0;
}
self.passed as f64 / total as f64
}
pub fn summary(&self) -> String {
format!(
"Stdlib tests: {}/{} passed ({:.1}%)",
self.passed,
self.passed + self.failed,
self.pass_rate() * 100.0
)
}
}
#[derive(Debug, Clone)]
pub struct IrCheckPattern {
pub pattern: String,
pub description: String,
pub required: bool,
pub min_count: usize,
pub max_count: usize,
}
impl IrCheckPattern {
pub fn required(pattern: &str, description: &str) -> Self {
Self {
pattern: pattern.to_string(),
description: description.to_string(),
required: true,
min_count: 1,
max_count: 0,
}
}
pub fn optional(pattern: &str, description: &str) -> Self {
Self {
pattern: pattern.to_string(),
description: description.to_string(),
required: false,
min_count: 0,
max_count: 0,
}
}
pub fn exact(pattern: &str, description: &str, count: usize) -> Self {
Self {
pattern: pattern.to_string(),
description: description.to_string(),
required: true,
min_count: count,
max_count: count,
}
}
pub fn check(&self, ir: &str) -> bool {
let count = ir.matches(&self.pattern).count();
if self.required {
if count < self.min_count {
return false;
}
if self.max_count > 0 && count > self.max_count {
return false;
}
}
true
}
pub fn count_in(&self, ir: &str) -> usize {
ir.matches(&self.pattern).count()
}
}
pub fn verify_ir_patterns(
name: &str,
ir_text: &str,
patterns: &[IrCheckPattern],
) -> IrVerificationResult {
let mut found = Vec::new();
let mut missing = Vec::new();
for p in patterns {
if p.check(ir_text) {
found.push(p.description.clone());
} else if p.required {
missing.push(format!(
"{} (expected: '{}', found {} times)",
p.description,
p.pattern,
p.count_in(ir_text)
));
}
}
if missing.is_empty() {
IrVerificationResult::pass(name, ir_text, found)
} else {
IrVerificationResult::fail(name, ir_text, missing)
}
}
pub fn vector_push_back_source() -> &'static str {
r#"
#include <vector>
int main() {
std::vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
return v.size();
}
"#
}
pub fn vector_iterator_source() -> &'static str {
r#"
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
int sum = 0;
for (int x : v) {
sum += x;
}
return sum;
}
"#
}
pub fn vector_resize_source() -> &'static str {
r#"
#include <vector>
int main() {
std::vector<int> v;
v.resize(10, 42);
return v[0] + v[9];
}
"#
}
pub fn vector_insert_erase_source() -> &'static str {
r#"
#include <vector>
int main() {
std::vector<int> v = {1, 3, 5};
v.insert(v.begin() + 1, 2);
v.erase(v.begin() + 2);
return v[0] + v[1] + v[2];
}
"#
}
pub fn vector_emplace_source() -> &'static str {
r#"
#include <vector>
#include <string>
struct Point { int x; int y; Point(int a, int b) : x(a), y(b) {} };
int main() {
std::vector<Point> v;
v.emplace_back(1, 2);
v.emplace_back(3, 4);
return v.size();
}
"#
}
pub fn vector_push_back_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("alloca", "stack allocation for vector"),
IrCheckPattern::required("call", "function call for push_back"),
IrCheckPattern::required("i32", "32-bit integer type"),
IrCheckPattern::optional("@_Znwm", "operator new allocation"),
]
}
pub fn vector_iterator_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("alloca", "stack allocation"),
IrCheckPattern::required("phi", "phi node for loop induction variable"),
IrCheckPattern::required("br", "branch for loop condition"),
IrCheckPattern::required("add", "addition for accumulating sum"),
]
}
pub fn string_construction_source() -> &'static str {
r#"
#include <string>
int main() {
std::string s1;
std::string s2("hello");
std::string s3 = "world";
std::string s4(s2);
return s2.length() + s3.length();
}
"#
}
pub fn string_concat_source() -> &'static str {
r#"
#include <string>
int main() {
std::string a = "hello";
std::string b = " ";
std::string c = "world";
std::string result = a + b + c;
return result.length();
}
"#
}
pub fn string_find_source() -> &'static str {
r#"
#include <string>
int main() {
std::string s = "hello world";
auto pos = s.find("world");
return pos == std::string::npos ? -1 : (int)pos;
}
"#
}
pub fn string_substr_source() -> &'static str {
r#"
#include <string>
int main() {
std::string s = "hello world";
std::string sub = s.substr(0, 5);
return sub.length();
}
"#
}
pub fn string_compare_source() -> &'static str {
r#"
#include <string>
int main() {
std::string a = "abc";
std::string b = "abd";
if (a < b) return 1;
if (a > b) return 2;
return 0;
}
"#
}
pub fn string_construction_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("alloca", "stack allocation for strings"),
IrCheckPattern::required("call", "constructor calls"),
IrCheckPattern::required("i32", "integer return type"),
]
}
pub fn string_concat_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("call", "operator+ calls"),
IrCheckPattern::required("alloca", "temporary string allocations"),
]
}
pub fn map_insertion_source() -> &'static str {
r#"
#include <map>
#include <string>
int main() {
std::map<int, std::string> m;
m[1] = "one";
m[2] = "two";
m[3] = "three";
return m.size();
}
"#
}
pub fn map_lookup_source() -> &'static str {
r#"
#include <map>
int main() {
std::map<int, int> m;
m[10] = 100;
m[20] = 200;
auto it = m.find(20);
if (it != m.end()) return it->second;
return -1;
}
"#
}
pub fn map_erase_source() -> &'static str {
r#"
#include <map>
int main() {
std::map<int, int> m;
m[1] = 10;
m[2] = 20;
m.erase(1);
return m.size();
}
"#
}
pub fn map_insertion_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("call", "map method calls"),
IrCheckPattern::required("alloca", "stack allocations"),
IrCheckPattern::required("i32", "integer types"),
]
}
pub fn sort_ints_source() -> &'static str {
r#"
#include <algorithm>
#include <vector>
int main() {
std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
std::sort(v.begin(), v.end());
return v[0] + v[7];
}
"#
}
pub fn sort_strings_source() -> &'static str {
r#"
#include <algorithm>
#include <string>
#include <vector>
int main() {
std::vector<std::string> v = {"banana", "apple", "cherry"};
std::sort(v.begin(), v.end());
return v[0].length() + v[2].length();
}
"#
}
pub fn sort_custom_source() -> &'static str {
r#"
#include <algorithm>
#include <vector>
bool descending(int a, int b) { return a > b; }
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
std::sort(v.begin(), v.end(), descending);
return v[0];
}
"#
}
pub fn stable_sort_source() -> &'static str {
r#"
#include <algorithm>
#include <vector>
struct Item { int value; int id; };
bool cmp(const Item& a, const Item& b) { return a.value < b.value; }
int main() {
std::vector<Item> v = {{5, 1}, {3, 2}, {5, 3}, {1, 4}};
std::stable_sort(v.begin(), v.end(), cmp);
return v[0].id;
}
"#
}
pub fn sort_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("call", "sort function call"),
IrCheckPattern::required("alloca", "stack allocation for vector"),
]
}
pub fn find_count_source() -> &'static str {
r#"
#include <algorithm>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 2, 3, 2, 4};
int c = std::count(v.begin(), v.end(), 2);
auto it = std::find(v.begin(), v.end(), 3);
return c + (it != v.end() ? 1 : 0);
}
"#
}
pub fn copy_transform_source() -> &'static str {
r#"
#include <algorithm>
#include <vector>
int main() {
std::vector<int> src = {1, 2, 3, 4, 5};
std::vector<int> dst(5);
std::copy(src.begin(), src.end(), dst.begin());
std::transform(dst.begin(), dst.end(), dst.begin(), [](int x) { return x * 2; });
return dst[0] + dst[4];
}
"#
}
pub fn accumulate_source() -> &'static str {
r#"
#include <numeric>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
int sum = std::accumulate(v.begin(), v.end(), 0);
return sum;
}
"#
}
pub fn unique_source() -> &'static str {
r#"
#include <algorithm>
#include <vector>
int main() {
std::vector<int> v = {1, 1, 2, 2, 2, 3, 3};
auto it = std::unique(v.begin(), v.end());
return (int)(it - v.begin());
}
"#
}
pub fn reverse_source() -> &'static str {
r#"
#include <algorithm>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
std::reverse(v.begin(), v.end());
return v[0];
}
"#
}
pub fn algorithm_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("call", "algorithm function calls"),
IrCheckPattern::required("alloca", "stack allocations"),
]
}
pub fn unique_ptr_source() -> &'static str {
r#"
#include <memory>
struct Foo { int x; Foo(int a) : x(a) {} };
int main() {
auto p = std::make_unique<Foo>(42);
return p->x;
}
"#
}
pub fn shared_ptr_source() -> &'static str {
r#"
#include <memory>
int main() {
auto sp1 = std::make_shared<int>(100);
auto sp2 = sp1;
*sp1 = 200;
return *sp2;
}
"#
}
pub fn weak_ptr_source() -> &'static str {
r#"
#include <memory>
int main() {
std::weak_ptr<int> wp;
{
auto sp = std::make_shared<int>(42);
wp = sp;
if (auto locked = wp.lock()) {
return *locked;
}
}
return wp.expired() ? 1 : 0;
}
"#
}
pub fn smart_ptr_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("call", "make_unique/make_shared calls"),
IrCheckPattern::required("alloca", "stack allocation for smart pointers"),
IrCheckPattern::required("i32", "integer type"),
]
}
pub fn accumulate_numeric_source() -> &'static str {
r#"
#include <numeric>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
return std::accumulate(v.begin(), v.end(), 0);
}
"#
}
pub fn gcd_lcm_source() -> &'static str {
r#"
#include <numeric>
int main() {
int a = std::gcd(12, 8);
int b = std::lcm(4, 6);
return a + b;
}
"#
}
pub fn numeric_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("call", "numeric function calls"),
IrCheckPattern::required("i32", "integer type"),
]
}
pub fn exception_throw_catch_source() -> &'static str {
r#"
#include <stdexcept>
int safe_divide(int a, int b) {
if (b == 0) throw std::runtime_error("division by zero");
return a / b;
}
int main() {
try {
return safe_divide(10, 2);
} catch (const std::runtime_error& e) {
return -1;
}
}
"#
}
pub fn out_of_range_source() -> &'static str {
r#"
#include <stdexcept>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3};
try {
v.at(5);
} catch (const std::out_of_range& e) {
return -1;
}
return 0;
}
"#
}
pub fn exception_ir_patterns() -> Vec<IrCheckPattern> {
vec![
IrCheckPattern::required("invoke", "invoke instruction for try/catch"),
IrCheckPattern::required("landingpad", "landingpad for exception handling"),
IrCheckPattern::required("@__cxa_allocate_exception", "exception allocation"),
IrCheckPattern::required("@__cxa_throw", "exception throw"),
]
}
#[derive(Debug, Clone)]
pub struct StdlibTestCase {
pub name: String,
pub source: String,
pub patterns: Vec<IrCheckPattern>,
pub flags: Vec<String>,
pub category: String,
}
impl StdlibTestCase {
pub fn new(name: &str, source: &str, patterns: Vec<IrCheckPattern>) -> Self {
Self {
name: name.to_string(),
source: source.to_string(),
patterns,
flags: vec!["-std=c++17".into()],
category: String::new(),
}
}
pub fn with_category(mut self, cat: &str) -> Self {
self.category = cat.to_string();
self
}
pub fn with_flags(mut self, flags: &[&str]) -> Self {
self.flags.extend(flags.iter().map(|s| s.to_string()));
self
}
}
pub fn build_stdlib_test_suite() -> Vec<StdlibTestCase> {
vec![
StdlibTestCase::new(
"vector_push_back",
vector_push_back_source(),
vector_push_back_ir_patterns(),
)
.with_category("vector"),
StdlibTestCase::new(
"vector_iterator",
vector_iterator_source(),
vector_iterator_ir_patterns(),
)
.with_category("vector"),
StdlibTestCase::new(
"vector_resize",
vector_resize_source(),
vector_push_back_ir_patterns(),
)
.with_category("vector"),
StdlibTestCase::new(
"vector_insert_erase",
vector_insert_erase_source(),
vector_push_back_ir_patterns(),
)
.with_category("vector"),
StdlibTestCase::new(
"vector_emplace",
vector_emplace_source(),
vector_push_back_ir_patterns(),
)
.with_category("vector"),
StdlibTestCase::new(
"string_construction",
string_construction_source(),
string_construction_ir_patterns(),
)
.with_category("string"),
StdlibTestCase::new(
"string_concat",
string_concat_source(),
string_concat_ir_patterns(),
)
.with_category("string"),
StdlibTestCase::new(
"string_find",
string_find_source(),
string_construction_ir_patterns(),
)
.with_category("string"),
StdlibTestCase::new(
"string_substr",
string_substr_source(),
string_construction_ir_patterns(),
)
.with_category("string"),
StdlibTestCase::new(
"string_compare",
string_compare_source(),
string_construction_ir_patterns(),
)
.with_category("string"),
StdlibTestCase::new(
"map_insertion",
map_insertion_source(),
map_insertion_ir_patterns(),
)
.with_category("map"),
StdlibTestCase::new(
"map_lookup",
map_lookup_source(),
map_insertion_ir_patterns(),
)
.with_category("map"),
StdlibTestCase::new(
"map_erase",
map_erase_source(),
map_insertion_ir_patterns(),
)
.with_category("map"),
StdlibTestCase::new(
"sort_ints",
sort_ints_source(),
sort_ir_patterns(),
)
.with_category("sort"),
StdlibTestCase::new(
"sort_strings",
sort_strings_source(),
sort_ir_patterns(),
)
.with_category("sort"),
StdlibTestCase::new(
"sort_custom",
sort_custom_source(),
sort_ir_patterns(),
)
.with_category("sort"),
StdlibTestCase::new(
"stable_sort",
stable_sort_source(),
sort_ir_patterns(),
)
.with_category("sort"),
StdlibTestCase::new(
"find_count",
find_count_source(),
algorithm_ir_patterns(),
)
.with_category("algorithm"),
StdlibTestCase::new(
"copy_transform",
copy_transform_source(),
algorithm_ir_patterns(),
)
.with_category("algorithm"),
StdlibTestCase::new(
"accumulate",
accumulate_source(),
algorithm_ir_patterns(),
)
.with_category("algorithm"),
StdlibTestCase::new(
"unique",
unique_source(),
algorithm_ir_patterns(),
)
.with_category("algorithm"),
StdlibTestCase::new(
"reverse",
reverse_source(),
algorithm_ir_patterns(),
)
.with_category("algorithm"),
StdlibTestCase::new(
"unique_ptr",
unique_ptr_source(),
smart_ptr_ir_patterns(),
)
.with_category("smart_ptr"),
StdlibTestCase::new(
"shared_ptr",
shared_ptr_source(),
smart_ptr_ir_patterns(),
)
.with_category("smart_ptr"),
StdlibTestCase::new(
"weak_ptr",
weak_ptr_source(),
smart_ptr_ir_patterns(),
)
.with_category("smart_ptr"),
StdlibTestCase::new(
"accumulate_numeric",
accumulate_numeric_source(),
numeric_ir_patterns(),
)
.with_category("numeric"),
StdlibTestCase::new(
"gcd_lcm",
gcd_lcm_source(),
numeric_ir_patterns(),
)
.with_category("numeric"),
StdlibTestCase::new(
"exception_throw_catch",
exception_throw_catch_source(),
exception_ir_patterns(),
)
.with_category("exception"),
StdlibTestCase::new(
"out_of_range",
out_of_range_source(),
exception_ir_patterns(),
)
.with_category("exception"),
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ir_verification_result_pass() {
let result = IrVerificationResult::pass("test1", "ir text", vec!["pattern1".into()]);
assert!(result.passed);
assert_eq!(result.patterns_found.len(), 1);
}
#[test]
fn test_ir_verification_result_fail() {
let result = IrVerificationResult::fail("test1", "ir text", vec!["missing".into()]);
assert!(!result.passed);
assert_eq!(result.patterns_missing.len(), 1);
}
#[test]
fn test_ir_verification_result_summary_pass() {
let result = IrVerificationResult::pass("t", "", vec!["p".into()]);
assert!(result.summary().contains("PASS"));
}
#[test]
fn test_ir_verification_result_summary_fail() {
let result = IrVerificationResult::fail("t", "", vec!["m".into()]);
assert!(result.summary().contains("FAIL"));
}
#[test]
fn test_stdlib_test_results_new() {
let results = StdlibTestResults::new();
assert_eq!(results.passed, 0);
assert_eq!(results.failed, 0);
}
#[test]
fn test_stdlib_test_results_add() {
let mut results = StdlibTestResults::new();
results.add(IrVerificationResult::pass("t1", "", vec![]));
results.add(IrVerificationResult::pass("t2", "", vec![]));
results.add(IrVerificationResult::fail("t3", "", vec![]));
assert_eq!(results.passed, 2);
assert_eq!(results.failed, 1);
assert!(!results.all_pass());
}
#[test]
fn test_stdlib_test_results_all_pass() {
let mut results = StdlibTestResults::new();
results.add(IrVerificationResult::pass("t1", "", vec![]));
results.add(IrVerificationResult::pass("t2", "", vec![]));
assert!(results.all_pass());
}
#[test]
fn test_stdlib_test_results_pass_rate() {
let mut results = StdlibTestResults::new();
results.add(IrVerificationResult::pass("t1", "", vec![]));
results.add(IrVerificationResult::pass("t2", "", vec![]));
results.add(IrVerificationResult::fail("t3", "", vec![]));
assert!((results.pass_rate() - 2.0 / 3.0).abs() < 0.01);
}
#[test]
fn test_ir_check_pattern_required() {
let pat = IrCheckPattern::required("alloca", "stack allocation");
assert!(pat.required);
assert_eq!(pat.min_count, 1);
}
#[test]
fn test_ir_check_pattern_optional() {
let pat = IrCheckPattern::optional("memcpy", "memory copy");
assert!(!pat.required);
}
#[test]
fn test_ir_check_pattern_exact() {
let pat = IrCheckPattern::exact("ret i32", "return instruction", 1);
assert!(pat.required);
assert_eq!(pat.min_count, 1);
assert_eq!(pat.max_count, 1);
}
#[test]
fn test_ir_check_pattern_check_present() {
let pat = IrCheckPattern::required("alloca", "stack alloc");
let ir = "alloca i32\nstore i32 0, i32* %1\nret i32 0";
assert!(pat.check(ir));
}
#[test]
fn test_ir_check_pattern_check_missing() {
let pat = IrCheckPattern::required("fadd", "float add");
let ir = "alloca i32\nret i32 0";
assert!(!pat.check(ir));
}
#[test]
fn test_ir_check_pattern_count() {
let pat = IrCheckPattern::required("alloca", "alloc");
let ir = "alloca i32\nalloca i64\nalloca double\nret void";
assert_eq!(pat.count_in(ir), 3);
}
#[test]
fn test_verify_ir_patterns_all_match() {
let patterns = vec![
IrCheckPattern::required("alloca", "stack alloc"),
IrCheckPattern::required("ret", "return"),
];
let ir = "alloca i32\nret i32 0";
let result = verify_ir_patterns("test", ir, &patterns);
assert!(result.passed);
}
#[test]
fn test_verify_ir_patterns_some_missing() {
let patterns = vec![
IrCheckPattern::required("alloca", "stack alloc"),
IrCheckPattern::required("fadd", "float add"),
];
let ir = "alloca i32\nret i32 0";
let result = verify_ir_patterns("test", ir, &patterns);
assert!(!result.passed);
assert_eq!(result.patterns_missing.len(), 1);
}
#[test]
fn test_vector_push_back_source_compiles() {
let src = vector_push_back_source();
assert!(src.contains("std::vector"));
assert!(src.contains("push_back"));
}
#[test]
fn test_vector_iterator_source_compiles() {
let src = vector_iterator_source();
assert!(src.contains("for"));
assert!(src.contains(": v"));
}
#[test]
fn test_vector_resize_source() {
let src = vector_resize_source();
assert!(src.contains("resize"));
}
#[test]
fn test_vector_insert_erase_source() {
let src = vector_insert_erase_source();
assert!(src.contains("insert"));
assert!(src.contains("erase"));
}
#[test]
fn test_vector_emplace_source() {
let src = vector_emplace_source();
assert!(src.contains("emplace_back"));
}
#[test]
fn test_string_construction_source() {
let src = string_construction_source();
assert!(src.contains("std::string"));
assert!(src.contains("length"));
}
#[test]
fn test_string_concat_source() {
let src = string_concat_source();
assert!(src.contains("+"));
assert!(src.contains("result"));
}
#[test]
fn test_string_find_source() {
let src = string_find_source();
assert!(src.contains("find"));
assert!(src.contains("npos"));
}
#[test]
fn test_string_substr_source() {
let src = string_substr_source();
assert!(src.contains("substr"));
}
#[test]
fn test_string_compare_source() {
let src = string_compare_source();
assert!(src.contains("<"));
}
#[test]
fn test_map_insertion_source() {
let src = map_insertion_source();
assert!(src.contains("std::map"));
assert!(src.contains("operator[]"));
}
#[test]
fn test_map_lookup_source() {
let src = map_lookup_source();
assert!(src.contains("find"));
assert!(src.contains("end"));
}
#[test]
fn test_map_erase_source() {
let src = map_erase_source();
assert!(src.contains("erase"));
}
#[test]
fn test_sort_ints_source() {
let src = sort_ints_source();
assert!(src.contains("std::sort"));
}
#[test]
fn test_sort_strings_source() {
let src = sort_strings_source();
assert!(src.contains("std::string"));
}
#[test]
fn test_sort_custom_source() {
let src = sort_custom_source();
assert!(src.contains("descending"));
}
#[test]
fn test_stable_sort_source() {
let src = stable_sort_source();
assert!(src.contains("stable_sort"));
}
#[test]
fn test_find_count_source() {
let src = find_count_source();
assert!(src.contains("count"));
assert!(src.contains("find"));
}
#[test]
fn test_copy_transform_source() {
let src = copy_transform_source();
assert!(src.contains("copy"));
assert!(src.contains("transform"));
}
#[test]
fn test_accumulate_source() {
let src = accumulate_source();
assert!(src.contains("accumulate"));
}
#[test]
fn test_unique_source() {
let src = unique_source();
assert!(src.contains("unique"));
}
#[test]
fn test_reverse_source() {
let src = reverse_source();
assert!(src.contains("reverse"));
}
#[test]
fn test_unique_ptr_source() {
let src = unique_ptr_source();
assert!(src.contains("make_unique"));
}
#[test]
fn test_shared_ptr_source() {
let src = shared_ptr_source();
assert!(src.contains("make_shared"));
}
#[test]
fn test_weak_ptr_source() {
let src = weak_ptr_source();
assert!(src.contains("weak_ptr"));
assert!(src.contains("expired"));
}
#[test]
fn test_accumulate_numeric_source() {
let src = accumulate_numeric_source();
assert!(src.contains("accumulate"));
}
#[test]
fn test_gcd_lcm_source() {
let src = gcd_lcm_source();
assert!(src.contains("gcd"));
assert!(src.contains("lcm"));
}
#[test]
fn test_exception_throw_catch_source() {
let src = exception_throw_catch_source();
assert!(src.contains("throw"));
assert!(src.contains("catch"));
}
#[test]
fn test_out_of_range_source() {
let src = out_of_range_source();
assert!(src.contains("out_of_range"));
assert!(src.contains("at("));
}
#[test]
fn test_build_stdlib_test_suite_not_empty() {
let suite = build_stdlib_test_suite();
assert!(!suite.is_empty());
}
#[test]
fn test_build_stdlib_test_suite_has_categories() {
let suite = build_stdlib_test_suite();
let cats: Vec<_> = suite.iter().map(|t| t.category.clone()).collect();
assert!(cats.contains(&"vector".to_string()));
assert!(cats.contains(&"string".to_string()));
assert!(cats.contains(&"map".to_string()));
assert!(cats.contains(&"sort".to_string()));
assert!(cats.contains(&"algorithm".to_string()));
assert!(cats.contains(&"smart_ptr".to_string()));
assert!(cats.contains(&"numeric".to_string()));
assert!(cats.contains(&"exception".to_string()));
}
#[test]
fn test_stdlib_test_case_with_flags() {
let tc = StdlibTestCase::new(
"test",
"int main() { return 0; }",
vec![],
)
.with_flags(&["-O2", "-Wall"]);
assert_eq!(tc.flags.len(), 3); }
#[test]
fn test_ir_check_pattern_exact_count() {
let pat = IrCheckPattern::exact("ret", "return", 1);
let ir = "ret i32 0";
assert!(pat.check(ir));
}
#[test]
fn test_ir_check_pattern_exact_count_fail() {
let pat = IrCheckPattern::exact("ret", "return", 1);
let ir = "ret i32 0\nret i32 1";
assert!(!pat.check(ir));
}
#[test]
fn test_ir_check_pattern_optional_not_required() {
let pat = IrCheckPattern::optional("fadd", "float");
let ir = "alloca i32";
assert!(pat.check(ir)); }
}