הערה (קובץ קוד)
קובץ זה הוא קובץ קוד מסוג CPP.
#include "tests_matamvidia_extra.h"
#include <iostream>
#include <sstream>
#include <string>
#include "Matrix.h"
#include "MataMvidia.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)
int getCounterPassed()
{
return passed;
}
int getCounterFailed()
{
return failed;
}
// ─── Helpers ─────────────────────────────────────────────────────────────────
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 a,int b,int c,int d,int e,int f,int g,int h,int k) {
Matrix m(3,3);
m(0,0)=a; m(0,1)=b; m(0,2)=c;
m(1,0)=d; m(1,1)=e; m(1,2)=f;
m(2,0)=g; m(2,1)=h; m(2,2)=k;
return m;
}
static MataMvidia make_movie(const string& name, const string& author, int n) {
Matrix* arr = new Matrix[n];
for (int i = 0; i < n; i++)
arr[i] = make2x2(i+1, i+2, i+3, i+4);
MataMvidia mv(name, author, arr, n);
delete[] arr;
return mv;
}
// ─── Tests ───────────────────────────────────────────────────────────────────
// 1. Frames are stored in order, not reversed or shuffled
void test_frame_order_preserved() {
cout << "\n[Frame Order Preserved]\n";
Matrix arr[5];
for (int i = 0; i < 5; i++)
arr[i] = make2x2(i*100, i*100, i*100, i*100);
MataMvidia mv("Order","Test", arr, 5);
bool ok = true;
for (int i = 0; i < 5; i++)
if (mv[i] != arr[i]) { ok = false; break; }
CHECK("all 5 frames in correct order", ok);
}
// 2. Constructing with different frame sizes (1x1, 2x2, 3x3)
void test_mixed_frame_sizes() {
cout << "\n[Mixed Frame Sizes]\n";
Matrix f1(1,1,7);
Matrix f2 = make2x2(1,2,3,4);
Matrix f3 = make3x3(9,8,7, 6,5,4, 3,2,1);
Matrix arr[3] = { f1, f2, f3 };
MataMvidia mv("Mixed","A", arr, 3);
CHECK("1x1 frame stored", mv[0] == f1);
CHECK("2x2 frame stored", mv[1] == f2);
CHECK("3x3 frame stored", mv[2] == f3);
}
// 3. Copy constructor: modifying original after copy doesn't affect copy
void test_copy_ctor_independence_both_ways() {
cout << "\n[Copy Independence Both Ways]\n";
MataMvidia original = make_movie("Orig","Dir",3);
MataMvidia copy(original);
original[0](0,0) = 9999;
CHECK("copy unaffected by original mutation", copy[0](0,0) != 9999);
copy[1](0,0) = 8888;
CHECK("original unaffected by copy mutation", original[1](0,0) != 8888);
}
// 4. Assignment operator: chained assignment a = b = c
void test_chained_assignment() {
cout << "\n[Chained Assignment]\n";
MataMvidia a = make_movie("A","x",2);
MataMvidia b = make_movie("B","y",3);
MataMvidia c = make_movie("C","z",4);
a = b = c;
CHECK("a == c after chained assign (frame 0)", a[0] == c[0]);
CHECK("b == c after chained assign (frame 3)", b[3] == c[3]);
c[0](0,0) = 42;
CHECK("a independent of c after chained assign", a[0](0,0) != 42);
}
// 5. operator+= with movie doesn't alter the argument movie
void test_append_movie_doesnt_alter_argument() {
cout << "\n[+= Movie: Argument Unchanged]\n";
MataMvidia mv1 = make_movie("M1","A",2);
MataMvidia mv2 = make_movie("M2","B",3);
Matrix before0 = mv2[0];
Matrix before2 = mv2[2];
mv1 += mv2;
CHECK("mv2[0] unchanged after mv1 += mv2", mv2[0] == before0);
CHECK("mv2[2] unchanged after mv1 += mv2", mv2[2] == before2);
}
// 6. operator+ doesn't alter either argument
void test_plus_doesnt_alter_arguments() {
cout << "\n[operator+: Arguments Unchanged]\n";
MataMvidia mv1 = make_movie("A","x",2);
MataMvidia mv2 = make_movie("B","y",2);
Matrix f1_0 = mv1[0], f2_0 = mv2[0];
MataMvidia result = mv1 + mv2;
CHECK("mv1[0] unchanged after +", mv1[0] == f1_0);
CHECK("mv2[0] unchanged after +", mv2[0] == f2_0);
}
// 7. operator+ result has correct total length
void test_plus_result_length() {
cout << "\n[operator+: Result Length]\n";
MataMvidia mv1 = make_movie("A","x",3);
MataMvidia mv2 = make_movie("B","y",5);
MataMvidia result = mv1 + mv2;
// Access all 8 frames — if length is wrong this will exit()
bool ok = true;
for (int i = 0; i < 8; i++) {
// just access, don't crash
(void)result[i];
}
CHECK("all 8 frames accessible in result", ok);
// Verify frame content order
CHECK("result[0] == mv1[0]", result[0] == mv1[0]);
CHECK("result[3] == mv2[0]", result[3] == mv2[0]);
CHECK("result[7] == mv2[4]", result[7] == mv2[4]);
}
// 8. Appending a movie to itself (self-concatenation)
void test_self_append() {
cout << "\n[Self-Append (mv += mv)]\n";
MataMvidia mv = make_movie("Self","S",3);
Matrix f0 = mv[0];
Matrix f2 = mv[2];
mv += mv;
CHECK("self-append: frame 0 unchanged", mv[0] == f0);
CHECK("self-append: frame 3 == old frame 0", mv[3] == f0);
CHECK("self-append: frame 5 == old frame 2", mv[5] == f2);
}
// 9. Multiple sequential += frame calls
void test_sequential_frame_appends() {
cout << "\n[Sequential Frame Appends]\n";
Matrix single[1] = { make2x2(0,0,0,0) };
MataMvidia mv("Seq","A", single, 1);
Matrix frames[10];
for (int i = 0; i < 10; i++) {
frames[i] = make2x2(i, i*2, i*3, i*4);
mv += frames[i];
}
bool ok = true;
for (int i = 0; i < 10; i++)
if (mv[i+1] != frames[i]) { ok = false; break; }
CHECK("all 10 sequentially appended frames correct", ok);
}
// 10. Multiple sequential += movie calls
void test_sequential_movie_appends() {
cout << "\n[Sequential Movie Appends]\n";
MataMvidia base = make_movie("Base","X",1);
for (int i = 0; i < 5; i++) {
MataMvidia extra = make_movie("Extra","Y",2);
base += extra;
}
// Should now have 1 + 5*2 = 11 frames
CHECK("frame 1 correct (first extra, batch 0)", base[1](0,0) == 1);
CHECK("frame 10 correct (last extra, batch 4)", base[10](0,0) == 2);
}
// 11. operator+ chained: (a + b) + c
void test_chained_plus() {
cout << "\n[Chained operator+]\n";
MataMvidia a = make_movie("A","x",2);
MataMvidia b = make_movie("B","y",2);
MataMvidia c = make_movie("C","z",2);
MataMvidia result = a + b + c;
CHECK("chained +: frame 0 from a", result[0] == a[0]);
CHECK("chained +: frame 2 from b", result[2] == b[0]);
CHECK("chained +: frame 4 from c", result[4] == c[0]);
CHECK("chained +: frame 5 from c", result[5] == c[1]);
}
// 12. Non-const operator[] allows in-place modification
void test_nonconst_index_mutation() {
cout << "\n[Non-const [] Mutation]\n";
MataMvidia mv = make_movie("M","A",3);
mv[1](0,0) = 42;
mv[1](1,1) = 99;
CHECK("mutation via [] persists (0,0)", mv[1](0,0) == 42);
CHECK("mutation via [] persists (1,1)", mv[1](1,1) == 99);
CHECK("other frames unaffected", mv[0](0,0) == 1 && mv[2](0,0) == 3);
}
// 13. Const movie: const [] returns correct value
void test_const_index_access() {
cout << "\n[Const [] Access]\n";
Matrix arr[2] = { make2x2(10,20,30,40), make2x2(50,60,70,80) };
const MataMvidia mv("C","D", arr, 2);
CHECK("const [0](0,0)", mv[0](0,0) == 10);
CHECK("const [0](1,1)", mv[0](1,1) == 40);
CHECK("const [1](0,0)", mv[1](0,0) == 50);
CHECK("const [1](1,1)", mv[1](1,1) == 80);
}
// 14. Output: correct number of frames printed
void test_output_frame_count() {
cout << "\n[Output: Frame Count]\n";
MataMvidia mv = make_movie("CountTest","Author",4);
std::ostringstream oss;
oss << mv;
string s = oss.str();
CHECK("output contains Frame 0", s.find("Frame 0") != string::npos);
CHECK("output contains Frame 1", s.find("Frame 1") != string::npos);
CHECK("output contains Frame 2", s.find("Frame 2") != string::npos);
CHECK("output contains Frame 3", s.find("Frame 3") != string::npos);
CHECK("output does NOT contain Frame 4", s.find("Frame 4") == string::npos);
}
// 15. Output format: movie name with spaces, author with spaces
void test_output_names_with_spaces() {
cout << "\n[Output: Names With Spaces]\n";
Matrix arr[1] = { make2x2(1,2,3,4) };
MataMvidia mv("The Great Movie","John Doe", arr, 1);
std::ostringstream oss;
oss << mv;
string s = oss.str();
CHECK("full movie name in output", s.find("The Great Movie") != string::npos);
CHECK("full author name in output", s.find("John Doe") != string::npos);
}
// 16. Expansion: frames survive across multiple expandArray calls
void test_expansion_data_integrity() {
cout << "\n[Expansion: Data Integrity Across Grows]\n";
Matrix arr[1] = { make2x2(77, 88, 99, 11) };
MataMvidia mv("Grow","Test", arr, 1);
// Default EXPANSION_RATE=8, so append 100 frames to force ~12 expansions
for (int i = 0; i < 100; i++)
mv += make2x2(i, i, i, i);
CHECK("original frame[0] survives 100 appends", mv[0] == arr[0]);
CHECK("frame[1] correct after expansion", mv[1](0,0) == 0);
CHECK("frame[50] correct after expansion", mv[50](0,0) == 49);
CHECK("frame[100] correct after expansion", mv[100](0,0) == 99);
}
// 17. Appending 1-frame movie to another 1-frame movie
void test_single_frame_movies_combined() {
cout << "\n[Single-frame Movies Combined]\n";
Matrix a1[1] = { make2x2(1,1,1,1) };
Matrix a2[1] = { make2x2(2,2,2,2) };
MataMvidia mv1("One","A", a1, 1);
MataMvidia mv2("Two","B", a2, 1);
MataMvidia result = mv1 + mv2;
CHECK("combined[0] == mv1[0]", result[0] == a1[0]);
CHECK("combined[1] == mv2[0]", result[1] == a2[0]);
}
// 18. Appended frames reference correct matrix values, not aliased
void test_appended_frame_not_aliased() {
cout << "\n[Appended Frame Not Aliased]\n";
MataMvidia mv = make_movie("M","A",1);
Matrix extra = make2x2(5,5,5,5);
mv += extra;
extra(0,0) = 123; // mutate original
CHECK("appended frame not aliased to source", mv[1](0,0) == 5);
}
// 19. operator+ result is independent of both sources
void test_plus_result_independent() {
cout << "\n[operator+: Result Independent of Sources]\n";
MataMvidia mv1 = make_movie("A","x",2);
MataMvidia mv2 = make_movie("B","y",2);
MataMvidia result = mv1 + mv2;
mv1[0](0,0) = 555;
mv2[0](0,0) = 666;
CHECK("result[0] unaffected by mv1 mutation", result[0](0,0) != 555);
CHECK("result[2] unaffected by mv2 mutation", result[2](0,0) != 666);
}
// 20. Many movies concatenated via operator+
void test_many_movies_concatenated() {
cout << "\n[Many Movies Concatenated]\n";
MataMvidia result = make_movie("Base","X",1);
for (int i = 0; i < 9; i++)
result = result + make_movie("Extra","Y",1);
bool ok = true;
for (int i = 0; i < 10; i++)
(void)result[i]; // must not crash
CHECK("10 movies concatenated: all frames accessible", ok);
CHECK("frame 0 value correct", result[0](0,0) == 1);
CHECK("frame 9 value correct", result[9](0,0) == 1);
}