{
  system ? builtins.currentSystem,
  config ? { },
  pkgs ? import ../../.. { inherit system config; },
  lib ? pkgs.lib,
}:

let
  inherit (import ./common.nix { inherit pkgs lib; })
    mkTestName
    mariadbPackages
    mysqlPackages
    perconaPackages
    ;

  makeTest = import ./../make-test-python.nix;
  # Setup common users
  makeMySQLTest =
    {
      package,
      name ? mkTestName package,
      useSocketAuth ? true,
      hasMroonga ? true,
      hasRocksDB ? pkgs.stdenv.hostPlatform.is64bit,
    }:
    makeTest {
      inherit name;
      meta = {
        maintainers = lib.teams.helsinki-systems.members;
      };

      nodes = {
        ${name} =
          { pkgs, ... }:
          {

            users = {
              groups.testusers = { };

              users.testuser = {
                isSystemUser = true;
                group = "testusers";
              };

              users.testuser2 = {
                isSystemUser = true;
                group = "testusers";
              };
            };

            services.mysql = {
              enable = true;
              initialDatabases = [
                {
                  name = "testdb3";
                  schema = ./testdb.sql;
                }
              ];
              # note that using pkgs.writeText here is generally not a good idea,
              # as it will store the password in world-readable /nix/store ;)
              initialScript = pkgs.writeText "mysql-init.sql" (
                if (!useSocketAuth) then
                  ''
                    CREATE USER 'testuser3'@'localhost' IDENTIFIED BY 'secure';
                    GRANT ALL PRIVILEGES ON testdb3.* TO 'testuser3'@'localhost';
                  ''
                else
                  ''
                    ALTER USER root@localhost IDENTIFIED WITH unix_socket;
                    DELETE FROM mysql.user WHERE password = ''' AND plugin = ''';
                    DELETE FROM mysql.user WHERE user = ''';
                    FLUSH PRIVILEGES;
                  ''
              );

              ensureDatabases = [
                "testdb"
                "testdb2"
              ];
              ensureUsers = [
                {
                  name = "testuser";
                  ensurePermissions = {
                    "testdb.*" = "ALL PRIVILEGES";
                  };
                }
                {
                  name = "testuser2";
                  ensurePermissions = {
                    "testdb2.*" = "ALL PRIVILEGES";
                  };
                }
              ];
              package = package;
              settings = {
                mysqld = {
                  plugin-load-add =
                    lib.optional hasMroonga "ha_mroonga.so" ++ lib.optional hasRocksDB "ha_rocksdb.so";
                };
              };
            };
          };
      };

      testScript = ''
        start_all()

        machine = ${name}
        machine.wait_for_unit("mysql")
        machine.succeed(
            "echo 'use testdb; create table tests (test_id INT, PRIMARY KEY (test_id));' | sudo -u testuser mysql -u testuser"
        )
        machine.succeed(
            "echo 'use testdb; insert into tests values (42);' | sudo -u testuser mysql -u testuser"
        )
        # Ensure testuser2 is not able to insert into testdb as mysql testuser2
        machine.fail(
            "echo 'use testdb; insert into tests values (23);' | sudo -u testuser2 mysql -u testuser2"
        )
        # Ensure testuser2 is not able to authenticate as mysql testuser
        machine.fail(
            "echo 'use testdb; insert into tests values (23);' | sudo -u testuser2 mysql -u testuser"
        )
        machine.succeed(
            "echo 'use testdb; select test_id from tests;' | sudo -u testuser mysql -u testuser -N | grep 42"
        )

        ${lib.optionalString hasMroonga ''
          # Check if Mroonga plugin works
          machine.succeed(
              "echo 'use testdb; create table mroongadb (test_id INT, PRIMARY KEY (test_id)) ENGINE = Mroonga;' | sudo -u testuser mysql -u testuser"
          )
          machine.succeed(
              "echo 'use testdb; insert into mroongadb values (25);' | sudo -u testuser mysql -u testuser"
          )
          machine.succeed(
              "echo 'use testdb; select test_id from mroongadb;' | sudo -u testuser mysql -u testuser -N | grep 25"
          )
          machine.succeed(
              "echo 'use testdb; drop table mroongadb;' | sudo -u testuser mysql -u testuser"
          )
        ''}

        ${lib.optionalString hasRocksDB ''
          # Check if RocksDB plugin works
          machine.succeed(
              "echo 'use testdb; create table rocksdb (test_id INT, PRIMARY KEY (test_id)) ENGINE = RocksDB;' | sudo -u testuser mysql -u testuser"
          )
          machine.succeed(
              "echo 'use testdb; insert into rocksdb values (28);' | sudo -u testuser mysql -u testuser"
          )
          machine.succeed(
              "echo 'use testdb; select test_id from rocksdb;' | sudo -u testuser mysql -u testuser -N | grep 28"
          )
          machine.succeed(
              "echo 'use testdb; drop table rocksdb;' | sudo -u testuser mysql -u testuser"
          )
        ''}
      '';
    };
in
lib.mapAttrs (
  _: package:
  makeMySQLTest {
    inherit package;
    hasRocksDB = false;
    hasMroonga = false;
    useSocketAuth = false;
  }
) mysqlPackages
// (lib.mapAttrs (
  _: package:
  makeMySQLTest {
    inherit package;
  }
) mariadbPackages)
// (lib.mapAttrs (
  _: package:
  makeMySQLTest {
    inherit package;
    name = builtins.replaceStrings [ "-" ] [ "_" ] package.pname;
    hasMroonga = false;
    useSocketAuth = false;
  }
) perconaPackages)
