[erlang-questions] Common test issues - Possible bug?

Mikkel Jensen <>
Wed Sep 29 11:13:52 CEST 2010


Hi Lukas

First of all, thanks for your response!

I have tried using both run_test and erlang shell to start the tests, both
gives me error i described, although the erlang shell usually seems like its
able to execute more repeated tests than the run_test command.

This is the first test case i'm building with Common Test - I have not made
any other test cases, so i have not experienced this in any other context.
Only when using ct_ssh.

I have been trying to narrow down the test case to find specificly what is
causing the errors, but i have been unable to. However the kinds of tests im
running are not too advanced.
I have made a test-case which imitates the behavior of my "real" test case,
just instead of using cnee for imitating user input, the test subject is a
python script which can be controlled directly from the console. In this
python-test, i have not been able to get the error, not even when repeating
the test 500 times or more.

I hope you can find the time to go through my not-so-minimal test case. As
you can probably see from the code, i am not the most experienced erlang
programmer, and the lack of websites/blogs describing Common Test best
practices and examples makes it very hard to know what i'm doing wrong. The
user guide is great, but can sometimes be a bit hard to understand.

Real test case: http://ideone.com/v6vvu
Python test case: http://ideone.com/GcxR2

%%% CODE FOR "REAL" TEST CASE %%%
%%%%%%%%%%%%%%%%%%%%%%%%

-module(migration_SUITE).
-compile(export_all).
-include_lib("common_test/include/ct.hrl").

% Require the following tags before executing the suite.
% The tags are provided by a config file
suite() ->
    [{require, hidenets},
     {require, demo},
     {require, node1},
     {require, node2},
     {require, testserver}].

init_per_suite(Config) ->
% Start ssh connections
{ok, Hidenets} = ct_ssh:connect(hidenets),
 {ok, Demo} = ct_ssh:connect(demo),
{ok, Node1} = ct_ssh:connect(node1),
{ok, Node2} = ct_ssh:connect(node2),
 {ok, Testserver} = ct_ssh:connect(testserver),

% Append handles to config
 % OBS: This is not actually used, because of the disconnect issue
[{ssh_handles,{Hidenets,Demo,Node1,Node2,Testserver}} | Config].
 end_per_suite(Config) ->
% Disconnect from all handles
Handles = erlang:tuple_to_list(?config(ssh_handles, Config)),
 lists:foreach(fun(Handle) -> ct_ssh:disconnect(Handle) end,
Handles).

init_per_group(_GroupName, Config) ->
% Get ssh handles from config
% {Hidenets, Demo, Node1, Node2, Testserver} = ?config(ssh_handles, Config),

% Start context agent on hidenets (simple console application)
runcmd(hidenets, "./ContextAgentLinux/ContextAgent"),

