github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/pkg/index/mysql/mysql_test.go (about)

     1  /*
     2  Copyright 2012 The Camlistore Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mysql_test
    18  
    19  import (
    20  	"database/sql"
    21  	"errors"
    22  	"fmt"
    23  	"log"
    24  	"sync"
    25  	"testing"
    26  
    27  	"camlistore.org/pkg/index"
    28  	"camlistore.org/pkg/index/indextest"
    29  	"camlistore.org/pkg/osutil"
    30  	"camlistore.org/pkg/sorted"
    31  	"camlistore.org/pkg/sorted/kvtest"
    32  	"camlistore.org/pkg/sorted/mysql"
    33  	"camlistore.org/pkg/test"
    34  
    35  	_ "camlistore.org/third_party/github.com/ziutek/mymysql/godrv"
    36  )
    37  
    38  var (
    39  	once        sync.Once
    40  	dbAvailable bool
    41  	rootdb      *sql.DB
    42  )
    43  
    44  func checkDB() {
    45  	var err error
    46  	rootdb, err = sql.Open("mymysql", "mysql/root/root")
    47  	if err != nil {
    48  		log.Printf("Could not open rootdb: %v", err)
    49  		return
    50  	}
    51  	var n int
    52  	err = rootdb.QueryRow("SELECT COUNT(*) FROM user").Scan(&n)
    53  	if err == nil {
    54  		dbAvailable = true
    55  	}
    56  }
    57  
    58  func skipOrFailIfNoMySQL(t *testing.T) {
    59  	once.Do(checkDB)
    60  	if !dbAvailable {
    61  		// TODO(bradfitz): accept somehow other passwords than
    62  		// 'root', and/or try localhost unix socket
    63  		// connections rather than using TCP localhost?
    64  		err := errors.New("Not running; start a MySQL daemon on the standard port (3306) with root password 'root'")
    65  		test.DependencyErrorOrSkip(t)
    66  		t.Fatalf("MySQL not available locally for testing: %v", err)
    67  	}
    68  }
    69  
    70  func do(db *sql.DB, sql string) {
    71  	_, err := db.Exec(sql)
    72  	if err == nil {
    73  		return
    74  	}
    75  	log.Fatalf("Error %v running SQL: %s", err, sql)
    76  }
    77  
    78  func newSorted(t *testing.T) (kv sorted.KeyValue, clean func()) {
    79  	skipOrFailIfNoMySQL(t)
    80  	dbname := "camlitest_" + osutil.Username()
    81  	do(rootdb, "DROP DATABASE IF EXISTS "+dbname)
    82  	do(rootdb, "CREATE DATABASE "+dbname)
    83  
    84  	db, err := sql.Open("mymysql", dbname+"/root/root")
    85  	if err != nil {
    86  		t.Fatalf("opening test database: " + err.Error())
    87  	}
    88  	for _, tableSql := range mysql.SQLCreateTables() {
    89  		do(db, tableSql)
    90  	}
    91  	do(db, fmt.Sprintf(`REPLACE INTO meta VALUES ('version', '%d')`, mysql.SchemaVersion()))
    92  
    93  	kv, err = mysql.NewKeyValue(mysql.Config{
    94  		Database: dbname,
    95  		User:     "root",
    96  		Password: "root",
    97  	})
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	return kv, func() {
   102  		kv.Close()
   103  	}
   104  }
   105  
   106  func TestSortedKV(t *testing.T) {
   107  	kv, clean := newSorted(t)
   108  	defer clean()
   109  	kvtest.TestSorted(t, kv)
   110  }
   111  
   112  type mysqlTester struct{}
   113  
   114  func (mysqlTester) test(t *testing.T, tfn func(*testing.T, func() *index.Index)) {
   115  	var mu sync.Mutex // guards cleanups
   116  	var cleanups []func()
   117  	defer func() {
   118  		mu.Lock() // never unlocked
   119  		for _, fn := range cleanups {
   120  			fn()
   121  		}
   122  	}()
   123  	makeIndex := func() *index.Index {
   124  		s, cleanup := newSorted(t)
   125  		mu.Lock()
   126  		cleanups = append(cleanups, cleanup)
   127  		mu.Unlock()
   128  		return index.New(s)
   129  	}
   130  	tfn(t, makeIndex)
   131  }
   132  
   133  func TestIndex_MySQL(t *testing.T) {
   134  	mysqlTester{}.test(t, indextest.Index)
   135  }
   136  
   137  func TestPathsOfSignerTarget_MySQL(t *testing.T) {
   138  	mysqlTester{}.test(t, indextest.PathsOfSignerTarget)
   139  }
   140  
   141  func TestFiles_MySQL(t *testing.T) {
   142  	mysqlTester{}.test(t, indextest.Files)
   143  }
   144  
   145  func TestEdgesTo_MySQL(t *testing.T) {
   146  	mysqlTester{}.test(t, indextest.EdgesTo)
   147  }
   148  
   149  func TestDelete_MySQL(t *testing.T) {
   150  	mysqlTester{}.test(t, indextest.Delete)
   151  }