mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 00:36:25 +00:00
98_FhemTestUtils.pm: Fhem Test Utils and test framework (Forum #111061)
git-svn-id: https://svn.fhem.de/fhem/trunk@21926 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
2e16ea71c6
commit
3978ce1663
1
fhem/.proverc
Normal file
1
fhem/.proverc
Normal file
@ -0,0 +1 @@
|
||||
--exec 'perl fhem.pl -t'
|
@ -1,5 +1,6 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||
# Do not insert empty lines here, update check depends on it.
|
||||
- feature: module test framework (fhem.pl -t / FhemTestUtils)
|
||||
- change: 00_MYSENSORS: apply some PBP recommendations,
|
||||
integrate libs from fib/Device/MySensors
|
||||
- feature: 10_MYSENSORS_DEVICE: PBP, see 00_MYSENSORS;
|
||||
|
130
fhem/FHEM/98_FhemTestUtils.pm
Normal file
130
fhem/FHEM/98_FhemTestUtils.pm
Normal file
@ -0,0 +1,130 @@
|
||||
##############################################
|
||||
# $Id$
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my @events;
|
||||
my @logs;
|
||||
sub FhemTestUtils_gotLog($);
|
||||
sub FhemTestUtils_resetLogs();
|
||||
sub FhemTestUtils_gotEvent($);
|
||||
sub FhemTestUtils_resetEvents();
|
||||
|
||||
sub
|
||||
FhemTestUtils_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{DefFn} = "FhemTestUtils_Define";
|
||||
$hash->{NotifyFn} = "FhemTestUtils_Notify";
|
||||
}
|
||||
|
||||
sub
|
||||
FhemTestUtils_Define($$)
|
||||
{
|
||||
my ($hash, $def) = @_;
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
|
||||
return "Wrong syntax: use define <name> dummy" if(int(@a) != 2);
|
||||
$logInform{$a[0]} = sub() { push @logs, $_[1] };
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
sub
|
||||
FhemTestUtils_Notify($$)
|
||||
{
|
||||
my ($ntfy, $dev) = @_;
|
||||
|
||||
my $events = deviceEvents($dev, 0);
|
||||
my $n = $dev->{NAME};
|
||||
#map { print "$n:$_\n" } @{$events};
|
||||
return if(!$events); # Some previous notify deleted the array.
|
||||
push @events, map { "$n:$_" } @{$events};
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
sub
|
||||
FhemTestUtils_gotEvent($)
|
||||
{
|
||||
my ($arg) = @_;
|
||||
return grep /$arg/,@events;
|
||||
}
|
||||
|
||||
sub
|
||||
FhemTestUtils_resetEvents()
|
||||
{
|
||||
@events=();
|
||||
}
|
||||
|
||||
sub
|
||||
FhemTestUtils_gotLog($)
|
||||
{
|
||||
my ($arg) = @_;
|
||||
return grep /$arg/,@logs;
|
||||
}
|
||||
|
||||
sub
|
||||
FhemTestUtils_resetLogs()
|
||||
{
|
||||
@logs=();
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
=item helper
|
||||
=item summary Utility functions for testing FHEM modules
|
||||
=item summary_DE Hilfsfunktionen, um FHEM Module zu testen
|
||||
=begin html
|
||||
|
||||
<a name="FhemTestUtils"></a>
|
||||
<h3>FhemTestUtils</h3>
|
||||
<ul>
|
||||
|
||||
An instance of this module will be automatically defined, if fhem.pl is
|
||||
called with the -t option.
|
||||
The module will collect all events and Log messages, so a test program is
|
||||
able to check, if an event or log message was generated.<br>
|
||||
Available functions:
|
||||
<ul>
|
||||
<li>FhemTestUtils_gotEvent($)<br>
|
||||
Return the events matching the regexp argument (with grep).
|
||||
</li>
|
||||
<li>FhemTestUtils_gotLog($)<br>
|
||||
Return the logs matching the regexp argument (with grep).
|
||||
Note, that loglevel filtering with verbose ist still active.
|
||||
</li>
|
||||
<li>FhemTestUtils_resetEvents()<br>
|
||||
Reset the internal event buffer.
|
||||
</li>
|
||||
<li>FhemTestUtils_resetLogs()<br>
|
||||
Reset the internal log buffer.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<br><br>
|
||||
<a name="FhemTestUtilsdefine"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> FhemTestUtils</code>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<a name="FhemTestUtilsset"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
<a name="FhemTestUtilsget"></a>
|
||||
<b>Get</b> <ul>N/A</ul><br>
|
||||
<a name="FhemTestUtilsattr"></a>
|
||||
<b>Attributes</b> <ul>N/A</ul><br>
|
||||
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
|
||||
|
||||
=cut
|
@ -480,6 +480,7 @@ FHEM/98_DSBMobile KernSani https://forum.fhem.de/index.php/topic,107104
|
||||
FHEM/98_expandJSON.pm dev0 Unterstützende Dienste
|
||||
FHEM/98_feels_like.pm hotbso Wettermodule
|
||||
FHEM/98_fhemdebug.pm rudolfkoenig Sonstiges
|
||||
FHEM/98_FhemTestUtils.pm rudolfkoenig Development
|
||||
FHEM/98_fheminfo.pm betateilchen Sonstiges
|
||||
FHEM/98_freezemon KernSani Unterstützende Dienste
|
||||
FHEM/98_FReplacer.pm StefanStrobel Sonstiges
|
||||
|
48
fhem/fhem.pl
48
fhem/fhem.pl
@ -127,6 +127,7 @@ sub devspec2array($;$$);
|
||||
sub doGlobalDef($);
|
||||
sub escapeLogLine($);
|
||||
sub evalStateFormat($);
|
||||
sub execFhemTestFile();
|
||||
sub fhem($@);
|
||||
sub fhemTimeGm($$$$$$);
|
||||
sub fhemTimeLocal($$$$$$);
|
||||
@ -143,6 +144,8 @@ sub latin1ToUtf8($);
|
||||
sub myrename($$$);
|
||||
sub notifyRegexpChanged($$);
|
||||
sub parseParams($;$$$);
|
||||
sub prepareFhemTestFile();
|
||||
sub execFhemTestFile();
|
||||
sub perlSyntaxCheck($%);
|
||||
sub readingsBeginUpdate($);
|
||||
sub readingsBulkUpdate($$$@);
|
||||
@ -241,6 +244,7 @@ use vars qw($cvsid); # used in 98_version.pm
|
||||
use vars qw($devcount); # Maximum device number, used for storing
|
||||
use vars qw($featurelevel);
|
||||
use vars qw($fhemForked); # 1 in a fhemFork()'ed process, else undef
|
||||
use vars qw($fhemTestFile); # file to include if -t is specified
|
||||
use vars qw($fhem_started); # used for uptime calculation
|
||||
use vars qw($haveInet6); # Using INET6
|
||||
use vars qw($init_done); #
|
||||
@ -478,14 +482,16 @@ my %ra = (
|
||||
# Start the program
|
||||
my $fhemdebug;
|
||||
$fhemdebug = shift @ARGV if($ARGV[0] eq "-d");
|
||||
prepareFhemTestFile();
|
||||
|
||||
if(int(@ARGV) < 1) {
|
||||
print "Usage:\n";
|
||||
print "as server: fhem configfile\n";
|
||||
print "as client: fhem [host:]port cmd cmd cmd...\n";
|
||||
print "as server: perl fhem.pl [-d] {<configfile>|configDb}\n";
|
||||
print "as client: perl fhem.pl [host:]port cmd cmd cmd...\n";
|
||||
print "testing: perl fhem.pl -t <testfile>.t\n";
|
||||
if($^O =~ m/Win/) {
|
||||
print "install as windows service: fhem.pl configfile -i\n";
|
||||
print "uninstall the windows service: fhem.pl -u\n";
|
||||
print "install as windows service: perl fhem.pl configfile -i\n";
|
||||
print "uninstall the windows service: perl fhem.pl -u\n";
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
@ -569,8 +575,9 @@ if(configDBUsed()) {
|
||||
|
||||
|
||||
# As newer Linux versions reset serial parameters after fork, we parse the
|
||||
# config file after the fork. But we need some global attr parameters before, so we
|
||||
# read them here.
|
||||
# config file after the fork. But we need some global attr parameters before,
|
||||
# so we read them here. FHEM_GLOBALATTR is for docker, as it needs to overwrite
|
||||
# fhem.cfg
|
||||
my (undef, $globalAttrFromEnv) = parseParams($ENV{FHEM_GLOBALATTR});
|
||||
setGlobalAttrBeforeFork($attr{global}{configfile});
|
||||
applyGlobalAttrFromEnv();
|
||||
@ -661,6 +668,7 @@ my $osuser = "os:$^O user:".(getlogin || getpwuid($<) || "unknown");
|
||||
Log 0, "Featurelevel: $featurelevel";
|
||||
Log 0, "Server started with ".int(keys %defs).
|
||||
" defined entities ($attr{global}{version} perl:$] $osuser pid:$$)";
|
||||
execFhemTestFile();
|
||||
|
||||
################################################
|
||||
# Main Loop
|
||||
@ -990,7 +998,7 @@ Log3($$$)
|
||||
|
||||
no strict "refs";
|
||||
foreach my $li (keys %logInform) {
|
||||
if($defs{$li}) {
|
||||
if($defs{$li}) { # Function wont be called for WARNING, don't know why
|
||||
&{$logInform{$li}}($li, "$tim $loglevel : $text");
|
||||
} else {
|
||||
delete $logInform{$li};
|
||||
@ -4378,6 +4386,7 @@ setGlobalAttrBeforeFork($)
|
||||
next if($l !~ m/^attr\s+global\s+([^\s]+)\s+(.*)$/);
|
||||
AnalyzeCommand(undef, $l);
|
||||
}
|
||||
CommandAttr(undef, "global modpath .") if(!AttrVal("global","modpath",""));
|
||||
}
|
||||
|
||||
sub
|
||||
@ -6070,4 +6079,29 @@ applyGlobalAttrFromEnv()
|
||||
}
|
||||
}
|
||||
|
||||
# set the test config file: either the corresponding X.cfg, or fhem.cfg
|
||||
sub
|
||||
prepareFhemTestFile()
|
||||
{
|
||||
return if($ARGV[0] ne "-t" || @ARGV < 2);
|
||||
shift @ARGV;
|
||||
|
||||
return if($ARGV[0] !~ m,^(.*?)([^/]+)\.t$,);
|
||||
my ($dir, $fileBase) = ($1, $2);
|
||||
|
||||
$fhemTestFile = $ARGV[0];
|
||||
$ARGV[0] = "${dir}fhem.cfg" if(-r "${dir}fhem.cfg");
|
||||
$ARGV[0] = "$dir$fileBase.cfg" if(-r "$dir$fileBase.cfg");
|
||||
}
|
||||
|
||||
sub
|
||||
execFhemTestFile()
|
||||
{
|
||||
return if(!$fhemTestFile);
|
||||
$attr{global}{autosave} = 0;
|
||||
AnalyzeCommand(undef, "define .ftu FhemTestUtils")
|
||||
if(!grep { $defs{$_}{TYPE} eq "FhemTestUtils" } keys %defs);
|
||||
InternalTimer(1, sub { require $fhemTestFile }, 0 ) if($fhemTestFile);
|
||||
}
|
||||
|
||||
1;
|
||||
|
15
fhem/t/00_MQTT2_SERVER/00_parseMsg.t
Normal file
15
fhem/t/00_MQTT2_SERVER/00_parseMsg.t
Normal file
@ -0,0 +1,15 @@
|
||||
# Simple test. NOTE: exit(0) is necessary
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More;
|
||||
|
||||
{ MQTT2_SERVER_ReadDebug($defs{m2s}, '0(12)(0)(5)helloworld') }
|
||||
is(FhemTestUtils_gotLog("ERROR:.*bogus data"), 0, "Correct MQTT message");
|
||||
|
||||
FhemTestUtils_resetLogs();
|
||||
{MQTT2_SERVER_ReadDebug($defs{m2s}, '(162)(50)(164)(252)(0).7c:2f:80:97:b0:98/GenericAc(130)(26)(212)4(0)(21)BLE2MQTT/OTA/')}
|
||||
is(FhemTestUtils_gotLog("ERROR:.*bogus data"), 1, "Bogus message, as expected");
|
||||
|
||||
done_testing;
|
||||
exit(0);
|
||||
1;
|
2
fhem/t/00_MQTT2_SERVER/01_autocreate.cfg
Normal file
2
fhem/t/00_MQTT2_SERVER/01_autocreate.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
define m2s MQTT2_SERVER 1883
|
||||
define ac autocreate
|
25
fhem/t/00_MQTT2_SERVER/01_autocreate.t
Normal file
25
fhem/t/00_MQTT2_SERVER/01_autocreate.t
Normal file
@ -0,0 +1,25 @@
|
||||
# More complex test, with external program and delayed log/event checking
|
||||
# Note: exit(0) must be called in the delayed code.
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More;
|
||||
|
||||
my $usage = `mosquitto_pub 2>&1`;
|
||||
if(!$usage) { # mosquitto not installed
|
||||
ok(1);
|
||||
done_testing;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fhem('"mosquitto_pub -i test -t hallo -m world"');
|
||||
InternalTimer(time()+1, sub() {
|
||||
is(FhemTestUtils_gotLog(
|
||||
"autocreate: define MQTT2_test MQTT2_DEVICE test m2s"), 1,
|
||||
"autocreate log");
|
||||
is(FhemTestUtils_gotEvent("MQTT2_test:hallo: world"), 1,
|
||||
"autocreate event");
|
||||
done_testing;
|
||||
exit(0);
|
||||
}, 0);
|
||||
|
||||
1;
|
1
fhem/t/00_MQTT2_SERVER/fhem.cfg
Normal file
1
fhem/t/00_MQTT2_SERVER/fhem.cfg
Normal file
@ -0,0 +1 @@
|
||||
define m2s MQTT2_SERVER 1883
|
Loading…
Reference in New Issue
Block a user