% Start GUI macro playback
        runcmd(hidenets, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee.xns"),
        runcmd(demo, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee.xns"),
        runcmd(node1, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee.xns"),
        runcmd(node2, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee.xns"),
Config.


end_per_group(_GroupName, Config) ->
% Get ssh handles from config
% {Hidenets, Demo, Node1, Node2, Testserver} = ?config(ssh_handles, Config),

% Stop GUY macro playback
runcmd(hidenets, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee-end.xns"),
        runcmd(demo, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee-end.xns"),
        runcmd(node1, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee-end.xns"),
        runcmd(node2, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee-end.xns"),

% Stop context agent on hidenets
 runcmd(hidenets, "pkill Context"),
ok.

% Initialize the testcase
init_per_testcase(_TestCase, Config) ->
Config.

% Execute the following after a test case is finished
end_per_testcase(_TestCase, Config) ->
 ok.

groups() ->
[{migrateTest, [sequence], [migCase1, migCase2]}].

all() ->
% Return a list of all test cases in the suite.
[migrateTest].

migCase1() ->
[].

migCase2() ->
[].

migCase1(Config) ->
%Hidenets = element(1, ?config(ssh_handles,Config)),

% Arbitrary delay to ensure eclipse + CA is started up and running
 ok = timer:sleep(5000),

% Trigger
runcmd(hidenets, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee-triggerzero.xns"),
 ok = timer:sleep(5000),
ok.

migCase2(Config) ->
 % Hidenets = element(1, ?config(ssh_handles,Config)),
% Arbitrary delay to ensure eclipse + CA is started up and running
                ok = timer:sleep(5000),

% Trigger
runcmd(hidenets, "export DISPLAY=:0.0 && cnee --replay -f
~/ct/xnee/xnee-triggerone.xns"),
 ok = timer:sleep(5000),
ok.

% Workaround for disconnect issue
runcmd(HandleCfg, Cmd) ->
case ct_ssh:connect(HandleCfg) of
{ok, Handle} ->
 case ct_ssh:exec(Handle, Cmd, 3000) of
{ok, Data} -> ok;
{error, _} -> runcmd(HandleCfg, Cmd);
 {_, _} -> ok
end;
{error, _} ->
 runcmd(HandleCfg, Cmd);
_ ->
runcmd(HandleCfg, Cmd)
 end.

%%% CODE FOR PYTHON TEST %%%
%%%%%%%%%%%%%%%%%%%%%%

-module(python_migration_SUITE).
-compile(export_all).
-include_lib("common_test/include/ct.hrl").

suite() ->
% Make SSH and Python settings from config files, sshconfig.cfg
 % and pyconfig.cfg, available in the suite
    [{require, server},
     {require, client1},
     {require, client2},
     {require, serverSettings},
     {require, client1Settings},
     {require, client2Settings}].

init_per_suite(Config) ->
    % Start ssh connection to server, client1 and client2
    {ok, Server}  = ct_ssh:connect(server),
    {ok, Client1} = ct_ssh:connect(client1),
{ok, Client2} = ct_ssh:connect(client2),
 % Append handles to config variable
    [{ssh_handles,{Server, Client1, Client2}} | Config].


end_per_suite(Config) ->
% Get ssh handles from config and make them a traversable list
    Handles = erlang:tuple_to_list(?config(ssh_handles, Config)),

    % Disconnect any active ssh handle
lists:foreach(fun(Handle) -> ct_ssh:disconnect(Handle) end,
  Handles).

init_per_group(_GroupName, Config) ->
    % Get ssh handles from config
{Server, Client1, Client2} = ?config(ssh_handles, Config),

    % Start python server on server and log stdout
ct_ssh:exec(Server, "python " ++ ct:get_config({serverSettings, serverpy})
 ++ " -i " ++ ct:get_config({serverSettings, serverip})
++ " -p " ++ ct:get_config({serverSettings, serverport})
 ++ " >> " ++ ct:get_config({serverSettings, serverlog}),
2000),

    % Start python client on client1 and log stdout
ct_ssh:exec(Client1, "python " ++ ct:get_config({client1Settings,
client1py})
 ++ " -i " ++ ct:get_config({client1Settings, client1ip})
++ " -p " ++ ct:get_config({client1Settings, client1port})
    ++ " > " ++ ct:get_config({client1Settings, client1log}),
2000),

    % Start python client on client2 and log stdout
ct_ssh:exec(Client2, "python " ++ ct:get_config({client2Settings,
client2py})
 ++ " -i " ++ ct:get_config({client2Settings, client2ip})
++ " -p " ++ ct:get_config({client2Settings, client2port})
    ++ " > " ++ ct:get_config({client2Settings, client2log}),
2000),
    Config.

end_per_group(_GroupName, Config) ->
    % Get ssh handles from config
{Server, Client1, Client2} = ?config(ssh_handles, Config),

    % End python server on server
ct_ssh:exec(Server, "python " ++ ct:get_config({serverSettings, commandpy})
++ " -x"),

    % End python client on client1
ct_ssh:exec(Client1, "pkill -f 'client.py'"),

    % End python client on client2
 ct_ssh:exec(Client2, "pkill -f 'client.py'"),
    ok.

init_per_testcase(_TestCase, Config) ->
    Config.

end_per_testcase(_TestCase, _Config) ->
    ok.

groups() ->
    % Define sequential group migrateC1, then migrate2
    [{migrateTest, [sequence], [migrateC1, migrateC2]}].

all() ->
% Run the whole group when the suite is run
    [migrateTest].

migrateC1() ->
 % Do nothing in this testcase info function
    [].

migrateC2() ->
% Do nothing in this testcase info function
    [].

migrateC1(Config) ->
    % Get server handle as it is the only one used in the testcase
Server = element(1, ?config(ssh_handles,Config)),
 % Initial delay 2 seconds to assure that the server has been started
properly
 ok = timer:sleep(2000),

    % Redirect server stream to client1
ct_ssh:exec(Server, "python " ++ ct:get_config({serverSettings, commandpy})
 ++ " -i " ++ ct:get_config({client1Settings, client1ip})
++ " -p " ++ ct:get_config({client1Settings, client1port})),

    % Delay 7 seconds
ok = timer:sleep(7000),
    ok.

migrateC2(Config) ->
    % Get server handle as it is the only one used in the testcase
Server = element(1, ?config(ssh_handles,Config)),

    % Redirect server stream to client2
 ct_ssh:exec(Server, "python " ++ ct:get_config({serverSettings,
commandpy})
++ " -i " ++ ct:get_config({client2Settings, client2ip})
 ++ " -p " ++ ct:get_config({client2Settings, client2port})),

    % Delay 7 seconds
ok = timer:sleep(7000),
    ok.





2010/9/27 Lukas Larsson <>

> Hi Mikkel!
>
> What are you using to run your tests? The run_test command, or are you
> starting them from an erlang shell?
>
> Also have you seen this problem when not using ct_ssh? or is it only
> when you are doing tests with ssh calls in them?
>
> If you could provide me with a minimal test suite which reproduces the
> error you are seeing that would be great!
>
> Regards,
> Lukas, Erlang/OTP, Ericsson AB.
>
> On Fri, Sep 24, 2010 at 6:40 PM, Mikkel Jensen <>
> wrote:
>         Hi list!
>
>        I have been working on setting up a test case using Erlang
>        Common Test. The
>        test is pretty simple, it consists of a sequence of calls to
>        ct_ssh:exec().
>
>        Running the test once works. Running the test a few times (using
>        repeat),
>        usually works. But if i let the test suite repeat a large number
>        of times,
>        it fails after successfully running the test multiple times (In
>        my last
>        attempt it completed 42 runs, no joke, but it seems like the
>        repeated runs
>        can stop at any time).
>
>        The error i'm getting is:
>        It is not possible to install CT while running in interactive
>        mode.
>        To exit this mode, run ct:stop_interactive().
>        To enter the interactive mode again, run ct:start_interactive()
>
>        Does anyone know how i can avoid this, allowing me to run a
>        large number of
>        repeated tests?
>
>        On a sidenote: I have noticed in the logs that ct_ssh will
>        sometimes have
>        lost its connection when trying to call ct_ssh:exec(), and thus
>        will attempt
>        to reconnect. This attempt will, however, always fail instantly.
>        A
>        workaround i have made is to manually connect on each call i
>        make to
>        ct_ssh:exec(). This seems less than ideal, is there a better
>        way?
>
>        Kind regards and thanks in advance,
>        Mikkel
>
>
>
>


More information about the erlang-questions mailing list