package main

import (
	"bytes"
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/stretchr/testify/assert"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

var (
	testdb   *sql.DB
	testInfo = DBInfo{
		User:     "root",
		Password: "",
		Host:     "127.0.0.1",
		Port:     "4000",
	}
)

func init() {
	testdb = newMysql(testInfo)
}

type checkShowCreate struct {
	sql   string
	value [2]string
}

func TestShowCreateSQL(t *testing.T) {
	ckscs := []checkShowCreate{
		{
			"show create database test",
			[2]string{
				"test", "CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */",
			},
		}, {
			"show create table test.t",
			[2]string{
				"t", "CREATE TABLE `t` (\n  `i` int(11) DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
			},
		},
	}
	for _, ck := range ckscs {
		sv, err := getShowCreate(testdb, ck.sql)
		assert.Nil(t, err)
		assert.Equal(t, ck.value[0], sv.Name)
		assert.Equal(t, ck.value[1], sv.SQL)
	}
}

func TestGetAllTables(t *testing.T) {
	rets, err := getAllSchema(testdb)
	assert.Nil(t, err)
	//
	vmap := map[string]bool{
		"test":               true,
		"INFORMATION_SCHEMA": true,
		"METRICS_SCHEMA":     true,
		"PERFORMANCE_SCHEMA": true,
		"mysql":              true,
	}
	for _, db := range rets {
		_, ok := vmap[db]
		assert.True(t, ok)
		if !ok {
			continue
		}
		obj := newMysql(testInfo)
		tbls, err := getAllTablesBySchema(obj, db)
		assert.Nil(t, err)
		if err != nil {
			continue
		}
		checkTables(t, db, tbls)
	}
}

func checkTables(t *testing.T, db string, tbls []string) {
	fp, err := os.Open(fmt.Sprintf("tests/%s.txt", db))
	assert.Nil(t, err)
	if err != nil {
		return
	}
	defer fp.Close()
	bs, err := ioutil.ReadAll(fp)
	assert.Nil(t, err)
	if err != nil {
		return
	}
	str := strings.Join(tbls, "\n")
	bs = bytes.TrimSpace(bs)
	assert.Equal(t, string(bs), str)
}

func TestAddFilter(t *testing.T) {
	ins := []string{"mysql","MySQL", "tt"}
	cks := []string{"INFORMATION_SCHEMA", "PERFORMANCE_SCHEMA", "mysql", "default", "tt"}
	for _, in := range ins {
		addDBFilter(in)
	}
	assert.Equal(t, cks, dbFilter)
}
