- Timestamp:
- Feb 13, 2018 9:02:21 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/serial/SerialTest.cpp
r70761 r70981 35 35 #include <iprt/param.h> 36 36 #include <iprt/process.h> 37 #include <iprt/rand.h> 37 38 #include <iprt/serialport.h> 38 39 #include <iprt/stream.h> … … 45 46 *********************************************************************************************************************************/ 46 47 47 48 /** Number of times to toggle the status lines during the test. */ 49 #define SERIALTEST_STS_LINE_TOGGLE_COUNT 100 48 50 49 51 /********************************************************************************************************************************* 50 52 * Structures and Typedefs * 51 53 *********************************************************************************************************************************/ 54 55 56 /** 57 * Serial test mode. 58 */ 59 typedef enum SERIALTESTMODE 60 { 61 /** Invalid mode. */ 62 SERIALTESTMODE_INVALID = 0, 63 /** Serial port is looped back to itself */ 64 SERIALTESTMODE_LOOPBACK, 65 /** A secondary serial port is used with a null modem cable in between. */ 66 SERIALTESTMODE_SECONDARY, 67 /** The serial port is connected externally over which we have no control. */ 68 SERIALTESTMODE_EXTERNAL, 69 /** Usual 32bit hack. */ 70 SERIALTESTMODE_32BIT_HACK = 0x7fffffff 71 } SERIALTESTMODE; 72 /** Pointer to a serial test mode. */ 73 typedef SERIALTESTMODE *PSERIALTESTMDOE; 52 74 53 75 /** Pointer to the serial test data instance. */ … … 130 152 {"--databits", 'c', RTGETOPT_REQ_UINT32 }, 131 153 {"--stopbits", 's', RTGETOPT_REQ_STRING }, 132 {"--loopbackdevice", 'l', RTGETOPT_REQ_STRING }, 154 {"--mode", 'm', RTGETOPT_REQ_STRING }, 155 {"--secondarydevice", 'l', RTGETOPT_REQ_STRING }, 133 156 {"--tests", 't', RTGETOPT_REQ_STRING }, 134 157 {"--txbytes", 'x', RTGETOPT_REQ_UINT32 }, … … 139 162 static DECLCALLBACK(int) serialTestRunReadWrite(PSERIALTEST pSerialTest); 140 163 static DECLCALLBACK(int) serialTestRunWrite(PSERIALTEST pSerialTest); 164 static DECLCALLBACK(int) serialTestRunStsLines(PSERIALTEST pSerialTest); 141 165 142 166 /** Implemented tests. */ … … 144 168 { 145 169 {"readwrite", "Simple Read/Write test on the same serial port", serialTestRunReadWrite }, 146 {"write", "Simple write test (verification done somewhere else)", serialTestRunWrite }, 170 {"write", "Simple write test (verification done somewhere else)", serialTestRunWrite }, 171 {"stslines", "Testing the status line setting and receiving", serialTestRunStsLines } 147 172 }; 148 173 149 174 /** The test handle. */ 150 static RTTEST g_hTest = NIL_RTTEST; 175 static RTTEST g_hTest = NIL_RTTEST; 176 /** The serial test mode. */ 177 static SERIALTESTMODE g_enmMode = SERIALTESTMODE_LOOPBACK; 178 /** Random number generator. */ 179 static RTRAND g_hRand = NIL_RTRAND; 151 180 /** The serial port handle. */ 152 static RTSERIALPORT g_hSerialPort = NIL_RTSERIALPORT;181 static RTSERIALPORT g_hSerialPort = NIL_RTSERIALPORT; 153 182 /** The loopback serial port handle if configured. */ 154 static RTSERIALPORT g_hSerialPort Loopback= NIL_RTSERIALPORT;183 static RTSERIALPORT g_hSerialPortSecondary = NIL_RTSERIALPORT; 155 184 /** Number of bytes to transmit for read/write tests. */ 156 static size_t g_cbTx = _1M;185 static size_t g_cbTx = _1M; 157 186 /** The config used. */ 158 187 static RTSERIALPORTCFG g_SerialPortCfg = … … 325 354 326 355 356 DECLINLINE(bool) serialTestRndTrue(void) 357 { 358 return RTRandAdvU32Ex(g_hRand, 0, 1) == 1; 359 } 360 327 361 /** 328 362 * Runs a simple read/write test. … … 407 441 tsRuntime /= 1000; /* Seconds */ 408 442 RTTestValue(pSerialTest->hTest, "Throughput", g_cbTx / tsRuntime, RTTESTUNIT_BYTES_PER_SEC); 443 444 return rc; 445 } 446 447 448 /** 449 * Tests setting status lines and getting notified about status line changes. 450 * 451 * @returns IPRT status code. 452 * @param pSerialTest The serial test configuration. 453 */ 454 static DECLCALLBACK(int) serialTestRunStsLines(PSERIALTEST pSerialTest) 455 { 456 int rc = VINF_SUCCESS; 457 458 if (g_enmMode == SERIALTESTMODE_LOOPBACK) 459 { 460 uint32_t fStsLinesQueriedOld = 0; 461 462 rc = RTSerialPortChgStatusLines(pSerialTest->hSerialPort, 463 RTSERIALPORT_CHG_STS_LINES_F_RTS | RTSERIALPORT_CHG_STS_LINES_F_DTR, 464 0); 465 if (RT_SUCCESS(rc)) 466 { 467 rc = RTSerialPortQueryStatusLines(pSerialTest->hSerialPort, &fStsLinesQueriedOld); 468 if (RT_SUCCESS(rc)) 469 { 470 /* Everything should be clear at this stage. */ 471 if (!fStsLinesQueriedOld) 472 { 473 uint32_t fStsLinesSetOld = 0; 474 475 for (uint32_t i = 0; i < SERIALTEST_STS_LINE_TOGGLE_COUNT; i++) 476 { 477 uint32_t fStsLinesSet = 0; 478 uint32_t fStsLinesClear = 0; 479 480 /* Change RTS? */ 481 if (serialTestRndTrue()) 482 { 483 /* Clear, if set previously otherwise set it. */ 484 if (fStsLinesSetOld & RTSERIALPORT_CHG_STS_LINES_F_RTS) 485 fStsLinesClear |= RTSERIALPORT_CHG_STS_LINES_F_RTS; 486 else 487 fStsLinesSet |= RTSERIALPORT_CHG_STS_LINES_F_RTS; 488 } 489 490 /* Change DTR? */ 491 if (serialTestRndTrue()) 492 { 493 /* Clear, if set previously otherwise set it. */ 494 if (fStsLinesSetOld & RTSERIALPORT_CHG_STS_LINES_F_DTR) 495 fStsLinesClear |= RTSERIALPORT_CHG_STS_LINES_F_DTR; 496 else 497 fStsLinesSet |= RTSERIALPORT_CHG_STS_LINES_F_DTR; 498 } 499 500 rc = RTSerialPortChgStatusLines(pSerialTest->hSerialPort, fStsLinesClear, fStsLinesSet); 501 if (RT_FAILURE(rc)) 502 { 503 RTTestFailed(g_hTest, "Changing status lines failed with %Rrc on iteration %u (fSet=%#x fClear=%#x)\n", 504 rc, i, fStsLinesSet, fStsLinesClear); 505 break; 506 } 507 508 /* Wait for status line monitor event. */ 509 uint32_t fEvtsRecv = 0; 510 rc = RTSerialPortEvtPoll(pSerialTest->hSerialPort, RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED, 511 &fEvtsRecv, RT_MS_1SEC); 512 if ( RT_FAILURE(rc) 513 && (rc != VERR_TIMEOUT && !fStsLinesSet && !fStsLinesClear)) 514 { 515 RTTestFailed(g_hTest, "Waiting for status line change failed with %Rrc on iteration %u\n", 516 rc, i); 517 break; 518 } 519 520 uint32_t fStsLinesQueried = 0; 521 rc = RTSerialPortQueryStatusLines(pSerialTest->hSerialPort, &fStsLinesQueried); 522 if (RT_FAILURE(rc)) 523 { 524 RTTestFailed(g_hTest, "Querying status lines failed with %Rrc on iteration %u\n", 525 rc, i); 526 break; 527 } 528 529 /* Compare expected and real result. */ 530 if ( (fStsLinesQueried & RTSERIALPORT_STS_LINE_DSR) 531 != (fStsLinesQueriedOld & RTSERIALPORT_STS_LINE_DSR)) 532 { 533 if ( (fStsLinesQueried & RTSERIALPORT_STS_LINE_DSR) 534 && !(fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_DTR)) 535 RTTestFailed(g_hTest, "DSR line got set when it shouldn't be on iteration %u\n", 536 rc, i); 537 else if ( !(fStsLinesQueried & RTSERIALPORT_STS_LINE_DSR) 538 && !(fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_DTR)) 539 RTTestFailed(g_hTest, "DSR line got cleared when it shouldn't be on iteration %u\n", 540 rc, i); 541 } 542 else if ( (fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_DTR) 543 || (fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_DTR)) 544 RTTestFailed(g_hTest, "DSR line didn't change when it should have on iteration %u\n", 545 rc, i); 546 547 if ( (fStsLinesQueried & RTSERIALPORT_STS_LINE_DCD) 548 != (fStsLinesQueriedOld & RTSERIALPORT_STS_LINE_DCD)) 549 { 550 if ( (fStsLinesQueried & RTSERIALPORT_STS_LINE_DCD) 551 && !(fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_DTR)) 552 RTTestFailed(g_hTest, "DCD line got set when it shouldn't be on iteration %u\n", 553 rc, i); 554 else if ( !(fStsLinesQueried & RTSERIALPORT_STS_LINE_DCD) 555 && !(fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_DTR)) 556 RTTestFailed(g_hTest, "DCD line got cleared when it shouldn't be on iteration %u\n", 557 rc, i); 558 } 559 else if ( (fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_DTR) 560 || (fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_DTR)) 561 RTTestFailed(g_hTest, "DSR line didn't change when it should have on iteration %u\n", 562 rc, i); 563 564 if ( (fStsLinesQueried & RTSERIALPORT_STS_LINE_CTS) 565 != (fStsLinesQueriedOld & RTSERIALPORT_STS_LINE_CTS)) 566 { 567 if ( (fStsLinesQueried & RTSERIALPORT_STS_LINE_CTS) 568 && !(fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_RTS)) 569 RTTestFailed(g_hTest, "CTS line got set when it shouldn't be on iteration %u\n", 570 rc, i); 571 else if ( !(fStsLinesQueried & RTSERIALPORT_STS_LINE_CTS) 572 && !(fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_RTS)) 573 RTTestFailed(g_hTest, "CTS line got cleared when it shouldn't be on iteration %u\n", 574 rc, i); 575 } 576 else if ( (fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_RTS) 577 || (fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_RTS)) 578 RTTestFailed(g_hTest, "CTS line didn't change when it should have on iteration %u\n", 579 rc, i); 580 581 if (RTTestErrorCount(g_hTest) > 0) 582 break; 583 584 fStsLinesSetOld |= fStsLinesSet; 585 fStsLinesSetOld &= ~fStsLinesClear; 586 fStsLinesQueriedOld = fStsLinesQueried; 587 } 588 } 589 else 590 RTTestFailed(g_hTest, "Status lines active which should be clear (%#x, but expected %#x)\n", 591 fStsLinesQueriedOld, 0); 592 } 593 else 594 RTTestFailed(g_hTest, "Querying status lines failed with %Rrc\n", rc); 595 } 596 else 597 RTTestFailed(g_hTest, "Clearing status lines failed with %Rrc\n", rc); 598 } 599 else 600 rc = VERR_NOT_IMPLEMENTED; 409 601 410 602 return rc; … … 524 716 pszHelp = "Use the given stop bitcount, valid are: 1, 1.5, 2"; 525 717 break; 718 case 'm': 719 pszHelp = "Mode of the serial port, valid are: loopback, secondary, external"; 720 break; 526 721 case 'l': 527 pszHelp = "Use the given serial port device as the loopbackdevice";722 pszHelp = "Use the given serial port device as the secondary device"; 528 723 break; 529 724 case 't': … … 557 752 */ 558 753 const char *pszDevice = NULL; 559 const char *pszDevice Loopback= NULL;754 const char *pszDeviceSecondary = NULL; 560 755 PSERIALTESTDESC paTests = NULL; 561 756 … … 574 769 break; 575 770 case 'l': 576 pszDevice Loopback= ValueUnion.psz;771 pszDeviceSecondary = ValueUnion.psz; 577 772 break; 578 773 case 'b': … … 624 819 } 625 820 break; 821 case 'm': 822 if (!RTStrICmp(ValueUnion.psz, "loopback")) 823 g_enmMode = SERIALTESTMODE_LOOPBACK; 824 else if (!RTStrICmp(ValueUnion.psz, "secondary")) 825 g_enmMode = SERIALTESTMODE_SECONDARY; 826 else if (!RTStrICmp(ValueUnion.psz, "external")) 827 g_enmMode = SERIALTESTMODE_EXTERNAL; 828 else 829 { 830 RTPrintf("Unknown serial test mode \"%s\" given\n", ValueUnion.psz); 831 return RTEXITCODE_FAILURE; 832 } 833 break; 626 834 case 't': 627 835 paTests = serialTestSelectFromCmdLine(ValueUnion.psz); … … 637 845 } 638 846 847 if (g_enmMode == SERIALTESTMODE_SECONDARY && !pszDeviceSecondary) 848 { 849 RTPrintf("Mode set to secondary device but no secondary device given\n"); 850 return RTEXITCODE_FAILURE; 851 } 852 639 853 if (!paTests) 640 854 { … … 648 862 memcpy(paTests, &g_aSerialTests[0], RT_ELEMENTS(g_aSerialTests) * sizeof(SERIALTESTDESC)); 649 863 } 864 865 rc = RTRandAdvCreateParkMiller(&g_hRand); 866 if (RT_FAILURE(rc)) 867 { 868 RTPrintf("Failed to create random number generator: %Rrc\n"); 869 return RTEXITCODE_FAILURE; 870 } 871 872 rc = RTRandAdvSeed(g_hRand, 0x123456789abcdef); 873 AssertRC(rc); 650 874 651 875 /* … … 664 888 if (RT_SUCCESS(rc)) 665 889 { 666 if ( pszDeviceLoopback)890 if (g_enmMode == SERIALTESTMODE_SECONDARY) 667 891 { 668 RTTestSub(g_hTest, "Opening loopbackdevice");669 rc = RTSerialPortOpen(&g_hSerialPort Loopback, pszDeviceLoopback, fFlags);892 RTTestSub(g_hTest, "Opening secondary device"); 893 rc = RTSerialPortOpen(&g_hSerialPortSecondary, pszDeviceSecondary, fFlags); 670 894 if (RT_FAILURE(rc)) 671 RTTestFailed(g_hTest, "Opening loopbackdevice \"%s\" failed with %Rrc\n", pszDevice, rc);895 RTTestFailed(g_hTest, "Opening secondary device \"%s\" failed with %Rrc\n", pszDevice, rc); 672 896 } 673 897 … … 679 903 if (RT_SUCCESS(rc)) 680 904 { 681 if ( pszDeviceLoopback)905 if (g_enmMode == SERIALTESTMODE_SECONDARY) 682 906 { 683 RTTestSub(g_hTest, "Setting serial port configuration for loopbackdevice");684 rc = RTSerialPortCfgSet(g_hSerialPort Loopback, &g_SerialPortCfg, NULL);907 RTTestSub(g_hTest, "Setting serial port configuration for secondary device"); 908 rc = RTSerialPortCfgSet(g_hSerialPortSecondary, &g_SerialPortCfg, NULL); 685 909 if (RT_FAILURE(rc)) 686 RTTestFailed(g_hTest, "Setting configuration of loopbackdevice \"%s\" failed with %Rrc\n", pszDevice, rc);910 RTTestFailed(g_hTest, "Setting configuration of secondary device \"%s\" failed with %Rrc\n", pszDevice, rc); 687 911 } 688 912 … … 700 924 RTTestSub(g_hTest, pTest->pszDesc); 701 925 rc = pTest->pfnRun(&Test); 702 if (RT_FAILURE(rc)) 703 RTTestFailed(g_hTest, "Running test \"%s\" failed with %Rrc\n", pTest->pszId, rc); 926 if ( RT_FAILURE(rc) 927 || RTTestErrorCount(g_hTest) > 0) 928 RTTestFailed(g_hTest, "Running test \"%s\" failed (%Rrc, cErrors=%u)\n", 929 pTest->pszId, rc, RTTestErrorCount(g_hTest)); 704 930 705 931 RTTestSubDone(g_hTest); … … 720 946 RTTestFailed(g_hTest, "No device given on command line\n"); 721 947 948 RTRandAdvDestroy(g_hRand); 722 949 RTMemFree(paTests); 723 950 RTEXITCODE rcExit = RTTestSummaryAndDestroy(g_hTest);
Note:
See TracChangeset
for help on using the changeset viewer.