github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/stdio.c (about) 1 // This program actually still works without including stdio.h but it should be 2 // here for consistency. 3 4 #include "tests.h" 5 #include <assert.h> 6 #include <stdarg.h> 7 #include <stdio.h> 8 #include <string.h> 9 10 #define START_TEST(t) \ 11 diag(#t); \ 12 test_##t(); 13 14 // size of that file 15 int filesize = 32; 16 char* test_file = "tests/stdio.txt"; 17 18 void test_putchar() 19 { 20 putchar('#'); 21 char c; 22 for (c = 'A'; c <= 'Z'; c++) 23 putchar(c); 24 putchar('\n'); 25 26 pass("%s", "putchar"); 27 } 28 29 void test_puts() 30 { 31 puts("#c4go"); 32 33 pass("%s", "puts"); 34 } 35 36 void test_printf() 37 { 38 // TODO: printf() has a different syntax to Go 39 // https://github.com/Konstantin8105/c4go/issues/94 40 41 printf("# Characters: %c %c \n", 'a', 65); 42 //printf("Decimals: %d %ld\n", 1977, 650000L); 43 printf("# Preceding with blanks: %10d \n", 1977); 44 printf("# Preceding with zeros: %010d \n", 1977); 45 printf("# Some different radices: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100); 46 printf("# floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416); 47 printf("# Width trick: %*d \n", 5, 10); 48 printf("# %s \n", "A string"); 49 50 // Type printf 51 unsigned long long ull = 42; 52 printf("Long long : %u\n", ull); 53 unsigned int ui = 42; 54 printf("uint : %u\n", ui); 55 double d = 42.42; 56 printf("double : %f\n", d); 57 printf("double : %lf\n", d); 58 printf("double : %2.2f\n", d); 59 60 // Literal error 61 printf("Символьный литерал \'A\':\t%d\n", sizeof('A')); 62 63 int magnitude = 4; 64 char printfFormat[30] = "%0"; 65 char magnitudeString[10]; 66 sprintf(magnitudeString, "%d", magnitude); 67 strcat(printfFormat, magnitudeString); 68 strcat(printfFormat, "d "); 69 printf("# "); 70 printf(printfFormat, 120); 71 printf(" \n"); 72 73 pass("%s", "printf"); 74 } 75 76 void test_remove() 77 { 78 // TODO: This does not actually test successfully deleting a file. 79 if (remove("myfile.txt") != 0) { 80 pass("%s", "error deleting file"); 81 } else { 82 fail("%s", "file successfully deleted"); 83 } 84 } 85 86 void test_rename() 87 { 88 // TODO: This does not actually test successfully renaming a file. 89 int result; 90 char oldname[] = "oldname.txt"; 91 char newname[] = "newname.txt"; 92 result = rename(oldname, newname); 93 if (result == 0) { 94 fail("%s", "File successfully renamed"); 95 } else { 96 pass("%s", "Error renaming file"); 97 } 98 } 99 100 void test_fopen() 101 { 102 FILE* pFile; 103 pFile = fopen("./testdata/myfile.txt", "w"); 104 if (pFile != NULL) { 105 is_not_null(pFile); 106 fclose(pFile); 107 } 108 } 109 110 void test_tmpfile() 111 { 112 char buffer[256]; 113 FILE* pFile; 114 pFile = tmpfile(); 115 116 fputs("hello world", pFile); 117 rewind(pFile); 118 fputs(fgets(buffer, 256, pFile), stdout); 119 fclose(pFile); 120 } 121 122 void test_tmpnam() 123 { 124 // TODO: This is a tricky one to test because the output of tmpnam() in C 125 // and Go will be different. I will keep the test here so at least it tries 126 // to run the code but the test itself is not actually proving anything. 127 128 char* pointer; 129 130 // FIXME: We cannot pass variables by reference yet, which is a legitimate 131 // way to use tmpnam(). I have to leave this disabled for now. 132 // 133 // char buffer[L_tmpnam]; 134 // tmpnam(buffer); 135 // assert(buffer != NULL); 136 137 pointer = tmpnam(NULL); 138 is_not_null(pointer); 139 } 140 141 void test_fclose() 142 { 143 remove("./testdata/myfile.txt"); 144 FILE* pFile; 145 pFile = fopen("./testdata/myfile.txt", "w"); 146 fputs("fclose example", pFile); 147 fclose(pFile); 148 // remove temp file 149 is_eq(remove("./testdata/myfile.txt"), 0) 150 } 151 152 void test_fflush() 153 { 154 char mybuffer[80]; 155 FILE* pFile; 156 pFile = fopen("./testdata/example.txt", "w+"); 157 is_not_null(pFile) or_return(); 158 159 fputs("test", pFile); 160 fflush(pFile); // flushing or repositioning required 161 fgets(mybuffer, 80, pFile); 162 fclose(pFile); 163 // remove temp file 164 is_eq(remove("./testdata/example.txt"), 0) 165 } 166 167 void test_fprintf() 168 { 169 remove("./testdata/myfile1.txt"); 170 FILE* pFile; 171 int n; 172 char* name = "John Smith"; 173 174 pFile = fopen("./testdata/myfile1.txt", "w"); 175 is_not_null(pFile); 176 177 for (n = 0; n < 3; n++) { 178 fprintf(pFile, "Name %d [%-10.10s]\n", n + 1, name); 179 } 180 181 fclose(pFile); 182 // remove temp file 183 is_eq(remove("./testdata/myfile1.txt"), 0) 184 } 185 186 void test_fscanf() 187 { 188 remove("./testdata/myfile2.txt"); 189 190 char str[80]; 191 char end[80]; 192 float f; 193 int i; 194 FILE* pFile; 195 196 pFile = fopen("./testdata/myfile2.txt", "w+"); 197 is_not_null(pFile); 198 199 fprintf(pFile, "%f \r\n\t\n %s %d %s", 3.1416, "PI", 42, "end"); 200 rewind(pFile); 201 fscanf(pFile, "%f", &f); 202 fscanf(pFile, "%s", str); 203 fscanf(pFile, "%d", &i); 204 fscanf(pFile, "%s", end); 205 fclose(pFile); 206 pFile = NULL; 207 208 is_eq(f, 3.1416); 209 is_streq(str, "PI"); 210 is_eq(i, 42); 211 is_streq(end, "end"); 212 213 // read again 214 FILE* pFile2; 215 pFile2 = fopen("./testdata/myfile2.txt", "r"); 216 is_not_null(pFile2); 217 218 fscanf(pFile2, "%f", &f); 219 fscanf(pFile2, "%s", str); 220 fscanf(pFile2, "%d", &i); 221 fscanf(pFile2, "%s", end); 222 fclose(pFile2); 223 pFile2 = NULL; 224 225 is_eq(f, 3.1416); 226 is_streq(str, "PI"); 227 is_eq(i, 42); 228 is_streq(end, "end"); 229 230 // remove temp file 231 is_eq(remove("./testdata/myfile2.txt"), 0) 232 233 // test file fscan.txt 234 FILE* in 235 = fopen("./tests/stdio_fscan.txt", "r"); 236 char dummy[128]; 237 238 for (int iter = 0; iter < 10; iter++) { 239 int e = fscanf(in, "%s", dummy); 240 printf("fscan : iter[%d] : err = %d\n", iter, e); 241 if (e < 0) { 242 break; 243 } 244 printf("fscan : iter[%d] : str = %s\n", iter, dummy); 245 } 246 } 247 248 void test_fgetc() 249 { 250 FILE* pFile; 251 int c; 252 int n = 0; 253 pFile = fopen("tests/stdio.c", "r"); 254 is_not_null(pFile); 255 256 do { 257 c = fgetc(pFile); 258 if (c == '$') 259 n++; 260 } while (c != EOF); 261 fclose(pFile); 262 263 is_eq(n, 2); 264 } 265 266 void test_fgets() 267 { 268 FILE* pFile; 269 char* mystring; 270 char dummy[20]; 271 272 pFile = fopen("tests/stdio.c", "r"); 273 is_not_null(pFile); 274 275 mystring = fgets(dummy, 20, pFile); 276 is_not_null(mystring); 277 278 fclose(pFile); 279 } 280 281 void test_fputc() 282 { 283 char c; 284 285 fputc('#', stdout); 286 for (c = 'A'; c <= 'Z'; c++) 287 fputc(c, stdout); 288 fputc('\n', stdout); 289 } 290 291 void test_fputs() 292 { 293 FILE* pFile; 294 char* sentence = "Hello, World"; 295 296 pFile = fopen("./testdata/mylog.txt", "w"); 297 fputs(sentence, pFile); 298 fclose(pFile); 299 // remove temp file 300 is_eq(remove("./testdata/mylog.txt"), 0) 301 } 302 303 void test_getc() 304 { 305 FILE* pFile; 306 int c; 307 int n = 0; 308 pFile = fopen("tests/stdio.c", "r"); 309 is_not_null(pFile); 310 311 do { 312 c = getc(pFile); 313 if (c == '$') 314 n++; 315 } while (c != EOF); 316 fclose(pFile); 317 318 is_eq(n, 2); 319 } 320 321 void test_putc() 322 { 323 FILE* pFile; 324 char c; 325 326 pFile = fopen("./testdata/whatever.txt", "w"); 327 for (c = 'A'; c <= 'Z'; c++) { 328 putc(c, pFile); 329 } 330 fclose(pFile); 331 // remove temp file 332 is_eq(remove("./testdata/whatever.txt"), 0) 333 } 334 335 void test_fseek() 336 { 337 FILE* pFile; 338 pFile = fopen("./testdata/example.txt", "w"); 339 fputs("This is an apple.", pFile); 340 fseek(pFile, 9, SEEK_SET); 341 fputs(" sam", pFile); 342 fclose(pFile); 343 // remove temp file 344 is_eq(remove("./testdata/example.txt"), 0) 345 } 346 347 void test_ftell() 348 { 349 FILE* pFile; 350 long size; 351 352 pFile = fopen(test_file, "r"); 353 is_not_null(pFile); 354 355 fseek(pFile, 0, SEEK_END); // non-portable 356 size = ftell(pFile); 357 fclose(pFile); 358 359 is_eq(size, filesize); 360 } 361 362 void test_fread() 363 { 364 FILE* pFile; 365 int lSize; 366 char buffer[1024]; 367 int result; 368 369 pFile = fopen("tests/getchar.c", "r"); 370 is_not_null(pFile); 371 372 // obtain file size: 373 fseek(pFile, 0, SEEK_END); 374 lSize = ftell(pFile); 375 is_eq(lSize, 216); 376 377 rewind(pFile); 378 379 // copy the file into the buffer: 380 result = fread(buffer, 1, lSize, pFile); 381 is_eq(result, lSize); 382 383 // See issue #107 384 buffer[lSize - 1] = 0; 385 386 is_eq(strlen(buffer), 215); 387 388 // terminate 389 fclose(pFile); 390 } 391 392 void test_fwrite() 393 { 394 FILE* pFile; 395 pFile = fopen("./testdata/myfile.bin", "w"); 396 fwrite("xyz", 1, 3, pFile); 397 fclose(pFile); 398 // remove temp file 399 is_eq(remove("./testdata/myfile.bin"), 0) 400 } 401 402 void test_fgetpos() 403 { 404 FILE* pFile; 405 int c; 406 int n; 407 fpos_t pos; 408 409 pFile = fopen("tests/stdio.c", "r"); 410 is_not_null(pFile); 411 412 c = fgetc(pFile); 413 is_eq(c, '/'); 414 415 fgetpos(pFile, &pos); 416 for (n = 0; n < 3; n++) { 417 fsetpos(pFile, &pos); 418 c = fgetc(pFile); 419 is_eq(c, '/'); 420 } 421 422 fclose(pFile); 423 } 424 425 void test_fsetpos() 426 { 427 FILE* pFile; 428 fpos_t position; 429 430 pFile = fopen("./testdata/myfile.txt", "w"); 431 fgetpos(pFile, &position); 432 fputs("That is a sample", pFile); 433 fsetpos(pFile, &position); 434 fputs("This", pFile); 435 fclose(pFile); 436 // remove temp file 437 is_eq(remove("./testdata/myfile.txt"), 0) 438 } 439 440 void test_rewind() 441 { 442 int n; 443 FILE* pFile; 444 char buffer[27]; 445 446 pFile = fopen("./testdata/myfile.txt", "w+"); 447 for (n = 'A'; n <= 'Z'; n++) 448 fputc(n, pFile); 449 rewind(pFile); 450 fread(buffer, 1, 26, pFile); 451 fclose(pFile); 452 buffer[26] = '\0'; 453 454 is_eq(strlen(buffer), 26); 455 456 // remove temp file 457 is_eq(remove("./testdata/myfile.txt"), 0) 458 } 459 460 void test_feof() 461 { 462 FILE* pFile; 463 int n = 0; 464 pFile = fopen(test_file, "r"); 465 is_not_null(pFile); 466 467 while (fgetc(pFile) != EOF) { 468 ++n; 469 } 470 if (feof(pFile)) { 471 pass("%s", "End-of-File reached."); 472 is_eq(n, filesize); 473 } else { 474 fail("%s", "End-of-File was not reached."); 475 } 476 477 fclose(pFile); 478 } 479 480 void test_sprintf() 481 { 482 char buffer[100]; 483 int cx; 484 cx = snprintf(buffer, 100, "The half of %d is %d", 60, 60 / 2); 485 is_streq(buffer, "The half of 60 is 30"); 486 is_eq(cx, 20); 487 } 488 489 void test_snprintf() 490 { 491 char buffer[50]; 492 int n, a = 5, b = 3; 493 n = sprintf(buffer, "%d plus %d is %d", a, b, a + b); 494 is_streq(buffer, "5 plus 3 is 8"); 495 is_eq(n, 13); 496 497 char status[80]; 498 char* filename = "out.txt"; 499 int numrows = 10; 500 int dirty = 1; 501 int len = snprintf(status, sizeof(status), "%.20s - %d lines %s", 502 filename, numrows, dirty ? "(modified)" : ""); 503 printf("%s\n", status); 504 is_eq(len, 29); 505 } 506 507 int PrintFError(const char* format, ...) 508 { 509 char buffer[256]; 510 va_list args; 511 va_start(args, format); 512 int s = vsprintf(buffer, format, args); 513 va_end(args); 514 printf("vsnprintf buffer: `%s`\n", buffer); 515 return s; 516 } 517 518 void test_vsprintf() 519 { 520 int s = PrintFError("Success function '%s' %.2f", "vsprintf", 3.1415926); 521 is_true(s == 19 + 8 + 5); 522 } 523 524 int PrintFError2(const char* format, ...) 525 { 526 char buffer[256]; 527 va_list args; 528 va_start(args, format); 529 int s = vsnprintf(buffer, 256, format, args); 530 va_end(args); 531 printf("vsnprintf buffer: `%s`\n", buffer); 532 return s; 533 } 534 535 void test_vsnprintf() 536 { 537 int s = PrintFError2("Success function '%s' %.2f", "vsprintf", 3.1415926); 538 is_true(s == 19 + 8 + 5); 539 s = PrintFError2("HHELP %d", (int)(2)); 540 is_true(s == 7); 541 } 542 543 void test_eof() 544 { 545 if ((int)(EOF) == -1) { 546 pass("ok"); 547 } 548 char c = EOF; 549 if (c == (char)(EOF)) { 550 pass("ok"); 551 } 552 char a[1]; 553 a[0] = 's'; 554 if (a[0] != EOF) { 555 pass("ok"); 556 } 557 a[0] = EOF; 558 if (a[0] != EOF) { 559 fail("EOF == EOF - fail"); 560 } else { 561 pass("ok"); 562 } 563 } 564 565 void test_perror() 566 { 567 perror("test perror"); 568 } 569 570 void test_getline() 571 { 572 { 573 diag("getline: not empty file"); 574 FILE* pFile; 575 pFile = fopen(test_file, "r"); 576 is_not_null(pFile); 577 578 size_t len; 579 char* line = NULL; 580 char** pnt = &line; 581 size_t* l = &len; 582 ssize_t pos = getline(pnt, l, pFile); 583 for (int i = 0; i < pos; i++) { 584 printf("[%d] : `%d`\n", i, line[i]); 585 } 586 printf("pos [%d] == filesize [%d]\n", pos, filesize); 587 is_eq(pos, filesize); 588 } 589 { 590 diag("getline: not empty file"); 591 FILE* pFile; 592 pFile = fopen("./tests/empty.txt", "r"); 593 is_not_null(pFile); 594 595 size_t len; 596 char* line = NULL; 597 char** pnt = &line; 598 size_t* l = &len; 599 ssize_t pos = getline(pnt, l, pFile); 600 is_eq(pos, -1); 601 } 602 } 603 604 void test_sscanf() 605 { 606 char sentence[] = "Example\nRudolph is 12 years old"; 607 char header[50]; 608 char temp[50]; 609 char str[20]; 610 int i; 611 sscanf(sentence, "%s %s %s %d", header, str, temp, &i); 612 printf("Header: %s\n", header); 613 is_eq(i, 12); 614 is_streq(str, "Rudolph"); 615 } 616 617 void test_FILE() 618 { 619 FILE* p = stdout; 620 is_true(p != stderr); 621 is_true(p == stdout); 622 (void)p; 623 } 624 625 void WriteFormatted(const char* format, ...) 626 { 627 va_list args; 628 va_start(args, format); 629 vprintf(format, args); 630 va_end(args); 631 } 632 633 void test_vprintf() 634 { 635 WriteFormatted("Call with %d variable argument.\n", 1); 636 WriteFormatted("Call with %d variable %s.\n", 2, "arguments"); 637 } 638 639 void FWriteFormatted(FILE* stream, const char* format, ...) 640 { 641 va_list args; 642 va_start(args, format); 643 vfprintf(stream, format, args); 644 va_end(args); 645 } 646 647 void test_vfprintf() 648 { 649 FILE* pFile; 650 pFile = fopen("./testdata/vfprintf.txt", "w"); 651 FWriteFormatted(pFile, "Call with %d variable argument.\n", 1); 652 FWriteFormatted(pFile, "Call with %d variable %s.\n", 2, "arguments"); 653 fclose(pFile); 654 } 655 656 void test_setbuf() 657 { 658 char buffer[BUFSIZ]; 659 FILE *pFile1, *pFile2; 660 661 pFile1 = fopen("./testdata/setbuf.txt", "w"); 662 pFile2 = fopen("./testdata/setbuf2.txt", "a"); 663 664 setbuf(pFile1, buffer); 665 fputs("This is sent to a buffered stream", pFile1); 666 fflush(pFile1); 667 668 setbuf(pFile2, NULL); 669 fputs("This is sent to an unbuffered stream", pFile2); 670 671 fclose(pFile1); 672 fclose(pFile2); 673 (void)(buffer); 674 } 675 676 void test_setvbuf() 677 { 678 FILE* pFile; 679 pFile = fopen("./testdata/detvbuf.txt", "w"); 680 setvbuf(pFile, NULL, _IOFBF, 1024); 681 fclose(pFile); 682 } 683 684 int main() 685 { 686 plan(71); 687 688 START_TEST(putchar); 689 START_TEST(puts); 690 START_TEST(printf); 691 START_TEST(remove); 692 START_TEST(rename); 693 START_TEST(fopen); 694 START_TEST(tmpfile); 695 START_TEST(tmpnam); 696 START_TEST(fclose); 697 START_TEST(fflush); 698 START_TEST(printf); 699 START_TEST(fprintf); 700 START_TEST(fscanf); 701 START_TEST(fgetc); 702 START_TEST(fgets); 703 START_TEST(fputc); 704 START_TEST(fputs); 705 START_TEST(getc); 706 START_TEST(putc); 707 START_TEST(fseek); 708 START_TEST(ftell); 709 START_TEST(fread); 710 START_TEST(fwrite); 711 START_TEST(fgetpos); 712 START_TEST(fsetpos); 713 START_TEST(rewind); 714 START_TEST(feof); 715 START_TEST(sprintf); 716 START_TEST(snprintf); 717 START_TEST(vsprintf); 718 START_TEST(vsnprintf); 719 START_TEST(eof); 720 START_TEST(getline); 721 START_TEST(sscanf); 722 START_TEST(FILE); 723 START_TEST(vprintf); 724 START_TEST(vfprintf); 725 START_TEST(setbuf); 726 START_TEST(setvbuf); 727 728 // that test must be last test 729 START_TEST(perror); 730 731 done_testing(); 732 }