Skip to content

Commit

Permalink
Add mysql based unit tests (#243)
Browse files Browse the repository at this point in the history
Signed-off-by: IWAMOTO Toshihiro <iwamoto@valinux.co.jp>
  • Loading branch information
toshiiw authored and k8s-ci-robot committed Nov 20, 2018
1 parent b6f8e07 commit 206bcaa
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 25 deletions.
65 changes: 46 additions & 19 deletions pkg/db/interface_test.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package db

import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"math/rand"
"os"
"testing"
"time"

_ "github.com/go-sql-driver/mysql"
"github.com/golang/protobuf/jsonpb"
"gopkg.in/DATA-DOG/go-sqlmock.v1"

api "github.com/kubeflow/katib/pkg/api"
)

var dbInterface VizierDBInterface
var dbInterface, mysqlInterface VizierDBInterface
var mock sqlmock.Sqlmock

var studyColumns = []string{
Expand Down Expand Up @@ -46,10 +49,22 @@ func TestMain(m *testing.M) {
mock.ExpectExec("CREATE TABLE IF NOT EXISTS earlystop_param").WithArgs().WillReturnResult(sqlmock.NewResult(1, 1))
dbInterface.DBInit()

mysqlAddr := os.Getenv("TEST_MYSQL")
if mysqlAddr != "" {
mysql, err := sql.Open("mysql", "root:test123@tcp("+mysqlAddr+")/vizier")

if err != nil {
fmt.Printf("error opening db: %v\n", err)
os.Exit(1)
}
mysqlInterface = NewWithSQLConn(mysql)
mysqlInterface.DBInit()
}

os.Exit(m.Run())
}

func TestGetStudyConfig(t *testing.T) {
func TestCreateStudy(t *testing.T) {
var in api.StudyConfig
in.ParameterConfigs = new(api.StudyConfig_ParameterConfigs)
//err := jsonpb.UnmarshalString("{}", &in)
Expand All @@ -58,12 +73,18 @@ func TestGetStudyConfig(t *testing.T) {
t.Errorf("err %v", err)
}

mock.ExpectExec("INSERT INTO studies VALUES").WithArgs().WillReturnError(errors.New("sql: Duplicated key"))
mock.ExpectExec("INSERT INTO studies VALUES").WithArgs().WillReturnResult(sqlmock.NewResult(1, 1))
id, err := dbInterface.CreateStudy(&in)
if err != nil {
t.Errorf("CreateStudy error %v", err)
} else if len(id) != 16 {
t.Errorf("CreateStudy returned incorrect ID %s", id)
}
// mock.ExpectExec("SELECT * FROM studies WHERE id").WithArgs(id).WillReturnRows(sqlmock.NewRows())
}

func TestGetStudyConfig(t *testing.T) {
id := generateRandid()
mock.ExpectQuery("SELECT").WillReturnRows(
sqlmock.NewRows(studyColumns).AddRow(
"abc", "test", "admin", 1, 0.99, "{}", "", "", "", "test"))
Expand Down Expand Up @@ -105,31 +126,37 @@ func TestDeleteStudy(t *testing.T) {
}

func TestCreateStudyIdGeneration(t *testing.T) {
if mysqlInterface == nil {
t.Skip("TEST_MYSQL is not defined.")
}
var in api.StudyConfig
in.ParameterConfigs = new(api.StudyConfig_ParameterConfigs)

var ids []string
seed := rand.Int63()
encountered := map[string]bool{}
for i := 0; i < 4; i++ {
rand.Seed(int64(i))
mock.ExpectExec("INSERT INTO studies VALUES").WithArgs().WillReturnResult(sqlmock.NewResult(1, 1))
id, err := dbInterface.CreateStudy(&in)
// Repeadedly use the seed to force the same ID generation
rand.Seed(seed)
id, err := mysqlInterface.CreateStudy(&in)
if i == 3 {
if err == nil || !isDBDuplicateError(err) {
t.Errorf("Expected an duplicate error but got %v",
err)
} else {
break
}
}
if err != nil {
t.Errorf("CreateStudy error %v", err)
}
ids = append(ids, id)
t.Logf("id gen %d %s %v\n", i, id, err)
}
encountered := map[string]bool{}
for i := 0; i < len(ids); i++ {
if !encountered[ids[i]] {
encountered[ids[i]] = true
} else if !encountered[id] {
encountered[id] = true
} else {
t.Fatalf("Study ID duplicated %v", ids)
t.Fatalf("Study ID duplicated %s", id)
}
t.Logf("id gen %d %s %v\n", i, id, err)
}
for _, id := range ids {
mock.ExpectExec("DELETE").WillReturnResult(sqlmock.NewResult(1, 1))
err := dbInterface.DeleteStudy(id)
for id, _ := range encountered {
err := mysqlInterface.DeleteStudy(id)
if err != nil {
t.Errorf("DeleteStudy error %v", err)
}
Expand Down
52 changes: 52 additions & 0 deletions test/scripts/unit-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,65 @@ set -o pipefail

export PATH=${GOPATH}/bin:/usr/local/go/bin:${PATH}
REGISTRY="${GCP_REGISTRY}"
CLUSTER_NAME="${CLUSTER_NAME}"
ZONE="${GCP_ZONE}"
PROJECT="${GCP_PROJECT}"
GO_DIR=${GOPATH}/src/github.com/${REPO_OWNER}/${REPO_NAME}
VERSION=$(git describe --tags --always --dirty)

echo "Activating service-account"
gcloud auth activate-service-account --key-file=${GOOGLE_APPLICATION_CREDENTIALS}

echo "Configuring kubectl"

gcloud container clusters describe ${CLUSTER_NAME} \
--zone ${ZONE} \
--format 'value(masterAuth.clusterCaCertificate)'| base64 -d > ca.pem

gcloud container clusters describe ${CLUSTER_NAME} \
--zone ${ZONE} \
--format 'value(masterAuth.clientCertificate)' | base64 -d > client.pem

gcloud container clusters describe ${CLUSTER_NAME} \
--zone ${ZONE} \
--format 'value(masterAuth.clientKey)' | base64 -d > key.rsa

kubectl config set-credentials temp-admin --username=admin --client-certificate=./client.pem --client-key=./key.rsa
kubectl config set-context temp-context --cluster=$(kubectl config get-clusters | grep ${CLUSTER_NAME}) --user=temp-admin
kubectl config use-context temp-context

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
labels:
instance: mysql-ut
name: mysql-ut
spec:
containers:
- name: mysql
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: test123
- name: MYSQL_DATABASE
value: vizier
EOF

TIMEOUT=120
until kubectl logs -l instance=mysql-ut |grep 'init process done'; do
sleep 10
TIMEOUT=$(( TIMEOUT - 1 ))
if [ "$TIMEOUT" -eq 0 ]; then
echo "DB failed to start"
kubectl get pod -l instance=mysql-ut
exit 1
fi
done

kubectl port-forward $(kubectl get pod -l instance=mysql-ut -o=name) 3306:3306&
export TEST_MYSQL=localhost

echo "Run unit test cases"
cd ${GO_DIR}
go test ./...
Expand Down
12 changes: 6 additions & 6 deletions test/workflows/components/workflows.libsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -254,19 +254,19 @@
template: "create-pr-symlink",
},
],
[
{
name: "unit-test",
template: "unit-test",
},
],
[ // Setup cluster needs to run after build because we depend on the chart
// created by the build statement.
{
name: "setup-cluster",
template: "setup-cluster",
},
],
[
{
name: "unit-test",
template: "unit-test",
},
],
[
{
name: "run-tests",
Expand Down

0 comments on commit 206bcaa

Please sign in to comment.