google test : 测试已有项目(模板类)

2023-12-21 16:42:21

项目结构如下:
在这里插入图片描述
greenNoiseMask 是原有项目
在解决方案中添加google test 项目:sample-test2
gtest基础使用02:测试已有项目中的类和函数

创建矩阵模板类

头文件:

 #pragma once
#include<vector>

template <typename T>
class Matrix {
private:
    std::vector<std::vector<T>> matrix;
    int m_nRows;
    int m_nCols;

public:
    // 构造函数
    Matrix(int m_nRows, int m_nCols, const T& initial = T());
    // 获取矩阵的行数和列数
    int numRows() const;  
    int numCols() const;

    // 获取矩阵中特定位置的元素
    T& at(int row, int col);
    // 获取矩阵元素的值
    T get(int row, int col) const;

    // 更新矩阵元素的值
    void set(int row, int col, const T& value);

    // 矩阵加法
    Matrix<T> operator+(const Matrix<T>& other) const;
  

    // 矩阵减法
    Matrix<T> operator-(const Matrix<T>& other) const;
    

    // 矩阵乘法
    Matrix<T> operator*(const Matrix<T>& other) const;
    
    // 统计矩阵中某个值的数量
    int countValue(const T& value) const;
};

// 矩阵加法 多线程
template <typename T>
Matrix<T> parallelMatrixAddition(const Matrix<T>& m1, const Matrix<T>& m2);

// 矩阵减法多线程
template <typename T>
Matrix<T> parallelMatrixSubtraction(const Matrix<T>& m1, const Matrix<T>& m2);

// 矩阵减法 多线程
template <typename T>
Matrix<T> parallelMatrixMultiply(const Matrix<T>& m1, const Matrix<T>& m2);

实现

 #include "Matrix.h"
#include<thread>
#include <stdexcept>
#include<iostream>

template class Matrix<int>;
template Matrix<int> Matrix<int>::operator+(const Matrix<int>& other) const;
template int Matrix<int>::numRows() const;
template int Matrix<int>::numCols() const;
template int& Matrix<int>::at(int row, int col);
template int Matrix<int>::get(int row, int col) const;
template void Matrix<int>::set(int row, int col, const int& value);
template Matrix<int> Matrix<int>::operator+(const Matrix<int>& other) const;
template Matrix<int> Matrix<int>::operator-(const Matrix<int>& other) const;
template Matrix<int> Matrix<int>::operator*(const Matrix<int>& other) const;
template int Matrix<int>::countValue(const int& value) const;
template Matrix<int> parallelMatrixAddition(const Matrix<int>& m1, const Matrix<int>& m2);
template Matrix<int> parallelMatrixSubtraction(const Matrix<int>& m1, const Matrix<int>& m2);
template Matrix<int> parallelMatrixMultiply(const Matrix<int>& m1, const Matrix<int>& m2);

template <typename T>
Matrix<T>::Matrix(int m_nRows, int m_nCols, const T& initial) : m_nRows(m_nRows), m_nCols(m_nCols), matrix(m_nRows, std::vector<T>(m_nCols, initial)) 
{}

template <typename T>
int Matrix<T>::numRows() const 
{ 
	return m_nRows; 
}

template <typename T>
int Matrix<T>::numCols() const 
{ 
	return m_nCols; 
}


// 获取矩阵中特定位置的元素
template <typename T>
T& Matrix<T>::at(int row, int col)
{
    if (row < 0 || row >= m_nRows || col < 0 || col >= m_nCols)
    {
        throw std::out_of_range("Invalid matrix index");
    }
    return matrix[row][col];
}

// 获取矩阵元素的值
template <typename T>
T Matrix<T>::get(int row, int col) const
{
    if (row < 0 || row >= m_nRows || col < 0 || col >= m_nCols)
    {
        throw std::out_of_range("Invalid matrix index");
    }
    return matrix[row][col];
}

// 更新矩阵元素的值
template <typename T>
void Matrix<T>::set(int row, int col, const T& value) {
    if (row < 0 || row >= m_nRows || col < 0 || col >= m_nCols) {
        throw std::out_of_range("Invalid matrix index");
    }
    matrix[row][col] = value;
}


