#!/bin/sh 

dbc_dbname="testdbname"
dbc_dbuser="testdbuser"
dbc_dbadmin="testadmin"
dbc_dbpass="testdbpass"
dbc_dbadmpass="testadmpass"
dbc_dbserver="testserver"
dbc_dbport="testport"

# get some common functions
. `dirname "$0"`/functions
. ${_dbc_root}/internal/mysql

test_generate_mycnf(){
  local cnf DIFF

  DIFF='diff -b -u -I "^# generated on"'

  cnf=`_dbc_generate_mycnf`
  assertTrue "_dbc_generate_mycnf returned error" $?
  assertFilesEqual ./data/generate_mycnf.txt "$cnf"
  rm -f "$cnf"
}

test_mysql_check_connect(){

  log_tc "successful connect"
  mockup -i mysql
  _dbc_mysql_check_connect </dev/null
  assertTrue "mysql_check_connect failed" $?
  subst_tmpfile dbconfig-common_my.cnf.XXXXXX "$mockup_cmdline"
  assertFilesEqual ./data/mysql_check_connect.txt "$mockup_cmdline"
  assertFileEmpty "unexpected input to mysql_check_connect" "$mockup_inputfile"

  log_tc "fail to connect with error code"
  mockup -r 1 -i mysql
  _dbc_mysql_check_connect </dev/null 2>/dev/null
  assertFalse "mysql_check_connect should have failed" $?

}

test_dbc_mysql_exec_file(){
  local _dbc_nodb sql

  sql=`mktemp -t`

  mockup -i mysql

  log_tc "expected behaviour for existing file"
  dbc_mysql_exec_file "$sql" >/dev/null
  assertTrue "dbc_mysql_exec_file (withdb) failed" $?
  subst_tmpfile dbconfig-common_my.cnf.XXXXXX "$mockup_cmdline"
  assertFilesEqual ./data/dbc_mysql_exec_file.withdb.txt "$mockup_cmdline"

  log_tc "expected behaviour for missing file"
  dbc_mysql_exec_file "does not exist.sql" >/dev/null
  assertFalse "dbc_mysql_exec_file (withdb) should have failed" $?
  subst_tmpfile dbconfig-common_my.cnf.XXXXXX "$mockup_cmdline"
  assertFilesEqual ./data/dbc_mysql_exec_file.withdb.txt "$mockup_cmdline"

  mockup -i mysql

  # same as before, but with _dbc_nodb set
  _dbc_nodb=yes
  log_tc "expected behaviour for existing file, no database"
  dbc_mysql_exec_file "$sql"
  assertTrue "dbc_mysql_exec_file (nodb) failed" $?
  subst_tmpfile dbconfig-common_my.cnf.XXXXXX "$mockup_cmdline"
  assertFilesEqual ./data/dbc_mysql_exec_file.nodb.txt "$mockup_cmdline"

  log_tc "expected behaviour for missing file, no database"
  dbc_mysql_exec_file "does not exist.sql" >/dev/null
  assertFalse "dbc_mysql_exec_file (nodb) should have failed" $?
  subst_tmpfile dbconfig-common_my.cnf.XXXXXX "$mockup_cmdline"
  assertFilesEqual ./data/dbc_mysql_exec_file.nodb.txt "$mockup_cmdline"

  rm -f "$sql"
}

test_mysql_exec_command(){
  mockup -i mysql
  dbc_mysql_exec_command "select * from foo where bar = 1"
  assertTrue "dbc_mysql_exec_command failed" $?
  assertFilesEqual ./data/mysql_exec_command.sql.txt "$mockup_inputfile"
}

test_dbc_mysql_check_database(){
  mockup -i -o ./data/dbc_mysql_check_database.exists.stdout.txt mysql
  log_tc "database exists"
  _dbc_mysql_check_database "$dbc_dbname"
  assertTrue "_dbc_mysql_check_database failed to find db" $?

  log_tc "database does not exist"
  mockup -i -o ./data/dbc_mysql_check_database.missing.stdout.txt mysql
  _dbc_mysql_check_database "$dbc_dbname"
  assertFalse "_dbc_mysql_check_database shouldn't have found db" $?
}

test_dbc_mysql_check_user(){
  local dbc_dballow

  log_tc "existing user, with grant, localhost"
  mockup -i -o ./data/dbc_mysql_check_user.localhost.exists.stdout.txt mysql
  dbc_mysql_check_user
  assertTrue "dbc_mysql_check_user failed to find user" $?

  log_tc "user does not exist at all"
  mockup -i mysql
  dbc_mysql_check_user
  assertFalse "dbc_mysql_check_user shouldn't have found user" $?

  log_tc "user exists, does not have grant"
  mockup -i -o ./data/dbc_mysql_check_user.localhost.nogrant.stdout.txt mysql
  dbc_mysql_check_user
  assertFalse "dbc_mysql_check_user shouldn't have found grant" $?

  log_tc "user exists on remote host"
  dbc_dballow="host2"
  mockup -i -o ./data/dbc_mysql_check_user.remote.exists.stdout.txt mysql
  dbc_mysql_check_user
  assertTrue "dbc_mysql_check_user failed to find user on remote" $?
}

