use super::common::*;
use crate::embed::build_embedding_text;
use crate::parser::Language;
#[test]
fn test_basic_function() {
let source = r#"int add(int a, int b) {
return a + b;
}"#;
let units = parse(source, Language::Cpp, "test.cpp");
let unit = get_unit_by_name(&units, "add").unwrap();
let text = build_embedding_text(unit);
let expected = r#"Function: add
Signature: int add(int a, int b) {
Parameters: a, b
Returns: int
File: test test.cpp
Code:
int add(int a, int b) {
return a + b;
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_class_definition() {
let source = r#"class Calculator {
public:
int add(int a, int b) {
return a + b;
}
private:
int value;
};"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 1);
let class = get_unit_by_name(&units, "Calculator").unwrap();
let class_text = build_embedding_text(class);
let expected_class = r#"Class: Calculator
Signature: class Calculator {
File: test test.cpp
Code:
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
private:
int value;
};"#;
assert_eq!(class_text, expected_class);
assert!(
get_unit_by_name(&units, "add").is_none(),
"Methods should not be extracted separately from classes"
);
}
#[test]
fn test_method_with_doxygen() {
let source = r#"class Math {
public:
/**
* @brief Calculates the sum of two numbers.
* @param a First number
* @param b Second number
* @return Sum of a and b
*/
int add(int a, int b) {
return a + b;
}
};"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 1);
let class_unit = get_unit_by_name(&units, "Math").unwrap();
let class_text = build_embedding_text(class_unit);
let expected = r#"Class: Math
Signature: class Math {
File: test test.cpp
Code:
class Math {
public:
/**
* @brief Calculates the sum of two numbers.
* @param a First number
* @param b Second number
* @return Sum of a and b
*/
int add(int a, int b) {
return a + b;
}
};"#;
assert_eq!(class_text, expected);
assert!(
get_unit_by_name(&units, "add").is_none(),
"Methods should not be extracted separately from classes"
);
}
#[test]
fn test_template_function() {
let source = r#"template<typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}"#;
let units = parse(source, Language::Cpp, "test.cpp");
let unit = get_unit_by_name(&units, "max").unwrap();
let text = build_embedding_text(unit);
let expected = r#"Function: max
Signature: T max(T a, T b) {
Parameters: a, b
Returns: T
File: test test.cpp
Code:
T max(T a, T b) {
return (a > b) ? a : b;
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_namespace_function() {
let source = r#"namespace utils {
int helper(int x) {
return x * 2;
}
}"#;
let units = parse(source, Language::Cpp, "test.cpp");
let unit = get_unit_by_name(&units, "helper").unwrap();
let text = build_embedding_text(unit);
let expected = r#"Function: helper
Signature: int helper(int x) {
Parameters: x
Returns: int
File: test test.cpp
Code:
int helper(int x) {
return x * 2;
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_constructor() {
let source = r#"class Person {
public:
Person(const std::string& name, int age)
: name_(name), age_(age) {}
private:
std::string name_;
int age_;
};"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 1);
let class_unit = get_unit_by_name(&units, "Person").unwrap();
let class_text = build_embedding_text(class_unit);
let expected = r#"Class: Person
Signature: class Person {
File: test test.cpp
Code:
class Person {
public:
Person(const std::string& name, int age)
: name_(name), age_(age) {}
private:
std::string name_;
int age_;
};"#;
assert_eq!(class_text, expected);
let person_units: Vec<_> = units.iter().filter(|u| u.name == "Person").collect();
assert_eq!(
person_units.len(),
1,
"Should only have 1 Person unit (the class), not separate constructor"
);
}
#[test]
fn test_virtual_method() {
let source = r#"class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() = default;
};"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 1);
let class_unit = get_unit_by_name(&units, "Shape").unwrap();
let class_text = build_embedding_text(class_unit);
let expected = r#"Class: Shape
Signature: class Shape {
File: test test.cpp
Code:
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() = default;
};"#;
assert_eq!(class_text, expected);
assert!(
get_unit_by_name(&units, "~Shape").is_none(),
"Destructors should not be extracted separately from classes"
);
assert!(
get_unit_by_name(&units, "area").is_none(),
"Methods should not be extracted separately from classes"
);
}
#[test]
fn test_function_with_stl() {
let source = r#"#include <vector>
#include <algorithm>
std::vector<int> filter_positive(const std::vector<int>& nums) {
std::vector<int> result;
std::copy_if(nums.begin(), nums.end(), std::back_inserter(result),
[](int x) { return x > 0; });
return result;
}"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 3);
let unit = get_unit_by_name(&units, "filter_positive").unwrap();
let text = build_embedding_text(unit);
let expected = r#"Function: filter_positive
Signature: std::vector<int> filter_positive(const std::vector<int>& nums) {
Parameters: nums
Returns: std::vector<int>
Calls: back_inserter, begin, copy_if, end
Variables: result
File: test test.cpp
Code:
std::vector<int> filter_positive(const std::vector<int>& nums) {
std::vector<int> result;
std::copy_if(nums.begin(), nums.end(), std::back_inserter(result),
[](int x) { return x > 0; });
return result;
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_struct_with_methods() {
let source = r#"struct Point {
double x, y;
double distance() const {
return std::sqrt(x*x + y*y);
}
};"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 1);
let unit = get_unit_by_name(&units, "Point").unwrap();
let text = build_embedding_text(unit);
let expected = r#"Class: Point
Signature: struct Point {
Calls: sqrt
File: test test.cpp
Code:
struct Point {
double x, y;
double distance() const {
return std::sqrt(x*x + y*y);
}
};"#;
assert_eq!(text, expected);
assert!(
get_unit_by_name(&units, "distance").is_none(),
"Methods should not be extracted separately from structs"
);
}
#[test]
fn test_operator_overload() {
let source = r#"class Vector {
public:
Vector operator+(const Vector& other) const {
return Vector(x + other.x, y + other.y);
}
private:
double x, y;
};"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 1);
let class_unit = get_unit_by_name(&units, "Vector").unwrap();
let class_text = build_embedding_text(class_unit);
let expected = r#"Class: Vector
Signature: class Vector {
Calls: Vector
File: test test.cpp
Code:
class Vector {
public:
Vector operator+(const Vector& other) const {
return Vector(x + other.x, y + other.y);
}
private:
double x, y;
};"#;
assert_eq!(class_text, expected);
assert!(
get_unit_by_name(&units, "operator+").is_none(),
"Operator overloads should not be extracted separately from classes"
);
}
#[test]
fn test_constexpr_function() {
let source = r#"constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 1);
let unit = get_unit_by_name(&units, "factorial").unwrap();
let text = build_embedding_text(unit);
let expected = r#"Function: factorial
Signature: constexpr int factorial(int n) {
Parameters: n
Returns: int
Calls: factorial
File: test test.cpp
Code:
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_class_inheritance() {
let source = r#"class Animal {
public:
virtual void speak() {
std::cout << "..." << std::endl;
}
};
class Dog : public Animal {
public:
void speak() override {
std::cout << "Woof!" << std::endl;
}
};"#;
let units = parse(source, Language::Cpp, "test.cpp");
assert_eq!(units.len(), 2);
let animal = get_unit_by_name(&units, "Animal").unwrap();
let animal_text = build_embedding_text(animal);
let expected_animal = r#"Class: Animal
Signature: class Animal {
File: test test.cpp
Code:
class Animal {
public:
virtual void speak() {
std::cout << "..." << std::endl;
}
};"#;
assert_eq!(animal_text, expected_animal);
assert!(!animal_text.contains("Extends:"));
let dog = get_unit_by_name(&units, "Dog").unwrap();
let dog_text = build_embedding_text(dog);
let expected_dog = r#"Class: Dog
Signature: class Dog : public Animal {
Extends: Animal
File: test test.cpp
Code:
class Dog : public Animal {
public:
void speak() override {
std::cout << "Woof!" << std::endl;
}
};"#;
assert_eq!(dog_text, expected_dog);
assert!(
get_unit_by_name(&units, "speak").is_none(),
"Methods should not be extracted separately from classes"
);
}
#[test]
fn test_uses_not_applicable() {
let source = r#"#include <iostream>
#include <vector>
void print_values(const std::vector<int>& values) {
for (int v : values) {
std::cout << v << std::endl;
}
}"#;
let units = parse(source, Language::Cpp, "test.cpp");
let func = get_unit_by_name(&units, "print_values").unwrap();
let text = build_embedding_text(func);
let expected = r#"Function: print_values
Signature: void print_values(const std::vector<int>& values) {
Parameters: values
Returns: void
File: test test.cpp
Code:
void print_values(const std::vector<int>& values) {
for (int v : values) {
std::cout << v << std::endl;
}
}"#;
assert_eq!(text, expected);
}