חזור לתיקייה: wet

tests_full

חיפוש בתיקיה
Ctrl K
לחץ כאן או הקש Ctrl K כדי לחפש בכל התיקיה

    tests_full

    02340124

    מבוא לתכנות מערכות

    רשימות הרצאה לקריאה בשבת

    tests_full

    הופק מתוך תקיית התואר של שקד

    uni-folder.vercel.app

    tests-full.cpp

    הערה (קובץ קוד)

    קובץ זה הוא קובץ קוד מסוג CPP.

    #include <iostream>
    #include <sstream>
    #include <string>
    #include "Matrix.h"
    #include "MataMvidia.h"
    #include "tests_matamvidia_extra.h"
    
    using namespace std;
    
    // ─── Test infrastructure ────────────────────────────────────────────────────
    
    static int passed = 0, failed = 0;
    
    #define CHECK(label, expr)                                              \
        do {                                                                \
            if (expr) {                                                     \
                std::cout << "  [PASS] " << label << "\n";                  \
                ++passed;                                                   \
            } else {                                                        \
                std::cout << "  [FAIL] " << label                          \
                          << "  (" << __FILE__ << ":" << __LINE__ << ")\n";\
                ++failed;                                                   \
            }                                                               \
        } while (0)
    
    // ─── Helper ─────────────────────────────────────────────────────────────────
    
    static Matrix make2x2(int a, int b, int c, int d) {
        Matrix m(2, 2);
        m(0,0)=a; m(0,1)=b;
        m(1,0)=c; m(1,1)=d;
        return m;
    }
    
    static Matrix make3x3(int vals[9]) {
        Matrix m(3, 3);
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                m(i, j) = vals[i*3+j];
        return m;
    }
    
    // ─── Matrix Tests ────────────────────────────────────────────────────────────
    
    void test_matrix_construction() {
        cout << "\n[Matrix Construction]\n";
    
        Matrix zero;
        CHECK("default constructor rows/cols are 0 (no crash)", true); // just don't crash
    
        Matrix m(3, 4, 7);
        bool allSeven = true;
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 4; j++)
                if (m(i,j) != 7) allSeven = false;
        CHECK("fill-value constructor sets all cells", allSeven);
    
        Matrix m2(2, 2, 0);
        CHECK("fill-value 0 constructor", m2(0,0)==0 && m2(1,1)==0);
    
        Matrix m1x1(1, 1, 42);
        CHECK("1x1 matrix value", m1x1(0,0) == 42);
    }
    
    void test_matrix_copy() {
        cout << "\n[Matrix Copy & Assignment]\n";
    
        Matrix a = make2x2(1, 2, 3, 4);
        Matrix b(a);
        CHECK("copy constructor produces equal matrix", a == b);
    
        b(0,0) = 99;
        CHECK("copy is independent (deep copy)", a(0,0) == 1);
    
        Matrix c(2,2);
        c = a;
        CHECK("assignment operator works", c == a);
    
        c(1,1) = 55;
        CHECK("assigned copy is independent", a(1,1) == 4);
    
        // self-assignment
        a = a;
        CHECK("self-assignment safe", a(0,0) == 1 && a(1,1) == 4);
    }
    
    void test_matrix_addition() {
        cout << "\n[Matrix Addition]\n";
    
        Matrix a = make2x2(1, 2, 3, 4);
        Matrix b = make2x2(5, 6, 7, 8);
        Matrix c = a + b;
        CHECK("operator+ (0,0)", c(0,0) == 6);
        CHECK("operator+ (0,1)", c(0,1) == 8);
        CHECK("operator+ (1,0)", c(1,0) == 10);
        CHECK("operator+ (1,1)", c(1,1) == 12);
    
        Matrix d = a;
        d += b;
        CHECK("operator+= matches operator+", d == c);
    
        // Adding zero matrix
        Matrix zero(2,2,0);
        CHECK("adding zero matrix is identity", a + zero == a);
    }
    
    void test_matrix_subtraction() {
        cout << "\n[Matrix Subtraction]\n";
    
        Matrix a = make2x2(10, 8, 6, 4);
        Matrix b = make2x2(1, 2, 3, 4);
        Matrix c = a - b;
        CHECK("operator- (0,0)", c(0,0) == 9);
        CHECK("operator- (1,1)", c(1,1) == 0);
    
        Matrix d = a;
        d -= b;
        CHECK("operator-= matches operator-", d == c);
    
        // a - a = zero
        Matrix zero(2,2,0);
        CHECK("a - a == zero", a - a == zero);
    }
    
    void test_matrix_multiplication() {
        cout << "\n[Matrix Multiplication]\n";
    
        Matrix a = make2x2(1, 2, 3, 4);
        Matrix b = make2x2(5, 6, 7, 8);
        Matrix c = a * b;
        // [1*5+2*7, 1*6+2*8, 3*5+4*7, 3*6+4*8] = [19,22,43,50]
        CHECK("operator* (0,0)", c(0,0) == 19);
        CHECK("operator* (0,1)", c(0,1) == 22);
        CHECK("operator* (1,0)", c(1,0) == 43);
        CHECK("operator* (1,1)", c(1,1) == 50);
    
        Matrix d = a;
        d *= b;
        CHECK("operator*= matches operator*", d == c);
    
        // non-square: 2x3 * 3x2
        Matrix p(2, 3, 0);
        p(0,0)=1; p(0,1)=2; p(0,2)=3;
        p(1,0)=4; p(1,1)=5; p(1,2)=6;
        Matrix q(3, 2, 0);
        q(0,0)=7;  q(0,1)=8;
        q(1,0)=9;  q(1,1)=10;
        q(2,0)=11; q(2,1)=12;
        Matrix pq = p * q;
        // row0: 1*7+2*9+3*11=58, 1*8+2*10+3*12=64
        // row1: 4*7+5*9+6*11=139, 4*8+5*10+6*12=154
        CHECK("non-square multiply (0,0)", pq(0,0) == 58);
        CHECK("non-square multiply (0,1)", pq(0,1) == 64);
        CHECK("non-square multiply (1,0)", pq(1,0) == 139);
        CHECK("non-square multiply (1,1)", pq(1,1) == 154);
    }
    
    void test_matrix_scalar_multiplication() {
        cout << "\n[Matrix Scalar Multiplication]\n";
    
        Matrix a = make2x2(1, 2, 3, 4);
        Matrix b = a * 3;
        CHECK("mat * scalar (0,0)", b(0,0) == 3);
        CHECK("mat * scalar (1,1)", b(1,1) == 12);
    
        Matrix c = 3 * a;
        CHECK("scalar * mat == mat * scalar", b == c);
    
        Matrix d = a;
        d *= 2;
        CHECK("operator*= scalar", d(0,1) == 4 && d(1,0) == 6);
    
        CHECK("multiply by 0 gives zero matrix", (a * 0) == Matrix(2,2,0));
        CHECK("multiply by 1 is identity", (a * 1) == a);
        CHECK("multiply by -1 == unary minus", (a * -1) == -a);
    }
    
    void test_matrix_unary_minus() {
        cout << "\n[Matrix Unary Minus]\n";
    
        Matrix a = make2x2(1, -2, 0, 4);
        Matrix neg = -a;
        CHECK("unary minus (0,0)", neg(0,0) == -1);
        CHECK("unary minus (0,1)", neg(0,1) == 2);
        CHECK("unary minus (1,0)", neg(1,0) == 0);
        CHECK("unary minus negated back", -neg == a);
    }
    
    void test_matrix_equality() {
        cout << "\n[Matrix Equality]\n";
    
        Matrix a = make2x2(1,2,3,4);
        Matrix b = make2x2(1,2,3,4);
        Matrix c = make2x2(1,2,3,5);
        CHECK("equal matrices", a == b);
        CHECK("unequal matrices !=", a != c);
        CHECK("different size matrices !=", a != Matrix(3,3,0));
    }
    
    void test_matrix_transpose() {
        cout << "\n[Matrix Transpose]\n";
    
        Matrix a = make2x2(1,2,3,4);
        Matrix t = a.transpose();
        CHECK("transpose (0,1) swapped", t(0,1) == 3);
        CHECK("transpose (1,0) swapped", t(1,0) == 2);
        CHECK("double transpose is identity", t.transpose() == a);
    
        // non-square 2x3
        Matrix m(2,3,0);
        m(0,0)=1; m(0,1)=2; m(0,2)=3;
        m(1,0)=4; m(1,1)=5; m(1,2)=6;
        Matrix mt = m.transpose();
        CHECK("non-square transpose dims (row)", mt(0,0)==1 && mt(1,0)==2 && mt(2,0)==3);
        CHECK("non-square transpose dims (col)", mt(0,1)==4 && mt(1,1)==5 && mt(2,1)==6);
    }
    
    void test_matrix_rotate() {
        cout << "\n[Matrix Rotate]\n";
    
        Matrix a = make2x2(1,2,3,4);
    
        // CW: top-left→top-right, bottom-left→top-left, etc.
        // original:      CW:
        // 1 2     →    3 1
        // 3 4          4 2
        Matrix cw = a.rotateClockwise();
        CHECK("CW (0,0)", cw(0,0) == 3);
        CHECK("CW (0,1)", cw(0,1) == 1);
        CHECK("CW (1,0)", cw(1,0) == 4);
        CHECK("CW (1,1)", cw(1,1) == 2);
    
        // CCW: 1 2 → 2 4 / 1 3
        //      3 4
        Matrix ccw = a.rotateCounterClockwise();
        CHECK("CCW (0,0)", ccw(0,0) == 2);
        CHECK("CCW (0,1)", ccw(0,1) == 4);
        CHECK("CCW (1,0)", ccw(1,0) == 1);
        CHECK("CCW (1,1)", ccw(1,1) == 3);
    
        CHECK("CW then CCW is identity", a.rotateClockwise().rotateCounterClockwise() == a);
        CHECK("CCW then CW is identity", a.rotateCounterClockwise().rotateClockwise() == a);
        CHECK("4x CW is identity", a.rotateClockwise().rotateClockwise().rotateClockwise().rotateClockwise() == a);
    }
    
    void test_matrix_frobenius_norm() {
        cout << "\n[Matrix Frobenius Norm]\n";
    
        Matrix a = make2x2(1, 0, 0, 1);  // identity → norm = sqrt(2)
        double norm = Matrix::CalcFrobeniusNorm(a);
        CHECK("identity 2x2 norm ≈ sqrt(2)", norm > 1.41 && norm < 1.42);
    
        Matrix b(2,2,0);
        CHECK("zero matrix norm == 0", Matrix::CalcFrobeniusNorm(b) == 0.0);
    
        Matrix c = make2x2(3, 4, 0, 0);  // sqrt(9+16) = 5
        CHECK("3-4-0-0 norm == 5", Matrix::CalcFrobeniusNorm(c) == 5.0);
    }
    
    void test_matrix_determinant() {
        cout << "\n[Matrix Determinant]\n";
    
        Matrix a = make2x2(1,2,3,4);  // det = 1*4 - 2*3 = -2
        CHECK("2x2 determinant", Matrix::CalcDeterminant(a) == -2);
    
        Matrix identity2 = make2x2(1,0,0,1);
        CHECK("2x2 identity det == 1", Matrix::CalcDeterminant(identity2) == 1);
    
        // 3x3
        int v[] = {1,2,3, 4,5,6, 7,8,9};
        Matrix m3 = make3x3(v);
        CHECK("singular 3x3 det == 0", Matrix::CalcDeterminant(m3) == 0);
    
        int v2[] = {2,0,0, 0,3,0, 0,0,4};
        Matrix diag = make3x3(v2);
        CHECK("diagonal 3x3 det == 24", Matrix::CalcDeterminant(diag) == 24);
    
        Matrix m1x1(1, 1, 7);
        CHECK("1x1 determinant", Matrix::CalcDeterminant(m1x1) == 7);
    }
    
    void test_matrix_output() {
        cout << "\n[Matrix Output]\n";
    
        Matrix a = make2x2(5,6,7,8);
        std::ostringstream oss;
        oss << a;
        string out = oss.str();
        CHECK("output contains |5|", out.find("|5|") != string::npos);
        CHECK("output contains |8|", out.find("|8|") != string::npos);
    }
    
    // ─── MataMvidia Tests ────────────────────────────────────────────────────────
    
    static MataMvidia make_movie(const string& name="TestMovie",
                                  const string& author="Tester",
                                  int numFrames=2) {
        Matrix* arr = new Matrix[numFrames];
        for (int i = 0; i < numFrames; i++)
            arr[i] = make2x2(i*10+1, i*10+2, i*10+3, i*10+4);
        MataMvidia mv(name, author, arr, numFrames);
        delete[] arr;
        return mv;
    }
    
    void test_matamvidia_construction() {
        cout << "\n[MataMvidia Construction]\n";
    
        Matrix arr[3];
        arr[0] = make2x2(1,2,3,4);
        arr[1] = make2x2(5,6,7,8);
        arr[2] = make2x2(9,10,11,12);
    
        MataMvidia mv("Film", "Director", arr, 3);
        CHECK("frame 0 correct", mv[0] == arr[0]);
        CHECK("frame 1 correct", mv[1] == arr[1]);
        CHECK("frame 2 correct", mv[2] == arr[2]);
    }
    
    void test_matamvidia_copy() {
        cout << "\n[MataMvidia Copy & Assignment]\n";
    
        MataMvidia mv = make_movie();
        MataMvidia mv2(mv);
        CHECK("copy constructor: frame 0 equal", mv2[0] == mv[0]);
    
        mv2[0](0,0) = 999;
        CHECK("copy is deep (modifying copy doesn't affect original)", mv[0](0,0) != 999);
    
        MataMvidia mv3 = make_movie("Other","Auth");
        mv3 = mv;
        CHECK("assignment: frame 0 equal", mv3[0] == mv[0]);
    
        mv3[0](0,0) = 777;
        CHECK("assigned copy is deep", mv[0](0,0) != 777);
    
        // self-assignment
        mv = mv;
        CHECK("self-assignment safe", mv[0](0,0) == 1);
    }
    
    void test_matamvidia_append_frame() {
        cout << "\n[MataMvidia Append Frame]\n";
    
        MataMvidia mv = make_movie("M","A",1);
        Matrix extra = make2x2(9,9,9,9);
        mv += extra;
        CHECK("frame count grows after += frame", mv[1] == extra);
    
        // append many frames (triggers expand)
        for (int i = 0; i < 20; i++) {
            Matrix f = make2x2(i,i,i,i);
            mv += f;
        }
        CHECK("after 20 appends, frame 2 value", mv[2](0,0) == 0);
        CHECK("last appended frame correct", mv[21](0,0) == 19);
    }
    
    void test_matamvidia_append_movie() {
        cout << "\n[MataMvidia Append Movie]\n";
    
        Matrix a1[2] = { make2x2(1,1,1,1), make2x2(2,2,2,2) };
        Matrix a2[2] = { make2x2(3,3,3,3), make2x2(4,4,4,4) };
    
        MataMvidia mv1("A","x", a1, 2);
        MataMvidia mv2("B","y", a2, 2);
    
        mv1 += mv2;
        CHECK("+= movie: frame 2 is first of mv2", mv1[2] == a2[0]);
        CHECK("+= movie: frame 3 is second of mv2", mv1[3] == a2[1]);
        CHECK("+= movie: original frames unchanged", mv1[0] == a1[0]);
    }
    
    void test_matamvidia_operator_plus() {
        cout << "\n[MataMvidia operator+]\n";
    
        Matrix a1[2] = { make2x2(1,2,3,4), make2x2(5,6,7,8) };
        Matrix a2[2] = { make2x2(9,10,11,12), make2x2(13,14,15,16) };
    
        MataMvidia mv1("M1","A", a1, 2);
        MataMvidia mv2("M2","B", a2, 2);
    
        MataMvidia mv3 = mv1 + mv2;
        CHECK("operator+: first frame from mv1", mv3[0] == a1[0]);
        CHECK("operator+: second frame from mv1", mv3[1] == a1[1]);
        CHECK("operator+: third frame from mv2", mv3[2] == a2[0]);
        CHECK("operator+: fourth frame from mv2", mv3[3] == a2[1]);
    
        // originals unchanged
        CHECK("mv1 unchanged after +", mv1[0] == a1[0]);
        CHECK("mv2 unchanged after +", mv2[0] == a2[0]);
    }
    
    void test_matamvidia_index_access() {
        cout << "\n[MataMvidia Index Access]\n";
    
        MataMvidia mv = make_movie("M","A",3);
        Matrix f = mv[1];
        CHECK("const [] access", f == mv[1]);
    
        mv[0](0,0) = 42;
        CHECK("non-const [] allows mutation", mv[0](0,0) == 42);
    }
    
    void test_matamvidia_output() {
        cout << "\n[MataMvidia Output]\n";
    
        Matrix arr[1] = { make2x2(1,2,3,4) };
        MataMvidia mv("CoolFilm","CoolAuthor",arr,1);
    
        std::ostringstream oss;
        oss << mv;
        string out = oss.str();
    
        CHECK("output has movie name", out.find("CoolFilm") != string::npos);
        CHECK("output has author", out.find("CoolAuthor") != string::npos);
        CHECK("output has Frame 0", out.find("Frame 0") != string::npos);
        CHECK("output has End marker", out.find("-----End of Movie-----") != string::npos);
        CHECK("output has frame contents", out.find("|1|") != string::npos);
    }
    
    void test_matamvidia_large_expand() {
        cout << "\n[MataMvidia Large Expand]\n";
    
        Matrix arr[1] = { make2x2(0,0,0,0) };
        MataMvidia mv("X","Y",arr,1);
    
        // Force multiple expansions
        for (int i = 1; i <= 50; i++) {
            mv += make2x2(i, i, i, i);
        }
        CHECK("after 50 appends, frame 50 correct", mv[50](0,0) == 50);
        CHECK("frame 1 still correct after many expands", mv[1](0,0) == 1);
        CHECK("frame 25 correct", mv[25](0,0) == 25);
    }
    
    void test_matamvidia_append_to_empty_movie() {
        cout << "\n[MataMvidia Edge: 0-frame base]\n";
    
        Matrix empty[1] = { make2x2(7,7,7,7) };
        MataMvidia mv("Empty","Nobody", empty, 1);
        // Not truly empty since MataMvidia needs >=1 to construct,
        // but test single-frame movie appended to
        mv += make2x2(8,8,8,8);
        CHECK("single-frame base + 1 frame", mv[1](0,0) == 8);
    }
    
    // ─── Main ────────────────────────────────────────────────────────────────────
    
    int main() {
        cout << "========================================\n";
        cout << "  WET Part: Full Test Suite\n";
        cout << "========================================\n";
    
        // Matrix
        test_matrix_construction();
        test_matrix_copy();
        test_matrix_addition();
        test_matrix_subtraction();
        test_matrix_multiplication();
        test_matrix_scalar_multiplication();
        test_matrix_unary_minus();
        test_matrix_equality();
        test_matrix_transpose();
        test_matrix_rotate();
        test_matrix_frobenius_norm();
        test_matrix_determinant();
        test_matrix_output();
    
        // MataMvidia
        test_matamvidia_construction();
        test_matamvidia_copy();
        test_matamvidia_append_frame();
        test_matamvidia_append_movie();
        test_matamvidia_operator_plus();
        test_matamvidia_index_access();
        test_matamvidia_output();
        test_matamvidia_large_expand();
        test_matamvidia_append_to_empty_movie();
    
        // Extra MataMvidia tests
        cout << "\n--- Extra MataMvidia Tests ---\n";
        test_frame_order_preserved();
        test_mixed_frame_sizes();
        test_copy_ctor_independence_both_ways();
        test_chained_assignment();
        test_append_movie_doesnt_alter_argument();
        test_plus_doesnt_alter_arguments();
        test_plus_result_length();
        test_self_append();
        test_sequential_frame_appends();
        test_sequential_movie_appends();
        test_chained_plus();
        test_nonconst_index_mutation();
        test_const_index_access();
        test_output_frame_count();
        test_output_names_with_spaces();
        test_expansion_data_integrity();
        test_single_frame_movies_combined();
        test_appended_frame_not_aliased();
        test_plus_result_independent();
        test_many_movies_concatenated();
    
        passed += getCounterPassed();
        failed += getCounterFailed();
        cout << "\n========================================\n";
        cout << "  Results: " << passed << " passed, " << failed << " failed\n";
        cout << "========================================\n";
    
        return failed == 0 ? 0 : 1;
    }