!CNF2.9
###
# Schema structure for tables and views.
-# This will be used to create the SQL statments by the DatabaseCentralPlugin.
-# It is simple and early development and mapping will generically be proper for automated select and insert statments.
+# This will be used to create the SQL statements by the DatabaseCentralPlugin.
+# It is simple and early development and mapping will generically be proper for automated select and insert statements.
# it doesn't cover for now, table relationships or constrains.
-# The following schema format in a CNF TREE will most definatelly also be rquired
-# to obtain access to an unknow or arbitary existing database driver. To bring into an CNF DATA property.
-# To do what ever you need with it. Hint, data migration, data display or revalation from one system to another.
+# The following schema format in a CNF TREE will most definitely also be required
+# to obtain access to an unknown or arbitrary existing database driver. To bring into an CNF DATA property.
+# To do what ever you need with it. Hint, data migration, data display or revelation from one system to another.
###
<<DB_SCHEMA <TREE>
[table[
# This is an uber more advanced version of the DataProcessorPlugin. Can be used in combination with it.
#
<<DB_CENTRAL<PLUGIN>
- DB = test_db_central
- DB_CREDENTIALS = admin/admin
- DBI_SQL_SOURCE = DBI:SQLite:
+ DB = tests/test_db_central.db
+ DB_CREDENTIALS = admin/admin
+ DB_SQL_SOURCE = "DBI:SQLite:"
+ suppress_data_log = true
+ is_auto_commit = true
+ is_raise_error = true
+
package : DatabaseCentralPlugin
subroutine : main
property : DB_SCHEMA
+
>>
###
# Original data processor converts scripted to expected CNF Data Type.
# This is an step more advanced version of the actual CNFParser provided DATA property.
# This plugin doesn't interact with any database but creates existing column data conversion.
-# The wild all '*' as property vealue, will go through all CND DATA entries in the repository and process them.
+# The wild all '*' as property value, will go through all CND DATA entries in the repository and process them.
# Otherwise only do a specified directly property.
#
<<DB_DATA_PRC<PLUGIN> ___HAS_PROCESSING_PRIORITY___
#`speter@smiths.fake.com`Peter Smith`01~
>>
-<<ADDRESS_BOOK<DATA>
+<<ADDRESS_BOOK<DATA>__HAS_HEADER__
ID`address`state`city`postcode`country~
#`Office Suit 2, Level 3, James Brown St`KM`Funnygrain`12345`Serbia~
>>
##
-# We shamelessly reuse same plugin package to nest another subrotine.
+# We shamelessly reuse same plugin package to nest another subroutine.
# With perl you use actually the same plugin code. Rewired into a new object, all this enabled for you by PerlCNF.
# Here we meta mark it HAS_PROCESSING_PRIORITY, as it builds data entries for new table being created.
# For the DB_SCHEMA property plugin instruction above, that creates tables and populates them if missing in the database.
<<PROCESS_RSS_FEEDS<PLUGIN> ___HAS_PROCESSING_PRIORITY___
RUN_FEEDS = yes
- CONVERT_TO_CNF_NODES = yes
+ CONVERT_TO_CNF_NODES = no
OUTPUT_TO_CONSOLE = false
OUTPUT_TO_MD = no
BENCHMARK = no
<<CAT<DATA> __SQL_TABLE__
ID`Category`Description~
- 01`Unspecified `For quick uncategorized entries.~
+ 01`Unspecified `For quick not categorized entries.~
03`File System `Operating file system/Application short log.~
06`System Log `Operating system important log.~
09`Event `Event that occurred, meeting, historically important.~
--- /dev/null
+<<paragraphs$$<TREE> __HAS_PROCESSING_PRIORITY__
+<content<
+ class : main
+ pass:true
+ div__\ __IN_SHORTIFE__
+ class: paragraphs
+ div1__\
+ class: paragraph
+ This is a Perl CNF to HTML example document.
+ It is similar to HTML that individual DOM elements.
+ Are tree like placed in the body of the TREE instructed CNF Property.
+ It is easier to the eye, and more readable. You can be the judge. __~
+ __/
+ div2__\
+ class: paragraph
+ Second paragraph here. __~ # A sub node values has to be terminated, otherwise will get skipped.
+ __//
+>content>
+>>
+
+<<paragraphs$$<TREE>
+<content< __IN_SHORTIFE__
+test list type anon with instructions.
+>content>
+>>
+
+<<paragraphs$$<Simple format of anon.>>>
+<<paranormal$$>value>>>
+
+<<<TREE __IN_SHORTIFE__ meta __\
+ @@ __\
+ header __\
+ link __\
+ rel = stylesheet
+ href = wsrc/main.css
+ Its Text
+ ________///
+ @@ __\
+ tag: css_style
+ property: <*<MarkdownPlugin::CSS>*>
+ __/
+__/ >>>
\ No newline at end of file
__/
__/
>>>));
- $test->isDefined("CNF sequential anon format 'listed' is it defined?",$parse_listed->anon('listed'));
+ if(not $test -> isDefined("CNF sequential anon format 'listed' is it defined?",$parse_listed->anon('listed'))){
+ $test -> failed("FATAL! A MUST PASS TEST!"); die
+ }
my $prp_listed = $parse_listed->anon('listed');
$test->evaluate("CNF sequential anon format 'listed' has two itens?",2,scalar(@{$prp_listed->list()}));
$test->subcase("Check CNF sequential anon format 'listed' values.");
###
###
- $test -> case("Test shortife from file test.cnf.",'5');
- $parser = CNFParser->new('test.cnf');
+ $test -> case("Test shortife from file tests/testCNFNodeShortiefs.cnf.",'5');
+ $parser = CNFParser->new('tests/testCNFNodeShortiefs.cnf');
my @para_instructed = $parser->list("paragraphs");
my @paragraphs = $parser->listProcessed("paragraphs");
my %anons = %{$parser->anon()};
###
$test->nextCase();
###
- $test -> case("Test CNF from test.cnf.",'6');
+ $test -> case("Test CNF from tests/testCNFNodeShortiefs.cnf.",'6');
my $node = $parser->anon("paragraphs0");
$test-> isDefined("\$node",$node);
#say $node->toScript();
- $test -> case("Test shortife from file test.cnf with nested nodes.",'7');
+ $test -> case("Test shortife from file tests/testCNFNodeShortiefs.cnf with nested nodes.",'7');
my $meta = $parser -> anon('meta');
$test->failed("meta shortif is not defined!") if not $test->isDefined("meta",$meta);
# A node can have a list of other nodes in an array style.
my $cnf;
try{
-
- my $fstat = CNFParser::_fetchScriptStat($0);
+ my $fstat = CNFParser::_fetchScriptStat($0);
die $test->failed() if not $cnf = CNFParser->new( undef,
{DO_ENABLED=>1,'%LOG'=>{console=>1},TZ=>'Australia/Sydney', CNF_STAT => $fstat}
);
#`2024-06-23 14:30:00``true``Testing 2222.~
#`2024-06-23 14:30:00``true``Testing 3.~
#`2024-06-23 14:30:00``true``Testing 4.~
+#`2025-07-01 19:36:10``true``Testing 5.~
>>
<<DB_CENTRAL<PLUGIN>
- DB = test_db_central_schedule
+ DB = tests/test_db_central_schedule
DB_CREDENTIALS = admin/admin
- DBI_SQL_SOURCE = DBI:SQLite:
+ DB_SQL_SOURCE = DBI:SQLite:
package : DatabaseCentralPlugin
subroutine : main
property : DB_SCHEMA
$cnf->log($message);
}
}
- $cnf->log($out)
+ # $cnf->log($out)
}
}
my $parser = CNFParser -> new(undef,{DO_ENABLED=>1});
$parser->parse(undef,qq(
- <<SYS_SHELL_PERL_SETTINGS <DO> _ON_DEMAND____ _SHELL_____
+ <<SYS_SHELL_PERL_SETTINGS <DO> _ON_DEMAND____ __SHELL_____
`env -i perl -V`
>>
#
- # LIB instruction is very powerfull, it took me a while to figure out.
+ # LIB instruction is very powerful, it took me a while to figure out.
# It loads the package based on file location or in form of a normal module declaration, which must available via the @INC paths.
- # Hence LIB instruction must be put at the begining of a config script file to load before a package is used.
+ # Hence LIB instruction must be put at the beginning of a config script file to load before a package is used.
# This feature enables you also to specify now from a config file, which packages you use from CNF,
# and not to have to declared them in your perl source with use or require.
#
$test->nextCase();
#
- $test->case("Test Lib loading.");
- my $last_lib = $parser->anon('LAST_LIB');
- $test -> isDefined("\$last_lib:$last_lib",$last_lib);
+ $test->case("Test Lib loading.");
my $LoadTestPackage = $parser->anon('LoadTestPackage');
$test -> isDefined("\$LoadTestPackage:$LoadTestPackage",$LoadTestPackage);
$test -> evaluate("\$LoadTestPackage value.",'Hello World!',$LoadTestPackage);
###
$test->subcase("Test if we can create a ghost object?");
+ my $last_lib = $parser->anon('LIB');
+ if($test -> isDefined("\$last_lib",$last_lib)){
my $ghost = $last_lib -> new();
$test -> isDefined("\$ghost", $ghost);
- $test -> evaluate("ghost is comming from?",$ghost->{'Comming from where?'},"out of thin air!");
+ $test -> evaluate("ghost is coming from?",$ghost->{'Coming from where?'},"out of thin air!");
+ }else{
+ $test->failed("Failed to locate \$last_lib")
+ }
#
$test->done();
<<DB_CENTRAL<PLUGIN>
DB = test_db_central
DB_CREDENTIALS = admin/admin
- DBI_SQL_SOURCE = DBI:SQLite:
+ DB_SQL_SOURCE = DBI:SQLite:
package : DatabaseCentralPlugin
subroutine : main
property : DB_SCHEMA
$script = q/ <<one<1>>
<<<two 2>>>
<<Three>3>>
- <<FILE<text.txt>>>/;
+ <<FILE<text.txt>>>/;#<----- Anon called FILE it is not an FILE instruction.
$test->subcase($script);
$cnf->parse(undef,$script);
$test->evaluate("one==1",$cnf->anon('one'),'1');
$test->evaluate("two==2",$cnf->anon('two'),'2');
$test->evaluate("Three==3",$cnf->anon('Three'),'3');
- $test->evaluate("FILE==3",$cnf->anon('FILE'),'text.txt');
+ $test->evaluate("FILE==text.txt",$cnf->anon('FILE'),'text.txt');
#
$test-> nextCase();
use Syntax::Keyword::Try;
use Benchmark;
+use lib::relative 'system/modules';
+
+
use lib "tests";
use lib "system/modules";
+
require TestManager;
require CNFParser;
require CNFSQL;
my $test = TestManager -> new($0);
my $cnf;
+ `rm -f tests/test_db_central.db`;
+
try{
die $test->failed() if not $cnf = CNFParser->new();
#
$test->nextCase();
#
+
+
###
$test->case("Test local SQL Database Setup.");
- `rm -f test_db_central.db`;
+
+
#
my $t0 = Benchmark->new;
die $test->failed() if not $cnf = CNFParser->new('tests/dbSQLSetup.cnf',{DO_ENABLED=>1,DEBUG=>1,'%LOG'=>{console=>1}});
print "The CNF translation for tests/dbSQLSetup.cnf took:",timestr($td),"\n";
my $sql2 = $cnf->SQL();
$test->subcase("Test CNFSQL obtained.");
- $test->evaluate("Is CNFSQl ref?","CNFSQL", ref($sql2));
+ $test->evaluate("Is CNFSQL ref?","CNFSQL", ref($sql2));
#
$test->nextCase();
###
- $test->case("Test RSS FEEDS Plugin.");
-
- my $plugin = $cnf->property('PROCESS_RSS_FEEDS');
- $test->failed() if not $plugin;
- if(CNFParser::_isTrue($plugin->{CONVERT_TO_CNF_NODES})){
- $test->subcase('Test data to CNF nodes tree conversion for RSS feeds.');
- my $perl_weekly = $cnf->getTree('Perl Weekly');
- $test->isDefined("Has tree 'Perl Weekly'?",$perl_weekly);
- my $url_node = $$perl_weekly->search("/Feed/URL");
- $test->isDefined("Has an URL defined node?",$url_node);
- $test->evaluate("CNF_FEED/Feed/URL is ok?","https://perlweekly.com/perlweekly.rss",$url_node);
- }else{
- $test->subcase('Skipped subcase tests, CONVERT_TO_CNF_NODES == false')
- }
- #
- $test->nextCase();
- #
+ # $test->case("Test RSS FEEDS Plugin.");
+
+ # my $plugin = $cnf->property('PROCESS_RSS_FEEDS');
+ # $test->failed() if not $plugin;
+ # if(CNFParser::_isTrue($plugin->{CONVERT_TO_CNF_NODES})){
+ # $test->subcase('Test data to CNF nodes tree conversion for RSS feeds.');
+ # my $perl_weekly = $cnf->getTree('Perl Weekly');
+ # $test->isDefined("Has tree 'Perl Weekly'?",$perl_weekly);
+ # my $url_node = $$perl_weekly->search("/Feed/URL");
+ # $test->isDefined("Has an URL defined node?",$url_node);
+ # $test->evaluate("CNF_FEED/Feed/URL is ok?","https://perlweekly.com/perlweekly.rss",$url_node);
+ # }else{
+ # $test->subcase('Skipped subcase tests, CONVERT_TO_CNF_NODES == false')
+ # }
+ # #
+ # $test->nextCase();
+ # #
+
$test->case("Test CNFSQL script to data synch and map.");
$cnf = CNFParser->new(undef,{DO_ENABLED=>1,DEBUG=>1,'%LOG'=>{console=>1}});
+ ###
+ # Here the table is mapped to CNF data property that is auto-numbered.
+ # But the table itself is not reflected to this so inserts and updates are different.
+ # Then directly making an SQL table from an CNF Data header.
$cnf->parse(undef,q(
<<TBL_A<TABLE> _MAP_TO_ TBL_A_DATA
"name" varchar(28) NOT NULL,
"ID" INTEGER NOT NULL,
- PRIMARY KEY ("ID" AUTOINCREMENT)
+ "Gender" varchar(10),
+ PRIMARY KEY ("ID")
>>
- <<TBL_A_DATA<DATA> __HAS_HEADER__ ____AUTONUMBER_
+ <<TBL_A_DATA<DATA> __HAS_HEADER__ __AUTONUMBER__
ID`NAME`Gender~
#`Mickey Mouse`rat~
5`Donald Duck`food~
#`Captain Cook`crook~
>>
));
+ #
+ $test->nextCase();
+ #
+
my $central = $cnf->property('DB_CENTRAL');
- my $db = CNFSQL::_connectDB('test','test',$central->{DBI_SQL_SOURCE},$central->{DB}.'.db');
+ my $db = CNFSQL::_connectDB('test','test',$central->{DB_SQL_SOURCE},$central->{DB});
$sql = $cnf->SQL();
- $sql -> {data } = $sql->{parser}->data();
- #$sql -> initDatabase($db,0,{'TBL_A' => ['TBL_A_DATA','name','ID']});
+ $sql -> {data } = $sql->{parser}->data();
$sql -> initDatabase($db,0);
$test->case("Test db view to existing database.");
$cnf = CNFParser->new(undef,{DO_ENABLED=>1,DEBUG=>1,'%LOG'=>{console=>1}});
$cnf->parse(undef,qq(
<<DB_CENTRAL<PLUGIN>
- DB = test_db_central
+ DB = tests/test_db_central.db
DB_CREDENTIALS = admin/admin
- DBI_SQL_SOURCE = DBI:SQLite:
+ DB_SQL_SOURCE = DBI:SQLite:
package : DatabaseCentralPlugin
subroutine : executeStatements
property : VIEW_TBL_A
my $view = $cnf->data()->{VIEW_TBL_A};
my @data = @{$$view->{data}};
$test->evaluate("Mapped view has selected three records?",3,scalar @data);
- $test->evaluate("Mapped view has record 2 at index 1?",'Donald Duck', $data[1][1]); #<-view is ID-0, Name is 1.
+ $test->evaluate("Mapped view has record 5 -Donald Duck at index 2?",'Donald Duck', $data[2][1]); #<-view is ID-0, Name is 1.
#
#
$test->done();
my $test = TestManager->new($0);
my $cnf;
+my $info = `apt-cache show bashtop`;
+$info =~ m/^Description[-\w]*:\s*(.*?)\./ms;
+
+my $desc = $1;
+
+$info =~ m/(^Version\s*:.*?\n)/ms;
+my $version = $1;
+
+print $desc;
+
try {
###
# Test instance creation.
$test->evaluate('a=1', $item{'ins'});
$test->evaluate('_some_value_', $item{'val'});
#
-
-+ my $hasFailures = $test->nextCase(); die $hasFailures if $hasFailures;
+ my $hasFailures = $test->nextCase(); die $hasFailures if $hasFailures;
#
###
$test->case("Check DATA instruction dynamically");
$cnf->parse(undef,qq(<<my\$\$<DATA>01`This comes from Cabramatta~\n>>));
$test->subcase("Contain 'my\$\$' as 'my' data property?");
- my $ref = $cnf->data()->{'my'};
+ my $ref = $cnf->data()->{'my'}; $test->isDefined("\$ref",$ref);
my @data = @{$$ref->{data}};
my @mydt = @{$data[0]};
$test->evaluate(\@mydt);