2017-05-06 2 views
1
lesen

Ich habe eine High-Level-Wrapper-und Befehls-Sammlung geschrieben, die die RProc/RPMsg-Schnittstelle verwendet, um mit einem Mikroprozessor zu kommunizieren, um so viel wie möglich zu testen Ich habe Komponententests dafür geschrieben ein Linux-Pseudoterminal anstelle der "echten" Schnittstelle.Kann nicht von pseudoterminal

Meine Tests haben nicht funktioniert. Ich vereinfachte schließlich den Test bis zu dem Punkt, wo es keine Spuren von meinem Code enthalten ist - und es immer noch nicht funktioniert:

BOOST_AUTO_TEST_CASE(constructor) 
{ 
    const auto master_pty = ::posix_openpt(O_RDWR); 
    BOOST_REQUIRE(master_pty != -1); 
    BOOST_REQUIRE(::grantpt(master_pty) != -1); 
    BOOST_REQUIRE(::unlockpt(master_pty) != -1); 

    const auto slave_pty_name = ::ptsname(master_pty); 
    const auto slave_pty = ::open(slave_pty_name, O_RDWR); 
    BOOST_REQUIRE(slave_pty != -1); 

    const auto in_data = std::array<std::uint8_t, 4>{1, 2, 3, 4}; 
    const auto bytes_written = ::write(master_pty, in_data.data(), in_data.size()); 
    if (bytes_written < 0) { 
     BOOST_FAIL("Failed to write: " << errno); 
    } 
    BOOST_REQUIRE_EQUAL(in_data.size(), bytes_written); 

    auto out_data = std::array<std::uint8_t, in_data.size()>{}; 
    const auto bytes_read = ::read(slave_pty, out_data.data(), out_data.size()); 
    BOOST_CHECK_EQUAL(bytes_read, bytes_written); 
    if (bytes_read < 0) { 
     BOOST_FAIL("::read failed: " << errno); 
    } 

    ::close(slave_pty); 
    ::close(master_pty); 
} 

Der Ausgang davon:

*** 1 failure is detected in the test module "cmPTP Test Suite" 
# cmPTP-manager-test -l all --run_test=comms_rproc_interface/constructor 
Running 1 test case... 
Entering test module "cmPTP Test Suite" 
interface_test.cpp(17): Entering test suite "comms_rproc_interface" 
interface_test.cpp(19): Entering test case "constructor" 
interface_test.cpp(23): info: check master_pty != -1 has passed 
interface_test.cpp(24): info: check grantpt(master_pty) != -1 has passed 
interface_test.cpp(25): info: check unlockpt(master_pty) != -1 has passed 
interface_test.cpp(32): info: check slave_pty != -1 has passed 
interface_test.cpp(72): info: check in_data.size() == bytes_written has passed 
interface_test.cpp(77): error: in "comms_rproc_interface/constructor": check bytes_read == bytes_written has failed [0 != 4] 
interface_test.cpp(19): Leaving test case "constructor"; testing time: 15282us 
interface_test.cpp(17): Leaving test suite "comms_rproc_interface"; testing time: 15931us 
Leaving test module "cmPTP Test Suite"; testing time: 16879us 

*** 1 failure is detected in the test module "cmPTP Test Suite" 

Ich kann meine 4 schreiben Bytes sind in Ordnung, aber auf der Slave-Seite ist nie etwas vorhanden. Warum?

+0

, die nicht wie eigentlich nicht die gelesenen sieht, sondern dass sie die Bytes nicht abgerufen hat. Wurde der Schreibpuffer geleert? – starturtle

+0

@starturtle Sollte: "POSIX erfordert, dass ein Lesevorgang (2), der nachweislich nach einem write() auftritt, die neuen Daten zurückgibt. Beachten Sie, dass nicht alle Dateisysteme POSIX-konform sind." Ich gehe natürlich davon aus, dass Linux/EXT4 POSIX konform ist ... Wie kann ich einen Flush erzwingen? – cmannett85

+0

@starttrotte Eigentlich ist mir gerade klar geworden, dass ein PTS zwei Dateideskriptoren ist, so dass das obige nicht zutrifft. – cmannett85

Antwort

0

Es ist, weil ich vergaß, dass ich ein Pseudo Terminal und kein serielles Gerät schuf. Die PTY behandelte meine Eingabewerte als ASCII (was sie wahrscheinlich ein wenig ausflippte) und wartete auf eine Zeilenrückgabe vor dem Leeren - also war @ starturtles Kommentar über das Leeren korrekt, nur nicht in einem "normalen" Schreibstil .

Diese trival SSCCE zeigt, wie ich es hätte tun sollen:

#include <unistd.h> 
#include <pty.h> 

#include <array> 
#include <iostream> 

int main() 
{ 
    // Make the PTY 'raw' to disable traditional terminal-like 
    // behaviour 
    struct termios ts; 
    cfmakeraw(&ts); 

    auto master_pty = -1; 
    auto slave_pty = -1; 
    if (::openpty(&master_pty, &slave_pty, nullptr, &ts, nullptr) < 0) { 
     std::cerr << "Cannot create PTY: " << errno << std::endl; 
     return EXIT_FAILURE; 
    } 

    const auto in_data = std::array<std::uint8_t, 5>{1, 2, 3, 4, 5}; 
    const auto bytes_written = ::write(master_pty, in_data.data(), in_data.size()); 
    if (bytes_written < 0) { 
     std::cerr << "Failed to write: " << errno << std::endl; 
     return EXIT_FAILURE; 
    } 

    auto out_data = std::array<std::uint8_t, in_data.size()>{}; 
    out_data.fill(0); 

    const auto bytes_read = ::read(slave_pty, out_data.data(), out_data.size()); 
    if (bytes_read < 0) { 
     std::cerr << "::read failed: " << errno << std::endl; 
     return EXIT_FAILURE; 
    } 

    for (auto&& c : out_data) { 
     std::cout << static_cast<int>(c); 
    } 
    std::cout << std::endl; 

    ::close(slave_pty); 
    ::close(master_pty); 
}