test_dbc_mysql_createdb(){
  local output

  log_tc "checkconnect fails"
  mockup -r 1 _dbc_mysql_check_connect
  dbc_mysql_createdb >/dev/null 
  assertFalse "dbc_mysql_createdb (checkconnect) should have failed" $?

  log_tc "database already exists"
  mockup _dbc_mysql_check_connect
  mockup _dbc_mysql_check_database
  output=`dbc_mysql_createdb 2>&1`
  assertTrue "dbc_mysql_createdb (exists) failed" $?
  assertEquals "creating database testdbname: already exists." "$output"

  log_tc "database does not exist, creation successful"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup -r 1 _dbc_mysql_check_database
  mockup dbc_mysql_exec_command
  mockup _dbc_mysql_check_database
  dbc_mysql_createdb >/dev/null 2>&1
  assertTrue "dbc_mysql_createdb failed" $?
  assertFilesEqual "./data/dbc_mysql_createdb.verifyok.txt" "$_dbc_logfile"

  log_tc "database does not exist, creation failed"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup -r 1 _dbc_mysql_check_database
  mockup -r 1 dbc_mysql_exec_command
  output=`dbc_mysql_createdb 2>&1`
  assertFalse "dbc_mysql_createdb should have failed" $?
  assertEquals "creating database testdbname: failed." "$output"

  log_tc "database does not exist, creation ok, verify failed"
  mockup _dbc_mysql_check_connect
  mockup -r 1 _dbc_mysql_check_database
  mockup dbc_mysql_exec_command
  mockup -r 1 _dbc_mysql_check_database
  cat </dev/null > "$_dbc_logfile"
  dbc_mysql_createdb >/dev/null 2>&1
  assertFalse "dbc_mysql_createdb should have failed" $?
  assertFilesEqual "./data/dbc_mysql_createdb.verifyfail.txt" "$_dbc_logfile"
}

test_dbc_mysql_dropdb(){
  local output

  log_tc "unable to connect"
  mockup -r 1 _dbc_mysql_check_connect
  dbc_mysql_dropdb
  assertFalse "dbc_mysql_dropdb should have failed to connect" $?

  log_tc "database does not exist"
  mockup _dbc_mysql_check_connect
  mockup -r 1 _dbc_mysql_check_database
  output=`dbc_mysql_dropdb 2>&1`
  assertTrue "dbc_mysql_dropdb failed" $?
  assertEquals "dropping database testdbname: database does not exist." "$output"

  log_tc "database exists, drop successful"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup _dbc_mysql_check_database
  mockup dbc_mysql_exec_command
  mockup -r 1 _dbc_mysql_check_database

  output=`dbc_mysql_dropdb 2>&1`
  assertTrue "dbc_mysql_dropdb failed" $?
  assertFilesEqual "./data/dbc_mysql_dropdb.verifyok.txt" "$_dbc_logfile"

  log_tc "database exists, drop failed"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup _dbc_mysql_check_database
  mockup -r 1 dbc_mysql_exec_command

  output=`dbc_mysql_dropdb 2>&1`
  assertFalse "dbc_mysql_dropdb should have failed" $?
  assertEquals "dropping database testdbname: failed." "$output"

  log_tc "database exists, drop ok, verify failed"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup _dbc_mysql_check_database
  mockup dbc_mysql_exec_command
  mockup _dbc_mysql_check_database
  output=`dbc_mysql_dropdb 2>&1`
  assertFalse "dbc_mysql_dropdb should have failed" $?
  assertFilesEqual "./data/dbc_mysql_dropdb.verifyfailed.txt" "$_dbc_logfile"

}