// 矩阵加法
template <typename T>
Matrix<T> Matrix<T>::operator+(const Matrix<T>& other) const 
{
    if (m_nRows != other.m_nRows || m_nCols != other.m_nCols) 
    {
        throw std::invalid_argument("Matrix dimensions don't match for addition");
    }

    Matrix<T> result(m_nRows, m_nCols);
    for (int i = 0; i < m_nRows; ++i) 
    {
        for (int j = 0; j < m_nCols; ++j) 
        {
            result.matrix[i][j] = matrix[i][j] + other.get(i, j); 
        }
    }
    return result;
}

// 矩阵减法
template <typename T>
Matrix<T> Matrix<T>::operator-(const Matrix<T>& other) const 
{
    if (m_nRows != other.m_nRows || m_nCols != other.m_nCols)
    {
        throw std::invalid_argument("Matrix dimensions don't match for subtraction");
    }

    Matrix<T> result(m_nRows, m_nCols);
    for (int i = 0; i < m_nRows; ++i)
    {
        for (int j = 0; j < m_nCols; ++j) {
            result.matrix[i][j] = matrix[i][j] - other.get(i,j);// other.matrix[i][j];
        }
    }
    return result;
}



// 矩阵乘法
template <typename T>
Matrix<T> Matrix<T>::operator*(const Matrix<T>& other) const 
{
    if (m_nCols != other.m_nRows) 
    {
        throw std::invalid_argument("Matrix dimensions are not compatible for multiplication");
    }

    int resultRows = m_nRows;
    int resultCols = other.m_nCols;
    Matrix<T> result(resultRows, resultCols);

    for (int i = 0; i < resultRows; ++i)
    {
        for (int j = 0; j < resultCols; ++j)
        {
            result.matrix[i][j] = static_cast<T>(0);
            for (int k = 0; k < m_nCols; ++k)
            {
                result.matrix[i][j] += matrix[i][k] * other.get(k, j); 
            }
        }
    }
    return result;
}


// 统计矩阵中某个值的数量
template <typename T>
int Matrix<T>::countValue(const T& value) const
{
    int count = 0;
    for (int i = 0; i < m_nRows; ++i) {
        for (int j = 0; j < m_nCols; ++j) {
            if (matrix[i][j] == value) {
                count++;
            }
        }
    }
    return count;
}



template <typename T>
Matrix<T> parallelMatrixAddition(const Matrix<T>& m1, const Matrix<T>& m2)
{
    if (m1.numRows() != m2.numRows() || m1.numCols() != m2.numCols())
    {
        throw std::invalid_argument("Matrix dimensions don't match for addition");
    }

    Matrix<T> result(m1.numRows(), m1.numCols());
    std::vector<std::thread> threads;
    const int numThreads = std::thread::hardware_concurrency(); // Number of available threads
    const int rowsPerThread = (m1.numRows() + numThreads - 1) / numThreads; // Rows per thread

    for (int i = 0; i < numThreads; ++i)
    {
        threads.emplace_back([&m1, &m2, &result, i, rowsPerThread]()
            {
                for (int row = i * rowsPerThread; row < std::min((i + 1) * rowsPerThread, result.numRows()); ++row)
                {
                    for (int col = 0; col < result.numCols(); ++col)
                    {
                        result.at(row, col) = m1.get(row, col) + m2.get(row, col);
                    }
                }
            });
    }

    for (auto& thread : threads)
    {
        thread.join();
    }

    return result;
}



template <typename T>
Matrix<T> parallelMatrixSubtraction(const Matrix<T>& m1, const Matrix<T>& m2)
{
    if (m1.numRows() != m2.numRows() || m1.numCols() != m2.numCols())
    {
        throw std::invalid_argument("Matrix dimensions don't match for subtraction");
    }

    Matrix<T> result(m1.numRows(), m1.numCols());
    std::vector<std::thread> threads;
    const int numThreads = std::thread::hardware_concurrency(); // Number of available threads
    const int rowsPerThread = (m1.numRows() + numThreads - 1) / numThreads; // Rows per thread

    for (int i = 0; i < numThreads; ++i)
    {
        threads.emplace_back([&m1, &m2, &result, i, rowsPerThread]()
            {
                for (int row = i * rowsPerThread; row < std::min((i + 1) * rowsPerThread, result.numRows()); ++row)
                {
                    for (int col = 0; col < result.numCols(); ++col)
                    {
                        result.at(row, col) = m1.get(row, col) - m2.get(row, col);
                    }
                }
            });
    }

    for (auto& thread : threads)
    {
        thread.join();
    }

    return result;
}


