Project

General

Profile

Actions

Task #3370

closed

TcpChannel: test suite improvement

Added by Junxiao Shi over 8 years ago. Updated about 8 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Faces
Target version:
Start date:
Due date:
% Done:

100%

Estimated time:
3.00 h

Description

Improve TcpChannel test suite with coverage for these functions and situations:

  • accept multiple incoming connections, and check each face works
  • after a face is closed, it's removed from the channel

Reference: commit:65caf200924b28748037750449e28bcb548dbc9c tcp.t.cpp, MultipleAccepts FaceClosing test cases.


Related issues 1 (0 open1 closed)

Blocks NFD - Task #3514: Merge Channel test cases as templateClosedDavide Pesavento

Actions
Actions #1

Updated by Spencer Lee over 8 years ago

  • Status changed from New to In Progress
  • Assignee set to Spencer Lee
Actions #2

Updated by Spencer Lee about 8 years ago

A lot of files were affected in in change 2632.

I am wondering what files I should be looking at and studying in order to write the MultipleAccepts and FaceClosing tests in tcp-channel.t.cpp,

besides daemon/face/tcp-channel.cpp and daemon/face/tcp-factory.cpp.

Actions #3

Updated by Junxiao Shi about 8 years ago

Answer to note-2:

Change 2632 is a big change that removed many test cases.
The missing test cases will be added in #3369 #3370 #3371 #3372 #3373 #3374 #3375 #3376.

Only tcp-channel.* is relevant to this task.

Actions #4

Updated by Spencer Lee about 8 years ago

Is there an advantage to using TcpFactory::createChannel versus the TcpChannel constructor?

tcp-factory.cpp/hpp

shared_ptr<TcpChannel>
createChannel(const std::string& localIp, const std::string& localPort);

versus

tcp-channel.cpp/hpp

TcpChannel(const tcp::Endpoint& localEndpoint);
Actions #5

Updated by Davide Pesavento about 8 years ago

If you're working on the TcpChannel test suite, you should NOT use any TcpFactory methods. Use TcpChannel constructor directly instead.

Actions #6

Updated by Spencer Lee about 8 years ago

  • Status changed from In Progress to Code review
Actions #7

Updated by Spencer Lee about 8 years ago

Change 2632 removed Face::onFail,
and I am uncertain as to what equivalent on fail callback should be specified in the EndToEndFixture, and if the usage of the fixture is preferred in this case.

Actions #8

Updated by Junxiao Shi about 8 years ago

Answer to note-7:

Face::onFail is replaced with Face::afterStateChange where newState is CLOSED.

LpFaceWrapper and its .cpp is a useful reference to determine the relation between face2014 and face2015 APIs.

Actions #9

Updated by Spencer Lee about 8 years ago

Have you seen this error occur before? The faces were not closing before I changed onFail to afterStateChange, and now the failure is a SIGABRT being called:

unknown location(0): fatal error in "FaceClosing": signal: SIGABRT (application abort requested)
../tests/daemon/face/tcp-channel.t.cpp(254): last checkpoint

Is there anything wrong with these lines:

// Face::close must be invoked during io run to be counted as an op
scheduler::schedule(time::milliseconds(100), bind(&Face::close, face1));
BOOST_CHECK_MESSAGE(limitedIo.run(2, time::seconds(10)) == LimitedIo::EXCEED_OPS,
                    "FaceClosing error: cannot properly close faces");
// both faces should get closed
BOOST_CHECK(!static_cast<bool>(face1));
BOOST_CHECK(!static_cast<bool>(face2));
Actions #10

Updated by Spencer Lee about 8 years ago

Another question - am I able to run specific unit-tests? Instead of run the full test suite within /build.

Also am I able to debug unit-test runs with gdb? I have tried gdb on a cpp.3.o file within /build and got a permission denied error.

Actions #11

Updated by Alex Afanasyev about 8 years ago

Spencer Lee wrote:

Have you seen this error occur before? The faces were not closing before I changed onFail to afterStateChange, and now the failure is a SIGABRT being called:

unknown location(0): fatal error in "FaceClosing": signal: SIGABRT (application abort requested)
../tests/daemon/face/tcp-channel.t.cpp(254): last checkpoint

Is there anything wrong with these lines:

// Face::close must be invoked during io run to be counted as an op
scheduler::schedule(time::milliseconds(100), bind(&Face::close, face1));
BOOST_CHECK_MESSAGE(limitedIo.run(2, time::seconds(10)) == LimitedIo::EXCEED_OPS,
                    "FaceClosing error: cannot properly close faces");
// both faces should get closed
BOOST_CHECK(!static_cast<bool>(face1));
BOOST_CHECK(!static_cast<bool>(face2));

Next time, please upload the code that has the error. Otherwise, there is only a guess work.

What you probably missed is the check that the new state of the face is CLOSED:

    face1->afterStateChange.connect([this] (face::FaceState oldState, face::FaceState newState) {
        if (newState == face::FaceState::CLOSED) {
          this->face1_onFail();
        }
      });

and

    face2->afterStateChange.connect([this] (face::FaceState oldState, face::FaceState newState) {
        if (newState == face::FaceState::CLOSED) {
          this->face2_onFail();
        }
      });

With these signals, I'm not getting any segfaults.

Actions #12

Updated by Alex Afanasyev about 8 years ago

Spencer Lee wrote:

Another question - am I able to run specific unit-tests? Instead of run the full test suite within /build.

Yes. Boost.Test provides an extensive mechanism on how can you run specific Suite or unit test. We put some basic info in NFD Developer's Guide, but more extensive and definitive documentation is in Boost.Test itself

Just as an example. To run this specific test, you can

./build/unit-tests-daemon -t Face/TestTcpChannel/FaceClosing -l all

Also am I able to debug unit-test runs with gdb? I have tried gdb on a cpp.3.o file within /build and got a permission denied error.

I'm a little confused. How can you gdb/lldb an object file? You use gdb/lldb on the executable, like this

gdb --args ./build/unit-tests-daemon -t Face/TestTcpChannel/FaceClosing -l all

lldb -- ./build/unit-tests-daemon -t Face/TestTcpChannel/FaceClosing -l all

To allow gdb handle segfaults, you also need to add -s no (--catch_system_errors=no)

Actions #13

Updated by Spencer Lee about 8 years ago

I see, sorry for the confusion, thank you very much.

I guess there were two different issues.
The error was listed as line 254 and the code I posted included that line number, which was for the failing test case, but the code for the SIGABRT was not included, leading to confusion.

Checking the closed faces resolved all issues, thank you.

Actions #14

Updated by Davide Pesavento about 8 years ago

Tests for the following behaviors are also missing:

  • getUri(): check that the channel URI is set correctly
  • isListening(): check that the listening state is toggled correctly (although there are zero users of this functionality throughout NFD, so we could simply remove it)
  • connecting to the same endpoint twice doesn't create two different faces, but the first face is reused for the second connect()
  • connecting to an endpoint that isn't listening (or doesn't exist) times out and invokes the FaceCreationFailedCallback
  • faces on the listening side are created with on-demand persistency; faces on the connecting side are persistent
Actions #15

Updated by Spencer Lee about 8 years ago

faces on the listening side are created with on-demand persistency; faces on the connecting side are persistent

Is this a valid method to test this?

faces on the listening side are created with on-demand persistency:

  • Check if a face on the connecting side closes, then the corresponding listening side face should also close

faces on the connecting side are persistent:

  • Check if a face on the listening side closes, then the corresponding listening side face should not be closed
Actions #16

Updated by Davide Pesavento about 8 years ago

Spencer Lee wrote:

Is this a valid method to test this?
[...]

No, just use Face::getPersistency().

Actions #17

Updated by Davide Pesavento about 8 years ago

Junxiao, what do you mean by "check each face works"?

Actions #18

Updated by Junxiao Shi about 8 years ago

what do you mean by "check each face works"?

For example, it is not null, has correct properties, can send or receive packets.
It's unnecessary to test all of the above.

Actions #19

Updated by Davide Pesavento about 8 years ago

How do we do that without duplicating the transport tests?

Actions #20

Updated by Junxiao Shi about 8 years ago

How do we do that without duplicating the transport tests?

I think just testing non-null is fine.

Actions #21

Updated by Davide Pesavento about 8 years ago

  • % Done changed from 0 to 100
Actions #22

Updated by Junxiao Shi about 8 years ago

  • Status changed from Code review to Closed
Actions #23

Updated by Junxiao Shi about 8 years ago

  • Blocks Task #3514: Merge Channel test cases as template added
Actions

Also available in: Atom PDF