Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manually create TAP output

Tags:

perl

tap

There is a great Perl module Test::More that everybody uses for unit testing. Here is the very simple script t/sample_1.t:

use Test::More tests => 1;

fail('This test fails');

I wanted to write script that does the same thing, but without Test::More.

I've read several the docs about TAP (test anything protocol) to find out how to write the script. I've read:

  • Wikipedia article about TAP
  • TAP specification

Unfortunately the documentation wasn't enough. I had to examine the output of script that uses Test::More to find out that I need to output diagnostics to STDERR (there was nothing about this in the docs).

So, I have written a script that does completely the same things as the script with Test::More script. Here is the listing of t/sample_2.t:

$| = 1;

print "1..1\n";
print "not ok 1 - This test fails\n";
print STDERR "#   Failed test 'This test fails'\n";
print STDERR "#   at t/sample_1.t line 3.\n";
print STDERR "# Looks like you failed 1 test of 1.\n";

exit 1;

But when using prove these 2 scripts output different things. The line "# Failed test 'This test fails'" in prove is displayed on different lines for different tests. Here is the screenshot:

Perl prove output for 2 sample unit tests

I've written a test scripts that uses Capture::Tiny to check that STDERR, STDOUT and exit code for both scripts a identical. And the script shows that both scripts output the same things.

I've stored all the test files and a test script at GitHub repo.

My question. How should I write Perl unit test without Test::More to have the same output as with Test::More.

PS If you are interested why I need this. I need this to solve the issue of my Perl module Test::Whitespaces.

like image 504
bessarabov Avatar asked Jun 29 '13 18:06

bessarabov


People also ask

How do I find my tap interface?

The tap interface information can be used to debug connectivity issues using tools such as tcpdump. Navigate to http:// <openstak-ip> /horizon/admin/instances / and note the following: IP address of the VM/Interface for which the associated tap interface is to be found.

What is the difference between TUN and tap?

TUN, namely network TUNnel, simulates a network layer device and operates in layer 3 carrying IP packets. TAP, namely network TAP, simulates a link layer device and operates in layer 2 carrying Ethernet frames. TUN is used with routing. TAP can be used to create a user space network bridge.

What is Linux Tunctl command?

tunctl allows the host sysadmin to preconfigure a TUN/TAP network interface for use by a particular user. That user may open and use the network/write side of the interface, but may not change any aspects of the host side of the interface.

What is a tap0 interface?

Tap interfaces are special software entities which tell the Linux bridge to forward Ethernet frames as it is. In other words, the virtual machines connected to tap interfaces will be able to receive raw Ethernet frames.


2 Answers

While I've got absolutely no frickin idea what's going on, I can get the outputs to match (visually at least) by including the following before any other output to STDERR:

print STDERR "\r";

This makes them match visually when run through prove or plain old perl. However, this is NOT what Test::More is doing.

The TAP you're outputting is per spec; if prove wants to treat it differently from the TAP Test::More is outputting, I'd argue that's a bug (or at least an oddity) in prove. Personally when I've written Test modules, I've always used Test::Builder or wrapped Test::More to output the TAP. Each of these is a core module. This seems to be what the majority of Test modules tend to do.

like image 174
tobyink Avatar answered Sep 24 '22 11:09

tobyink


At last I have found out what is going on.

hobbs has advised me to use Test::Builder. I created test script with Test::Builder that worked exaclty as the script with Test::More (here it is).

Then I started examinig source code of Test::Builder to find out why the source of such behaviour. Here is the part of lib/TB2/Formatter/TAP/Base.pm file:

# Emit old style comment failure diagnostics
sub _comment_diagnostics {
    my($self, $result) = @_;

    ...

    # Start on a new line if we're being output by Test::Harness.
    # Makes it easier to read
    $self->$out_method("\n") if ($out_method eq 'err') and $ENV{HARNESS_ACTIVE};
    $self->$diag_method($msg);

    return;
}

So, this is the answer. prove sets up special environment variable HARNESS_ACTIVE and Test::More and friends puts additional line break symbol "\n" before any diagnostics that are printed to STDERR.

At last I've created test script that outputs exactly the same as the script written with Test::More. Source code of the script.

I really don't like this solution. It took me and outher peopler much time to find out what is going on. I'm sure that the task of pretty output should be solved in TAP parsers, and not in TAP producers.

=(

like image 29
bessarabov Avatar answered Sep 23 '22 11:09

bessarabov