test_dbc_mysql_createuser(){
  local output sqllog
  local dbc_dballow dbc_dbserver
  dbc_dballow=localhost

  # what's being checked, roughly:
  # connecting with no hostname
  #    grant input
  # connecting with hostname
  #    grant input
  # connecting with no hostname
  #   user exists
  #   user does not exist
  #    grant input
  #     creation succeeds
  #       verify succeeds
  #         log message
  #       verify fails
  #         log message
  #     creation fails
  #       log message
  # connecting with hostname
  #   user exists
  #   user does not exist
  #    grant input
  #     creation succeeds
  #       verify succeeds
  #         log message
  #       verify fails
  #         log message
  #     creation fails
  #       log message

  log_tc "connect fails"
  mockup -r 1 _dbc_mysql_check_connect
  output=`dbc_mysql_createuser 2>&1`
  assertFalse "dbc_mysql_createuser should have failed to connect" $?

  log_tc "local host, user does not exist, creation success, verify ok"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup -r 1 dbc_mysql_check_user
  mockup -i mysql
  sqllog="${mockup_inputfile}"
  mockup dbc_mysql_check_user
  output=`dbc_mysql_createuser 2>&1`
  assertTrue "dbc_mysql_createuser failed" $?
  assertFilesEqual "./data/dbc_mysql_createuser.nohost.sql.txt" "${sqllog}"
  assertFilesEqual "data/dbc_mysql_createuser.nohost.log.verifyok.txt" "$_dbc_logfile"

  log_tc "remote host, user does not exist, creation success, verify ok"
  cat </dev/null > "$_dbc_logfile"
  dbc_dballow="host2"
  mockup _dbc_mysql_check_connect
  mockup -r 1 dbc_mysql_check_user
  mockup -i mysql
  sqllog="${mockup_inputfile}"
  mockup dbc_mysql_check_user
  output=`dbc_mysql_createuser 2>&1`
  assertTrue "dbc_mysql_createuser failed" $?
  assertFilesEqual "./data/dbc_mysql_createuser.remote.sql.txt" "${sqllog}"
  assertFilesEqual "data/dbc_mysql_createuser.remote.log.verifyok.txt" "$_dbc_logfile"

  log_tc "local host, user exists"
  dbc_dballow="localhost"
  mockup _dbc_mysql_check_connect
  mockup dbc_mysql_check_user
  output=`dbc_mysql_createuser 2>&1`
  assertTrue "dbc_mysql_createuser failed" $?
  assertEquals "granting access to database testdbname for testdbuser@localhost: already exists." "$output"

  log_tc "local host, user does not exist, creation success, verify fails"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup -r 1 dbc_mysql_check_user
  mockup -i -o ./data/dbc_mysql_check_user.localhost.exists.stdout.txt mysql
  mockup -r 1 dbc_mysql_check_user
  output=`dbc_mysql_createuser 2>&1`
  assertFalse "dbc_mysql_createuser should have failed" $?
  assertFilesEqual "data/dbc_mysql_createuser.nohost.log.verifyfail.txt" "$_dbc_logfile"

  log_tc "local host, user does not exist, creation fails"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup -r 1 dbc_mysql_check_user
  mockup -r 1 dbc_mysql_exec_file
  output=`dbc_mysql_createuser 2>&1`
  assertFalse "dbc_mysql_createuser should have failed" $?
  assertEquals "granting access to database testdbname for testdbuser@localhost: failed." "$output"

  log_tc "remote host, user exists"
  export dbc_dballow="host2"
  mockup _dbc_mysql_check_connect
  mockup dbc_mysql_check_user
  output=`dbc_mysql_createuser 2>&1`
  assertTrue "dbc_mysql_createuser failed" $?
  assertEquals "granting access to database testdbname for testdbuser@host2: already exists." "$output"

  log_tc "remote host, user does not exist, creation success, verify fails"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup -r 1 dbc_mysql_check_user
  mockup dbc_mysql_exec_file
  mockup -r 1 dbc_mysql_check_user
  output=`dbc_mysql_createuser 2>&1`
  assertFalse "dbc_mysql_createuser should have failed" $?
  assertFilesEqual "data/dbc_mysql_createuser.remote.log.verifyfail.txt" "$_dbc_logfile"

  log_tc "remote host, user does not exist, creation fails"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup -r 1 dbc_mysql_check_user
  mockup -r 1 dbc_mysql_exec_file
  output=`dbc_mysql_createuser 2>&1`
  assertFalse "dbc_mysql_createuser should have failed" $?
  assertEquals "granting access to database testdbname for testdbuser@host2: failed." "$output"
}

