diff --git a/CMake/CMakeLists_itest.txt b/CMake/CMakeLists_itest.txt
index ae311993d4c783907d41fd546e72a280abbfef63..bf51ad2adcbd3a82d90108e051ae46bd18aaaa03 100644
--- a/CMake/CMakeLists_itest.txt
+++ b/CMake/CMakeLists_itest.txt
@@ -1,4 +1,3 @@
-find_package(Catch2 REQUIRED)
 include(Catch)
 
 project({project_name})
@@ -23,7 +22,7 @@ set_target_properties(${{PROJECT_NAME_TEST}} PROPERTIES
         CXX_STANDARD_REQUIRED ON
         )
 
-target_link_libraries(${{PROJECT_NAME_TEST}} {target_test_libs} Catch2::Catch2)
+target_link_libraries(${{PROJECT_NAME_TEST}} {target_test_libs} catch2)
 
 # Include dependencies directories
 target_include_directories(${{PROJECT_NAME_TEST}}
diff --git a/alib2integrationtest/project.conf b/alib2integrationtest/project.conf
new file mode 100644
index 0000000000000000000000000000000000000000..bea004a24bb35d88d8812d91f9c4ced89381da4c
--- /dev/null
+++ b/alib2integrationtest/project.conf
@@ -0,0 +1,9 @@
+[General]
+category: testing
+
+[TestDependencies]
+project: alib2cli alib2str alib2std alib2common alib2algo alib2data alib2elgo alib2aux
+system: stdc++fs
+
+[CMake:Deps:stdc++fs]
+link: stdc++fs
diff --git a/alib2integrationtest/test-src/main.cpp b/alib2integrationtest/test-src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f1f402b8b19a1a5195ef48e463d7a5703654d5b1
--- /dev/null
+++ b/alib2integrationtest/test-src/main.cpp
@@ -0,0 +1,3 @@
+#define CATCH_CONFIG_MAIN
+#define CATCH_CONFIG_NO_POSIX_SIGNALS
+#include <catch2/catch.hpp>
diff --git a/alib2integrationtest/test-src/testing/TestFiles.cpp b/alib2integrationtest/test-src/testing/TestFiles.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9a87addf9a00c791e2aa2401d4a3658a61682d04
--- /dev/null
+++ b/alib2integrationtest/test-src/testing/TestFiles.cpp
@@ -0,0 +1,44 @@
+#include "TestFiles.hpp"
+#include "testfiles_basedir.hpp"
+
+#include <exception/CommonException.h>
+#include <experimental/filesystem>
+
+std::vector < std::string > TestFiles::Get ( const std::string& regex ) {
+	return Get ( std::regex ( regex ) );
+}
+
+std::vector < std::string > TestFiles::Get ( const std::regex& regex ) {
+	std::vector < std::string > res;
+
+	try {
+		for ( const std::experimental::filesystem::directory_entry & entry: std::experimental::filesystem::recursive_directory_iterator ( TEST_FILES_BASEDIR ) ) {
+			std::smatch match;
+			const std::string path = entry.path ( );
+
+			if ( std::regex_search ( path, match, regex ) ) {
+				res.push_back ( path );
+			}
+		}
+	} catch ( const std::experimental::filesystem::filesystem_error & e ) {
+		throw exception::CommonException ( e.what ( ) );
+	}
+
+	return res;
+}
+
+std::string TestFiles::GetOne ( const std::string& regex ) {
+	return GetOne ( std::regex ( regex ) );
+}
+
+std::string TestFiles::GetOne ( const std::regex& regex ) {
+	std::vector < std::string > res = Get ( regex );
+
+	if ( res.size ( ) > 1 )
+		throw exception::CommonException ( std::string ( "Multiple files found for TestFiles::GetOne. TestFilesDir is " ) + TEST_FILES_BASEDIR );
+
+	if ( res.size ( ) == 0 )
+		throw exception::CommonException ( std::string ( "No files found for TestFiles::GetOne. TestFilesDir is " ) + TEST_FILES_BASEDIR );
+
+	return res.at ( 0 );
+}
diff --git a/alib2integrationtest/test-src/testing/TestFiles.hpp b/alib2integrationtest/test-src/testing/TestFiles.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fdf7b70c4862f531f074d4d95fc77596ab1dcd0d
--- /dev/null
+++ b/alib2integrationtest/test-src/testing/TestFiles.hpp
@@ -0,0 +1,16 @@
+#ifndef _TEST_FILES_
+#define _TEST_FILES_
+
+#include <vector>
+#include <string>
+#include <regex>
+
+class TestFiles {
+	public:
+		static std::vector < std::string > Get ( const std::regex& regex );
+		static std::vector < std::string > Get ( const std::string& regex );
+		static std::string GetOne ( const std::string& regex );
+		static std::string GetOne ( const std::regex& regex );
+};
+
+#endif /* _TEST_FILES_ */
diff --git a/alib2integrationtest/test-src/testing/TimeoutAqlTest.cpp b/alib2integrationtest/test-src/testing/TimeoutAqlTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5db375636118be4a7897272ff4ee4105759eccf0
--- /dev/null
+++ b/alib2integrationtest/test-src/testing/TimeoutAqlTest.cpp
@@ -0,0 +1,136 @@
+#include "TimeoutAqlTest.hpp"
+#include <cstring>
+#include <exception/CommonException.h>
+#include <parser/Parser.h>
+
+#include <unistd.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#define PIPE_RD 0
+#define PIPE_WR 1
+
+/* Communication between signal handler and the rest of the program */
+int g_Wakeup [ 2 ];  // pipe for wakeup
+int g_RecvSignal; // signalled flag
+
+int waitSignalTimeout ( int timeout ) {
+	struct timeval tv;
+	fd_set rd;
+
+	tv.tv_sec = 0;
+	tv.tv_usec = timeout;
+	FD_ZERO ( &rd );
+	FD_SET ( g_Wakeup [ PIPE_RD ], &rd );
+
+	select ( g_Wakeup [ PIPE_RD ] + 1, &rd, NULL, NULL, &tv );
+	return g_RecvSignal;
+}
+
+void newSigChild ( int ) {
+	char dummy = 0;
+	g_RecvSignal = 1;
+
+	// write into the pipe so select can read something, this effectively means that SIGCHILD was raised
+	if ( write ( g_Wakeup [ PIPE_WR ], &dummy, 1 ) != 1 )
+		throw exception::CommonException ( "TimeoutAqlTest: write() failure (wakeup signalling)" );
+}
+
+int aqlTest ( int fd, const ext::vector < std::string > & queries ) {
+	cli::Environment environment;
+
+	try {
+		for ( const std::string & q : queries ) {
+			cli::Parser parser = cli::Parser ( cli::Lexer ( q ) );
+			parser.parse ( ) -> run ( environment );
+		}
+	} catch ( const exception::CommonException & e ) {
+		const char * what = e.what ( );
+		ssize_t what_len = ( ssize_t ) strlen ( what );
+		if ( write ( fd, what, what_len ) != what_len )
+			throw exception::CommonException ( "TimeoutAqlTest: write() failure (child to parent communication)" );
+		return -1;
+	}
+
+	return environment.getResult ( ); /* 0 = OK */
+}
+
+std::string readChildOutput ( int fd ) {
+	static const size_t BUFSIZE = 64;
+
+	std::string res;
+	int rd;
+	char buf [ BUFSIZE ];
+
+	while ( ( rd = read ( fd, &buf, BUFSIZE - 1 ) ) > 0 ) {
+		res.append ( buf, rd );
+	}
+
+	return res;
+}
+
+void _TimeoutAqlTest ( const std::chrono::microseconds & timeout, const ext::vector < std::string > & queries ) {
+	/* Register SIGCHLD handler */
+	struct sigaction act;
+	memset ( &act, 0, sizeof ( act ) );
+	act . sa_handler = newSigChild;
+	sigaction ( SIGCHLD, &act, NULL );
+
+	/* parent-child communication ( for exceptions ) */
+	int pipefd [ 2 ];
+	if ( pipe ( pipefd ) != 0 )
+		throw exception::CommonException ( "TimeoutAqlTest: Failed to initialize pipe (child to parent communication)" );
+
+	/* SIGCHLD was not yet raised, initialize communication pipe */
+	g_RecvSignal = 0;
+	if ( pipe ( g_Wakeup ) )
+		throw exception::CommonException ( "TimeoutAqlTest: Failed to initialize pipe (wakeup signalling)" );
+
+	/* do the forking */
+	pid_t x = fork ();
+	if ( x < 0 ) {
+		FAIL ( "Fork error" );
+	} else if ( x == 0 ) {
+		/* child, run the test here */
+		close ( g_Wakeup [ PIPE_RD ] );
+		close ( g_Wakeup [ PIPE_WR ] );
+		close ( pipefd [ PIPE_RD ] );
+
+		/* just in case ... */
+		close ( 1 );
+		close ( 2 );
+
+		exit ( aqlTest ( pipefd [ PIPE_WR ], queries ) );
+	}
+
+	close ( pipefd [ PIPE_WR ] );
+
+	/* lets wait the specified time of microseconds, maybe the child will terminate on its own */
+	if ( ! waitSignalTimeout ( timeout.count ( ) ) ) {
+		/* ... and in case it did not ... */
+		kill ( x, SIGTERM );
+		while ( ! waitSignalTimeout ( 250000 ) ) /* 1/4 second */
+			kill ( x, SIGKILL );
+	}
+
+	/* child termination confirmed */
+	int status;
+	waitpid ( x, &status, 0 );
+	close ( g_Wakeup [ PIPE_RD ] );
+	close ( g_Wakeup [ PIPE_WR ] );
+
+	std::string childOutput = readChildOutput ( pipefd [ PIPE_RD ] );
+
+	close ( pipefd [ PIPE_RD ] );
+	close ( pipefd [ PIPE_WR ] );
+
+	if ( WIFEXITED ( status ) ) {
+		// std::cerr << "Child process finished, code " << WEXITSTATUS ( status ) << std::endl;
+		INFO ( "AqlTest failure. Trying to execute: " << queries );
+		INFO ( "Child output was: >" << childOutput << "<" );
+		REQUIRE ( WEXITSTATUS ( status ) == 0 );
+	} else if ( WIFSIGNALED ( status ) ) {
+		// std::cerr << "Child process signaled, signal ", WTERMSIG ( status ) << std::endl;
+		WARN ( "Timeout (" << timeout.count ( ) << " us) reached in test (" << queries << ")" );
+	}
+}
diff --git a/alib2integrationtest/test-src/testing/TimeoutAqlTest.hpp b/alib2integrationtest/test-src/testing/TimeoutAqlTest.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ec27ec3570fa43973ae504655121d658ce3e4d1d
--- /dev/null
+++ b/alib2integrationtest/test-src/testing/TimeoutAqlTest.hpp
@@ -0,0 +1,17 @@
+#ifndef _TIMEOUT_AQL_TEST_HPP__
+#define _TIMEOUT_AQL_TEST_HPP__
+
+#include <catch2/catch.hpp>
+#include <chrono>
+#include <alib/vector>
+
+using namespace std::chrono_literals;
+
+void _TimeoutAqlTest ( const std::chrono::microseconds & timeout, const ext::vector < std::string > & queries );
+
+template < class D >
+void TimeoutAqlTest ( const D & timeout, const ext::vector < std::string > & queries ) {
+	_TimeoutAqlTest ( std::chrono::duration_cast < std::chrono::microseconds > ( timeout ), queries );
+}
+
+#endif /* _TIMEOUT_AQL_TEST_HPP__ */
diff --git a/alib2integrationtest/test-src/tests/approximateMatching.cpp b/alib2integrationtest/test-src/tests/approximateMatching.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..44de13c0ec1db09e0fa97070211096b77f4c737b
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/approximateMatching.cpp
@@ -0,0 +1,108 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+const size_t PATTERN_SIZE = 7;
+const size_t SUBJECT_SIZE = 100;
+const size_t ALPHABET_SIZE = 4;
+const size_t RANDOM_ITERATIONS = 20;
+
+static std::string qSetError ( const size_t error,  const std::string & var ) {
+	return "execute " + std::to_string ( error ) + " > $" + var;
+}
+
+static std::string qPrepareString ( const std::string &file, const std::string & var ) {
+	return "execute < " + file + " > $" + var;
+}
+
+static std::string qExtendAlphabet ( const std::string & s1, const std::string & s2 ) {
+	return "execute string::GeneralAlphabet::add $" + s1 + " <( string::GeneralAlphabet::get $" + s2 + " ) > $" + s1;
+}
+
+static std::string qGenString ( const size_t & len, const size_t &alph_len, const std::string & var ) {
+	std::ostringstream oss;
+	oss << "execute string::generate::RandomStringFactory ";
+	oss << "( size_t )" << rand ( ) % len + 1;
+	oss << "( size_t )" << rand ( ) % alph_len + 1;
+	oss << "true | ";
+	oss << "string::simplify::NormalizeAlphabet - > $" + var;
+	return oss.str ( );
+}
+
+static std::string qCreateMatchingAutomaton ( const std::string & algo, const std::string & pattern, const std::string & error, const std::string & var ) {
+	std::ostringstream oss;
+	oss << "execute ";
+	oss << algo << " $" + pattern + " $" + error + " | ";
+	oss << "automaton::simplify::efficient::EpsilonRemoverIncoming - | ";
+	oss << "automaton::determinize::Determinize - ";
+	oss << "> $" << var;
+	return oss.str ( );
+}
+
+static std::string qRunAutomaton ( const std::string & automaton, const std::string & subject, const std::string & res ) {
+	return "execute automaton::run::Occurrences $" + automaton + " $" + subject + " > $" + res;
+}
+
+static std::string qRunDynamicAlgorithm ( const std::string & algo, const std::string &pattern, const std::string & subject, const std::string & error, const std::string & res ) {
+	std::ostringstream oss;
+	oss << "execute " << algo << " ";
+	oss << "$" << subject << " ";
+	oss << "$" << pattern << " ";
+	oss << "$" << error << " ";
+	oss << "> $" << res;
+	return oss.str ( );
+}
+
+TEST_CASE ( "Approximate Matching", "[integration]" ) {
+	auto definition = GENERATE ( as < std::pair < std::string, std::string > > ( ),
+			std::make_pair ( "stringology::matching::HammingMatchingAutomaton", "stringology::simulations::HammingDynamicProgramming" ),
+			std::make_pair ( "stringology::matching::HammingMatchingAutomaton", "stringology::simulations::HammingBitParalelism" ),
+			std::make_pair ( "stringology::matching::LevenshteinMatchingAutomaton", "stringology::simulations::LevenshteinDynamicProgramming" ),
+			std::make_pair ( "stringology::matching::LevenshteinMatchingAutomaton", "stringology::simulations::LevenshteinBitParalelism" ),
+			std::make_pair ( "stringology::matching::GeneralizedLevenshteinMatchingAutomaton", "stringology::simulations::GeneralizedLevenshteinDynamicProgramming" ),
+			std::make_pair ( "stringology::matching::GeneralizedLevenshteinMatchingAutomaton", "stringology::simulations::GeneralizedLevenshteinBitParalelism" ) );
+	auto error = GENERATE ( 0, 1, 2, 3, 4, 5, 6 );
+
+	SECTION ( "Test files" ) {
+		for ( const std::string & patternFile : TestFiles::Get ( "/string/astringology.test.*.pattern.xml$" ) ) {
+			static const std::string p ( ".pattern." ), s ( ".subject." );
+			std::string subjectFile = patternFile;
+
+			size_t pos = subjectFile.find ( p );
+			subjectFile.replace ( pos, s.size ( ), s );
+
+			ext::vector < std::string > qs = {
+				qSetError ( error, "error" ),
+				qPrepareString ( patternFile, "pattern" ),
+				qPrepareString ( subjectFile, "subject" ),
+				qExtendAlphabet ( "pattern", "subject" ),
+				qCreateMatchingAutomaton ( std::get < 0 > ( definition ), "pattern", "error", "automaton" ),
+				qRunAutomaton ( "automaton", "subject", "res1" ),
+				qRunDynamicAlgorithm ( std::get < 1 > ( definition ), "pattern", "subject", "error", "res2" ),
+				"quit compare::SetCompare $res1 $res2",
+			};
+
+			TimeoutAqlTest ( 2s, qs );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+
+			ext::vector < std::string > qs = {
+				qSetError ( error, "error" ),
+				qGenString ( PATTERN_SIZE, ALPHABET_SIZE, "pattern" ),
+				qGenString ( SUBJECT_SIZE, ALPHABET_SIZE, "subject" ),
+				qExtendAlphabet ( "pattern", "subject" ),
+				qCreateMatchingAutomaton ( std::get < 0 > ( definition ), "pattern", "error", "automaton" ),
+				qRunAutomaton ( "automaton", "subject", "res1" ),
+				qRunDynamicAlgorithm ( std::get < 1 > ( definition ), "pattern", "subject", "error", "res2" ),
+				"quit compare::SetCompare $res1 $res2",
+			};
+
+			TimeoutAqlTest ( 5s, qs );
+		}
+	}
+}
diff --git a/alib2integrationtest/test-src/tests/arbologyTest.cpp b/alib2integrationtest/test-src/tests/arbologyTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..30fb5500fa06c5b017176cace09f4de59fb1ac1b
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/arbologyTest.cpp
@@ -0,0 +1,283 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+enum class EGenerateType {
+	PATTERN,
+	SUBTREE,
+	NONLINEAR_PATTERN,
+	NONLINEAR_PATTERN_SINGLE_VAR,
+
+	SUBJECT,
+};
+
+std::ostream& operator << ( std::ostream& os, const EGenerateType& type ) {
+	switch ( type ) {
+		case EGenerateType::PATTERN:
+			return ( os << "PATTERN" );
+		case EGenerateType::SUBTREE:
+			return ( os << "SUBTREE" );
+		case EGenerateType::NONLINEAR_PATTERN:
+			return ( os << "NONLINEAR_PATTERN" );
+		case EGenerateType::NONLINEAR_PATTERN_SINGLE_VAR:
+			return ( os << "NONLINEAR_PATTERN_SINGLE_VAR");
+		case EGenerateType::SUBJECT:
+			return ( os << "SUBJECT" );
+		default:
+			return ( os << "Unhandled EGenerateType" );
+	}
+}
+
+const size_t PATTERN_SIZE = 4;
+const size_t ALPHABET_SIZE = 3;
+const size_t SUBJECT_HEIGHT = 25;
+const size_t PATTERN_HEIGHT = 2;
+const size_t RANDOM_ITERATIONS = 20;
+
+static std::string qGen ( const EGenerateType & type, int height, int nodes, int alphSize, const std::string & output ) {
+	std::ostringstream oss;
+	oss << "execute ";
+
+	if ( type == EGenerateType::SUBJECT ) {
+		oss << "tree::generate::RandomRankedTreeFactory";
+	} else if ( type == EGenerateType::PATTERN ) {
+		oss << "tree::generate::RandomRankedPatternFactory";
+	} else if ( type == EGenerateType::SUBTREE ) {
+		oss << "tree::generate::RandomRankedTreeFactory";
+	} else if ( type == EGenerateType::NONLINEAR_PATTERN ) {
+		oss << "tree::generate::RandomRankedNonlinearPatternFactory";
+	} else if ( type == EGenerateType::NONLINEAR_PATTERN_SINGLE_VAR ) {
+		oss << "tree::generate::RandomRankedNonlinearPatternFactory";
+	}
+
+	oss << " (int)" << height;
+	oss << " (int)" << nodes;
+	oss << " (int)" << rand ( ) % alphSize + 1;
+	oss << " (bool) false"; /* alphRand */
+	if ( type == EGenerateType::NONLINEAR_PATTERN || type == EGenerateType::NONLINEAR_PATTERN_SINGLE_VAR )
+		oss << " (bool)" << ( type == EGenerateType::NONLINEAR_PATTERN_SINGLE_VAR );
+	oss << " (int)" << 5; /* rank */
+	oss << "> $" << output;
+	return oss.str ( );
+}
+
+static std::string search_replace ( std::string text, const std::string & search, const std::string & replace ) {
+	size_t pos = text.find ( search );
+	text.replace ( pos, search.size ( ), replace );
+	return text;
+}
+
+static std::vector < std::pair < std::string, std::string > > pair_pattern_subject ( const std::vector < std::string > & files, const std::string & pattern, const std::string & subj ) {
+	std::vector < std::pair < std::string, std::string > > res;
+	for ( const auto & file : files )
+		res.push_back ( std::make_pair ( file, search_replace ( file, pattern, subj ) ) );
+
+	return res;
+}
+
+
+void runTest ( const std::string & exactPipeline, const std::string &pipeline, const std::string &pFile, const std::string &sFile ) {
+	ext::vector < std::string > qs = {
+		"execute < " + pFile + " > $pattern",
+		"execute < " + sFile + " > $subject",
+		"execute " + exactPipeline + " > $res1",
+		"execute " + pipeline + " > $res2",
+		"quit compare::PrimitiveCompare <(stats::SizeStat $res1) <(stats::SizeStat $res2)",
+	};
+
+	TimeoutAqlTest ( 10s, qs );
+}
+
+void runRandom ( const std::string & exactPipeline, const std::string &pipeline, const EGenerateType &patternType, const size_t& subjSize ) {
+	ext::vector < std::string > qs = {
+		qGen ( patternType, PATTERN_HEIGHT, PATTERN_SIZE, ALPHABET_SIZE, "pattern" ),
+		qGen ( EGenerateType::SUBJECT, SUBJECT_HEIGHT, subjSize, ALPHABET_SIZE, "subject" ),
+		"execute " + exactPipeline + " > $res1",
+		"execute " + pipeline + " > $res2",
+		"quit compare::PrimitiveCompare <(stats::SizeStat $res1) <(stats::SizeStat $res2)",
+	};
+
+	TimeoutAqlTest ( 10s, qs );
+}
+
+TEST_CASE ( "Arbology tests | nonlinear pattern", "[integration]" ) {
+	auto definition = GENERATE ( as < std::tuple < std::string, std::string, size_t > > ( ),
+		std::make_tuple ( "Exact Nonlinear Pattern Matching Using Compressed Bit Vectors (PrefixRankedBar)",
+				"arbology::indexing::NonlinearCompressedBitParallelIndexConstruction (PrefixRankedBarTree)$subject | arbology::query::NonlinearCompressedBitParallelismPatterns - (PrefixRankedBarNonlinearPattern)$pattern", 1000 ),
+		std::make_tuple ( "Exact Nonlinear Pattern Matching Using Full And Linear Index (PrefixRanked)",
+				"arbology::indexing::NonlinearFullAndLinearIndexConstruction (PrefixRankedTree)$subject | arbology::query::NonlinearFullAndLinearIndexPatterns - (PrefixRankedNonlinearPattern) $pattern", 1000 ),
+		std::make_tuple ( "Exact Nonlinear Pattern Matching Using Full And Linear Index (PrefixRankedBar)",
+				"arbology::indexing::NonlinearFullAndLinearIndexConstruction (PrefixRankedBarTree)$subject | arbology::query::NonlinearFullAndLinearIndexPatterns - (PrefixRankedBarNonlinearPattern) $pattern", 1000 ),
+		std::make_tuple ( "Exact Nonlinear Tree Pattern Automaton (PrefixRankedBar)",
+				"arbology::exact::ExactNonlinearTreePatternAutomaton (PrefixRankedBarTree)$subject <(tree::SubtreeWildcard::get $pattern) <(tree::NonlinearAlphabet::get $pattern) <(tree::VariablesBarSymbol::get (PrefixRankedBarNonlinearPattern)$pattern) | "
+				"automaton::determinize::Determinize - | (SetOfObjects)automaton::run::Result - (LinearString)(PrefixRankedBarNonlinearPattern)$pattern (DefaultStateType){ :Object }", 80 ),
+		std::make_tuple ( "Exact Pattern Match (NonlinearPattern PrefixRankedBar)",
+				"arbology::exact::ExactPatternMatch (PrefixRankedBarTree)$subject (PrefixRankedBarNonlinearPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Boyer Moore Horspool (NonlinearPattern PrefixRankedBar)",
+				"arbology::exact::BoyerMooreHorspool (PrefixRankedBarTree)$subject (PrefixRankedBarNonlinearPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Reversed Boyer Moore Horspool (NonlinearPattern PrefixRankedBar)",
+				"arbology::exact::ReversedBoyerMooreHorspool (PrefixRankedBarTree)$subject (PrefixRankedBarNonlinearPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Reversed Boyer Moore Horspool (NonlinearPattern PrefixRanked)",
+				"arbology::exact::ReversedBoyerMooreHorspool (PrefixRankedTree)$subject (PrefixRankedNonlinearPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ) );
+
+	auto exact = "arbology::exact::ExactPatternMatch $subject $pattern";
+	auto pattern = EGenerateType::NONLINEAR_PATTERN;
+
+
+	SECTION ( "Test files" ) {
+		for ( const std::pair < std::string, std::string > files : pair_pattern_subject ( TestFiles::Get ( "/tree/aarbology.test[0-9]+.nonlinear.pattern.xml$" ), ".nonlinear.pattern.xml", ".subject.xml" ) ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), files.first, files.second );
+			runTest ( exact, std::get < 1 > ( definition ), files.first, files.second );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+			runRandom ( exact, std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+		}
+	}
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+TEST_CASE ( "Arbology tests | nonlinear pattern ends", "[integration]" ) {
+	auto definition = GENERATE ( as < std::tuple < std::string, std::string, size_t > > ( ),
+		std::make_tuple ( "Exact Nonlinear Tree Pattern Automaton (PrefixRanked)",
+				"arbology::exact::ExactNonlinearTreePatternAutomaton (PrefixRankedTree)$subject <(tree::SubtreeWildcard::get $pattern) <(tree::NonlinearAlphabet::get $pattern) | automaton::determinize::Determinize - |"
+				"(SetOfObjects)automaton::run::Result - (LinearString)(PrefixRankedNonlinearPattern) $pattern (DefaultStateType) { :Object } ", 80 ) );
+
+	auto exact = "arbology::exact::ExactPatternMatch $subject $pattern | arbology::transform::BeginToEndIndex $subject -";
+	auto pattern = EGenerateType::NONLINEAR_PATTERN_SINGLE_VAR;
+
+	SECTION ( "Test files" ) {
+		for ( const std::pair < std::string, std::string > files : pair_pattern_subject ( TestFiles::Get ( "/tree/aarbology.test[0-9]+.nonlinear.pattern.xml$" ), ".nonlinear.pattern.xml", ".subject.xml" ) ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), files.first, files.second );
+			runTest ( exact, std::get < 1 > ( definition ), files.first, files.second );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+			runRandom ( exact, std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+		}
+	}
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+TEST_CASE ( "Arbology tests | pattern", "[integration]" ) {
+	auto definition = GENERATE ( as < std::tuple < std::string, std::string, size_t > > ( ),
+		std::make_tuple ( "Exact Pattern Matching Using Full And Linear Index (PrefixRankedBar)",
+				"arbology::indexing::FullAndLinearIndexConstruction (PrefixRankedBarTree) $subject | arbology::query::FullAndLinearIndexPatterns - (PrefixRankedBarPattern) $pattern", 1000 ),
+		std::make_tuple ( "Exact Pattern Matching Using Full And Linear Index (PrefixRanked)",
+				"arbology::indexing::FullAndLinearIndexConstruction (PrefixRankedTree) $subject | arbology::query::FullAndLinearIndexPatterns - (PrefixRankedPattern) $pattern", 1000 ),
+		std::make_tuple ( "Exact Pattern Matching Using Compressed Bit Vectors (PrefixRankedBar)",
+				"arbology::indexing::CompressedBitParallelIndexConstruction (PrefixRankedBarTree)$subject | arbology::query::CompressedBitParallelismPatterns - (PrefixRankedBarPattern)$pattern", 1000 ),
+		std::make_tuple ( "Exact Knuth Morris Pratt (Pattern PrefixRankedBar)",
+				"arbology::exact::KnuthMorrisPratt (PrefixRankedBarTree)$subject (PrefixRankedBarPattern)$pattern", 1000 ),
+		std::make_tuple ( "Exact Knuth Morris Pratt (Pattern PrefixRanked)",
+				"arbology::exact::KnuthMorrisPratt (PrefixRankedTree)$subject (PrefixRankedPattern)$pattern", 1000 ),
+		std::make_tuple ( "Exact Boyer Moore Horspool (Pattern PrefixRankedBar)",
+				"arbology::exact::BoyerMooreHorspool (PrefixRankedBarTree)$subject (PrefixRankedBarPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Reversed Boyer Moore Horspool (Pattern PrefixRankedBar)",
+				"arbology::exact::ReversedBoyerMooreHorspool (PrefixRankedBarTree)$subject (PrefixRankedBarPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Reversed Boyer Moore Horspool (Pattern PrefixRanked)",
+				"arbology::exact::ReversedBoyerMooreHorspool (PrefixRankedTree)$subject (PrefixRankedPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Quick Search (Pattern PrefixRankedBar)",
+				"arbology::exact::QuickSearch (PrefixRankedBarTree)$subject (PrefixRankedBarPattern)<(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Reversed Quick Search (Pattern PrefixRankedBar)",
+				"arbology::exact::ReversedQuickSearch (PrefixRankedBarTree)$subject (PrefixRankedBarPattern)<(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Reversed Quick Search (Pattern PrefixRanked)",
+				"arbology::exact::ReversedQuickSearch (PrefixRankedTree)$subject (PrefixRankedPattern)<(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Dead Zone Using Bad Character Shift And Border Array (Pattern PrefixRanked)",
+				"arbology::exact::DeadZoneUsingBadCharacterShiftAndBorderArray (PrefixRankedTree)$subject (PrefixRankedPattern)<(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Dead Zone Using Bad Character Shift And Border Array (Pattern PrefixRankedBar)",
+				"arbology::exact::DeadZoneUsingBadCharacterShiftAndBorderArray (PrefixRankedBarTree)$subject (PrefixRankedBarPattern)<(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ),
+		std::make_tuple ( "Exact Pattern Matching Automaton (Pattern Tree)",
+				"automaton::run::Occurrences <(arbology::exact::ExactPatternMatchingAutomaton <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject)) | automaton::determinize::Determinize - ) $subject", 1000 ),
+		std::make_tuple ( "Exact Pattern Matching Automaton (PrefixRankedBar)",
+				"arbology::exact::ExactPatternMatchingAutomaton (PrefixRankedBarPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject)) | automaton::determinize::Determinize - | automaton::run::Occurrences - (LinearString)(PrefixRankedBarTree)$subject", 1000 ) );
+
+	auto exact = "arbology::exact::ExactPatternMatch $subject $pattern";
+	auto pattern = EGenerateType::PATTERN;
+
+	SECTION ( "Test files" ) {
+		for ( const std::pair < std::string, std::string > files : pair_pattern_subject ( TestFiles::Get ( "/tree/aarbology.test[0-9]+.pattern.xml$" ), ".pattern.xml", ".subject.xml" ) ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), files.first, files.second );
+			runTest ( exact, std::get < 1 > ( definition ), files.first, files.second );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+			runRandom ( exact, std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+		}
+	}
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+TEST_CASE ( "Arbology tests | pattern ends ", "[integration]" ) {
+	auto definition = GENERATE ( as < std::tuple < std::string, std::string, size_t > > ( ),
+		std::make_tuple ( "Exact Pattern Matching Using Compressed Bit Vectors (PrefixRanked)",
+				"arbology::indexing::CompressedBitParallelIndexConstruction (PrefixRankedTree)$subject | arbology::query::CompressedBitParallelismPatterns - (PrefixRankedPattern)$pattern", 1000 ),
+
+		std::make_tuple ( "Exact Pattern Matching Automaton (PrefixRanked)",
+				"arbology::exact::ExactPatternMatchingAutomaton (PrefixRankedPattern) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject) ) | automaton::determinize::Determinize - | "
+				"automaton::run::Occurrences - (LinearString)(PrefixRankedTree) $subject", 1000 ),
+
+		std::make_tuple ( "Exact Tree Pattern Automaton (PrefixRanked)",
+				"arbology::exact::ExactTreePatternAutomaton (PrefixRankedTree)$subject <(tree::SubtreeWildcard::get $pattern) | automaton::determinize::Determinize - | (SetOfObjects) automaton::run::Result - (LinearString)(PrefixRankedPattern)$pattern (DefaultStateType) { :Object }", 120 ) );
+
+	auto exact = "arbology::exact::ExactPatternMatch (PrefixRankedTree)$subject (PrefixRankedPattern)$pattern | arbology::transform::BeginToEndIndex (PrefixRankedTree)$subject -";
+	auto pattern = EGenerateType::PATTERN;
+
+	SECTION ( "Test files" ) {
+		for ( const std::pair < std::string, std::string > files : pair_pattern_subject ( TestFiles::Get ( "/tree/aarbology.test[0-9]+.pattern.xml$" ), ".pattern.xml", ".subject.xml" ) ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), files.first, files.second );
+			runTest ( exact, std::get < 1 > ( definition ), files.first, files.second );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+			runRandom ( exact, std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+		}
+	}
+}
+// --------------------------------------------------------------------------------------------------------------------
+
+TEST_CASE ( "Arbology tests | subtree", "[integration]" ) {
+	auto definition = GENERATE ( as < std::tuple < std::string, std::string, size_t > > ( ),
+		std::make_tuple ( "Exact Subtree Automaton (Tree)",
+				"automaton::run::Occurrences <(arbology::exact::ExactSubtreeMatchingAutomaton $pattern | automaton::determinize::Determinize -) $subject", 1000 ),
+		std::make_tuple ( "Exact Minimized Subtree Automaton (Tree)",
+				"automaton::run::Occurrences <(arbology::exact::ExactSubtreeMatchingAutomaton $pattern | automaton::determinize::Determinize - | "
+				"automaton::simplify::Trim - | automaton::simplify::Minimize -) $subject", 1000 ),
+		std::make_tuple ( "Exact Boyer Moore Horspool (Subtree PrefixRankedBar)",
+				"arbology::exact::BoyerMooreHorspool (PrefixRankedBarTree)$subject (PrefixRankedBarTree) <(tree::GeneralAlphabet::add $pattern <(tree::GeneralAlphabet::get $subject))", 1000 ) );
+
+
+	auto exact = "arbology::exact::ExactSubtreeMatch $subject $pattern";
+	auto pattern = EGenerateType::SUBTREE;
+
+	SECTION ( "Test files" ) {
+		for ( const std::pair < std::string, std::string > files : pair_pattern_subject ( TestFiles::Get ( "/tree/aarbology.test[0-9]+.subtree.xml$" ), ".subtree.xml", ".subject.xml" ) ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), files.first, files.second );
+			runTest ( exact, std::get < 1 > ( definition ), files.first, files.second );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			CAPTURE ( std::get < 0 > ( definition ), std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+			runRandom ( exact, std::get < 1 > ( definition ), pattern, std::get < 2 > ( definition ) );
+		}
+	}
+}
diff --git a/alib2integrationtest/test-src/tests/conversionsTest.cpp b/alib2integrationtest/test-src/tests/conversionsTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..19e2cc1231a9e1aaa78fece5816df90474aa0f38
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/conversionsTest.cpp
@@ -0,0 +1,69 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+const unsigned RAND_STATES   = 15;
+const unsigned RAND_ALPHABET = 5;
+const double   RAND_DENSITY  = 2.5;
+const size_t   ITERATIONS = 50;
+
+const std::string qGenNFA ( ) {
+	std::ostringstream oss;
+	oss << "execute automaton::generate::RandomAutomatonFactory ";
+	oss << "(size_t)" << rand ( ) % RAND_STATES + 1 << " ";
+	oss << "(size_t)" << rand ( ) % RAND_ALPHABET + 1 << " ";
+	oss << "(bool)true ";
+	oss << "(double)\"" << RAND_DENSITY << "\"";
+	return oss.str ( );
+}
+
+TEST_CASE ( "FA-RG-RE conversions test", "[integration]" ) {
+	auto pipeline = GENERATE ( as < std::string > ( ),
+			"automaton::convert::ToGrammarLeftRG  - | grammar::convert::ToGrammarRightRG - | grammar::convert::ToAutomaton -",
+			"automaton::convert::ToGrammarRightRG - | grammar::convert::ToGrammarLeftRG  - | grammar::convert::ToAutomaton -",
+
+			"automaton::convert::ToRegExpAlgebraic        - | regexp::convert::ToAutomatonDerivation -",
+			"automaton::convert::ToRegExpAlgebraic        - | regexp::convert::ToAutomatonGlushkov   -",
+			"automaton::convert::ToRegExpAlgebraic        - | regexp::convert::ToAutomatonThompson   -",
+			"automaton::convert::ToRegExpStateElimination - | regexp::convert::ToAutomatonDerivation -",
+			"automaton::convert::ToRegExpStateElimination - | regexp::convert::ToAutomatonGlushkov   -",
+			"automaton::convert::ToRegExpStateElimination - | regexp::convert::ToAutomatonThompson   -",
+
+			"automaton::convert::ToRegExpAlgebraic        - | regexp::convert::ToGrammarRightRGDerivation - | grammar::convert::ToGrammarLeftRG - | grammar::convert::ToAutomaton -",
+			"automaton::convert::ToRegExpAlgebraic        - | regexp::convert::ToGrammarRightRGGlushkov   - | grammar::convert::ToGrammarLeftRG - | grammar::convert::ToAutomaton -",
+			"automaton::convert::ToRegExpStateElimination - | regexp::convert::ToGrammarRightRGDerivation - | grammar::convert::ToGrammarLeftRG - | grammar::convert::ToAutomaton -",
+			"automaton::convert::ToRegExpStateElimination - | regexp::convert::ToGrammarRightRGGlushkov   - | grammar::convert::ToGrammarLeftRG - | grammar::convert::ToAutomaton -",
+
+			"automaton::convert::ToGrammarLeftRG  - | grammar::convert::ToRegExp - | regexp::convert::ToAutomatonDerivation -",
+			"automaton::convert::ToGrammarRightRG - | grammar::convert::ToRegExp - | regexp::convert::ToAutomatonDerivation -",
+			"automaton::convert::ToGrammarLeftRG  - | grammar::convert::ToRegExp - | regexp::convert::ToAutomatonThompson   -",
+			"automaton::convert::ToGrammarRightRG - | grammar::convert::ToRegExp - | regexp::convert::ToAutomatonThompson   -",
+			"automaton::convert::ToGrammarLeftRG  - | grammar::convert::ToRegExp - | regexp::convert::ToAutomatonGlushkov   -",
+			"automaton::convert::ToGrammarRightRG - | grammar::convert::ToRegExp - | regexp::convert::ToAutomatonGlushkov   -" );
+
+	static const std::string qMinimize ( "automaton::simplify::efficient::EpsilonRemoverIncoming - | automaton::determinize::Determinize - | "
+			"automaton::simplify::Trim - | automaton::simplify::Minimize - | automaton::simplify::Normalize -" );
+
+
+	SECTION ( "Files tests" ) {
+		for ( const std::string & inputFile : TestFiles::Get ( "/automaton/aconversion.test.*.xml$" ) ) {
+			ext::vector < std::string > qs = {
+				"execute < " + inputFile + " > $gen",
+				"quit compare::AutomatonCompare <( $gen | " + qMinimize + " )" + " <( $gen | " + pipeline + " | " + qMinimize + ")"
+			};
+			TimeoutAqlTest ( 10s, qs );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < ITERATIONS; i++ ) {
+			ext::vector < std::string > qs = {
+				qGenNFA ( ) + " > $gen",
+				"quit compare::AutomatonCompare <( $gen | " + qMinimize + " )" + " <( $gen | " + pipeline + " | " + qMinimize + ")"
+			};
+			TimeoutAqlTest ( 10s, qs );
+		}
+	}
+}
diff --git a/alib2integrationtest/test-src/tests/determinizeTest.cpp b/alib2integrationtest/test-src/tests/determinizeTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5d49fe6fb8ad839afec7f90a5ad1df01d9c89b07
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/determinizeTest.cpp
@@ -0,0 +1,29 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+TEST_CASE ( "Determinization", "[integration]" ) {
+	auto definition = GENERATE ( as < std::tuple < std::string, std::string, std::string > > ( ),
+			std::make_tuple ( "automaton::determinize::Determinize - | automaton::simplify::Trim -",      TestFiles::GetOne ( "/automaton/NFSM1.xml$" ),   TestFiles::GetOne ( "/automaton/NFSM1.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize - | automaton::simplify::Trim -",      TestFiles::GetOne ( "/automaton/NFSM2.xml$" ),   TestFiles::GetOne ( "/automaton/NFSM2.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize - | automaton::simplify::Trim -",      TestFiles::GetOne ( "/automaton/NFSM3.xml$" ),   TestFiles::GetOne ( "/automaton/NFSM3.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize - | automaton::simplify::Trim -",      TestFiles::GetOne ( "/automaton/NFSM4.xml$" ),   TestFiles::GetOne ( "/automaton/NFSM4.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize - | automaton::simplify::Trim -",      TestFiles::GetOne ( "/automaton/NFSM5.xml$" ),   TestFiles::GetOne ( "/automaton/NFSM5.DET.xml$" ) ),
+			std::make_tuple ( "automaton::simplify::EpsilonRemoverIncoming - | automaton::determinize::Determinize -", TestFiles::GetOne ( "/automaton/ENFSM2.xml$" ),  TestFiles::GetOne ( "/automaton/ENFSM2.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize -                              ",      TestFiles::GetOne ( "/automaton/NFTA.xml$" ),    TestFiles::GetOne ( "/automaton/NFTA.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize -                              ",      TestFiles::GetOne ( "/automaton/NIDPDA0.xml$" ), TestFiles::GetOne ( "/automaton/NIDPDA0.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize -                              ",      TestFiles::GetOne ( "/automaton/NIDPDA1.xml$" ), TestFiles::GetOne ( "/automaton/NIDPDA1.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize -                              ",      TestFiles::GetOne ( "/automaton/NIDPDA2.xml$" ), TestFiles::GetOne ( "/automaton/NIDPDA2.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize -                              ",      TestFiles::GetOne ( "/automaton/NIDPDA3.xml$" ), TestFiles::GetOne ( "/automaton/NIDPDA3.DET.xml$" ) ),
+			std::make_tuple ( "automaton::determinize::Determinize - | automaton::simplify::Normalize -", TestFiles::GetOne ( "/automaton/NPDA1.xml$" ),   TestFiles::GetOne ( "/automaton/NPDA1.DET.xml$" ) ) );
+
+	ext::vector < std::string > qs = {
+		"execute < " + std::get < 1 > ( definition ) + " > $input",
+		"execute < " + std::get < 2 > ( definition ) + " > $expected",
+		"quit compare::AutomatonCompare <( $input | " + std::get < 0 > ( definition ) + " ) $expected"
+	};
+
+	TimeoutAqlTest ( 2s, qs );
+}
diff --git a/alib2integrationtest/test-src/tests/dummyTest.cpp b/alib2integrationtest/test-src/tests/dummyTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3216f53d6a9feff395f1ab91fc500fb024a7a248
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/dummyTest.cpp
@@ -0,0 +1,14 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+TEST_CASE ( "Dummy Test", "[integration][dummy][!mayfail]" ) {
+	ext::vector < std::string > qs = {
+		"execute 1",
+		"exec"
+	};
+
+	TimeoutAqlTest ( 1s, qs );
+}
diff --git a/alib2integrationtest/test-src/tests/exactMatching.cpp b/alib2integrationtest/test-src/tests/exactMatching.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6b34df65d6ae3620393983b492eb9860d635a67
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/exactMatching.cpp
@@ -0,0 +1,85 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+const size_t PATTERN_SIZE = 7;
+const size_t SUBJECT_SIZE = 100;
+const size_t ALPHABET_SIZE = 4;
+const size_t RANDOM_ITERATIONS = 20;
+
+static std::string qExtendAlphabet ( const std::string & s1, const std::string & s2 ) {
+	return "execute string::GeneralAlphabet::add $" + s1 + " <( string::GeneralAlphabet::get $" + s2 + " ) > ";
+}
+
+static std::string qGenString ( const size_t & len, const size_t &alph_len, const std::string & var ) {
+	std::ostringstream oss;
+	oss << "execute string::generate::RandomStringFactory ";
+	oss << "( size_t )" << rand ( ) % len + 1;
+	oss << "( size_t )" << rand ( ) % alph_len + 1;
+	oss << "true | ";
+	oss << "string::simplify::NormalizeAlphabet - > $" + var;
+	return oss.str ( );
+}
+
+TEST_CASE ( "ExactMatching", "[integration]" ) {
+	auto definition = GENERATE ( as < std::tuple < std::string, std::string, bool > > ( ),
+			std::make_tuple ( "Exact Boyer Moore", "stringology::exact::BoyerMoore $subject $pattern", true ),
+			std::make_tuple ( "Exact Boyer Moore Horspool", " stringology::exact::BoyerMooreHorspool $subject $pattern", true ),
+			std::make_tuple ( "Exact Reversed Boyer Moore Horspool", " stringology::exact::ReversedBoyerMooreHorspool $subject $pattern", true ),
+			std::make_tuple ( "Quick Search", "stringology::exact::QuickSearch $subject $pattern", true ),
+			std::make_tuple ( "Exact Dead Zone Using Bad Character Shift", "stringology::exact::DeadZoneUsingBadCharacterShift $subject $pattern", true ),
+			std::make_tuple ( "Exact Matching Automaton", "automaton::run::Occurrences <(stringology::matching::ExactMatchingAutomaton $pattern | automaton::determinize::Determinize -) $subject", true ),
+			std::make_tuple ( "DAWG Factors", "stringology::indexing::ExactSuffixAutomaton $subject | stringology::query::SuffixAutomatonFactors - $pattern", false ),
+			std::make_tuple ( "BNDM Matcher", "stringology::matching::BNDMMatcherConstruction $pattern | stringology::query::BNDMOccurrences - $subject", false ),
+			std::make_tuple ( "Compressed Bit Parallelism Factors", "stringology::indexing::CompressedBitParallelIndexConstruction $subject | stringology::query::CompressedBitParallelismFactors - $pattern", false ),
+			std::make_tuple ( "Bit Parallelism Factors", "stringology::indexing::BitParallelIndexConstruction $subject | stringology::query::BitParallelismFactors - $pattern", false ),
+			std::make_tuple ( "Position Heap Factors", "stringology::indexing::PositionHeapNaive $subject | stringology::query::PositionHeapFactors - $pattern", false ),
+			std::make_tuple ( "Suffix Array Factors", "stringology::indexing::SuffixArrayNaive $subject | stringology::query::SuffixArrayFactors - $pattern", false ),
+			std::make_tuple ( "Suffix Trie Factors", "stringology::indexing::SuffixTrieNaive $subject | stringology::query::SuffixTrieFactors - $pattern", false ) );
+
+	SECTION ( "Test files" ) {
+		for ( const std::string & patternFile : TestFiles::Get ( "/string/astringology.test.*.pattern.xml$" ) ) {
+			static const std::string p ( ".pattern." ), s ( ".subject." );
+			std::string subjectFile = patternFile;
+
+			size_t pos = subjectFile.find ( p );
+			subjectFile.replace ( pos, s.size ( ), s );
+
+			ext::vector < std::string > qs = {
+				"execute < " + patternFile + " > $pattern",
+				"execute < " + subjectFile + " > $subject",
+				"execute stringology::exact::ExactFactorMatch $subject $pattern > $res1"
+			};
+
+			if ( std::get < 2 > ( definition ) )
+				qs.push_back ( qExtendAlphabet ( "pattern", "subject" ) );
+
+			qs.push_back ( "execute " + std::get < 1 > ( definition ) + " > $res2" );
+			qs.push_back ( "quit compare::PrimitiveCompare <(stats::SizeStat $res1) <(stats::SizeStat $res2)" );
+
+			INFO ( std::get < 0 > ( definition ) );
+			TimeoutAqlTest ( 2s, qs );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			ext::vector < std::string > qs = {
+				qGenString ( PATTERN_SIZE, ALPHABET_SIZE, "pattern" ),
+				qGenString ( SUBJECT_SIZE, ALPHABET_SIZE, "subject" ),
+				"execute stringology::exact::ExactFactorMatch $subject $pattern > $res1"
+			};
+
+			if ( std::get < 2 > ( definition ) )
+				qs.push_back ( qExtendAlphabet ( "pattern", "subject" ) );
+
+			qs.push_back ( "execute " + std::get < 1 > ( definition ) + " > $res2" );
+			qs.push_back ( "quit compare::PrimitiveCompare <(stats::SizeStat $res1) <(stats::SizeStat $res2)" );
+
+			INFO ( std::get < 0 > ( definition ) );
+			TimeoutAqlTest ( 2s, qs );
+		}
+	}
+}
diff --git a/alib2integrationtest/test-src/tests/glushkovRteTest.cpp b/alib2integrationtest/test-src/tests/glushkovRteTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e5d9efef9239dc272f4b7f5d7b3ef3d1927c26c5
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/glushkovRteTest.cpp
@@ -0,0 +1,45 @@
+#include <catch2/catch.hpp>
+#include <memory>
+#include <alib/vector>
+#include <libgen.h>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+#include "glushkovRteTestGenerators.hpp"
+
+static size_t TESTCASES = 50;
+
+std::map < std::string, std::shared_ptr < TreeGenerator > > m_Generators = {
+	{ "rte1.xml", std::make_shared < TreeGenerator1 > ( ) },
+	{ "rte2.xml", std::make_shared < TreeGenerator2 > ( ) },
+	{ "rte3.xml", std::make_shared < TreeGenerator3 > ( ) },
+	{ "rte4.xml", std::make_shared < TreeGenerator4 > ( ) },
+	{ "rte5.xml", std::make_shared < TreeGenerator5 > ( ) },
+	{ "rte6.xml", std::make_shared < TreeGenerator6 > ( ) },
+	{ "rte7.xml", std::make_shared < TreeGenerator7 > ( ) },
+	{ "rte8.xml", std::make_shared < TreeGenerator8 > ( ) },
+	{ "rte9.xml", std::make_shared < TreeGenerator9 > ( ) },
+};
+
+TEST_CASE ( "GlushkovRTE", "[integration]" ) {
+	for ( const std::string & file : TestFiles::Get ( "/rte/rte[0-9]+.xml$" ) ) {
+		char * p_filepath = strdup ( file.c_str ( ) );
+		std::string base = basename ( p_filepath ); // be careful, there are posix and gnu versions
+		free ( p_filepath );
+
+		try {
+			for ( size_t i = 0; i < TESTCASES; i++ ) {
+				ext::vector < std::string > qs = {
+						"execute < " + file + " | rte::convert::ToPostfixPushdownAutomatonGlushkov - | automaton::determinize::Determinize - > $pda",
+						"execute \"\\\"" + m_Generators.at ( base ) -> generate ( ) + "\\\"\" | string::Parse @string::String ^ - > $string",
+						"quit automaton::run::Accept $pda $string",
+				};
+
+				TimeoutAqlTest ( 5s, qs );
+			}
+		} catch ( const std::out_of_range & ) {
+			FAIL ( "No generator assigned for file " << file );
+		}
+	}
+}
diff --git a/alib2integrationtest/test-src/tests/glushkovRteTestGenerators.hpp b/alib2integrationtest/test-src/tests/glushkovRteTestGenerators.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2cdab1a4d35e6a5dc1d0cf7c4cd5e63f7addf9c
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/glushkovRteTestGenerators.hpp
@@ -0,0 +1,159 @@
+class TreeGenerator {
+	protected:
+		static size_t MAX_DEPTH;
+		static size_t MAX_LENGTH;
+		std::string m_Str;
+
+		int randint ( int lo, int hi ) const {
+			return rand ( ) % ( hi - lo + 1 ) + lo;
+		}
+
+	public:
+		std::string generate ( ) {
+			m_Str.clear ( );
+			S ( );
+			m_Str += "#$";
+			return m_Str;
+		}
+
+	private:
+		virtual void S ( size_t depth = 1 ) = 0;
+};
+
+size_t TreeGenerator::MAX_DEPTH = 200;
+size_t TreeGenerator::MAX_LENGTH = 1000;
+
+/** Generator for rte1.xml */
+class TreeGenerator1 : public TreeGenerator {
+	private:
+		void S ( size_t depth = 1 ) {
+			m_Str += ( depth > MAX_DEPTH || randint ( 0, 1 ) == 0 ) ? "b " : "c ";
+			S2 ( depth + 1 );
+		}
+
+		void S2 ( size_t depth ) {
+			if ( depth > MAX_DEPTH || randint ( 0, 1 ) == 0 )
+				return;
+
+			m_Str += "b a d ";
+			S2 ( depth + 1 );
+		}
+};
+
+/** Generator for rte2.xml */
+class TreeGenerator2 : public TreeGenerator {
+	private:
+		void S ( size_t /* depth = 1 */ ) {
+			m_Str += "b b a ";
+		}
+};
+
+/** Generator for rte3.xml */
+class TreeGenerator3 : public TreeGenerator {
+	private:
+		void S ( size_t depth = 1 ) {
+			if ( depth > MAX_DEPTH || randint ( 0, 1 ) == 0 ) {
+				m_Str += "b ";
+				return;
+			}
+
+			S ( depth + 1 );
+			S ( depth + 1 );
+			m_Str += "a ";
+		}
+};
+
+/** Generator for rte4.xml */
+class TreeGenerator4 : public TreeGenerator {
+	private:
+		void S ( size_t depth = 1 ) {
+			if ( depth > MAX_DEPTH || randint ( 0, 1 ) == 0 ) {
+				m_Str += "b b a ";
+				return;
+			}
+
+			S ( depth + 1 );
+			S ( depth + 1 );
+			m_Str += "a ";
+		}
+};
+
+/** Generator for rte5.xml */
+class TreeGenerator5 : public TreeGenerator {
+	private:
+		void S ( size_t /* depth = 1 */ ) {
+			m_Str += "a ";
+		}
+};
+
+/** Generator for rte6.xml */
+class TreeGenerator6 : public TreeGenerator {
+	private:
+		void S ( size_t depth = 1 ) {
+			SL ( depth + 1 );
+			SR ( depth + 1 );
+			m_Str += "a ";
+		}
+
+		void SL ( size_t depth ) {
+			int r = randint ( 0, 1 );
+			if ( r == 0 || depth > MAX_DEPTH )
+				m_Str += "b ";
+			else if ( r == 1 )
+				S ( depth + 1 );
+		}
+
+		void SR ( size_t depth ) {
+			int r = randint ( 0, 1 );
+			if ( r == 0 || depth > MAX_DEPTH )
+				m_Str += "c ";
+			else if ( r == 1 )
+				S ( depth + 1 );
+		}
+};
+
+/** Generator for rte7.xml */
+class TreeGenerator7 : public TreeGenerator {
+	private:
+		void S ( size_t depth = 1 ) {
+			m_Str += "c b a ";
+			S2 ( depth + 1 );
+		}
+
+		void S2 ( size_t depth ) {
+			if ( depth > MAX_DEPTH || randint ( 0, 2 ) == 0 )
+				return;
+
+			m_Str += "d ";
+			S2 ( depth + 1 );
+		}
+};
+
+/** Generator for rte8.xml */
+class TreeGenerator8 : public TreeGenerator {
+	private:
+		void S ( size_t depth = 1 ) {
+			if ( depth > MAX_DEPTH || randint ( 0, 1 ) == 0 ) {
+				m_Str += std::string ( 1, 'b' + randint ( 0, 3 ) ) + ' ';
+				return;
+			}
+
+			S ( depth + 1 );
+			S ( depth + 1 );
+			m_Str += "a ";
+		}
+};
+
+/** Generator for rte9.xml */
+class TreeGenerator9 : public TreeGenerator {
+	private:
+		void S ( size_t depth = 1 ) {
+			if ( depth > MAX_DEPTH || randint ( 0, 1 ) == 0 ) {
+				m_Str += "b ";
+			} else {
+				S ( depth + 1 );
+				S ( depth + 1 );
+				m_Str += "a ";
+			}
+		}
+};
diff --git a/alib2integrationtest/test-src/tests/normalizeTest.cpp b/alib2integrationtest/test-src/tests/normalizeTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5f9a28790d6784c63c2f7d9b5d216e55b75a4d0a
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/normalizeTest.cpp
@@ -0,0 +1,57 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+#include <extensions/container/string.hpp>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+double RAND_DENSITY = 50;
+size_t RAND_NONTERMINALS = 2;
+size_t RAND_TERMINALS = 4;
+size_t STRING_LENGTHS = 6;
+size_t RANDOM_ITERATIONS = 50;
+
+
+std::string qGenerateCfg ( const std::string & var ) {
+	std::ostringstream oss;
+	oss << "execute grammar::generate::RandomGrammarFactory" << " ";
+	oss << "(int) " << rand ( ) % RAND_NONTERMINALS + 1 << " ";
+	oss << "(int) " << rand ( ) % RAND_TERMINALS + 1 << " ";
+	oss << "(bool) true ";
+	oss << "(double) " << RAND_DENSITY << " | ";
+	oss << "grammar::simplify::EpsilonRemover - | ";
+	oss << "grammar::simplify::SimpleRulesRemover - > $" << var;
+	return oss.str();
+}
+
+TEST_CASE ( "Normalize test", "[integration]" ) {
+	auto algorithm = GENERATE ( as < std::string > ( ), "grammar::simplify::ToCNF", "grammar::simplify::ToGNF" );
+
+	SECTION ( "Test Files" ) {
+		for ( const std::string & file : TestFiles::Get ( "/grammar/anormalization.test.*.xml$" ) ) {
+			ext::vector < std::string > qs = {
+				"execute < " + file + " > $cfg",
+				"execute " + algorithm + " $cfg > $cfg2",
+				"execute grammar::generate::GenerateUpToLength $cfg "  + ext::to_string ( STRING_LENGTHS ) + " > $str",
+				"execute grammar::generate::GenerateUpToLength $cfg2 " + ext::to_string ( STRING_LENGTHS ) + " > $str2",
+				"quit compare::TrieCompare $str $str2",
+			};
+
+			TimeoutAqlTest ( 1s, qs );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			ext::vector < std::string > qs = {
+				qGenerateCfg ( "cfg" ),
+				"execute " + algorithm + " $cfg > $cfg2",
+				"execute grammar::generate::GenerateUpToLength $cfg "  + ext::to_string ( STRING_LENGTHS ) + " > $str",
+				"execute grammar::generate::GenerateUpToLength $cfg2 " + ext::to_string ( STRING_LENGTHS ) + " > $str2",
+				"quit compare::TrieCompare $str $str2",
+			};
+
+			TimeoutAqlTest ( 1s, qs );
+		}
+	}
+}
diff --git a/alib2integrationtest/test-src/tests/readerTest.cpp b/alib2integrationtest/test-src/tests/readerTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..86b032ff0f73cdc723e055da34225219f298d2c3
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/readerTest.cpp
@@ -0,0 +1,35 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+TEST_CASE ( "ReaderTest | Xml", "[integration]" ) {
+	auto regexp = GENERATE ( as<std::string>(), "/automaton/.*.xml$", "/grammar/.*.xml$", "/regexp/.*.xml$", "/string/.*.xml$", "/rte/.*.xml$" );
+
+	for ( const std::string & file : TestFiles::Get ( regexp ) ) {
+		ext::vector < std::string > qs = {
+			"execute < " + file + " > $object",
+			"execute $object > /dev/null",
+		};
+
+		TimeoutAqlTest ( 1s, qs );
+	}
+}
+
+TEST_CASE ( "ReaderTest | Txt ", "[integration]" ) {
+	auto def = GENERATE (
+			std::make_pair ( "automaton::Automaton", "/automaton/.*.txt$" ),
+			std::make_pair ( "regexp::RegExp", "/regexp/.*.txt$" ),
+			std::make_pair ( "grammar::Grammar", "/grammar/.*.txt$" ),
+			std::make_pair ( "string::String", "/string/.*.txt$" ) );
+
+	for ( const std::string & file : TestFiles::Get ( def.second ) ) {
+		ext::vector < std::string > qs = {
+			"execute cli::builtin::ReadFile " + file + " | string::Parse @" + def.first + " ^ -  > $object",
+			"execute $object > /dev/null",
+		};
+
+		TimeoutAqlTest ( 1s, qs );
+	}
+}
diff --git a/alib2integrationtest/test-src/tests/regexpDerivationIntegralTest.cpp b/alib2integrationtest/test-src/tests/regexpDerivationIntegralTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a06cca9fd5e233d29b42b1b4f2dd6530e849bf3
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/regexpDerivationIntegralTest.cpp
@@ -0,0 +1,34 @@
+#include <catch2/catch.hpp>
+#include <tuple>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+enum class Op {
+	DERIVATION,
+	INTEGRAL
+};
+
+
+TEST_CASE ( "RegExp Derivation/Integral test", "[integration]" ) {
+	static const std::string mdfa = "regexp::convert::ToAutomatonGlushkov - | automaton::determinize::Determinize - | automaton::simplify::Trim - | automaton::simplify::Minimize - | automaton::simplify::Normalize -";
+
+	auto definition = GENERATE ( as < std::tuple < Op, std::string, std::string, std::string > > ( ),
+			std::make_tuple ( Op::DERIVATION, TestFiles::GetOne ( "/regexp/unbounded.oppa.4.13.xml$" ), TestFiles::GetOne ( "/regexp/unbounded.oppa.4.13.d0.xml$" ),   "0" ),
+			std::make_tuple ( Op::DERIVATION, TestFiles::GetOne ( "/regexp/unbounded.oppa.4.13.xml$" ), TestFiles::GetOne ( "/regexp/unbounded.oppa.4.13.d00.xml$" ),  "0 0" ),
+			std::make_tuple ( Op::DERIVATION, TestFiles::GetOne ( "/regexp/unbounded.oppa.4.14.xml$" ), TestFiles::GetOne ( "/regexp/unbounded.oppa.4.14.d1.xml$" ),   "1" ),
+			std::make_tuple ( Op::DERIVATION, TestFiles::GetOne ( "/regexp/unbounded.oppa.4.14.xml$" ), TestFiles::GetOne ( "/regexp/unbounded.oppa.4.14.d10.xml$" ),  "1 0" ),
+			std::make_tuple ( Op::DERIVATION, TestFiles::GetOne ( "/regexp/unbounded.oppa.4.15.xml$" ), TestFiles::GetOne ( "/regexp/unbounded.oppa.4.15.d100.xml$" ), "1 0 0" ),
+			std::make_tuple ( Op::INTEGRAL, TestFiles::GetOne ( "/regexp/unbounded.oppa.4.16.xml" ), TestFiles::GetOne ( "/regexp/unbounded.oppa.4.16.i1.xml" ), "1" ),
+			std::make_tuple ( Op::INTEGRAL, TestFiles::GetOne ( "/regexp/Melichar2-94.xml" ),        TestFiles::GetOne ( "/regexp/Melichar2-94.i0.xml" ), "0" ),
+			std::make_tuple ( Op::INTEGRAL, TestFiles::GetOne ( "/regexp/Melichar2-94.xml" ),        TestFiles::GetOne ( "/regexp/Melichar2-94.i1.xml" ), "1" ) );
+
+	ext::vector < std::string > qs = {
+		"execute < " + std::get < 1 > ( definition ) + " > $regexp",
+		"execute < " + std::get < 2 > ( definition ) + " > $result",
+		"execute \"\\\"" + std::get < 3 > ( definition ) + "\\\"\"" + " | string::Parse @string::String ^ - > $string",
+		"quit compare::AutomatonCompare <( $result | " + mdfa + " ) <( regexp::RegExp" + ( std::get < 0 > ( definition ) == Op::DERIVATION ? "Derivation" : "Integral" ) + " $regexp $string | " + mdfa + " )"
+	};
+
+	TimeoutAqlTest ( 1s, qs );
+}
diff --git a/alib2integrationtest/test-src/tests/treeNotationTest.cpp b/alib2integrationtest/test-src/tests/treeNotationTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..096c3cb2e877e20e2d7e8f3e7f2c446ec6e243ad
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/treeNotationTest.cpp
@@ -0,0 +1,44 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+const size_t SIZE = 100;
+const size_t HEIGHT = 15;
+const size_t ALPHABET_SIZE = 10;
+const size_t RANDOM_ITERATIONS = 15;
+
+
+TEST_CASE ( "TreeNotation tests | Files", "[integration]" ) {
+	auto casts = GENERATE ( as < std::string > ( ), "(PostfixRankedTree)" );
+
+	SECTION ( "Test files" ) {
+		for ( const std::string & file : TestFiles::Get ( "/tree/repeats.*.xml" ) ) {
+			ext::vector < std::string > qs = {
+				"execute < " + file + " > $res1",
+				"execute (RankedTree)" + casts + "$res1 > $res2",
+				"quit compare::TreeCompare $res1 $res2",
+			};
+
+			TimeoutAqlTest ( 1s, qs );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		std::ostringstream oss;
+		oss << "execute tree::generate::RandomRankedTreeFactory ";
+		oss << HEIGHT << " " << SIZE << " " << ( rand ( ) % ALPHABET_SIZE + 1 );
+		oss << " (bool)true 5 > $res1";
+
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			ext::vector < std::string > qs = {
+				oss.str ( ),
+				"execute (RankedTree)" + casts + "$res1 > $res2",
+				"quit compare::TreeCompare $res1 $res2",
+			};
+
+			TimeoutAqlTest ( 2s, qs );
+		}
+	}
+}
diff --git a/alib2integrationtest/test-src/tests/treeRepeatsTest.cpp b/alib2integrationtest/test-src/tests/treeRepeatsTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..35a3b9e7009d9d773c030cb9c7c50a11ba52b48e
--- /dev/null
+++ b/alib2integrationtest/test-src/tests/treeRepeatsTest.cpp
@@ -0,0 +1,45 @@
+#include <catch2/catch.hpp>
+#include <alib/vector>
+#include <extensions/container/string.hpp>
+
+#include "testing/TimeoutAqlTest.hpp"
+#include "testing/TestFiles.hpp"
+
+const size_t SIZE = 100;
+const size_t HEIGHT = 15;
+const size_t ALPHABET_SIZE = 10;
+const size_t RANDOM_ITERATIONS = 15;
+
+TEST_CASE ( "TreeRepeats", "[integration]" ) {
+	auto pipeline = GENERATE ( as < std::string > ( ),
+		"arbology::properties::ExactSubtreeRepeatsFromSubtreeAutomaton (PrefixRankedTree)$tree | tree::NormalizeTreeLabels (RankedTree) -",
+		"tree::properties::ExactSubtreeRepeatsNaive (PostfixRankedTree)$tree | tree::NormalizeTreeLabels (RankedTree) -",
+		"tree::properties::ExactSubtreeRepeatsNaive (PostfixRankedTree)$tree | tree::NormalizeTreeLabels (RankedTree) -" );
+
+
+	SECTION ( "Test Files" ) {
+		for ( const std::string & file : TestFiles::Get ( "/tree/repeats.*.xml" ) ) {
+			ext::vector < std::string > qs = {
+				"execute < " + file + " > $tree",
+				"execute tree::properties::ExactSubtreeRepeatsNaive $tree | tree::NormalizeTreeLabels - > $res1", // naive
+				"execute " + pipeline + " > $res2",
+				"quit compare::TreeCompare $res1 $res2",
+			};
+
+			TimeoutAqlTest ( 2s, qs );
+		}
+	}
+
+	SECTION ( "Random tests" ) {
+		for ( size_t i = 0; i < RANDOM_ITERATIONS; i++ ) {
+			ext::vector < std::string > qs = {
+				"execute tree::generate::RandomRankedTreeFactory " + ext::to_string ( HEIGHT ) + " " + ext::to_string ( SIZE ) + " " + ext::to_string ( rand ( ) % ALPHABET_SIZE + 1 ) + " (bool)true 5 > $tree",
+				"execute tree::properties::ExactSubtreeRepeatsNaive $tree | tree::NormalizeTreeLabels - > $res1", // naive
+				"execute " + pipeline + " > $res2",
+				"quit compare::TreeCompare $res1 $res2",
+			};
+
+			TimeoutAqlTest ( 2s, qs );
+		}
+	}
+}