Compare commits
10 Commits
83b2f94a22
...
78c9c967bb
| Author | SHA1 | Date | |
|---|---|---|---|
| 78c9c967bb | |||
| ed63c6ea25 | |||
| 8223eba81b | |||
| 659b61a5f0 | |||
| 3975d92651 | |||
| d01f7afe3e | |||
| e38f69eed7 | |||
| fa54a2def0 | |||
| 0f3ca699dc | |||
| c7c64f560d |
@@ -1,2 +1,3 @@
|
|||||||
x*
|
x*
|
||||||
**.swp
|
**.swp
|
||||||
|
log_*
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 fanasina
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
# y_test_h
|
||||||
|
This is a C-only testing library, similar to gtest but written entirely in C.
|
||||||
|
|
||||||
|
To use it, simply copy the y_test_h.h file into your project, include it in your test files, and use the following macros:
|
||||||
|
|
||||||
|
-`IMPLEMENTATION_FTEST()` to generate all test functions.
|
||||||
|
|
||||||
|
-`IMPLEMENTATION_FMOCK()` to generate all mock functions.
|
||||||
|
|
||||||
|
|
||||||
|
# How to create test (ftest)
|
||||||
|
## Example
|
||||||
|
Example for this file `test.c`:
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
#include "y_test_h.h"
|
||||||
|
IMPLEMENTATION_FTEST()
|
||||||
|
|
||||||
|
TEST(nametest){
|
||||||
|
EXPECT_EQ(1,1);
|
||||||
|
}
|
||||||
|
/* allow empty nametest, e.g*/
|
||||||
|
TEST(){}
|
||||||
|
/* allow duplicate name test, to have suit test */
|
||||||
|
TEST(){
|
||||||
|
EXPECT_TRUE(true);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Requirements
|
||||||
|
This program was developed for Linux. It has not been tested on Windows or macOS yet.
|
||||||
|
```
|
||||||
|
Bash
|
||||||
|
```
|
||||||
|
```
|
||||||
|
$ ls
|
||||||
|
test.c y_test_h.h
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compilation
|
||||||
|
`gcc -o exectest test.c`
|
||||||
|
|
||||||
|
Its typically works with `gcc` and `clang`.
|
||||||
|
|
||||||
|
### Running test
|
||||||
|
`./exectest`
|
||||||
|
|
||||||
|
## The main function
|
||||||
|
### Using command-line options:
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
int main(int arc, char** argv){
|
||||||
|
run_all_tests_args(argc, argv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
We can add execution option like:
|
||||||
|
|
||||||
|
`./exectest -h` : Print help
|
||||||
|
|
||||||
|
`./exectest -p 5` : Parallelize tests using 5 threads.
|
||||||
|
|
||||||
|
`./exectest` : Run tests sequentially (1 thread).
|
||||||
|
|
||||||
|
|
||||||
|
### Using only sequential tests
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
int main(){
|
||||||
|
run_all_tests();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Note: In this case, `./exectest` does not read command-line arguments.
|
||||||
|
|
||||||
|
### Using only parrallel tests
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
int main(){
|
||||||
|
run_all_tests_parallel(4); /* to use 4 threads */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Note: In this case, `./exectest` does not read command-line arguments.
|
||||||
|
|
||||||
|
# FMOCK
|
||||||
|
You can create functions with predefined return values based on specific calls and conditions to simulate the behavior of real functions.
|
||||||
|
|
||||||
|
## How to create fmock
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
#include "y_test_h.h"
|
||||||
|
IMPLEMENTATION_FMOCK()
|
||||||
|
```
|
||||||
|
outside of any function:
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
MOCK_FUNC(
|
||||||
|
returnType,
|
||||||
|
name_function_mock,
|
||||||
|
(prototype of the function with paranthesis),
|
||||||
|
(args when call the funct with parathesis)
|
||||||
|
)
|
||||||
|
/* use (returnType) in parathesis if the returType has more than 1 words
|
||||||
|
for example (long int) or (struct someStruct) */
|
||||||
|
```
|
||||||
|
## Example
|
||||||
|
To mock a function with the signature `int f_mock(int a,int b);`
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
MOCK_FUNC(int, f_mock,(int a,int b),(a,b))
|
||||||
|
```
|
||||||
|
## Arguments breakdown
|
||||||
|
```
|
||||||
|
returnType: int,
|
||||||
|
function_name: f_mock,
|
||||||
|
Prototype: (int a,int b),
|
||||||
|
Variables : (a,b)
|
||||||
|
```
|
||||||
|
## Printing variables
|
||||||
|
You can define a function to print the mock function's variables for logging purposes. The macro uses similar arguments to `MOCK_FUNC`, but the return type is always `char*`.
|
||||||
|
|
||||||
|
Example for `f_mock` :
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
STR_PRINT_CUR_VAR(f_mock, (int a,int b),(a,b)){
|
||||||
|
char *ret=malloc(150);
|
||||||
|
sprintf(ret,"(int)a: %d, (int)b: %d",a,b);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Define an expected call
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
EXPECT_MOCK_CALL(int, f_mock, (int a,int b), (a<b), 3){
|
||||||
|
return a+b;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Arguments:
|
||||||
|
```
|
||||||
|
returnType: int,
|
||||||
|
function_name: f_mock,
|
||||||
|
Prototype : (int a,int b),
|
||||||
|
Condition : (a<b) (boolean expression checked before execution)
|
||||||
|
Repetition : 3 (number of times this response is expected)
|
||||||
|
```
|
||||||
|
## Define a "will" call
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
WILL_MOCK_CALL(int, f_mock, (int a,int b), (a==b), 1){
|
||||||
|
return a*b;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
The arguments are the same as `EXPECT_MOCK_CALL`. The difference is that `EXPECT_MOCK_CALL` must be triggered during the test, whereas `WILL_MOCK_CALL` is optional.
|
||||||
|
|
||||||
|
## Initializing and calling mocks
|
||||||
|
In a `TEST` environment, you should use the `INIT_CALLER_MOCK(f_mock)`; macro before calling the mock to get explicit logs.
|
||||||
|
|
||||||
|
Calling a mock function is done exactly like a normal functions.
|
||||||
|
|
||||||
|
### Example:
|
||||||
|
```
|
||||||
|
C
|
||||||
|
```
|
||||||
|
```
|
||||||
|
TEST(f_mock_test){
|
||||||
|
INIT_CALLER_MOCK(f_mock);
|
||||||
|
PRINTF(" first call: %d\n",f_mock(2,3));
|
||||||
|
PRINTF(" second call: %d\n",f_mock(3,3));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
# PRINTF
|
||||||
|
While you can use the standard `printf`, this library provides a `PRINTF` macro. It allows logs to be recorded in files and ensures that logs remain ordered when running parallel tests.
|
||||||
|
|
||||||
|
The arguments are identical to the standard `stdio.h` `printf`.
|
||||||
|
|
||||||
|
```
|
||||||
|
PRINTF("hello\n");
|
||||||
|
```
|
||||||
|
Note : `LOG` is also available as an alias for `PRINTF`
|
||||||
|
|
||||||
|
|
||||||
@@ -96,10 +96,114 @@ TEST(lessThan){
|
|||||||
EXPECT_LT_TYPE_DOUBLE(db,da);
|
EXPECT_LT_TYPE_DOUBLE(db,da);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMPLEMENTATION_FMOCK()
|
||||||
|
|
||||||
|
MOCK_FUNC(int, f_mock, (), ())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EXPECT_MOCK_CALL(int,f_mock, (),false, 2) {
|
||||||
|
EXPECT_EQ_IN_MOCKF(21,21,f_mock);
|
||||||
|
EXPECT_EQ(1,3);
|
||||||
|
EXPECT_EQ(4,4);
|
||||||
|
EXPECT_EQ_IN_MOCKF(23,24,f_mock); return 12;}
|
||||||
|
EXPECT_MOCK_CALL(int,f_mock, (),1, 1) { EXPECT_EQ_IN_MOCKF(23,21,f_mock);return 10;}
|
||||||
|
|
||||||
|
EXPECT_MOCK_CALL(int,f_mock, (),1==2||2<1, 1) {return 18;}
|
||||||
|
EXPECT_MOCK_CALL(int,f_mock, (),1, ININITY_REPS) {return -18;}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(mockf1){
|
||||||
|
INIT_CALLER_MOCK(f_mock);
|
||||||
|
|
||||||
|
for(int i = 0; i<8; ++i){
|
||||||
|
|
||||||
|
LOG("call f_mock:%d: ret:%d\n",i,f_mock());
|
||||||
|
// int val=f_mock();
|
||||||
|
//PRINTF("call f_mock:%d: ret:%d\n",i,val);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// //
|
||||||
|
|
||||||
|
MOCK_FUNC(int, f2_mock,(int a,int b),(a,b))
|
||||||
|
|
||||||
|
STR_PRINT_CUR_VAR(f2_mock, (int a,int b),(a,b)){
|
||||||
|
char *ret=malloc(150);
|
||||||
|
//char ret[150];
|
||||||
|
sprintf(ret,"(int)a: %d, (int)b: %d",a,b);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EXPECT_MOCK_CALL(int, f2_mock, (int a,int b), (a<b), 3){
|
||||||
|
return a+b;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_MOCK_CALL(int, f2_mock, (int a,int b), ((a<b)&&(b<100)), 1){
|
||||||
|
return a*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
WILL_MOCK_CALL(int, f2_mock, (int a,int b), (a!=b), 6){
|
||||||
|
return a/b;
|
||||||
|
}
|
||||||
|
EXPECT_MOCK_CALL(int, f2_mock, (int a,int b), (a==b), 1){
|
||||||
|
return a/b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// //
|
||||||
|
|
||||||
|
MOCK_FUNC(int, f3_mock,(int a,int b),(a,b))
|
||||||
|
|
||||||
|
EXPECT_MOCK_CALL(int, f3_mock, (int a,int b), (a<b), 2){
|
||||||
|
return a+b;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_MOCK_CALL(int, f2_mock, (int a,int b), ((a<b)&&(b<100)), 1){
|
||||||
|
return a*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
WILL_MOCK_CALL(int, f2_mock, (int a,int b), (a!=b), 6){
|
||||||
|
return a/b;
|
||||||
|
}
|
||||||
|
EXPECT_MOCK_CALL(int, f2_mock, (int a,int b), (a==b), 1){
|
||||||
|
return a/b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// //
|
||||||
|
|
||||||
|
EXPECT_MOCK_CALL(int, f2_mock, (int a,int b), (1), ININITY_REPS){
|
||||||
|
return a*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(f2mock_test){
|
||||||
|
INIT_CALLER_MOCK(f2_mock);
|
||||||
|
//LOG("--------------------------- > call f2_mock:%d: %d\n",0,f2_mock(1,4));
|
||||||
|
|
||||||
|
|
||||||
|
for(int i=0; i<8; ++i){
|
||||||
|
|
||||||
|
if(i<2) {
|
||||||
|
//int val = f2_mock(i,4);
|
||||||
|
//LOG("call f2_mock:%d: %d\n",i,val);
|
||||||
|
LOG("call f2_mock:%d: %d\n",i,f2_mock(i,4));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(i<4) LOG("call:%d: %d\n",i,f2_mock(i,3));
|
||||||
|
else LOG("call:%d:%d\n",i,f2_mock(i,i*i));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
|
|
||||||
//run_all_tests();
|
//run_all_tests();
|
||||||
//run_all_tests_parallel(4);
|
//run_all_tests_parallel(4);
|
||||||
|
|
||||||
|
|||||||
+1265
-11
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user