From 81cd5c00e118825e8c9558e820cd739c85b0b0bb Mon Sep 17 00:00:00 2001 From: Andrew Haynes Date: Fri, 17 Apr 2026 10:48:42 -0400 Subject: [PATCH] Safer push_back and faster push_back (I went from 0(n^2) to 0(1)) --- .DS_Store | Bin 0 -> 6148 bytes src/main.c | 161 ++++++++++++++------ tests/cpu_stress | Bin 0 -> 34072 bytes tests/cpu_stress.c | 187 +++++++++++++++++++++++ tests/edge_case_test | Bin 0 -> 34112 bytes tests/edge_case_test.c | 317 +++++++++++++++++++++++++++++++++++++++ tests/memory_stress | Bin 0 -> 33824 bytes tests/memory_stress.c | 95 ++++++++++++ tests/reliability_test | Bin 0 -> 34064 bytes tests/reliability_test.c | 264 ++++++++++++++++++++++++++++++++ tests/stress_test | Bin 0 -> 34168 bytes tests/stress_test.c | 191 +++++++++++++++++++++++ 12 files changed, 1165 insertions(+), 50 deletions(-) create mode 100644 .DS_Store create mode 100755 tests/cpu_stress create mode 100644 tests/cpu_stress.c create mode 100755 tests/edge_case_test create mode 100644 tests/edge_case_test.c create mode 100755 tests/memory_stress create mode 100644 tests/memory_stress.c create mode 100755 tests/reliability_test create mode 100644 tests/reliability_test.c create mode 100755 tests/stress_test create mode 100644 tests/stress_test.c diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..67c9429e3be4b133d607d5d604c1b953e2b9b462 GIT binary patch literal 6148 zcmeHLJxc>I7=B}~wNwNb!9{w5Lvc`C#PO_k7rGTh?FUt8ZPB`k+~};hxL9|GI;eXW zb?_J1Rs0K%K5r7+#H+Z8XkJL3yZ7Us+!HQoN<<=iP+lOKAfhB1qnAQA#5m3^Vk6o! z1r+ib+f=Dl7xJY>y&1`N4yS-q;I}Ej-)@5Ds6<<6k?%KE_#Ce{a=BuyQG`FaK9k8- zy7$Y`obtCh&24j?;Pr<*jH60B)Uwx*%~!zju_SI|!x<~XiSo|p9; zM6w1-e4S;DhetycqkY<=lBETWpA8}=fBN+7RqLSZObsr3FX>w~Lpo~n$$5`ciz?u3 z(Z0ngGKb(aq9*TT;^=zmL;rrg$$ftF*1l8R#xpE_vBvNFUk!UUTXIaH>zx8l0jEG; z0bU<`G{!( #include #include #include @@ -23,17 +33,35 @@ typedef struct { char* arr; size_t size; + size_t capacity; } Vec8_t; +/* Takes in a temporary cpy of a vec + * - Can be nullptr to not have size incrementation and have a size of 0 (Create + * an empty vector) + * + * - Can be a vec to have size incrementation and size of base vec + 1 (Create a + * vector for modifying an old vector) + * + * */ Vec8_t -create(size_t init_size) +create(const Vec8_t* input) { - Vec8_t vec = { .arr = nullptr, .size = 0 }; - if (init_size > 0) + Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 }; + if (input == nullptr) { - vec.arr = malloc(init_size * sizeof(char)); - vec.size = init_size; + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; } + if (input->size > 0) + { + vec.size = input->size + 1; + } + if (input->capacity >= vec.capacity) + { + vec.capacity = 2 * input->capacity; + } + vec.arr = calloc(vec.capacity, sizeof(char)); return vec; } @@ -47,11 +75,22 @@ delete(Vec8_t* vec) vec->arr = nullptr; } - char -at(Vec8_t* vec, int idx) +at(const Vec8_t* vec, const int idx) { - if (vec->arr != nullptr && vec->size >= idx) + if (vec == nullptr) + { + return -2; + } + if (vec->arr == nullptr) + { + return -3; + } + if (vec->size <= idx) + { + return -4; + } + if (vec != nullptr && vec->arr != nullptr && vec->size > idx) { return vec->arr[idx]; } @@ -59,27 +98,32 @@ at(Vec8_t* vec, int idx) } void -print_vec(Vec8_t* vec) { - for(int i = 0; i < vec->size; i++) { - printf("%c ", at(vec, i)); - } - printf("\n"); +print_vec(const Vec8_t* vec) +{ + for (int i = 0; i < vec->size; i++) + { + if (vec->arr[i]) + { + printf("%c ", at(vec, i)); + } + } + printf("\n"); } int -begin(Vec8_t* vec) +begin(const Vec8_t* vec) { - if (vec->arr != nullptr && vec->size > 0) + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) { - return 1; + return 0; } return -1; } int -end(Vec8_t* vec) +end(const Vec8_t* vec) { - if (vec->arr != nullptr && vec->size > 0) + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) { return (int)(vec->size - 1); } @@ -87,60 +131,77 @@ end(Vec8_t* vec) } char -front(Vec8_t* vec) +front(const Vec8_t* vec) { - if (vec->arr != nullptr && vec->size > 0) - { - return vec->arr[0]; - } - return -1; + return at(vec, 0); } char -back(Vec8_t* vec) +back(const Vec8_t* vec) { - if (vec->arr != nullptr && vec->size > 0) + if (vec) { - return vec->arr[vec->size - 1]; + return at(vec, (int)vec->size - 1); } return -1; } +/* Return a Vector + * if below capacity + * + * + * */ Vec8_t -add_back(Vec8_t* vec, char val) +add_back(Vec8_t* vec, const char val) { - Vec8_t nvec = create(vec->size + 1); - memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char)); - if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) + Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 }; + if (vec->size < vec->capacity) { - nvec.arr[vec->size] = val; + vec->arr[vec->size] = val; + vec->size++; + return *vec; } - return nvec; + + if (vec->size >= vec->capacity) + { + Vec8_t nvec = create(vec); + memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char)); + if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) + { + nvec.arr[vec->size] = val; + } + free(vec->arr); + return nvec; + } + return ret; } -Vec8_t -add_front(Vec8_t* vec, char val) -{ - Vec8_t nvec = create(vec->size + 1); - memcpy(&nvec.arr[1], &vec->arr[0], vec->size * sizeof(char)); - if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) - { - nvec.arr[0] = val; - } - return nvec; -} +// Vec8_t +// add_front(Vec8_t* vec, char val) +// { +// Vec8_t nvec = create(vec->size + 1); +// memcpy(&nvec.arr[1], &vec->arr[0], vec->size * sizeof(char)); +// if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) +// { +// nvec.arr[0] = val; +// } +// return nvec; +// } int main() { - Vec8_t vec = create(0); + Vec8_t vec = create(nullptr); vec = add_back(&vec, '3'); vec = add_back(&vec, '4'); vec = add_back(&vec, '5'); vec = add_back(&vec, '6'); - print_vec(&vec); - vec = add_front(&vec, 'c'); - print_vec(&vec); + vec = add_back(&vec, '7'); + print_vec(&vec); + // vec = add_back(&vec, '6'); + // vec = add_front(&vec, 'c'); + // print_vec(&vec); + // printf("%c", at(nullptr, 0)); delete(&vec); return 0; diff --git a/tests/cpu_stress b/tests/cpu_stress new file mode 100755 index 0000000000000000000000000000000000000000..06a92d72da80746c255225f560275da7822ea5cc GIT binary patch literal 34072 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 +#include +#include +#include +#include + +typedef struct { + char* arr; + size_t size; + size_t capacity; +} Vec8_t; + +Vec8_t create(Vec8_t* input) { + Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 }; + if(input == nullptr) { + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; + } + if (input->size > 0) { + vec.size = input->size + 1; + } + if (input->capacity >= vec.capacity) { + vec.capacity = 2 * input->capacity; + } + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; +} + +void delete(Vec8_t* vec) { + if (vec->arr != nullptr) free(vec->arr); + vec->arr = nullptr; +} + +char at(Vec8_t* vec, int idx) { + if (vec == nullptr) return -2; + if (vec->arr == nullptr) return -3; + if (vec->size <= idx) return -4; + if (vec != nullptr && vec->arr != nullptr && vec->size > idx) { + return vec->arr[idx]; + } + return -1; +} + +int begin(Vec8_t* vec) { + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0; + return -1; +} + +int end(Vec8_t* vec) { + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1); + return -1; +} + +char front(Vec8_t* vec) { + return at(vec, 0); +} + +char back(Vec8_t* vec) { + if (vec) return at(vec, (int)vec->size - 1); + return -1; +} + +Vec8_t add_back(Vec8_t* vec, char val) { + Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 }; + if (vec->size < vec->capacity) { + vec->arr[vec->size] = val; + vec->size++; + return *vec; + } + if (vec->size >= vec->capacity) { + Vec8_t nvec = create(vec); + memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char)); + if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) { + nvec.arr[vec->size] = val; + } + free(vec->arr); + return nvec; + } + return ret; +} + +double time_diff(struct timespec start, struct timespec end_t) { + return (end_t.tv_sec - start.tv_sec) + (end_t.tv_nsec - start.tv_nsec) / 1e9; +} + +int main() { + struct timespec start, end_t; + Vec8_t vec; + + printf("=== CPU Stress Tests ===\n\n"); + + // Test 1: Rapid fire inserts (tight loop) + printf("--- Test 1: Rapid Fire (100M tight loop) ---\n"); + vec = create(nullptr); + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < 100000000; i++) { + vec = add_back(&vec, (char)i); + } + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t1 = time_diff(start, end_t); + printf(" Time: %.3f sec\n", t1); + printf(" Rate: %.0f/sec\n", 100000000.0 / t1); + delete(&vec); + + // Test 2: Read-heavy (iteration + at()) + printf("\n--- Test 2: Read Every Element (100M at() calls) ---\n"); + vec = create(nullptr); + for (int i = 0; i < 100000000; i++) vec = add_back(&vec, (char)i); + long sum = 0; + clock_gettime(CLOCK_MONOTONIC, &start); + for (size_t i = 0; i < vec.size; i++) { + sum += at(&vec, (int)i); + } + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t2 = time_diff(start, end_t); + printf(" Time: %.3f sec\n", t2); + printf(" Sum: %ld\n", sum); + printf(" Rate: %.0f reads/sec\n", 100000000.0 / t2); + delete(&vec); + + // Test 3: Mixed operations + printf("\n--- Test 3: Mixed Operations (50M each) ---\n"); + vec = create(nullptr); + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < 50000000; i++) { + vec = add_back(&vec, (char)i); + char f = front(&vec); + char b = back(&vec); + at(&vec, i / 2); + } + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t3 = time_diff(start, end_t); + printf(" Time: %.3f sec\n", t3); + printf(" Rate: %.0f ops/sec\n", 50000000.0 * 3 / t3); + delete(&vec); + + // Test 4: Cache thrashing (random access) + printf("\n--- Test 4: Random Access (100M random at() calls) ---\n"); + vec = create(nullptr); + for (int i = 0; i < 100000000; i++) vec = add_back(&vec, (char)i); + srand(12345); + clock_gettime(CLOCK_MONOTONIC, &start); + sum = 0; + for (int i = 0; i < 100000000; i++) { + int idx = rand() % (int)vec.size; + sum += at(&vec, idx); + } + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t4 = time_diff(start, end_t); + printf(" Time: %.3f sec\n", t4); + printf(" Sum: %ld\n", sum); + printf(" Rate: %.0f random reads/sec\n", 100000000.0 / t4); + delete(&vec); + + // Test 5: Sequential scan (raw pointer access) + printf("\n--- Test 5: Sequential Scan (raw pointer, 500M bytes) ---\n"); + vec = create(nullptr); + for (int i = 0; i < 500000000; i++) vec = add_back(&vec, (char)(i % 256)); + sum = 0; + clock_gettime(CLOCK_MONOTONIC, &start); + char* ptr = vec.arr; + for (size_t i = 0; i < vec.size; i++) { + sum += ptr[i]; + } + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t5 = time_diff(start, end_t); + printf(" Time: %.3f sec\n", t5); + printf(" Throughput: %.1f GB/sec\n", (vec.size / 1e9) / t5); + printf(" Sum: %ld\n", sum); + delete(&vec); + + // Test 6: Create/delete cycles (memory allocation stress) + printf("\n--- Test 6: Create/Delete Cycles (1M vectors) ---\n"); + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < 1000000; i++) { + vec = create(nullptr); + for (int j = 0; j < 100; j++) vec = add_back(&vec, (char)j); + delete(&vec); + } + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t6 = time_diff(start, end_t); + printf(" Time: %.3f sec\n", t6); + printf(" Rate: %.0f create/delete cycles/sec\n", 1000000.0 / t6); + + printf("\n=== CPU Stress Complete ===\n"); + return 0; +} diff --git a/tests/edge_case_test b/tests/edge_case_test new file mode 100755 index 0000000000000000000000000000000000000000..27576456827b93d5884ca9c70b1c5d18b489a29b GIT binary patch literal 34112 zcmeHQeQ;FQb-%kS!Ah7fX#w*UT^leGAifg=HT4Q1jBLK5kAz}p9#6YZ+6}8+vG1+K zSHeNSkH`d+?0Gv?Ck0gQv-~)DCvj#D>)Ih@o^sk-@?c`aAc% zw|ZKMIGy&N&fGh5_ug|q&OPUM&bjw$LAw8R>+0|BW6Z;lyvRk!{(Qy`Fpe5ylabdV zE6S#d$Evne)oi5J!AVRW+%$wDJ|AMBqSRGwt{dDf<_8D2F`I@c%*ixDQ4DQ|K{YGo z@>`3+#P7o~RzK0CS2pFbbheI)qUc7dLC-ej^5X%EA7Ma=Xg5E<%?}ugq$r_8TptiH zmtVx@cfUQJXrEmlt^hyXNJisLc4scXw9PLt(i%XtJGo`0c120W+oJKX5{)+|1U=Xu zN2Xf(w%AOF&gEfuiGu9pSz#xZ(zP#N2j0Wab)USkkXS2V$p^L;hnKCXi9J& zA;;O?nXjDKv5+6#ed9m(y`P_1jCPJ}=`@A0yeXnCV!{7kd2`Sw^g~Ih6#9`qd;EgT ze$cwhkg3nYeVy0=va&#)+MT+gHP2r)A96(-tf>#7ApQ~HLuHvw6JC_2BUAg!`;jdn zsrjC%Z{y!}-`VZyzEjD}>pp)5VxI8-<#>~MdRA`rrdRq4g8h*~)(<65`twj{DD#;a z8NvGf{$PK}cyy~|Z^chxVF z+~CzkrL6}{Q$zDn7E#IV^?L0w1!ynKXJ0Szuxs4&%oO)nfd}}NVom}0L8g;_PjI;- z#~&ioR(rj6l%!uZ)++nX@H+Oobh(#~pDSm&Z+z1Oti711KYzG$%Ddo0KJm8g6Nt^gGT=;Y`|sYZBmd~J{bLer zeiO3w!0xX@o=d(7nP2+?8EU`lW!Lb; z=)9kq7=NgsAb6@QpN%glV5j`#&z>T)5ar_)MdqW7ZC~qY?|2;J9``Ww36$H$GgJ3G z({b6yx-SB!TV8e~;tiexF5@F!cIwXVRluU68*7>519#7Q&fiXWx^FdkfsGFs<)J?x zGK_!>9uvWKf=zqSyaGO={^EmXFY3pD1H}o&#)qKEF88B8k){9TFiISSfm7f9+Oi8H znArz??;pv=m&|3`gFaR_d8B9j$KK*AK4AE7=>Hh_+!}ebBXVo+dwYx6wd;%9J1+W) zGsOEX@a_X|3(tv}v!M5mV%I{j3AXK%FJKMA^EBFT_@=-=0-4|3y*r6y>7Jaf+2Tpp z+(a9&3w(jGzr=c<`6dZ@Zuq8UN)CIr_dq89-h!$Am7{9?m!?denm=tZ$+!P^ckBMu zmhZMpzJuVsWYK_(&)fQ60^eWzCT2Q7KWfWZ4;kMSGET~vXuk0y2G+W_$ee`o=BgsI(>vkHMepH`Z(!U7FEjrH=?F7+Ml5dOQb$n2fXy7z%^ zyKUok*tp9ZTwapz*f=L|ne)o+rkotZ|MWWWz0(13MjZ%SZOwfOg?eff;5U>O*)<4v000M>YE0 z^ToU)Gt4!^&AT)(?~jI?cYB7pY`A$ZO~|fSo-=QVY~>TPV;{^JD`eX<(<~Wojh_t6 z3k)~!lbPmtvbiN z)>Qa2#Vz^5@obC)GP@D86eD~8k!{DNtj>wq;bOuav+sj1?FW|-cN7m7Ko5*5eq{w&c9#iCa_>d<~fX|I5=nf-#Pes3b94L^d|bmxV5v*w@`QXrPolu4mnEK zw%0`3yOPlF6vKW%`^t~eN4iIdAKK6O(>2q^vE}4%KSJLSc`jMH&m7>lJ%?X=5%vu1OXA$YzEl$RY{%{J#Fok;bE~(b7)~$d~mu;Ue*ykebUxzk<#lli^3+l&#y<;DoS;9{odJX6sE_)FV zN4H1ON4g3Au$N`437JRGUb^P#n#j{XOp;GH4@7dsa6Q+rI zV{_&aetBpkANQgJj)$PF>38bArDi_rZe1Y%p|bjESzo!ua(sn&oGCMJqFwOgbId-} zhw%9M0FTSV@#vdleu{R-b|0WlF+UCV4PY-hijwXCXK>#+f-{uPy%({cbm9)cv6pmu zCtjI>^S=XqojCvdM;_@ohx7kqod2y$=xm*6o&VrV_bTT;br!T@pRMr2leg{r)M>Q$ z`6lE1pCtB^HW7=HGAGeKL^o}E7N6J9|5e6*`#R27*h$=z$nV^9I_I!!0$1F*wt5eC zlwo`s?pY^M7wtc@_;rF8d_?eQ&*34)?fXi0U4TC*R)j5{nrq_V9V+kSlI*;vbLP3_ z6l**;Fn0HsjV<6=zAaxi_Q1ecEoZEd{ikzH{OmO7URVQ~_TMS+1v+1jp!CBh_TY@6 zd*5etKM-fk)Qn>L#Z%&L7`XE9uDjP4xO=t3H#*@Ped2By5WcYj{H=4QSe!GDfOelV zXT-g$II~2^F+to5g{+Zz=EGa&so? zG^W>wpDjgvJz!2lTPf!H^Ih%#@qjtenHMX!>*<<1yVu~(U4^^%YTUsqaTj0JeLF#S zbdR{Bj{~1^_?d!vOD>4|2v@z(RUhN37rE*atvX~Il=5uq$xRitwcp}1W`$SqS$ZLR za!p0`Iv1@r8d{PkH8mDXgj6G%h|lA#T4=tSO!BDC<60XFtA@&3lA5k1TeUEc#;KJC zF=XDH(hc6A5er?9HpMk8MC~iN8V)NBYG_+&8Pg4v)Vw0w%9|76Xk%2v8VMtUFW`7- zNNrI=QDY}xSjHCfIlQ)dOO>*|Vlz*)YRSe}qD|+eVGUmv;Tt>Ez)YvTjHyOx8E=ak z5y;jAHCi=Zz6dfIsbpN|S~8hPy2ey*s8iNgZy2^ek=&;9#zd00s<9}v4e#J#O>c=B z8gEd;T#xS3SSlWkM~x^3>>_ow9W7eO;7w|>L2c4F=7y509^s|+tIAlj8c(S)2jLYw zt7KDBDCD5T!wF4~&o=nBc%rS0Y0WJFqFHMWwd~|t7;HnTuC3s0mVD8;#)%+;jEb*)7u!?4yx)*O2YhJL}rp~Hz3q~VQ84H~85VXYDRgyBUIwKWP$#S^?) zI3#a`ojOh(KtNJX@zeIh>7{ig-nZw@7>v$OvK4MvvZdYnrlVKy?XIw zcSvh7;6W=mToC9YLU}kv-&hZX64Xn@b+u7rn-GNLlC#2vYz?q;>MK{S*TUX1`RmjTA%Xy7!6X2_CTX6KSLh7!i7%s1{_6b<4)<~w{_1XUF zxS_#u_(nTe2YPD7wy>Z+ZtV|zeRKzjpPjij1^2EcJAFfqr4ZNIo_cqnxmV=85)L9j zAZ&rjpqPZUNx1p*=QGahBEUyLl*Y{ zG9cJ`D=@1lFe?$5E}5&F;v&9k#O5w|P%Z3V>|1cg|KbGwDY1bdKy zU+3xw9it)}iM* zqFKYD&K%&{l8C~wk`RV`xHi??tR{Do)3OZ-iu~F14=qWU2Z5o+W^dXdqWNB^d^8grj+|G5EC$FAiGV~vA|Mfv2uK7Z0ulj%0Rc}DG9D@O%t!uXWIPhgl#qDag(>u03{$L^qnOfymx7E& zlqo}Jiv0i#vGgdco&G2R{Xqh}V>|{QpWyLwul;Bj8*Q*6AA4ss+E3sSa4#PJVYBEN zBsRy#&K08hjZye`|2}-AY1Hj;cQOd_HkY% zo@!?Gy26@RfzljNv>jR~WoSx7Q^Q)46{u`d16yFd^~4^r9(iIFcxH*M5zi^HCz@4A zvWXshVLM5kbA>JQ*3F!^dQ+drAez(~>%og^NTep-W&@1}>hLHF(cGp#fdPn~Y18ij za-!$h^g^3nWYhFE4D~O!={Ib;!lvu&@oQ{4ZPV**n%-BZ`L#Cfw`sf+%Em%Af7s*wZ?|b?(|bXK53v&Id-!zI&*sq2<}oqqQ88wa0y;k0sT=KAtCcdhv3Cwu?qwatltxZK#2_rdw|+q@e$=il9P za?h>h}Z~Hs(a#wYH^wsgt81MYW@>PevWgLBX`Ks5BAG!TO<>epz;&lPre*>KmsZ;;} literal 0 HcmV?d00001 diff --git a/tests/edge_case_test.c b/tests/edge_case_test.c new file mode 100644 index 0000000..13c770c --- /dev/null +++ b/tests/edge_case_test.c @@ -0,0 +1,317 @@ +#include +#include +#include +#include +#include + +typedef struct { + char* arr; + size_t size; + size_t capacity; +} Vec8_t; + +Vec8_t create(Vec8_t* input) { + Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 }; + if(input == nullptr) { + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; + } + if (input->size > 0) { + vec.size = input->size + 1; + } + if (input->capacity >= vec.capacity) { + vec.capacity = 2 * input->capacity; + } + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; +} + +void delete(Vec8_t* vec) { + if (vec->arr != nullptr) free(vec->arr); + vec->arr = nullptr; +} + +char at(Vec8_t* vec, int idx) { + if (vec == nullptr) return -2; + if (vec->arr == nullptr) return -3; + if (vec->size <= idx) return -4; + if (vec != nullptr && vec->arr != nullptr && vec->size > idx) { + return vec->arr[idx]; + } + return -1; +} + +int begin(Vec8_t* vec) { + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0; + return -1; +} + +int end(Vec8_t* vec) { + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1); + return -1; +} + +char front(Vec8_t* vec) { + return at(vec, 0); +} + +char back(Vec8_t* vec) { + if (vec) return at(vec, (int)vec->size - 1); + return -1; +} + +Vec8_t add_back(Vec8_t* vec, char val) { + Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 }; + if (vec->size < vec->capacity) { + vec->arr[vec->size] = val; + vec->size++; + return *vec; + } + if (vec->size >= vec->capacity) { + Vec8_t nvec = create(vec); + memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char)); + if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) { + nvec.arr[vec->size] = val; + } + free(vec->arr); + return nvec; + } + return ret; +} + +int tests_passed = 0; +int tests_failed = 0; +int test_num = 0; + +void test(const char* name, int passed) { + test_num++; + if (passed) { + printf("[PASS] #%d: %s\n", test_num, name); + tests_passed++; + } else { + printf("[FAIL] #%d: %s\n", test_num, name); + tests_failed++; + } +} + +int main() { + printf("=== EDGE CASE BRUTAL TESTS ===\n\n"); + + Vec8_t vec; + char* ptr; + + // === Test 1: Use after reallocation (expected behavior) === + printf("--- Reallocation Behavior ---\n"); + + vec = create(nullptr); + for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i)); + ptr = vec.arr; // save pointer (will be freed on next realloc) + + for (int i = 0; i < 100; i++) vec = add_back(&vec, (char)('0' + (i % 10))); + + // Pointer changes after reallocation - this is expected + test("after reallocation, vec.arr is new", ptr != vec.arr); + test("data preserved in new vec", vec.arr[0] == 'A' && vec.arr[9] == 'J'); + test("vec must be reassigned: vec = add_back()", 1); + delete(&vec); + + // === Test 2: Stack-allocated struct (not created via create) === + printf("\n--- Stack-Allocated Struct ---\n"); + + Vec8_t stack_vec; + stack_vec.arr = nullptr; + stack_vec.size = 0; + stack_vec.capacity = 0; + + // This will fail because capacity starts at 0, not 4 + // and there's no way to use add_back properly + // BUG: User can't easily use functions without calling create() + test("stack vec: add_back modifies nothing (capacity 0)", 1); // informational + + // === Test 3: Integer overflow potential === + printf("\n--- Integer Overflow ---\n"); + + // If someone passes SIZE_MAX or near-max to create + // The doubling could overflow + vec = create(nullptr); + vec.capacity = (size_t)-1; // max size_t + vec.size = 0; + vec.arr = calloc(1, 1); // tiny allocation + + // BUG: 2 * capacity overflows to 0 + size_t doubled = 2 * vec.capacity; + test("2 * SIZE_MAX overflows (demonstrates overflow)", 1); // informational + + free(vec.arr); + + // === Test 4: Negative index with signed int === + printf("\n--- Signed/Unsigned Mixing ---\n"); + + vec = create(nullptr); + vec = add_back(&vec, 'X'); + + int neg_idx = -1; + // BUG: -1 as unsigned is huge, causing out-of-bounds access + char result = at(&vec, neg_idx); + test("at() with negative -1 returns error", result == -4); + + neg_idx = -2147483648; + result = at(&vec, neg_idx); + test("at() with INT_MIN returns error", result == -4); + + delete(&vec); + + // === Test 5: Size very large === + printf("\n--- Huge Size Values ---\n"); + + vec = create(nullptr); + vec.size = 1000000; // manually corrupt size (bad user code) + vec.capacity = 4; + vec.arr = calloc(4, 1); + + // BUG: size > capacity, add_back will try to create with size+1 = 1000001 + // which allocates based on old logic + result = at(&vec, 0); + // Should still work for valid indices within actual capacity + test("at() works for valid idx despite bad size", result == 0); + + delete(&vec); + + // === Test 6: Uninitialized struct === + printf("\n--- Uninitialized Struct ---\n"); + + Vec8_t uninit; + // BUG: arr, size, capacity contain garbage + // Any function call is undefined behavior + printf(" Calling at() on uninitialized struct...\n"); + printf(" This is undefined behavior - results unpredictable!\n"); + test("uninitialized: expect garbage or crash (UB)", 1); // informational + + // === Test 7: Capacity not matching allocation === + printf("\n--- Capacity Mismatch ---\n"); + + vec = create(nullptr); + vec.arr = realloc(vec.arr, 1000); // manually grow + vec.capacity = 1000; // but don't tell anyone + + for (int i = 0; i < 50; i++) vec = add_back(&vec, (char)i); + test("manual realloc: capacity grows (add_back doesn't know)", 1); // informational + + delete(&vec); + + // === Test 8: memcpy with null === + printf("\n--- Memcpy Edge Cases ---\n"); + + vec = create(nullptr); + vec.size = 0; + // BUG: memcpy(&vec.arr[0], &vec.arr[0], 0) - this is actually fine (no-op) + for (int i = 0; i < 5; i++) vec = add_back(&vec, (char)('A' + i)); + test("empty memcpy edge case: works fine", vec.size == 5); + delete(&vec); + + // === Test 9: Return value ignored === + printf("\n--- Ignored Return Values ---\n"); + + vec = create(nullptr); + add_back(&vec, 'X'); // Modifies in-place when capacity available + test("add_back modifies in-place when capacity available", vec.size == 1); + test("data stored correctly", vec.arr[0] == 'X'); + + // Fill to capacity (4): size goes 1->4 + for (int i = 0; i < 3; i++) vec = add_back(&vec, (char)('A' + i)); + // Now size=4, cap=4 + + // Add more: this triggers reallocation (size >= capacity) + char* old_ptr = vec.arr; + vec = add_back(&vec, 'Z'); // reallocates! size becomes 5, cap becomes 8 + test("reallocation triggered", old_ptr != vec.arr); + test("realloc: data preserved in new vec", vec.arr[4] == 'Z'); + delete(&vec); + + // === Test 10: Multiple vectors, aliasing === + printf("\n--- Aliasing Issues ---\n"); + + Vec8_t v1 = create(nullptr); + Vec8_t v2 = create(nullptr); + + for (int i = 0; i < 5; i++) v1 = add_back(&v1, (char)('A' + i)); + for (int i = 0; i < 5; i++) v2 = add_back(&v2, (char)('1' + i)); + + test("v1 and v2 are separate", v1.arr != v2.arr); + test("v1 data correct", v1.arr[0] == 'A'); + test("v2 data correct", v2.arr[0] == '1'); + + delete(&v1); + delete(&v2); + + // === Test 11: Freeing already-freed memory === + printf("\n--- Double Free ---\n"); + + vec = create(nullptr); + vec = add_back(&vec, 'X'); + char* data = vec.arr; + delete(&vec); + free(data); // BUG: double free! + printf(" Double free detected (would crash with sanitizers)\n"); + test("double free: undefined behavior", 1); // informational + + // === Test 12: Realloc failure === + printf("\n--- Realloc Failure ---\n"); + + // Hard to test without mocking, but conceptually: + // If malloc/calloc fails, the library doesn't check + // BUG: nvec.arr could be NULL, then memcpy with NULL crashes + printf(" If realloc fails: nvec.arr is NULL, memcpy crashes\n"); + test("no malloc failure check in create()", 1); // informational + + // === Test 13: Reading freed memory === + printf("\n--- Use After Delete ---\n"); + + vec = create(nullptr); + for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)i); + delete(&vec); + + // BUG: vec.arr is nullptr, vec.size is still 10 + // User might expect size to be 0 after delete + test("after delete: arr is null", vec.arr == nullptr); + test("after delete: size is still 10 (not cleared)", vec.size == 10); + test("after delete: accessing returns error", at(&vec, 0) == -3); + + // === Test 14: Size 0 with capacity 0 === + printf("\n--- Size/Capacity Edge ---\n"); + + vec.arr = malloc(100); + vec.size = 0; + vec.capacity = 100; + + // BUG: begin() checks size > 0, so returns -1 even though we have capacity + test("begin() returns -1 when size=0", begin(&vec) == -1); + test("end() returns -1 when size=0", end(&vec) == -1); + test("front() returns -4 when size=0", front(&vec) == -4); + test("back() returns -4 when size=0", back(&vec) == -4); + + free(vec.arr); + + // === Test 15: Concurrent modification (conceptual) === + printf("\n--- Iterator Invalidation Concept ---\n"); + + vec = create(nullptr); + for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i)); + + // If user iterates while adding: + // for (int i = 0; i < 1000; i++) { + // if (i == 10) vec = add_back(&vec, 'Z'); // reallocation! + // use vec.arr[i]; // BUG: pointer invalid after realloc + // } + printf(" Iteration + reallocation invalidates pointers\n"); + test("conceptual: iteration during add_back is unsafe", 1); + delete(&vec); + + // === Summary === + printf("\n=== Summary ===\n"); + printf("Passed: %d\n", tests_passed); + printf("Failed: %d\n", tests_failed); + printf("Note: 'informational' tests always pass, real bugs above\n"); + + return 0; +} diff --git a/tests/memory_stress b/tests/memory_stress new file mode 100755 index 0000000000000000000000000000000000000000..d3edd05a514d0dcd4aa878bf4fff2ff13cf0aadc GIT binary patch literal 33824 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 +#include +#include +#include + +typedef struct { + char* arr; + size_t size; +} Vec8_t; + +Vec8_t create(size_t init_size) { + Vec8_t vec = { .arr = nullptr, .size = 0 }; + if (init_size > 0) { + vec.arr = malloc(init_size * sizeof(char)); + vec.size = init_size; + } + return vec; +} + +void delete(Vec8_t* vec) { + if (vec->arr != nullptr) free(vec->arr); + vec->arr = nullptr; +} + +int main(int argc, char* argv[]) { + size_t count = 100000000; // 100M + int vec_count = 1; + + if (argc > 1) count = atoll(argv[1]); + if (argc > 2) vec_count = atoi(argv[2]); + + size_t total = count * (size_t)vec_count; + printf("=== Direct Allocation Memory Test ===\n"); + printf("Elements per vector: %zu\n", count); + printf("Number of vectors: %d\n", vec_count); + printf("Total elements: %zu\n", total); + printf("Total memory: %.1f GB\n", (total * sizeof(char)) / (1024.0 * 1024.0 * 1024.0)); + printf("\n"); + + struct timespec start, end; + Vec8_t* vecs = malloc(vec_count * sizeof(Vec8_t)); + + clock_gettime(CLOCK_MONOTONIC, &start); + + printf("Allocating %d vectors of %zu elements each...\n", vec_count, count); + for (int v = 0; v < vec_count; v++) { + vecs[v] = create(count); + if (vecs[v].arr == nullptr) { + printf(" ERROR: Failed to allocate vector %d!\n", v); + return 1; + } + } + + clock_gettime(CLOCK_MONOTONIC, &end); + double alloc_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; + printf("Allocation time: %.2f seconds\n", alloc_time); + + printf("\nFilling vectors...\n"); + clock_gettime(CLOCK_MONOTONIC, &start); + + for (int v = 0; v < vec_count; v++) { + for (size_t i = 0; i < count; i++) { + vecs[v].arr[i] = (char)(i % 256); + } + } + + clock_gettime(CLOCK_MONOTONIC, &end); + double fill_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; + printf("Fill time: %.2f seconds\n", fill_time); + + printf("\nVerifying...\n"); + int errors = 0; + for (int v = 0; v < vec_count; v++) { + if (vecs[v].size != count) errors++; + if (vecs[v].arr[0] != 0) errors++; + if (vecs[v].arr[count - 1] != (char)((count - 1) % 256)) errors++; + } + printf("Errors: %d\n", errors); + + printf("\nFreeing...\n"); + clock_gettime(CLOCK_MONOTONIC, &start); + for (int v = 0; v < vec_count; v++) { + delete(&vecs[v]); + } + clock_gettime(CLOCK_MONOTONIC, &end); + double free_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; + printf("Free time: %.2f seconds\n", free_time); + + free(vecs); + + printf("\n=== Complete ===\n"); + printf("Total time: %.2f seconds\n", alloc_time + fill_time + free_time); + + return errors > 0 ? 1 : 0; +} diff --git a/tests/reliability_test b/tests/reliability_test new file mode 100755 index 0000000000000000000000000000000000000000..a78214c70b8b448d91e21ad3fb385ee0334d3082 GIT binary patch literal 34064 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 literal 0 HcmV?d00001 diff --git a/tests/reliability_test.c b/tests/reliability_test.c new file mode 100644 index 0000000..d3cef1e --- /dev/null +++ b/tests/reliability_test.c @@ -0,0 +1,264 @@ +#include +#include +#include +#include + +typedef struct { + char* arr; + size_t size; + size_t capacity; +} Vec8_t; + +Vec8_t create(Vec8_t* input) { + Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 }; + if(input == nullptr) { + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; + } + if (input->size > 0) { + vec.size = input->size + 1; + } + if (input->capacity >= vec.capacity) { + vec.capacity = 2 * input->capacity; + } + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; +} + +void delete(Vec8_t* vec) { + if (vec->arr != nullptr) free(vec->arr); + vec->arr = nullptr; +} + +char at(Vec8_t* vec, int idx) { + if (vec == nullptr) return -2; + if (vec->arr == nullptr) return -3; + if (vec->size <= idx) return -4; + if (vec != nullptr && vec->arr != nullptr && vec->size > idx) { + return vec->arr[idx]; + } + return -1; +} + +int begin(Vec8_t* vec) { + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0; + return -1; +} + +int end(Vec8_t* vec) { + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1); + return -1; +} + +char front(Vec8_t* vec) { + return at(vec, 0); +} + +char back(Vec8_t* vec) { + if (vec) return at(vec, (int)vec->size - 1); + return -1; +} + +Vec8_t add_back(Vec8_t* vec, char val) { + Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 }; + if (vec->size < vec->capacity) { + vec->arr[vec->size] = val; + vec->size++; + return *vec; + } + if (vec->size >= vec->capacity) { + Vec8_t nvec = create(vec); + memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char)); + if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) { + nvec.arr[vec->size] = val; + } + free(vec->arr); + return nvec; + } + return ret; +} + +int tests_passed = 0; +int tests_failed = 0; +int test_num = 0; + +void test(const char* name, int passed) { + test_num++; + if (passed) { + printf("[PASS] #%d: %s\n", test_num, name); + tests_passed++; + } else { + printf("[FAIL] #%d: %s\n", test_num, name); + tests_failed++; + } +} + +int main() { + printf("=== Reliability Tests ===\n\n"); + + Vec8_t vec; + + // === Basic Initialization === + printf("--- Initialization ---\n"); + + vec = create(nullptr); + test("create(nullptr) returns valid vec", vec.arr != nullptr); + test("create(nullptr) capacity = 4", vec.capacity == 4); + test("create(nullptr) size = 0", vec.size == 0); + delete(&vec); + + // === Empty Vector Operations === + printf("\n--- Empty Vector Operations ---\n"); + + vec = create(nullptr); + test("at() on empty returns error", at(&vec, 0) == -4); + test("at() on empty (neg idx) returns error", at(&vec, -1) == -4); + test("at() on empty (large idx) returns error", at(&vec, 100) == -4); + test("front() on empty returns error", front(&vec) == -4); + test("back() on empty returns error", back(&vec) == -4); + test("begin() on empty returns -1", begin(&vec) == -1); + test("end() on empty returns -1", end(&vec) == -1); + delete(&vec); + + // === Single Element === + printf("\n--- Single Element ---\n"); + + vec = create(nullptr); + vec = add_back(&vec, 'X'); + test("single element: size = 1", vec.size == 1); + test("single element: at(0) = 'X'", at(&vec, 0) == 'X'); + test("single element: front() = 'X'", front(&vec) == 'X'); + test("single element: back() = 'X'", back(&vec) == 'X'); + test("single element: begin() = 0", begin(&vec) == 0); + test("single element: end() = 0", end(&vec) == 0); + delete(&vec); + + // === Capacity Boundaries === + printf("\n--- Capacity Boundaries ---\n"); + + vec = create(nullptr); + for (int i = 0; i < 4; i++) vec = add_back(&vec, (char)('A' + i)); + test("at capacity (4): size = 4", vec.size == 4); + test("at capacity (4): capacity = 4", vec.capacity == 4); + + vec = add_back(&vec, 'E'); + test("at capacity (4): size = 5", vec.size == 5); + test("at capacity (4): capacity doubled = 8", vec.capacity == 8); + test("at capacity (4): arr[4] = 'E'", vec.arr[4] == 'E'); + delete(&vec); + + // === Data Integrity === + printf("\n--- Data Integrity ---\n"); + + vec = create(nullptr); + for (int i = 0; i < 100; i++) vec = add_back(&vec, (char)i); + test("data integrity: size = 100", vec.size == 100); + for (int i = 0; i < 100; i++) { + test("data integrity: arr[i] = i", vec.arr[i] == (char)i); + } + delete(&vec); + + // === Large Capacity === + printf("\n--- Large Capacity ---\n"); + + vec = create(nullptr); + for (int i = 0; i < 1000; i++) vec = add_back(&vec, (char)(i % 256)); + test("large vec: size = 1000", vec.size == 1000); + test("large vec: capacity >= size", vec.capacity >= 1000); + test("large vec: first preserved", vec.arr[0] == 0); + test("large vec: last preserved", vec.arr[999] == (char)(999 % 256)); + delete(&vec); + + // === NULL Safety === + printf("\n--- NULL Safety ---\n"); + + test("at(nullptr) = -2", at(nullptr, 0) == -2); + test("front(nullptr) = -2", front(nullptr) == -2); + test("back(nullptr) = -1", back(nullptr) == -1); + test("begin(nullptr) = -1", begin(nullptr) == -1); + test("end(nullptr) = -1", end(nullptr) == -1); + + // === Memory Leak Check (basic) === + printf("\n--- Memory Leak Check ---\n"); + + for (int round = 0; round < 100; round++) { + vec = create(nullptr); + for (int i = 0; i < 50; i++) vec = add_back(&vec, (char)i); + delete(&vec); + } + test("100 create/delete cycles: no crash", 1); + + // === Double Delete === + printf("\n--- Double Delete Safety ---\n"); + + vec = create(nullptr); + vec = add_back(&vec, 'T'); + delete(&vec); + delete(&vec); // Should not crash + test("double delete: no crash", 1); + + // === Delete Then Access === + printf("\n--- Delete Then Access ---\n"); + + vec = create(nullptr); + vec = add_back(&vec, 'A'); + vec = add_back(&vec, 'B'); + delete(&vec); + test("after delete: at() returns error", at(&vec, 0) == -3); + test("after delete: front() returns error", front(&vec) == -3); + test("after delete: back() returns -3 (size still 2)", back(&vec) == -3); + + // === Extreme Values === + printf("\n--- Extreme Values ---\n"); + + vec = create(nullptr); + vec = add_back(&vec, 0); + vec = add_back(&vec, 127); + vec = add_back(&vec, -128); + test("extreme: zero preserved", vec.arr[0] == 0); + test("extreme: max char preserved", vec.arr[1] == 127); + test("extreme: min char preserved", vec.arr[2] == -128); + delete(&vec); + + // === Rapid Small Operations === + printf("\n--- Rapid Small Operations ---\n"); + + for (int round = 0; round < 10; round++) { + vec = create(nullptr); + for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i)); + test("rapid small: round preserves data", + vec.arr[0] == 'A' && vec.arr[9] == 'J'); + delete(&vec); + } + + // === Alternating Add/Read === + printf("\n--- Alternating Add/Read ---\n"); + + vec = create(nullptr); + for (int i = 0; i < 50; i++) { + vec = add_back(&vec, (char)('A' + i)); + test("alternating: read during add", + at(&vec, i) == (char)('A' + i)); + } + delete(&vec); + + // === Capacity Exact Match === + printf("\n--- Capacity Exact Match ---\n"); + + vec = create(nullptr); + for (int i = 0; i < 8; i++) vec = add_back(&vec, (char)i); + test("exact cap: size = 8", vec.size == 8); + test("exact cap: capacity = 8", vec.capacity == 8); + vec = add_back(&vec, 'X'); + test("exact cap +1: size = 9", vec.size == 9); + test("exact cap +1: capacity = 16", vec.capacity == 16); + delete(&vec); + + // === Summary === + printf("\n=== Summary ===\n"); + printf("Passed: %d\n", tests_passed); + printf("Failed: %d\n", tests_failed); + printf("Total: %d\n", tests_passed + tests_failed); + + return tests_failed > 0 ? 1 : 0; +} diff --git a/tests/stress_test b/tests/stress_test new file mode 100755 index 0000000000000000000000000000000000000000..4f4c9bd6178cdf6954c59f458cc994d274420889 GIT binary patch literal 34168 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 Tdoh34`aP58B&;5BCYbqO`6*}V literal 0 HcmV?d00001 diff --git a/tests/stress_test.c b/tests/stress_test.c new file mode 100644 index 0000000..ec642b9 --- /dev/null +++ b/tests/stress_test.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include + +typedef struct { + char* arr; + size_t size; + size_t capacity; +} Vec8_t; + +Vec8_t create(Vec8_t* input) { + Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 }; + if(input == nullptr) { + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; + } + if (input->size > 0) { + vec.size = input->size + 1; + } + if (input->capacity >= vec.capacity) { + vec.capacity = 2 * input->capacity; + } + vec.arr = calloc(vec.capacity, sizeof(char)); + return vec; +} + +void delete(Vec8_t* vec) { + if (vec->arr != nullptr) free(vec->arr); + vec->arr = nullptr; +} + +char at(Vec8_t* vec, int idx) { + if (vec == nullptr) return -2; + if (vec->arr == nullptr) return -3; + if (vec->size <= idx) return -4; + if (vec != nullptr && vec->arr != nullptr && vec->size > idx) { + return vec->arr[idx]; + } + return -1; +} + +int begin(Vec8_t* vec) { + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0; + return -1; +} + +int end(Vec8_t* vec) { + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1); + return -1; +} + +char front(Vec8_t* vec) { + return at(vec, 0); +} + +char back(Vec8_t* vec) { + if (vec) return at(vec, (int)vec->size - 1); + return -1; +} + +Vec8_t add_back(Vec8_t* vec, char val) { + Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 }; + if (vec->size < vec->capacity) { + vec->arr[vec->size] = val; + vec->size++; + return *vec; + } + if (vec->size >= vec->capacity) { + Vec8_t nvec = create(vec); + memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char)); + if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) { + nvec.arr[vec->size] = val; + } + free(vec->arr); + return nvec; + } + return ret; +} + +int tests_passed = 0; +int tests_failed = 0; + +void test(const char* name, int passed) { + if (passed) { printf("[PASS] %s\n", name); tests_passed++; } + else { printf("[FAIL] %s\n", name); tests_failed++; } +} + +double time_diff(struct timespec start, struct timespec end_t) { + return (end_t.tv_sec - start.tv_sec) + (end_t.tv_nsec - start.tv_nsec) / 1e9; +} + +int main() { + printf("=== Stress Testing libvec (doubling) ===\n\n"); + + struct timespec start, end_t; + Vec8_t vec; + + printf("--- Basic correctness ---\n"); + vec = create(nullptr); + test("create nullptr: capacity = 4", vec.capacity == 4); + test("create nullptr: size = 0", vec.size == 0); + + vec = add_back(&vec, 'a'); + test("add_back 1: size = 1", vec.size == 1); + test("add_back 1: capacity = 4", vec.capacity == 4); + + vec = add_back(&vec, 'b'); + test("add_back 2: size = 2", vec.size == 2); + + vec = add_back(&vec, 'c'); + test("add_back 3: size = 3", vec.size == 3); + + vec = add_back(&vec, 'd'); + test("add_back 4: size = 4", vec.size == 4); + + vec = add_back(&vec, 'e'); + test("add_back 5: capacity = 8 (doubled)", vec.capacity == 8); + test("add_back 5: arr[4] = 'e'", vec.arr[4] == 'e'); + delete(&vec); + + printf("\n--- NULL safety ---\n"); + test("at(nullptr) returns -2", at(nullptr, 0) == -2); + test("front(nullptr) returns -2", front(nullptr) == -2); + test("back(nullptr) returns -1", back(nullptr) == -1); + test("begin(nullptr) == -1", begin(nullptr) == -1); + test("end(nullptr) == -1", end(nullptr) == -1); + + printf("\n--- Capacity growth pattern ---\n"); + vec = create(nullptr); + size_t prev_cap = vec.capacity; + printf(" cap=%zu", vec.capacity); + for (int i = 1; i <= 100; i++) { + vec = add_back(&vec, (char)i); + if (vec.capacity != prev_cap) { + printf(" -> %zu (at size %d)", vec.capacity, i); + prev_cap = vec.capacity; + } + } + printf("\n"); + test("final capacity = 128", vec.capacity == 128); + delete(&vec); + + printf("\n--- 1M add_back ---\n"); + vec = create(nullptr); + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < 1000000; i++) vec = add_back(&vec, (char)i); + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t1 = time_diff(start, end_t); + printf(" Time: %.3f sec (%.0f/sec)\n", t1, 1000000.0/t1); + test("1M: size correct", vec.size == 1000000); + test("1M: data correct", vec.arr[0] == 0 && vec.arr[999999] == (char)999999); + delete(&vec); + + printf("\n--- 10M add_back ---\n"); + vec = create(nullptr); + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < 10000000; i++) vec = add_back(&vec, (char)i); + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t10 = time_diff(start, end_t); + printf(" Time: %.3f sec (%.0f/sec)\n", t10, 10000000.0/t10); + test("10M: size correct", vec.size == 10000000); + test("10M: data correct", vec.arr[0] == 0 && vec.arr[9999999] == (char)(9999999 % 256)); + delete(&vec); + + printf("\n--- 100M add_back ---\n"); + vec = create(nullptr); + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < 100000000; i++) vec = add_back(&vec, (char)i); + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t100 = time_diff(start, end_t); + printf(" Time: %.3f sec (%.0f/sec)\n", t100, 100000000.0/t100); + test("100M: size correct", vec.size == 100000000); + test("100M: data correct", vec.arr[0] == 0 && vec.arr[99999999] == (char)(99999999 % 256)); + delete(&vec); + + printf("\n--- 1B add_back ---\n"); + vec = create(nullptr); + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < 1000000000; i++) vec = add_back(&vec, (char)i); + clock_gettime(CLOCK_MONOTONIC, &end_t); + double t1b = time_diff(start, end_t); + printf(" Time: %.3f sec (%.0f/sec)\n", t1b, 1000000000.0/t1b); + test("1B: size correct", vec.size == 1000000000); + test("1B: data correct", vec.arr[0] == 0 && vec.arr[999999999] == (char)(999999999 % 256)); + delete(&vec); + + printf("\n=== Summary ===\n"); + printf("Passed: %d, Failed: %d\n", tests_passed, tests_failed); + return tests_failed > 0 ? 1 : 0; +}