template <typename T>
Matrix<T>  parallelMatrixMultiply(const Matrix<T>& m1, const Matrix<T>& m2)
{
    if (m1.numCols() != m2.numRows())
    {
        throw std::invalid_argument("Matrix dimensions are not compatible for multiplication");
    }

    int resultRows = m1.numRows();
    int resultCols = m2.numCols();
    Matrix<T> result(resultRows, resultCols);

    std::vector<std::thread> threads;
    //std::mutex mutex; // Mutex to control access to the result matrix

    const int numThreads = std::thread::hardware_concurrency(); // Number of available threads
    const int rowsPerThread = (resultRows + numThreads - 1) / numThreads; // Rows per thread

    for (int i = 0; i < numThreads; ++i) {
        threads.emplace_back([&m1, &m2, &result, i, rowsPerThread]()
            {
                for (int row = i * rowsPerThread; row < std::min((i + 1) * rowsPerThread, result.numRows()); ++row)
                {
                    for (int col = 0; col < result.numCols(); ++col)
                    {
                        T sum = static_cast<T>(0);
                        for (int k = 0; k < m1.numCols(); ++k)
                        {
                            sum += m1.get(row, k) * m2.get(k, col);
                        }
                        //std::lock_guard<std::mutex> lock(mutex);
                        result.set(row, col, sum);
                    }
                }
            });
    }

    for (auto& thread : threads)
    {
        thread.join();
    }

    return result;
}



google test

#include "pch.h"
#include "..\greenNoiseMask\Matrix.h"


// 测试构造函数和矩阵元素访问
TEST(MatrixTest, ConstructionAndAccess) {
    // 创建一个矩阵
    Matrix<int> mat(2, 2);

    // 测试矩阵是否被正确构建
    EXPECT_EQ(mat.numRows(), 2);
    EXPECT_EQ(mat.numCols(), 2);

    // 测试矩阵元素访问
    mat.at(0, 0) = 5;
    mat.at(1, 1) = 10;

    EXPECT_EQ(mat.at(0, 0), 5);
    EXPECT_EQ(mat.at(1, 1), 10);

    // 测试矩阵元素更新
    mat.set(0, 0, 2) ;
    mat.set(1, 1,6) ;
}

// 测试矩阵加法
TEST(MatrixTest, Addition) {
    // 创建两个矩阵
    Matrix<int> mat1(2, 2);
    Matrix<int> mat2(2, 2);

    // 设置矩阵元素
    mat1.at(0, 0) = 1;
    mat1.at(0, 1) = 2;
    mat1.at(1, 0) = 3;
    mat1.at(1, 1) = 4;

    mat2.at(0, 0) = 5;
    mat2.at(0, 1) = 6;
    mat2.at(1, 0) = 7;
    mat2.at(1, 1) = 8;

    // 执行加法操作
    Matrix<int> result = mat1 + mat2;

    // 检查加法结果是否正确
    EXPECT_EQ(result.at(0, 0), 6);
    EXPECT_EQ(result.at(0, 1), 8);
    EXPECT_EQ(result.at(1, 0), 10);
    EXPECT_EQ(result.at(1, 1), 12);
   
}

// 测试矩阵加法
TEST(MatrixTest, parallelAddition) {
    // 创建两个矩阵
    Matrix<int> mat1(10, 10);
    Matrix<int> mat2(10, 10);

    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            mat1.at(i, j) = i + j;
            mat2.at(i, j) = -(i + j);
        }
    }
    // 执行加法操作
    Matrix<int> result = parallelMatrixAddition<int>(mat1, mat2);
    // 检查加法结果是否正确
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            EXPECT_EQ(result.at(i, j), 0);
        }
    }
}