test_dbc_mysql_dropuser(){
  local output dbc_dballow dbc_dbserver
  dbc_dballow=localhost

  # to check:
  # connect failure
  # connecting with no hostname
  #   user doesn't exist
  #   user exists
  #     revoke input
  #     revoke fails
  #         log msg
  #     revoke succeeds
  #       verifying revoke succeeds
  #         log msg
  #       verifying revoke fails
  #         log msg
  # connecting with hostname
  #   user doesn't exist
  #   user exists
  #     revoke input
  #     revoke fails
  #       log msg
  #     revoke succeeds
  #       verifying revoke succeeds
  #         log msg
  #       verifying revoke fails
  #         log msg

  log_tc "connect fails"
  mockup -r 1 _dbc_mysql_check_connect
  dbc_mysql_dropuser 2>/dev/null
  assertFalse "dbc_mysql_dropuser should have failed to connect" $?

  . ${_dbc_root}/internal/mysql
  log_tc "localhost, user exists, revoke fails"
  mockup _dbc_mysql_check_connect
  mockup dbc_mysql_check_user
  mockup -i -r 1 mysql
  dbc_mysql_dropuser >/dev/null 2>&1
  assertFalse "dbc_mysql_dropuser should have failed" $?
  assertFilesEqual ./data/dbc_mysql_dropuser.nohost.sql.txt ${mockup_inputfile}
  assertFilesEqual ./data/dbc_mysql_dropuser.nohost.log.fail.txt $_dbc_logfile

  log_tc "localhost, user exists, revoke succeeds, (TODO verify ok)"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup dbc_mysql_check_user
  mockup dbc_mysql_exec_file
  dbc_mysql_dropuser >/dev/null 2>&1
  assertTrue "dbc_mysql_dropuser should not have failed" $?
  assertFilesEqual ./data/dbc_mysql_dropuser.nohost.log.verifyok.txt $_dbc_logfile

  log_tc "TODO localhost, user exists, revoke fails"

  . ${_dbc_root}/internal/mysql
  rm -f ./tmp/mockup/mockup.control
  export dbc_dballow="host2"
  cat </dev/null > "$_dbc_logfile"
  log_tc "remote, user exists, revoke fails"
  mockup _dbc_mysql_check_connect
  mockup dbc_mysql_check_user
  mockup -i -r 1 mysql
  dbc_mysql_dropuser >/dev/null 2>&1
  assertFalse "dbc_mysql_dropuser should have failed" $?
  assertFilesEqual ./data/dbc_mysql_dropuser.remote.sql.txt ${mockup_inputfile}
  assertFilesEqual ./data/dbc_mysql_dropuser.remote.log.fail.txt $_dbc_logfile

  log_tc "remote, user exists, revoke succeeds, (TODO verify ok)"
  cat </dev/null > "$_dbc_logfile"
  mockup _dbc_mysql_check_connect
  mockup dbc_mysql_check_user
  mockup dbc_mysql_exec_file
  dbc_mysql_dropuser >/dev/null 2>&1
  assertTrue "dbc_mysql_dropuser should not have failed" $?
  assertFilesEqual ./data/dbc_mysql_dropuser.remote.log.verifyok.txt $_dbc_logfile

  log_tc "TODO remote, user exists, revoke fails"
}

test_dbc_mysql_dump(){
  # to check:
  # mysqldump cmdline
  # mysqldump succeeds
  #   log msg
  # mysqldump fails
  #   log msg
  . ${_dbc_root}/internal/mysql
  rm -f ./tmp/mockup/mockup.control

  log_tc "mysqldump succeeds"
  mockup _dbc_mysql_check_connect
  mockup -o ./data/dbc_logline.simple.txt mysqldump 
  dbc_mysql_dump good
  assertTrue "mysql dump should have succeeded" $?
  assertTrue "mysql dump should have created a dumpfile" "[ -s good ]"

  log_tc "mysqldump fails"
  mockup _dbc_mysql_check_connect
  mockup -r 1 -o ./data/dbc_logline.simple.txt mysqldump 
  dbc_mysql_dump bad
  assertFalse "mysql dump should have failed" $?
  assertTrue "mysql dump should have created a dumpfile" "[ -s bad ]"

  rm -f good bad
}

test_dbc_mysql_db_installed(){

  log_tc "mysqld in path"
  touch ./tmp/mysqld
  chmod +x ./tmp/mysqld
  ( PATH="/bin:./tmp"; dbc_mysql_db_installed )
  assertTrue "mysqld should have been found" $?
  rm -f ./tmp/mysqld

  log_tc "mysqld not in path"
  ( PATH="/bin"; dbc_mysql_db_installed )
  assertFalse "mysqld should not have been found" $?
}

test_dbc_mysql_escape_str(){
  local str t

  t=`mktemp`
  # normal string
  log_tc "escaping normal string"
  str=`dbc_mysql_escape_str "this is a normal string"`
  assertTrue "error escaping string" "[ '$str' = 'this is a normal string' ]"
  # string with \
  log_tc "escaping string w/backslash"
  dbc_mysql_escape_str 'should have 1 backslash (\) but escape to 2' > "$t"
  assertFilesEqual ./data/mysql_escape_str.backslash.txt "$t"
  # string with '
  log_tc "escaping string w/single quote"
  dbc_mysql_escape_str "it isn't unusual to find quotes" > "$t"
  assertFilesEqual ./data/mysql_escape_str.quote.txt "$t"

  rm -f "$t"
}

. /usr/share/shunit2/shunit2
