diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 4cecbe1f81934e577ce8bce88bd1c3618f1caea3..e6d42bc60a2bc65465acf4f76927932a13a18095 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -93,11 +93,7 @@ static my_bool get_one_option(int optid, const struct my_option *,
 C_MODE_END
 
 enum {
-  OPT_PS_PROTOCOL=OPT_MAX_CLIENT_OPTION, OPT_SP_PROTOCOL,
-  OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL, OPT_MAX_CONNECT_RETRIES,
-  OPT_MAX_CONNECTIONS, OPT_MARK_PROGRESS, OPT_LOG_DIR,
-  OPT_TAIL_LINES, OPT_RESULT_FORMAT_VERSION,
-  OPT_MY_CONNECT_TIMEOUT, OPT_NON_BLOCKING_API
+  OPT_LOG_DIR=OPT_MAX_CLIENT_OPTION, OPT_RESULT_FORMAT_VERSION
 };
 
 static int record= 0, opt_sleep= -1;
@@ -105,7 +101,7 @@ static char *opt_db= 0, *opt_pass= 0;
 const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./";
 static char *shared_memory_base_name=0;
 const char *opt_logdir= "";
-const char *opt_include= 0, *opt_charsets_dir;
+const char *opt_prologue= 0, *opt_charsets_dir;
 static int opt_port= 0;
 static int opt_max_connect_retries;
 static int opt_result_format_version;
@@ -216,7 +212,6 @@ static struct st_test_file file_stack[16];
 static struct st_test_file* cur_file;
 static struct st_test_file* file_stack_end;
 
-
 static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
 
 static const char *embedded_server_groups[]=
@@ -242,7 +237,9 @@ static ulonglong timer_now(void);
 
 static ulong connection_retry_sleep= 100000; /* Microseconds */
 
-static char *opt_plugin_dir= 0;
+static const char *opt_plugin_dir;
+static const char *opt_suite_dir, *opt_overlay_dir;
+static size_t suite_dir_len, overlay_dir_len;
 
 /* Precompiled re's */
 static my_regex_t ps_re;     /* the query can be run using PS protocol */
@@ -2866,40 +2863,128 @@ void eval_expr(VAR *v, const char *p, const char **p_end,
 }
 
 
-int open_file(const char *name)
+bool open_and_set_current(const char *name)
+{
+  FILE *opened= fopen(name, "rb");
+
+  if (!opened)
+    return false;
+
+  cur_file++;
+  cur_file->file= opened;
+  cur_file->file_name= my_strdup(name, MYF(MY_FAE));
+  cur_file->lineno=1;
+  return true;
+}
+
+
+void open_file(const char *name)
 {
   char buff[FN_REFLEN];
   size_t length;
+  const char *curname= cur_file->file_name;
   DBUG_ENTER("open_file");
   DBUG_PRINT("enter", ("name: %s", name));
 
-  /* Extract path from current file and try it as base first */
-  if (dirname_part(buff, cur_file->file_name, &length))
+  if (cur_file == file_stack_end)
+    die("Source directives are nesting too deep");
+
+  if (test_if_hard_path(name))
   {
-    strxmov(buff, buff, name, NullS);
-    if (access(buff, F_OK) == 0){
-      DBUG_PRINT("info", ("The file exists"));
-      name= buff;
-    }
+    if (open_and_set_current(name))
+      DBUG_VOID_RETURN;
   }
-  if (!test_if_hard_path(name))
+  else
   {
-    strxmov(buff, opt_basedir, name, NullS);
-    name=buff;
-  }
-  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
+    /*
+      if overlay-dir is specified, and the file is located somewhere
+      under overlay-dir or under suite-dir, the search works as follows:
+
+      0.let suffix be current file dirname relative to siute-dir or overlay-dir
+      1.try in overlay-dir/suffix
+      2.try in suite-dir/suffix
+      3.try in overlay-dir
+      4.try in suite-dir
+      5.try in basedir
+
+        consider an example: 'rty' overlay of the 'qwe' suite,
+        file qwe/include/some.inc contains the line
+          --source thing.inc
+        we look for it in this order:
+        0.suffix is "include/"
+        1.try in rty/include/thing.inc
+        2.try in qwe/include/thing.inc
+        3.try in try/thing.inc             | this is useful when t/a.test has
+        4.try in qwe/thing.inc             | source include/b.inc;
+        5.try in mysql-test/include/thing.inc
+
+      otherwise the search is as follows
+      1.try in current file dirname
+      3.try in overlay-dir (if any)
+      4.try in suite-dir
+      5.try in basedir
+    */
 
-  if (cur_file == file_stack_end)
-    die("Source directives are nesting too deep");
-  cur_file++;
-  if (!(cur_file->file = fopen(buff, "rb")))
-  {
-    cur_file--;
-    die("Could not open '%s' for reading, errno: %d", buff, errno);
+    bool in_overlay= opt_overlay_dir &&
+                     !strncmp(curname, opt_overlay_dir, overlay_dir_len);
+    bool in_suiteir= opt_overlay_dir && !in_overlay &&
+                     !strncmp(curname, opt_suite_dir, suite_dir_len);
+    if (in_overlay || in_suiteir)
+    {
+      size_t prefix_len = in_overlay ? overlay_dir_len : suite_dir_len;
+      char buf2[FN_REFLEN], *suffix= buf2 + prefix_len;
+      dirname_part(buf2, curname, &length);
+
+      /* 1. first we look in the overlay dir */
+      strxnmov(buff, sizeof(buff), opt_overlay_dir, suffix, name, NullS);
+
+      /*
+        Overlayed rty/include/thing.inc can contain the line
+        --source thing.inc
+        which would mean to include qwe/include/thing.inc.
+        But it looks like including "itself", so don't try to open the file,
+        if buff contains the same file name as curname.
+      */
+      if (strcmp(buff, curname) && open_and_set_current(buff))
+        DBUG_VOID_RETURN;
+
+      /* 2. if that failed, we look in the suite dir */
+      strxnmov(buff, sizeof(buff), opt_suite_dir, suffix, name, NullS);
+
+      /* buff can not be equal to curname, as a file can never include itself */
+      if (open_and_set_current(buff))
+        DBUG_VOID_RETURN;
+    }
+    else
+    {
+      /* 1. try in current file dirname */
+      dirname_part(buff, curname, &length);
+      strxnmov(buff, sizeof(buff), buff, name, NullS);
+      if (open_and_set_current(buff))
+        DBUG_VOID_RETURN;
+    }
+
+    /* 3. now, look in the overlay dir */
+    if (opt_overlay_dir)
+    {
+      strxmov(buff, opt_overlay_dir, name, NullS);
+      if (open_and_set_current(buff))
+        DBUG_VOID_RETURN;
+    }
+
+    /* 4. if that failed - look in the suite dir */
+    strxmov(buff, opt_suite_dir, name, NullS);
+    if (open_and_set_current(buff))
+      DBUG_VOID_RETURN;
+    
+    /* 5. the last resort - look in the base dir */
+    strxnmov(buff, sizeof(buff), opt_basedir, name, NullS);
+    if (open_and_set_current(buff))
+      DBUG_VOID_RETURN;
   }
-  cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
-  cur_file->lineno=1;
-  DBUG_RETURN(0);
+
+  die("Could not open '%s' for reading, errno: %d", name, errno);
+  DBUG_VOID_RETURN;
 }
 
 
@@ -6584,13 +6669,13 @@ static struct my_option my_long_options[] =
    0, 0, 0, 0, 0, 0},
   {"basedir", 'b', "Basedir for tests.", &opt_basedir,
    &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-  {"character-sets-dir", OPT_CHARSETS_DIR,
+  {"character-sets-dir", 0,
    "Directory for character set files.", &opt_charsets_dir,
    &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"compress", 'C', "Use the compressed server/client protocol.",
    &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
    0, 0, 0},
-  {"cursor-protocol", OPT_CURSOR_PROTOCOL, "Use cursors for prepared statements.",
+  {"cursor-protocol", 0, "Use cursors for prepared statements.",
    &cursor_protocol, &cursor_protocol, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"database", 'D', "Database to use.", &opt_db, &opt_db, 0,
@@ -6602,27 +6687,27 @@ static struct my_option my_long_options[] =
   {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
    0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 #endif
-  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
+  {"debug-check", 0, "Check memory and open file usage at exit.",
    &debug_check_flag, &debug_check_flag, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
+  {"debug-info", 0, "Print some debug info at exit.",
    &debug_info_flag, &debug_info_flag,
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"host", 'h', "Connect to host.", &opt_host, &opt_host, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-  {"include", 'i', "Include SQL before each test case.", &opt_include,
-   &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"prologue", 0, "Include SQL before each test case.", &opt_prologue,
+   &opt_prologue, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"logdir", OPT_LOG_DIR, "Directory for log files", &opt_logdir,
    &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-  {"mark-progress", OPT_MARK_PROGRESS,
+  {"mark-progress", 0,
    "Write line number and elapsed time to <testname>.progress.",
    &opt_mark_progress, &opt_mark_progress, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-  {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
+  {"max-connect-retries", 0,
    "Maximum number of attempts to connect to server.",
    &opt_max_connect_retries, &opt_max_connect_retries, 0,
    GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
-  {"max-connections", OPT_MAX_CONNECTIONS,
+  {"max-connections", 0,
    "Max number of open connections to server",
    &opt_max_connections, &opt_max_connections, 0,
    GET_INT, REQUIRED_ARG, DEFAULT_MAX_CONN, 8, 5120, 0, 0, 0},
@@ -6637,11 +6722,11 @@ static struct my_option my_long_options[] =
 #endif
    "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
    &opt_port, &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-  {"ps-protocol", OPT_PS_PROTOCOL, 
+  {"ps-protocol", 0, 
    "Use prepared-statement protocol for communication.",
    &ps_protocol, &ps_protocol, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-  {"non-blocking-api", OPT_NON_BLOCKING_API,
+  {"non-blocking-api", 0,
    "Use the non-blocking client API for communication.",
    &non_blocking_api_enabled, &non_blocking_api_enabled, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -6661,7 +6746,7 @@ static struct my_option my_long_options[] =
    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"server-file", 'F', "Read embedded server arguments from file.",
    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
+  {"shared-memory-base-name", 0,
    "Base name of shared memory.", &shared_memory_base_name, 
    &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 
    0, 0, 0},
@@ -6673,11 +6758,11 @@ static struct my_option my_long_options[] =
   {"socket", 'S', "The socket file to use for connection.",
    &unix_sock, &unix_sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
    0, 0, 0},
-  {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select.",
+  {"sp-protocol", 0, "Use stored procedures for select.",
    &sp_protocol, &sp_protocol, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 #include "sslopt-longopts.h"
-  {"tail-lines", OPT_TAIL_LINES,
+  {"tail-lines", 0,
    "Number of lines of the result to include in a failure report.",
    &opt_tail_lines, &opt_tail_lines, 0,
    GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
@@ -6693,16 +6778,20 @@ static struct my_option my_long_options[] =
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"version", 'V', "Output version information and exit.",
    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-  {"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select.",
+  {"view-protocol", 0, "Use views for select.",
    &view_protocol, &view_protocol, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-  {"connect_timeout", OPT_CONNECT_TIMEOUT,
+  {"connect_timeout", 0,
    "Number of seconds before connection timeout.",
    &opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG,
    120, 0, 3600 * 12, 0, 0, 0},
-  {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+  {"plugin_dir", 0, "Directory for client-side plugins.",
     &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"overlay-dir", 0, "Overlay directory.", &opt_overlay_dir,
+    &opt_overlay_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"suite-dir", 0, "Suite directory.", &opt_suite_dir,
+    &opt_suite_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
@@ -6908,6 +6997,11 @@ int parse_args(int argc, char **argv)
     memcpy(global_subst_to, comma+1, strlen(comma));
   }
 
+  if (!opt_suite_dir)
+    opt_suite_dir= "./";
+  suite_dir_len= strlen(opt_suite_dir);
+  overlay_dir_len= opt_overlay_dir ? strlen(opt_overlay_dir) : 0;
+
   if (!record)
   {
     /* Check that the result file exists */
@@ -8738,9 +8832,9 @@ int main(int argc, char **argv)
 
   set_current_connection(con);
 
-  if (opt_include)
+  if (opt_prologue)
   {
-    open_file(opt_include);
+    open_file(opt_prologue);
   }
 
   verbose_msg("Start processing test commands from '%s' ...", cur_file->file_name);
diff --git a/mysql-test/README.suites b/mysql-test/README.suites
index a78134e44c3dbe7626482912a922d3fe602a6f2f..13422990791f0832c95127c9a154844fa4c92eb6 100644
--- a/mysql-test/README.suites
+++ b/mysql-test/README.suites
@@ -133,7 +133,6 @@ and values - with templating extensions. They are
     to values in the [ENV] group of my.cnf file.
 
   Via the OPT group one can refer to special values:
-    @OPT.plugindir - a path to plugindir
     @OPT.vardir - a path to vardir
     @OPT.port - a new port number is reserved out of the pool. It will not
                 match any other port number used by this test run.
diff --git a/mysql-test/t/disabled.def b/mysql-test/disabled.def
similarity index 100%
rename from mysql-test/t/disabled.def
rename to mysql-test/disabled.def
diff --git a/mysql-test/include/check_ipv6.inc b/mysql-test/include/check_ipv6.inc
index f9a61f1661e47723fc010ab5df9594a9f9d23456..9b4fa16bbd992c612f85867e682f1492fc52a80b 100644
--- a/mysql-test/include/check_ipv6.inc
+++ b/mysql-test/include/check_ipv6.inc
@@ -1,6 +1,5 @@
 # Check if ipv6 is available.
 #
-# The real test is done in the mysql-test-run.pl
+# The real check is done in the suite.pm
 # (it has to be done *before* mysqld is started)
-# This file only signals mysql-test-run.pl that ipv6 support is needed
 #
diff --git a/mysql-test/include/default_client.cnf b/mysql-test/include/default_client.cnf
index c9acd2d6b58d1dde6ca6d19d2e28cb1602c90638..bcd6a4849d2a2df57f82f59895eb563b7721d3fd 100644
--- a/mysql-test/include/default_client.cnf
+++ b/mysql-test/include/default_client.cnf
@@ -4,7 +4,7 @@
 #
 
 [client]
-plugin-dir=@OPT.plugindir
+plugin-dir=@mysqld.1.plugin-dir
 
 [mysql]
 default-character-set=latin1
diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf
index 06830dce669239c56b98ed28ae182ba133b2ba6d..74fcfc0e39742ee22ce278fb0266fda9c43dc73d 100644
--- a/mysql-test/include/default_mysqld.cnf
+++ b/mysql-test/include/default_mysqld.cnf
@@ -23,21 +23,19 @@ character-set-server=      latin1
 # disconnects when test servers are put under load see BUG#28359
 connect-timeout=            60
 
-plugin-dir=@OPT.plugindir
 secure-file-priv= @OPT.vardir
 
 log-basename=mysqld
 debug-no-sync
 
+# Retry bind as this may fail on busy server
+port-open-timeout=10
+
 log-bin-trust-function-creators=1
 key_buffer_size=            1M
 sort_buffer=                256K
 max_heap_table_size=        1M
 
-loose-skip-innodb
-loose-skip-pbxt
-loose-skip-federated
-loose-skip-feedback
 loose-feedback-user-info=  mysql-test
 
 loose-innodb_data_file_path=      ibdata1:10M:autoextend
@@ -61,3 +59,20 @@ loose-performance-schema-max-table-instances=500
 loose-performance-schema-max-table-handles=1000
 
 binlog-direct-non-transactional-updates
+
+# here, at the end of [mysqld] group mtr will automatically disable
+# all optional plugins.
+
+[embedded]
+# mtr automatically adds [embedded] group at the end and copies [mysqld]
+# and [mysqld.1] groups into it.
+# but we want [server] group to be after [mysqld] (and its copies).
+# create a non-empty [embedded] group here, to force it before [server]
+local-infile
+
+[server]
+# Aria is optional, but it must be enabled if it's used for temporary
+# tables.  Let's enable it in the [server] group, because this group
+# is read after [mysqld] and [embedded]
+loose-aria
+
diff --git a/mysql-test/include/have_debug.inc b/mysql-test/include/have_debug.inc
index 6f3a82881f5037d20af4b919b2168077e53882a2..5432f7dfa7e19ff7faa985e6276ef34adef27d7e 100644
--- a/mysql-test/include/have_debug.inc
+++ b/mysql-test/include/have_debug.inc
@@ -1,3 +1,9 @@
+#
+# suite.pm will make sure that all tests including this file
+# will be skipped unless this is a debug build.
+#
+# The test below is redundant
+
 -- require r/have_debug.require
 disable_query_log;
 select (version() like '%debug%') as debug;
diff --git a/mysql-test/include/have_innodb.combinations b/mysql-test/include/have_innodb.combinations
index 5051719d92a40b4e7c459c8cc53f4979f64be2b2..117bf2216a175d5eb3402dc4ab87eb389a074672 100644
--- a/mysql-test/include/have_innodb.combinations
+++ b/mysql-test/include/have_innodb.combinations
@@ -2,11 +2,17 @@
 ignore-builtin-innodb
 plugin-load=$HA_INNODB_SO
 innodb
+innodb-cmpmem
+innodb-trx
 
 [xtradb_plugin]
 ignore-builtin-innodb
 plugin-load=$HA_XTRADB_SO
 innodb
+innodb-cmpmem
+innodb-trx
 
 [xtradb]
 innodb
+innodb-cmpmem
+innodb-trx
diff --git a/mysql-test/include/have_innodb.inc b/mysql-test/include/have_innodb.inc
index fa3e586834cc2aadff03f6d99390bd68cc5713ff..021970423cd4a2640dbfbf7df9a98e59dc246964 100644
--- a/mysql-test/include/have_innodb.inc
+++ b/mysql-test/include/have_innodb.inc
@@ -1,3 +1,9 @@
+#
+# suite.pm will make sure that all tests including this file
+# will be skipped unless innodb or xtradb is enabled
+#
+# The test below is redundant
+
 if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED')`)
 {
   --skip Test requires InnoDB.
diff --git a/mysql-test/include/have_partition.opt b/mysql-test/include/have_partition.opt
new file mode 100644
index 0000000000000000000000000000000000000000..efbbfda392178edcd69b8d26a3c552a56eba102f
--- /dev/null
+++ b/mysql-test/include/have_partition.opt
@@ -0,0 +1 @@
+--enable-partition
diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql
index aa0d91a9cf8d33658f4d019a3cbd5a640aa1518c..bcbb9b94136e4ec7329183d6d9670137311c847c 100644
--- a/mysql-test/include/mtr_check.sql
+++ b/mysql-test/include/mtr_check.sql
@@ -74,5 +74,8 @@ BEGIN
     mysql.time_zone_transition_type,
     mysql.user;
 
+  -- verify that no plugin changed its disabled/enabled state
+  SELECT * FROM INFORMATION_SCHEMA.PLUGINS;
+
 END||
 
diff --git a/mysql-test/include/not_embedded.inc b/mysql-test/include/not_embedded.inc
index 360f268ad4f86a445fb9954936ecc7b98819630b..c3a9c3e12c803c710919b0493649cab3d655db81 100644
--- a/mysql-test/include/not_embedded.inc
+++ b/mysql-test/include/not_embedded.inc
@@ -1,3 +1,9 @@
+#
+# suite.pm will make sure that all tests including this file
+# will be skipped unless this is an embedded test run
+#
+# The test below is redundant
+
 -- require r/not_embedded.require
 disable_query_log;
 select version() like '%embedded%' as 'have_embedded';
diff --git a/mysql-test/lib/My/Config.pm b/mysql-test/lib/My/Config.pm
index 5274620ef95553a3bf5b6fe344420e6db5ecfbce..1d8d1617fce33826c40e1cc4e90c9daaa2ccad69 100644
--- a/mysql-test/lib/My/Config.pm
+++ b/mysql-test/lib/My/Config.pm
@@ -164,9 +164,6 @@ sub value {
   return $option->value();
 }
 
-
-sub auto { 0 };
-
 #
 # Return value for an option if it exist
 #
@@ -191,8 +188,6 @@ sub new {
   bless My::Config::Group->new($group_name), $class;
 }
 
-sub auto { 1 };
-
 #
 # Return value for an option in the group, fail if it does not exist
 #
@@ -218,8 +213,6 @@ use strict;
 use warnings;
 use Carp;
 
-sub auto { 1 };
-
 sub new {
   my ($class, $group_name)= @_;
   bless My::Config::Group->new($group_name), $class;
@@ -442,6 +435,17 @@ sub groups {
 }
 
 
+#
+# Return a list with "real" groups in config, those
+# that should be written to a my.cnf file, those that contain options.
+# Same as groups() but without auto-generated groups like ENV or OPT.
+#
+sub option_groups {
+  my ($self)= @_;
+  return ( grep { ref $_ eq 'My::Config::Group' } @{$self->{groups}} );
+}
+
+
 #
 # Return a list of all the groups in config
 # starting with the given string
diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm
index 3e6221f5e4ca12c2b4034b5730e85c9ef0c966cf..ca93cbc543ab2f36716cbce93d8693184a810560 100644
--- a/mysql-test/lib/My/ConfigFactory.pm
+++ b/mysql-test/lib/My/ConfigFactory.pm
@@ -31,8 +31,19 @@ use File::Basename;
 #
 # Rules to run first of all
 #
+
+sub add_opt_values {
+  my ($self, $config)= @_;
+
+  # add auto-options
+  $config->insert('OPT', 'port'   => sub { fix_port($self, $config) });
+  $config->insert('OPT', 'vardir' => sub { $self->{ARGS}->{vardir} });
+  $config->insert('mysqld', "loose-skip-$_" => undef) for (@::optional_plugins);
+}
+
 my @pre_rules=
 (
+  \&add_opt_values,
 );
 
 
@@ -230,9 +241,10 @@ my @mysqld_rules=
  { 'port' => \&fix_port },
  { 'socket' => \&fix_socket },
  { '#log-error' => \&fix_log_error },
- { 'general-log' => sub { return 1; } },
+ { 'general-log' => 1 },
+ { 'plugin-dir' => sub { $::plugindir } },
  { 'general-log-file' => \&fix_log },
- { 'slow-query-log' => sub { return 1; } },
+ { 'slow-query-log' => 1 },
  { 'slow-query-log-file' => \&fix_log_slow_queries },
  { '#user' => sub { return shift->{ARGS}->{user} || ""; } },
  { '#password' => sub { return shift->{ARGS}->{password} || ""; } },
@@ -432,7 +444,7 @@ sub post_check_embedded_group {
   my $first_mysqld= $config->first_like('mysqld.') or
     croak "Can't run with embedded, config has no mysqld";
 
-  my @no_copy =
+  my %no_copy = map { $_ => 1 }
     (
      '#log-error', # Embedded server writes stderr to mysqltest's log file
      'slave-net-timeout', # Embedded server are not build with replication
@@ -441,7 +453,7 @@ sub post_check_embedded_group {
 
   foreach my $option ( $mysqld->options(), $first_mysqld->options() ) {
     # Don't copy options whose name is in "no_copy" list
-    next if grep ( $option->name() eq $_, @no_copy);
+    next if $no_copy{$option->name()};
 
     $config->insert('embedded', $option->name(), $option->value())
   }
@@ -632,19 +644,11 @@ sub new_config {
                    testname     => $args->{testname},
 		  }, $class;
 
-  # add auto-options
-  $config->insert('OPT', 'port'   => sub { fix_port($self, $config) });
-  $config->insert('OPT', 'vardir' => sub { $self->{ARGS}->{vardir} });
-  $config->insert('OPT', 'plugindir' => sub { $::plugindir });
-
-  {
-    # Run pre rules
-    foreach my $rule ( @pre_rules ) {
-      &$rule($self, $config);
-    }
+  # Run pre rules
+  foreach my $rule ( @pre_rules ) {
+    &$rule($self, $config);
   }
 
-
   $self->run_section_rules($config,
 			   'cluster_config\.\w*$',
 			   @cluster_config_rules);
diff --git a/mysql-test/lib/My/Find.pm b/mysql-test/lib/My/Find.pm
index bd153becaf76b48a185d36497d3c97ed656e0b95..1d5e0f368bca82973eba5b55e97089374d99b942 100644
--- a/mysql-test/lib/My/Find.pm
+++ b/mysql-test/lib/My/Find.pm
@@ -64,7 +64,7 @@ sub my_find_bin {
   # -------------------------------------------------------
   # Find and return the first executable
   # -------------------------------------------------------
-  foreach my $path (my_find_paths($base, $paths, $names, $bin_extension)) {
+  foreach my $path (my_build_path_list($base, $paths, $names, $bin_extension)) {
     return $path if ( -x $path or (IS_WINDOWS and -f $path) );
   }
   if (defined $required and $required == NOT_REQUIRED){
@@ -98,7 +98,7 @@ sub my_find_file {
   # -------------------------------------------------------
   # Find and return the first executable
   # -------------------------------------------------------
-  foreach my $path (my_find_paths($base, $paths, $names, $bin_extension)) {
+  foreach my $path (my_build_path_list($base, $paths, $names, $bin_extension)) {
     return $path if ( -f $path );
   }
   if (defined $required and $required == NOT_REQUIRED){
@@ -110,8 +110,9 @@ sub my_find_file {
 
 
 #
-# my_find_dir - find the first existing directory in one of
-# the given paths
+# my_find_dir - find the existing directories in one of
+# the given paths. Returns the first found in the scalar context
+# and all of them in the list context.
 #
 # Example:
 #    my $charset_set= my_find_dir($basedir,
@@ -127,20 +128,22 @@ sub my_find_file {
 #
 sub my_find_dir {
   my ($base, $paths, $dirs, $required)= @_;
-  croak "usage: my_find_dir(<base>, <paths>[, <dirs>])"
-    unless (@_ == 3 or @_ == 2);
-
-  # -------------------------------------------------------
-  # Find and return the first directory
-  # -------------------------------------------------------
-  foreach my $path (my_find_paths($base, $paths, $dirs)) {
-    return $path if ( -d $path );
+  croak "usage: my_find_dir(<base>, <paths>[, <dirs>[, <required>]])"
+    unless (@_ >= 2 and @_ <= 4);
+
+  my @all;
+  foreach my $path (my_build_path_list($base, $paths, $dirs)) {
+    next unless -d $path;
+    return $path unless wantarray;
+    push @all, $path;
   }
+  return @all if @all;
+  return wantarray ? () : "" if defined $required and $required == NOT_REQUIRED;
   find_error($base, $paths, $dirs);
 }
 
 
-sub my_find_paths {
+sub my_build_path_list {
   my ($base, $paths, $names, $extension)= @_;
 
   # Convert the arguments into two normal arrays to ease
@@ -237,7 +240,7 @@ sub find_error {
 
   croak "** ERROR: Could not find ",
     commify(fnuttify(@names)), " in ",
-      commify(fnuttify(my_find_paths($base, $paths, $names))), "\n";
+      commify(fnuttify(my_build_path_list($base, $paths, $names))), "\n";
 }
 
 1;
diff --git a/mysql-test/lib/My/Suite.pm b/mysql-test/lib/My/Suite.pm
index 948187da1e59a60627eca4758649e85d2f5e4415..b5870ea1e1649bf29ffdb2a13c8f2e93a89d6237 100644
--- a/mysql-test/lib/My/Suite.pm
+++ b/mysql-test/lib/My/Suite.pm
@@ -7,9 +7,11 @@ sub config_files { () }
 sub servers { () }
 sub skip_combinations { () }
 
+sub new { bless { } }
+
 sub list_cases {
   my ($self, $testdir) = @_;
-  opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!");
+  opendir(TESTDIR, $testdir) or return ();
   my (@cases) = grep { s/\.test$// } readdir TESTDIR;
   closedir TESTDIR;
   @cases;
diff --git a/mysql-test/lib/My/Test.pm b/mysql-test/lib/My/Test.pm
index 735e8db5485b09d9546714cce6b208d1989528f4..2d2bac3be03d25c32a4d3c4856f40cf41e74f7fd 100644
--- a/mysql-test/lib/My/Test.pm
+++ b/mysql-test/lib/My/Test.pm
@@ -40,7 +40,7 @@ sub copy {
   my $copy= My::Test->new();
   while (my ($key, $value) = each(%$self)) {
     if (ref $value eq "ARRAY") {
-      push(@{$copy->{$key}}, @$value);
+      $copy->{$key} = [ @$value ];
     } else {
       $copy->{$key}= $value;
     }
diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm
index c412ad08da3b8f03142c3591276aab74132755cd..11c8b2a6b35579e65d68bf6f6c0197838997e68c 100644
--- a/mysql-test/lib/mtr_cases.pm
+++ b/mysql-test/lib/mtr_cases.pm
@@ -36,7 +36,6 @@ our $binlog_format;
 our $enable_disabled;
 our $default_storage_engine;
 our $opt_with_ndbcluster_only;
-our $defaults_file;
 
 sub collect_option {
   my ($opt, $value)= @_;
@@ -109,7 +108,7 @@ sub collect_test_cases ($$$$) {
   {
     foreach my $suite (split(",", $suites))
     {
-      push(@$cases, collect_one_suite($suite, $opt_cases, $opt_skip_test_list));
+      push(@$cases, collect_one_suite($suite, $opt_cases));
     }
   }
 
@@ -137,7 +136,7 @@ sub collect_test_cases ($$$$) {
 	$sname= "main" if !$opt_reorder and !$sname;
 	mtr_error("Could not find '$tname' in '$suites' suite(s)") unless $sname;
 	# If suite was part of name, find it there, may come with combinations
-	my @this_case = collect_one_suite($sname, [ $tname ]);
+	my @this_case = collect_one_suite($sname, [ $test_name_spec ]);
 	if (@this_case)
         {
 	  push (@$cases, @this_case);
@@ -152,9 +151,6 @@ sub collect_test_cases ($$$$) {
 
   if ( $opt_reorder )
   {
-    # Reorder the test cases in an order that will make them faster to run
-    my %sort_criteria;
-
     # Make a mapping of test name to a string that represents how that test
     # should be sorted among the other tests.  Put the most important criterion
     # first, then a sub-criterion, then sub-sub-criterion, etc.
@@ -163,9 +159,12 @@ sub collect_test_cases ($$$$) {
       my @criteria = ();
 
       #
-      # Append the criteria for sorting, in order of importance.
+      # Collect the criteria for sorting, in order of importance.
+      # Note that criteria are also used in mysql-test-run.pl to
+      # schedule tests to workers, and it preferres tests that have
+      # *identical* criteria. That is, test name is *not* part of
+      # the criteria, but it's part of the sorting function below.
       #
-      push @criteria, ($tinfo->{'long_test'} ? "long" : "short");
       push(@criteria, $tinfo->{template_path});
       for (qw(master_opt slave_opt)) {
         # Group test with equal options together.
@@ -173,11 +172,15 @@ sub collect_test_cases ($$$$) {
         my $opts= $tinfo->{$_} ? $tinfo->{$_} : [];
         push(@criteria, join("!", sort @{$opts}) . "~");
       }
-      push @criteria, $tinfo->{name};
       $tinfo->{criteria}= join(" ", @criteria);
     }
 
-    @$cases = sort { $a->{criteria} cmp $b->{criteria} } @$cases;
+    @$cases = sort {                            # ORDER BY
+      $b->{skip} <=> $a->{skip}           ||    #   skipped DESC,
+      $a->{criteria} cmp $b->{criteria}   ||    #   criteria ASC,
+      $b->{long_test} <=> $a->{long_test} ||    #   long_test DESC,
+      $a->{name} cmp $b->{name}                 #   name ASC
+    } @$cases;
   }
 
   return $cases;
@@ -214,8 +217,12 @@ sub split_testname {
   mtr_error("Illegal format of test name: $test_name");
 }
 
-my %skip_combinations;
-my %file_combinations;
+our %file_to_tags;
+our %file_to_master_opts;
+our %file_to_slave_opts;
+our %file_combinations;
+our %skip_combinations;
+our %file_in_overlay;
 
 sub load_suite_object {
   my ($suitename, $suitedir) = @_;
@@ -225,11 +232,11 @@ sub load_suite_object {
       $suite= do "$suitedir/suite.pm";
       unless (ref $suite) {
         my $comment = $suite;
-        $suite = do 'My/Suite.pm';
+        $suite = My::Suite->new();
         $suite->{skip} = $comment;
       }
     } else {
-      $suite = do 'My/Suite.pm';
+      $suite = My::Suite->new();
     }
 
     $suites{$suitename} = $suite;
@@ -238,7 +245,12 @@ sub load_suite_object {
     # with only one lookup
     my %suite_skiplist = $suite->skip_combinations();
     while (my ($file, $skiplist) = each %suite_skiplist) {
-      $skip_combinations{"$suitedir/$file => $_"} = 1 for (@$skiplist);
+      $file =~ s/\.\w+$/\.combinations/;
+      if (ref $skiplist) {
+        $skip_combinations{"$suitedir/$file => $_"} = 1 for (@$skiplist);
+      } else {
+        $skip_combinations{"$suitedir/$file"} = $skiplist;
+      }
     }
   }
   return $suites{$suitename};
@@ -246,36 +258,36 @@ sub load_suite_object {
 
 
 # returns a pair of (suite, suitedir)
-sub find_suite_of_file($) {
+sub load_suite_for_file($) {
   my ($file) = @_;
-  return ($2, $1)
+  return load_suite_object($2, $1)
     if $file =~ m@^(.*/(?:storage|plugin)/\w+/mysql-test/(\w+))/@;
-  return ($2, $1) if $file =~ m@^(.*/mysql-test/suite/(\w+))/@;
-  return ('main', $1) if $file =~ m@^(.*/mysql-test)/@;
+  return load_suite_object($2, $1) if $file =~ m@^(.*/mysql-test/suite/(\w+))/@;
+  return load_suite_object('main', $1) if $file =~ m@^(.*/mysql-test)/@;
   mtr_error("Cannot determine suite for $file");
 }
 
-sub combinations_from_file($)
+sub combinations_from_file($$)
 {
-  my ($filename) = @_;
-  return () if @::opt_combinations or not -f $filename;
-
-  # check the suite object, and load its %skip_combinations
-  my $suite = load_suite_object(find_suite_of_file($filename));
-  return () if $suite->{skip}; # XXX
-
-  # Read combinations file in my.cnf format
-  mtr_verbose("Read combinations file");
-  my $config= My::Config->new($filename);
+  my ($in_overlay, $filename) = @_;
   my @combs;
-  foreach my $group ($config->groups()) {
-    next if $group->auto();
-    my $comb= { name => $group->name() };
-    next if $skip_combinations{"$filename => $comb->{name}"}; # XXX
-    foreach my $option ( $group->options() ) {
-      push(@{$comb->{comb_opt}}, $option->option());
+  if ($skip_combinations{$filename}) {
+    @combs = ({ skip => $skip_combinations{$filename} });
+  } else {
+    return () if @::opt_combinations or not -f $filename;
+    # Read combinations file in my.cnf format
+    mtr_verbose("Read combinations file");
+    my $config= My::Config->new($filename);
+    foreach my $group ($config->option_groups()) {
+      my $comb= { name => $group->name(), comb_opt => [] };
+      next if $skip_combinations{"$filename => $comb->{name}"};
+      foreach my $option ( $group->options() ) {
+        push(@{$comb->{comb_opt}}, $option->option());
+      }
+      $comb->{in_overlay} = 1 if $in_overlay;
+      push @combs, $comb;
     }
-    push @combs, $comb;
+    @combs = ({ skip => 'Requires: ' . basename($filename, '.combinations') }) unless @combs;
   }
   @combs;
 }
@@ -302,12 +314,14 @@ sub collect_one_suite
 {
   my $suitename= shift;  # Test suite name
   my $opt_cases= shift;
-  my $opt_skip_test_list= shift;
-  my @cases; # Array of hash
+  my $over;
+
+  ($suitename, $over) = split '-', $suitename;
 
   mtr_verbose("Collecting: $suitename");
 
-  my $suitedir= "$::glob_mysql_test_dir"; # Default
+  my $suitedir= $::glob_mysql_test_dir; # Default
+  my @overlays = ();
   if ( $suitename ne "main" )
   {
     # Allow suite to be path to "some dir" if $suitename has at least
@@ -319,62 +333,108 @@ sub collect_one_suite
     }
     else
     {
-      $suitedir= my_find_dir($::basedir,
-			     ["share/mysql-test/suite",
-			      "share/mysql/mysql-test/suite",
-			      "mysql-test/suite",
-			      "mysql-test",
-			      # Look in storage engine specific suite dirs
-			      "storage/*/mtr",
-			      # Look in plugin specific suite dir
-			      "plugin/$suitename/tests",
-			     ],
-			     [$suitename]);
-    }
-    mtr_verbose("suitedir: $suitedir");
-  }
-
-  my $testdir= "$suitedir/t";
-  my $resdir=  "$suitedir/r";
-
-  # Check if t/ exists
-  if (-d $testdir){
-    # t/ exists
+      @overlays = my_find_dir($::basedir,
+                              ["mysql-test/suite",
+                               "storage/*/mysql-test",
+                               "plugin/*/mysql-test"],
+                              [$suitename]);
+      #
+      # XXX at the moment, for simplicity, we will not fully support one plugin
+      # overlaying a suite of another plugin. Only suites in the main
+      # mysql-test directory can be safely overlayed. To be fixed, when needed.
+      # To fix it we'll need a smarter overlay detection (that is, detection of
+      # what is an overlay and what is the "original" suite) than simply
+      # "prefer directories with more files".
+      #
 
-    if ( -d $resdir )
-    {
-      # r/exists
-    }
-    else
-    {
-      # No r/, use t/ as result dir
-      $resdir= $testdir;
+      if ($overlays[0] !~ m@/mysql-test/suite/$suitename$@) {
+        # prefer directories with more files
+        @overlays = sort { scalar(<$a/*>) <=> scalar(<$b/*>) } @overlays;
+      }
+      $suitedir = shift @overlays;
     }
-
+  } else {
+    @overlays = my_find_dir($::basedir,
+                            ["storage/*/mysql-test",
+                             "plugin/*/mysql-test"],
+                            ['main'], NOT_REQUIRED);
   }
-  else {
-    # No t/ dir => there can' be any r/ dir
-    mtr_error("Can't have r/ dir without t/") if -d $resdir;
-
-    # No t/ or r/ => use suitedir
-    $resdir= $testdir= $suitedir;
+  mtr_verbose("suitedir: $suitedir");
+  mtr_verbose("overlays: @overlays") if @overlays;
+
+  # we always need to process the parent suite, even if we won't use any
+  # test from it.
+  my @cases= process_suite($suitename, undef, $suitedir,
+                           $over ? [ '*BOGUS*' ] : $opt_cases);
+
+  # when working with overlays we cannot use global caches like
+  # %file_to_tags. Because the same file may have different tags
+  # with and without overlays. For example, when a.test includes
+  # b.inc, which includes c.inc, and an overlay replaces c.inc.
+  # In this case b.inc may have different tags in the overlay,
+  # despite the fact that b.inc itself is not replaced.
+  for (@overlays) {
+    local %file_to_tags = ();
+    local %file_to_master_opts = ();
+    local %file_to_slave_opts = ();
+    local %file_combinations = ();
+    local %file_in_overlay = ();
+
+    die unless m@/(?:storage|plugin)/(\w+)/mysql-test/\w+$@;
+    next unless defined $over and ($over eq '' or $over eq $1);
+    push @cases, 
+    # don't add cases that take *all* data from the parent suite
+      grep { $_->{in_overlay} } process_suite($suitename, $1, $_, $opt_cases);
   }
+  return @cases;
+}
 
-  mtr_verbose("testdir: $testdir");
-  mtr_verbose("resdir: $resdir");
+sub process_suite {
+  my ($basename, $overname, $suitedir, $opt_cases) = @_;
+  my $suitename;
+  my $parent;
+
+  if ($overname) {
+    $parent = $suites{$basename};
+    die unless $parent;
+    $suitename = $basename . '-' . $overname;
+  } else {
+    $suitename = $basename;
+  }
 
   my $suite = load_suite_object($suitename, $suitedir);
 
   #
   # Read suite config files, unless it was done aleady
   #
-  unless (defined $suite->{dir}) {
-    $suite->{dir} = $suitedir;
-    $suite->{tdir} = $testdir;
-    $suite->{rdir} = $resdir;
+  unless (defined $suite->{name}) {
+    $suite->{name} = $suitename;
+    $suite->{dir}  = $suitedir;
+
+    # First, we need to find where the test files and result files are.
+    # test files are usually in a t/ dir inside suite dir. Or directly in the
+    # suite dir. result files are in a r/ dir or in the suite dir.
+    # Overlay uses t/ and r/ if and only if its parent does.
+    if ($parent) {
+      $suite->{parent} = $parent;
+      my $tdir = $parent->{tdir};
+      my $rdir = $parent->{rdir};
+      substr($tdir, 0, length $parent->{dir}) = $suitedir;
+      substr($rdir, 0, length $parent->{dir}) = $suitedir;
+      $suite->{tdir} = $tdir if -d $tdir;
+      $suite->{rdir} = $rdir if -d $rdir;
+    } else {
+      my $tdir= "$suitedir/t";
+      my $rdir= "$suitedir/r";
+      $suite->{tdir} = -d $tdir ? $tdir : $suitedir;
+      $suite->{rdir} = -d $rdir ? $rdir : $suite->{tdir};
+    }
+
+    mtr_verbose("testdir: " . $suite->{tdir});
+    mtr_verbose( "resdir: " . $suite->{rdir});
 
     # disabled.def
-    parse_disabled("$testdir/disabled.def", $suitename);
+    parse_disabled($suite->{dir} .'/disabled.def', $suitename);
 
     # combinations
     if (@::opt_combinations)
@@ -390,120 +450,52 @@ sub collect_one_suite
     }
     else
     {
-      my @combs = combinations_from_file("$suitedir/combinations");
+      my @combs;
+      @combs = combinations_from_file($parent, "$suitedir/combinations")
+        unless $suite->{skip};
       $suite->{combinations} = [ @combs ];
+      #  in overlays it's a union of parent's and overlay's files.
+      unshift @{$suite->{combinations}}, @{$parent->{combinations}} if $parent;
     }
 
     # suite.opt
+    #  in overlays it's a union of parent's and overlay's files.
     $suite->{opts} = [ opts_from_file("$suitedir/suite.opt") ];
+    $suite->{in_overlay} = 1 if $parent and @{$suite->{opts}};
+    unshift @{$suite->{opts}}, @{$parent->{opts}} if $parent;
+
+    $suite->{cases} = [ $suite->list_cases($suite->{tdir}) ];
   }
 
-  my @case_names= $suite->list_cases($testdir);
-
-  if ( @$opt_cases )
-  {
-    my (%case_names)= map { $_ => 1 } @case_names;
-    @case_names= ();
+  my %all_cases;
+  %all_cases = map { $_ => $parent->{tdir} } @{$parent->{cases}} if $parent;
+  $all_cases{$_} = $suite->{tdir} for @{$suite->{cases}};
 
+  my @cases;
+  if (@$opt_cases) {
     # Collect in specified order
     foreach my $test_name_spec ( @$opt_cases )
     {
       my ($sname, $tname)= split_testname($test_name_spec);
 
       # Check correct suite if suitename is defined
-      next if (defined $sname and $suitename ne $sname);
-
-      if (not $case_names{$tname})
-      {
-        # This is only an error if suite was specified, otherwise it
-        # could exist in another suite
-        mtr_error("Test '$tname' was not found in suite '$sname'")
-          if $sname;
+      next if defined $sname and $sname ne $suitename
+                             and $sname ne "$basename-";
 
-        next;
-      }
-      push @case_names, $tname;
+      next unless $all_cases{$tname};
+      push @cases, collect_one_test_case($suite, $all_cases{$tname}, $tname);
     }
-  }
-
-  foreach (@case_names)
-  {
-    # Skip tests that do not match the --do-test= filter
-    next if ($do_test_reg and not $_ =~ /$do_test_reg/o);
-
-    push @cases, collect_one_test_case($suitename, $_);
-  }
-
-  #  Return empty list if no testcases found
-  return if (@cases == 0);
-
-  optimize_cases(\@cases);
-
-  return @cases;
-}
-
-
-
-#
-# Loop through all test cases
-# - optimize which test to run by skipping unnecessary ones
-# - update settings if necessary
-#
-sub optimize_cases {
-  my ($cases)= @_;
-
-  my @new_cases= ();
-
-  foreach my $tinfo ( @$cases )
-  {
-    push @new_cases, $tinfo;
-
-    # Skip processing if already marked as skipped
-    next if $tinfo->{skip};
-
-    # =======================================================
-    # Check that engine selected by
-    # --default-storage-engine=<engine> is supported
-    # =======================================================
-
-    #
-    # mandatory engines cannot be disabled with --skip-FOO.
-    # That is, --FOO switch does not exist, and mtr cannot detect
-    # if the engine is available.
-    #
-    my %mandatory_engines = ('myisam' => 1, 'memory' => 1, 'csv' => 1);
-
-    foreach my $opt ( @{$tinfo->{master_opt}} ) {
-      my $default_engine=
-	mtr_match_prefix($opt, "--default-storage-engine=");
-
-      # Allow use of uppercase, convert to all lower case
-      $default_engine =~ tr/A-Z/a-z/;
-
-      if (defined $default_engine){
-
-	#print " $tinfo->{name}\n";
-	#print " - The test asked to use '$default_engine'\n";
-
-	#my $engine_value= $::mysqld_variables{$default_engine};
-	#print " - The mysqld_variables says '$engine_value'\n";
-
-	if ( ! exists $::mysqld_variables{$default_engine} and
-	     ! exists $mandatory_engines{$default_engine} )
-	{
-	  $tinfo->{'skip'}= 1;
-	  $tinfo->{'comment'}=
-	    "'$default_engine' not supported";
-	}
-
-	$tinfo->{'ndb_test'}= 1
-	  if ( $default_engine =~ /^ndb/i );
-      }
+  } else {
+    for (sort keys %all_cases)
+    {
+      # Skip tests that do not match the --do-test= filter
+      next if $do_test_reg and not /$do_test_reg/o;
+      push @cases, collect_one_test_case($suite, $all_cases{$_}, $_);
     }
   }
-  @$cases= @new_cases;
-}
 
+  @cases;
+}
 
 #
 # Read options from the given opt file and append them as an array
@@ -549,6 +541,12 @@ sub make_combinations($@)
   my ($test, @combinations) = @_;
 
   return ($test) if $test->{'skip'} or not @combinations;
+  if ($combinations[0]->{skip}) {
+    $test->{skip} = 1;
+    $test->{comment} = $combinations[0]->{skip} unless $test->{comment};
+    die unless @combinations == 1;
+    return ($test);
+  }
 
   foreach my $comb (@combinations)
   {
@@ -578,6 +576,8 @@ sub make_combinations($@)
     # Add combination name short name
     push @{$new_test->{combinations}}, $comb->{name};
 
+    $new_test->{in_overlay} = 1 if $comb->{in_overlay};
+
     # Add the new test to new test cases list
     push(@cases, $new_test);
   }
@@ -585,6 +585,23 @@ sub make_combinations($@)
 }
 
 
+sub find_file_in_dirs
+{
+  my ($tinfo, $slot, $filename) = @_;
+  my $parent = $tinfo->{suite}->{parent};
+  my $f = $tinfo->{suite}->{$slot} . '/' . $filename;
+
+  if (-f $f) {
+    $tinfo->{in_overlay} = 1 if $parent;
+    return $f;
+  }
+
+  return undef unless $parent;
+
+  $f = $parent->{$slot} . '/' . $filename;
+  return -f $f ? $f : undef;
+}
+
 ##############################################################################
 #
 #  Collect information about a single test case
@@ -592,15 +609,13 @@ sub make_combinations($@)
 ##############################################################################
 
 sub collect_one_test_case {
-  my $suitename=  shift;
-  my $tname=      shift;
+  my $suite     =  shift;
+  my $tpath     =  shift;
+  my $tname     =  shift;
 
-  my $name     = "$suitename.$tname";
-  my $suite    =  $suites{$suitename};
-  my $suitedir =  $suite->{dir};
-  my $testdir  =  $suite->{tdir};
-  my $resdir   =  $suite->{rdir};
-  my $filename = "$testdir/${tname}.test";
+  my $suitename =  $suite->{name};
+  my $name      = "$suitename.$tname";
+  my $filename  = "$tpath/${tname}.test";
 
   # ----------------------------------------------------------------------
   # Set defaults
@@ -611,6 +626,7 @@ sub collect_one_test_case {
      shortname     => $tname,
      path          => $filename,
      suite         => $suite,
+     in_overlay    => $suite->{in_overlay},
      master_opt    => [ @{$suite->{opts}} ],
      slave_opt     => [ @{$suite->{opts}} ],
     );
@@ -618,8 +634,8 @@ sub collect_one_test_case {
   # ----------------------------------------------------------------------
   # Skip some tests but include in list, just mark them as skipped
   # ----------------------------------------------------------------------
-  if ( $skip_test_reg and ($tname =~ /$skip_test_reg/o ||
-                           $name =~ /$skip_test/o))
+  if ( $skip_test_reg and ($tname =~ /$skip_test_reg/o or
+                            $name =~ /$skip_test_reg/o))
   {
     $tinfo->{'skip'}= 1;
     return $tinfo;
@@ -629,34 +645,41 @@ sub collect_one_test_case {
   # Check for disabled tests
   # ----------------------------------------------------------------------
   my $disable = $disabled{".$tname"} || $disabled{$name};
-  if ($disable)
+  if (not defined $disable and $suite->{parent}) {
+    $disable = $disabled{$suite->{parent}->{name} . ".$tname"};
+  }
+  if (defined $disable)
   {
     $tinfo->{comment}= $disable;
     if ( $enable_disabled )
     {
       # User has selected to run all disabled tests
       mtr_report(" - $tinfo->{name} wil be run although it's been disabled\n",
-		 "  due to '$tinfo->{comment}'");
+		 "  due to '$disable'");
     }
     else
     {
       $tinfo->{'skip'}= 1;
       $tinfo->{'disable'}= 1;   # Sub type of 'skip'
-      return $tinfo;
+
+      # we can stop test file processing early if the test if disabled, but
+      # only if we're not in the overlay.  for overlays we want to know exactly
+      # whether the test is ignored (in_overlay=0) or disabled.
+      return $tinfo unless $suite->{parent};
     }
   }
 
   if ($suite->{skip}) {
     $tinfo->{skip}= 1;
-    $tinfo->{comment}= $suite->{skip};
-    return $tinfo;
+    $tinfo->{comment}= $suite->{skip} unless $tinfo->{comment};
+    return $tinfo unless $suite->{parent};
   }
 
   # ----------------------------------------------------------------------
   # Check for test specific config file
   # ----------------------------------------------------------------------
-  my $test_cnf_file= "$testdir/$tname.cnf";
-  if ( -f $test_cnf_file ) {
+  my $test_cnf_file= find_file_in_dirs($tinfo, tdir => "$tname.cnf");
+  if ($test_cnf_file ) {
     # Specifies the configuration file to use for this test
     $tinfo->{'template_path'}= $test_cnf_file;
   }
@@ -664,8 +687,8 @@ sub collect_one_test_case {
   # ----------------------------------------------------------------------
   # master sh
   # ----------------------------------------------------------------------
-  my $master_sh= "$testdir/$tname-master.sh";
-  if ( -f $master_sh )
+  my $master_sh= find_file_in_dirs($tinfo, tdir => "$tname-master.sh");
+  if ($master_sh)
   {
     if ( IS_WIN32PERL )
     {
@@ -682,8 +705,8 @@ sub collect_one_test_case {
   # ----------------------------------------------------------------------
   # slave sh
   # ----------------------------------------------------------------------
-  my $slave_sh= "$testdir/$tname-slave.sh";
-  if ( -f $slave_sh )
+  my $slave_sh= find_file_in_dirs($tinfo, tdir => "$tname-slave.sh");
+  if ($slave_sh)
   {
     if ( IS_WIN32PERL )
     {
@@ -697,8 +720,8 @@ sub collect_one_test_case {
     }
   }
 
-  my ($master_opts, $slave_opts)=
-    tags_from_test_file($tinfo, $filename, $suitedir);
+  my ($master_opts, $slave_opts)= tags_from_test_file($tinfo);
+  $tinfo->{in_overlay} = 1 if $file_in_overlay{$filename};
 
   if ( $tinfo->{'big_test'} and ! $::opt_big_test )
   {
@@ -760,41 +783,19 @@ sub collect_one_test_case {
     }
   }
 
-  if ( $tinfo->{'need_ipv6'} )
-  {
-    # This is a test that needs ssl
-    if ( ! $::have_ipv6 ) {
-      # IPv6 is not supported, skip it
-      $tinfo->{'skip'}= 1;
-      $tinfo->{'comment'}= "No IPv6";
-      return $tinfo;
-    }
-  }
-
   # ----------------------------------------------------------------------
   # Find config file to use if not already selected in <testname>.opt file
   # ----------------------------------------------------------------------
-  if (defined $defaults_file) {
-    # Using same config file for all tests
-    $tinfo->{template_path}= $defaults_file;
-  }
-  elsif (! $tinfo->{template_path} )
+  if (not $tinfo->{template_path} )
   {
-    my $config= "$suitedir/my.cnf";
-    if (! -f $config )
+    my $config= find_file_in_dirs($tinfo, dir => 'my.cnf');
+    if (not $config)
     {
-      # assume default.cnf will be used
-      $config= "include/default_my.cnf";
-
       # Suite has no config, autodetect which one to use
-      if ( $tinfo->{rpl_test} ){
-	$config= "suite/rpl/my.cnf";
-	if ( $tinfo->{ndb_test} ){
-	  $config= "suite/rpl_ndb/my.cnf";
-	}
-      }
-      elsif ( $tinfo->{ndb_test} ){
-	$config= "suite/ndb/my.cnf";
+      if ($tinfo->{rpl_test}) {
+        $config= "suite/rpl/my.cnf";
+      } else {
+        $config= "include/default_my.cnf";
       }
     }
     $tinfo->{template_path}= $config;
@@ -816,34 +817,86 @@ sub collect_one_test_case {
   }
 
   for $tinfo (@cases) {
+    #
+    # Now we find a result file for every test file. It's a bit complicated.
+    # For a test foobar.test in the combination pair {aa,bb}, and in the
+    # overlay "rty" to the suite "qwe", in other words, for the
+    # that that mtr prints as
+    #   ...
+    #   qwe-rty.foobar                   'aa,bb'  [ pass ]
+    #   ...
+    # the result can be expected in
+    #  * either .rdiff or .result file
+    #  * either in the overlay or in the original suite
+    #  * with or without combinations in the file name.
+    # which means any of the following 15 file names can be used:
+    #
+    #  1    rty/r/foo,aa,bb.result          
+    #  2    rty/r/foo,aa,bb.rdiff
+    #  3    qwe/r/foo,aa,bb.result
+    #  4    qwe/r/foo,aa,bb.rdiff
+    #  5    rty/r/foo,aa.result
+    #  6    rty/r/foo,aa.rdiff
+    #  7    qwe/r/foo,aa.result
+    #  8    qwe/r/foo,aa.rdiff
+    #  9    rty/r/foo,bb.result
+    # 10    rty/r/foo,bb.rdiff
+    # 11    qwe/r/foo,bb.result
+    # 12    qwe/r/foo,bb.rdiff
+    # 13    rty/r/foo.result
+    # 14    rty/r/foo.rdiff
+    # 15    qwe/r/foo.result
+    #
+    # They are listed, precisely, in the order of preference.
+    # mtr will walk that list from top to bottom and the first file that
+    # is found will be used.
+    #
+    # If this found file is a .rdiff, mtr continues walking down the list
+    # until the first .result file is found.
+    # A .rdiff is applied to that .result.
+    #
+    my $re ='';
+
     if ($tinfo->{combinations}) {
-      my $re = '(?:' . join('|', @{$tinfo->{combinations}}) . ')';
-      my $found = 0;
-      for (<$resdir/$tname,*.{rdiff,result}>) {
-        my ($combs, $ext) = m@$tname((?:,$re)+)\.(rdiff|result)$@ or next;
-        my @commas = ($combs =~ m/,/g);
-        # prefer the most specific result file
-        if (@commas > $found) {
-          $found = @commas;
-          $tinfo->{result_file} = $_;
-          if ($ext eq 'rdiff' and not $::exe_patch) {
-            $tinfo->{skip} = 1;
-            $tinfo->{comment} = "requires patch executable";
-          }
-        }
-      }
+      $re = '(?:' . join('|', @{$tinfo->{combinations}}) . ')';
     }
-    
-    unless (defined $tinfo->{result_file}) {
-      my $result_file= "$resdir/$tname.result";
-      if (-f $result_file) {
-        $tinfo->{result_file}= $result_file;
-      } else {
-        # No .result file exist
-        # Remember the path  where it should be
-        # saved in case of --record
-        $tinfo->{record_file}= $result_file;
+    my $resdirglob = $suite->{rdir};
+    $resdirglob.= ',' . $suite->{parent}->{rdir} if $suite->{parent};
+
+    my %files;
+    for (<{$resdirglob}/$tname*.{rdiff,result}>) {
+      my ($path, $combs, $ext) =
+                  m@^(.*)/$tname((?:,$re)*)\.(rdiff|result)$@ or next;
+      my @combs = sort split /,/, $combs;
+      $files{$_} = join '~', (                # sort files by
+        99 - scalar(@combs),                  # number of combinations DESC
+        join(',', sort @combs),               # combination names ASC
+        $path eq $suite->{rdir} ? 1 : 2,      # overlay first
+        $ext eq 'result' ? 1 : 2              # result before rdiff
+      );
+    }
+    my @results = sort { $files{$a} cmp $files{$b} } keys %files;
+
+    if (@results) {
+      my $result_file = shift @results;
+      $tinfo->{result_file} = $result_file;
+
+      if ($result_file =~ /\.rdiff$/) {
+        shift @results while $results[0] =~ /\.rdiff$/;
+        mtr_error ("$result_file has no corresponding .result file")
+          unless @results;
+        $tinfo->{base_result} = $results[0];
+
+        if (not $::exe_patch) {
+          $tinfo->{skip} = 1;
+          $tinfo->{comment} = "requires patch executable";
+        }
       }
+    } else {
+      # No .result file exist
+      # Remember the path  where it should be
+      # saved in case of --record
+      $tinfo->{record_file}= $suite->{rdir} . "/$tname.result";
     }
   }
 
@@ -856,16 +909,11 @@ my $tags_map= {'big_test' => ['big_test', 1],
                'have_multi_ndb' => ['ndb_test', 1],
                'master-slave' => ['rpl_test', 1],
                'ndb_master-slave' => ['rpl_test', 1, 'ndb_test', 1],
-               'check_ipv6' => ['need_ipv6', 1],
                'long_test' => ['long_test', 1],
 };
 my $tags_regex_string= join('|', keys %$tags_map);
 my $tags_regex= qr:include/($tags_regex_string)\.inc:o;
 
-my %file_to_tags;
-my %file_to_master_opts;
-my %file_to_slave_opts;
-
 # Get various tags from a file, recursively scanning also included files.
 # And get options from .opt file, also recursively for included files.
 # Return a list of [TAG_TO_SET, VALUE_TO_SET_TO] of found tags.
@@ -875,7 +923,7 @@ my %file_to_slave_opts;
 # We need to be a bit careful about speed here; previous version of this code
 # took forever to scan the full test suite.
 sub get_tags_from_file($$) {
-  my ($file, $suitedir)= @_;
+  my ($file, $suite)= @_;
 
   return @{$file_to_tags{$file}} if exists $file_to_tags{$file};
 
@@ -887,6 +935,25 @@ sub get_tags_from_file($$) {
   my $slave_opts= [];
   my @combinations;
 
+  my $over = defined $suite->{parent};
+  my $sdir = $suite->{dir};
+  my $pdir = $suite->{parent}->{dir} if $over;
+  my $in_overlay = 0;
+  my $suffix = $file;
+  my @prefix = ('');
+
+  # to be able to look up all auxillary files in the overlay
+  # we split the file path in a prefix and a suffix
+  if ($file =~ m@^$sdir/(.*)$@) {
+    $suffix = $1;
+    @prefix =  ("$sdir/");
+    push @prefix, "$pdir/" if $over;
+    $in_overlay = $over;
+  } elsif ($over and $file =~ m@^$pdir/(.*)$@) {
+    $suffix = $1;
+    @prefix = map { "$_/" } $sdir, $pdir;
+  }
+
   while (my $line= <$F>)
   {
     # Ignore comments.
@@ -906,20 +973,23 @@ sub get_tags_from_file($$) {
     if ($line =~ /^(--)?[[:space:]]*source[[:space:]]+([^;[:space:]]+)/)
     {
       my $include= $2;
-      # Sourced file may exist relative to test file, or in global location.
+      # The rules below must match open_file() function of mysqltest.cc
       # Note that for the purpose of tag collection we ignore
       # non-existing files, and let mysqltest handle the error
       # (e.g. mysqltest.test needs this)
-      for my $sourced_file (dirname($file) . '/' . $include,
-                            $suitedir . '/' . $include,
-                            $::glob_mysql_test_dir . '/' . $include)
+      for ((map { dirname("$_$suffix") } @prefix),
+           $sdir, $pdir, $::glob_mysql_test_dir)
       {
+        next unless defined $_;
+        my $sourced_file = "$_/$include";
+        next if $sourced_file eq $file;
         if (-e $sourced_file)
         {
-          push @$tags, get_tags_from_file($sourced_file, $suitedir);
+          push @$tags, get_tags_from_file($sourced_file, $suite);
           push @$master_opts, @{$file_to_master_opts{$sourced_file}};
           push @$slave_opts, @{$file_to_slave_opts{$sourced_file}};
           push @combinations, @{$file_combinations{$sourced_file}};
+          $file_in_overlay{$file} ||= $file_in_overlay{$sourced_file};
           last;
         }
       }
@@ -929,30 +999,48 @@ sub get_tags_from_file($$) {
   # Add options from main file _after_ those of any includes; this allows a
   # test file to override options set by includes (eg. rpl.rpl_ddl uses this
   # to enable innodb, then disable innodb in the slave.
-  my $file_no_ext= $file;
-  $file_no_ext =~ s/\.\w+$//;
-  my @common_opts= opts_from_file("$file_no_ext.opt");
-  push @$master_opts, @common_opts, opts_from_file("$file_no_ext-master.opt");
-  push @$slave_opts, @common_opts, opts_from_file("$file_no_ext-slave.opt");
+  $suffix =~ s/\.\w+$//;
+
+  for (qw(.opt -master.opt -slave.opt)) {
+    my @res;
+    push @res, opts_from_file("$prefix[1]$suffix$_") if $over;
+    if (-f "$prefix[0]$suffix$_") {
+      $in_overlay = $over;
+      push @res, opts_from_file("$prefix[0]$suffix$_");
+    }
+    push @$master_opts, @res unless /slave/;
+    push @$slave_opts, @res unless /master/;
+  }
 
-  push @combinations, [ combinations_from_file("$file_no_ext.combinations") ];
+  # for combinations we need to make sure that its suite object is loaded,
+  # even if this file does not belong to a current suite!
+  my $comb_file = "$suffix.combinations";
+  $suite = load_suite_for_file($comb_file) if $prefix[0] eq '';
+  my @comb;
+  unless ($suite->{skip}) {
+    @comb = combinations_from_file($over, "$prefix[0]$comb_file");
+    push @comb, combinations_from_file(undef, "$prefix[1]$comb_file") if $over;
+  }
+  push @combinations, [ @comb ];
 
   # Save results so we can reuse without parsing if seen again.
   $file_to_tags{$file}= $tags;
   $file_to_master_opts{$file}= $master_opts;
   $file_to_slave_opts{$file}= $slave_opts;
   $file_combinations{$file}= [ uniq(@combinations) ];
+  $file_in_overlay{$file} = 1 if $in_overlay;
   return @{$tags};
 }
 
 sub tags_from_test_file {
-  my ($tinfo, $file, $suitedir)= @_;
+  my ($tinfo)= @_;
+  my $file = $tinfo->{path};
 
   # a suite may generate tests that don't map to real *.test files
   # see unit suite for an example.
   return ([], []) unless -f $file;
 
-  for (get_tags_from_file($file, $suitedir))
+  for (get_tags_from_file($file, $tinfo->{suite}))
   {
     $tinfo->{$_->[0]}= $_->[1];
   }
@@ -973,7 +1061,7 @@ sub opts_from_file ($) {
 
   return () unless -f $file;
 
-  open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!");
+  open(FILE, '<', $file) or mtr_error("can't open file \"$file\": $!");
   my @args;
   while ( <FILE> )
   {
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 00d5d2142a67e4198734275348c9bf2ad26c4185..7ddfacbfbeecdb6d9284ddadb9e220b8519d1d6e 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -161,7 +161,7 @@ my $path_config_file;           # The generated config file, var/my.cnf
 # executables will be used by the test suite.
 our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
 
-my $DEFAULT_SUITES= join(',', qw(
+my $DEFAULT_SUITES= join(',', map { "$_-" } qw(
     main
     binlog
     federated
@@ -208,7 +208,6 @@ my $opt_ssl;
 my $opt_skip_ssl;
 my @opt_skip_test_list;
 our $opt_ssl_supported;
-our $have_ipv6;
 my $opt_ps_protocol;
 my $opt_sp_protocol;
 my $opt_cursor_protocol;
@@ -339,9 +338,8 @@ my $exe_ndb_mgmd;
 my $exe_ndb_waiter;
 my $exe_ndb_mgm;
 
-our $debug_compiled_binaries;
-
 our %mysqld_variables;
+our @optional_plugins;
 
 my $source_dist= 0;
 
@@ -432,11 +430,11 @@ sub main {
   {
     # Run the mysqld to find out what features are available
     collect_mysqld_features();
+    mysql_install_db(default_mysqld(), "$opt_vardir/install.db");
   }
-  check_ndbcluster_support(\%mysqld_variables);
-  check_ssl_support(\%mysqld_variables);
-  check_ipv6_support();
-  check_debug_support(\%mysqld_variables);
+  check_ndbcluster_support();
+  check_ssl_support();
+  check_debug_support();
 
   executable_setup();
 
@@ -1860,8 +1858,6 @@ sub set_build_thread_ports($) {
 
 
 sub collect_mysqld_features {
-  my $found_variable_list_start= 0;
-
   #
   # Execute "mysqld --no-defaults --help --verbose" to get a
   # list of all features and settings
@@ -1878,6 +1874,7 @@ sub collect_mysqld_features {
   mtr_add_arg($args, "--basedir=%s", $basedir);
   mtr_add_arg($args, "--lc-messages-dir=%s", $path_language);
   mtr_add_arg($args, "--skip-grant-tables");
+  mtr_add_arg($args, "--log-warnings=0");
   for (@opt_extra_mysqld_opt) {
     mtr_add_arg($args, $_) unless /^--binlog-format\b/;
   }
@@ -1896,70 +1893,40 @@ sub collect_mysqld_features {
 
   my $exe_mysqld= find_mysqld($bindir);
   my $cmd= join(" ", $exe_mysqld, @$args);
-  my $list= `$cmd`;
 
   mtr_verbose("cmd: $cmd");
 
-  foreach my $line (split('\n', $list))
-  {
-    # First look for version
-    if ( !$mysql_version_id )
-    {
-      # Look for version
-      my $exe_name= basename($exe_mysqld);
-      mtr_verbose("exe_name: $exe_name");
-      if ( $line =~ /^\S*$exe_name\s\sVer\s([0-9]*)\.([0-9]*)\.([0-9]*)([^\s]*)/ )
-      {
-	#print "Major: $1 Minor: $2 Build: $3\n";
-	$mysql_version_id= $1*10000 + $2*100 + $3;
-	#print "mysql_version_id: $mysql_version_id\n";
-	mtr_report("MariaDB Version $1.$2.$3");
-	$mysql_version_extra= $4;
-      }
-    }
-    else
-    {
-      if (!$found_variable_list_start)
-      {
-	# Look for start of variables list
-	if ( $line =~ /[\-]+\s[\-]+/ )
-	{
-	  $found_variable_list_start= 1;
-	}
-      }
-      else
-      {
-	# Put variables into hash
-	if ( $line =~ /^([\S]+)[ \t]+(.*?)\r?$/ )
-	{
-          my $name= $1;
-          my $value=$2;
-          $name =~ s/_/-/g;
-          # print "$name=\"$value\"\n";
-          $mysqld_variables{$name}= $value;
-	}
-	else
-	{
-	  # The variable list is ended with a blank line
-	  if ( $line =~ /^[\s]*$/ )
-	  {
-	    last;
-	  }
-	  else
-	  {
-	    # Send out a warning, we should fix the variables that has no
-	    # space between variable name and it's value
-	    # or should it be fixed width column parsing? It does not
-	    # look like that in function my_print_variables in my_getopt.c
-	    mtr_warning("Could not parse variable list line : $line");
-	  }
-	}
-      }
+  my $list= `$cmd`;
+
+  # to simplify the parsing, we'll merge all nicely formatted --help texts
+  $list =~ s/\n {22}(\S)/ $1/g;
+
+  my @list= split '\n', $list;
+  mtr_error("Could not find version of MariaDB")
+     unless shift(@list) =~ /^$exe_mysqld\s+Ver\s(\d+)\.(\d+)\.(\d+)(\S*)/;
+  $mysql_version_id= $1*10000 + $2*100 + $3;
+  $mysql_version_extra= $4;
+  mtr_report("MariaDB Version $1.$2.$3$4");
+
+  for (@list)
+  {
+    # first part of the help - command-line options.
+    if (/Copyright/ .. /^-{30,}/) {
+      # here we want to detect all not mandatory plugins
+      # they are listed in the --help output as
+      #  --archive[=name]    Enable or disable ARCHIVE plugin. Possible values are ON, OFF, FORCE (don't start if the plugin fails to load).
+      push @optional_plugins, $1
+        if /^  --([-a-z0-9]+)\[=name\] +Enable or disable \w+ plugin. Possible values are ON, OFF, FORCE/;
+      next;
     }
-  }
-  mtr_error("Could not find version of MySQL") unless $mysql_version_id;
-  mtr_error("Could not find variabes list") unless $found_variable_list_start;
 
+    last if /^$/; # then goes a list of variables, it ends with an empty line
+
+    # Put a variable into hash
+    /^([\S]+)[ \t]+(.*?)\r?$/ or die "Could not parse mysqld --help: $_\n";
+    $mysqld_variables{$1}= $2;
+  }
+  mtr_error("Could not find variabes list") unless %mysqld_variables;
 }
 
 
@@ -2789,9 +2756,7 @@ sub  check_running_as_root () {
 }
 
 
-sub check_ssl_support ($) {
-  my $mysqld_variables= shift;
-
+sub check_ssl_support {
   if ($opt_skip_ssl)
   {
     mtr_report(" - skipping SSL");
@@ -2800,7 +2765,7 @@ sub check_ssl_support ($) {
     return;
   }
 
-  if ( ! $mysqld_variables->{'ssl'} )
+  if ( ! $mysqld_variables{'ssl'} )
   {
     if ( $opt_ssl)
     {
@@ -2816,29 +2781,15 @@ sub check_ssl_support ($) {
   $opt_ssl_supported= 1;
 }
 
-sub check_ipv6_support {
-  use Socket;
-  $have_ipv6 = socket SOCK, PF_INET6, SOCK_STREAM, getprotobyname('tcp');
-  close SOCK;
-}
-
-sub check_debug_support ($) {
-  my $mysqld_variables= shift;
-  my $debug_var= $mysqld_variables->{'debug'};
-  
-  if ( !$debug_var || $debug_var eq "disabled")
+sub check_debug_support {
+  if (defined $mysqld_variables{'debug-dbug'})
   {
-    #mtr_report(" - binaries are not debug compiled");
-    $debug_compiled_binaries= 0;
-
-    if ( $opt_debug_server )
-    {
-      mtr_error("Can't use --debug[-server], binary does not support it");
-    }
-    return;
+    mtr_report(" - binaries are debug compiled");
+  }
+  elsif ($opt_debug_server)
+  {
+    mtr_error("Can't use --debug[-server], binary does not support it");
   }
-  mtr_report(" - binaries are debug compiled");
-  $debug_compiled_binaries= 1;
 }
 
 
@@ -2901,8 +2852,7 @@ sub vs_config_dirs ($$) {
 }
 
 
-sub check_ndbcluster_support ($) {
-  my $mysqld_variables= shift;
+sub check_ndbcluster_support {
 
   # Check if this is MySQL Cluster, ie. mysql version string ends
   # with -ndb-Y.Y.Y[-status]
@@ -3396,8 +3346,6 @@ sub initialize_servers {
     {
       remove_stale_vardir();
       setup_vardir();
-
-      mysql_install_db(default_mysqld(), "$opt_vardir/install.db");
     }
   }
 }
@@ -3490,10 +3438,7 @@ sub mysql_install_db {
   mtr_add_arg($args, "--basedir=%s", $install_basedir);
   mtr_add_arg($args, "--datadir=%s", $install_datadir);
   mtr_add_arg($args, "--default-storage-engine=myisam");
-  mtr_add_arg($args, "--loose-skip-innodb");
-  mtr_add_arg($args, "--loose-skip-pbxt");
-  mtr_add_arg($args, "--loose-skip-ndbcluster");
-  mtr_add_arg($args, "--loose-skip-aria");
+  mtr_add_arg($args, "--skip-$_") for @optional_plugins;
   mtr_add_arg($args, "--disable-sync-frm");
   mtr_add_arg($args, "--tmpdir=%s", "$opt_vardir/tmp/");
   mtr_add_arg($args, "--core-file");
@@ -3719,23 +3664,27 @@ sub do_before_run_mysqltest($)
 
   # Remove old files produced by mysqltest
   die "unsupported result file name $resfile, stoping" unless
-         $resfile =~ /^(.*)\.(rdiff|result)$/;
-  my $base_file= $1;
+         $resfile =~ /^(.*?)((?:,\w+)*)\.(rdiff|result)$/;
+  my ($base_file, $suites, $ext)= ($1, $2, $3);
   # if the result file is a diff, make a proper result file
-  if ($2 eq 'rdiff') {
+  if ($ext eq 'rdiff') {
+    my $base_result = $tinfo->{base_result};
     my $resdir= dirname($resfile);
     # we'll use a separate extension for generated result files
-    # to be able to distinguish them from manually created version
-    # controlled results, and to ignore them in bzr.
-    my $dest = "$base_file.result~";
+    # to be able to distinguish them from manually created
+    # version-controlled results, and to ignore them in bzr.
+    my $dest = "$base_file$suites.result~";
+    my @cmd = ($exe_patch, qw/--binary -r - -f -s -o/,
+               $dest, $base_result, $resfile);
     if (-w $resdir) {
       # don't rebuild a file if it's up to date
-      unless (-e $dest and -M $dest < -M $resfile) {
-        run_system("$exe_patch -o $dest -i $resfile -r - -f -s -d $resdir");
+      unless (-e $dest and -M $dest < -M $resfile
+                       and -M $dest < -M $base_result) {
+        run_system(@cmd);
       }
     } else {
-      $dest = $opt_tmpdir . '/' . basename($dest);
-      run_system("$exe_patch -o $dest -i $resfile -r - -f -s -d $resdir");
+      $cmd[-3] = $dest = $opt_tmpdir . '/' . basename($dest);
+      run_system(@cmd);
     }
     $tinfo->{result_file} = $dest;
   }
@@ -4064,7 +4013,7 @@ sub mycnf_create {
   my ($config) = @_;
   my $res;
 
-  foreach my $group ($config->groups()) {
+  foreach my $group ($config->option_groups()) {
     $res .= "[$group->{name}]\n";
 
     foreach my $option ($group->options()) {
@@ -4176,6 +4125,7 @@ sub run_testcase ($$) {
   } else {
     delete($ENV{'TZ'});
   }
+  $ENV{MTR_SUITE_DIR} = $tinfo->{suite}->{dir};
   mtr_verbose("Setting timezone: $timezone");
 
   if ( ! using_extern() )
@@ -5228,10 +5178,9 @@ sub report_failure_and_restart ($) {
 }
 
 
-sub run_system($) {
-  my ($script)= @_;
-  mtr_verbose("Running '$script'");
-  my $ret= system($script) >> 8;
+sub run_system(@) {
+  mtr_verbose("Running '$_[0]'");
+  my $ret= system(@_) >> 8;
   return $ret;
 }
 
@@ -5285,19 +5234,6 @@ sub mysqld_arguments ($$$) {
     mtr_add_arg($args, "--user=root");
   }
 
-  if ( $opt_valgrind_mysqld )
-  {
-    if ( $mysql_version_id < 50100 )
-    {
-      mtr_add_arg($args, "--skip-bdb");
-    }
-  }
-
-  mtr_add_arg($args, "--loose-skip-safemalloc");
-  mtr_add_arg($args, "%s--disable-sync-frm");
-  # Retry bind as this may fail on busy server
-  mtr_add_arg($args, "%s--port-open-timeout=10");
-
   # On some old linux kernels, aio on tmpfs is not supported
   # Remove this if/when Bug #58421 fixes this in the server
   if ($^O eq "linux" && $opt_mem)
@@ -5305,7 +5241,7 @@ sub mysqld_arguments ($$$) {
     mtr_add_arg($args, "--loose-skip-innodb-use-native-aio");
   }
 
-  if (!using_extern() and $mysql_version_id >= 50106 && !$opt_user_args)
+  if (!using_extern() and !$opt_user_args)
   {
     # Turn on logging to file
     mtr_add_arg($args, "%s--log-output=file");
@@ -5909,6 +5845,14 @@ sub start_mysqltest ($) {
     mtr_add_arg($args, "%s", $_) for @args_saved;
   }
 
+  my $suite = $tinfo->{suite};
+  if ($suite->{parent}) {
+    mtr_add_arg($args, "--overlay-dir=%s/", $suite->{dir});
+    mtr_add_arg($args, "--suite-dir=%s/", $suite->{parent}->{dir});
+  } else {
+    mtr_add_arg($args, "--suite-dir=%s/", $suite->{dir});
+  }
+
   mtr_add_arg($args, "--test-file=%s", $tinfo->{'path'});
 
   # Number of lines of resut to include in failure report
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index 101392958718eac431d81e8d5af51f618bbea08c..25345227d59a082d4a6a3fd26a3e7900bcb398d5 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -366,7 +366,7 @@ $dollar
 drop table t1;
 mysqltest: At line 1: query 'let $var2= `failing query`' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'failing query' at line 1
 mysqltest: At line 1: Missing required argument 'filename' to command 'source'
-mysqltest: At line 1: Could not open './non_existingFile' for reading, errno: 2
+mysqltest: At line 1: Could not open 'non_existingFile' for reading, errno: 2
 mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": 
 included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1:
 included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1:
diff --git a/mysql-test/r/plugin_innodb,innodb_plugin.rdiff b/mysql-test/r/plugin_innodb,innodb_plugin.rdiff
new file mode 100644
index 0000000000000000000000000000000000000000..d76f2356ae08ffd6589cdfce2d487f9a72f56b64
--- /dev/null
+++ b/mysql-test/r/plugin_innodb,innodb_plugin.rdiff
@@ -0,0 +1,12 @@
+--- r/plugin_innodb.result	2011-10-21 23:35:26.000000000 +0200
++++ r/plugin_innodb.reject	2012-02-08 13:59:19.000000000 +0100
+@@ -4,6 +4,9 @@
+ alter table mysql.plugin engine=innodb;
+ restart
+ create table t1(a int) engine=example;
++Warnings:
++Warning	1286	Unknown storage engine 'example'
++Warning	1266	Using storage engine MyISAM for table 't1'
+ select * from t1;
+ a
+ drop table t1;
diff --git a/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff b/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff
new file mode 100644
index 0000000000000000000000000000000000000000..b31cb319732794540fdd088276f9ed54dc6e47c5
--- /dev/null
+++ b/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff
@@ -0,0 +1,326 @@
+--- r/range_vs_index_merge_innodb.result	2011-11-23 22:19:38.000000000 +0100
++++ r/range_vs_index_merge_innodb.reject	2012-02-08 13:04:41.000000000 +0100
+@@ -50,14 +50,14 @@
+ WHERE (Population >= 100000 OR Name LIKE 'P%') AND Country='CAN' OR
+ (Population < 100000 OR Name Like 'T%') AND Country='ARG';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population,Country,Name	Country	3	NULL	106	Using index condition; Using where
++1	SIMPLE	City	range	Population,Country,Name	Country	3	NULL	106	Using where
+ EXPLAIN
+ SELECT * FROM City
+ WHERE Population < 200000 AND Name LIKE 'P%' AND
+ (Population > 300000 OR Name LIKE 'T%') AND
+ (Population < 100000 OR Name LIKE 'Pa%');
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population,Name	Name	35	NULL	235	Using index condition; Using where
++1	SIMPLE	City	range	Population,Name	Name	35	NULL	235	Using where
+ EXPLAIN
+ SELECT * FROM City
+ WHERE Population > 100000 AND Name LIKE 'Aba%' OR
+@@ -70,12 +70,12 @@
+ SELECT * FROM City
+ WHERE (Population > 101000 AND Population < 115000);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	458	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	458	Using where
+ EXPLAIN 
+ SELECT * FROM City
+ WHERE (Population > 101000 AND Population < 102000);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	38	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	38	Using where
+ EXPLAIN 
+ SELECT * FROM City
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'));
+@@ -92,7 +92,7 @@
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'))
+ AND (Population > 101000 AND Population < 102000);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population,Country,Name	Population	4	NULL	38	Using index condition; Using where
++1	SIMPLE	City	range	Population,Country,Name	Population	4	NULL	38	Using where
+ SELECT * FROM City USE INDEX ()
+ WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'))
+ AND (Population > 101000 AND Population < 115000);
+@@ -172,37 +172,37 @@
+ EXPLAIN
+ SELECT  * FROM City WHERE (Name < 'Ac');
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	23	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	23	Using where
+ EXPLAIN
+ SELECT  * FROM City WHERE (Name < 'Bb');
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	373	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	373	Using where
+ EXPLAIN
+ SELECT  * FROM City WHERE (Country > 'A' AND Country < 'B');
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Country	Country	3	NULL	106	Using index condition
++1	SIMPLE	City	range	Country	Country	3	NULL	106	Using where
+ EXPLAIN
+ SELECT  * FROM City WHERE (Name BETWEEN 'P' AND 'Pb');
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	71	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	71	Using where
+ EXPLAIN
+ SELECT  * FROM City WHERE (Name BETWEEN 'P' AND 'S');
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	384	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	384	Using where
+ EXPLAIN
+ SELECT  * FROM City WHERE (Population > 101000 AND Population < 110000);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	327	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	327	Using where
+ EXPLAIN
+ SELECT  * FROM City WHERE (Population > 103000 AND Population < 104000);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	36	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	36	Using where
+ EXPLAIN
+ SELECT  * FROM City 
+ WHERE (Name < 'Ac' AND (Country > 'A' AND Country < 'B')) OR
+ (Name BETWEEN 'P' AND 'Pb' AND (Population > 101000 AND Population < 110000));
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population,Country,Name	Name	35	NULL	94	Using index condition; Using where
++1	SIMPLE	City	range	Population,Country,Name	Name	35	NULL	94	Using where
+ EXPLAIN
+ SELECT  * FROM City
+ WHERE (Name < 'Ac' AND (Country > 'A' AND Country < 'B')) OR
+@@ -328,34 +328,34 @@
+ EXPLAIN
+ SELECT * FROM City WHERE (ID < 10) OR (ID BETWEEN 100 AND 110);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	20	Using index condition; Using where
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	20	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE (ID < 200) OR (ID BETWEEN 100 AND 200);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	200	Using index condition; Using where
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	200	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE (ID < 600) OR (ID BETWEEN 900 AND 1500);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	1198	Using index condition; Using where
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	1198	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Country > 'A' AND Country < 'ARG';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Country	Country	3	NULL	19	Using index condition
++1	SIMPLE	City	range	Country	Country	3	NULL	19	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Name LIKE 'H%' OR Name LIKE 'P%' ;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	394	Using index condition; Using where
++1	SIMPLE	City	range	Name	Name	35	NULL	394	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Name LIKE 'Ha%' OR Name LIKE 'Pa%' ;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	133	Using index condition; Using where
++1	SIMPLE	City	range	Name	Name	35	NULL	133	Using where
+ EXPLAIN
+ SELECT * FROM City
+ WHERE ((ID < 10) AND (Name LIKE 'H%' OR (Country > 'A' AND Country < 'ARG')))
+ OR ((ID BETWEEN 100 AND 110) AND 
+ (Name LIKE 'P%' OR (Population > 103000 AND Population < 104000)));
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY,Population,Country,Name	PRIMARY	4	NULL	20	Using index condition; Using where
++1	SIMPLE	City	range	PRIMARY,Population,Country,Name	PRIMARY	4	NULL	20	Using where
+ EXPLAIN
+ SELECT * FROM City
+ WHERE ((ID < 800) AND (Name LIKE 'Ha%' OR (Country > 'A' AND Country < 'ARG')))
+@@ -369,7 +369,7 @@
+ OR ((ID BETWEEN 100 AND 200) AND 
+ (Name LIKE 'Pa%' OR (Population > 103000 AND Population < 104000)));
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY,Population,Country,Name	PRIMARY	4	NULL	200	Using index condition; Using where
++1	SIMPLE	City	range	PRIMARY,Population,Country,Name	PRIMARY	4	NULL	200	Using where
+ SELECT * FROM City USE INDEX ()
+ WHERE ((ID < 10) AND (Name LIKE 'H%' OR (Country > 'A' AND Country < 'ARG')))
+ OR ((ID BETWEEN 100 AND 110) AND 
+@@ -577,39 +577,39 @@
+ EXPLAIN 
+ SELECT * FROM City WHERE Population > 101000 AND Population < 102000;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	38	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	38	Using where
+ EXPLAIN 
+ SELECT * FROM City WHERE Population > 101000 AND Population < 110000;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	327	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	327	Using where
+ EXPLAIN 
+ SELECT * FROM City WHERE Country < 'C';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Country	Country	3	NULL	446	Using index condition
++1	SIMPLE	City	range	Country	Country	3	NULL	446	Using where
+ EXPLAIN 
+ SELECT * FROM City WHERE Country < 'AGO';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Country	Country	3	NULL	5	Using index condition
++1	SIMPLE	City	range	Country	Country	3	NULL	5	Using where
+ EXPLAIN 
+ SELECT * FROM City WHERE Name BETWEEN 'P' AND 'S';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	384	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	384	Using where
+ EXPLAIN 
+ SELECT * FROM City WHERE Name BETWEEN 'P' AND 'Pb';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	71	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	71	Using where
+ EXPLAIN 
+ SELECT * FROM City WHERE ID BETWEEN 3400 AND 3800;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	400	Using index condition
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	400	Using where
+ EXPLAIN 
+ SELECT * FROM City WHERE ID BETWEEN 3790 AND 3800;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	11	Using index condition
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	11	Using where
+ EXPLAIN 
+ SELECT * FROM City WHERE Name LIKE 'P%';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	235	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	235	Using where
+ EXPLAIN
+ SELECT * FROM City
+ WHERE ((Population > 101000 AND Population < 102000) AND
+@@ -680,23 +680,23 @@
+ EXPLAIN
+ SELECT * FROM City WHERE Name LIKE 'Pas%';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	8	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	8	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Name LIKE 'P%';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	235	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	235	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE (Population > 101000 AND Population < 103000);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	80	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	80	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Country='USA';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	ref	Country,CountryPopulation	Country	3	const	274	Using index condition
++1	SIMPLE	City	ref	Country,CountryPopulation	Country	3	const	274	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Country='FIN';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	ref	Country,CountryPopulation	Country	3	const	7	Using index condition
++1	SIMPLE	City	ref	Country,CountryPopulation	Country	3	const	7	Using where
+ EXPLAIN
+ SELECT * FROM City 
+ WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'Pas%')
+@@ -708,7 +708,7 @@
+ WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'P%')
+ AND Country='FIN';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	ref	Population,Country,Name,CountryPopulation	Country	3	const	7	Using index condition; Using where
++1	SIMPLE	City	ref	Population,Country,Name,CountryPopulation	Country	3	const	7	Using where
+ SELECT * FROM City 
+ WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'Pas%')
+ AND Country='USA';
+@@ -753,51 +753,51 @@
+ EXPLAIN
+ SELECT * FROM City WHERE Country='USA';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	ref	Country,CountryPopulation,CountryName	Country	3	const	274	Using index condition
++1	SIMPLE	City	ref	Country,CountryPopulation,CountryName	Country	3	const	274	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Country='FIN';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	ref	Country,CountryPopulation,CountryName	Country	3	const	7	Using index condition
++1	SIMPLE	City	ref	Country,CountryPopulation,CountryName	Country	3	const	7	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Country='BRA';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	ref	Country,CountryPopulation,CountryName	Country	3	const	250	Using index condition
++1	SIMPLE	City	ref	Country,CountryPopulation,CountryName	Country	3	const	250	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE ID BETWEEN 3790 AND 3800;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	11	Using index condition
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	11	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE ID BETWEEN 4025 AND 4035;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	11	Using index condition
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	11	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE ID BETWEEN 4028 AND 4032;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	5	Using index condition
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	5	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE ID BETWEEN 3500 AND 3800;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	300	Using index condition
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	300	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE ID BETWEEN 4000 AND 4300;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	80	Using index condition
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	80	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE ID BETWEEN 250 and 260 ;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	11	Using index condition
++1	SIMPLE	City	range	PRIMARY	PRIMARY	4	NULL	11	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE (Population > 101000 AND Population < 102000);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	38	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	38	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE (Population > 101000 AND Population < 103000);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Population	Population	4	NULL	80	Using index condition
++1	SIMPLE	City	range	Population	Population	4	NULL	80	Using where
+ EXPLAIN
+ SELECT * FROM City WHERE Name LIKE 'Pa%';
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	Name	Name	35	NULL	71	Using index condition
++1	SIMPLE	City	range	Name	Name	35	NULL	71	Using where
+ EXPLAIN
+ SELECT * FROM City
+ WHERE ((Population > 101000 AND Population < 102000) OR
+@@ -818,7 +818,7 @@
+ ID BETWEEN 3500 AND 3800) AND Country='FIN'
+         AND (Name BETWEEN 'P' AND 'T' OR ID BETWEEN 4000 AND 4300);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	ref	PRIMARY,Population,Country,Name,CountryPopulation,CountryName	Country	3	const	7	Using index condition; Using where
++1	SIMPLE	City	ref	PRIMARY,Population,Country,Name,CountryPopulation,CountryName	Country	3	const	7	Using where
+ SELECT * FROM City USE INDEX ()
+ WHERE ((Population > 101000 AND Population < 102000) OR
+ ID BETWEEN 3790 AND 3800) AND Country='USA'
+@@ -950,14 +950,14 @@
+ ID BETWEEN 3500 AND 3800) AND Country='USA'
+         AND (Name LIKE 'P%' OR ID BETWEEN 4000 AND 4300);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY,Population,Country,Name,CountryPopulation,CountryName	CountryName	38	NULL	18	Using index condition; Using where
++1	SIMPLE	City	range	PRIMARY,Population,Country,Name,CountryPopulation,CountryName	CountryName	38	NULL	18	Using where
+ EXPLAIN
+ SELECT * FROM City
+ WHERE ((Population > 101000 AND Population < 11000) OR
+ ID BETWEEN 3500 AND 3800) AND Country='USA'
+         AND (Name LIKE 'Pho%' OR ID BETWEEN 4000 AND 4300);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	City	range	PRIMARY,Population,Country,Name,CountryPopulation,CountryName	Name	35	NULL	1	Using index condition; Using where
++1	SIMPLE	City	range	PRIMARY,Population,Country,Name,CountryPopulation,CountryName	Name	35	NULL	1	Using where
+ SELECT * FROM City USE INDEX ()
+ WHERE ((Population > 101000 AND Population < 11000) OR
+ ID BETWEEN 3500 AND 3800) AND Country='USA'
+@@ -1422,7 +1422,7 @@
+ WHERE t1.a>300 AND t1.c!=0 AND t1.b>=350 AND t1.b<=400 AND
+ (t1.c=0 OR t1.a=500);
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	t1	range	PRIMARY,idx	PRIMARY	4	NULL	1	Using index condition; Using where
++1	SIMPLE	t1	range	PRIMARY,idx	PRIMARY	4	NULL	1	Using where
+ SELECT * FROM t1
+ WHERE t1.a>300 AND t1.c!=0 AND t1.b>=350 AND t1.b<=400 AND
+ (t1.c=0 OR t1.a=500);
diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm
index 18290e05bd4ae7fa681a532f2f24ddf56311a950..fc9d724a6e0cf324616fe2433a7c971711d9006c 100644
--- a/mysql-test/suite.pm
+++ b/mysql-test/suite.pm
@@ -5,12 +5,31 @@ package My::Suite::Main;
 sub skip_combinations {
   my @combinations;
 
+  # disable innodb/xtradb combinatons for configurations that were not built
   push @combinations, 'innodb_plugin' unless $ENV{HA_INNODB_SO};
   push @combinations, 'xtradb_plugin' unless $ENV{HA_XTRADB_SO};
   push @combinations, 'xtradb' unless $::mysqld_variables{'innodb'} eq "ON";
 
-  ( 'include/have_innodb.combinations' => [ @combinations ] )
+  my %skip = ( 'include/have_innodb.combinations' => [ @combinations ]);
+
+  # as a special case, disable certain include files as a whole
+  $skip{'include/not_embedded.inc'} = 'Not run for embedded server'
+             if $::opt_embedded_server;
+
+  $skip{'include/have_debug.inc'} = 'Requires debug build'
+             unless defined $::mysqld_variables{'debug-dbug'};
+
+  $skip{'include/not_windows.inc'} = 'Requires not Windows' if IS_WINDOWS;
+
+  # disable tests that use ipv6, if unsupported
+  use Socket;
+  $skip{'include/check_ipv6.inc'} = 'No IPv6'
+             unless socket SOCK, PF_INET6, SOCK_STREAM, getprotobyname('tcp');
+  close SOCK;
+
+  %skip;
 }
 
+
 bless { };
 
diff --git a/mysql-test/suite/binlog/t/disabled.def b/mysql-test/suite/binlog/disabled.def
similarity index 100%
rename from mysql-test/suite/binlog/t/disabled.def
rename to mysql-test/suite/binlog/disabled.def
diff --git a/mysql-test/suite/engines/funcs/t/disabled.def b/mysql-test/suite/engines/funcs/disabled.def
similarity index 100%
rename from mysql-test/suite/engines/funcs/t/disabled.def
rename to mysql-test/suite/engines/funcs/disabled.def
diff --git a/mysql-test/suite/engines/iuds/t/disabled.def b/mysql-test/suite/engines/iuds/disabled.def
similarity index 100%
rename from mysql-test/suite/engines/iuds/t/disabled.def
rename to mysql-test/suite/engines/iuds/disabled.def
diff --git a/mysql-test/suite/federated/combinations b/mysql-test/suite/federated/combinations
index 18fd5f0d72164d101c10a8d602f5fc060097247b..668c1c05c5089bdef69b06be0faa964adb0be271 100644
--- a/mysql-test/suite/federated/combinations
+++ b/mysql-test/suite/federated/combinations
@@ -1,8 +1,6 @@
 [old]
---federated
---plugin-load=$HA_FEDERATED_SO
+plugin-load=$HA_FEDERATED_SO
 
 [X]
---federated
---plugin-load=$HA_FEDERATEDX_SO
+plugin-load=$HA_FEDERATEDX_SO
 
diff --git a/mysql-test/suite/federated/have_federatedx.opt b/mysql-test/suite/federated/have_federatedx.opt
index 22f40b6d3d7052ead4665818c32c0919d697f89f..21f6f149f098257dc65ede2b60487421fefff9b4 100644
--- a/mysql-test/suite/federated/have_federatedx.opt
+++ b/mysql-test/suite/federated/have_federatedx.opt
@@ -1 +1 @@
---plugin-load=$HA_FEDERATEDX_SO
+--plugin-load=$HA_FEDERATEDX_SO --federated
diff --git a/mysql-test/suite/federated/my.cnf b/mysql-test/suite/federated/my.cnf
index ec27e18917917676ae2318a783bbd6040056480e..b97f8266ff109d35f91f8886b3a9bd7a12652a05 100644
--- a/mysql-test/suite/federated/my.cnf
+++ b/mysql-test/suite/federated/my.cnf
@@ -3,6 +3,7 @@
 !include include/default_client.cnf
 
 [mysqld.1]
+federated
 #log-bin=                 master-bin
 
 [mysqld.2]
diff --git a/mysql-test/suite/funcs_1/t/disabled.def b/mysql-test/suite/funcs_1/disabled.def
similarity index 100%
rename from mysql-test/suite/funcs_1/t/disabled.def
rename to mysql-test/suite/funcs_1/disabled.def
diff --git a/mysql-test/suite/funcs_1/t/is_columns_is_embedded.test b/mysql-test/suite/funcs_1/t/is_columns_is_embedded.test
index 27d23be00e0868e2ef935b764d70cc446382b582..330dfa20629ecd3ecc57c830f4e167eabd9a741c 100644
--- a/mysql-test/suite/funcs_1/t/is_columns_is_embedded.test
+++ b/mysql-test/suite/funcs_1/t/is_columns_is_embedded.test
@@ -13,7 +13,6 @@
 # 2008-06-06 mleich Create this variant for the embedded server
 #
 
---source include/have_innodb.inc
 --source include/have_xtradb.inc
 
 if (`SELECT VERSION() NOT LIKE '%embedded%'`)
diff --git a/mysql-test/suite/funcs_2/t/disabled.def b/mysql-test/suite/funcs_2/disabled.def
similarity index 100%
rename from mysql-test/suite/funcs_2/t/disabled.def
rename to mysql-test/suite/funcs_2/disabled.def
diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/disabled.def
similarity index 100%
rename from mysql-test/suite/innodb/t/disabled.def
rename to mysql-test/suite/innodb/disabled.def
diff --git a/mysql-test/suite/innodb/include/restart_and_reinit.inc b/mysql-test/suite/innodb/include/restart_and_reinit.inc
index f95373c40370c99ee55a275f636e569b32959c8e..0f8c1f913d08af4c45b4d93c389ac0246f8593b5 100644
--- a/mysql-test/suite/innodb/include/restart_and_reinit.inc
+++ b/mysql-test/suite/innodb/include/restart_and_reinit.inc
@@ -3,12 +3,13 @@
 #
 # this file deletes old innodb files and restarts mysqld
 #
+source include/not_embedded.inc;
 
 let $_server_id= `SELECT @@server_id`;
 let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect;
 let $datadir= `SELECT @@datadir`;
 exec echo "wait" > $_expect_file_name;
-shutdown_server 10; # give it 10 seconds to die
+shutdown_server;
 remove_file $datadir/ib_logfile0;
 remove_file $datadir/ib_logfile1;
 remove_file $datadir/ibdata1;
diff --git a/mysql-test/suite/innodb/t/innodb_bug47167.test b/mysql-test/suite/innodb/t/innodb_bug47167.test
index a7e1e607cd84fc3523528a6b88f294330c80f32a..505c21547b2a6f92d437341b331c0af70a658ef0 100644
--- a/mysql-test/suite/innodb/t/innodb_bug47167.test
+++ b/mysql-test/suite/innodb/t/innodb_bug47167.test
@@ -4,7 +4,7 @@
 # originally "innodb_file_format_check") with a user-Defined Variable.
 
 --source include/not_embedded.inc
---source suite/innodb/include/restart_and_reinit.inc
+--source include/restart_and_reinit.inc
 
 # Save the value (Antelope) in 'innodb_file_format_max' to
 # 'old_innodb_file_format_max'
diff --git a/mysql-test/suite/innodb/t/innodb_file_format.test b/mysql-test/suite/innodb/t/innodb_file_format.test
index e6c442f80dc172b3eba1584bfd75aec2f1b1e878..941edb728ddbfff6b98a995fe7a341d42f9e4168 100644
--- a/mysql-test/suite/innodb/t/innodb_file_format.test
+++ b/mysql-test/suite/innodb/t/innodb_file_format.test
@@ -1,5 +1,5 @@
 --source include/have_innodb.inc
---source suite/innodb/include/restart_and_reinit.inc
+--source include/restart_and_reinit.inc
 
 let $innodb_file_format_orig=`select @@innodb_file_format`;
 
diff --git a/mysql-test/suite/jp/t/disabled.def b/mysql-test/suite/jp/disabled.def
similarity index 100%
rename from mysql-test/suite/jp/t/disabled.def
rename to mysql-test/suite/jp/disabled.def
diff --git a/mysql-test/suite/mtr/t/combs.combinations b/mysql-test/suite/mtr/t/combs.combinations
new file mode 100644
index 0000000000000000000000000000000000000000..9e49febf18f47b619a64bc4d42936750169d53b9
--- /dev/null
+++ b/mysql-test/suite/mtr/t/combs.combinations
@@ -0,0 +1,5 @@
+[c1]
+allow-suspicious-udfs
+
+[c2]
+disable-local-infile
diff --git a/mysql-test/suite/mtr/t/combs.inc b/mysql-test/suite/mtr/t/combs.inc
new file mode 100644
index 0000000000000000000000000000000000000000..fb677ac9128db2444cc2dd5590d1b806b59805ce
--- /dev/null
+++ b/mysql-test/suite/mtr/t/combs.inc
@@ -0,0 +1 @@
+select @@local_infile;
diff --git a/mysql-test/suite/mtr/t/inc.inc b/mysql-test/suite/mtr/t/inc.inc
new file mode 100644
index 0000000000000000000000000000000000000000..bf391f6e16f7b9dde0a18bbe9e1d2f92477467b4
--- /dev/null
+++ b/mysql-test/suite/mtr/t/inc.inc
@@ -0,0 +1 @@
+let $a=1;
diff --git a/mysql-test/suite/mtr/t/newcomb.result b/mysql-test/suite/mtr/t/newcomb.result
new file mode 100644
index 0000000000000000000000000000000000000000..8f7c125196a0d3ab94e7054d4f7d12efe3173640
--- /dev/null
+++ b/mysql-test/suite/mtr/t/newcomb.result
@@ -0,0 +1,3 @@
+select 1;
+1
+1
diff --git a/mysql-test/suite/mtr/t/newcomb.test b/mysql-test/suite/mtr/t/newcomb.test
new file mode 100644
index 0000000000000000000000000000000000000000..fa0fa48e56a4397b6d03cf465463f24628c7fbd6
--- /dev/null
+++ b/mysql-test/suite/mtr/t/newcomb.test
@@ -0,0 +1,5 @@
+#
+# this tests how mtr handles a test that has no combinations in the
+# parent suite and one combination in the overlay.
+#
+select 1;
diff --git a/mysql-test/suite/mtr/t/proxy.inc b/mysql-test/suite/mtr/t/proxy.inc
new file mode 100644
index 0000000000000000000000000000000000000000..245f6a5a7fccae4ece9c3237fea42e4e0e7a8237
--- /dev/null
+++ b/mysql-test/suite/mtr/t/proxy.inc
@@ -0,0 +1,2 @@
+select "proxy";
+source combs.inc;
diff --git a/mysql-test/suite/mtr/t/self.result b/mysql-test/suite/mtr/t/self.result
new file mode 100644
index 0000000000000000000000000000000000000000..bd0d7c6ec53b107aa379446bcb2a69117c552144
--- /dev/null
+++ b/mysql-test/suite/mtr/t/self.result
@@ -0,0 +1,3 @@
+select "<>";
+<>
+<>
diff --git a/mysql-test/suite/mtr/t/self.test b/mysql-test/suite/mtr/t/self.test
new file mode 100644
index 0000000000000000000000000000000000000000..ad6e155cd944434cec0cc1b4cec34986316a80cd
--- /dev/null
+++ b/mysql-test/suite/mtr/t/self.test
@@ -0,0 +1,4 @@
+#
+# Test file that includes itself. See self.test in the example overlay
+#
+eval select "<$a>";
diff --git a/mysql-test/suite/mtr/t/simple,c2,s1.rdiff b/mysql-test/suite/mtr/t/simple,c2,s1.rdiff
new file mode 100644
index 0000000000000000000000000000000000000000..3023756aa8aa8100a98fdef6fa76349df5cb1055
--- /dev/null
+++ b/mysql-test/suite/mtr/t/simple,c2,s1.rdiff
@@ -0,0 +1,11 @@
+--- suite/mtr/t/simple.result	2012-02-04 12:13:41.000000000 +0100
++++ suite/mtr/t/simple,infile,verbose.reject	2012-02-04 12:16:10.000000000 +0100
+@@ -3,7 +3,7 @@
+ proxy
+ select @@local_infile;
+ @@local_infile
+-1
++0
+ select @@old;
+ @@old
+ 0
diff --git a/mysql-test/suite/mtr/t/simple,s2,c2.rdiff b/mysql-test/suite/mtr/t/simple,s2,c2.rdiff
new file mode 100644
index 0000000000000000000000000000000000000000..a9b9b56ef1c8cc57db566169acef531f47beee5b
--- /dev/null
+++ b/mysql-test/suite/mtr/t/simple,s2,c2.rdiff
@@ -0,0 +1,11 @@
+--- suite/mtr/t/simple,old.result	2012-02-04 12:13:25.000000000 +0100
++++ suite/mtr/t/simple,old,infile.reject	2012-02-04 12:13:59.000000000 +0100
+@@ -3,7 +3,7 @@
+ proxy
+ select @@local_infile;
+ @@local_infile
+-1
++0
+ select @@old;
+ @@old
+ 1
diff --git a/mysql-test/suite/mtr/t/simple,s2.result b/mysql-test/suite/mtr/t/simple,s2.result
new file mode 100644
index 0000000000000000000000000000000000000000..0cd7a21e5f54de3c4ea29f67647e0b15d8c27bc8
--- /dev/null
+++ b/mysql-test/suite/mtr/t/simple,s2.result
@@ -0,0 +1,9 @@
+select "proxy";
+proxy
+proxy
+select @@local_infile;
+@@local_infile
+1
+select @@old;
+@@old
+1
diff --git a/mysql-test/suite/mtr/t/simple.combinations b/mysql-test/suite/mtr/t/simple.combinations
new file mode 100644
index 0000000000000000000000000000000000000000..88cbb688451a88394945303e92489272d26da710
--- /dev/null
+++ b/mysql-test/suite/mtr/t/simple.combinations
@@ -0,0 +1,5 @@
+[s1]
+verbose
+
+[s2]
+old
diff --git a/mysql-test/suite/mtr/t/simple.result b/mysql-test/suite/mtr/t/simple.result
new file mode 100644
index 0000000000000000000000000000000000000000..b4a0c1238fa44d15c01d6be946fb9c42866c3429
--- /dev/null
+++ b/mysql-test/suite/mtr/t/simple.result
@@ -0,0 +1,9 @@
+select "proxy";
+proxy
+proxy
+select @@local_infile;
+@@local_infile
+1
+select @@old;
+@@old
+0
diff --git a/mysql-test/suite/mtr/t/simple.test b/mysql-test/suite/mtr/t/simple.test
new file mode 100644
index 0000000000000000000000000000000000000000..f69a7dc7911c2f4a362231b46cbf75d470ddcc4c
--- /dev/null
+++ b/mysql-test/suite/mtr/t/simple.test
@@ -0,0 +1,15 @@
+#
+# This tests the following:
+#   simple.test has two combinations (in simple.combinations).
+#   it includes combs.inc (indirectly, via proxy.inc) with two more combinations
+#   thus it should run 4 times
+#
+#   combs.combinations is overlayed in the example overlay, adding one more
+#   combination. Thus simple.test must run two more times in the mtr-example.
+#
+#   Note that neither simple.test nor proxy.inc are touched by the overlay,
+#   mtr needs to propagate "affected by the overlay" flag up the
+#   inclusion chain.
+#
+source proxy.inc;
+select @@old;
diff --git a/mysql-test/suite/mtr/t/single.result b/mysql-test/suite/mtr/t/single.result
new file mode 100644
index 0000000000000000000000000000000000000000..8f7c125196a0d3ab94e7054d4f7d12efe3173640
--- /dev/null
+++ b/mysql-test/suite/mtr/t/single.result
@@ -0,0 +1,3 @@
+select 1;
+1
+1
diff --git a/mysql-test/suite/mtr/t/single.test b/mysql-test/suite/mtr/t/single.test
new file mode 100644
index 0000000000000000000000000000000000000000..15262646ede07d3121706b0abe1e236f5ab4cac0
--- /dev/null
+++ b/mysql-test/suite/mtr/t/single.test
@@ -0,0 +1,5 @@
+#
+# the test is present in the mtr suite and is not affected by the example
+# overlay. It should run only once.
+#
+select 1;
diff --git a/mysql-test/suite/mtr/t/source.result b/mysql-test/suite/mtr/t/source.result
new file mode 100644
index 0000000000000000000000000000000000000000..8f7c125196a0d3ab94e7054d4f7d12efe3173640
--- /dev/null
+++ b/mysql-test/suite/mtr/t/source.result
@@ -0,0 +1,3 @@
+select 1;
+1
+1
diff --git a/mysql-test/suite/mtr/t/source.test b/mysql-test/suite/mtr/t/source.test
new file mode 100644
index 0000000000000000000000000000000000000000..1a2fc61e048446205404caca25266ac7e1bf635b
--- /dev/null
+++ b/mysql-test/suite/mtr/t/source.test
@@ -0,0 +1,8 @@
+#
+# The inc.inc file is overlayed in the example overlay. mtr should correctly
+# detect that this test needs to run for mtr-example. And mysqltest
+# needs to use the correct version of inc.inc depending on whether it
+# runs the parent suite or the overlay.
+#
+source inc.inc;
+eval select $a;
diff --git a/mysql-test/suite/mtr/t/test2.result b/mysql-test/suite/mtr/t/test2.result
new file mode 100644
index 0000000000000000000000000000000000000000..b1a55b32da2739cc95ea5cfb4ac2dc013077e7d2
--- /dev/null
+++ b/mysql-test/suite/mtr/t/test2.result
@@ -0,0 +1,4 @@
+select @@local_infile;
+select @@max_error_count;
+@@max_error_count
+64
diff --git a/mysql-test/suite/mtr/t/test2.test b/mysql-test/suite/mtr/t/test2.test
new file mode 100644
index 0000000000000000000000000000000000000000..5e310eaed2f6f94668486d0dd9d91b41ce76615c
--- /dev/null
+++ b/mysql-test/suite/mtr/t/test2.test
@@ -0,0 +1,10 @@
+#
+# This test has two combinations in the mtr suite (from combs.combinations)
+# and one combination from mtr-example (overlayed combs.combinations).
+# But it also has test2.opt file in the overlay. Thus it will run
+# two times in the parent suite, and three times in the overlay.
+#
+--disable_result_log
+source combs.inc;
+--enable_result_log
+select @@max_error_count;
diff --git a/mysql-test/suite/mtr/t/testsh.result b/mysql-test/suite/mtr/t/testsh.result
new file mode 100644
index 0000000000000000000000000000000000000000..8f7c125196a0d3ab94e7054d4f7d12efe3173640
--- /dev/null
+++ b/mysql-test/suite/mtr/t/testsh.result
@@ -0,0 +1,3 @@
+select 1;
+1
+1
diff --git a/mysql-test/suite/mtr/t/testsh.test b/mysql-test/suite/mtr/t/testsh.test
new file mode 100644
index 0000000000000000000000000000000000000000..0bb818d2697b3593a83fd6bdbc0eaf1c29038fad
--- /dev/null
+++ b/mysql-test/suite/mtr/t/testsh.test
@@ -0,0 +1,6 @@
+#
+# There is testsh-master.sh in the example overlay. That makes the test
+# "affected by the overlay" and it will run twice: for the parent suite and
+# for the overlay.
+#
+select 1;
diff --git a/mysql-test/suite/mtr2/single.result b/mysql-test/suite/mtr2/single.result
new file mode 100644
index 0000000000000000000000000000000000000000..8f7c125196a0d3ab94e7054d4f7d12efe3173640
--- /dev/null
+++ b/mysql-test/suite/mtr2/single.result
@@ -0,0 +1,3 @@
+select 1;
+1
+1
diff --git a/mysql-test/suite/mtr2/single.test b/mysql-test/suite/mtr2/single.test
new file mode 100644
index 0000000000000000000000000000000000000000..122e1bb00e4c126289ccf7583f960378bec346bb
--- /dev/null
+++ b/mysql-test/suite/mtr2/single.test
@@ -0,0 +1,8 @@
+#
+# this suite is overlayed in heap and myisam.
+# mtr2-heap has my.cnf, mtr2-myisam has suite.opt
+# it means that all tests from the mtr2 suite will run
+# three times - once for the parent suite, and once for each overlay.
+# even if the test files are not overlayed.
+#
+select 1;
diff --git a/mysql-test/suite/optimizer_unfixed_bugs/t/disabled.def b/mysql-test/suite/optimizer_unfixed_bugs/disabled.def
similarity index 100%
rename from mysql-test/suite/optimizer_unfixed_bugs/t/disabled.def
rename to mysql-test/suite/optimizer_unfixed_bugs/disabled.def
diff --git a/mysql-test/suite/parts/t/disabled.def b/mysql-test/suite/parts/disabled.def
similarity index 100%
rename from mysql-test/suite/parts/t/disabled.def
rename to mysql-test/suite/parts/disabled.def
diff --git a/mysql-test/suite/percona/innodb_sys_index.test b/mysql-test/suite/percona/innodb_sys_index.test
index 9b1ac4c87e81f84293a89f4436b169ea40ef5173..212baeda663ac4ebfae22122ade93c3a5d77ce55 100644
--- a/mysql-test/suite/percona/innodb_sys_index.test
+++ b/mysql-test/suite/percona/innodb_sys_index.test
@@ -1,5 +1,5 @@
 --source include/big_test.inc
---source include/have_innodb.inc
+--source include/have_xtradb.inc
 
 drop table if exists t1;
 #
diff --git a/mysql-test/suite/perfschema/t/disabled.def b/mysql-test/suite/perfschema/disabled.def
similarity index 100%
rename from mysql-test/suite/perfschema/t/disabled.def
rename to mysql-test/suite/perfschema/disabled.def
diff --git a/mysql-test/suite/plugins/suite.pm b/mysql-test/suite/plugins/suite.pm
index f8f78086c1501b854237e53ed7eb16ce8699c816..9ada541e44bcbc62c266a3ae3aa307e166e2801e 100644
--- a/mysql-test/suite/plugins/suite.pm
+++ b/mysql-test/suite/plugins/suite.pm
@@ -2,7 +2,12 @@ package My::Suite::Plugins;
 
 @ISA = qw(My::Suite);
 
-$ENV{PAM_SETUP_FOR_MTR}=1 if -e '/etc/pam.d/mariadb_mtr';
+sub skip_combinations {
+  my %skip;
+  $skip{'t/pam.test'} = 'No pam setup for mtr'
+             unless -e '/etc/pam.d/mariadb_mtr';
+  %skip;
+}
 
 bless { };
 
diff --git a/mysql-test/suite/plugins/t/pam.test b/mysql-test/suite/plugins/t/pam.test
index 2a097b9bfd5205b995681429123f4f346f167ce8..587a2380f94c95e0900368bcb19ae216ed7218f4 100644
--- a/mysql-test/suite/plugins/t/pam.test
+++ b/mysql-test/suite/plugins/t/pam.test
@@ -5,10 +5,6 @@ if (!$AUTH_PAM_SO) {
   skip No pam auth plugin;
 }
 
-if (!$PAM_SETUP_FOR_MTR) {
-  skip No pam setup for mtr;
-}
-
 eval install plugin pam soname '$AUTH_PAM_SO';
 create user test_pam identified via pam using 'mariadb_mtr';
 create user pam_test;
diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/disabled.def
similarity index 100%
rename from mysql-test/suite/rpl/t/disabled.def
rename to mysql-test/suite/rpl/disabled.def
diff --git a/mysql-test/suite/rpl/t/rpl_plugin_load.test b/mysql-test/suite/rpl/t/rpl_plugin_load.test
index 5f9725a8e663dbe1e2b80bafe4d8a81ccc711796..def10f50a642d0c23c7a9bbd76f30df44c5eb1ed 100644
--- a/mysql-test/suite/rpl/t/rpl_plugin_load.test
+++ b/mysql-test/suite/rpl/t/rpl_plugin_load.test
@@ -10,8 +10,6 @@
 
 --source include/not_embedded.inc
 --source include/have_log_bin.inc
-# Dynamic loading of Example does not work on Windows currently.
---source include/not_windows.inc
 --source include/have_example_plugin.inc
 
 # Initialize replication.
@@ -21,7 +19,8 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE';
 --echo Get binlog position before install plugin.
 let $before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
 --echo Install example engine.
-INSTALL PLUGIN example SONAME 'ha_example.so';
+--replace_regex /\.dll/.so/
+eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO';
 --echo Get binlog position after install plugin.
 let $after_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
 --echo Compute the difference of the  binlog positions.
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync.test b/mysql-test/suite/rpl/t/rpl_semi_sync.test
index f697fedfad4f10df19c1e3e480dc92577f0eae9f..42adeed06a75b5dbd94f4f9b0ebb6c0ae1a1eb2e 100644
--- a/mysql-test/suite/rpl/t/rpl_semi_sync.test
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync.test
@@ -19,6 +19,10 @@ call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received w
 enable_query_log;
 connection master;
 
+# wait for dying connections (if any) to disappear
+let $wait_condition= select count(*) = 0 from information_schema.processlist where command='killed';
+--source include/wait_condition.inc
+
 # After fix of BUG#45848, semi-sync slave should not create any extra
 # connections on master, save the count of connections before start
 # semi-sync slave for comparison below.
@@ -166,8 +170,7 @@ show status like 'Rpl_semi_sync_master_yes_tx';
 # After fix of BUG#45848, semi-sync slave should not create any extra
 # connections on master.
 let $_connections_semisync_slave= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1);
-replace_result $_connections_semisync_slave CONNECTIONS_SEMISYNC_SLAVE;
-replace_result $_connections_normal_slave CONNECTIONS_NORMAL_SLAVE;
+replace_result $_connections_normal_slave CONNECTIONS_NORMAL_SLAVE $_connections_semisync_slave CONNECTIONS_SEMISYNC_SLAVE;
 eval select $_connections_semisync_slave - $_connections_normal_slave as 'Should be 0';
 
 let $i=300;
diff --git a/mysql-test/suite/sphinx/my.cnf b/mysql-test/suite/sphinx/my.cnf
index ba5dd7578e8ce1cc6577136180488ea22ae683a8..b4a4dc8e050805047268985fbe8c5588e4d6a12d 100644
--- a/mysql-test/suite/sphinx/my.cnf
+++ b/mysql-test/suite/sphinx/my.cnf
@@ -2,7 +2,7 @@
 
 [source src1]
 type = xmlpipe2
-xmlpipe_command = cat suite/sphinx/testdata.xml
+xmlpipe_command = cat @ENV.MTR_SUITE_DIR/testdata.xml
 
 [index test1]
 source = src1
diff --git a/mysql-test/suite/sphinx/suite.opt b/mysql-test/suite/sphinx/suite.opt
index b8964ecd9e94aeb7fd76b6bd8df0817782a3da43..6a0a190f67a05a0c625dc91375b0ae63dfb707a9 100644
--- a/mysql-test/suite/sphinx/suite.opt
+++ b/mysql-test/suite/sphinx/suite.opt
@@ -1 +1 @@
---plugin-load=$HA_SPHINX_SO
+--plugin-load=$HA_SPHINX_SO --sphinx
diff --git a/mysql-test/suite/sys_vars/t/disabled.def b/mysql-test/suite/sys_vars/disabled.def
similarity index 100%
rename from mysql-test/suite/sys_vars/t/disabled.def
rename to mysql-test/suite/sys_vars/disabled.def
diff --git a/mysql-test/t/archive_plugin.test b/mysql-test/t/archive_plugin.test
index 3b0e10e6401586f401fd412e2bf35fc54be31918..ba80652fb02b15f4004e76af78356efe32020c92 100644
--- a/mysql-test/t/archive_plugin.test
+++ b/mysql-test/t/archive_plugin.test
@@ -1,5 +1,5 @@
 if (!$HA_ARCHIVE_SO) {
-  --skip Need example plugin
+  --skip Need archive plugin
 }
 
 CREATE TABLE t1(a int) ENGINE=ARCHIVE;
diff --git a/mysql-test/t/information_schema-big.test b/mysql-test/t/information_schema-big.test
index c9cd65f0851f04b9c71b5ab52ef8ea955b75fa75..5e73c867143021ae6adf6e891ab24d6710d8d84b 100644
--- a/mysql-test/t/information_schema-big.test
+++ b/mysql-test/t/information_schema-big.test
@@ -1,6 +1,7 @@
 # This test  uses grants, which can't get tested for embedded server
 -- source include/big_test.inc
 -- source include/not_embedded.inc
+-- source include/have_xtradb.inc
 
 # check that CSV engine was compiled in, as the result of the test depends
 # on the presence of the log tables (which are CSV-based).
diff --git a/mysql-test/t/partition_binlog.test b/mysql-test/t/partition_binlog.test
index c1f618b794f3ad555a668f50194e31b3685770f4..9869be75759e5499b1cc9a987efca9cb6ce6517f 100644
--- a/mysql-test/t/partition_binlog.test
+++ b/mysql-test/t/partition_binlog.test
@@ -1,4 +1,5 @@
 --source include/have_log_bin.inc
+--source include/have_partition.inc
 
 --disable_warnings
 DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/t/system_mysql_db_fix40123.test b/mysql-test/t/system_mysql_db_fix40123.test
index 7a96f22e0d19ea714db1e721a97d865d1fa6ef77..5c82f0022b86e433ef609ab2da9b354be6021a4e 100644
--- a/mysql-test/t/system_mysql_db_fix40123.test
+++ b/mysql-test/t/system_mysql_db_fix40123.test
@@ -61,7 +61,7 @@ CREATE TABLE time_zone_leap_second (   Transition_time bigint signed NOT NULL,
 
 
 # Run the mysql_fix_privilege_tables.sql using "mysql --force"
---exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES > $MYSQLTEST_VARDIR/log/system_mysql_db_fix40123.log 2>&1
+--exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES
 
 -- enable_query_log
 -- enable_result_log
diff --git a/mysql-test/t/system_mysql_db_fix50030.test b/mysql-test/t/system_mysql_db_fix50030.test
index 8adf0a09b223b431efa9da664e7e87ad62b6dd91..e8cfe6a6cf3439b19fcb92db0b059e8f803a5bc8 100644
--- a/mysql-test/t/system_mysql_db_fix50030.test
+++ b/mysql-test/t/system_mysql_db_fix50030.test
@@ -67,7 +67,7 @@ CREATE TABLE servers ( Server_name char(64) NOT NULL DEFAULT '', Host char(64) N
 INSERT INTO servers VALUES ('test','localhost','test','root','', 0,'','mysql','root');
 
 # Run the mysql_fix_privilege_tables.sql using "mysql --force"
---exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES > $MYSQLTEST_VARDIR/log/system_mysql_db_fix50030.log 2>&1
+--exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES
 
 -- enable_query_log
 -- enable_result_log
diff --git a/mysql-test/t/system_mysql_db_fix50117.test b/mysql-test/t/system_mysql_db_fix50117.test
index 9aeb654716c504fa2274c55701821b951113a67e..69ad68faaa89b88d1a5405ceae725363c67789c0 100644
--- a/mysql-test/t/system_mysql_db_fix50117.test
+++ b/mysql-test/t/system_mysql_db_fix50117.test
@@ -86,7 +86,7 @@ CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_b
 CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;
 
 # Run the mysql_fix_privilege_tables.sql using "mysql --force"
---exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES > $MYSQLTEST_VARDIR/log/system_mysql_db_fix50117.log 2>&1
+--exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES
 
 -- enable_query_log
 -- enable_result_log
diff --git a/sql/handler.cc b/sql/handler.cc
index 516f61c870057f29b4483d8082761dc9770448ed..57049e87d317d0cae01015e3da345596083475e9 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -155,7 +155,7 @@ plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
   if ((plugin= my_plugin_lock_by_name(thd, name, MYSQL_STORAGE_ENGINE_PLUGIN)))
   {
     handlerton *hton= plugin_data(plugin, handlerton *);
-    if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
+    if (hton && !(hton->flags & HTON_NOT_USER_SELECTABLE))
       return plugin;
       
     /*
diff --git a/storage/example/mysql-test/README b/storage/example/mysql-test/README
new file mode 100644
index 0000000000000000000000000000000000000000..0af43c76efaddbcfafd074c473c63b49836459c4
--- /dev/null
+++ b/storage/example/mysql-test/README
@@ -0,0 +1,2 @@
+These tests don't have anything to do with the EXAMPLE engine itself,
+but they show how mysql-test handles overlays
diff --git a/storage/example/mysql-test/mtr/t/combs.combinations b/storage/example/mysql-test/mtr/t/combs.combinations
new file mode 100644
index 0000000000000000000000000000000000000000..518a0262a01a7cf9575103c55cdcb8e2a24da9cb
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/combs.combinations
@@ -0,0 +1,2 @@
+[c3o]
+table-cache=32
diff --git a/storage/example/mysql-test/mtr/t/inc.inc b/storage/example/mysql-test/mtr/t/inc.inc
new file mode 100644
index 0000000000000000000000000000000000000000..8bca2f83167e54440336e969d73c74e6d0ee706b
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/inc.inc
@@ -0,0 +1 @@
+let $a=2;
diff --git a/storage/example/mysql-test/mtr/t/newcomb.combinations b/storage/example/mysql-test/mtr/t/newcomb.combinations
new file mode 100644
index 0000000000000000000000000000000000000000..baeaaf8307049a0eebf1797fc809d1ef1ca01f5b
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/newcomb.combinations
@@ -0,0 +1,2 @@
+[new]
+--ansi
diff --git a/storage/example/mysql-test/mtr/t/over.result b/storage/example/mysql-test/mtr/t/over.result
new file mode 100644
index 0000000000000000000000000000000000000000..20f11088394494bfe335e71e39b330452ff14ff0
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/over.result
@@ -0,0 +1,4 @@
+select @@local_infile;
+select 1;
+1
+1
diff --git a/storage/example/mysql-test/mtr/t/over.test b/storage/example/mysql-test/mtr/t/over.test
new file mode 100644
index 0000000000000000000000000000000000000000..15c57ec495a40bff8420b8b1a0a1927e073deaaa
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/over.test
@@ -0,0 +1,8 @@
+#
+# This test exists only in the overlay. It will run only for the overlay
+# and not for the parent suite.
+#
+--disable_result_log
+source suite/mtr/t/combs.inc;
+--enable_result_log
+select 1;
diff --git a/storage/example/mysql-test/mtr/t/self.result b/storage/example/mysql-test/mtr/t/self.result
new file mode 100644
index 0000000000000000000000000000000000000000..b907150d81ab795d6f067c76c2b3b909d9f23739
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/self.result
@@ -0,0 +1,6 @@
+select "<1>";
+<1>
+<1>
+select "<2>";
+<2>
+<2>
diff --git a/storage/example/mysql-test/mtr/t/self.test b/storage/example/mysql-test/mtr/t/self.test
new file mode 100644
index 0000000000000000000000000000000000000000..6afa109d48a49b6d7ec17147265e88e0f53ed232
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/self.test
@@ -0,0 +1,8 @@
+#
+# A test that includes itself. But really it includes the
+# self.test from the parent suite, not itself.
+#
+let $a=1;
+source self.test;
+let $a=2;
+source self.test;
diff --git a/storage/example/mysql-test/mtr/t/source.result b/storage/example/mysql-test/mtr/t/source.result
new file mode 100644
index 0000000000000000000000000000000000000000..07fac9ed53ded1a92c69f08db497bdd944ce8b41
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/source.result
@@ -0,0 +1,3 @@
+select 2;
+2
+2
diff --git a/storage/example/mysql-test/mtr/t/test2,c2.result b/storage/example/mysql-test/mtr/t/test2,c2.result
new file mode 100644
index 0000000000000000000000000000000000000000..ff5fb3371f1513a35855d1cdb5ba92848935e0c2
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/test2,c2.result
@@ -0,0 +1,4 @@
+select @@local_infile;
+select @@max_error_count;
+@@max_error_count
+32
diff --git a/storage/example/mysql-test/mtr/t/test2.opt b/storage/example/mysql-test/mtr/t/test2.opt
new file mode 100644
index 0000000000000000000000000000000000000000..e0a2b8429b590135d763e2f28a0907b311aa7f89
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/test2.opt
@@ -0,0 +1 @@
+--max-error-count=32
diff --git a/storage/example/mysql-test/mtr/t/test2.rdiff b/storage/example/mysql-test/mtr/t/test2.rdiff
new file mode 100644
index 0000000000000000000000000000000000000000..b0bf2fdfe4d57bca4c20a74030ea77740195ec3f
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/test2.rdiff
@@ -0,0 +1,8 @@
+--- /usr/home/serg/Abk/mysql/5.1/mysql-test/suite/mtr/t/test2.result	2012-02-04 21:15:14.000000000 +0100
++++ /usr/home/serg/Abk/mysql/5.1/mysql-test/suite/mtr/t/test2.reject	2012-02-04 21:31:45.000000000 +0100
+@@ -1,4 +1,4 @@
+ select @@local_infile;
+ select @@max_error_count;
+ @@max_error_count
+-64
++32
diff --git a/storage/example/mysql-test/mtr/t/testsh-master.sh b/storage/example/mysql-test/mtr/t/testsh-master.sh
new file mode 100644
index 0000000000000000000000000000000000000000..27ba77ddaf61532f217964734769a42cdabc17dc
--- /dev/null
+++ b/storage/example/mysql-test/mtr/t/testsh-master.sh
@@ -0,0 +1 @@
+true
diff --git a/storage/heap/mysql-test/mtr2/README b/storage/heap/mysql-test/mtr2/README
new file mode 100644
index 0000000000000000000000000000000000000000..5b2453d0fa2eef8552ade80aeca01f723521f58e
--- /dev/null
+++ b/storage/heap/mysql-test/mtr2/README
@@ -0,0 +1,2 @@
+These tests don't have anything to do with the engine itself,
+but they test how mysql-test handles overlays
diff --git a/storage/heap/mysql-test/mtr2/my.cnf b/storage/heap/mysql-test/mtr2/my.cnf
new file mode 100644
index 0000000000000000000000000000000000000000..772daa0f5457a6e1b1164a67fd4b319ae0d5788e
--- /dev/null
+++ b/storage/heap/mysql-test/mtr2/my.cnf
@@ -0,0 +1 @@
+!include include/default_my.cnf
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 8b6d347bef9f3e58da03e8e19e029f8d8b6a6908..b6d36809aaf34b70e51209a32aa88e45713997e9 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -7553,7 +7553,6 @@ ha_innobase::records_in_range(
 	mem_heap_t*	heap;
 
 	DBUG_ENTER("records_in_range");
-	DBUG_ASSERT(min_key || max_key);
 
 	ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
diff --git a/storage/myisam/mysql-test/mtr2/README b/storage/myisam/mysql-test/mtr2/README
new file mode 100644
index 0000000000000000000000000000000000000000..5b2453d0fa2eef8552ade80aeca01f723521f58e
--- /dev/null
+++ b/storage/myisam/mysql-test/mtr2/README
@@ -0,0 +1,2 @@
+These tests don't have anything to do with the engine itself,
+but they test how mysql-test handles overlays
diff --git a/storage/myisam/mysql-test/mtr2/suite.opt b/storage/myisam/mysql-test/mtr2/suite.opt
new file mode 100644
index 0000000000000000000000000000000000000000..8e7b7f9e36ff117a6a73b0cdaff3128f5b7ba697
--- /dev/null
+++ b/storage/myisam/mysql-test/mtr2/suite.opt
@@ -0,0 +1 @@
+--old