// 测试矩阵减法
TEST(MatrixTest, subtraction) {
    // 创建两个矩阵
    Matrix<int> mat1(2, 2);
    Matrix<int> mat2(2, 2);

    // 设置矩阵元素
    mat1.at(0, 0) = 1;
    mat1.at(0, 1) = 2;
    mat1.at(1, 0) = 3;
    mat1.at(1, 1) = 4;

    mat2.at(0, 0) = 5;
    mat2.at(0, 1) = 6;
    mat2.at(1, 0) = 7;
    mat2.at(1, 1) = 8;

    // 执行减法操作
    Matrix<int> result = mat1 - mat2;

    // 检查减法结果是否正确
    EXPECT_EQ(result.at(0, 0), -4);
    EXPECT_EQ(result.at(0, 1), -4);
    EXPECT_EQ(result.at(1, 0), -4);
    EXPECT_EQ(result.at(1, 1), -4);

}

TEST(MatrixTest, parallelSubtraction) {
    // 创建两个矩阵
    Matrix<int> mat1(10, 10);
    Matrix<int> mat2(10, 10);

    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            mat1.at(i, j) = i + j;
            mat2.at(i, j) = (i + j);
        }
    }
    // 执行减法操作
    Matrix<int> result = parallelMatrixSubtraction<int>(mat1, mat2);
    // 检查减法结果是否正确
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            EXPECT_EQ(result.at(i, j), 0);
        }
    }
}

// 测试矩阵乘法
TEST(MatrixTest, multiplication) {
    // 创建两个矩阵
    Matrix<int> mat1(2, 2);
    Matrix<int> mat2(2, 2);

    // 设置矩阵元素
    mat1.at(0, 0) = 1;
    mat1.at(0, 1) = 2;
    mat1.at(1, 0) = 3;
    mat1.at(1, 1) = 4;

    mat2.at(0, 0) = 5;
    mat2.at(0, 1) = 6;
    mat2.at(1, 0) = 7;
    mat2.at(1, 1) = 8;

    // 执行乘法操作
    Matrix<int> result = mat1 * mat2;

    // 检查乘法结果是否正确
    EXPECT_EQ(result.at(0, 0), 19);
    EXPECT_EQ(result.at(0, 1), 22);
    EXPECT_EQ(result.at(1, 0), 43);
    EXPECT_EQ(result.at(1, 1), 50);

}

TEST(MatrixTest, parallelMatrixMultiply) {
    // 创建两个矩阵
    Matrix<int> mat1(10, 10);
    Matrix<int> mat2(10, 10);

    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            mat1.at(i, j) = i + j;
            if (i == j)
            {
                mat2.at(i, j) = 1;
            }
            else
            {
                mat2.at(i, j) = 0;
            }
            
        }
    }
    // 执行减法操作
    Matrix<int> result = parallelMatrixMultiply<int>(mat1, mat2);
    // 检查减法结果是否正确
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            EXPECT_EQ(result.at(i, j), i+j);
        }
    }
}

int main(int argc, char** argv) {
    printf("Running main() from %s\n", __FILE__);
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

运行结果
在这里插入图片描述

因为测试文件中使用了 Matrix 实例化,但是在自己的项目中 没有加

template class Matrix<int>;
template Matrix<int> Matrix<int>::operator+(const Matrix<int>& other) const;
template int Matrix<int>::numRows() const;
template int Matrix<int>::numCols() const;
template int& Matrix<int>::at(int row, int col);
template int Matrix<int>::get(int row, int col) const;
template void Matrix<int>::set(int row, int col, const int& value);
template Matrix<int> Matrix<int>::operator+(const Matrix<int>& other) const;
template Matrix<int> Matrix<int>::operator-(const Matrix<int>& other) const;
template Matrix<int> Matrix<int>::operator*(const Matrix<int>& other) const;
template int Matrix<int>::countValue(const int& value) const;
template Matrix<int> parallelMatrixAddition(const Matrix<int>& m1, const Matrix<int>& m2);
template Matrix<int> parallelMatrixSubtraction(const Matrix<int>& m1, const Matrix<int>& m2);
template Matrix<int> parallelMatrixMultiply(const Matrix<int>& m1, const Matrix<int>& m2);

导致 google test 一直报错:VS “error LNK2019: 无法解析的外部符号 …”

参考
【C++】模板(template)进阶

因为模板需要编译两次:

  1. 在声明函数模板地方编译一次
  2. 在调用的地方再编译一次。

如果没有加上面的实例化的模板,编译器链接的时候 不知道有Matrix 会报错
所以需要在自己的项目中 实例化要用的模板类,生成的lib 在Google test项目中才能使用

文章来源:https://blog.csdn.net/fuyouzhiyi/article/details/135132622
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。